dub 0.34.1__py3-none-any.whl → 0.35.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.
- dub/_version.py +3 -3
- dub/basesdk.py +20 -6
- dub/models/components/__init__.py +108 -26
- dub/models/components/analyticsbrowsers.py +18 -1
- dub/models/components/analyticscities.py +18 -1
- dub/models/components/analyticscontinents.py +18 -1
- dub/models/components/analyticscount.py +18 -1
- dub/models/components/analyticscountries.py +20 -1
- dub/models/components/analyticsdevices.py +18 -1
- dub/models/components/analyticsos.py +18 -1
- dub/models/components/analyticsreferers.py +18 -1
- dub/models/components/analyticsrefererurls.py +18 -1
- dub/models/components/analyticsregions.py +18 -1
- dub/models/components/analyticstimeseries.py +18 -1
- dub/models/components/analyticstoplinks.py +16 -26
- dub/models/components/analyticstopurls.py +18 -1
- dub/models/components/analyticstriggers.py +18 -1
- dub/models/components/commissioncreatedevent.py +96 -64
- dub/models/components/domainschema.py +31 -50
- dub/models/components/folderschema.py +18 -19
- dub/models/components/leadcreatedevent.py +151 -134
- dub/models/components/linkclickedevent.py +57 -70
- dub/models/components/linkschema.py +63 -64
- dub/models/components/linkwebhookevent.py +43 -51
- dub/models/components/partneranalyticscount.py +18 -1
- dub/models/components/partneranalyticstimeseries.py +18 -1
- dub/models/components/partneranalyticstoplinks.py +16 -27
- dub/models/components/partnerapplicationsubmittedevent.py +42 -75
- dub/models/components/partnerenrolledevent.py +477 -83
- dub/models/components/salecreatedevent.py +152 -151
- dub/models/errors/badrequest.py +18 -1
- dub/models/errors/conflict.py +18 -1
- dub/models/errors/forbidden.py +18 -1
- dub/models/errors/internalservererror.py +18 -1
- dub/models/errors/inviteexpired.py +18 -1
- dub/models/errors/notfound.py +18 -1
- dub/models/errors/ratelimitexceeded.py +18 -1
- dub/models/errors/unauthorized.py +18 -1
- dub/models/errors/unprocessableentity.py +18 -1
- dub/models/operations/__init__.py +230 -19
- dub/models/operations/approvebountysubmission.py +71 -45
- dub/models/operations/banpartner.py +14 -19
- dub/models/operations/bulkcreatelinks.py +86 -87
- dub/models/operations/bulkupdatelinks.py +97 -82
- dub/models/operations/checkdomainstatus.py +1 -17
- dub/models/operations/createdomain.py +33 -34
- dub/models/operations/createfolder.py +18 -19
- dub/models/operations/createlink.py +86 -87
- dub/models/operations/createpartner.py +560 -168
- dub/models/operations/createpartnerlink.py +74 -85
- dub/models/operations/createreferralsembedtoken.py +99 -87
- dub/models/operations/createtag.py +18 -1
- dub/models/operations/deactivatepartner.py +65 -0
- dub/models/operations/getcustomer.py +106 -105
- dub/models/operations/getcustomers.py +123 -105
- dub/models/operations/getlinkinfo.py +18 -1
- dub/models/operations/getlinks.py +36 -1
- dub/models/operations/getlinkscount.py +32 -1
- dub/models/operations/getqrcode.py +29 -1
- dub/models/operations/gettags.py +20 -1
- dub/models/operations/listbountysubmissions.py +63 -26
- dub/models/operations/listcommissions.py +129 -64
- dub/models/operations/listdomains.py +18 -1
- dub/models/operations/listevents.py +414 -389
- dub/models/operations/listfolders.py +18 -1
- dub/models/operations/listpartners.py +510 -84
- dub/models/operations/registerdomain.py +1 -17
- dub/models/operations/rejectbountysubmission.py +71 -26
- dub/models/operations/retrieveanalytics.py +65 -66
- dub/models/operations/retrievelinks.py +30 -19
- dub/models/operations/retrievepartneranalytics.py +25 -28
- dub/models/operations/tracklead.py +38 -83
- dub/models/operations/tracksale.py +52 -95
- dub/models/operations/updatecommission.py +126 -64
- dub/models/operations/updatecustomer.py +122 -131
- dub/models/operations/updatedomain.py +50 -35
- dub/models/operations/updatefolder.py +34 -19
- dub/models/operations/updatelink.py +101 -86
- dub/models/operations/updatetag.py +34 -1
- dub/models/operations/upsertlink.py +86 -87
- dub/models/operations/upsertpartnerlink.py +72 -78
- dub/partners.py +288 -0
- dub/sdk.py +0 -3
- dub/utils/__init__.py +10 -1
- {dub-0.34.1.dist-info → dub-0.35.0.dist-info}/METADATA +4 -8
- dub-0.35.0.dist-info/RECORD +143 -0
- dub/models/components/workspaceschema.py +0 -328
- dub/models/operations/getworkspace.py +0 -21
- dub/models/operations/updateworkspace.py +0 -78
- dub/workspaces.py +0 -561
- dub-0.34.1.dist-info/RECORD +0 -146
- {dub-0.34.1.dist-info → dub-0.35.0.dist-info}/WHEEL +0 -0
- {dub-0.34.1.dist-info → dub-0.35.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -30,6 +30,22 @@ class GetCustomerRequest(BaseModel):
|
|
|
30
30
|
] = None
|
|
31
31
|
r"""Whether to include expanded fields on the customer (`link`, `partner`, `discount`)."""
|
|
32
32
|
|
|
33
|
+
@model_serializer(mode="wrap")
|
|
34
|
+
def serialize_model(self, handler):
|
|
35
|
+
optional_fields = set(["includeExpandedFields"])
|
|
36
|
+
serialized = handler(self)
|
|
37
|
+
m = {}
|
|
38
|
+
|
|
39
|
+
for n, f in type(self).model_fields.items():
|
|
40
|
+
k = f.alias or n
|
|
41
|
+
val = serialized.get(k)
|
|
42
|
+
|
|
43
|
+
if val != UNSET_SENTINEL:
|
|
44
|
+
if val is not None or k not in optional_fields:
|
|
45
|
+
m[k] = val
|
|
46
|
+
|
|
47
|
+
return m
|
|
48
|
+
|
|
33
49
|
|
|
34
50
|
class GetCustomerLinkTypedDict(TypedDict):
|
|
35
51
|
id: str
|
|
@@ -67,30 +83,14 @@ class GetCustomerLink(BaseModel):
|
|
|
67
83
|
|
|
68
84
|
@model_serializer(mode="wrap")
|
|
69
85
|
def serialize_model(self, handler):
|
|
70
|
-
optional_fields = []
|
|
71
|
-
nullable_fields = ["programId"]
|
|
72
|
-
null_default_fields = []
|
|
73
|
-
|
|
74
86
|
serialized = handler(self)
|
|
75
|
-
|
|
76
87
|
m = {}
|
|
77
88
|
|
|
78
89
|
for n, f in type(self).model_fields.items():
|
|
79
90
|
k = f.alias or n
|
|
80
91
|
val = serialized.get(k)
|
|
81
|
-
serialized.pop(k, None)
|
|
82
|
-
|
|
83
|
-
optional_nullable = k in optional_fields and k in nullable_fields
|
|
84
|
-
is_set = (
|
|
85
|
-
self.__pydantic_fields_set__.intersection({n})
|
|
86
|
-
or k in null_default_fields
|
|
87
|
-
) # pylint: disable=no-member
|
|
88
92
|
|
|
89
|
-
if val
|
|
90
|
-
m[k] = val
|
|
91
|
-
elif val != UNSET_SENTINEL and (
|
|
92
|
-
not k in optional_fields or (optional_nullable and is_set)
|
|
93
|
-
):
|
|
93
|
+
if val != UNSET_SENTINEL:
|
|
94
94
|
m[k] = val
|
|
95
95
|
|
|
96
96
|
return m
|
|
@@ -122,30 +122,14 @@ class GetCustomerPartner(BaseModel):
|
|
|
122
122
|
|
|
123
123
|
@model_serializer(mode="wrap")
|
|
124
124
|
def serialize_model(self, handler):
|
|
125
|
-
optional_fields = []
|
|
126
|
-
nullable_fields = ["email", "image"]
|
|
127
|
-
null_default_fields = []
|
|
128
|
-
|
|
129
125
|
serialized = handler(self)
|
|
130
|
-
|
|
131
126
|
m = {}
|
|
132
127
|
|
|
133
128
|
for n, f in type(self).model_fields.items():
|
|
134
129
|
k = f.alias or n
|
|
135
130
|
val = serialized.get(k)
|
|
136
|
-
serialized.pop(k, None)
|
|
137
131
|
|
|
138
|
-
|
|
139
|
-
is_set = (
|
|
140
|
-
self.__pydantic_fields_set__.intersection({n})
|
|
141
|
-
or k in null_default_fields
|
|
142
|
-
) # pylint: disable=no-member
|
|
143
|
-
|
|
144
|
-
if val is not None and val != UNSET_SENTINEL:
|
|
145
|
-
m[k] = val
|
|
146
|
-
elif val != UNSET_SENTINEL and (
|
|
147
|
-
not k in optional_fields or (optional_nullable and is_set)
|
|
148
|
-
):
|
|
132
|
+
if val != UNSET_SENTINEL:
|
|
149
133
|
m[k] = val
|
|
150
134
|
|
|
151
135
|
return m
|
|
@@ -188,37 +172,28 @@ class GetCustomerDiscount(BaseModel):
|
|
|
188
172
|
|
|
189
173
|
@model_serializer(mode="wrap")
|
|
190
174
|
def serialize_model(self, handler):
|
|
191
|
-
optional_fields = ["description", "partnersCount"]
|
|
192
|
-
nullable_fields =
|
|
193
|
-
"maxDuration",
|
|
194
|
-
|
|
195
|
-
"couponTestId",
|
|
196
|
-
"description",
|
|
197
|
-
"partnersCount",
|
|
198
|
-
]
|
|
199
|
-
null_default_fields = []
|
|
200
|
-
|
|
175
|
+
optional_fields = set(["description", "partnersCount"])
|
|
176
|
+
nullable_fields = set(
|
|
177
|
+
["maxDuration", "couponId", "couponTestId", "description", "partnersCount"]
|
|
178
|
+
)
|
|
201
179
|
serialized = handler(self)
|
|
202
|
-
|
|
203
180
|
m = {}
|
|
204
181
|
|
|
205
182
|
for n, f in type(self).model_fields.items():
|
|
206
183
|
k = f.alias or n
|
|
207
184
|
val = serialized.get(k)
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
):
|
|
221
|
-
m[k] = val
|
|
185
|
+
is_nullable_and_explicitly_set = (
|
|
186
|
+
k in nullable_fields
|
|
187
|
+
and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member
|
|
188
|
+
)
|
|
189
|
+
|
|
190
|
+
if val != UNSET_SENTINEL:
|
|
191
|
+
if (
|
|
192
|
+
val is not None
|
|
193
|
+
or k not in optional_fields
|
|
194
|
+
or is_nullable_and_explicitly_set
|
|
195
|
+
):
|
|
196
|
+
m[k] = val
|
|
222
197
|
|
|
223
198
|
return m
|
|
224
199
|
|
|
@@ -228,22 +203,28 @@ class GetCustomerResponseBodyTypedDict(TypedDict):
|
|
|
228
203
|
|
|
229
204
|
id: str
|
|
230
205
|
r"""The unique ID of the customer. You may use either the customer's `id` on Dub (obtained via `/customers` endpoint) or their `externalId` (unique ID within your system, prefixed with `ext_`, e.g. `ext_123`)."""
|
|
231
|
-
external_id: str
|
|
232
|
-
r"""Unique identifier for the customer in the client's app."""
|
|
233
206
|
name: str
|
|
234
207
|
r"""Name of the customer."""
|
|
208
|
+
external_id: str
|
|
209
|
+
r"""Unique identifier for the customer in the client's app."""
|
|
235
210
|
created_at: str
|
|
236
|
-
r"""The date the customer was created."""
|
|
211
|
+
r"""The date the customer was created (usually the signup date or trial start date)."""
|
|
237
212
|
email: NotRequired[Nullable[str]]
|
|
238
213
|
r"""Email of the customer."""
|
|
239
214
|
avatar: NotRequired[Nullable[str]]
|
|
240
215
|
r"""Avatar URL of the customer."""
|
|
216
|
+
stripe_customer_id: NotRequired[Nullable[str]]
|
|
217
|
+
r"""The customer's Stripe customer ID. This is useful for attributing recurring sale events to the partner who referred the customer."""
|
|
241
218
|
country: NotRequired[Nullable[str]]
|
|
242
219
|
r"""Country of the customer."""
|
|
243
220
|
sales: NotRequired[Nullable[float]]
|
|
244
221
|
r"""Total number of sales for the customer."""
|
|
245
222
|
sale_amount: NotRequired[Nullable[float]]
|
|
246
223
|
r"""Total amount of sales for the customer."""
|
|
224
|
+
first_sale_at: NotRequired[Nullable[str]]
|
|
225
|
+
r"""The date the customer made their first sale. Useful for calculating the time to first sale and LTV."""
|
|
226
|
+
subscription_canceled_at: NotRequired[Nullable[str]]
|
|
227
|
+
r"""The date the customer canceled their subscription. Useful for calculating LTV and churn rate."""
|
|
247
228
|
link: NotRequired[Nullable[GetCustomerLinkTypedDict]]
|
|
248
229
|
program_id: NotRequired[Nullable[str]]
|
|
249
230
|
partner: NotRequired[Nullable[GetCustomerPartnerTypedDict]]
|
|
@@ -256,14 +237,14 @@ class GetCustomerResponseBody(BaseModel):
|
|
|
256
237
|
id: str
|
|
257
238
|
r"""The unique ID of the customer. You may use either the customer's `id` on Dub (obtained via `/customers` endpoint) or their `externalId` (unique ID within your system, prefixed with `ext_`, e.g. `ext_123`)."""
|
|
258
239
|
|
|
259
|
-
external_id: Annotated[str, pydantic.Field(alias="externalId")]
|
|
260
|
-
r"""Unique identifier for the customer in the client's app."""
|
|
261
|
-
|
|
262
240
|
name: str
|
|
263
241
|
r"""Name of the customer."""
|
|
264
242
|
|
|
243
|
+
external_id: Annotated[str, pydantic.Field(alias="externalId")]
|
|
244
|
+
r"""Unique identifier for the customer in the client's app."""
|
|
245
|
+
|
|
265
246
|
created_at: Annotated[str, pydantic.Field(alias="createdAt")]
|
|
266
|
-
r"""The date the customer was created."""
|
|
247
|
+
r"""The date the customer was created (usually the signup date or trial start date)."""
|
|
267
248
|
|
|
268
249
|
email: OptionalNullable[str] = UNSET
|
|
269
250
|
r"""Email of the customer."""
|
|
@@ -271,6 +252,11 @@ class GetCustomerResponseBody(BaseModel):
|
|
|
271
252
|
avatar: OptionalNullable[str] = UNSET
|
|
272
253
|
r"""Avatar URL of the customer."""
|
|
273
254
|
|
|
255
|
+
stripe_customer_id: Annotated[
|
|
256
|
+
OptionalNullable[str], pydantic.Field(alias="stripeCustomerId")
|
|
257
|
+
] = UNSET
|
|
258
|
+
r"""The customer's Stripe customer ID. This is useful for attributing recurring sale events to the partner who referred the customer."""
|
|
259
|
+
|
|
274
260
|
country: OptionalNullable[str] = UNSET
|
|
275
261
|
r"""Country of the customer."""
|
|
276
262
|
|
|
@@ -282,6 +268,16 @@ class GetCustomerResponseBody(BaseModel):
|
|
|
282
268
|
] = UNSET
|
|
283
269
|
r"""Total amount of sales for the customer."""
|
|
284
270
|
|
|
271
|
+
first_sale_at: Annotated[
|
|
272
|
+
OptionalNullable[str], pydantic.Field(alias="firstSaleAt")
|
|
273
|
+
] = UNSET
|
|
274
|
+
r"""The date the customer made their first sale. Useful for calculating the time to first sale and LTV."""
|
|
275
|
+
|
|
276
|
+
subscription_canceled_at: Annotated[
|
|
277
|
+
OptionalNullable[str], pydantic.Field(alias="subscriptionCanceledAt")
|
|
278
|
+
] = UNSET
|
|
279
|
+
r"""The date the customer canceled their subscription. Useful for calculating LTV and churn rate."""
|
|
280
|
+
|
|
285
281
|
link: OptionalNullable[GetCustomerLink] = UNSET
|
|
286
282
|
|
|
287
283
|
program_id: Annotated[OptionalNullable[str], pydantic.Field(alias="programId")] = (
|
|
@@ -294,50 +290,55 @@ class GetCustomerResponseBody(BaseModel):
|
|
|
294
290
|
|
|
295
291
|
@model_serializer(mode="wrap")
|
|
296
292
|
def serialize_model(self, handler):
|
|
297
|
-
optional_fields =
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
293
|
+
optional_fields = set(
|
|
294
|
+
[
|
|
295
|
+
"email",
|
|
296
|
+
"avatar",
|
|
297
|
+
"stripeCustomerId",
|
|
298
|
+
"country",
|
|
299
|
+
"sales",
|
|
300
|
+
"saleAmount",
|
|
301
|
+
"firstSaleAt",
|
|
302
|
+
"subscriptionCanceledAt",
|
|
303
|
+
"link",
|
|
304
|
+
"programId",
|
|
305
|
+
"partner",
|
|
306
|
+
"discount",
|
|
307
|
+
]
|
|
308
|
+
)
|
|
309
|
+
nullable_fields = set(
|
|
310
|
+
[
|
|
311
|
+
"email",
|
|
312
|
+
"avatar",
|
|
313
|
+
"stripeCustomerId",
|
|
314
|
+
"country",
|
|
315
|
+
"sales",
|
|
316
|
+
"saleAmount",
|
|
317
|
+
"firstSaleAt",
|
|
318
|
+
"subscriptionCanceledAt",
|
|
319
|
+
"link",
|
|
320
|
+
"programId",
|
|
321
|
+
"partner",
|
|
322
|
+
"discount",
|
|
323
|
+
]
|
|
324
|
+
)
|
|
321
325
|
serialized = handler(self)
|
|
322
|
-
|
|
323
326
|
m = {}
|
|
324
327
|
|
|
325
328
|
for n, f in type(self).model_fields.items():
|
|
326
329
|
k = f.alias or n
|
|
327
330
|
val = serialized.get(k)
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
):
|
|
341
|
-
m[k] = val
|
|
331
|
+
is_nullable_and_explicitly_set = (
|
|
332
|
+
k in nullable_fields
|
|
333
|
+
and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member
|
|
334
|
+
)
|
|
335
|
+
|
|
336
|
+
if val != UNSET_SENTINEL:
|
|
337
|
+
if (
|
|
338
|
+
val is not None
|
|
339
|
+
or k not in optional_fields
|
|
340
|
+
or is_nullable_and_explicitly_set
|
|
341
|
+
):
|
|
342
|
+
m[k] = val
|
|
342
343
|
|
|
343
344
|
return m
|
|
@@ -15,6 +15,8 @@ class GetCustomersQueryParamSortBy(str, Enum):
|
|
|
15
15
|
|
|
16
16
|
CREATED_AT = "createdAt"
|
|
17
17
|
SALE_AMOUNT = "saleAmount"
|
|
18
|
+
FIRST_SALE_AT = "firstSaleAt"
|
|
19
|
+
SUBSCRIPTION_CANCELED_AT = "subscriptionCanceledAt"
|
|
18
20
|
|
|
19
21
|
|
|
20
22
|
class GetCustomersQueryParamSortOrder(str, Enum):
|
|
@@ -132,6 +134,37 @@ class GetCustomersRequest(BaseModel):
|
|
|
132
134
|
] = 100
|
|
133
135
|
r"""The number of items per page."""
|
|
134
136
|
|
|
137
|
+
@model_serializer(mode="wrap")
|
|
138
|
+
def serialize_model(self, handler):
|
|
139
|
+
optional_fields = set(
|
|
140
|
+
[
|
|
141
|
+
"email",
|
|
142
|
+
"externalId",
|
|
143
|
+
"search",
|
|
144
|
+
"country",
|
|
145
|
+
"linkId",
|
|
146
|
+
"programId",
|
|
147
|
+
"partnerId",
|
|
148
|
+
"includeExpandedFields",
|
|
149
|
+
"sortBy",
|
|
150
|
+
"sortOrder",
|
|
151
|
+
"page",
|
|
152
|
+
"pageSize",
|
|
153
|
+
]
|
|
154
|
+
)
|
|
155
|
+
serialized = handler(self)
|
|
156
|
+
m = {}
|
|
157
|
+
|
|
158
|
+
for n, f in type(self).model_fields.items():
|
|
159
|
+
k = f.alias or n
|
|
160
|
+
val = serialized.get(k)
|
|
161
|
+
|
|
162
|
+
if val != UNSET_SENTINEL:
|
|
163
|
+
if val is not None or k not in optional_fields:
|
|
164
|
+
m[k] = val
|
|
165
|
+
|
|
166
|
+
return m
|
|
167
|
+
|
|
135
168
|
|
|
136
169
|
class GetCustomersLinkTypedDict(TypedDict):
|
|
137
170
|
id: str
|
|
@@ -169,30 +202,14 @@ class GetCustomersLink(BaseModel):
|
|
|
169
202
|
|
|
170
203
|
@model_serializer(mode="wrap")
|
|
171
204
|
def serialize_model(self, handler):
|
|
172
|
-
optional_fields = []
|
|
173
|
-
nullable_fields = ["programId"]
|
|
174
|
-
null_default_fields = []
|
|
175
|
-
|
|
176
205
|
serialized = handler(self)
|
|
177
|
-
|
|
178
206
|
m = {}
|
|
179
207
|
|
|
180
208
|
for n, f in type(self).model_fields.items():
|
|
181
209
|
k = f.alias or n
|
|
182
210
|
val = serialized.get(k)
|
|
183
|
-
serialized.pop(k, None)
|
|
184
|
-
|
|
185
|
-
optional_nullable = k in optional_fields and k in nullable_fields
|
|
186
|
-
is_set = (
|
|
187
|
-
self.__pydantic_fields_set__.intersection({n})
|
|
188
|
-
or k in null_default_fields
|
|
189
|
-
) # pylint: disable=no-member
|
|
190
211
|
|
|
191
|
-
if val
|
|
192
|
-
m[k] = val
|
|
193
|
-
elif val != UNSET_SENTINEL and (
|
|
194
|
-
not k in optional_fields or (optional_nullable and is_set)
|
|
195
|
-
):
|
|
212
|
+
if val != UNSET_SENTINEL:
|
|
196
213
|
m[k] = val
|
|
197
214
|
|
|
198
215
|
return m
|
|
@@ -224,30 +241,14 @@ class GetCustomersPartner(BaseModel):
|
|
|
224
241
|
|
|
225
242
|
@model_serializer(mode="wrap")
|
|
226
243
|
def serialize_model(self, handler):
|
|
227
|
-
optional_fields = []
|
|
228
|
-
nullable_fields = ["email", "image"]
|
|
229
|
-
null_default_fields = []
|
|
230
|
-
|
|
231
244
|
serialized = handler(self)
|
|
232
|
-
|
|
233
245
|
m = {}
|
|
234
246
|
|
|
235
247
|
for n, f in type(self).model_fields.items():
|
|
236
248
|
k = f.alias or n
|
|
237
249
|
val = serialized.get(k)
|
|
238
|
-
serialized.pop(k, None)
|
|
239
250
|
|
|
240
|
-
|
|
241
|
-
is_set = (
|
|
242
|
-
self.__pydantic_fields_set__.intersection({n})
|
|
243
|
-
or k in null_default_fields
|
|
244
|
-
) # pylint: disable=no-member
|
|
245
|
-
|
|
246
|
-
if val is not None and val != UNSET_SENTINEL:
|
|
247
|
-
m[k] = val
|
|
248
|
-
elif val != UNSET_SENTINEL and (
|
|
249
|
-
not k in optional_fields or (optional_nullable and is_set)
|
|
250
|
-
):
|
|
251
|
+
if val != UNSET_SENTINEL:
|
|
251
252
|
m[k] = val
|
|
252
253
|
|
|
253
254
|
return m
|
|
@@ -290,37 +291,28 @@ class Discount(BaseModel):
|
|
|
290
291
|
|
|
291
292
|
@model_serializer(mode="wrap")
|
|
292
293
|
def serialize_model(self, handler):
|
|
293
|
-
optional_fields = ["description", "partnersCount"]
|
|
294
|
-
nullable_fields =
|
|
295
|
-
"maxDuration",
|
|
296
|
-
|
|
297
|
-
"couponTestId",
|
|
298
|
-
"description",
|
|
299
|
-
"partnersCount",
|
|
300
|
-
]
|
|
301
|
-
null_default_fields = []
|
|
302
|
-
|
|
294
|
+
optional_fields = set(["description", "partnersCount"])
|
|
295
|
+
nullable_fields = set(
|
|
296
|
+
["maxDuration", "couponId", "couponTestId", "description", "partnersCount"]
|
|
297
|
+
)
|
|
303
298
|
serialized = handler(self)
|
|
304
|
-
|
|
305
299
|
m = {}
|
|
306
300
|
|
|
307
301
|
for n, f in type(self).model_fields.items():
|
|
308
302
|
k = f.alias or n
|
|
309
303
|
val = serialized.get(k)
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
):
|
|
323
|
-
m[k] = val
|
|
304
|
+
is_nullable_and_explicitly_set = (
|
|
305
|
+
k in nullable_fields
|
|
306
|
+
and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member
|
|
307
|
+
)
|
|
308
|
+
|
|
309
|
+
if val != UNSET_SENTINEL:
|
|
310
|
+
if (
|
|
311
|
+
val is not None
|
|
312
|
+
or k not in optional_fields
|
|
313
|
+
or is_nullable_and_explicitly_set
|
|
314
|
+
):
|
|
315
|
+
m[k] = val
|
|
324
316
|
|
|
325
317
|
return m
|
|
326
318
|
|
|
@@ -328,22 +320,28 @@ class Discount(BaseModel):
|
|
|
328
320
|
class GetCustomersResponseBodyTypedDict(TypedDict):
|
|
329
321
|
id: str
|
|
330
322
|
r"""The unique ID of the customer. You may use either the customer's `id` on Dub (obtained via `/customers` endpoint) or their `externalId` (unique ID within your system, prefixed with `ext_`, e.g. `ext_123`)."""
|
|
331
|
-
external_id: str
|
|
332
|
-
r"""Unique identifier for the customer in the client's app."""
|
|
333
323
|
name: str
|
|
334
324
|
r"""Name of the customer."""
|
|
325
|
+
external_id: str
|
|
326
|
+
r"""Unique identifier for the customer in the client's app."""
|
|
335
327
|
created_at: str
|
|
336
|
-
r"""The date the customer was created."""
|
|
328
|
+
r"""The date the customer was created (usually the signup date or trial start date)."""
|
|
337
329
|
email: NotRequired[Nullable[str]]
|
|
338
330
|
r"""Email of the customer."""
|
|
339
331
|
avatar: NotRequired[Nullable[str]]
|
|
340
332
|
r"""Avatar URL of the customer."""
|
|
333
|
+
stripe_customer_id: NotRequired[Nullable[str]]
|
|
334
|
+
r"""The customer's Stripe customer ID. This is useful for attributing recurring sale events to the partner who referred the customer."""
|
|
341
335
|
country: NotRequired[Nullable[str]]
|
|
342
336
|
r"""Country of the customer."""
|
|
343
337
|
sales: NotRequired[Nullable[float]]
|
|
344
338
|
r"""Total number of sales for the customer."""
|
|
345
339
|
sale_amount: NotRequired[Nullable[float]]
|
|
346
340
|
r"""Total amount of sales for the customer."""
|
|
341
|
+
first_sale_at: NotRequired[Nullable[str]]
|
|
342
|
+
r"""The date the customer made their first sale. Useful for calculating the time to first sale and LTV."""
|
|
343
|
+
subscription_canceled_at: NotRequired[Nullable[str]]
|
|
344
|
+
r"""The date the customer canceled their subscription. Useful for calculating LTV and churn rate."""
|
|
347
345
|
link: NotRequired[Nullable[GetCustomersLinkTypedDict]]
|
|
348
346
|
program_id: NotRequired[Nullable[str]]
|
|
349
347
|
partner: NotRequired[Nullable[GetCustomersPartnerTypedDict]]
|
|
@@ -354,14 +352,14 @@ class GetCustomersResponseBody(BaseModel):
|
|
|
354
352
|
id: str
|
|
355
353
|
r"""The unique ID of the customer. You may use either the customer's `id` on Dub (obtained via `/customers` endpoint) or their `externalId` (unique ID within your system, prefixed with `ext_`, e.g. `ext_123`)."""
|
|
356
354
|
|
|
357
|
-
external_id: Annotated[str, pydantic.Field(alias="externalId")]
|
|
358
|
-
r"""Unique identifier for the customer in the client's app."""
|
|
359
|
-
|
|
360
355
|
name: str
|
|
361
356
|
r"""Name of the customer."""
|
|
362
357
|
|
|
358
|
+
external_id: Annotated[str, pydantic.Field(alias="externalId")]
|
|
359
|
+
r"""Unique identifier for the customer in the client's app."""
|
|
360
|
+
|
|
363
361
|
created_at: Annotated[str, pydantic.Field(alias="createdAt")]
|
|
364
|
-
r"""The date the customer was created."""
|
|
362
|
+
r"""The date the customer was created (usually the signup date or trial start date)."""
|
|
365
363
|
|
|
366
364
|
email: OptionalNullable[str] = UNSET
|
|
367
365
|
r"""Email of the customer."""
|
|
@@ -369,6 +367,11 @@ class GetCustomersResponseBody(BaseModel):
|
|
|
369
367
|
avatar: OptionalNullable[str] = UNSET
|
|
370
368
|
r"""Avatar URL of the customer."""
|
|
371
369
|
|
|
370
|
+
stripe_customer_id: Annotated[
|
|
371
|
+
OptionalNullable[str], pydantic.Field(alias="stripeCustomerId")
|
|
372
|
+
] = UNSET
|
|
373
|
+
r"""The customer's Stripe customer ID. This is useful for attributing recurring sale events to the partner who referred the customer."""
|
|
374
|
+
|
|
372
375
|
country: OptionalNullable[str] = UNSET
|
|
373
376
|
r"""Country of the customer."""
|
|
374
377
|
|
|
@@ -380,6 +383,16 @@ class GetCustomersResponseBody(BaseModel):
|
|
|
380
383
|
] = UNSET
|
|
381
384
|
r"""Total amount of sales for the customer."""
|
|
382
385
|
|
|
386
|
+
first_sale_at: Annotated[
|
|
387
|
+
OptionalNullable[str], pydantic.Field(alias="firstSaleAt")
|
|
388
|
+
] = UNSET
|
|
389
|
+
r"""The date the customer made their first sale. Useful for calculating the time to first sale and LTV."""
|
|
390
|
+
|
|
391
|
+
subscription_canceled_at: Annotated[
|
|
392
|
+
OptionalNullable[str], pydantic.Field(alias="subscriptionCanceledAt")
|
|
393
|
+
] = UNSET
|
|
394
|
+
r"""The date the customer canceled their subscription. Useful for calculating LTV and churn rate."""
|
|
395
|
+
|
|
383
396
|
link: OptionalNullable[GetCustomersLink] = UNSET
|
|
384
397
|
|
|
385
398
|
program_id: Annotated[OptionalNullable[str], pydantic.Field(alias="programId")] = (
|
|
@@ -392,50 +405,55 @@ class GetCustomersResponseBody(BaseModel):
|
|
|
392
405
|
|
|
393
406
|
@model_serializer(mode="wrap")
|
|
394
407
|
def serialize_model(self, handler):
|
|
395
|
-
optional_fields =
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
408
|
+
optional_fields = set(
|
|
409
|
+
[
|
|
410
|
+
"email",
|
|
411
|
+
"avatar",
|
|
412
|
+
"stripeCustomerId",
|
|
413
|
+
"country",
|
|
414
|
+
"sales",
|
|
415
|
+
"saleAmount",
|
|
416
|
+
"firstSaleAt",
|
|
417
|
+
"subscriptionCanceledAt",
|
|
418
|
+
"link",
|
|
419
|
+
"programId",
|
|
420
|
+
"partner",
|
|
421
|
+
"discount",
|
|
422
|
+
]
|
|
423
|
+
)
|
|
424
|
+
nullable_fields = set(
|
|
425
|
+
[
|
|
426
|
+
"email",
|
|
427
|
+
"avatar",
|
|
428
|
+
"stripeCustomerId",
|
|
429
|
+
"country",
|
|
430
|
+
"sales",
|
|
431
|
+
"saleAmount",
|
|
432
|
+
"firstSaleAt",
|
|
433
|
+
"subscriptionCanceledAt",
|
|
434
|
+
"link",
|
|
435
|
+
"programId",
|
|
436
|
+
"partner",
|
|
437
|
+
"discount",
|
|
438
|
+
]
|
|
439
|
+
)
|
|
419
440
|
serialized = handler(self)
|
|
420
|
-
|
|
421
441
|
m = {}
|
|
422
442
|
|
|
423
443
|
for n, f in type(self).model_fields.items():
|
|
424
444
|
k = f.alias or n
|
|
425
445
|
val = serialized.get(k)
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
):
|
|
439
|
-
m[k] = val
|
|
446
|
+
is_nullable_and_explicitly_set = (
|
|
447
|
+
k in nullable_fields
|
|
448
|
+
and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member
|
|
449
|
+
)
|
|
450
|
+
|
|
451
|
+
if val != UNSET_SENTINEL:
|
|
452
|
+
if (
|
|
453
|
+
val is not None
|
|
454
|
+
or k not in optional_fields
|
|
455
|
+
or is_nullable_and_explicitly_set
|
|
456
|
+
):
|
|
457
|
+
m[k] = val
|
|
440
458
|
|
|
441
459
|
return m
|