dub 0.27.1__py3-none-any.whl → 0.27.3__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 (38) hide show
  1. dub/_version.py +3 -3
  2. dub/models/components/__init__.py +41 -2
  3. dub/models/components/analyticstriggers.py +2 -0
  4. dub/models/components/clickevent.py +92 -47
  5. dub/models/components/commissioncreatedevent.py +281 -0
  6. dub/models/components/leadcreatedevent.py +66 -21
  7. dub/models/components/leadevent.py +126 -48
  8. dub/models/components/linkclickedevent.py +66 -21
  9. dub/models/components/linkschema.py +26 -20
  10. dub/models/components/linkwebhookevent.py +33 -21
  11. dub/models/components/partnerenrolledevent.py +207 -80
  12. dub/models/components/salecreatedevent.py +66 -21
  13. dub/models/components/saleevent.py +206 -122
  14. dub/models/components/webhookevent.py +6 -0
  15. dub/models/errors/__init__.py +3 -2
  16. dub/models/operations/__init__.py +71 -2
  17. dub/models/operations/bulkcreatelinks.py +25 -25
  18. dub/models/operations/bulkupdatelinks.py +25 -25
  19. dub/models/operations/createlink.py +25 -25
  20. dub/models/operations/createpartner.py +207 -80
  21. dub/models/operations/getlinks.py +2 -2
  22. dub/models/operations/getlinkscount.py +2 -2
  23. dub/models/operations/listcommissions.py +169 -8
  24. dub/models/operations/listevents.py +48 -20
  25. dub/models/operations/listpartners.py +516 -0
  26. dub/models/operations/retrieveanalytics.py +48 -20
  27. dub/models/operations/retrievelinks.py +6 -6
  28. dub/models/operations/tracksale.py +1 -0
  29. dub/models/operations/updatecommission.py +169 -8
  30. dub/models/operations/updatelink.py +25 -25
  31. dub/models/operations/upsertlink.py +25 -25
  32. dub/partners.py +262 -0
  33. dub/sdk.py +1 -1
  34. dub/utils/__init__.py +3 -2
  35. {dub-0.27.1.dist-info → dub-0.27.3.dist-info}/METADATA +3 -2
  36. {dub-0.27.1.dist-info → dub-0.27.3.dist-info}/RECORD +38 -36
  37. {dub-0.27.1.dist-info → dub-0.27.3.dist-info}/LICENSE +0 -0
  38. {dub-0.27.1.dist-info → dub-0.27.3.dist-info}/WHEEL +0 -0
@@ -78,10 +78,12 @@ class Interval(str, Enum):
78
78
 
79
79
 
80
80
  class Trigger(str, Enum):
81
- r"""The trigger to retrieve analytics for. If undefined, return both QR and link clicks."""
81
+ r"""The trigger to retrieve analytics for. If undefined, returns all trigger types."""
82
82
 
83
83
  QR = "qr"
84
84
  LINK = "link"
85
+ PAGEVIEW = "pageview"
86
+ DEEPLINK = "deeplink"
85
87
 
86
88
 
