paid-python 0.4.1a0__py3-none-any.whl → 0.5.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. paid/__init__.py +42 -4
  2. paid/agents/client.py +32 -0
  3. paid/agents/raw_client.py +32 -0
  4. paid/client.py +25 -2
  5. paid/core/client_wrapper.py +2 -3
  6. paid/customers/client.py +168 -36
  7. paid/customers/raw_client.py +217 -36
  8. paid/errors/__init__.py +2 -1
  9. paid/errors/internal_server_error.py +11 -0
  10. paid/orders/lines/client.py +0 -4
  11. paid/plans/__init__.py +4 -0
  12. paid/plans/client.py +261 -0
  13. paid/plans/raw_client.py +345 -0
  14. paid/products/__init__.py +7 -0
  15. paid/products/client.py +788 -0
  16. paid/products/raw_client.py +807 -0
  17. paid/products/types/__init__.py +7 -0
  18. paid/products/types/product_create_type.py +5 -0
  19. paid/traces/__init__.py +4 -0
  20. paid/traces/client.py +218 -0
  21. paid/traces/raw_client.py +226 -0
  22. paid/tracing/context_manager.py +9 -4
  23. paid/types/__init__.py +32 -2
  24. paid/types/cost_trace.py +6 -1
  25. paid/types/customer.py +4 -3
  26. paid/types/customer_update.py +4 -2
  27. paid/types/order_line_attribute_create_one.py +5 -0
  28. paid/types/order_line_create.py +26 -5
  29. paid/types/pagination_meta.py +26 -0
  30. paid/types/plan.py +81 -0
  31. paid/types/plan_plan_products_item.py +35 -0
  32. paid/types/plan_plan_products_item_plan_product_attribute_item.py +34 -0
  33. paid/types/product.py +56 -0
  34. paid/types/product_type.py +5 -0
  35. paid/types/product_update.py +36 -0
  36. paid/types/product_update_type.py +5 -0
  37. paid/types/signal.py +17 -5
  38. paid/types/signal_v_2.py +56 -0
  39. paid/types/trace.py +69 -0
  40. paid/types/traces_response.py +26 -0
  41. paid/types/{order_line_attribute_create.py → usage_pagination_meta.py} +16 -8
  42. paid/types/usage_summaries_response.py +26 -0
  43. paid/types/usage_summary.py +121 -0
  44. paid/types/usage_summary_order.py +26 -0
  45. paid/types/usage_summary_order_line.py +26 -0
  46. paid/usage/__init__.py +3 -0
  47. paid/usage/client.py +206 -0
  48. paid/usage/raw_client.py +283 -0
  49. paid/usage/types/__init__.py +7 -0
  50. paid/usage/types/usage_check_usage_response.py +53 -0
  51. {paid_python-0.4.1a0.dist-info → paid_python-0.5.0.dist-info}/METADATA +20 -20
  52. {paid_python-0.4.1a0.dist-info → paid_python-0.5.0.dist-info}/RECORD +54 -25
  53. {paid_python-0.4.1a0.dist-info → paid_python-0.5.0.dist-info}/LICENSE +0 -0
  54. {paid_python-0.4.1a0.dist-info → paid_python-0.5.0.dist-info}/WHEEL +0 -0
