dub 0.29.3__py3-none-any.whl → 0.32.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. dub/_version.py +3 -3
  2. dub/analytics.py +2 -2
  3. dub/commissions.py +4 -4
  4. dub/customers.py +10 -10
  5. dub/domains.py +12 -12
  6. dub/embed_tokens.py +2 -2
  7. dub/events.py +2 -2
  8. dub/folders.py +8 -8
  9. dub/httpclient.py +0 -1
  10. dub/links.py +20 -20
  11. dub/models/components/__init__.py +22 -10
  12. dub/models/components/clickevent.py +3 -3
  13. dub/models/components/commissioncreatedevent.py +9 -6
  14. dub/models/components/folderschema.py +6 -1
  15. dub/models/components/leadcreatedevent.py +128 -4
  16. dub/models/components/leadevent.py +3 -3
  17. dub/models/components/linkclickedevent.py +3 -3
  18. dub/models/components/linkschema.py +3 -3
  19. dub/models/components/{tagschema.py → linktagschema.py} +2 -2
  20. dub/models/components/linkwebhookevent.py +3 -3
  21. dub/models/components/partnerenrolledevent.py +45 -92
  22. dub/models/components/salecreatedevent.py +128 -4
  23. dub/models/components/saleevent.py +3 -3
  24. dub/models/components/workspaceschema.py +13 -0
  25. dub/models/errors/badrequest.py +1 -1
  26. dub/models/errors/conflict.py +1 -1
  27. dub/models/errors/duberror.py +1 -1
  28. dub/models/errors/forbidden.py +1 -1
  29. dub/models/errors/internalservererror.py +1 -1
  30. dub/models/errors/inviteexpired.py +1 -1
  31. dub/models/errors/no_response_error.py +1 -1
  32. dub/models/errors/notfound.py +1 -1
  33. dub/models/errors/ratelimitexceeded.py +1 -1
  34. dub/models/errors/responsevalidationerror.py +1 -1
  35. dub/models/errors/sdkerror.py +1 -1
  36. dub/models/errors/unauthorized.py +1 -1
  37. dub/models/errors/unprocessableentity.py +1 -1
  38. dub/models/operations/bulkcreatelinks.py +2 -2
  39. dub/models/operations/createcustomer.py +10 -3
  40. dub/models/operations/createfolder.py +8 -3
  41. dub/models/operations/createlink.py +2 -2
  42. dub/models/operations/createpartner.py +47 -94
  43. dub/models/operations/getcustomer.py +1 -1
  44. dub/models/operations/getcustomers.py +1 -1
  45. dub/models/operations/listcommissions.py +11 -2
  46. dub/models/operations/listevents.py +10 -0
  47. dub/models/operations/listpartners.py +66 -115
  48. dub/models/operations/retrieveanalytics.py +14 -1
  49. dub/models/operations/retrievelinks.py +5 -0
  50. dub/models/operations/tracklead.py +2 -2
  51. dub/models/operations/updatecustomer.py +10 -3
  52. dub/models/operations/updatefolder.py +8 -3
  53. dub/models/operations/updatelink.py +2 -2
  54. dub/models/operations/upsertlink.py +2 -2
  55. dub/partners.py +16 -16
  56. dub/qr_codes.py +2 -2
  57. dub/sdk.py +2 -2
  58. dub/tags.py +20 -20
  59. dub/track.py +4 -4
  60. dub/utils/annotations.py +32 -8
  61. dub/workspaces.py +4 -4
  62. {dub-0.29.3.dist-info → dub-0.32.0.dist-info}/METADATA +7 -4
  63. {dub-0.29.3.dist-info → dub-0.32.0.dist-info}/RECORD +65 -65
  64. {dub-0.29.3.dist-info → dub-0.32.0.dist-info}/WHEEL +1 -1
  65. {dub-0.29.3.dist-info → dub-0.32.0.dist-info/licenses}/LICENSE +0 -0
