dub 0.31.0__py3-none-any.whl → 0.33.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/analytics.py +6 -6
- dub/commissions.py +12 -12
- dub/customers.py +24 -321
- dub/domains.py +34 -38
- dub/embed_tokens.py +6 -6
- dub/events.py +6 -6
- dub/folders.py +24 -28
- dub/links.py +58 -74
- dub/models/components/__init__.py +38 -6
- dub/models/components/analyticstopurls.py +2 -2
- dub/models/components/clickevent.py +10 -9
- dub/models/components/commissioncreatedevent.py +5 -2
- dub/models/components/folderschema.py +6 -1
- dub/models/components/leadcreatedevent.py +15 -11
- dub/models/components/leadevent.py +10 -9
- dub/models/components/linkclickedevent.py +10 -9
- dub/models/components/linkschema.py +9 -3
- dub/models/components/{tagschema.py → linktagschema.py} +2 -2
- dub/models/components/linkwebhookevent.py +10 -9
- dub/models/components/partnerapplicationsubmittedevent.py +269 -0
- dub/models/components/partnerenrolledevent.py +93 -29
- dub/models/components/salecreatedevent.py +15 -11
- dub/models/components/saleevent.py +10 -9
- dub/models/components/webhookevent.py +6 -0
- dub/models/components/workspaceschema.py +11 -0
- dub/models/errors/badrequest.py +1 -1
- dub/models/errors/conflict.py +1 -1
- dub/models/errors/duberror.py +1 -1
- dub/models/errors/forbidden.py +1 -1
- dub/models/errors/internalservererror.py +1 -1
- dub/models/errors/inviteexpired.py +1 -1
- dub/models/errors/no_response_error.py +1 -1
- dub/models/errors/notfound.py +1 -1
- dub/models/errors/ratelimitexceeded.py +1 -1
- dub/models/errors/responsevalidationerror.py +1 -1
- dub/models/errors/sdkerror.py +1 -1
- dub/models/errors/unauthorized.py +1 -1
- dub/models/errors/unprocessableentity.py +1 -1
- dub/models/operations/__init__.py +17 -35
- dub/models/operations/banpartner.py +83 -0
- dub/models/operations/bulkcreatelinks.py +2 -2
- dub/models/operations/createfolder.py +8 -3
- dub/models/operations/createlink.py +2 -2
- dub/models/operations/createpartner.py +93 -29
- dub/models/operations/listcommissions.py +13 -2
- dub/models/operations/listevents.py +10 -0
- dub/models/operations/listpartners.py +107 -47
- dub/models/operations/retrieveanalytics.py +16 -1
- dub/models/operations/retrievelinks.py +42 -7
- dub/models/operations/retrievepartneranalytics.py +51 -11
- dub/models/operations/tracklead.py +2 -2
- dub/models/operations/updatecommission.py +7 -2
- dub/models/operations/updatefolder.py +8 -3
- dub/models/operations/updatelink.py +2 -2
- dub/models/operations/upsertlink.py +2 -2
- dub/partners.py +310 -36
- dub/qr_codes.py +4 -4
- dub/tags.py +24 -32
- dub/track.py +12 -20
- dub/utils/retries.py +69 -5
- dub/utils/unmarshal_json_response.py +15 -1
- dub/workspaces.py +12 -20
- {dub-0.31.0.dist-info → dub-0.33.0.dist-info}/METADATA +2 -21
- {dub-0.31.0.dist-info → dub-0.33.0.dist-info}/RECORD +67 -66
- dub/models/operations/createcustomer.py +0 -382
- {dub-0.31.0.dist-info → dub-0.33.0.dist-info}/WHEEL +0 -0
- {dub-0.31.0.dist-info → dub-0.33.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -83,6 +83,7 @@ class ListCommissionsRequestTypedDict(TypedDict):
|
|
|
83
83
|
r"""The start date of the date range to filter the commissions by."""
|
|
84
84
|
end: NotRequired[str]
|
|
85
85
|
r"""The end date of the date range to filter the commissions by."""
|
|
86
|
+
timezone: NotRequired[str]
|
|
86
87
|
page: NotRequired[float]
|
|
87
88
|
r"""The page number for pagination."""
|
|
88
89
|
page_size: NotRequired[float]
|
|
@@ -175,6 +176,11 @@ class ListCommissionsRequest(BaseModel):
|
|
|
175
176
|
] = None
|
|
176
177
|
r"""The end date of the date range to filter the commissions by."""
|
|
177
178
|
|
|
179
|
+
timezone: Annotated[
|
|
180
|
+
Optional[str],
|
|
181
|
+
FieldMetadata(query=QueryParamMetadata(style="form", explode=True)),
|
|
182
|
+
] = None
|
|
183
|
+
|
|
178
184
|
page: Annotated[
|
|
179
185
|
Optional[float],
|
|
180
186
|
FieldMetadata(query=QueryParamMetadata(style="form", explode=True)),
|
|
@@ -219,6 +225,8 @@ class ListCommissionsPartnerTypedDict(TypedDict):
|
|
|
219
225
|
r"""The date when the partner enabled payouts."""
|
|
220
226
|
country: Nullable[str]
|
|
221
227
|
r"""The partner's country (required for tax purposes)."""
|
|
228
|
+
group_id: NotRequired[Nullable[str]]
|
|
229
|
+
r"""The partner's group ID on Dub."""
|
|
222
230
|
|
|
223
231
|
|
|
224
232
|
class ListCommissionsPartner(BaseModel):
|
|
@@ -242,10 +250,13 @@ class ListCommissionsPartner(BaseModel):
|
|
|
242
250
|
country: Nullable[str]
|
|
243
251
|
r"""The partner's country (required for tax purposes)."""
|
|
244
252
|
|
|
253
|
+
group_id: Annotated[OptionalNullable[str], pydantic.Field(alias="groupId")] = UNSET
|
|
254
|
+
r"""The partner's group ID on Dub."""
|
|
255
|
+
|
|
245
256
|
@model_serializer(mode="wrap")
|
|
246
257
|
def serialize_model(self, handler):
|
|
247
|
-
optional_fields = []
|
|
248
|
-
nullable_fields = ["email", "image", "payoutsEnabledAt", "country"]
|
|
258
|
+
optional_fields = ["groupId"]
|
|
259
|
+
nullable_fields = ["email", "image", "payoutsEnabledAt", "country", "groupId"]
|
|
249
260
|
null_default_fields = []
|
|
250
261
|
|
|
251
262
|
serialized = handler(self)
|
|
@@ -148,6 +148,8 @@ class ListEventsRequestTypedDict(TypedDict):
|
|
|
148
148
|
r"""The tag IDs to retrieve analytics for."""
|
|
149
149
|
folder_id: NotRequired[str]
|
|
150
150
|
r"""The folder ID to retrieve analytics for. If not provided, return analytics for unsorted links."""
|
|
151
|
+
group_id: NotRequired[str]
|
|
152
|
+
r"""The group ID to retrieve analytics for."""
|
|
151
153
|
root: NotRequired[bool]
|
|
152
154
|
r"""Filter for root domains. If true, filter for domains only. If false, filter for links only. If undefined, return both."""
|
|
153
155
|
sale_type: NotRequired[QueryParamSaleType]
|
|
@@ -346,6 +348,13 @@ class ListEventsRequest(BaseModel):
|
|
|
346
348
|
] = None
|
|
347
349
|
r"""The folder ID to retrieve analytics for. If not provided, return analytics for unsorted links."""
|
|
348
350
|
|
|
351
|
+
group_id: Annotated[
|
|
352
|
+
Optional[str],
|
|
353
|
+
pydantic.Field(alias="groupId"),
|
|
354
|
+
FieldMetadata(query=QueryParamMetadata(style="form", explode=True)),
|
|
355
|
+
] = None
|
|
356
|
+
r"""The group ID to retrieve analytics for."""
|
|
357
|
+
|
|
349
358
|
root: Annotated[
|
|
350
359
|
Optional[bool],
|
|
351
360
|
FieldMetadata(query=QueryParamMetadata(style="form", explode=True)),
|
|
@@ -473,6 +482,7 @@ class ListEventsRequest(BaseModel):
|
|
|
473
482
|
"url",
|
|
474
483
|
"tagIds",
|
|
475
484
|
"folderId",
|
|
485
|
+
"groupId",
|
|
476
486
|
"root",
|
|
477
487
|
"saleType",
|
|
478
488
|
"query",
|
|
@@ -24,16 +24,21 @@ class ListPartnersQueryParamStatus(str, Enum):
|
|
|
24
24
|
|
|
25
25
|
|
|
26
26
|
class ListPartnersQueryParamSortBy(str, Enum):
|
|
27
|
-
r"""The field to sort the partners by. The default is `
|
|
27
|
+
r"""The field to sort the partners by. The default is `totalSaleAmount`."""
|
|
28
28
|
|
|
29
29
|
CREATED_AT = "createdAt"
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
SALE_AMOUNT = "saleAmount"
|
|
30
|
+
TOTAL_CLICKS = "totalClicks"
|
|
31
|
+
TOTAL_LEADS = "totalLeads"
|
|
32
|
+
TOTAL_CONVERSIONS = "totalConversions"
|
|
33
|
+
TOTAL_SALE_AMOUNT = "totalSaleAmount"
|
|
35
34
|
TOTAL_COMMISSIONS = "totalCommissions"
|
|
36
35
|
NET_REVENUE = "netRevenue"
|
|
36
|
+
EARNINGS_PER_CLICK = "earningsPerClick"
|
|
37
|
+
AVERAGE_LIFETIME_VALUE = "averageLifetimeValue"
|
|
38
|
+
CLICK_TO_LEAD_RATE = "clickToLeadRate"
|
|
39
|
+
CLICK_TO_CONVERSION_RATE = "clickToConversionRate"
|
|
40
|
+
LEAD_TO_CONVERSION_RATE = "leadToConversionRate"
|
|
41
|
+
RETURN_ON_AD_SPEND = "returnOnAdSpend"
|
|
37
42
|
|
|
38
43
|
|
|
39
44
|
class ListPartnersQueryParamSortOrder(str, Enum):
|
|
@@ -49,7 +54,7 @@ class ListPartnersRequestTypedDict(TypedDict):
|
|
|
49
54
|
country: NotRequired[str]
|
|
50
55
|
r"""A filter on the list based on the partner's `country` field."""
|
|
51
56
|
sort_by: NotRequired[ListPartnersQueryParamSortBy]
|
|
52
|
-
r"""The field to sort the partners by. The default is `
|
|
57
|
+
r"""The field to sort the partners by. The default is `totalSaleAmount`."""
|
|
53
58
|
sort_order: NotRequired[ListPartnersQueryParamSortOrder]
|
|
54
59
|
r"""The sort order. The default is `desc`."""
|
|
55
60
|
email: NotRequired[str]
|
|
@@ -58,8 +63,6 @@ class ListPartnersRequestTypedDict(TypedDict):
|
|
|
58
63
|
r"""Filter the partner list based on the partner's `tenantId`. The value must be a string. Takes precedence over `email` and `search`."""
|
|
59
64
|
search: NotRequired[str]
|
|
60
65
|
r"""A search query to filter partners by ID, name, email, or link."""
|
|
61
|
-
include_expanded_fields: NotRequired[bool]
|
|
62
|
-
r"""Whether to include stats fields on the partner (`clicks`, `leads`, `conversions`, `sales`, `saleAmount`, `commissions`, `netRevenue`). If false, those fields will be returned as 0."""
|
|
63
66
|
page: NotRequired[float]
|
|
64
67
|
r"""The page number for pagination."""
|
|
65
68
|
page_size: NotRequired[float]
|
|
@@ -83,8 +86,8 @@ class ListPartnersRequest(BaseModel):
|
|
|
83
86
|
Optional[ListPartnersQueryParamSortBy],
|
|
84
87
|
pydantic.Field(alias="sortBy"),
|
|
85
88
|
FieldMetadata(query=QueryParamMetadata(style="form", explode=True)),
|
|
86
|
-
] = ListPartnersQueryParamSortBy.
|
|
87
|
-
r"""The field to sort the partners by. The default is `
|
|
89
|
+
] = ListPartnersQueryParamSortBy.TOTAL_SALE_AMOUNT
|
|
90
|
+
r"""The field to sort the partners by. The default is `totalSaleAmount`."""
|
|
88
91
|
|
|
89
92
|
sort_order: Annotated[
|
|
90
93
|
Optional[ListPartnersQueryParamSortOrder],
|
|
@@ -112,13 +115,6 @@ class ListPartnersRequest(BaseModel):
|
|
|
112
115
|
] = None
|
|
113
116
|
r"""A search query to filter partners by ID, name, email, or link."""
|
|
114
117
|
|
|
115
|
-
include_expanded_fields: Annotated[
|
|
116
|
-
Optional[bool],
|
|
117
|
-
pydantic.Field(alias="includeExpandedFields"),
|
|
118
|
-
FieldMetadata(query=QueryParamMetadata(style="form", explode=True)),
|
|
119
|
-
] = None
|
|
120
|
-
r"""Whether to include stats fields on the partner (`clicks`, `leads`, `conversions`, `sales`, `saleAmount`, `commissions`, `netRevenue`). If false, those fields will be returned as 0."""
|
|
121
|
-
|
|
122
118
|
page: Annotated[
|
|
123
119
|
Optional[float],
|
|
124
120
|
FieldMetadata(query=QueryParamMetadata(style="form", explode=True)),
|
|
@@ -231,6 +227,8 @@ class ListPartnersResponseBodyTypedDict(TypedDict):
|
|
|
231
227
|
r"""The partner's Stripe Connect ID (for receiving payouts via Stripe)."""
|
|
232
228
|
payouts_enabled_at: Nullable[str]
|
|
233
229
|
r"""The date when the partner enabled payouts."""
|
|
230
|
+
trusted_at: Nullable[str]
|
|
231
|
+
r"""The date when the partner received the trusted badge in the partner network."""
|
|
234
232
|
program_id: str
|
|
235
233
|
r"""The program's unique ID on Dub."""
|
|
236
234
|
partner_id: str
|
|
@@ -247,7 +245,7 @@ class ListPartnersResponseBodyTypedDict(TypedDict):
|
|
|
247
245
|
group_id: NotRequired[Nullable[str]]
|
|
248
246
|
r"""The partner's group ID on Dub."""
|
|
249
247
|
total_commissions: NotRequired[float]
|
|
250
|
-
r"""The total commissions paid to the partner for their referrals
|
|
248
|
+
r"""The total commissions paid to the partner for their referrals"""
|
|
251
249
|
click_reward_id: NotRequired[Nullable[str]]
|
|
252
250
|
lead_reward_id: NotRequired[Nullable[str]]
|
|
253
251
|
sale_reward_id: NotRequired[Nullable[str]]
|
|
@@ -258,18 +256,30 @@ class ListPartnersResponseBodyTypedDict(TypedDict):
|
|
|
258
256
|
r"""If the partner was banned from the program, this is the date of the ban."""
|
|
259
257
|
banned_reason: NotRequired[Nullable[ListPartnersBannedReason]]
|
|
260
258
|
r"""If the partner was banned from the program, this is the reason for the ban."""
|
|
261
|
-
|
|
262
|
-
r"""The total number of clicks on the partner's links
|
|
263
|
-
|
|
264
|
-
r"""The total number of leads generated by the partner's links
|
|
265
|
-
|
|
266
|
-
r"""The total number of leads that converted to paying customers
|
|
267
|
-
|
|
268
|
-
r"""The total number of sales generated by the partner's links (includes recurring sales)
|
|
269
|
-
|
|
270
|
-
r"""
|
|
259
|
+
total_clicks: NotRequired[float]
|
|
260
|
+
r"""The total number of clicks on the partner's links"""
|
|
261
|
+
total_leads: NotRequired[float]
|
|
262
|
+
r"""The total number of leads generated by the partner's links"""
|
|
263
|
+
total_conversions: NotRequired[float]
|
|
264
|
+
r"""The total number of leads that converted to paying customers"""
|
|
265
|
+
total_sales: NotRequired[float]
|
|
266
|
+
r"""The total number of sales generated by the partner's links (includes recurring sales)"""
|
|
267
|
+
total_sale_amount: NotRequired[float]
|
|
268
|
+
r"""Total revenue generated by the partner's links"""
|
|
271
269
|
net_revenue: NotRequired[float]
|
|
272
|
-
r"""
|
|
270
|
+
r"""Net revenue after commissions (`Total Revenue - Total Commissions`)"""
|
|
271
|
+
earnings_per_click: NotRequired[Nullable[float]]
|
|
272
|
+
r"""Earnings Per Click (EPC) (`Total Revenue ÷ Total Clicks`)"""
|
|
273
|
+
average_lifetime_value: NotRequired[Nullable[float]]
|
|
274
|
+
r"""Average lifetime value for each paying customer (`Total Revenue ÷ Total Conversions`)"""
|
|
275
|
+
click_to_lead_rate: NotRequired[Nullable[float]]
|
|
276
|
+
r"""Percentage of clicks that become leads (`Total Leads ÷ Total Clicks`)"""
|
|
277
|
+
click_to_conversion_rate: NotRequired[Nullable[float]]
|
|
278
|
+
r"""Percentage of clicks that convert to paying customers (`Total Conversions ÷ Total Clicks`)"""
|
|
279
|
+
lead_to_conversion_rate: NotRequired[Nullable[float]]
|
|
280
|
+
r"""Percentage of leads that convert to paying customers (`Total Conversions ÷ Total Leads`)"""
|
|
281
|
+
return_on_ad_spend: NotRequired[Nullable[float]]
|
|
282
|
+
r"""Return On Ad Spend (ROAS) (`Total Revenue ÷ Total Commissions`)"""
|
|
273
283
|
website: NotRequired[Nullable[str]]
|
|
274
284
|
r"""The partner's website URL (including the https protocol)."""
|
|
275
285
|
youtube: NotRequired[Nullable[str]]
|
|
@@ -314,6 +324,9 @@ class ListPartnersResponseBody(BaseModel):
|
|
|
314
324
|
]
|
|
315
325
|
r"""The date when the partner enabled payouts."""
|
|
316
326
|
|
|
327
|
+
trusted_at: Annotated[Nullable[str], pydantic.Field(alias="trustedAt")]
|
|
328
|
+
r"""The date when the partner received the trusted badge in the partner network."""
|
|
329
|
+
|
|
317
330
|
program_id: Annotated[str, pydantic.Field(alias="programId")]
|
|
318
331
|
r"""The program's unique ID on Dub."""
|
|
319
332
|
|
|
@@ -340,7 +353,7 @@ class ListPartnersResponseBody(BaseModel):
|
|
|
340
353
|
total_commissions: Annotated[
|
|
341
354
|
Optional[float], pydantic.Field(alias="totalCommissions")
|
|
342
355
|
] = 0
|
|
343
|
-
r"""The total commissions paid to the partner for their referrals
|
|
356
|
+
r"""The total commissions paid to the partner for their referrals"""
|
|
344
357
|
|
|
345
358
|
click_reward_id: Annotated[
|
|
346
359
|
OptionalNullable[str], pydantic.Field(alias="clickRewardId")
|
|
@@ -373,23 +386,57 @@ class ListPartnersResponseBody(BaseModel):
|
|
|
373
386
|
] = UNSET
|
|
374
387
|
r"""If the partner was banned from the program, this is the reason for the ban."""
|
|
375
388
|
|
|
376
|
-
|
|
377
|
-
r"""The total number of clicks on the partner's links
|
|
389
|
+
total_clicks: Annotated[Optional[float], pydantic.Field(alias="totalClicks")] = 0
|
|
390
|
+
r"""The total number of clicks on the partner's links"""
|
|
378
391
|
|
|
379
|
-
|
|
380
|
-
r"""The total number of leads generated by the partner's links
|
|
392
|
+
total_leads: Annotated[Optional[float], pydantic.Field(alias="totalLeads")] = 0
|
|
393
|
+
r"""The total number of leads generated by the partner's links"""
|
|
381
394
|
|
|
382
|
-
|
|
383
|
-
|
|
395
|
+
total_conversions: Annotated[
|
|
396
|
+
Optional[float], pydantic.Field(alias="totalConversions")
|
|
397
|
+
] = 0
|
|
398
|
+
r"""The total number of leads that converted to paying customers"""
|
|
384
399
|
|
|
385
|
-
|
|
386
|
-
r"""The total number of sales generated by the partner's links (includes recurring sales)
|
|
400
|
+
total_sales: Annotated[Optional[float], pydantic.Field(alias="totalSales")] = 0
|
|
401
|
+
r"""The total number of sales generated by the partner's links (includes recurring sales)"""
|
|
387
402
|
|
|
388
|
-
|
|
389
|
-
|
|
403
|
+
total_sale_amount: Annotated[
|
|
404
|
+
Optional[float], pydantic.Field(alias="totalSaleAmount")
|
|
405
|
+
] = 0
|
|
406
|
+
r"""Total revenue generated by the partner's links"""
|
|
390
407
|
|
|
391
408
|
net_revenue: Annotated[Optional[float], pydantic.Field(alias="netRevenue")] = 0
|
|
392
|
-
r"""
|
|
409
|
+
r"""Net revenue after commissions (`Total Revenue - Total Commissions`)"""
|
|
410
|
+
|
|
411
|
+
earnings_per_click: Annotated[
|
|
412
|
+
OptionalNullable[float], pydantic.Field(alias="earningsPerClick")
|
|
413
|
+
] = UNSET
|
|
414
|
+
r"""Earnings Per Click (EPC) (`Total Revenue ÷ Total Clicks`)"""
|
|
415
|
+
|
|
416
|
+
average_lifetime_value: Annotated[
|
|
417
|
+
OptionalNullable[float], pydantic.Field(alias="averageLifetimeValue")
|
|
418
|
+
] = UNSET
|
|
419
|
+
r"""Average lifetime value for each paying customer (`Total Revenue ÷ Total Conversions`)"""
|
|
420
|
+
|
|
421
|
+
click_to_lead_rate: Annotated[
|
|
422
|
+
OptionalNullable[float], pydantic.Field(alias="clickToLeadRate")
|
|
423
|
+
] = UNSET
|
|
424
|
+
r"""Percentage of clicks that become leads (`Total Leads ÷ Total Clicks`)"""
|
|
425
|
+
|
|
426
|
+
click_to_conversion_rate: Annotated[
|
|
427
|
+
OptionalNullable[float], pydantic.Field(alias="clickToConversionRate")
|
|
428
|
+
] = UNSET
|
|
429
|
+
r"""Percentage of clicks that convert to paying customers (`Total Conversions ÷ Total Clicks`)"""
|
|
430
|
+
|
|
431
|
+
lead_to_conversion_rate: Annotated[
|
|
432
|
+
OptionalNullable[float], pydantic.Field(alias="leadToConversionRate")
|
|
433
|
+
] = UNSET
|
|
434
|
+
r"""Percentage of leads that convert to paying customers (`Total Conversions ÷ Total Leads`)"""
|
|
435
|
+
|
|
436
|
+
return_on_ad_spend: Annotated[
|
|
437
|
+
OptionalNullable[float], pydantic.Field(alias="returnOnAdSpend")
|
|
438
|
+
] = UNSET
|
|
439
|
+
r"""Return On Ad Spend (ROAS) (`Total Revenue ÷ Total Commissions`)"""
|
|
393
440
|
|
|
394
441
|
website: OptionalNullable[str] = UNSET
|
|
395
442
|
r"""The partner's website URL (including the https protocol)."""
|
|
@@ -422,12 +469,18 @@ class ListPartnersResponseBody(BaseModel):
|
|
|
422
469
|
"applicationId",
|
|
423
470
|
"bannedAt",
|
|
424
471
|
"bannedReason",
|
|
425
|
-
"
|
|
426
|
-
"
|
|
427
|
-
"
|
|
428
|
-
"
|
|
429
|
-
"
|
|
472
|
+
"totalClicks",
|
|
473
|
+
"totalLeads",
|
|
474
|
+
"totalConversions",
|
|
475
|
+
"totalSales",
|
|
476
|
+
"totalSaleAmount",
|
|
430
477
|
"netRevenue",
|
|
478
|
+
"earningsPerClick",
|
|
479
|
+
"averageLifetimeValue",
|
|
480
|
+
"clickToLeadRate",
|
|
481
|
+
"clickToConversionRate",
|
|
482
|
+
"leadToConversionRate",
|
|
483
|
+
"returnOnAdSpend",
|
|
431
484
|
"website",
|
|
432
485
|
"youtube",
|
|
433
486
|
"twitter",
|
|
@@ -444,6 +497,7 @@ class ListPartnersResponseBody(BaseModel):
|
|
|
444
497
|
"paypalEmail",
|
|
445
498
|
"stripeConnectId",
|
|
446
499
|
"payoutsEnabledAt",
|
|
500
|
+
"trustedAt",
|
|
447
501
|
"groupId",
|
|
448
502
|
"tenantId",
|
|
449
503
|
"links",
|
|
@@ -454,6 +508,12 @@ class ListPartnersResponseBody(BaseModel):
|
|
|
454
508
|
"applicationId",
|
|
455
509
|
"bannedAt",
|
|
456
510
|
"bannedReason",
|
|
511
|
+
"earningsPerClick",
|
|
512
|
+
"averageLifetimeValue",
|
|
513
|
+
"clickToLeadRate",
|
|
514
|
+
"clickToConversionRate",
|
|
515
|
+
"leadToConversionRate",
|
|
516
|
+
"returnOnAdSpend",
|
|
457
517
|
"website",
|
|
458
518
|
"youtube",
|
|
459
519
|
"twitter",
|
|
@@ -52,9 +52,14 @@ class QueryParamGroupBy(str, Enum):
|
|
|
52
52
|
TRIGGERS = "triggers"
|
|
53
53
|
REFERERS = "referers"
|
|
54
54
|
REFERER_URLS = "referer_urls"
|
|
55
|
-
|
|
55
|
+
TOP_FOLDERS = "top_folders"
|
|
56
|
+
TOP_LINK_TAGS = "top_link_tags"
|
|
57
|
+
TOP_DOMAINS = "top_domains"
|
|
56
58
|
TOP_LINKS = "top_links"
|
|
57
59
|
TOP_URLS = "top_urls"
|
|
60
|
+
TOP_BASE_URLS = "top_base_urls"
|
|
61
|
+
TOP_PARTNERS = "top_partners"
|
|
62
|
+
TOP_GROUPS = "top_groups"
|
|
58
63
|
UTM_SOURCES = "utm_sources"
|
|
59
64
|
UTM_MEDIUMS = "utm_mediums"
|
|
60
65
|
UTM_CAMPAIGNS = "utm_campaigns"
|
|
@@ -159,6 +164,8 @@ class RetrieveAnalyticsRequestTypedDict(TypedDict):
|
|
|
159
164
|
r"""The tag IDs to retrieve analytics for."""
|
|
160
165
|
folder_id: NotRequired[str]
|
|
161
166
|
r"""The folder ID to retrieve analytics for. If not provided, return analytics for unsorted links."""
|
|
167
|
+
group_id: NotRequired[str]
|
|
168
|
+
r"""The group ID to retrieve analytics for."""
|
|
162
169
|
root: NotRequired[bool]
|
|
163
170
|
r"""Filter for root domains. If true, filter for domains only. If false, filter for links only. If undefined, return both."""
|
|
164
171
|
sale_type: NotRequired[SaleType]
|
|
@@ -356,6 +363,13 @@ class RetrieveAnalyticsRequest(BaseModel):
|
|
|
356
363
|
] = None
|
|
357
364
|
r"""The folder ID to retrieve analytics for. If not provided, return analytics for unsorted links."""
|
|
358
365
|
|
|
366
|
+
group_id: Annotated[
|
|
367
|
+
Optional[str],
|
|
368
|
+
pydantic.Field(alias="groupId"),
|
|
369
|
+
FieldMetadata(query=QueryParamMetadata(style="form", explode=True)),
|
|
370
|
+
] = None
|
|
371
|
+
r"""The group ID to retrieve analytics for."""
|
|
372
|
+
|
|
359
373
|
root: Annotated[
|
|
360
374
|
Optional[bool],
|
|
361
375
|
FieldMetadata(query=QueryParamMetadata(style="form", explode=True)),
|
|
@@ -454,6 +468,7 @@ class RetrieveAnalyticsRequest(BaseModel):
|
|
|
454
468
|
"url",
|
|
455
469
|
"tagIds",
|
|
456
470
|
"folderId",
|
|
471
|
+
"groupId",
|
|
457
472
|
"root",
|
|
458
473
|
"saleType",
|
|
459
474
|
"query",
|
|
@@ -1,30 +1,65 @@
|
|
|
1
1
|
"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
|
-
from dub.types import BaseModel
|
|
4
|
+
from dub.types import BaseModel, Nullable, OptionalNullable, UNSET, UNSET_SENTINEL
|
|
5
5
|
from dub.utils import FieldMetadata, QueryParamMetadata
|
|
6
6
|
import pydantic
|
|
7
|
+
from pydantic import model_serializer
|
|
7
8
|
from typing import Optional
|
|
8
9
|
from typing_extensions import Annotated, NotRequired, TypedDict
|
|
9
10
|
|
|
10
11
|
|
|
11
12
|
class RetrieveLinksRequestTypedDict(TypedDict):
|
|
12
|
-
partner_id: NotRequired[str]
|
|
13
|
-
|
|
13
|
+
partner_id: NotRequired[Nullable[str]]
|
|
14
|
+
r"""The ID of the partner to create a link for. Will take precedence over `tenantId` if provided."""
|
|
15
|
+
tenant_id: NotRequired[Nullable[str]]
|
|
16
|
+
r"""The ID of the partner in your system. If both `partnerId` and `tenantId` are not provided, an error will be thrown."""
|
|
14
17
|
|
|
15
18
|
|
|
16
19
|
class RetrieveLinksRequest(BaseModel):
|
|
17
20
|
partner_id: Annotated[
|
|
18
|
-
|
|
21
|
+
OptionalNullable[str],
|
|
19
22
|
pydantic.Field(alias="partnerId"),
|
|
20
23
|
FieldMetadata(query=QueryParamMetadata(style="form", explode=True)),
|
|
21
|
-
] =
|
|
24
|
+
] = UNSET
|
|
25
|
+
r"""The ID of the partner to create a link for. Will take precedence over `tenantId` if provided."""
|
|
22
26
|
|
|
23
27
|
tenant_id: Annotated[
|
|
24
|
-
|
|
28
|
+
OptionalNullable[str],
|
|
25
29
|
pydantic.Field(alias="tenantId"),
|
|
26
30
|
FieldMetadata(query=QueryParamMetadata(style="form", explode=True)),
|
|
27
|
-
] =
|
|
31
|
+
] = UNSET
|
|
32
|
+
r"""The ID of the partner in your system. If both `partnerId` and `tenantId` are not provided, an error will be thrown."""
|
|
33
|
+
|
|
34
|
+
@model_serializer(mode="wrap")
|
|
35
|
+
def serialize_model(self, handler):
|
|
36
|
+
optional_fields = ["partnerId", "tenantId"]
|
|
37
|
+
nullable_fields = ["partnerId", "tenantId"]
|
|
38
|
+
null_default_fields = []
|
|
39
|
+
|
|
40
|
+
serialized = handler(self)
|
|
41
|
+
|
|
42
|
+
m = {}
|
|
43
|
+
|
|
44
|
+
for n, f in type(self).model_fields.items():
|
|
45
|
+
k = f.alias or n
|
|
46
|
+
val = serialized.get(k)
|
|
47
|
+
serialized.pop(k, None)
|
|
48
|
+
|
|
49
|
+
optional_nullable = k in optional_fields and k in nullable_fields
|
|
50
|
+
is_set = (
|
|
51
|
+
self.__pydantic_fields_set__.intersection({n})
|
|
52
|
+
or k in null_default_fields
|
|
53
|
+
) # pylint: disable=no-member
|
|
54
|
+
|
|
55
|
+
if val is not None and val != UNSET_SENTINEL:
|
|
56
|
+
m[k] = val
|
|
57
|
+
elif val != UNSET_SENTINEL and (
|
|
58
|
+
not k in optional_fields or (optional_nullable and is_set)
|
|
59
|
+
):
|
|
60
|
+
m[k] = val
|
|
61
|
+
|
|
62
|
+
return m
|
|
28
63
|
|
|
29
64
|
|
|
30
65
|
class LinkTypedDict(TypedDict):
|
|
@@ -6,10 +6,11 @@ from dub.models.components import (
|
|
|
6
6
|
partneranalyticstimeseries as components_partneranalyticstimeseries,
|
|
7
7
|
partneranalyticstoplinks as components_partneranalyticstoplinks,
|
|
8
8
|
)
|
|
9
|
-
from dub.types import BaseModel
|
|
9
|
+
from dub.types import BaseModel, Nullable, OptionalNullable, UNSET, UNSET_SENTINEL
|
|
10
10
|
from dub.utils import FieldMetadata, QueryParamMetadata
|
|
11
11
|
from enum import Enum
|
|
12
12
|
import pydantic
|
|
13
|
+
from pydantic import model_serializer
|
|
13
14
|
from typing import List, Optional, Union
|
|
14
15
|
from typing_extensions import Annotated, NotRequired, TypeAliasType, TypedDict
|
|
15
16
|
|
|
@@ -37,10 +38,10 @@ class RetrievePartnerAnalyticsQueryParamGroupBy(str, Enum):
|
|
|
37
38
|
|
|
38
39
|
|
|
39
40
|
class RetrievePartnerAnalyticsRequestTypedDict(TypedDict):
|
|
40
|
-
partner_id: NotRequired[str]
|
|
41
|
-
r"""The ID of the partner to
|
|
42
|
-
tenant_id: NotRequired[str]
|
|
43
|
-
r"""The ID of the
|
|
41
|
+
partner_id: NotRequired[Nullable[str]]
|
|
42
|
+
r"""The ID of the partner to create a link for. Will take precedence over `tenantId` if provided."""
|
|
43
|
+
tenant_id: NotRequired[Nullable[str]]
|
|
44
|
+
r"""The ID of the partner in your system. If both `partnerId` and `tenantId` are not provided, an error will be thrown."""
|
|
44
45
|
interval: NotRequired[RetrievePartnerAnalyticsQueryParamInterval]
|
|
45
46
|
r"""The interval to retrieve analytics for. If undefined, defaults to 24h."""
|
|
46
47
|
start: NotRequired[str]
|
|
@@ -57,18 +58,18 @@ class RetrievePartnerAnalyticsRequestTypedDict(TypedDict):
|
|
|
57
58
|
|
|
58
59
|
class RetrievePartnerAnalyticsRequest(BaseModel):
|
|
59
60
|
partner_id: Annotated[
|
|
60
|
-
|
|
61
|
+
OptionalNullable[str],
|
|
61
62
|
pydantic.Field(alias="partnerId"),
|
|
62
63
|
FieldMetadata(query=QueryParamMetadata(style="form", explode=True)),
|
|
63
|
-
] =
|
|
64
|
-
r"""The ID of the partner to
|
|
64
|
+
] = UNSET
|
|
65
|
+
r"""The ID of the partner to create a link for. Will take precedence over `tenantId` if provided."""
|
|
65
66
|
|
|
66
67
|
tenant_id: Annotated[
|
|
67
|
-
|
|
68
|
+
OptionalNullable[str],
|
|
68
69
|
pydantic.Field(alias="tenantId"),
|
|
69
70
|
FieldMetadata(query=QueryParamMetadata(style="form", explode=True)),
|
|
70
|
-
] =
|
|
71
|
-
r"""The ID of the
|
|
71
|
+
] = UNSET
|
|
72
|
+
r"""The ID of the partner in your system. If both `partnerId` and `tenantId` are not provided, an error will be thrown."""
|
|
72
73
|
|
|
73
74
|
interval: Annotated[
|
|
74
75
|
Optional[RetrievePartnerAnalyticsQueryParamInterval],
|
|
@@ -107,6 +108,45 @@ class RetrievePartnerAnalyticsRequest(BaseModel):
|
|
|
107
108
|
] = RetrievePartnerAnalyticsQueryParamGroupBy.COUNT
|
|
108
109
|
r"""The parameter to group the analytics data points by. Defaults to `count` if undefined."""
|
|
109
110
|
|
|
111
|
+
@model_serializer(mode="wrap")
|
|
112
|
+
def serialize_model(self, handler):
|
|
113
|
+
optional_fields = [
|
|
114
|
+
"partnerId",
|
|
115
|
+
"tenantId",
|
|
116
|
+
"interval",
|
|
117
|
+
"start",
|
|
118
|
+
"end",
|
|
119
|
+
"timezone",
|
|
120
|
+
"query",
|
|
121
|
+
"groupBy",
|
|
122
|
+
]
|
|
123
|
+
nullable_fields = ["partnerId", "tenantId"]
|
|
124
|
+
null_default_fields = []
|
|
125
|
+
|
|
126
|
+
serialized = handler(self)
|
|
127
|
+
|
|
128
|
+
m = {}
|
|
129
|
+
|
|
130
|
+
for n, f in type(self).model_fields.items():
|
|
131
|
+
k = f.alias or n
|
|
132
|
+
val = serialized.get(k)
|
|
133
|
+
serialized.pop(k, None)
|
|
134
|
+
|
|
135
|
+
optional_nullable = k in optional_fields and k in nullable_fields
|
|
136
|
+
is_set = (
|
|
137
|
+
self.__pydantic_fields_set__.intersection({n})
|
|
138
|
+
or k in null_default_fields
|
|
139
|
+
) # pylint: disable=no-member
|
|
140
|
+
|
|
141
|
+
if val is not None and val != UNSET_SENTINEL:
|
|
142
|
+
m[k] = val
|
|
143
|
+
elif val != UNSET_SENTINEL and (
|
|
144
|
+
not k in optional_fields or (optional_nullable and is_set)
|
|
145
|
+
):
|
|
146
|
+
m[k] = val
|
|
147
|
+
|
|
148
|
+
return m
|
|
149
|
+
|
|
110
150
|
|
|
111
151
|
RetrievePartnerAnalyticsResponseBodyTypedDict = TypeAliasType(
|
|
112
152
|
"RetrievePartnerAnalyticsResponseBodyTypedDict",
|
|
@@ -19,7 +19,7 @@ class Mode(str, Enum):
|
|
|
19
19
|
|
|
20
20
|
class TrackLeadRequestBodyTypedDict(TypedDict):
|
|
21
21
|
click_id: str
|
|
22
|
-
r"""The unique ID of the click that the lead conversion event is attributed to. You can read this value from `dub_id` cookie. If an empty string is provided, Dub will try to find an existing customer with the provided `customerExternalId` and use the `clickId` from the customer if found."""
|
|
22
|
+
r"""The unique ID of the click that the lead conversion event is attributed to. You can read this value from `dub_id` cookie. [For deferred lead tracking]: If an empty string is provided, Dub will try to find an existing customer with the provided `customerExternalId` and use the `clickId` from the customer if found."""
|
|
23
23
|
event_name: str
|
|
24
24
|
r"""The name of the lead event to track. Can also be used as a unique identifier to associate a given lead event for a customer for a subsequent sale event (via the `leadEventName` prop in `/track/sale`)."""
|
|
25
25
|
customer_external_id: str
|
|
@@ -40,7 +40,7 @@ class TrackLeadRequestBodyTypedDict(TypedDict):
|
|
|
40
40
|
|
|
41
41
|
class TrackLeadRequestBody(BaseModel):
|
|
42
42
|
click_id: Annotated[str, pydantic.Field(alias="clickId")]
|
|
43
|
-
r"""The unique ID of the click that the lead conversion event is attributed to. You can read this value from `dub_id` cookie. If an empty string is provided, Dub will try to find an existing customer with the provided `customerExternalId` and use the `clickId` from the customer if found."""
|
|
43
|
+
r"""The unique ID of the click that the lead conversion event is attributed to. You can read this value from `dub_id` cookie. [For deferred lead tracking]: If an empty string is provided, Dub will try to find an existing customer with the provided `customerExternalId` and use the `clickId` from the customer if found."""
|
|
44
44
|
|
|
45
45
|
event_name: Annotated[str, pydantic.Field(alias="eventName")]
|
|
46
46
|
r"""The name of the lead event to track. Can also be used as a unique identifier to associate a given lead event for a customer for a subsequent sale event (via the `leadEventName` prop in `/track/sale`)."""
|
|
@@ -94,6 +94,8 @@ class UpdateCommissionPartnerTypedDict(TypedDict):
|
|
|
94
94
|
r"""The date when the partner enabled payouts."""
|
|
95
95
|
country: Nullable[str]
|
|
96
96
|
r"""The partner's country (required for tax purposes)."""
|
|
97
|
+
group_id: NotRequired[Nullable[str]]
|
|
98
|
+
r"""The partner's group ID on Dub."""
|
|
97
99
|
|
|
98
100
|
|
|
99
101
|
class UpdateCommissionPartner(BaseModel):
|
|
@@ -117,10 +119,13 @@ class UpdateCommissionPartner(BaseModel):
|
|
|
117
119
|
country: Nullable[str]
|
|
118
120
|
r"""The partner's country (required for tax purposes)."""
|
|
119
121
|
|
|
122
|
+
group_id: Annotated[OptionalNullable[str], pydantic.Field(alias="groupId")] = UNSET
|
|
123
|
+
r"""The partner's group ID on Dub."""
|
|
124
|
+
|
|
120
125
|
@model_serializer(mode="wrap")
|
|
121
126
|
def serialize_model(self, handler):
|
|
122
|
-
optional_fields = []
|
|
123
|
-
nullable_fields = ["email", "image", "payoutsEnabledAt", "country"]
|
|
127
|
+
optional_fields = ["groupId"]
|
|
128
|
+
nullable_fields = ["email", "image", "payoutsEnabledAt", "country", "groupId"]
|
|
124
129
|
null_default_fields = []
|
|
125
130
|
|
|
126
131
|
serialized = handler(self)
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT."""
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
|
-
from dub.types import BaseModel, Nullable, OptionalNullable, UNSET_SENTINEL
|
|
4
|
+
from dub.types import BaseModel, Nullable, OptionalNullable, UNSET, UNSET_SENTINEL
|
|
5
5
|
from dub.utils import FieldMetadata, PathParamMetadata, RequestMetadata
|
|
6
6
|
from enum import Enum
|
|
7
7
|
import pydantic
|
|
@@ -20,6 +20,8 @@ class UpdateFolderAccessLevel(str, Enum):
|
|
|
20
20
|
class UpdateFolderRequestBodyTypedDict(TypedDict):
|
|
21
21
|
name: NotRequired[str]
|
|
22
22
|
r"""The name of the folder."""
|
|
23
|
+
description: NotRequired[Nullable[str]]
|
|
24
|
+
r"""The description of the folder."""
|
|
23
25
|
access_level: NotRequired[Nullable[UpdateFolderAccessLevel]]
|
|
24
26
|
r"""The access level of the folder within the workspace."""
|
|
25
27
|
|
|
@@ -28,6 +30,9 @@ class UpdateFolderRequestBody(BaseModel):
|
|
|
28
30
|
name: Optional[str] = None
|
|
29
31
|
r"""The name of the folder."""
|
|
30
32
|
|
|
33
|
+
description: OptionalNullable[str] = UNSET
|
|
34
|
+
r"""The description of the folder."""
|
|
35
|
+
|
|
31
36
|
access_level: Annotated[
|
|
32
37
|
OptionalNullable[UpdateFolderAccessLevel], pydantic.Field(alias="accessLevel")
|
|
33
38
|
] = None
|
|
@@ -35,8 +40,8 @@ class UpdateFolderRequestBody(BaseModel):
|
|
|
35
40
|
|
|
36
41
|
@model_serializer(mode="wrap")
|
|
37
42
|
def serialize_model(self, handler):
|
|
38
|
-
optional_fields = ["name", "accessLevel"]
|
|
39
|
-
nullable_fields = ["accessLevel"]
|
|
43
|
+
optional_fields = ["name", "description", "accessLevel"]
|
|
44
|
+
nullable_fields = ["description", "accessLevel"]
|
|
40
45
|
null_default_fields = ["accessLevel"]
|
|
41
46
|
|
|
42
47
|
serialized = handler(self)
|