paid/plans/client.py ADDED
@@ -0,0 +1,261 @@
1
+ # This file was auto-generated by Fern from our API Definition.
2
+
3
+ import datetime as dt
4
+ import typing
5
+
6
+ from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
7
+ from ..core.request_options import RequestOptions
8
+ from ..types.plan import Plan
9
+ from ..types.usage_summaries_response import UsageSummariesResponse
10
+ from .raw_client import AsyncRawPlansClient, RawPlansClient
11
+
12
+
13
+ class PlansClient:
14
+ def __init__(self, *, client_wrapper: SyncClientWrapper):
15
+ self._raw_client = RawPlansClient(client_wrapper=client_wrapper)
16
+
17
+ @property
18
+ def with_raw_response(self) -> RawPlansClient:
19
+ """
20
+ Retrieves a raw implementation of this client that returns raw responses.
21
+
22
+ Returns
23
+ -------
24
+ RawPlansClient
25
+ """
26
+ return self._raw_client
27
+
28
+ def get_by_id(self, plan_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> Plan:
29
+ """
30
+ Parameters
31
+ ----------
32
+ plan_id : str
33
+ The ID of the plan
34
+
35
+ request_options : typing.Optional[RequestOptions]
36
+ Request-specific configuration.
37
+
38
+ Returns
39
+ -------
40
+ Plan
41
+ Success response
42
+
43
+ Examples
44
+ --------
45
+ from paid import Paid
46
+
47
+ client = Paid(
48
+ token="YOUR_TOKEN",
49
+ )
50
+ client.plans.get_by_id(
51
+ plan_id="planId",
52
+ )
53
+ """
54
+ _response = self._raw_client.get_by_id(plan_id, request_options=request_options)
55
+ return _response.data
56
+
57
+ def get_usage(
58
+ self,
59
+ plan_id: str,
60
+ *,
61
+ external_id: str,
62
+ limit: typing.Optional[int] = None,
63
+ offset: typing.Optional[int] = None,
64
+ start_time: typing.Optional[dt.datetime] = None,
65
+ end_time: typing.Optional[dt.datetime] = None,
66
+ request_options: typing.Optional[RequestOptions] = None,
67
+ ) -> UsageSummariesResponse:
68
+ """
69
+ Parameters
70
+ ----------
71
+ plan_id : str
72
+ The ID of the plan
73
+
74
+ external_id : str
75
+ The external ID of the customer
76
+
77
+ limit : typing.Optional[int]
78
+ Maximum number of usage summaries to return (1-1000)
79
+
80
+ offset : typing.Optional[int]
81
+ Number of usage summaries to skip for pagination
82
+
83
+ start_time : typing.Optional[dt.datetime]
84
+ Filter usage summaries starting from this time (ISO 8601 format). Returns summaries that overlap with the time range.
85
+
86
+ end_time : typing.Optional[dt.datetime]
87
+ Filter usage summaries up to this time (ISO 8601 format). Returns summaries that overlap with the time range.
88
+
89
+ request_options : typing.Optional[RequestOptions]
90
+ Request-specific configuration.
91
+
92
+ Returns
93
+ -------
94
+ UsageSummariesResponse
95
+ Success response
96
+
97
+ Examples
98
+ --------
99
+ import datetime
100
+
101
+ from paid import Paid
102
+
103
+ client = Paid(
104
+ token="YOUR_TOKEN",
105
+ )
106
+ client.plans.get_usage(
107
+ plan_id="planId",
108
+ external_id="externalId",
109
+ limit=1,
110
+ offset=1,
111
+ start_time=datetime.datetime.fromisoformat(
112
+ "2024-01-15 09:30:00+00:00",
113
+ ),
114
+ end_time=datetime.datetime.fromisoformat(
115
+ "2024-01-15 09:30:00+00:00",
116
+ ),
117
+ )
118
+ """
119
+ _response = self._raw_client.get_usage(
120
+ plan_id,
121
+ external_id=external_id,
122
+ limit=limit,
123
+ offset=offset,
124
+ start_time=start_time,
125
+ end_time=end_time,
126
+ request_options=request_options,
127
+ )
128
+ return _response.data
129
+
130
+
131
+ class AsyncPlansClient:
132
+ def __init__(self, *, client_wrapper: AsyncClientWrapper):
133
+ self._raw_client = AsyncRawPlansClient(client_wrapper=client_wrapper)
134
+
135
+ @property
136
+ def with_raw_response(self) -> AsyncRawPlansClient:
137
+ """
138
+ Retrieves a raw implementation of this client that returns raw responses.
139
+
140
+ Returns
141
+ -------
142
+ AsyncRawPlansClient
143
+ """
144
+ return self._raw_client
145
+
146
+ async def get_by_id(self, plan_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> Plan:
147
+ """
148
+ Parameters
149
+ ----------
150
+ plan_id : str
151
+ The ID of the plan
152
+
153
+ request_options : typing.Optional[RequestOptions]
154
+ Request-specific configuration.
155
+
156
+ Returns
157
+ -------
158
+ Plan
159
+ Success response
160
+
161
+ Examples
162
+ --------
163
+ import asyncio
164
+
165
+ from paid import AsyncPaid
166
+
167
+ client = AsyncPaid(
168
+ token="YOUR_TOKEN",
169
+ )
170
+
171
+
172
+ async def main() -> None:
173
+ await client.plans.get_by_id(
174
+ plan_id="planId",
175
+ )
176
+
177
+
178
+ asyncio.run(main())
179
+ """
180
+ _response = await self._raw_client.get_by_id(plan_id, request_options=request_options)
181
+ return _response.data
182
+
183
+ async def get_usage(
184
+ self,
185
+ plan_id: str,
186
+ *,
187
+ external_id: str,
188
+ limit: typing.Optional[int] = None,
189
+ offset: typing.Optional[int] = None,
190
+ start_time: typing.Optional[dt.datetime] = None,
191
+ end_time: typing.Optional[dt.datetime] = None,
192
+ request_options: typing.Optional[RequestOptions] = None,
193
+ ) -> UsageSummariesResponse:
194
+ """
195
+ Parameters
196
+ ----------
197
+ plan_id : str
198
+ The ID of the plan
199
+
200
+ external_id : str
201
+ The external ID of the customer
202
+
203
+ limit : typing.Optional[int]
204
+ Maximum number of usage summaries to return (1-1000)
205
+
206
+ offset : typing.Optional[int]
207
+ Number of usage summaries to skip for pagination
208
+
209
+ start_time : typing.Optional[dt.datetime]
210
+ Filter usage summaries starting from this time (ISO 8601 format). Returns summaries that overlap with the time range.
211
+
212
+ end_time : typing.Optional[dt.datetime]
213
+ Filter usage summaries up to this time (ISO 8601 format). Returns summaries that overlap with the time range.
214
+
215
+ request_options : typing.Optional[RequestOptions]
216
+ Request-specific configuration.
217
+
218
+ Returns
219
+ -------
220
+ UsageSummariesResponse
221
+ Success response
222
+
223
+ Examples
224
+ --------
225
+ import asyncio
226
+ import datetime
227
+
228
+ from paid import AsyncPaid
229
+
230
+ client = AsyncPaid(
231
+ token="YOUR_TOKEN",
232
+ )
233
+
234
+
235
+ async def main() -> None:
236
+ await client.plans.get_usage(
237
+ plan_id="planId",
238
+ external_id="externalId",
239
+ limit=1,
240
+ offset=1,
241
+ start_time=datetime.datetime.fromisoformat(
242
+ "2024-01-15 09:30:00+00:00",
243
+ ),
244
+ end_time=datetime.datetime.fromisoformat(
245
+ "2024-01-15 09:30:00+00:00",
246
+ ),
247
+ )
248
+
249
+
250
+ asyncio.run(main())
251
+ """
252
+ _response = await self._raw_client.get_usage(
253
+ plan_id,
254
+ external_id=external_id,
255
+ limit=limit,
256
+ offset=offset,
257
+ start_time=start_time,
258
+ end_time=end_time,
259
+ request_options=request_options,
260
+ )
261
+ return _response.data
@@ -0,0 +1,345 @@
1
+ # This file was auto-generated by Fern from our API Definition.
2
+
3
+ import datetime as dt
4
+ import typing
5
+ from json.decoder import JSONDecodeError
6
+
7
+ from ..core.api_error import ApiError
8
+ from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
9
+ from ..core.datetime_utils import serialize_datetime
10
+ from ..core.http_response import AsyncHttpResponse, HttpResponse
11
+ from ..core.jsonable_encoder import jsonable_encoder
12
+ from ..core.pydantic_utilities import parse_obj_as
13
+ from ..core.request_options import RequestOptions
14
+ from ..errors.bad_request_error import BadRequestError
15
+ from ..errors.forbidden_error import ForbiddenError
16
+ from ..errors.not_found_error import NotFoundError
17
+ from ..types.error import Error
18
+ from ..types.plan import Plan
19
+ from ..types.usage_summaries_response import UsageSummariesResponse
20
+
21
+
22
+ class RawPlansClient:
23
+ def __init__(self, *, client_wrapper: SyncClientWrapper):
24
+ self._client_wrapper = client_wrapper
25
+
26
+ def get_by_id(self, plan_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> HttpResponse[Plan]:
27
+ """
28
+ Parameters
29
+ ----------
30
+ plan_id : str
31
+ The ID of the plan
32
+
33
+ request_options : typing.Optional[RequestOptions]
34
+ Request-specific configuration.
35
+
36
+ Returns
37
+ -------
38
+ HttpResponse[Plan]
39
+ Success response
40
+ """
41
+ _response = self._client_wrapper.httpx_client.request(
42
+ f"plans/{jsonable_encoder(plan_id)}",
43
+ method="GET",
44
+ request_options=request_options,
45
+ )
46
+ try:
47
+ if 200 <= _response.status_code < 300:
48
+ _data = typing.cast(
49
+ Plan,
50
+ parse_obj_as(
51
+ type_=Plan, # type: ignore
52
+ object_=_response.json(),
53
+ ),
54
+ )
55
+ return HttpResponse(response=_response, data=_data)
56
+ if _response.status_code == 403:
57
+ raise ForbiddenError(
58
+ headers=dict(_response.headers),
59
+ body=typing.cast(
60
+ Error,
61
+ parse_obj_as(
62
+ type_=Error, # type: ignore
63
+ object_=_response.json(),
64
+ ),
65
+ ),
66
+ )
67
+ if _response.status_code == 404:
68
+ raise NotFoundError(
69
+ headers=dict(_response.headers),
70
+ body=typing.cast(
71
+ Error,
72
+ parse_obj_as(
73
+ type_=Error, # type: ignore
74
+ object_=_response.json(),
75
+ ),
76
+ ),
77
+ )
78
+ _response_json = _response.json()
79
+ except JSONDecodeError:
80
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
81
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
82
+
83
+ def get_usage(
84
+ self,
85
+ plan_id: str,
86
+ *,
87
+ external_id: str,
88
+ limit: typing.Optional[int] = None,
89
+ offset: typing.Optional[int] = None,
90
+ start_time: typing.Optional[dt.datetime] = None,
91
+ end_time: typing.Optional[dt.datetime] = None,
92
+ request_options: typing.Optional[RequestOptions] = None,
93
+ ) -> HttpResponse[UsageSummariesResponse]:
94
+ """
95
+ Parameters
96
+ ----------
97
+ plan_id : str
98
+ The ID of the plan
99
+
100
+ external_id : str
101
+ The external ID of the customer
102
+
103
+ limit : typing.Optional[int]
104
+ Maximum number of usage summaries to return (1-1000)
105
+
106
+ offset : typing.Optional[int]
107
+ Number of usage summaries to skip for pagination
108
+
109
+ start_time : typing.Optional[dt.datetime]
110
+ Filter usage summaries starting from this time (ISO 8601 format). Returns summaries that overlap with the time range.
111
+
112
+ end_time : typing.Optional[dt.datetime]
113
+ Filter usage summaries up to this time (ISO 8601 format). Returns summaries that overlap with the time range.
114
+
115
+ request_options : typing.Optional[RequestOptions]
116
+ Request-specific configuration.
117
+
118
+ Returns
119
+ -------
120
+ HttpResponse[UsageSummariesResponse]
121
+ Success response
122
+ """
123
+ _response = self._client_wrapper.httpx_client.request(
124
+ f"plans/{jsonable_encoder(plan_id)}/usage",
125
+ method="GET",
126
+ params={
127
+ "externalId": external_id,
128
+ "limit": limit,
129
+ "offset": offset,
130
+ "startTime": serialize_datetime(start_time) if start_time is not None else None,
131
+ "endTime": serialize_datetime(end_time) if end_time is not None else None,
132
+ },
133
+ request_options=request_options,
134
+ )
135
+ try:
136
+ if 200 <= _response.status_code < 300:
137
+ _data = typing.cast(
138
+ UsageSummariesResponse,
139
+ parse_obj_as(
140
+ type_=UsageSummariesResponse, # type: ignore
141
+ object_=_response.json(),
142
+ ),
143
+ )
144
+ return HttpResponse(response=_response, data=_data)
145
+ if _response.status_code == 400:
146
+ raise BadRequestError(
147
+ headers=dict(_response.headers),
148
+ body=typing.cast(
149
+ Error,
150
+ parse_obj_as(
151
+ type_=Error, # type: ignore
152
+ object_=_response.json(),
153
+ ),
154
+ ),
155
+ )
156
+ if _response.status_code == 403:
157
+ raise ForbiddenError(
158
+ headers=dict(_response.headers),
159
+ body=typing.cast(
160
+ Error,
161
+ parse_obj_as(
162
+ type_=Error, # type: ignore
163
+ object_=_response.json(),
164
+ ),
165
+ ),
166
+ )
167
+ if _response.status_code == 404:
168
+ raise NotFoundError(
169
+ headers=dict(_response.headers),
170
+ body=typing.cast(
171
+ Error,
172
+ parse_obj_as(
173
+ type_=Error, # type: ignore
174
+ object_=_response.json(),
175
+ ),
176
+ ),
177
+ )
178
+ _response_json = _response.json()
179
+ except JSONDecodeError:
180
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
181
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
182
+
183
+
184
+ class AsyncRawPlansClient:
185
+ def __init__(self, *, client_wrapper: AsyncClientWrapper):
186
+ self._client_wrapper = client_wrapper
187
+
188
+ async def get_by_id(
189
+ self, plan_id: str, *, request_options: typing.Optional[RequestOptions] = None
190
+ ) -> AsyncHttpResponse[Plan]:
191
+ """
192
+ Parameters
193
+ ----------
194
+ plan_id : str
195
+ The ID of the plan
196
+
197
+ request_options : typing.Optional[RequestOptions]
198
+ Request-specific configuration.
199
+
200
+ Returns
201
+ -------
202
+ AsyncHttpResponse[Plan]
203
+ Success response
204
+ """
205
+ _response = await self._client_wrapper.httpx_client.request(
206
+ f"plans/{jsonable_encoder(plan_id)}",
207
+ method="GET",
208
+ request_options=request_options,
209
+ )
210
+ try:
211
+ if 200 <= _response.status_code < 300:
212
+ _data = typing.cast(
213
+ Plan,
214
+ parse_obj_as(
215
+ type_=Plan, # type: ignore
216
+ object_=_response.json(),
217
+ ),
218
+ )
219
+ return AsyncHttpResponse(response=_response, data=_data)
220
+ if _response.status_code == 403:
221
+ raise ForbiddenError(
222
+ headers=dict(_response.headers),
223
+ body=typing.cast(
224
+ Error,
225
+ parse_obj_as(
226
+ type_=Error, # type: ignore
227
+ object_=_response.json(),
228
+ ),
229
+ ),
230
+ )
231
+ if _response.status_code == 404:
232
+ raise NotFoundError(
233
+ headers=dict(_response.headers),
234
+ body=typing.cast(
235
+ Error,
236
+ parse_obj_as(
237
+ type_=Error, # type: ignore
238
+ object_=_response.json(),
239
+ ),
240
+ ),
241
+ )
242
+ _response_json = _response.json()
243
+ except JSONDecodeError:
244
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
245
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
246
+
247
+ async def get_usage(
248
+ self,
249
+ plan_id: str,
250
+ *,
251
+ external_id: str,
252
+ limit: typing.Optional[int] = None,
253
+ offset: typing.Optional[int] = None,
254
+ start_time: typing.Optional[dt.datetime] = None,
255
+ end_time: typing.Optional[dt.datetime] = None,
256
+ request_options: typing.Optional[RequestOptions] = None,
257
+ ) -> AsyncHttpResponse[UsageSummariesResponse]:
258
+ """
259
+ Parameters
260
+ ----------
261
+ plan_id : str
262
+ The ID of the plan
263
+
264
+ external_id : str
265
+ The external ID of the customer
266
+
267
+ limit : typing.Optional[int]
268
+ Maximum number of usage summaries to return (1-1000)
269
+
270
+ offset : typing.Optional[int]
271
+ Number of usage summaries to skip for pagination
272
+
273
+ start_time : typing.Optional[dt.datetime]
274
+ Filter usage summaries starting from this time (ISO 8601 format). Returns summaries that overlap with the time range.
275
+
276
+ end_time : typing.Optional[dt.datetime]
277
+ Filter usage summaries up to this time (ISO 8601 format). Returns summaries that overlap with the time range.
278
+
279
+ request_options : typing.Optional[RequestOptions]
280
+ Request-specific configuration.
281
+
282
+ Returns
283
+ -------
284
+ AsyncHttpResponse[UsageSummariesResponse]
285
+ Success response
286
+ """
287
+ _response = await self._client_wrapper.httpx_client.request(
288
+ f"plans/{jsonable_encoder(plan_id)}/usage",
289
+ method="GET",
290
+ params={
291
+ "externalId": external_id,
292
+ "limit": limit,
293
+ "offset": offset,
294
+ "startTime": serialize_datetime(start_time) if start_time is not None else None,
295
+ "endTime": serialize_datetime(end_time) if end_time is not None else None,
296
+ },
297
+ request_options=request_options,
298
+ )
299
+ try:
300
+ if 200 <= _response.status_code < 300:
301
+ _data = typing.cast(
302
+ UsageSummariesResponse,
303
+ parse_obj_as(
304
+ type_=UsageSummariesResponse, # type: ignore
305
+ object_=_response.json(),
306
+ ),
307
+ )
308
+ return AsyncHttpResponse(response=_response, data=_data)
309
+ if _response.status_code == 400:
310
+ raise BadRequestError(
311
+ headers=dict(_response.headers),
312
+ body=typing.cast(
313
+ Error,
314
+ parse_obj_as(
315
+ type_=Error, # type: ignore
316
+ object_=_response.json(),
317
+ ),
318
+ ),
319
+ )
320
+ if _response.status_code == 403:
321
+ raise ForbiddenError(
322
+ headers=dict(_response.headers),
323
+ body=typing.cast(
324
+ Error,
325
+ parse_obj_as(
326
+ type_=Error, # type: ignore
327
+ object_=_response.json(),
328
+ ),
329
+ ),
330
+ )
331
+ if _response.status_code == 404:
332
+ raise NotFoundError(
333
+ headers=dict(_response.headers),
334
+ body=typing.cast(
335
+ Error,
336
+ parse_obj_as(
337
+ type_=Error, # type: ignore
338
+ object_=_response.json(),
339
+ ),
340
+ ),
341
+ )
342
+ _response_json = _response.json()
343
+ except JSONDecodeError:
344
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
345
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
@@ -0,0 +1,7 @@
1
+ # This file was auto-generated by Fern from our API Definition.
2
+
3
+ # isort: skip_file
4
+
5
+ from .types import ProductCreateType
6
+
7
+ __all__ = ["ProductCreateType"]