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.
Files changed (68) hide show
  1. dub/_version.py +3 -3
  2. dub/analytics.py +6 -6
  3. dub/commissions.py +12 -12
  4. dub/customers.py +24 -321
  5. dub/domains.py +34 -38
  6. dub/embed_tokens.py +6 -6
  7. dub/events.py +6 -6
  8. dub/folders.py +24 -28
  9. dub/links.py +58 -74
  10. dub/models/components/__init__.py +38 -6
  11. dub/models/components/analyticstopurls.py +2 -2
  12. dub/models/components/clickevent.py +10 -9
  13. dub/models/components/commissioncreatedevent.py +5 -2
  14. dub/models/components/folderschema.py +6 -1
  15. dub/models/components/leadcreatedevent.py +15 -11
  16. dub/models/components/leadevent.py +10 -9
  17. dub/models/components/linkclickedevent.py +10 -9
  18. dub/models/components/linkschema.py +9 -3
  19. dub/models/components/{tagschema.py → linktagschema.py} +2 -2
  20. dub/models/components/linkwebhookevent.py +10 -9
  21. dub/models/components/partnerapplicationsubmittedevent.py +269 -0
  22. dub/models/components/partnerenrolledevent.py +93 -29
  23. dub/models/components/salecreatedevent.py +15 -11
  24. dub/models/components/saleevent.py +10 -9
  25. dub/models/components/webhookevent.py +6 -0
  26. dub/models/components/workspaceschema.py +11 -0
  27. dub/models/errors/badrequest.py +1 -1
  28. dub/models/errors/conflict.py +1 -1
  29. dub/models/errors/duberror.py +1 -1
  30. dub/models/errors/forbidden.py +1 -1
  31. dub/models/errors/internalservererror.py +1 -1
  32. dub/models/errors/inviteexpired.py +1 -1
  33. dub/models/errors/no_response_error.py +1 -1
  34. dub/models/errors/notfound.py +1 -1
  35. dub/models/errors/ratelimitexceeded.py +1 -1
  36. dub/models/errors/responsevalidationerror.py +1 -1
  37. dub/models/errors/sdkerror.py +1 -1
  38. dub/models/errors/unauthorized.py +1 -1
  39. dub/models/errors/unprocessableentity.py +1 -1
  40. dub/models/operations/__init__.py +17 -35
  41. dub/models/operations/banpartner.py +83 -0
  42. dub/models/operations/bulkcreatelinks.py +2 -2
  43. dub/models/operations/createfolder.py +8 -3
  44. dub/models/operations/createlink.py +2 -2
  45. dub/models/operations/createpartner.py +93 -29
  46. dub/models/operations/listcommissions.py +13 -2
  47. dub/models/operations/listevents.py +10 -0
  48. dub/models/operations/listpartners.py +107 -47
  49. dub/models/operations/retrieveanalytics.py +16 -1
  50. dub/models/operations/retrievelinks.py +42 -7
  51. dub/models/operations/retrievepartneranalytics.py +51 -11
  52. dub/models/operations/tracklead.py +2 -2
  53. dub/models/operations/updatecommission.py +7 -2
  54. dub/models/operations/updatefolder.py +8 -3
  55. dub/models/operations/updatelink.py +2 -2
  56. dub/models/operations/upsertlink.py +2 -2
  57. dub/partners.py +310 -36
  58. dub/qr_codes.py +4 -4
  59. dub/tags.py +24 -32
  60. dub/track.py +12 -20
  61. dub/utils/retries.py +69 -5
  62. dub/utils/unmarshal_json_response.py +15 -1
  63. dub/workspaces.py +12 -20
  64. {dub-0.31.0.dist-info → dub-0.33.0.dist-info}/METADATA +2 -21
  65. {dub-0.31.0.dist-info → dub-0.33.0.dist-info}/RECORD +67 -66
  66. dub/models/operations/createcustomer.py +0 -382
  67. {dub-0.31.0.dist-info → dub-0.33.0.dist-info}/WHEEL +0 -0
  68. {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 `saleAmount`."""
27
+ r"""The field to sort the partners by. The default is `totalSaleAmount`."""
28
28
 
29
29
  CREATED_AT = "createdAt"
30
- CLICKS = "clicks"
31
- LEADS = "leads"
32
- CONVERSIONS = "conversions"
33
- SALES = "sales"
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 `saleAmount`."""
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.SALE_AMOUNT
87
- r"""The field to sort the partners by. The default is `saleAmount`."""
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. Defaults to 0 if `includeExpandedFields` is false."""
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
- clicks: NotRequired[float]
262
- r"""The total number of clicks on the partner's links. Defaults to 0 if `includeExpandedFields` is false."""
263
- leads: NotRequired[float]
264
- r"""The total number of leads generated by the partner's links. Defaults to 0 if `includeExpandedFields` is false."""
265
- conversions: NotRequired[float]
266
- r"""The total number of leads that converted to paying customers. Defaults to 0 if `includeExpandedFields` is false."""
267
- sales: NotRequired[float]
268
- r"""The total number of sales generated by the partner's links (includes recurring sales). Defaults to 0 if `includeExpandedFields` is false."""
269
- sale_amount: NotRequired[float]
270
- r"""The total amount of sales (in cents) generated by the partner's links. Defaults to 0 if `includeExpandedFields` is false."""
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"""The total net revenue generated by the partner. Defaults to 0 if `includeExpandedFields` is false."""
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. Defaults to 0 if `includeExpandedFields` is false."""
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
- clicks: Optional[float] = 0
377
- r"""The total number of clicks on the partner's links. Defaults to 0 if `includeExpandedFields` is false."""
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
- leads: Optional[float] = 0
380
- r"""The total number of leads generated by the partner's links. Defaults to 0 if `includeExpandedFields` is false."""
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
- conversions: Optional[float] = 0
383
- r"""The total number of leads that converted to paying customers. Defaults to 0 if `includeExpandedFields` is false."""
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
- sales: Optional[float] = 0
386
- r"""The total number of sales generated by the partner's links (includes recurring sales). Defaults to 0 if `includeExpandedFields` is false."""
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
- sale_amount: Annotated[Optional[float], pydantic.Field(alias="saleAmount")] = 0
389
- r"""The total amount of sales (in cents) generated by the partner's links. Defaults to 0 if `includeExpandedFields` is false."""
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"""The total net revenue generated by the partner. Defaults to 0 if `includeExpandedFields` is false."""
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
- "clicks",
426
- "leads",
427
- "conversions",
428
- "sales",
429
- "saleAmount",
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
- 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_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
- tenant_id: NotRequired[str]
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
- Optional[str],
21
+ OptionalNullable[str],
19
22
  pydantic.Field(alias="partnerId"),
20
23
  FieldMetadata(query=QueryParamMetadata(style="form", explode=True)),
21
- ] = None
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
- Optional[str],
28
+ OptionalNullable[str],
25
29
  pydantic.Field(alias="tenantId"),
26
30
  FieldMetadata(query=QueryParamMetadata(style="form", explode=True)),
27
- ] = None
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 retrieve analytics for."""
42
- tenant_id: NotRequired[str]
43
- r"""The ID of the tenant that created the link inside your system."""
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
- Optional[str],
61
+ OptionalNullable[str],
61
62
  pydantic.Field(alias="partnerId"),
62
63
  FieldMetadata(query=QueryParamMetadata(style="form", explode=True)),
63
- ] = None
64
- r"""The ID of the partner to retrieve analytics for."""
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
- Optional[str],
68
+ OptionalNullable[str],
68
69
  pydantic.Field(alias="tenantId"),
69
70
  FieldMetadata(query=QueryParamMetadata(style="form", explode=True)),
70
- ] = None
71
- r"""The ID of the tenant that created the link inside your system."""
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)