87
89
  RetrieveAnalyticsQueryParamTagIdsTypedDict = TypeAliasType(
@@ -96,6 +98,13 @@ RetrieveAnalyticsQueryParamTagIds = TypeAliasType(
96
98
  r"""The tag IDs to retrieve analytics for."""
97
99
 
98
100
 
101
+ class SaleType(str, Enum):
102
+ r"""Filter sales by type: 'new' for first-time purchases, 'recurring' for repeat purchases. If undefined, returns both."""
103
+
104
+ NEW = "new"
105
+ RECURRING = "recurring"
106
+
107
+
99
108
  class RetrieveAnalyticsRequestTypedDict(TypedDict):
100
109
  event: NotRequired[Event]
101
110
  r"""The type of event to retrieve analytics for. Defaults to `clicks`."""
@@ -140,23 +149,27 @@ class RetrieveAnalyticsRequestTypedDict(TypedDict):
140
149
  os: NotRequired[str]
141
150
  r"""The OS to retrieve analytics for."""
142
151
  trigger: NotRequired[Trigger]
143
- r"""The trigger to retrieve analytics for. If undefined, return both QR and link clicks."""
152
+ r"""The trigger to retrieve analytics for. If undefined, returns all trigger types."""
144
153
  referer: NotRequired[str]
145
154
  r"""The referer to retrieve analytics for."""
146
155
  referer_url: NotRequired[str]
147
156
  r"""The full referer URL to retrieve analytics for."""
148
157
  url: NotRequired[str]
149
158
  r"""The URL to retrieve analytics for."""
150
- tag_id: NotRequired[str]
151
- r"""Deprecated. Use `tagIds` instead. The tag ID to retrieve analytics for."""
152
159
  tag_ids: NotRequired[RetrieveAnalyticsQueryParamTagIdsTypedDict]
153
160
  r"""The tag IDs to retrieve analytics for."""
154
161
  folder_id: NotRequired[str]
155
162
  r"""The folder ID to retrieve analytics for. If not provided, return analytics for unsorted links."""
156
- qr: NotRequired[bool]
157
- r"""Deprecated. Use the `trigger` field instead. Filter for QR code scans. If true, filter for QR codes only. If false, filter for links only. If undefined, return both."""
158
163
  root: NotRequired[bool]
159
164
  r"""Filter for root domains. If true, filter for domains only. If false, filter for links only. If undefined, return both."""
165
+ sale_type: NotRequired[SaleType]
166
+ r"""Filter sales by type: 'new' for first-time purchases, 'recurring' for repeat purchases. If undefined, returns both."""
167
+ query: NotRequired[str]
168
+ r"""Search the events by a custom metadata value. Only available for lead and sale events."""
169
+ tag_id: NotRequired[str]
170
+ r"""Deprecated: Use `tagIds` instead. The tag ID to retrieve analytics for."""
171
+ qr: NotRequired[bool]
172
+ r"""Deprecated: Use the `trigger` field instead. Filter for QR code scans. If true, filter for QR codes only. If false, filter for links only. If undefined, return both."""
160
173
  utm_source: NotRequired[Nullable[str]]
161
174
  r"""The UTM source of the short link."""
162
175
  utm_medium: NotRequired[Nullable[str]]
@@ -307,7 +320,7 @@ class RetrieveAnalyticsRequest(BaseModel):
307
320
  Optional[Trigger],
308
321
  FieldMetadata(query=QueryParamMetadata(style="form", explode=True)),
309
322
  ] = None
310
- r"""The trigger to retrieve analytics for. If undefined, return both QR and link clicks."""
323
+ r"""The trigger to retrieve analytics for. If undefined, returns all trigger types."""
311
324
 
312
325
  referer: Annotated[
313
326
  Optional[str],
@@ -328,13 +341,6 @@ class RetrieveAnalyticsRequest(BaseModel):
328
341
  ] = None
329
342
  r"""The URL to retrieve analytics for."""
330
343
 
331
- tag_id: Annotated[
332
- Optional[str],
333
- pydantic.Field(alias="tagId"),
334
- FieldMetadata(query=QueryParamMetadata(style="form", explode=True)),
335
- ] = None
336
- r"""Deprecated. Use `tagIds` instead. The tag ID to retrieve analytics for."""
337
-
338
344
  tag_ids: Annotated[
339
345
  Optional[RetrieveAnalyticsQueryParamTagIds],
340
346
  pydantic.Field(alias="tagIds"),
@@ -349,17 +355,37 @@ class RetrieveAnalyticsRequest(BaseModel):
349
355
  ] = None
350
356
  r"""The folder ID to retrieve analytics for. If not provided, return analytics for unsorted links."""
351
357
 
352
- qr: Annotated[
358
+ root: Annotated[
353
359
  Optional[bool],
354
360
  FieldMetadata(query=QueryParamMetadata(style="form", explode=True)),
355
361
  ] = None
356
- r"""Deprecated. Use the `trigger` field instead. Filter for QR code scans. If true, filter for QR codes only. If false, filter for links only. If undefined, return both."""
362
+ r"""Filter for root domains. If true, filter for domains only. If false, filter for links only. If undefined, return both."""
357
363
 
358
- root: Annotated[
364
+ sale_type: Annotated[
365
+ Optional[SaleType],
366
+ pydantic.Field(alias="saleType"),
367
+ FieldMetadata(query=QueryParamMetadata(style="form", explode=True)),
368
+ ] = None
369
+ r"""Filter sales by type: 'new' for first-time purchases, 'recurring' for repeat purchases. If undefined, returns both."""
370
+
371
+ query: Annotated[
372
+ Optional[str],
373
+ FieldMetadata(query=QueryParamMetadata(style="form", explode=True)),
374
+ ] = None
375
+ r"""Search the events by a custom metadata value. Only available for lead and sale events."""
376
+
377
+ tag_id: Annotated[
378
+ Optional[str],
379
+ pydantic.Field(alias="tagId"),
380
+ FieldMetadata(query=QueryParamMetadata(style="form", explode=True)),
381
+ ] = None
382
+ r"""Deprecated: Use `tagIds` instead. The tag ID to retrieve analytics for."""
383
+
384
+ qr: Annotated[
359
385
  Optional[bool],
360
386
  FieldMetadata(query=QueryParamMetadata(style="form", explode=True)),
361
387
  ] = None
362
- r"""Filter for root domains. If true, filter for domains only. If false, filter for links only. If undefined, return both."""
388
+ r"""Deprecated: Use the `trigger` field instead. Filter for QR code scans. If true, filter for QR codes only. If false, filter for links only. If undefined, return both."""
363
389
 
364
390
  utm_source: Annotated[
365
391
  OptionalNullable[str],
@@ -419,11 +445,13 @@ class RetrieveAnalyticsRequest(BaseModel):
419
445
  "referer",
420
446
  "refererUrl",
421
447
  "url",
422
- "tagId",
423
448
  "tagIds",
424
449
  "folderId",
425
- "qr",
426
450
  "root",
451
+ "saleType",
452
+ "query",
453
+ "tagId",
454
+ "qr",
427
455
  "utm_source",
428
456
  "utm_medium",
429
457
  "utm_campaign",
@@ -41,11 +41,11 @@ class LinkTypedDict(TypedDict):
41
41
  clicks: NotRequired[float]
42
42
  r"""The number of clicks on the short link."""
43
43
  leads: NotRequired[float]
44
- r"""The number of leads the short links has generated."""
44
+ r"""The number of leads the short link has generated."""
45
45
  sales: NotRequired[float]
46
- r"""The number of sales the short links has generated."""
46
+ r"""The total number of sales (includes recurring sales) generated by the short link."""
47
47
  sale_amount: NotRequired[float]
48
- r"""The total dollar amount of sales the short links has generated (in cents)."""
48
+ r"""The total dollar value of sales (in cents) generated by the short link."""
49
49
 
50
50
 
51
51
  class Link(BaseModel):
@@ -68,10 +68,10 @@ class Link(BaseModel):
68
68
  r"""The number of clicks on the short link."""
69
69
 
70
70
  leads: Optional[float] = 0
71
- r"""The number of leads the short links has generated."""
71
+ r"""The number of leads the short link has generated."""
72
72
 
73
73
  sales: Optional[float] = 0
74
- r"""The number of sales the short links has generated."""
74
+ r"""The total number of sales (includes recurring sales) generated by the short link."""
75
75
 
76
76
  sale_amount: Annotated[Optional[float], pydantic.Field(alias="saleAmount")] = 0
77
- r"""The total dollar amount of sales the short links has generated (in cents)."""
77
+ r"""The total dollar value of sales (in cents) generated by the short link."""
@@ -16,6 +16,7 @@ class PaymentProcessor(str, Enum):
16
16
  SHOPIFY = "shopify"
17
17
  POLAR = "polar"
18
18
  PADDLE = "paddle"
19
+ REVENUECAT = "revenuecat"
19
20
  CUSTOM = "custom"
20
21
 
21
22
 
@@ -81,6 +81,155 @@ class UpdateCommissionStatus(str, Enum):
81
81
  CANCELED = "canceled"
82
82
 
83
83
 
84
+ class UpdateCommissionPartnerTypedDict(TypedDict):
85
+ id: str
86
+ r"""The partner's unique ID on Dub."""
87
+ name: str
88
+ r"""The partner's full legal name."""
89
+ email: Nullable[str]
90
+ r"""The partner's email address. Should be a unique value across Dub."""
91
+ image: Nullable[str]
92
+ r"""The partner's avatar image."""
93
+ payouts_enabled_at: Nullable[str]
94
+ r"""The date when the partner enabled payouts."""
95
+ country: Nullable[str]
96
+ r"""The partner's country (required for tax purposes)."""
97
+
98
+
99
+ class UpdateCommissionPartner(BaseModel):
100
+ id: str
101
+ r"""The partner's unique ID on Dub."""
102
+
103
+ name: str
104
+ r"""The partner's full legal name."""
105
+
106
+ email: Nullable[str]
107
+ r"""The partner's email address. Should be a unique value across Dub."""
108
+
109
+ image: Nullable[str]
110
+ r"""The partner's avatar image."""
111
+
112
+ payouts_enabled_at: Annotated[
113
+ Nullable[str], pydantic.Field(alias="payoutsEnabledAt")
114
+ ]
115
+ r"""The date when the partner enabled payouts."""
116
+
117
+ country: Nullable[str]
118
+ r"""The partner's country (required for tax purposes)."""
119
+
120
+ @model_serializer(mode="wrap")
121
+ def serialize_model(self, handler):
122
+ optional_fields = []
123
+ nullable_fields = ["email", "image", "payoutsEnabledAt", "country"]
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
+
150
+
151
+ class UpdateCommissionCustomerTypedDict(TypedDict):
152
+ id: str
153
+ r"""The unique ID of the customer. You may use either the customer's `id` on Dub (obtained via `/customers` endpoint) or their `externalId` (unique ID within your system, prefixed with `ext_`, e.g. `ext_123`)."""
154
+ external_id: str
155
+ r"""Unique identifier for the customer in the client's app."""
156
+ name: str
157
+ r"""Name of the customer."""
158
+ created_at: str
159
+ r"""The date the customer was created."""
160
+ email: NotRequired[Nullable[str]]
161
+ r"""Email of the customer."""
162
+ avatar: NotRequired[Nullable[str]]
163
+ r"""Avatar URL of the customer."""
164
+ country: NotRequired[Nullable[str]]
165
+ r"""Country of the customer."""
166
+ sales: NotRequired[Nullable[float]]
167
+ r"""Total number of sales for the customer."""
168
+ sale_amount: NotRequired[Nullable[float]]
169
+ r"""Total amount of sales for the customer."""
170
+
171
+
172
+ class UpdateCommissionCustomer(BaseModel):
173
+ id: str
174
+ r"""The unique ID of the customer. You may use either the customer's `id` on Dub (obtained via `/customers` endpoint) or their `externalId` (unique ID within your system, prefixed with `ext_`, e.g. `ext_123`)."""
175
+
176
+ external_id: Annotated[str, pydantic.Field(alias="externalId")]
177
+ r"""Unique identifier for the customer in the client's app."""
178
+
179
+ name: str
180
+ r"""Name of the customer."""
181
+
182
+ created_at: Annotated[str, pydantic.Field(alias="createdAt")]
183
+ r"""The date the customer was created."""
184
+
185
+ email: OptionalNullable[str] = UNSET
186
+ r"""Email of the customer."""
187
+
188
+ avatar: OptionalNullable[str] = UNSET
189
+ r"""Avatar URL of the customer."""
190
+
191
+ country: OptionalNullable[str] = UNSET
192
+ r"""Country of the customer."""
193
+
194
+ sales: OptionalNullable[float] = UNSET
195
+ r"""Total number of sales for the customer."""
196
+
197
+ sale_amount: Annotated[
198
+ OptionalNullable[float], pydantic.Field(alias="saleAmount")
199
+ ] = UNSET
200
+ r"""Total amount of sales for the customer."""
201
+
202
+ @model_serializer(mode="wrap")
203
+ def serialize_model(self, handler):
204
+ optional_fields = ["email", "avatar", "country", "sales", "saleAmount"]
205
+ nullable_fields = ["email", "avatar", "country", "sales", "saleAmount"]
206
+ null_default_fields = []
207
+
208
+ serialized = handler(self)
209
+
210
+ m = {}
211
+
212
+ for n, f in type(self).model_fields.items():
213
+ k = f.alias or n
214
+ val = serialized.get(k)
215
+ serialized.pop(k, None)
216
+
217
+ optional_nullable = k in optional_fields and k in nullable_fields
218
+ is_set = (
219
+ self.__pydantic_fields_set__.intersection({n})
220
+ or k in null_default_fields
221
+ ) # pylint: disable=no-member
222
+
223
+ if val is not None and val != UNSET_SENTINEL:
224
+ m[k] = val
225
+ elif val != UNSET_SENTINEL and (
226
+ not k in optional_fields or (optional_nullable and is_set)
227
+ ):
228
+ m[k] = val
229
+
230
+ return m
231
+
232
+
84
233
  class UpdateCommissionResponseBodyTypedDict(TypedDict):
85
234
  r"""The updated commission."""
86
235
 
@@ -90,11 +239,16 @@ class UpdateCommissionResponseBodyTypedDict(TypedDict):
90
239
  earnings: float
91
240
  currency: str
92
241
  status: UpdateCommissionStatus
242
+ invoice_id: Nullable[str]
243
+ description: Nullable[str]
244
+ quantity: float
93
245
  created_at: str
94
246
  updated_at: str
247
+ partner: UpdateCommissionPartnerTypedDict
95
248
  type: NotRequired[UpdateCommissionType]
96
- invoice_id: NotRequired[Nullable[str]]
97
- description: NotRequired[Nullable[str]]
249
+ user_id: NotRequired[Nullable[str]]
250
+ r"""The user who created the manual commission."""
251
+ customer: NotRequired[Nullable[UpdateCommissionCustomerTypedDict]]
98
252
 
99
253
 
100
254
  class UpdateCommissionResponseBody(BaseModel):
@@ -111,22 +265,29 @@ class UpdateCommissionResponseBody(BaseModel):
111
265
 
112
266
  status: UpdateCommissionStatus
113
267
 
268
+ invoice_id: Annotated[Nullable[str], pydantic.Field(alias="invoiceId")]
269
+
270
+ description: Nullable[str]
271
+
272
+ quantity: float
273
+
114
274
  created_at: Annotated[str, pydantic.Field(alias="createdAt")]
115
275
 
116
276
  updated_at: Annotated[str, pydantic.Field(alias="updatedAt")]
117
277
 
278
+ partner: UpdateCommissionPartner
279
+
118
280
  type: Optional[UpdateCommissionType] = None
119
281
 
120
- invoice_id: Annotated[OptionalNullable[str], pydantic.Field(alias="invoiceId")] = (
121
- UNSET
122
- )
282
+ user_id: Annotated[OptionalNullable[str], pydantic.Field(alias="userId")] = UNSET
283
+ r"""The user who created the manual commission."""
123
284
 
124
- description: OptionalNullable[str] = UNSET
285
+ customer: OptionalNullable[UpdateCommissionCustomer] = UNSET
125
286
 
126
287
  @model_serializer(mode="wrap")
127
288
  def serialize_model(self, handler):
128
- optional_fields = ["type", "invoiceId", "description"]
129
- nullable_fields = ["invoiceId", "description"]
289
+ optional_fields = ["type", "userId", "customer"]
290
+ nullable_fields = ["invoiceId", "description", "userId", "customer"]
130
291
  null_default_fields = []
131
292
 
132
293
  serialized = handler(self)
@@ -60,10 +60,6 @@ class UpdateLinkRequestBodyTypedDict(TypedDict):
60
60
  r"""Whether to track conversions for the short link. Defaults to `false` if not provided."""
61
61
  archived: NotRequired[bool]
62
62
  r"""Whether the short link is archived. Defaults to `false` if not provided."""
63
- public_stats: NotRequired[bool]
64
- r"""Deprecated: Use `dashboard` instead. Whether the short link's stats are publicly accessible. Defaults to `false` if not provided."""
65
- tag_id: NotRequired[Nullable[str]]
66
- r"""The unique ID of the tag assigned to the short link. This field is deprecated – use `tagIds` instead."""
67
63
  tag_ids: NotRequired[UpdateLinkTagIdsTypedDict]
68
64
  r"""The unique IDs of the tags assigned to the short link."""
69
65
  tag_names: NotRequired[UpdateLinkTagNamesTypedDict]
@@ -117,6 +113,10 @@ class UpdateLinkRequestBodyTypedDict(TypedDict):
117
113
  r"""The date and time when the tests started."""
118
114
  test_completed_at: NotRequired[Nullable[str]]
119
115
  r"""The date and time when the tests were or will be completed."""
116
+ public_stats: NotRequired[bool]
117
+ r"""Deprecated: Use `dashboard` instead. Whether the short link's stats are publicly accessible. Defaults to `false` if not provided."""
118
+ tag_id: NotRequired[Nullable[str]]
119
+ r"""Deprecated: Use `tagIds` instead. The unique ID of the tag assigned to the short link."""
120
120
 
121
121
 
122
122
  class UpdateLinkRequestBody(BaseModel):
@@ -157,24 +157,6 @@ class UpdateLinkRequestBody(BaseModel):
157
157
  archived: Optional[bool] = None
158
158
  r"""Whether the short link is archived. Defaults to `false` if not provided."""
159
159
 
160
- public_stats: Annotated[
161
- Optional[bool],
162
- pydantic.Field(
163
- deprecated="warning: ** DEPRECATED ** - This will be removed in a future release, please migrate away from it as soon as possible.",
164
- alias="publicStats",
165
- ),
166
- ] = None
167
- r"""Deprecated: Use `dashboard` instead. Whether the short link's stats are publicly accessible. Defaults to `false` if not provided."""
168
-
169
- tag_id: Annotated[
170
- OptionalNullable[str],
171
- pydantic.Field(
172
- deprecated="warning: ** DEPRECATED ** - This will be removed in a future release, please migrate away from it as soon as possible.",
173
- alias="tagId",
174
- ),
175
- ] = UNSET
176
- r"""The unique ID of the tag assigned to the short link. This field is deprecated – use `tagIds` instead."""
177
-
178
160
  tag_ids: Annotated[Optional[UpdateLinkTagIds], pydantic.Field(alias="tagIds")] = (
179
161
  None
180
162
  )
@@ -274,6 +256,24 @@ class UpdateLinkRequestBody(BaseModel):
274
256
  ] = UNSET
275
257
  r"""The date and time when the tests were or will be completed."""
276
258
 
259
+ public_stats: Annotated[
260
+ Optional[bool],
261
+ pydantic.Field(
262
+ deprecated="warning: ** DEPRECATED ** - This will be removed in a future release, please migrate away from it as soon as possible.",
263
+ alias="publicStats",
264
+ ),
265
+ ] = None
266
+ r"""Deprecated: Use `dashboard` instead. Whether the short link's stats are publicly accessible. Defaults to `false` if not provided."""
267
+
268
+ tag_id: Annotated[
269
+ OptionalNullable[str],
270
+ pydantic.Field(
271
+ deprecated="warning: ** DEPRECATED ** - This will be removed in a future release, please migrate away from it as soon as possible.",
272
+ alias="tagId",
273
+ ),
274
+ ] = UNSET
275
+ r"""Deprecated: Use `tagIds` instead. The unique ID of the tag assigned to the short link."""
276
+
277
277
  @model_serializer(mode="wrap")
278
278
  def serialize_model(self, handler):
279
279
  optional_fields = [
@@ -286,8 +286,6 @@ class UpdateLinkRequestBody(BaseModel):
286
286
  "partnerId",
287
287
  "trackConversion",
288
288
  "archived",
289
- "publicStats",
290
- "tagId",
291
289
  "tagIds",
292
290
  "tagNames",
293
291
  "folderId",
@@ -315,13 +313,14 @@ class UpdateLinkRequestBody(BaseModel):
315
313
  "testVariants",
316
314
  "testStartedAt",
317
315
  "testCompletedAt",
316
+ "publicStats",
317
+ "tagId",
318
318
  ]
319
319
  nullable_fields = [
320
320
  "externalId",
321
321
  "tenantId",
322
322
  "programId",
323
323
  "partnerId",
324
- "tagId",
325
324
  "folderId",
326
325
  "comments",
327
326
  "expiresAt",
@@ -344,6 +343,7 @@ class UpdateLinkRequestBody(BaseModel):
344
343
  "testVariants",
345
344
  "testStartedAt",
346
345
  "testCompletedAt",
346
+ "tagId",
347
347
  ]
348
348
  null_default_fields = []
349
349
 
@@ -63,10 +63,6 @@ class UpsertLinkRequestBodyTypedDict(TypedDict):
63
63
  r"""Whether to track conversions for the short link. Defaults to `false` if not provided."""
64
64
  archived: NotRequired[bool]
65
65
  r"""Whether the short link is archived. Defaults to `false` if not provided."""
66
- public_stats: NotRequired[bool]
67
- r"""Deprecated: Use `dashboard` instead. Whether the short link's stats are publicly accessible. Defaults to `false` if not provided."""
68
- tag_id: NotRequired[Nullable[str]]
69
- r"""The unique ID of the tag assigned to the short link. This field is deprecated – use `tagIds` instead."""
70
66
  tag_ids: NotRequired[UpsertLinkTagIdsTypedDict]
71
67
  r"""The unique IDs of the tags assigned to the short link."""
72
68
  tag_names: NotRequired[UpsertLinkTagNamesTypedDict]
@@ -121,6 +117,10 @@ class UpsertLinkRequestBodyTypedDict(TypedDict):
121
117
  r"""The date and time when the tests started."""
122
118
  test_completed_at: NotRequired[Nullable[str]]
123
119
  r"""The date and time when the tests were or will be completed."""
120
+ public_stats: NotRequired[bool]
121
+ r"""Deprecated: Use `dashboard` instead. Whether the short link's stats are publicly accessible. Defaults to `false` if not provided."""
122
+ tag_id: NotRequired[Nullable[str]]
123
+ r"""Deprecated: Use `tagIds` instead. The unique ID of the tag assigned to the short link."""
124
124
 
125
125
 
126
126
  class UpsertLinkRequestBody(BaseModel):
@@ -167,24 +167,6 @@ class UpsertLinkRequestBody(BaseModel):
167
167
  archived: Optional[bool] = None
168
168
  r"""Whether the short link is archived. Defaults to `false` if not provided."""
169
169
 
170
- public_stats: Annotated[
171
- Optional[bool],
172
- pydantic.Field(
173
- deprecated="warning: ** DEPRECATED ** - This will be removed in a future release, please migrate away from it as soon as possible.",
174
- alias="publicStats",
175
- ),
176
- ] = None
177
- r"""Deprecated: Use `dashboard` instead. Whether the short link's stats are publicly accessible. Defaults to `false` if not provided."""
178
-
179
- tag_id: Annotated[
180
- OptionalNullable[str],
181
- pydantic.Field(
182
- deprecated="warning: ** DEPRECATED ** - This will be removed in a future release, please migrate away from it as soon as possible.",
183
- alias="tagId",
184
- ),
185
- ] = UNSET
186
- r"""The unique ID of the tag assigned to the short link. This field is deprecated – use `tagIds` instead."""
187
-
188
170
  tag_ids: Annotated[Optional[UpsertLinkTagIds], pydantic.Field(alias="tagIds")] = (
189
171
  None
190
172
  )
@@ -285,6 +267,24 @@ class UpsertLinkRequestBody(BaseModel):
285
267
  ] = UNSET
286
268
  r"""The date and time when the tests were or will be completed."""
287
269
 
270
+ public_stats: Annotated[
271
+ Optional[bool],
272
+ pydantic.Field(
273
+ deprecated="warning: ** DEPRECATED ** - This will be removed in a future release, please migrate away from it as soon as possible.",
274
+ alias="publicStats",
275
+ ),
276
+ ] = None
277
+ r"""Deprecated: Use `dashboard` instead. Whether the short link's stats are publicly accessible. Defaults to `false` if not provided."""
278
+
279
+ tag_id: Annotated[
280
+ OptionalNullable[str],
281
+ pydantic.Field(
282
+ deprecated="warning: ** DEPRECATED ** - This will be removed in a future release, please migrate away from it as soon as possible.",
283
+ alias="tagId",
284
+ ),
285
+ ] = UNSET
286
+ r"""Deprecated: Use `tagIds` instead. The unique ID of the tag assigned to the short link."""
287
+
288
288
  @model_serializer(mode="wrap")
289
289
  def serialize_model(self, handler):
290
290
  optional_fields = [
@@ -298,8 +298,6 @@ class UpsertLinkRequestBody(BaseModel):
298
298
  "prefix",
299
299
  "trackConversion",
300
300
  "archived",
301
- "publicStats",
302
- "tagId",
303
301
  "tagIds",
304
302
  "tagNames",
305
303
  "folderId",
@@ -327,13 +325,14 @@ class UpsertLinkRequestBody(BaseModel):
327
325
  "testVariants",
328
326
  "testStartedAt",
329
327
  "testCompletedAt",
328
+ "publicStats",
329
+ "tagId",
330
330
  ]
331
331
  nullable_fields = [
332
332
  "externalId",
333
333
  "tenantId",
334
334
  "programId",
335
335
  "partnerId",
336
- "tagId",
337
336
  "folderId",
338
337
  "comments",
339
338
  "expiresAt",
@@ -356,6 +355,7 @@ class UpsertLinkRequestBody(BaseModel):
356
355
  "testVariants",
357
356
  "testStartedAt",
358
357
  "testCompletedAt",
358
+ "tagId",
359
359
  ]
360
360
  null_default_fields = []
361
361