dodopayments 1.51.0__py3-none-any.whl → 1.52.4__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.
Potentially problematic release.
This version of dodopayments might be problematic. Click here for more details.
- dodopayments/_client.py +18 -0
- dodopayments/_models.py +1 -1
- dodopayments/_types.py +35 -1
- dodopayments/_utils/__init__.py +1 -0
- dodopayments/_utils/_transform.py +6 -0
- dodopayments/_utils/_typing.py +5 -0
- dodopayments/_version.py +1 -1
- dodopayments/resources/__init__.py +28 -0
- dodopayments/resources/discounts.py +6 -6
- dodopayments/resources/invoices/payments.py +80 -0
- dodopayments/resources/meters.py +554 -0
- dodopayments/resources/products/products.py +16 -16
- dodopayments/resources/subscriptions.py +223 -0
- dodopayments/resources/usage_events.py +597 -0
- dodopayments/types/__init__.py +20 -0
- dodopayments/types/add_meter_to_price.py +29 -0
- dodopayments/types/add_meter_to_price_param.py +30 -0
- dodopayments/types/discount_create_params.py +3 -2
- dodopayments/types/discount_update_params.py +3 -2
- dodopayments/types/event.py +26 -0
- dodopayments/types/event_input_param.py +38 -0
- dodopayments/types/meter.py +40 -0
- dodopayments/types/meter_aggregation.py +16 -0
- dodopayments/types/meter_aggregation_param.py +16 -0
- dodopayments/types/meter_create_params.py +31 -0
- dodopayments/types/meter_filter.py +131 -0
- dodopayments/types/meter_filter_param.py +143 -0
- dodopayments/types/meter_list_params.py +18 -0
- dodopayments/types/payment.py +6 -0
- dodopayments/types/price.py +52 -5
- dodopayments/types/price_param.py +52 -5
- dodopayments/types/product_create_params.py +3 -2
- dodopayments/types/product_update_params.py +4 -3
- dodopayments/types/subscription.py +20 -1
- dodopayments/types/subscription_retrieve_usage_history_params.py +28 -0
- dodopayments/types/subscription_retrieve_usage_history_response.py +46 -0
- dodopayments/types/usage_event_ingest_params.py +15 -0
- dodopayments/types/usage_event_ingest_response.py +9 -0
- dodopayments/types/usage_event_list_params.py +42 -0
- {dodopayments-1.51.0.dist-info → dodopayments-1.52.4.dist-info}/METADATA +1 -1
- {dodopayments-1.51.0.dist-info → dodopayments-1.52.4.dist-info}/RECORD +43 -25
- {dodopayments-1.51.0.dist-info → dodopayments-1.52.4.dist-info}/WHEEL +0 -0
- {dodopayments-1.51.0.dist-info → dodopayments-1.52.4.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,597 @@
|
|
|
1
|
+
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import Union, Iterable
|
|
6
|
+
from datetime import datetime
|
|
7
|
+
|
|
8
|
+
import httpx
|
|
9
|
+
|
|
10
|
+
from ..types import usage_event_list_params, usage_event_ingest_params
|
|
11
|
+
from .._types import NOT_GIVEN, Body, Query, Headers, NotGiven
|
|
12
|
+
from .._utils import maybe_transform, async_maybe_transform
|
|
13
|
+
from .._compat import cached_property
|
|
14
|
+
from .._resource import SyncAPIResource, AsyncAPIResource
|
|
15
|
+
from .._response import (
|
|
16
|
+
to_raw_response_wrapper,
|
|
17
|
+
to_streamed_response_wrapper,
|
|
18
|
+
async_to_raw_response_wrapper,
|
|
19
|
+
async_to_streamed_response_wrapper,
|
|
20
|
+
)
|
|
21
|
+
from ..pagination import SyncDefaultPageNumberPagination, AsyncDefaultPageNumberPagination
|
|
22
|
+
from ..types.event import Event
|
|
23
|
+
from .._base_client import AsyncPaginator, make_request_options
|
|
24
|
+
from ..types.event_input_param import EventInputParam
|
|
25
|
+
from ..types.usage_event_ingest_response import UsageEventIngestResponse
|
|
26
|
+
|
|
27
|
+
__all__ = ["UsageEventsResource", "AsyncUsageEventsResource"]
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class UsageEventsResource(SyncAPIResource):
|
|
31
|
+
@cached_property
|
|
32
|
+
def with_raw_response(self) -> UsageEventsResourceWithRawResponse:
|
|
33
|
+
"""
|
|
34
|
+
This property can be used as a prefix for any HTTP method call to return
|
|
35
|
+
the raw response object instead of the parsed content.
|
|
36
|
+
|
|
37
|
+
For more information, see https://www.github.com/dodopayments/dodopayments-python#accessing-raw-response-data-eg-headers
|
|
38
|
+
"""
|
|
39
|
+
return UsageEventsResourceWithRawResponse(self)
|
|
40
|
+
|
|
41
|
+
@cached_property
|
|
42
|
+
def with_streaming_response(self) -> UsageEventsResourceWithStreamingResponse:
|
|
43
|
+
"""
|
|
44
|
+
An alternative to `.with_raw_response` that doesn't eagerly read the response body.
|
|
45
|
+
|
|
46
|
+
For more information, see https://www.github.com/dodopayments/dodopayments-python#with_streaming_response
|
|
47
|
+
"""
|
|
48
|
+
return UsageEventsResourceWithStreamingResponse(self)
|
|
49
|
+
|
|
50
|
+
def retrieve(
|
|
51
|
+
self,
|
|
52
|
+
event_id: str,
|
|
53
|
+
*,
|
|
54
|
+
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
|
|
55
|
+
# The extra values given here take precedence over values defined on the client or passed to this method.
|
|
56
|
+
extra_headers: Headers | None = None,
|
|
57
|
+
extra_query: Query | None = None,
|
|
58
|
+
extra_body: Body | None = None,
|
|
59
|
+
timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN,
|
|
60
|
+
) -> Event:
|
|
61
|
+
"""Fetch detailed information about a single event using its unique event ID.
|
|
62
|
+
|
|
63
|
+
This
|
|
64
|
+
endpoint is useful for:
|
|
65
|
+
|
|
66
|
+
- Debugging specific event ingestion issues
|
|
67
|
+
- Retrieving event details for customer support
|
|
68
|
+
- Validating that events were processed correctly
|
|
69
|
+
- Getting the complete metadata for an event
|
|
70
|
+
|
|
71
|
+
## Event ID Format:
|
|
72
|
+
|
|
73
|
+
The event ID should be the same value that was provided during event ingestion
|
|
74
|
+
via the `/events/ingest` endpoint. Event IDs are case-sensitive and must match
|
|
75
|
+
exactly.
|
|
76
|
+
|
|
77
|
+
## Response Details:
|
|
78
|
+
|
|
79
|
+
The response includes all event data including:
|
|
80
|
+
|
|
81
|
+
- Complete metadata key-value pairs
|
|
82
|
+
- Original timestamp (preserved from ingestion)
|
|
83
|
+
- Customer and business association
|
|
84
|
+
- Event name and processing information
|
|
85
|
+
|
|
86
|
+
## Example Usage:
|
|
87
|
+
|
|
88
|
+
```text
|
|
89
|
+
GET /events/api_call_12345
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Args:
|
|
93
|
+
extra_headers: Send extra headers
|
|
94
|
+
|
|
95
|
+
extra_query: Add additional query parameters to the request
|
|
96
|
+
|
|
97
|
+
extra_body: Add additional JSON properties to the request
|
|
98
|
+
|
|
99
|
+
timeout: Override the client-level default timeout for this request, in seconds
|
|
100
|
+
"""
|
|
101
|
+
if not event_id:
|
|
102
|
+
raise ValueError(f"Expected a non-empty value for `event_id` but received {event_id!r}")
|
|
103
|
+
return self._get(
|
|
104
|
+
f"/events/{event_id}",
|
|
105
|
+
options=make_request_options(
|
|
106
|
+
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
|
|
107
|
+
),
|
|
108
|
+
cast_to=Event,
|
|
109
|
+
)
|
|
110
|
+
|
|
111
|
+
def list(
|
|
112
|
+
self,
|
|
113
|
+
*,
|
|
114
|
+
customer_id: str | NotGiven = NOT_GIVEN,
|
|
115
|
+
end: Union[str, datetime] | NotGiven = NOT_GIVEN,
|
|
116
|
+
event_name: str | NotGiven = NOT_GIVEN,
|
|
117
|
+
meter_id: str | NotGiven = NOT_GIVEN,
|
|
118
|
+
page_number: int | NotGiven = NOT_GIVEN,
|
|
119
|
+
page_size: int | NotGiven = NOT_GIVEN,
|
|
120
|
+
start: Union[str, datetime] | NotGiven = NOT_GIVEN,
|
|
121
|
+
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
|
|
122
|
+
# The extra values given here take precedence over values defined on the client or passed to this method.
|
|
123
|
+
extra_headers: Headers | None = None,
|
|
124
|
+
extra_query: Query | None = None,
|
|
125
|
+
extra_body: Body | None = None,
|
|
126
|
+
timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN,
|
|
127
|
+
) -> SyncDefaultPageNumberPagination[Event]:
|
|
128
|
+
"""Fetch events from your account with powerful filtering capabilities.
|
|
129
|
+
|
|
130
|
+
This
|
|
131
|
+
endpoint is ideal for:
|
|
132
|
+
|
|
133
|
+
- Debugging event ingestion issues
|
|
134
|
+
- Analyzing customer usage patterns
|
|
135
|
+
- Building custom analytics dashboards
|
|
136
|
+
- Auditing billing-related events
|
|
137
|
+
|
|
138
|
+
## Filtering Options:
|
|
139
|
+
|
|
140
|
+
- **Customer filtering**: Filter by specific customer ID
|
|
141
|
+
- **Event name filtering**: Filter by event type/name
|
|
142
|
+
- **Meter-based filtering**: Use a meter ID to apply the meter's event name and
|
|
143
|
+
filter criteria automatically
|
|
144
|
+
- **Time range filtering**: Filter events within a specific date range
|
|
145
|
+
- **Pagination**: Navigate through large result sets
|
|
146
|
+
|
|
147
|
+
## Meter Integration:
|
|
148
|
+
|
|
149
|
+
When using `meter_id`, the endpoint automatically applies:
|
|
150
|
+
|
|
151
|
+
- The meter's configured `event_name` filter
|
|
152
|
+
- The meter's custom filter criteria (if any)
|
|
153
|
+
- If you also provide `event_name`, it must match the meter's event name
|
|
154
|
+
|
|
155
|
+
## Example Queries:
|
|
156
|
+
|
|
157
|
+
- Get all events for a customer: `?customer_id=cus_abc123`
|
|
158
|
+
- Get API request events: `?event_name=api_request`
|
|
159
|
+
- Get events from last 24 hours:
|
|
160
|
+
`?start=2024-01-14T10:30:00Z&end=2024-01-15T10:30:00Z`
|
|
161
|
+
- Get events with meter filtering: `?meter_id=mtr_xyz789`
|
|
162
|
+
- Paginate results: `?page_size=50&page_number=2`
|
|
163
|
+
|
|
164
|
+
Args:
|
|
165
|
+
customer_id: Filter events by customer ID
|
|
166
|
+
|
|
167
|
+
end: Filter events created before this timestamp
|
|
168
|
+
|
|
169
|
+
event_name: Filter events by event name. If both event_name and meter_id are provided, they
|
|
170
|
+
must match the meter's configured event_name
|
|
171
|
+
|
|
172
|
+
meter_id: Filter events by meter ID. When provided, only events that match the meter's
|
|
173
|
+
event_name and filter criteria will be returned
|
|
174
|
+
|
|
175
|
+
page_number: Page number (0-based, default: 0)
|
|
176
|
+
|
|
177
|
+
page_size: Number of events to return per page (default: 10)
|
|
178
|
+
|
|
179
|
+
start: Filter events created after this timestamp
|
|
180
|
+
|
|
181
|
+
extra_headers: Send extra headers
|
|
182
|
+
|
|
183
|
+
extra_query: Add additional query parameters to the request
|
|
184
|
+
|
|
185
|
+
extra_body: Add additional JSON properties to the request
|
|
186
|
+
|
|
187
|
+
timeout: Override the client-level default timeout for this request, in seconds
|
|
188
|
+
"""
|
|
189
|
+
return self._get_api_list(
|
|
190
|
+
"/events",
|
|
191
|
+
page=SyncDefaultPageNumberPagination[Event],
|
|
192
|
+
options=make_request_options(
|
|
193
|
+
extra_headers=extra_headers,
|
|
194
|
+
extra_query=extra_query,
|
|
195
|
+
extra_body=extra_body,
|
|
196
|
+
timeout=timeout,
|
|
197
|
+
query=maybe_transform(
|
|
198
|
+
{
|
|
199
|
+
"customer_id": customer_id,
|
|
200
|
+
"end": end,
|
|
201
|
+
"event_name": event_name,
|
|
202
|
+
"meter_id": meter_id,
|
|
203
|
+
"page_number": page_number,
|
|
204
|
+
"page_size": page_size,
|
|
205
|
+
"start": start,
|
|
206
|
+
},
|
|
207
|
+
usage_event_list_params.UsageEventListParams,
|
|
208
|
+
),
|
|
209
|
+
),
|
|
210
|
+
model=Event,
|
|
211
|
+
)
|
|
212
|
+
|
|
213
|
+
def ingest(
|
|
214
|
+
self,
|
|
215
|
+
*,
|
|
216
|
+
events: Iterable[EventInputParam],
|
|
217
|
+
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
|
|
218
|
+
# The extra values given here take precedence over values defined on the client or passed to this method.
|
|
219
|
+
extra_headers: Headers | None = None,
|
|
220
|
+
extra_query: Query | None = None,
|
|
221
|
+
extra_body: Body | None = None,
|
|
222
|
+
timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN,
|
|
223
|
+
) -> UsageEventIngestResponse:
|
|
224
|
+
"""
|
|
225
|
+
This endpoint allows you to ingest custom events that can be used for:
|
|
226
|
+
|
|
227
|
+
- Usage-based billing and metering
|
|
228
|
+
- Analytics and reporting
|
|
229
|
+
- Customer behavior tracking
|
|
230
|
+
|
|
231
|
+
## Important Notes:
|
|
232
|
+
|
|
233
|
+
- **Duplicate Prevention**:
|
|
234
|
+
- Duplicate `event_id` values within the same request are rejected (entire
|
|
235
|
+
request fails)
|
|
236
|
+
- Subsequent requests with existing `event_id` values are ignored (idempotent
|
|
237
|
+
behavior)
|
|
238
|
+
- **Rate Limiting**: Maximum 1000 events per request
|
|
239
|
+
- **Time Validation**: Events with timestamps older than 1 hour or more than 5
|
|
240
|
+
minutes in the future will be rejected
|
|
241
|
+
- **Metadata Limits**: Maximum 50 key-value pairs per event, keys max 100 chars,
|
|
242
|
+
values max 500 chars
|
|
243
|
+
|
|
244
|
+
## Example Usage:
|
|
245
|
+
|
|
246
|
+
```json
|
|
247
|
+
{
|
|
248
|
+
"events": [
|
|
249
|
+
{
|
|
250
|
+
"event_id": "api_call_12345",
|
|
251
|
+
"customer_id": "cus_abc123",
|
|
252
|
+
"event_name": "api_request",
|
|
253
|
+
"timestamp": "2024-01-15T10:30:00Z",
|
|
254
|
+
"metadata": {
|
|
255
|
+
"endpoint": "/api/v1/users",
|
|
256
|
+
"method": "GET",
|
|
257
|
+
"tokens_used": "150"
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
]
|
|
261
|
+
}
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
Args:
|
|
265
|
+
events: List of events to be pushed
|
|
266
|
+
|
|
267
|
+
extra_headers: Send extra headers
|
|
268
|
+
|
|
269
|
+
extra_query: Add additional query parameters to the request
|
|
270
|
+
|
|
271
|
+
extra_body: Add additional JSON properties to the request
|
|
272
|
+
|
|
273
|
+
timeout: Override the client-level default timeout for this request, in seconds
|
|
274
|
+
"""
|
|
275
|
+
return self._post(
|
|
276
|
+
"/events/ingest",
|
|
277
|
+
body=maybe_transform({"events": events}, usage_event_ingest_params.UsageEventIngestParams),
|
|
278
|
+
options=make_request_options(
|
|
279
|
+
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
|
|
280
|
+
),
|
|
281
|
+
cast_to=UsageEventIngestResponse,
|
|
282
|
+
)
|
|
283
|
+
|
|
284
|
+
|
|
285
|
+
class AsyncUsageEventsResource(AsyncAPIResource):
|
|
286
|
+
@cached_property
|
|
287
|
+
def with_raw_response(self) -> AsyncUsageEventsResourceWithRawResponse:
|
|
288
|
+
"""
|
|
289
|
+
This property can be used as a prefix for any HTTP method call to return
|
|
290
|
+
the raw response object instead of the parsed content.
|
|
291
|
+
|
|
292
|
+
For more information, see https://www.github.com/dodopayments/dodopayments-python#accessing-raw-response-data-eg-headers
|
|
293
|
+
"""
|
|
294
|
+
return AsyncUsageEventsResourceWithRawResponse(self)
|
|
295
|
+
|
|
296
|
+
@cached_property
|
|
297
|
+
def with_streaming_response(self) -> AsyncUsageEventsResourceWithStreamingResponse:
|
|
298
|
+
"""
|
|
299
|
+
An alternative to `.with_raw_response` that doesn't eagerly read the response body.
|
|
300
|
+
|
|
301
|
+
For more information, see https://www.github.com/dodopayments/dodopayments-python#with_streaming_response
|
|
302
|
+
"""
|
|
303
|
+
return AsyncUsageEventsResourceWithStreamingResponse(self)
|
|
304
|
+
|
|
305
|
+
async def retrieve(
|
|
306
|
+
self,
|
|
307
|
+
event_id: str,
|
|
308
|
+
*,
|
|
309
|
+
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
|
|
310
|
+
# The extra values given here take precedence over values defined on the client or passed to this method.
|
|
311
|
+
extra_headers: Headers | None = None,
|
|
312
|
+
extra_query: Query | None = None,
|
|
313
|
+
extra_body: Body | None = None,
|
|
314
|
+
timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN,
|
|
315
|
+
) -> Event:
|
|
316
|
+
"""Fetch detailed information about a single event using its unique event ID.
|
|
317
|
+
|
|
318
|
+
This
|
|
319
|
+
endpoint is useful for:
|
|
320
|
+
|
|
321
|
+
- Debugging specific event ingestion issues
|
|
322
|
+
- Retrieving event details for customer support
|
|
323
|
+
- Validating that events were processed correctly
|
|
324
|
+
- Getting the complete metadata for an event
|
|
325
|
+
|
|
326
|
+
## Event ID Format:
|
|
327
|
+
|
|
328
|
+
The event ID should be the same value that was provided during event ingestion
|
|
329
|
+
via the `/events/ingest` endpoint. Event IDs are case-sensitive and must match
|
|
330
|
+
exactly.
|
|
331
|
+
|
|
332
|
+
## Response Details:
|
|
333
|
+
|
|
334
|
+
The response includes all event data including:
|
|
335
|
+
|
|
336
|
+
- Complete metadata key-value pairs
|
|
337
|
+
- Original timestamp (preserved from ingestion)
|
|
338
|
+
- Customer and business association
|
|
339
|
+
- Event name and processing information
|
|
340
|
+
|
|
341
|
+
## Example Usage:
|
|
342
|
+
|
|
343
|
+
```text
|
|
344
|
+
GET /events/api_call_12345
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
Args:
|
|
348
|
+
extra_headers: Send extra headers
|
|
349
|
+
|
|
350
|
+
extra_query: Add additional query parameters to the request
|
|
351
|
+
|
|
352
|
+
extra_body: Add additional JSON properties to the request
|
|
353
|
+
|
|
354
|
+
timeout: Override the client-level default timeout for this request, in seconds
|
|
355
|
+
"""
|
|
356
|
+
if not event_id:
|
|
357
|
+
raise ValueError(f"Expected a non-empty value for `event_id` but received {event_id!r}")
|
|
358
|
+
return await self._get(
|
|
359
|
+
f"/events/{event_id}",
|
|
360
|
+
options=make_request_options(
|
|
361
|
+
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
|
|
362
|
+
),
|
|
363
|
+
cast_to=Event,
|
|
364
|
+
)
|
|
365
|
+
|
|
366
|
+
def list(
|
|
367
|
+
self,
|
|
368
|
+
*,
|
|
369
|
+
customer_id: str | NotGiven = NOT_GIVEN,
|
|
370
|
+
end: Union[str, datetime] | NotGiven = NOT_GIVEN,
|
|
371
|
+
event_name: str | NotGiven = NOT_GIVEN,
|
|
372
|
+
meter_id: str | NotGiven = NOT_GIVEN,
|
|
373
|
+
page_number: int | NotGiven = NOT_GIVEN,
|
|
374
|
+
page_size: int | NotGiven = NOT_GIVEN,
|
|
375
|
+
start: Union[str, datetime] | NotGiven = NOT_GIVEN,
|
|
376
|
+
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
|
|
377
|
+
# The extra values given here take precedence over values defined on the client or passed to this method.
|
|
378
|
+
extra_headers: Headers | None = None,
|
|
379
|
+
extra_query: Query | None = None,
|
|
380
|
+
extra_body: Body | None = None,
|
|
381
|
+
timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN,
|
|
382
|
+
) -> AsyncPaginator[Event, AsyncDefaultPageNumberPagination[Event]]:
|
|
383
|
+
"""Fetch events from your account with powerful filtering capabilities.
|
|
384
|
+
|
|
385
|
+
This
|
|
386
|
+
endpoint is ideal for:
|
|
387
|
+
|
|
388
|
+
- Debugging event ingestion issues
|
|
389
|
+
- Analyzing customer usage patterns
|
|
390
|
+
- Building custom analytics dashboards
|
|
391
|
+
- Auditing billing-related events
|
|
392
|
+
|
|
393
|
+
## Filtering Options:
|
|
394
|
+
|
|
395
|
+
- **Customer filtering**: Filter by specific customer ID
|
|
396
|
+
- **Event name filtering**: Filter by event type/name
|
|
397
|
+
- **Meter-based filtering**: Use a meter ID to apply the meter's event name and
|
|
398
|
+
filter criteria automatically
|
|
399
|
+
- **Time range filtering**: Filter events within a specific date range
|
|
400
|
+
- **Pagination**: Navigate through large result sets
|
|
401
|
+
|
|
402
|
+
## Meter Integration:
|
|
403
|
+
|
|
404
|
+
When using `meter_id`, the endpoint automatically applies:
|
|
405
|
+
|
|
406
|
+
- The meter's configured `event_name` filter
|
|
407
|
+
- The meter's custom filter criteria (if any)
|
|
408
|
+
- If you also provide `event_name`, it must match the meter's event name
|
|
409
|
+
|
|
410
|
+
## Example Queries:
|
|
411
|
+
|
|
412
|
+
- Get all events for a customer: `?customer_id=cus_abc123`
|
|
413
|
+
- Get API request events: `?event_name=api_request`
|
|
414
|
+
- Get events from last 24 hours:
|
|
415
|
+
`?start=2024-01-14T10:30:00Z&end=2024-01-15T10:30:00Z`
|
|
416
|
+
- Get events with meter filtering: `?meter_id=mtr_xyz789`
|
|
417
|
+
- Paginate results: `?page_size=50&page_number=2`
|
|
418
|
+
|
|
419
|
+
Args:
|
|
420
|
+
customer_id: Filter events by customer ID
|
|
421
|
+
|
|
422
|
+
end: Filter events created before this timestamp
|
|
423
|
+
|
|
424
|
+
event_name: Filter events by event name. If both event_name and meter_id are provided, they
|
|
425
|
+
must match the meter's configured event_name
|
|
426
|
+
|
|
427
|
+
meter_id: Filter events by meter ID. When provided, only events that match the meter's
|
|
428
|
+
event_name and filter criteria will be returned
|
|
429
|
+
|
|
430
|
+
page_number: Page number (0-based, default: 0)
|
|
431
|
+
|
|
432
|
+
page_size: Number of events to return per page (default: 10)
|
|
433
|
+
|
|
434
|
+
start: Filter events created after this timestamp
|
|
435
|
+
|
|
436
|
+
extra_headers: Send extra headers
|
|
437
|
+
|
|
438
|
+
extra_query: Add additional query parameters to the request
|
|
439
|
+
|
|
440
|
+
extra_body: Add additional JSON properties to the request
|
|
441
|
+
|
|
442
|
+
timeout: Override the client-level default timeout for this request, in seconds
|
|
443
|
+
"""
|
|
444
|
+
return self._get_api_list(
|
|
445
|
+
"/events",
|
|
446
|
+
page=AsyncDefaultPageNumberPagination[Event],
|
|
447
|
+
options=make_request_options(
|
|
448
|
+
extra_headers=extra_headers,
|
|
449
|
+
extra_query=extra_query,
|
|
450
|
+
extra_body=extra_body,
|
|
451
|
+
timeout=timeout,
|
|
452
|
+
query=maybe_transform(
|
|
453
|
+
{
|
|
454
|
+
"customer_id": customer_id,
|
|
455
|
+
"end": end,
|
|
456
|
+
"event_name": event_name,
|
|
457
|
+
"meter_id": meter_id,
|
|
458
|
+
"page_number": page_number,
|
|
459
|
+
"page_size": page_size,
|
|
460
|
+
"start": start,
|
|
461
|
+
},
|
|
462
|
+
usage_event_list_params.UsageEventListParams,
|
|
463
|
+
),
|
|
464
|
+
),
|
|
465
|
+
model=Event,
|
|
466
|
+
)
|
|
467
|
+
|
|
468
|
+
async def ingest(
|
|
469
|
+
self,
|
|
470
|
+
*,
|
|
471
|
+
events: Iterable[EventInputParam],
|
|
472
|
+
# Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs.
|
|
473
|
+
# The extra values given here take precedence over values defined on the client or passed to this method.
|
|
474
|
+
extra_headers: Headers | None = None,
|
|
475
|
+
extra_query: Query | None = None,
|
|
476
|
+
extra_body: Body | None = None,
|
|
477
|
+
timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN,
|
|
478
|
+
) -> UsageEventIngestResponse:
|
|
479
|
+
"""
|
|
480
|
+
This endpoint allows you to ingest custom events that can be used for:
|
|
481
|
+
|
|
482
|
+
- Usage-based billing and metering
|
|
483
|
+
- Analytics and reporting
|
|
484
|
+
- Customer behavior tracking
|
|
485
|
+
|
|
486
|
+
## Important Notes:
|
|
487
|
+
|
|
488
|
+
- **Duplicate Prevention**:
|
|
489
|
+
- Duplicate `event_id` values within the same request are rejected (entire
|
|
490
|
+
request fails)
|
|
491
|
+
- Subsequent requests with existing `event_id` values are ignored (idempotent
|
|
492
|
+
behavior)
|
|
493
|
+
- **Rate Limiting**: Maximum 1000 events per request
|
|
494
|
+
- **Time Validation**: Events with timestamps older than 1 hour or more than 5
|
|
495
|
+
minutes in the future will be rejected
|
|
496
|
+
- **Metadata Limits**: Maximum 50 key-value pairs per event, keys max 100 chars,
|
|
497
|
+
values max 500 chars
|
|
498
|
+
|
|
499
|
+
## Example Usage:
|
|
500
|
+
|
|
501
|
+
```json
|
|
502
|
+
{
|
|
503
|
+
"events": [
|
|
504
|
+
{
|
|
505
|
+
"event_id": "api_call_12345",
|
|
506
|
+
"customer_id": "cus_abc123",
|
|
507
|
+
"event_name": "api_request",
|
|
508
|
+
"timestamp": "2024-01-15T10:30:00Z",
|
|
509
|
+
"metadata": {
|
|
510
|
+
"endpoint": "/api/v1/users",
|
|
511
|
+
"method": "GET",
|
|
512
|
+
"tokens_used": "150"
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
]
|
|
516
|
+
}
|
|
517
|
+
```
|
|
518
|
+
|
|
519
|
+
Args:
|
|
520
|
+
events: List of events to be pushed
|
|
521
|
+
|
|
522
|
+
extra_headers: Send extra headers
|
|
523
|
+
|
|
524
|
+
extra_query: Add additional query parameters to the request
|
|
525
|
+
|
|
526
|
+
extra_body: Add additional JSON properties to the request
|
|
527
|
+
|
|
528
|
+
timeout: Override the client-level default timeout for this request, in seconds
|
|
529
|
+
"""
|
|
530
|
+
return await self._post(
|
|
531
|
+
"/events/ingest",
|
|
532
|
+
body=await async_maybe_transform({"events": events}, usage_event_ingest_params.UsageEventIngestParams),
|
|
533
|
+
options=make_request_options(
|
|
534
|
+
extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
|
|
535
|
+
),
|
|
536
|
+
cast_to=UsageEventIngestResponse,
|
|
537
|
+
)
|
|
538
|
+
|
|
539
|
+
|
|
540
|
+
class UsageEventsResourceWithRawResponse:
|
|
541
|
+
def __init__(self, usage_events: UsageEventsResource) -> None:
|
|
542
|
+
self._usage_events = usage_events
|
|
543
|
+
|
|
544
|
+
self.retrieve = to_raw_response_wrapper(
|
|
545
|
+
usage_events.retrieve,
|
|
546
|
+
)
|
|
547
|
+
self.list = to_raw_response_wrapper(
|
|
548
|
+
usage_events.list,
|
|
549
|
+
)
|
|
550
|
+
self.ingest = to_raw_response_wrapper(
|
|
551
|
+
usage_events.ingest,
|
|
552
|
+
)
|
|
553
|
+
|
|
554
|
+
|
|
555
|
+
class AsyncUsageEventsResourceWithRawResponse:
|
|
556
|
+
def __init__(self, usage_events: AsyncUsageEventsResource) -> None:
|
|
557
|
+
self._usage_events = usage_events
|
|
558
|
+
|
|
559
|
+
self.retrieve = async_to_raw_response_wrapper(
|
|
560
|
+
usage_events.retrieve,
|
|
561
|
+
)
|
|
562
|
+
self.list = async_to_raw_response_wrapper(
|
|
563
|
+
usage_events.list,
|
|
564
|
+
)
|
|
565
|
+
self.ingest = async_to_raw_response_wrapper(
|
|
566
|
+
usage_events.ingest,
|
|
567
|
+
)
|
|
568
|
+
|
|
569
|
+
|
|
570
|
+
class UsageEventsResourceWithStreamingResponse:
|
|
571
|
+
def __init__(self, usage_events: UsageEventsResource) -> None:
|
|
572
|
+
self._usage_events = usage_events
|
|
573
|
+
|
|
574
|
+
self.retrieve = to_streamed_response_wrapper(
|
|
575
|
+
usage_events.retrieve,
|
|
576
|
+
)
|
|
577
|
+
self.list = to_streamed_response_wrapper(
|
|
578
|
+
usage_events.list,
|
|
579
|
+
)
|
|
580
|
+
self.ingest = to_streamed_response_wrapper(
|
|
581
|
+
usage_events.ingest,
|
|
582
|
+
)
|
|
583
|
+
|
|
584
|
+
|
|
585
|
+
class AsyncUsageEventsResourceWithStreamingResponse:
|
|
586
|
+
def __init__(self, usage_events: AsyncUsageEventsResource) -> None:
|
|
587
|
+
self._usage_events = usage_events
|
|
588
|
+
|
|
589
|
+
self.retrieve = async_to_streamed_response_wrapper(
|
|
590
|
+
usage_events.retrieve,
|
|
591
|
+
)
|
|
592
|
+
self.list = async_to_streamed_response_wrapper(
|
|
593
|
+
usage_events.list,
|
|
594
|
+
)
|
|
595
|
+
self.ingest = async_to_streamed_response_wrapper(
|
|
596
|
+
usage_events.ingest,
|
|
597
|
+
)
|
dodopayments/types/__init__.py
CHANGED
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
5
|
from .brand import Brand as Brand
|
|
6
|
+
from .event import Event as Event
|
|
7
|
+
from .meter import Meter as Meter
|
|
6
8
|
from .price import Price as Price
|
|
7
9
|
from .refund import Refund as Refund
|
|
8
10
|
from .dispute import Dispute as Dispute
|
|
@@ -15,6 +17,7 @@ from .get_dispute import GetDispute as GetDispute
|
|
|
15
17
|
from .license_key import LicenseKey as LicenseKey
|
|
16
18
|
from .price_param import PriceParam as PriceParam
|
|
17
19
|
from .country_code import CountryCode as CountryCode
|
|
20
|
+
from .meter_filter import MeterFilter as MeterFilter
|
|
18
21
|
from .subscription import Subscription as Subscription
|
|
19
22
|
from .tax_category import TaxCategory as TaxCategory
|
|
20
23
|
from .discount_type import DiscountType as DiscountType
|
|
@@ -27,8 +30,13 @@ from .dispute_status import DisputeStatus as DisputeStatus
|
|
|
27
30
|
from .billing_address import BillingAddress as BillingAddress
|
|
28
31
|
from .webhook_details import WebhookDetails as WebhookDetails
|
|
29
32
|
from .addon_list_params import AddonListParams as AddonListParams
|
|
33
|
+
from .event_input_param import EventInputParam as EventInputParam
|
|
34
|
+
from .meter_aggregation import MeterAggregation as MeterAggregation
|
|
35
|
+
from .meter_list_params import MeterListParams as MeterListParams
|
|
36
|
+
from .add_meter_to_price import AddMeterToPrice as AddMeterToPrice
|
|
30
37
|
from .attach_addon_param import AttachAddonParam as AttachAddonParam
|
|
31
38
|
from .license_key_status import LicenseKeyStatus as LicenseKeyStatus
|
|
39
|
+
from .meter_filter_param import MeterFilterParam as MeterFilterParam
|
|
32
40
|
from .new_customer_param import NewCustomerParam as NewCustomerParam
|
|
33
41
|
from .payout_list_params import PayoutListParams as PayoutListParams
|
|
34
42
|
from .refund_list_params import RefundListParams as RefundListParams
|
|
@@ -39,6 +47,7 @@ from .brand_create_params import BrandCreateParams as BrandCreateParams
|
|
|
39
47
|
from .brand_list_response import BrandListResponse as BrandListResponse
|
|
40
48
|
from .brand_update_params import BrandUpdateParams as BrandUpdateParams
|
|
41
49
|
from .dispute_list_params import DisputeListParams as DisputeListParams
|
|
50
|
+
from .meter_create_params import MeterCreateParams as MeterCreateParams
|
|
42
51
|
from .payment_list_params import PaymentListParams as PaymentListParams
|
|
43
52
|
from .product_list_params import ProductListParams as ProductListParams
|
|
44
53
|
from .subscription_status import SubscriptionStatus as SubscriptionStatus
|
|
@@ -68,7 +77,10 @@ from .customer_portal_session import CustomerPortalSession as CustomerPortalSess
|
|
|
68
77
|
from .license_activate_params import LicenseActivateParams as LicenseActivateParams
|
|
69
78
|
from .license_key_list_params import LicenseKeyListParams as LicenseKeyListParams
|
|
70
79
|
from .license_validate_params import LicenseValidateParams as LicenseValidateParams
|
|
80
|
+
from .meter_aggregation_param import MeterAggregationParam as MeterAggregationParam
|
|
71
81
|
from .payment_create_response import PaymentCreateResponse as PaymentCreateResponse
|
|
82
|
+
from .usage_event_list_params import UsageEventListParams as UsageEventListParams
|
|
83
|
+
from .add_meter_to_price_param import AddMeterToPriceParam as AddMeterToPriceParam
|
|
72
84
|
from .addon_cart_response_item import AddonCartResponseItem as AddonCartResponseItem
|
|
73
85
|
from .customer_limited_details import CustomerLimitedDetails as CustomerLimitedDetails
|
|
74
86
|
from .subscription_list_params import SubscriptionListParams as SubscriptionListParams
|
|
@@ -76,6 +88,7 @@ from .checkout_session_response import CheckoutSessionResponse as CheckoutSessio
|
|
|
76
88
|
from .license_deactivate_params import LicenseDeactivateParams as LicenseDeactivateParams
|
|
77
89
|
from .license_key_update_params import LicenseKeyUpdateParams as LicenseKeyUpdateParams
|
|
78
90
|
from .license_validate_response import LicenseValidateResponse as LicenseValidateResponse
|
|
91
|
+
from .usage_event_ingest_params import UsageEventIngestParams as UsageEventIngestParams
|
|
79
92
|
from .license_key_duration_param import LicenseKeyDurationParam as LicenseKeyDurationParam
|
|
80
93
|
from .one_time_product_cart_item import OneTimeProductCartItem as OneTimeProductCartItem
|
|
81
94
|
from .subscription_charge_params import SubscriptionChargeParams as SubscriptionChargeParams
|
|
@@ -83,6 +96,7 @@ from .subscription_create_params import SubscriptionCreateParams as Subscription
|
|
|
83
96
|
from .subscription_list_response import SubscriptionListResponse as SubscriptionListResponse
|
|
84
97
|
from .subscription_update_params import SubscriptionUpdateParams as SubscriptionUpdateParams
|
|
85
98
|
from .product_update_files_params import ProductUpdateFilesParams as ProductUpdateFilesParams
|
|
99
|
+
from .usage_event_ingest_response import UsageEventIngestResponse as UsageEventIngestResponse
|
|
86
100
|
from .addon_update_images_response import AddonUpdateImagesResponse as AddonUpdateImagesResponse
|
|
87
101
|
from .brand_update_images_response import BrandUpdateImagesResponse as BrandUpdateImagesResponse
|
|
88
102
|
from .on_demand_subscription_param import OnDemandSubscriptionParam as OnDemandSubscriptionParam
|
|
@@ -100,3 +114,9 @@ from .payment_retrieve_line_items_response import PaymentRetrieveLineItemsRespon
|
|
|
100
114
|
from .misc_list_supported_countries_response import (
|
|
101
115
|
MiscListSupportedCountriesResponse as MiscListSupportedCountriesResponse,
|
|
102
116
|
)
|
|
117
|
+
from .subscription_retrieve_usage_history_params import (
|
|
118
|
+
SubscriptionRetrieveUsageHistoryParams as SubscriptionRetrieveUsageHistoryParams,
|
|
119
|
+
)
|
|
120
|
+
from .subscription_retrieve_usage_history_response import (
|
|
121
|
+
SubscriptionRetrieveUsageHistoryResponse as SubscriptionRetrieveUsageHistoryResponse,
|
|
122
|
+
)
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
|
|
2
|
+
|
|
3
|
+
from typing import Optional
|
|
4
|
+
|
|
5
|
+
from .._models import BaseModel
|
|
6
|
+
|
|
7
|
+
__all__ = ["AddMeterToPrice"]
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class AddMeterToPrice(BaseModel):
|
|
11
|
+
meter_id: str
|
|
12
|
+
|
|
13
|
+
price_per_unit: str
|
|
14
|
+
"""The price per unit in lowest denomination.
|
|
15
|
+
|
|
16
|
+
Must be greater than zero. Supports up to 5 digits before decimal point and 12
|
|
17
|
+
decimal places.
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
description: Optional[str] = None
|
|
21
|
+
"""Meter description. Will ignored on Request, but will be shown in response"""
|
|
22
|
+
|
|
23
|
+
free_threshold: Optional[int] = None
|
|
24
|
+
|
|
25
|
+
measurement_unit: Optional[str] = None
|
|
26
|
+
"""Meter measurement unit. Will ignored on Request, but will be shown in response"""
|
|
27
|
+
|
|
28
|
+
name: Optional[str] = None
|
|
29
|
+
"""Meter name. Will ignored on Request, but will be shown in response"""
|