@@ -18,21 +18,20 @@ class ListPartnersQueryParamStatus(str, Enum):
18
18
  REJECTED = "rejected"
19
19
  INVITED = "invited"
20
20
  DECLINED = "declined"
21
+ DEACTIVATED = "deactivated"
21
22
  BANNED = "banned"
22
23
  ARCHIVED = "archived"
23
24
 
24
25
 
25
26
  class ListPartnersQueryParamSortBy(str, Enum):
26
- r"""The field to sort the partners by. The default is `saleAmount`."""
27
+ r"""The field to sort the partners by. The default is `totalSaleAmount`."""
27
28
 
28
29
  CREATED_AT = "createdAt"
29
- CLICKS = "clicks"
30
- LEADS = "leads"
31
- CONVERSIONS = "conversions"
32
- SALES = "sales"
33
- SALE_AMOUNT = "saleAmount"
34
- COMMISSIONS = "commissions"
35
- NET_REVENUE = "netRevenue"
30
+ TOTAL_CLICKS = "totalClicks"
31
+ TOTAL_LEADS = "totalLeads"
32
+ TOTAL_CONVERSIONS = "totalConversions"
33
+ TOTAL_SALE_AMOUNT = "totalSaleAmount"
34
+ TOTAL_COMMISSIONS = "totalCommissions"
36
35
 
37
36
 
38
37
  class ListPartnersQueryParamSortOrder(str, Enum):
@@ -48,15 +47,15 @@ class ListPartnersRequestTypedDict(TypedDict):
48
47
  country: NotRequired[str]
49
48
  r"""A filter on the list based on the partner's `country` field."""
50
49
  sort_by: NotRequired[ListPartnersQueryParamSortBy]
51
- r"""The field to sort the partners by. The default is `saleAmount`."""
50
+ r"""The field to sort the partners by. The default is `totalSaleAmount`."""
52
51
  sort_order: NotRequired[ListPartnersQueryParamSortOrder]
53
52
  r"""The sort order. The default is `desc`."""
53
+ email: NotRequired[str]
54
+ r"""Filter the partner list based on the partner's `email`. The value must be a string. Takes precedence over `search`."""
54
55
  tenant_id: NotRequired[str]
55
- r"""A case-sensitive filter on the list based on the partner's `tenantId` field. The value must be a string. Takes precedence over `search`."""
56
- include_expanded_fields: NotRequired[bool]
57
- 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."""
56
+ r"""Filter the partner list based on the partner's `tenantId`. The value must be a string. Takes precedence over `email` and `search`."""
58
57
  search: NotRequired[str]
59
- r"""A search query to filter partners by name, email, or tenantId."""
58
+ r"""A search query to filter partners by ID, name, email, or link."""
60
59
  page: NotRequired[float]
61
60
  r"""The page number for pagination."""
62
61
  page_size: NotRequired[float]
@@ -80,8 +79,8 @@ class ListPartnersRequest(BaseModel):
80
79
  Optional[ListPartnersQueryParamSortBy],
81
80
  pydantic.Field(alias="sortBy"),
82
81
  FieldMetadata(query=QueryParamMetadata(style="form", explode=True)),
83
- ] = ListPartnersQueryParamSortBy.SALE_AMOUNT
84
- r"""The field to sort the partners by. The default is `saleAmount`."""
82
+ ] = ListPartnersQueryParamSortBy.TOTAL_SALE_AMOUNT
83
+ r"""The field to sort the partners by. The default is `totalSaleAmount`."""
85
84
 
86
85
  sort_order: Annotated[
87
86
  Optional[ListPartnersQueryParamSortOrder],
@@ -90,25 +89,24 @@ class ListPartnersRequest(BaseModel):
90
89
  ] = ListPartnersQueryParamSortOrder.DESC
91
90
  r"""The sort order. The default is `desc`."""
92
91
 
93
- tenant_id: Annotated[
92
+ email: Annotated[
94
93
  Optional[str],
95
- pydantic.Field(alias="tenantId"),
96
94
  FieldMetadata(query=QueryParamMetadata(style="form", explode=True)),
97
95
  ] = None
98
- r"""A case-sensitive filter on the list based on the partner's `tenantId` field. The value must be a string. Takes precedence over `search`."""
96
+ r"""Filter the partner list based on the partner's `email`. The value must be a string. Takes precedence over `search`."""
99
97
 
100
- include_expanded_fields: Annotated[
101
- Optional[bool],
102
- pydantic.Field(alias="includeExpandedFields"),
98
+ tenant_id: Annotated[
99
+ Optional[str],
100
+ pydantic.Field(alias="tenantId"),
103
101
  FieldMetadata(query=QueryParamMetadata(style="form", explode=True)),
104
102
  ] = None
105
- 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."""
103
+ r"""Filter the partner list based on the partner's `tenantId`. The value must be a string. Takes precedence over `email` and `search`."""
106
104
 
107
105
  search: Annotated[
108
106
  Optional[str],
109
107
  FieldMetadata(query=QueryParamMetadata(style="form", explode=True)),
110
108
  ] = None
111
- r"""A search query to filter partners by name, email, or tenantId."""
109
+ r"""A search query to filter partners by ID, name, email, or link."""
112
110
 
113
111
  page: Annotated[
114
112
  Optional[float],
@@ -132,6 +130,7 @@ class ListPartnersStatus(str, Enum):
132
130
  REJECTED = "rejected"
133
131
  INVITED = "invited"
134
132
  DECLINED = "declined"
133
+ DEACTIVATED = "deactivated"
135
134
  BANNED = "banned"
136
135
  ARCHIVED = "archived"
137
136
 
@@ -151,6 +150,8 @@ class ListPartnersLinkTypedDict(TypedDict):
151
150
  r"""The number of clicks on the short link."""
152
151
  leads: NotRequired[float]
153
152
  r"""The number of leads the short link has generated."""
153
+ conversions: NotRequired[float]
154
+ r"""The number of leads that converted to paying customers."""
154
155
  sales: NotRequired[float]
155
156
  r"""The total number of sales (includes recurring sales) generated by the short link."""
156
157
  sale_amount: NotRequired[float]
@@ -179,6 +180,9 @@ class ListPartnersLink(BaseModel):
179
180
  leads: Optional[float] = 0
180
181
  r"""The number of leads the short link has generated."""
181
182
 
183
+ conversions: Optional[float] = 0
184
+ r"""The number of leads that converted to paying customers."""
185
+
182
186
  sales: Optional[float] = 0
183
187
  r"""The total number of sales (includes recurring sales) generated by the short link."""
184
188
 
@@ -202,6 +206,8 @@ class ListPartnersResponseBodyTypedDict(TypedDict):
202
206
  r"""The partner's unique ID on Dub."""
203
207
  name: str
204
208
  r"""The partner's full legal name."""
209
+ company_name: Nullable[str]
210
+ r"""If the partner profile type is a company, this is the partner's legal company name."""
205
211
  email: Nullable[str]
206
212
  r"""The partner's email address. Should be a unique value across Dub."""
207
213
  image: Nullable[str]
@@ -230,7 +236,7 @@ class ListPartnersResponseBodyTypedDict(TypedDict):
230
236
  group_id: NotRequired[Nullable[str]]
231
237
  r"""The partner's group ID on Dub."""
232
238
  total_commissions: NotRequired[float]
233
- r"""The total commissions paid to the partner for their referrals. Defaults to 0 if `includeExpandedFields` is false."""
239
+ r"""The total commissions paid to the partner for their referrals"""
234
240
  click_reward_id: NotRequired[Nullable[str]]
235
241
  lead_reward_id: NotRequired[Nullable[str]]
236
242
  sale_reward_id: NotRequired[Nullable[str]]
@@ -241,39 +247,30 @@ class ListPartnersResponseBodyTypedDict(TypedDict):
241
247
  r"""If the partner was banned from the program, this is the date of the ban."""
242
248
  banned_reason: NotRequired[Nullable[ListPartnersBannedReason]]
243
249
  r"""If the partner was banned from the program, this is the reason for the ban."""
244
- clicks: NotRequired[float]
245
- r"""The total number of clicks on the partner's links. Defaults to 0 if `includeExpandedFields` is false."""
246
- leads: NotRequired[float]
247
- r"""The total number of leads generated by the partner's links. Defaults to 0 if `includeExpandedFields` is false."""
248
- conversions: NotRequired[float]
249
- r"""The total number of leads that converted to paying customers. Defaults to 0 if `includeExpandedFields` is false."""
250
- sales: NotRequired[float]
251
- r"""The total number of sales generated by the partner's links (includes recurring sales). Defaults to 0 if `includeExpandedFields` is false."""
252
- sale_amount: NotRequired[float]
253
- r"""The total amount of sales (in cents) generated by the partner's links. Defaults to 0 if `includeExpandedFields` is false."""
250
+ total_clicks: NotRequired[float]
251
+ r"""The total number of clicks on the partner's links"""
252
+ total_leads: NotRequired[float]
253
+ r"""The total number of leads generated by the partner's links"""
254
+ total_conversions: NotRequired[float]
255
+ r"""The total number of leads that converted to paying customers"""
256
+ total_sales: NotRequired[float]
257
+ r"""The total number of sales generated by the partner's links (includes recurring sales)"""
258
+ total_sale_amount: NotRequired[float]
259
+ r"""The total amount of sales (in cents) generated by the partner's links"""
254
260
  net_revenue: NotRequired[float]
255
- r"""The total net revenue generated by the partner. Defaults to 0 if `includeExpandedFields` is false."""
261
+ r"""The total net revenue generated by the partner"""
256
262
  website: NotRequired[Nullable[str]]
257
263
  r"""The partner's website URL (including the https protocol)."""
258
- website_txt_record: NotRequired[Nullable[str]]
259
- website_verified_at: NotRequired[Nullable[str]]
260
264
  youtube: NotRequired[Nullable[str]]
261
265
  r"""The partner's YouTube channel username (e.g. `johndoe`)."""
262
- youtube_verified_at: NotRequired[Nullable[str]]
263
- youtube_subscriber_count: NotRequired[Nullable[float]]
264
- youtube_view_count: NotRequired[Nullable[float]]
265
266
  twitter: NotRequired[Nullable[str]]
266
267
  r"""The partner's Twitter username (e.g. `johndoe`)."""
267
- twitter_verified_at: NotRequired[Nullable[str]]
268
268
  linkedin: NotRequired[Nullable[str]]
269
269
  r"""The partner's LinkedIn username (e.g. `johndoe`)."""
270
- linkedin_verified_at: NotRequired[Nullable[str]]
271
270
  instagram: NotRequired[Nullable[str]]
272
271
  r"""The partner's Instagram username (e.g. `johndoe`)."""
273
- instagram_verified_at: NotRequired[Nullable[str]]
274
272
  tiktok: NotRequired[Nullable[str]]
275
273
  r"""The partner's TikTok username (e.g. `johndoe`)."""
276
- tiktok_verified_at: NotRequired[Nullable[str]]
277
274
 
278
275
 
279
276
  class ListPartnersResponseBody(BaseModel):
@@ -283,6 +280,9 @@ class ListPartnersResponseBody(BaseModel):
283
280
  name: str
284
281
  r"""The partner's full legal name."""
285
282
 
283
+ company_name: Annotated[Nullable[str], pydantic.Field(alias="companyName")]
284
+ r"""If the partner profile type is a company, this is the partner's legal company name."""
285
+
286
286
  email: Nullable[str]
287
287
  r"""The partner's email address. Should be a unique value across Dub."""
288
288
 
@@ -329,7 +329,7 @@ class ListPartnersResponseBody(BaseModel):
329
329
  total_commissions: Annotated[
330
330
  Optional[float], pydantic.Field(alias="totalCommissions")
331
331
  ] = 0
332
- r"""The total commissions paid to the partner for their referrals. Defaults to 0 if `includeExpandedFields` is false."""
332
+ r"""The total commissions paid to the partner for their referrals"""
333
333
 
334
334
  click_reward_id: Annotated[
335
335
  OptionalNullable[str], pydantic.Field(alias="clickRewardId")
@@ -362,78 +362,46 @@ class ListPartnersResponseBody(BaseModel):
362
362
  ] = UNSET
363
363
  r"""If the partner was banned from the program, this is the reason for the ban."""
364
364
 
365
- clicks: Optional[float] = 0
366
- r"""The total number of clicks on the partner's links. Defaults to 0 if `includeExpandedFields` is false."""
365
+ total_clicks: Annotated[Optional[float], pydantic.Field(alias="totalClicks")] = 0
366
+ r"""The total number of clicks on the partner's links"""
367
367
 
368
- leads: Optional[float] = 0
369
- r"""The total number of leads generated by the partner's links. Defaults to 0 if `includeExpandedFields` is false."""
368
+ total_leads: Annotated[Optional[float], pydantic.Field(alias="totalLeads")] = 0
369
+ r"""The total number of leads generated by the partner's links"""
370
370
 
371
- conversions: Optional[float] = 0
372
- r"""The total number of leads that converted to paying customers. Defaults to 0 if `includeExpandedFields` is false."""
371
+ total_conversions: Annotated[
372
+ Optional[float], pydantic.Field(alias="totalConversions")
373
+ ] = 0
374
+ r"""The total number of leads that converted to paying customers"""
373
375
 
374
- sales: Optional[float] = 0
375
- r"""The total number of sales generated by the partner's links (includes recurring sales). Defaults to 0 if `includeExpandedFields` is false."""
376
+ total_sales: Annotated[Optional[float], pydantic.Field(alias="totalSales")] = 0
377
+ r"""The total number of sales generated by the partner's links (includes recurring sales)"""
376
378
 
377
- sale_amount: Annotated[Optional[float], pydantic.Field(alias="saleAmount")] = 0
378
- r"""The total amount of sales (in cents) generated by the partner's links. Defaults to 0 if `includeExpandedFields` is false."""
379
+ total_sale_amount: Annotated[
380
+ Optional[float], pydantic.Field(alias="totalSaleAmount")
381
+ ] = 0
382
+ r"""The total amount of sales (in cents) generated by the partner's links"""
379
383
 
380
384
  net_revenue: Annotated[Optional[float], pydantic.Field(alias="netRevenue")] = 0
381
- r"""The total net revenue generated by the partner. Defaults to 0 if `includeExpandedFields` is false."""
385
+ r"""The total net revenue generated by the partner"""
382
386
 
383
387
  website: OptionalNullable[str] = UNSET
384
388
  r"""The partner's website URL (including the https protocol)."""
385
389
 
386
- website_txt_record: Annotated[
387
- OptionalNullable[str], pydantic.Field(alias="websiteTxtRecord")
388
- ] = UNSET
389
-
390
- website_verified_at: Annotated[
391
- OptionalNullable[str], pydantic.Field(alias="websiteVerifiedAt")
392
- ] = UNSET
393
-
394
390
  youtube: OptionalNullable[str] = UNSET
395
391
  r"""The partner's YouTube channel username (e.g. `johndoe`)."""
396
392
 
397
- youtube_verified_at: Annotated[
398
- OptionalNullable[str], pydantic.Field(alias="youtubeVerifiedAt")
399
- ] = UNSET
400
-
401
- youtube_subscriber_count: Annotated[
402
- OptionalNullable[float], pydantic.Field(alias="youtubeSubscriberCount")
403
- ] = UNSET
404
-
405
- youtube_view_count: Annotated[
406
- OptionalNullable[float], pydantic.Field(alias="youtubeViewCount")
407
- ] = UNSET
408
-
409
393
  twitter: OptionalNullable[str] = UNSET
410
394
  r"""The partner's Twitter username (e.g. `johndoe`)."""
411
395
 
412
- twitter_verified_at: Annotated[
413
- OptionalNullable[str], pydantic.Field(alias="twitterVerifiedAt")
414
- ] = UNSET
415
-
416
396
  linkedin: OptionalNullable[str] = UNSET
417
397
  r"""The partner's LinkedIn username (e.g. `johndoe`)."""
418
398
 
419
- linkedin_verified_at: Annotated[
420
- OptionalNullable[str], pydantic.Field(alias="linkedinVerifiedAt")
421
- ] = UNSET
422
-
423
399
  instagram: OptionalNullable[str] = UNSET
424
400
  r"""The partner's Instagram username (e.g. `johndoe`)."""
425
401
 
426
- instagram_verified_at: Annotated[
427
- OptionalNullable[str], pydantic.Field(alias="instagramVerifiedAt")
428
- ] = UNSET
429
-
430
402
  tiktok: OptionalNullable[str] = UNSET
431
403
  r"""The partner's TikTok username (e.g. `johndoe`)."""
432
404
 
433
- tiktok_verified_at: Annotated[
434
- OptionalNullable[str], pydantic.Field(alias="tiktokVerifiedAt")
435
- ] = UNSET
436
-
437
405
  @model_serializer(mode="wrap")
438
406
  def serialize_model(self, handler):
439
407
  optional_fields = [
@@ -447,29 +415,21 @@ class ListPartnersResponseBody(BaseModel):
447
415
  "applicationId",
448
416
  "bannedAt",
449
417
  "bannedReason",
450
- "clicks",
451
- "leads",
452
- "conversions",
453
- "sales",
454
- "saleAmount",
418
+ "totalClicks",
419
+ "totalLeads",
420
+ "totalConversions",
421
+ "totalSales",
422
+ "totalSaleAmount",
455
423
  "netRevenue",
456
424
  "website",
457
- "websiteTxtRecord",
458
- "websiteVerifiedAt",
459
425
  "youtube",
460
- "youtubeVerifiedAt",
461
- "youtubeSubscriberCount",
462
- "youtubeViewCount",
463
426
  "twitter",
464
- "twitterVerifiedAt",
465
427
  "linkedin",
466
- "linkedinVerifiedAt",
467
428
  "instagram",
468
- "instagramVerifiedAt",
469
429
  "tiktok",
470
- "tiktokVerifiedAt",
471
430
  ]
472
431
  nullable_fields = [
432
+ "companyName",
473
433
  "email",
474
434
  "image",
475
435
  "description",
@@ -488,20 +448,11 @@ class ListPartnersResponseBody(BaseModel):
488
448
  "bannedAt",
489
449
  "bannedReason",
490
450
  "website",
491
- "websiteTxtRecord",
492
- "websiteVerifiedAt",
493
451
  "youtube",
494
- "youtubeVerifiedAt",
495
- "youtubeSubscriberCount",
496
- "youtubeViewCount",
497
452
  "twitter",
498
- "twitterVerifiedAt",
499
453
  "linkedin",
500
- "linkedinVerifiedAt",
501
454
  "instagram",
502
- "instagramVerifiedAt",
503
455
  "tiktok",
504
- "tiktokVerifiedAt",
505
456
  ]
506
457
  null_default_fields = []
507
458
 
@@ -52,9 +52,12 @@ class QueryParamGroupBy(str, Enum):
52
52
  TRIGGERS = "triggers"
53
53
  REFERERS = "referers"
54
54
  REFERER_URLS = "referer_urls"
55
- TOP_PARTNERS = "top_partners"
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_PARTNERS = "top_partners"
58
61
  UTM_SOURCES = "utm_sources"
59
62
  UTM_MEDIUMS = "utm_mediums"
60
63
  UTM_CAMPAIGNS = "utm_campaigns"
@@ -179,6 +182,8 @@ class RetrieveAnalyticsRequestTypedDict(TypedDict):
179
182
  r"""The UTM term of the short link."""
180
183
  utm_content: NotRequired[Nullable[str]]
181
184
  r"""The UTM content of the short link."""
185
+ ref: NotRequired[Nullable[str]]
186
+ r"""The ref of the short link."""
182
187
 
183
188
 
184
189
  class RetrieveAnalyticsRequest(BaseModel):
@@ -416,6 +421,12 @@ class RetrieveAnalyticsRequest(BaseModel):
416
421
  ] = UNSET
417
422
  r"""The UTM content of the short link."""
418
423
 
424
+ ref: Annotated[
425
+ OptionalNullable[str],
426
+ FieldMetadata(query=QueryParamMetadata(style="form", explode=True)),
427
+ ] = UNSET
428
+ r"""The ref of the short link."""
429
+
419
430
  @model_serializer(mode="wrap")
420
431
  def serialize_model(self, handler):
421
432
  optional_fields = [
@@ -456,6 +467,7 @@ class RetrieveAnalyticsRequest(BaseModel):
456
467
  "utm_campaign",
457
468
  "utm_term",
458
469
  "utm_content",
470
+ "ref",
459
471
  ]
460
472
  nullable_fields = [
461
473
  "utm_source",
@@ -463,6 +475,7 @@ class RetrieveAnalyticsRequest(BaseModel):
463
475
  "utm_campaign",
464
476
  "utm_term",
465
477
  "utm_content",
478
+ "ref",
466
479
  ]
467
480
  null_default_fields = []
468
481
 
@@ -42,6 +42,8 @@ class LinkTypedDict(TypedDict):
42
42
  r"""The number of clicks on the short link."""
43
43
  leads: NotRequired[float]
44
44
  r"""The number of leads the short link has generated."""
45
+ conversions: NotRequired[float]
46
+ r"""The number of leads that converted to paying customers."""
45
47
  sales: NotRequired[float]
46
48
  r"""The total number of sales (includes recurring sales) generated by the short link."""
47
49
  sale_amount: NotRequired[float]
@@ -70,6 +72,9 @@ class Link(BaseModel):
70
72
  leads: Optional[float] = 0
71
73
  r"""The number of leads the short link has generated."""
72
74
 
75
+ conversions: Optional[float] = 0
76
+ r"""The number of leads that converted to paying customers."""
77
+
73
78
  sales: Optional[float] = 0
74
79
  r"""The total number of sales (includes recurring sales) generated by the short link."""
75
80
 
@@ -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`)."""
@@ -24,6 +24,8 @@ class UpdateCustomerRequestBodyTypedDict(TypedDict):
24
24
  r"""Avatar URL of the customer in the client's app."""
25
25
  external_id: NotRequired[str]
26
26
  r"""Unique identifier for the customer in the client's app."""
27
+ stripe_customer_id: NotRequired[Nullable[str]]
28
+ r"""The customer's Stripe customer ID. Useful for attribution recurring sale events to the partner who referred the customer."""
27
29
 
28
30
 
29
31
  class UpdateCustomerRequestBody(BaseModel):
@@ -39,10 +41,15 @@ class UpdateCustomerRequestBody(BaseModel):
39
41
  external_id: Annotated[Optional[str], pydantic.Field(alias="externalId")] = None
40
42
  r"""Unique identifier for the customer in the client's app."""
41
43
 
44
+ stripe_customer_id: Annotated[
45
+ OptionalNullable[str], pydantic.Field(alias="stripeCustomerId")
46
+ ] = UNSET
47
+ r"""The customer's Stripe customer ID. Useful for attribution recurring sale events to the partner who referred the customer."""
48
+
42
49
  @model_serializer(mode="wrap")
43
50
  def serialize_model(self, handler):
44
- optional_fields = ["email", "name", "avatar", "externalId"]
45
- nullable_fields = ["email", "name", "avatar"]
51
+ optional_fields = ["email", "name", "avatar", "externalId", "stripeCustomerId"]
52
+ nullable_fields = ["email", "name", "avatar", "stripeCustomerId"]
46
53
  null_default_fields = []
47
54
 
48
55
  serialized = handler(self)
@@ -257,9 +264,9 @@ class UpdateCustomerDiscount(BaseModel):
257
264
  optional_fields = ["description", "partnersCount"]
258
265
  nullable_fields = [
259
266
  "maxDuration",
260
- "description",
261
267
  "couponId",
262
268
  "couponTestId",
269
+ "description",
263
270
  "partnersCount",
264
271
  ]
265
272
  null_default_fields = []
@@ -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)
@@ -44,7 +44,7 @@ class UpdateLinkRequestBodyTypedDict(TypedDict):
44
44
  url: NotRequired[str]
45
45
  r"""The destination URL of the short link."""
46
46
  domain: NotRequired[str]
47
- r"""The domain of the short link. If not provided, the primary domain for the workspace will be used (or `dub.sh` if the workspace has no domains)."""
47
+ r"""The domain of the short link (without protocol). If not provided, the primary domain for the workspace will be used (or `dub.sh` if the workspace has no domains)."""
48
48
  key: NotRequired[str]
49
49
  r"""The short link slug. If not provided, a random 7-character slug will be generated."""
50
50
  external_id: NotRequired[Nullable[str]]
@@ -123,7 +123,7 @@ class UpdateLinkRequestBody(BaseModel):
123
123
  r"""The destination URL of the short link."""
124
124
 
125
125
  domain: Optional[str] = None
126
- r"""The domain of the short link. If not provided, the primary domain for the workspace will be used (or `dub.sh` if the workspace has no domains)."""
126
+ r"""The domain of the short link (without protocol). If not provided, the primary domain for the workspace will be used (or `dub.sh` if the workspace has no domains)."""
127
127
 
128
128
  key: Optional[str] = None
129
129
  r"""The short link slug. If not provided, a random 7-character slug will be generated."""
@@ -43,7 +43,7 @@ class UpsertLinkRequestBodyTypedDict(TypedDict):
43
43
  url: str
44
44
  r"""The destination URL of the short link."""
45
45
  domain: NotRequired[str]
46
- r"""The domain of the short link. If not provided, the primary domain for the workspace will be used (or `dub.sh` if the workspace has no domains)."""
46
+ r"""The domain of the short link (without protocol). If not provided, the primary domain for the workspace will be used (or `dub.sh` if the workspace has no domains)."""
47
47
  key: NotRequired[str]
48
48
  r"""The short link slug. If not provided, a random 7-character slug will be generated."""
49
49
  key_length: NotRequired[float]
@@ -127,7 +127,7 @@ class UpsertLinkRequestBody(BaseModel):
127
127
  r"""The destination URL of the short link."""
128
128
 
129
129
  domain: Optional[str] = None
130
- r"""The domain of the short link. If not provided, the primary domain for the workspace will be used (or `dub.sh` if the workspace has no domains)."""
130
+ r"""The domain of the short link (without protocol). If not provided, the primary domain for the workspace will be used (or `dub.sh` if the workspace has no domains)."""
131
131
 
132
132
  key: Optional[str] = None
133
133
  r"""The short link slug. If not provided, a random 7-character slug will be generated."""