diff --git a/apps/docs/mintlify/api-reference/billing/attach.mdx b/apps/docs/mintlify/api-reference/billing/attach.mdx index 849c8b492..c13aee618 100644 --- a/apps/docs/mintlify/api-reference/billing/attach.mdx +++ b/apps/docs/mintlify/api-reference/billing/attach.mdx @@ -77,15 +77,15 @@ This is useful for attaching custom metadata to the Stripe subscription created ### Body Parameters - The ID of the customer to attach the plan to. + The ID of the customer to attach the plan to. - The ID of the entity to attach the plan to. + The ID of the entity to attach the plan to. - The ID of the plan. + The ID of the plan. @@ -107,7 +107,7 @@ This is useful for attaching custom metadata to the Stripe subscription created - The version of the plan to attach. + The version of the plan to attach. @@ -278,28 +278,16 @@ This is useful for attaching custom metadata to the Stripe subscription created - - How to handle proration when updating an existing subscription. - 'prorate_immediately' charges/credits prorated amounts now, 'none' skips - creating any charges. + + How to handle proration when updating an existing subscription. 'prorate_immediately' charges/credits prorated amounts now, 'none' skips creating any charges. - - Controls when to return a checkout URL. 'always' returns a URL even if - payment succeeds, 'if_required' only when payment action is needed, 'never' - disables redirects. + + Controls when to return a checkout URL. 'always' returns a URL even if payment succeeds, 'if_required' only when payment action is needed, 'never' disables redirects. - A unique ID to identify this subscription. Can be used to target specific - subscriptions in update operations when a customer has multiple products - with the same plan. + A unique ID to identify this subscription. Can be used to target specific subscriptions in update operations when a customer has multiple products with the same plan. @@ -317,24 +305,19 @@ This is useful for attaching custom metadata to the Stripe subscription created - URL to redirect to after successful checkout. + URL to redirect to after successful checkout. - Only applicable when the customer has an existing Stripe subscription. If - true, creates a new separate subscription instead of merging into the - existing one. + Only applicable when the customer has an existing Stripe subscription. If true, creates a new separate subscription instead of merging into the existing one. - When the plan change should take effect. 'immediate' applies now, - 'end_of_cycle' schedules for the end of the current billing cycle. By - default, upgrades are immediate and downgrades are scheduled. + When the plan change should take effect. 'immediate' applies now, 'end_of_cycle' schedules for the end of the current billing cycle. By default, upgrades are immediate and downgrades are scheduled. - Additional parameters to pass into the creation of the Stripe checkout - session. + Additional parameters to pass into the creation of the Stripe checkout session. @@ -352,8 +335,7 @@ This is useful for attaching custom metadata to the Stripe subscription created - The processor subscription ID to link. Use this to attach an existing Stripe - subscription instead of creating a new one. + The processor subscription ID to link. Use this to attach an existing Stripe subscription instead of creating a new one. @@ -384,14 +366,15 @@ This is useful for attaching custom metadata to the Stripe subscription created + ### Response - The ID of the customer. + The ID of the customer. - The ID of the entity, if the plan was attached to an entity. + The ID of the entity, if the plan was attached to an entity. @@ -421,8 +404,7 @@ This is useful for attaching custom metadata to the Stripe subscription created - URL to redirect the customer to complete payment. Null if no payment action - is required. + URL to redirect the customer to complete payment. Null if no payment action is required. @@ -439,6 +421,7 @@ This is useful for attaching custom metadata to the Stripe subscription created + ```json 200 { diff --git a/apps/docs/mintlify/api-reference/billing/billingUpdate.mdx b/apps/docs/mintlify/api-reference/billing/billingUpdate.mdx index 41209587e..4d4a633f1 100644 --- a/apps/docs/mintlify/api-reference/billing/billingUpdate.mdx +++ b/apps/docs/mintlify/api-reference/billing/billingUpdate.mdx @@ -265,6 +265,16 @@ const response = await autumn.billing.update({ If true, the subscription is updated internally without applying billing changes in Stripe. + + Controls whether balances should be recalculated during the subscription update. + + + If true, recalculates balances during the subscription update. Only applicable when updating feature quantities. + + + + + ### Response diff --git a/apps/docs/mintlify/api-reference/billing/multiAttach.mdx b/apps/docs/mintlify/api-reference/billing/multiAttach.mdx index 056698d30..8ca9a27e2 100644 --- a/apps/docs/mintlify/api-reference/billing/multiAttach.mdx +++ b/apps/docs/mintlify/api-reference/billing/multiAttach.mdx @@ -347,6 +347,32 @@ import { DynamicResponseExample } from "/components/dynamic-response-example.jsx + + List of usage alert configurations per feature. + + + The feature ID this alert applies to. If omitted, the alert applies globally. + + + + Whether this usage alert is enabled. + + + + The threshold value that triggers the alert. For usage, this is an absolute count. For usage_percentage, this is a percentage (0-100). + + + + Whether the threshold is an absolute usage count or a percentage of the usage allowance. + + + + Optional user-defined label to distinguish multiple alerts on the same feature. + + + + + @@ -384,6 +410,32 @@ import { DynamicResponseExample } from "/components/dynamic-response-example.jsx + + List of usage alert configurations per feature. + + + The feature ID this alert applies to. If omitted, the alert applies globally. + + + + Whether this usage alert is enabled. + + + + The threshold value that triggers the alert. For usage, this is an absolute count. For usage_percentage, this is a percentage (0-100). + + + + Whether the threshold is an absolute usage count or a percentage of the usage allowance. + + + + Optional user-defined label to distinguish multiple alerts on the same feature. + + + + + diff --git a/apps/docs/mintlify/api-reference/billing/previewAttach.mdx b/apps/docs/mintlify/api-reference/billing/previewAttach.mdx index 9fa53e6be..45c72fc71 100644 --- a/apps/docs/mintlify/api-reference/billing/previewAttach.mdx +++ b/apps/docs/mintlify/api-reference/billing/previewAttach.mdx @@ -796,6 +796,14 @@ import { DynamicResponseExample } from "/components/dynamic-response-example.jsx When this change takes effect, in milliseconds since the Unix epoch, or null if it applies immediately. + + When this plan was canceled, in milliseconds since the Unix epoch, or null if it is not canceled. + + + + When this plan expires, in milliseconds since the Unix epoch, or null if it does not expire. + + @@ -1099,6 +1107,14 @@ import { DynamicResponseExample } from "/components/dynamic-response-example.jsx When this change takes effect, in milliseconds since the Unix epoch, or null if it applies immediately. + + When this plan was canceled, in milliseconds since the Unix epoch, or null if it is not canceled. + + + + When this plan expires, in milliseconds since the Unix epoch, or null if it does not expire. + + diff --git a/apps/docs/mintlify/api-reference/billing/previewMultiAttach.mdx b/apps/docs/mintlify/api-reference/billing/previewMultiAttach.mdx index e51b1e666..378b81392 100644 --- a/apps/docs/mintlify/api-reference/billing/previewMultiAttach.mdx +++ b/apps/docs/mintlify/api-reference/billing/previewMultiAttach.mdx @@ -347,6 +347,32 @@ import { DynamicResponseExample } from "/components/dynamic-response-example.jsx + + List of usage alert configurations per feature. + + + The feature ID this alert applies to. If omitted, the alert applies globally. + + + + Whether this usage alert is enabled. + + + + The threshold value that triggers the alert. For usage, this is an absolute count. For usage_percentage, this is a percentage (0-100). + + + + Whether the threshold is an absolute usage count or a percentage of the usage allowance. + + + + Optional user-defined label to distinguish multiple alerts on the same feature. + + + + + @@ -384,6 +410,32 @@ import { DynamicResponseExample } from "/components/dynamic-response-example.jsx + + List of usage alert configurations per feature. + + + The feature ID this alert applies to. If omitted, the alert applies globally. + + + + Whether this usage alert is enabled. + + + + The threshold value that triggers the alert. For usage, this is an absolute count. For usage_percentage, this is a percentage (0-100). + + + + Whether the threshold is an absolute usage count or a percentage of the usage allowance. + + + + Optional user-defined label to distinguish multiple alerts on the same feature. + + + + + @@ -887,6 +939,14 @@ import { DynamicResponseExample } from "/components/dynamic-response-example.jsx When this change takes effect, in milliseconds since the Unix epoch, or null if it applies immediately. + + When this plan was canceled, in milliseconds since the Unix epoch, or null if it is not canceled. + + + + When this plan expires, in milliseconds since the Unix epoch, or null if it does not expire. + + @@ -1190,6 +1250,14 @@ import { DynamicResponseExample } from "/components/dynamic-response-example.jsx When this change takes effect, in milliseconds since the Unix epoch, or null if it applies immediately. + + When this plan was canceled, in milliseconds since the Unix epoch, or null if it is not canceled. + + + + When this plan expires, in milliseconds since the Unix epoch, or null if it does not expire. + + diff --git a/apps/docs/mintlify/api-reference/billing/previewUpdate.mdx b/apps/docs/mintlify/api-reference/billing/previewUpdate.mdx index 5f861ef42..e4c259a8d 100644 --- a/apps/docs/mintlify/api-reference/billing/previewUpdate.mdx +++ b/apps/docs/mintlify/api-reference/billing/previewUpdate.mdx @@ -231,6 +231,16 @@ import { DynamicResponseExample } from "/components/dynamic-response-example.jsx If true, the subscription is updated internally without applying billing changes in Stripe. + + Controls whether balances should be recalculated during the subscription update. + + + If true, recalculates balances during the subscription update. Only applicable when updating feature quantities. + + + + + ### Response @@ -728,6 +738,14 @@ import { DynamicResponseExample } from "/components/dynamic-response-example.jsx When this change takes effect, in milliseconds since the Unix epoch, or null if it applies immediately. + + When this plan was canceled, in milliseconds since the Unix epoch, or null if it is not canceled. + + + + When this plan expires, in milliseconds since the Unix epoch, or null if it does not expire. + + @@ -1031,6 +1049,14 @@ import { DynamicResponseExample } from "/components/dynamic-response-example.jsx When this change takes effect, in milliseconds since the Unix epoch, or null if it applies immediately. + + When this plan was canceled, in milliseconds since the Unix epoch, or null if it is not canceled. + + + + When this plan expires, in milliseconds since the Unix epoch, or null if it does not expire. + + diff --git a/apps/docs/mintlify/api-reference/customers/getOrCreateCustomer.mdx b/apps/docs/mintlify/api-reference/customers/getOrCreateCustomer.mdx index 77beac59b..23440c961 100644 --- a/apps/docs/mintlify/api-reference/customers/getOrCreateCustomer.mdx +++ b/apps/docs/mintlify/api-reference/customers/getOrCreateCustomer.mdx @@ -110,6 +110,32 @@ import { DynamicResponseExample } from "/components/dynamic-response-example.jsx + + List of usage alert configurations per feature. + + + The feature ID this alert applies to. If omitted, the alert applies globally. + + + + Whether this usage alert is enabled. + + + + The threshold value that triggers the alert. For usage, this is an absolute count. For usage_percentage, this is a percentage (0-100). + + + + Whether the threshold is an absolute usage count or a percentage of the usage allowance. + + + + Optional user-defined label to distinguish multiple alerts on the same feature. + + + + + @@ -217,6 +243,32 @@ import { DynamicResponseExample } from "/components/dynamic-response-example.jsx + + List of usage alert configurations per feature. + + + The feature ID this alert applies to. If omitted, the alert applies globally. + + + + Whether this usage alert is enabled. + + + + The threshold value that triggers the alert. For usage, this is an absolute count. For usage_percentage, this is a percentage (0-100). + + + + Whether the threshold is an absolute usage count or a percentage of the usage allowance. + + + + Optional user-defined label to distinguish multiple alerts on the same feature. + + + + + diff --git a/apps/docs/mintlify/api-reference/customers/listCustomers.mdx b/apps/docs/mintlify/api-reference/customers/listCustomers.mdx index 3a269957c..5ff98dedd 100644 --- a/apps/docs/mintlify/api-reference/customers/listCustomers.mdx +++ b/apps/docs/mintlify/api-reference/customers/listCustomers.mdx @@ -138,6 +138,32 @@ import { DynamicResponseExample } from "/components/dynamic-response-example.jsx + + List of usage alert configurations per feature. + + + The feature ID this alert applies to. If omitted, the alert applies globally. + + + + Whether this usage alert is enabled. + + + + The threshold value that triggers the alert. For usage, this is an absolute count. For usage_percentage, this is a percentage (0-100). + + + + Whether the threshold is an absolute usage count or a percentage of the usage allowance. + + + + Optional user-defined label to distinguish multiple alerts on the same feature. + + + + + diff --git a/apps/docs/mintlify/api-reference/customers/updateCustomer.mdx b/apps/docs/mintlify/api-reference/customers/updateCustomer.mdx index d58f82e54..da1b6ce1c 100644 --- a/apps/docs/mintlify/api-reference/customers/updateCustomer.mdx +++ b/apps/docs/mintlify/api-reference/customers/updateCustomer.mdx @@ -98,6 +98,32 @@ import { DynamicResponseExample } from "/components/dynamic-response-example.jsx + + List of usage alert configurations per feature. + + + The feature ID this alert applies to. If omitted, the alert applies globally. + + + + Whether this usage alert is enabled. + + + + The threshold value that triggers the alert. For usage, this is an absolute count. For usage_percentage, this is a percentage (0-100). + + + + Whether the threshold is an absolute usage count or a percentage of the usage allowance. + + + + Optional user-defined label to distinguish multiple alerts on the same feature. + + + + + @@ -205,6 +231,32 @@ import { DynamicResponseExample } from "/components/dynamic-response-example.jsx + + List of usage alert configurations per feature. + + + The feature ID this alert applies to. If omitted, the alert applies globally. + + + + Whether this usage alert is enabled. + + + + The threshold value that triggers the alert. For usage, this is an absolute count. For usage_percentage, this is a percentage (0-100). + + + + Whether the threshold is an absolute usage count or a percentage of the usage allowance. + + + + Optional user-defined label to distinguish multiple alerts on the same feature. + + + + + diff --git a/apps/docs/mintlify/api-reference/entities/createEntity.mdx b/apps/docs/mintlify/api-reference/entities/createEntity.mdx index e382339cc..8a1af6506 100644 --- a/apps/docs/mintlify/api-reference/entities/createEntity.mdx +++ b/apps/docs/mintlify/api-reference/entities/createEntity.mdx @@ -38,6 +38,32 @@ import { DynamicResponseExample } from "/components/dynamic-response-example.jsx + + List of usage alert configurations per feature. + + + The feature ID this alert applies to. If omitted, the alert applies globally. + + + + Whether this usage alert is enabled. + + + + The threshold value that triggers the alert. For usage, this is an absolute count. For usage_percentage, this is a percentage (0-100). + + + + Whether the threshold is an absolute usage count or a percentage of the usage allowance. + + + + Optional user-defined label to distinguish multiple alerts on the same feature. + + + + + @@ -137,6 +163,32 @@ import { DynamicResponseExample } from "/components/dynamic-response-example.jsx + + List of usage alert configurations per feature. + + + The feature ID this alert applies to. If omitted, the alert applies globally. + + + + Whether this usage alert is enabled. + + + + The threshold value that triggers the alert. For usage, this is an absolute count. For usage_percentage, this is a percentage (0-100). + + + + Whether the threshold is an absolute usage count or a percentage of the usage allowance. + + + + Optional user-defined label to distinguish multiple alerts on the same feature. + + + + + @@ -1101,6 +1153,32 @@ import { DynamicResponseExample } from "/components/dynamic-response-example.jsx + + List of usage alert configurations per feature. + + + The feature ID this alert applies to. If omitted, the alert applies globally. + + + + Whether this usage alert is enabled. + + + + The threshold value that triggers the alert. For usage, this is an absolute count. For usage_percentage, this is a percentage (0-100). + + + + Whether the threshold is an absolute usage count or a percentage of the usage allowance. + + + + Optional user-defined label to distinguish multiple alerts on the same feature. + + + + + diff --git a/apps/docs/mintlify/api-reference/entities/getEntity.mdx b/apps/docs/mintlify/api-reference/entities/getEntity.mdx index 27a9912ca..e3385c575 100644 --- a/apps/docs/mintlify/api-reference/entities/getEntity.mdx +++ b/apps/docs/mintlify/api-reference/entities/getEntity.mdx @@ -967,6 +967,32 @@ import { DynamicResponseExample } from "/components/dynamic-response-example.jsx + + List of usage alert configurations per feature. + + + The feature ID this alert applies to. If omitted, the alert applies globally. + + + + Whether this usage alert is enabled. + + + + The threshold value that triggers the alert. For usage, this is an absolute count. For usage_percentage, this is a percentage (0-100). + + + + Whether the threshold is an absolute usage count or a percentage of the usage allowance. + + + + Optional user-defined label to distinguish multiple alerts on the same feature. + + + + + diff --git a/apps/docs/mintlify/api-reference/entities/updateEntity.mdx b/apps/docs/mintlify/api-reference/entities/updateEntity.mdx index 6c26b0f9b..2e72a9299 100644 --- a/apps/docs/mintlify/api-reference/entities/updateEntity.mdx +++ b/apps/docs/mintlify/api-reference/entities/updateEntity.mdx @@ -38,6 +38,32 @@ import { DynamicResponseExample } from "/components/dynamic-response-example.jsx + + List of usage alert configurations per feature. + + + The feature ID this alert applies to. If omitted, the alert applies globally. + + + + Whether this usage alert is enabled. + + + + The threshold value that triggers the alert. For usage, this is an absolute count. For usage_percentage, this is a percentage (0-100). + + + + Whether the threshold is an absolute usage count or a percentage of the usage allowance. + + + + Optional user-defined label to distinguish multiple alerts on the same feature. + + + + + @@ -991,6 +1017,32 @@ import { DynamicResponseExample } from "/components/dynamic-response-example.jsx + + List of usage alert configurations per feature. + + + The feature ID this alert applies to. If omitted, the alert applies globally. + + + + Whether this usage alert is enabled. + + + + The threshold value that triggers the alert. For usage, this is an absolute count. For usage_percentage, this is a percentage (0-100). + + + + Whether the threshold is an absolute usage count or a percentage of the usage allowance. + + + + Optional user-defined label to distinguish multiple alerts on the same feature. + + + + + diff --git a/apps/docs/mintlify/api-reference/webhooks/balancesLimitReached.mdx b/apps/docs/mintlify/api-reference/webhooks/balancesLimitReached.mdx new file mode 100644 index 000000000..781e60296 --- /dev/null +++ b/apps/docs/mintlify/api-reference/webhooks/balancesLimitReached.mdx @@ -0,0 +1,22 @@ +--- +title: "Limit Reached" +openapi: "api/openapi.yml webhook balances.limit_reached" +--- + +### Payload Fields + + + The ID of the customer who hit the limit. + + + + The entity ID, if the limit was reached on a specific entity. + + + + The feature ID whose limit was reached. + + + + Which limit was hit: included allowance, max purchase cap, or spend limit. + diff --git a/apps/docs/mintlify/api-reference/webhooks/balancesUsageAlertTriggered.mdx b/apps/docs/mintlify/api-reference/webhooks/balancesUsageAlertTriggered.mdx new file mode 100644 index 000000000..a1852e162 --- /dev/null +++ b/apps/docs/mintlify/api-reference/webhooks/balancesUsageAlertTriggered.mdx @@ -0,0 +1,36 @@ +--- +title: "Usage Alert Triggered" +openapi: "api/openapi.yml webhook balances.usage_alert_triggered" +--- + +### Payload Fields + + + The ID of the customer whose usage alert was triggered. + + + + The feature ID the alert applies to. + + + + The entity ID the alert applies to, if the usage was entity-scoped. + + + + Details of the usage alert that was triggered. + + + User-defined label for the alert, if provided. + + + + The threshold value that was crossed. + + + + Whether the threshold is an absolute usage count or a percentage. + + + + diff --git a/apps/docs/mintlify/api-reference/webhooks/vercelResourcesDeleted.mdx b/apps/docs/mintlify/api-reference/webhooks/vercelResourcesDeleted.mdx new file mode 100644 index 000000000..3640f088a --- /dev/null +++ b/apps/docs/mintlify/api-reference/webhooks/vercelResourcesDeleted.mdx @@ -0,0 +1,20 @@ +--- +title: "Resource Deleted" +openapi: "api/openapi.yml webhook vercel.resources.deleted" +--- + +### Payload Fields + + + The resource that was deleted. + + + The unique identifier of the deleted resource. + + + + + + + The Vercel integration configuration ID. + diff --git a/apps/docs/mintlify/api-reference/webhooks/vercelResourcesProvisioned.mdx b/apps/docs/mintlify/api-reference/webhooks/vercelResourcesProvisioned.mdx new file mode 100644 index 000000000..9add61c97 --- /dev/null +++ b/apps/docs/mintlify/api-reference/webhooks/vercelResourcesProvisioned.mdx @@ -0,0 +1,28 @@ +--- +title: "Resource Provisioned" +openapi: "api/openapi.yml webhook vercel.resources.provisioned" +--- + +### Payload Fields + + + The resource that was provisioned. + + + The unique identifier of the provisioned resource. + + + + The display name of the provisioned resource. + + + + + + + The Vercel integration configuration ID. + + + + An access token that can be used to patch the resource's secrets. + diff --git a/apps/docs/mintlify/api-reference/webhooks/vercelResourcesRotateSecrets.mdx b/apps/docs/mintlify/api-reference/webhooks/vercelResourcesRotateSecrets.mdx new file mode 100644 index 000000000..74f8e58c6 --- /dev/null +++ b/apps/docs/mintlify/api-reference/webhooks/vercelResourcesRotateSecrets.mdx @@ -0,0 +1,24 @@ +--- +title: "Rotate Secrets" +openapi: "api/openapi.yml webhook vercel.resources.rotate_secrets" +--- + +### Payload Fields + + + The resource whose secrets should be rotated. + + + The unique identifier of the resource. + + + + + + + The Vercel integration configuration ID. + + + + The raw request body from Vercel's rotation request. + diff --git a/apps/docs/mintlify/api-reference/webhooks/vercelWebhooksEvent.mdx b/apps/docs/mintlify/api-reference/webhooks/vercelWebhooksEvent.mdx new file mode 100644 index 000000000..1b08b751f --- /dev/null +++ b/apps/docs/mintlify/api-reference/webhooks/vercelWebhooksEvent.mdx @@ -0,0 +1,14 @@ +--- +title: "Webhook Event" +openapi: "api/openapi.yml webhook vercel.webhooks.event" +--- + +### Payload Fields + + + The Vercel integration configuration ID. + + + + The raw Vercel webhook event payload. + diff --git a/apps/docs/mintlify/api/openapi.yml b/apps/docs/mintlify/api/openapi.yml index c907f5ddf..16dae50d0 100644 --- a/apps/docs/mintlify/api/openapi.yml +++ b/apps/docs/mintlify/api/openapi.yml @@ -86,6 +86,7 @@ components: - day - week - month + type: string description: The time interval for the purchase limit window. interval_count: type: number @@ -122,6 +123,40 @@ components: minimum: 0 description: Maximum allowed overage spend for the target feature. description: List of overage spend limits per feature. + usage_alerts: + type: array + items: + type: object + properties: + feature_id: + type: string + description: The feature ID this alert applies to. If omitted, the alert applies + globally. + enabled: + type: boolean + default: true + description: Whether this usage alert is enabled. + threshold: + type: number + minimum: 0 + description: The threshold value that triggers the alert. For usage, this is an + absolute count. For usage_percentage, this is a percentage + (0-100). + threshold_type: + enum: + - usage + - usage_percentage + type: string + description: Whether the threshold is an absolute usage count or a percentage of + the usage allowance. + name: + type: string + description: Optional user-defined label to distinguish multiple alerts on the + same feature. + required: + - threshold + - threshold_type + description: List of usage alert configurations per feature. description: Billing controls for the customer (auto top-ups, etc.) title: CustomerData description: Customer details to set when creating a customer @@ -161,6 +196,7 @@ components: enum: - sandbox - live + type: string description: The environment this customer was created in. metadata: type: object @@ -203,6 +239,7 @@ components: - day - week - month + type: string description: The time interval for the purchase limit window. interval_count: type: number @@ -239,6 +276,40 @@ components: minimum: 0 description: Maximum allowed overage spend for the target feature. description: List of overage spend limits per feature. + usage_alerts: + type: array + items: + type: object + properties: + feature_id: + type: string + description: The feature ID this alert applies to. If omitted, the alert applies + globally. + enabled: + type: boolean + default: true + description: Whether this usage alert is enabled. + threshold: + type: number + minimum: 0 + description: The threshold value that triggers the alert. For usage, this is an + absolute count. For usage_percentage, this is a percentage + (0-100). + threshold_type: + enum: + - usage + - usage_percentage + type: string + description: Whether the threshold is an absolute usage count or a percentage of + the usage allowance. + name: + type: string + description: Optional user-defined label to distinguish multiple alerts on the + same feature. + required: + - threshold + - threshold_type + description: List of usage alert configurations per feature. description: Billing controls for the customer (auto top-ups, etc.) subscriptions: type: array @@ -266,6 +337,7 @@ components: enum: - active - scheduled + type: string description: Current status of the subscription. past_due: type: boolean @@ -393,6 +465,7 @@ components: - boolean - metered - credit_system + type: string description: "Feature type: 'boolean' for on/off access, 'metered' for usage-tracked features, 'credit_system' for unified credit pools." @@ -530,6 +603,7 @@ components: enum: - sandbox - live + type: string description: The environment (sandbox/live) required: - id @@ -575,6 +649,7 @@ components: - fixed_discount - free_product - invoice_credits + type: string description: The type of reward discount_value: type: number @@ -584,6 +659,7 @@ components: - one_off - months - forever + type: string description: How long the discount lasts duration_value: anyOf: @@ -782,6 +858,7 @@ components: - quarter - semi_annual - year + type: string description: Billing interval (e.g. 'month', 'year'). interval_count: type: number @@ -831,6 +908,7 @@ components: - single_use - continuous_use - credit_system + type: string description: The type of the feature display: anyOf: @@ -895,6 +973,7 @@ components: - quarter - semi_annual - year + type: string description: The interval at which the feature balance resets (e.g. 'month', 'year'). For consumable features, usage resets to 0 and included units are restored. @@ -928,6 +1007,7 @@ components: enum: - graduated - volume + type: string interval: enum: - one_off @@ -936,6 +1016,7 @@ components: - quarter - semi_annual - year + type: string description: Billing interval for this price. For consumable features, should match reset.interval. interval_count: @@ -950,6 +1031,7 @@ components: enum: - prepaid - usage_based + type: string description: "'prepaid' for features like seats where customers pay upfront, 'usage_based' for pay-as-you-go after included usage." max_purchase: @@ -992,6 +1074,7 @@ components: enum: - month - forever + type: string description: When rolled over units expire. expiry_duration_length: type: number @@ -1020,6 +1103,7 @@ components: - day - month - year + type: string description: Unit of time for the trial duration ('day', 'month', 'year'). card_required: type: boolean @@ -1038,6 +1122,7 @@ components: enum: - sandbox - live + type: string description: Environment this plan belongs to ('sandbox' or 'live'). archived: type: boolean @@ -1060,6 +1145,7 @@ components: enum: - active - scheduled + type: string description: The customer's current status with this plan. 'active' if attached, 'scheduled' if pending activation. canceling: @@ -1076,6 +1162,7 @@ components: - downgrade - none - purchase + type: string description: The action that would occur if this plan were attached to the customer. required: @@ -1115,6 +1202,7 @@ components: - boolean - metered - credit_system + type: string description: "Feature type: 'boolean' for on/off access, 'metered' for usage-tracked features, 'credit_system' for unified credit pools." @@ -1244,6 +1332,7 @@ components: - quarter - semi_annual - year + type: string - const: multiple description: The reset interval (hour, day, week, month, etc.) or 'multiple' if combined from different intervals. @@ -1278,6 +1367,7 @@ components: enum: - graduated - volume + type: string description: "How tiers are applied: graduated (split across bands) or volume (flat rate for the matched tier)." billing_units: @@ -1287,6 +1377,7 @@ components: enum: - prepaid - usage_based + type: string description: Whether usage is prepaid or billed pay-per-use. max_purchase: anyOf: @@ -1463,6 +1554,7 @@ paths: - day - week - month + type: string description: The time interval for the purchase limit window. interval_count: type: number @@ -1499,6 +1591,40 @@ paths: minimum: 0 description: Maximum allowed overage spend for the target feature. description: List of overage spend limits per feature. + usage_alerts: + type: array + items: + type: object + properties: + feature_id: + type: string + description: The feature ID this alert applies to. If omitted, the alert applies + globally. + enabled: + type: boolean + default: true + description: Whether this usage alert is enabled. + threshold: + type: number + minimum: 0 + description: The threshold value that triggers the alert. For usage, this is an + absolute count. For usage_percentage, this is a + percentage (0-100). + threshold_type: + enum: + - usage + - usage_percentage + type: string + description: Whether the threshold is an absolute usage count or a percentage of + the usage allowance. + name: + type: string + description: Optional user-defined label to distinguish multiple alerts on the + same feature. + required: + - threshold + - threshold_type + description: List of usage alert configurations per feature. description: Billing controls for the customer (auto top-ups, etc.) expand: type: array @@ -1602,6 +1728,7 @@ paths: enum: - active - scheduled + type: string description: Filter by customer product status. Defaults to active and scheduled search: type: string @@ -1659,6 +1786,7 @@ paths: enum: - sandbox - live + type: string description: The environment this customer was created in. metadata: type: object @@ -1701,6 +1829,7 @@ paths: - day - week - month + type: string description: The time interval for the purchase limit window. interval_count: type: number @@ -1737,6 +1866,40 @@ paths: minimum: 0 description: Maximum allowed overage spend for the target feature. description: List of overage spend limits per feature. + usage_alerts: + type: array + items: + type: object + properties: + feature_id: + type: string + description: The feature ID this alert applies to. If omitted, the alert applies + globally. + enabled: + type: boolean + default: true + description: Whether this usage alert is enabled. + threshold: + type: number + minimum: 0 + description: The threshold value that triggers the alert. For usage, this is an + absolute count. For usage_percentage, this + is a percentage (0-100). + threshold_type: + enum: + - usage + - usage_percentage + type: string + description: Whether the threshold is an absolute usage count or a percentage of + the usage allowance. + name: + type: string + description: Optional user-defined label to distinguish multiple alerts on the + same feature. + required: + - threshold + - threshold_type + description: List of usage alert configurations per feature. description: Billing controls for the customer (auto top-ups, etc.) subscriptions: type: array @@ -1764,6 +1927,7 @@ paths: enum: - active - scheduled + type: string description: Current status of the subscription. past_due: type: boolean @@ -1892,6 +2056,7 @@ paths: - boolean - metered - credit_system + type: string description: "Feature type: 'boolean' for on/off access, 'metered' for usage-tracked features, 'credit_system' for unified credit pools." @@ -2221,6 +2386,7 @@ paths: - day - week - month + type: string description: The time interval for the purchase limit window. interval_count: type: number @@ -2257,6 +2423,40 @@ paths: minimum: 0 description: Maximum allowed overage spend for the target feature. description: List of overage spend limits per feature. + usage_alerts: + type: array + items: + type: object + properties: + feature_id: + type: string + description: The feature ID this alert applies to. If omitted, the alert applies + globally. + enabled: + type: boolean + default: true + description: Whether this usage alert is enabled. + threshold: + type: number + minimum: 0 + description: The threshold value that triggers the alert. For usage, this is an + absolute count. For usage_percentage, this is a + percentage (0-100). + threshold_type: + enum: + - usage + - usage_percentage + type: string + description: Whether the threshold is an absolute usage count or a percentage of + the usage allowance. + name: + type: string + description: Optional user-defined label to distinguish multiple alerts on the + same feature. + required: + - threshold + - threshold_type + description: List of usage alert configurations per feature. description: Billing controls for the customer (auto top-ups, etc.) new_customer_id: $ref: "#/components/schemas/CustomerId" @@ -2311,6 +2511,7 @@ paths: enum: - sandbox - live + type: string description: The environment this customer was created in. metadata: type: object @@ -2353,6 +2554,7 @@ paths: - day - week - month + type: string description: The time interval for the purchase limit window. interval_count: type: number @@ -2389,6 +2591,40 @@ paths: minimum: 0 description: Maximum allowed overage spend for the target feature. description: List of overage spend limits per feature. + usage_alerts: + type: array + items: + type: object + properties: + feature_id: + type: string + description: The feature ID this alert applies to. If omitted, the alert applies + globally. + enabled: + type: boolean + default: true + description: Whether this usage alert is enabled. + threshold: + type: number + minimum: 0 + description: The threshold value that triggers the alert. For usage, this is an + absolute count. For usage_percentage, this is a + percentage (0-100). + threshold_type: + enum: + - usage + - usage_percentage + type: string + description: Whether the threshold is an absolute usage count or a percentage of + the usage allowance. + name: + type: string + description: Optional user-defined label to distinguish multiple alerts on the + same feature. + required: + - threshold + - threshold_type + description: List of usage alert configurations per feature. description: Billing controls for the customer (auto top-ups, etc.) subscriptions: type: array @@ -2416,6 +2652,7 @@ paths: enum: - active - scheduled + type: string description: Current status of the subscription. past_due: type: boolean @@ -2544,6 +2781,7 @@ paths: - boolean - metered - credit_system + type: string description: "Feature type: 'boolean' for on/off access, 'metered' for usage-tracked features, 'credit_system' for unified credit pools." @@ -2853,6 +3091,7 @@ paths: - quarter - semi_annual - year + type: string description: Billing interval (e.g. 'month', 'year'). interval_count: type: number @@ -2891,6 +3130,7 @@ paths: - quarter - semi_annual - year + type: string description: Interval at which balance resets (e.g. 'month', 'year'). For consumable features only. interval_count: @@ -2927,6 +3167,7 @@ paths: enum: - graduated - volume + type: string interval: enum: - one_off @@ -2935,6 +3176,7 @@ paths: - quarter - semi_annual - year + type: string description: Billing interval. For consumable features, should match reset.interval. interval_count: @@ -2950,6 +3192,7 @@ paths: enum: - prepaid - usage_based + type: string description: "'prepaid' for upfront payment (seats), 'usage_based' for pay-as-you-go." max_purchase: @@ -2969,6 +3212,7 @@ paths: - prorate_immediately - prorate_next_cycle - bill_next_cycle + type: string description: Billing behavior when quantity increases mid-cycle. on_decrease: enum: @@ -2977,6 +3221,7 @@ paths: - prorate_next_cycle - none - no_prorations + type: string description: Credit behavior when quantity decreases mid-cycle. required: - on_increase @@ -2993,6 +3238,7 @@ paths: enum: - month - forever + type: string description: When rolled over units expire. expiry_duration_length: type: number @@ -3019,6 +3265,7 @@ paths: - day - month - year + type: string default: month description: Unit of time for the trial ('day', 'month', 'year'). card_required: @@ -3125,6 +3372,7 @@ paths: - quarter - semi_annual - year + type: string description: Billing interval (e.g. 'month', 'year'). interval_count: type: number @@ -3174,6 +3422,7 @@ paths: - single_use - continuous_use - credit_system + type: string description: The type of the feature display: anyOf: @@ -3238,6 +3487,7 @@ paths: - quarter - semi_annual - year + type: string description: The interval at which the feature balance resets (e.g. 'month', 'year'). For consumable features, usage resets to 0 and included units are restored. @@ -3271,6 +3521,7 @@ paths: enum: - graduated - volume + type: string interval: enum: - one_off @@ -3279,6 +3530,7 @@ paths: - quarter - semi_annual - year + type: string description: Billing interval for this price. For consumable features, should match reset.interval. interval_count: @@ -3294,6 +3546,7 @@ paths: enum: - prepaid - usage_based + type: string description: "'prepaid' for features like seats where customers pay upfront, 'usage_based' for pay-as-you-go after included usage." @@ -3337,6 +3590,7 @@ paths: enum: - month - forever + type: string description: When rolled over units expire. expiry_duration_length: type: number @@ -3365,6 +3619,7 @@ paths: - day - month - year + type: string description: Unit of time for the trial duration ('day', 'month', 'year'). card_required: type: boolean @@ -3383,6 +3638,7 @@ paths: enum: - sandbox - live + type: string description: Environment this plan belongs to ('sandbox' or 'live'). archived: type: boolean @@ -3405,6 +3661,7 @@ paths: enum: - active - scheduled + type: string description: The customer's current status with this plan. 'active' if attached, 'scheduled' if pending activation. canceling: @@ -3421,6 +3678,7 @@ paths: - downgrade - none - purchase + type: string description: The action that would occur if this plan were attached to the customer. required: @@ -3629,6 +3887,7 @@ paths: - quarter - semi_annual - year + type: string description: Billing interval (e.g. 'month', 'year'). interval_count: type: number @@ -3678,6 +3937,7 @@ paths: - single_use - continuous_use - credit_system + type: string description: The type of the feature display: anyOf: @@ -3742,6 +4002,7 @@ paths: - quarter - semi_annual - year + type: string description: The interval at which the feature balance resets (e.g. 'month', 'year'). For consumable features, usage resets to 0 and included units are restored. @@ -3775,6 +4036,7 @@ paths: enum: - graduated - volume + type: string interval: enum: - one_off @@ -3783,6 +4045,7 @@ paths: - quarter - semi_annual - year + type: string description: Billing interval for this price. For consumable features, should match reset.interval. interval_count: @@ -3798,6 +4061,7 @@ paths: enum: - prepaid - usage_based + type: string description: "'prepaid' for features like seats where customers pay upfront, 'usage_based' for pay-as-you-go after included usage." @@ -3841,6 +4105,7 @@ paths: enum: - month - forever + type: string description: When rolled over units expire. expiry_duration_length: type: number @@ -3869,6 +4134,7 @@ paths: - day - month - year + type: string description: Unit of time for the trial duration ('day', 'month', 'year'). card_required: type: boolean @@ -3887,6 +4153,7 @@ paths: enum: - sandbox - live + type: string description: Environment this plan belongs to ('sandbox' or 'live'). archived: type: boolean @@ -3909,6 +4176,7 @@ paths: enum: - active - scheduled + type: string description: The customer's current status with this plan. 'active' if attached, 'scheduled' if pending activation. canceling: @@ -3925,6 +4193,7 @@ paths: - downgrade - none - purchase + type: string description: The action that would occur if this plan were attached to the customer. required: @@ -4112,6 +4381,7 @@ paths: - quarter - semi_annual - year + type: string description: Billing interval (e.g. 'month', 'year'). interval_count: type: number @@ -4161,6 +4431,7 @@ paths: - single_use - continuous_use - credit_system + type: string description: The type of the feature display: anyOf: @@ -4225,6 +4496,7 @@ paths: - quarter - semi_annual - year + type: string description: The interval at which the feature balance resets (e.g. 'month', 'year'). For consumable features, usage resets to 0 and included units @@ -4259,6 +4531,7 @@ paths: enum: - graduated - volume + type: string interval: enum: - one_off @@ -4267,6 +4540,7 @@ paths: - quarter - semi_annual - year + type: string description: Billing interval for this price. For consumable features, should match reset.interval. interval_count: @@ -4282,6 +4556,7 @@ paths: enum: - prepaid - usage_based + type: string description: "'prepaid' for features like seats where customers pay upfront, 'usage_based' for pay-as-you-go after included usage." @@ -4326,6 +4601,7 @@ paths: enum: - month - forever + type: string description: When rolled over units expire. expiry_duration_length: type: number @@ -4355,6 +4631,7 @@ paths: - day - month - year + type: string description: Unit of time for the trial duration ('day', 'month', 'year'). card_required: type: boolean @@ -4373,6 +4650,7 @@ paths: enum: - sandbox - live + type: string description: Environment this plan belongs to ('sandbox' or 'live'). archived: type: boolean @@ -4395,6 +4673,7 @@ paths: enum: - active - scheduled + type: string description: The customer's current status with this plan. 'active' if attached, 'scheduled' if pending activation. canceling: @@ -4411,6 +4690,7 @@ paths: - downgrade - none - purchase + type: string description: The action that would occur if this plan were attached to the customer. required: @@ -4567,6 +4847,7 @@ paths: - quarter - semi_annual - year + type: string description: Billing interval (e.g. 'month', 'year'). interval_count: type: number @@ -4607,6 +4888,7 @@ paths: - quarter - semi_annual - year + type: string description: Interval at which balance resets (e.g. 'month', 'year'). For consumable features only. interval_count: @@ -4643,6 +4925,7 @@ paths: enum: - graduated - volume + type: string interval: enum: - one_off @@ -4651,6 +4934,7 @@ paths: - quarter - semi_annual - year + type: string description: Billing interval. For consumable features, should match reset.interval. interval_count: @@ -4666,6 +4950,7 @@ paths: enum: - prepaid - usage_based + type: string description: "'prepaid' for upfront payment (seats), 'usage_based' for pay-as-you-go." max_purchase: @@ -4685,6 +4970,7 @@ paths: - prorate_immediately - prorate_next_cycle - bill_next_cycle + type: string description: Billing behavior when quantity increases mid-cycle. on_decrease: enum: @@ -4693,6 +4979,7 @@ paths: - prorate_next_cycle - none - no_prorations + type: string description: Credit behavior when quantity decreases mid-cycle. required: - on_increase @@ -4709,6 +4996,7 @@ paths: enum: - month - forever + type: string description: When rolled over units expire. expiry_duration_length: type: number @@ -4736,6 +5024,7 @@ paths: - day - month - year + type: string default: month description: Unit of time for the trial ('day', 'month', 'year'). card_required: @@ -4827,6 +5116,7 @@ paths: - quarter - semi_annual - year + type: string description: Billing interval (e.g. 'month', 'year'). interval_count: type: number @@ -4876,6 +5166,7 @@ paths: - single_use - continuous_use - credit_system + type: string description: The type of the feature display: anyOf: @@ -4940,6 +5231,7 @@ paths: - quarter - semi_annual - year + type: string description: The interval at which the feature balance resets (e.g. 'month', 'year'). For consumable features, usage resets to 0 and included units are restored. @@ -4973,6 +5265,7 @@ paths: enum: - graduated - volume + type: string interval: enum: - one_off @@ -4981,6 +5274,7 @@ paths: - quarter - semi_annual - year + type: string description: Billing interval for this price. For consumable features, should match reset.interval. interval_count: @@ -4996,6 +5290,7 @@ paths: enum: - prepaid - usage_based + type: string description: "'prepaid' for features like seats where customers pay upfront, 'usage_based' for pay-as-you-go after included usage." @@ -5039,6 +5334,7 @@ paths: enum: - month - forever + type: string description: When rolled over units expire. expiry_duration_length: type: number @@ -5067,6 +5363,7 @@ paths: - day - month - year + type: string description: Unit of time for the trial duration ('day', 'month', 'year'). card_required: type: boolean @@ -5085,6 +5382,7 @@ paths: enum: - sandbox - live + type: string description: Environment this plan belongs to ('sandbox' or 'live'). archived: type: boolean @@ -5107,6 +5405,7 @@ paths: enum: - active - scheduled + type: string description: The customer's current status with this plan. 'active' if attached, 'scheduled' if pending activation. canceling: @@ -5123,6 +5422,7 @@ paths: - downgrade - none - purchase + type: string description: The action that would occur if this plan were attached to the customer. required: @@ -5338,6 +5638,7 @@ paths: - boolean - metered - credit_system + type: string description: The type of the feature. 'single_use' features are consumed, like API calls, tokens, or messages. 'continuous_use' features are allocated, like seats, workspaces, or projects. @@ -5423,6 +5724,7 @@ paths: - boolean - metered - credit_system + type: string description: "Feature type: 'boolean' for on/off access, 'metered' for usage-tracked features, 'credit_system' for unified credit pools." @@ -5570,6 +5872,7 @@ paths: - boolean - metered - credit_system + type: string description: "Feature type: 'boolean' for on/off access, 'metered' for usage-tracked features, 'credit_system' for unified credit pools." @@ -5699,6 +6002,7 @@ paths: - boolean - metered - credit_system + type: string description: "Feature type: 'boolean' for on/off access, 'metered' for usage-tracked features, 'credit_system' for unified credit pools." @@ -5833,6 +6137,7 @@ paths: - boolean - metered - credit_system + type: string description: The type of the feature. 'single_use' features are consumed, like API calls, tokens, or messages. 'continuous_use' features are allocated, like seats, workspaces, or projects. @@ -5918,6 +6223,7 @@ paths: - boolean - metered - credit_system + type: string description: "Feature type: 'boolean' for on/off access, 'metered' for usage-tracked features, 'credit_system' for unified credit pools." @@ -6167,6 +6473,7 @@ paths: - quarter - semi_annual - year + type: string description: Billing interval (e.g. 'month', 'year'). interval_count: type: number @@ -6208,6 +6515,7 @@ paths: - quarter - semi_annual - year + type: string description: Interval at which balance resets (e.g. 'month', 'year'). For consumable features only. interval_count: @@ -6244,6 +6552,7 @@ paths: enum: - graduated - volume + type: string interval: enum: - one_off @@ -6252,6 +6561,7 @@ paths: - quarter - semi_annual - year + type: string description: Billing interval. For consumable features, should match reset.interval. interval_count: @@ -6267,6 +6577,7 @@ paths: enum: - prepaid - usage_based + type: string description: "'prepaid' for upfront payment (seats), 'usage_based' for pay-as-you-go." max_purchase: @@ -6286,6 +6597,7 @@ paths: - prorate_immediately - prorate_next_cycle - bill_next_cycle + type: string description: Billing behavior when quantity increases mid-cycle. on_decrease: enum: @@ -6294,6 +6606,7 @@ paths: - prorate_next_cycle - none - no_prorations + type: string description: Credit behavior when quantity decreases mid-cycle. required: - on_increase @@ -6310,6 +6623,7 @@ paths: enum: - month - forever + type: string description: When rolled over units expire. expiry_duration_length: type: number @@ -6336,6 +6650,7 @@ paths: - day - month - year + type: string default: month description: Unit of time for the trial ('day', 'month', 'year'). card_required: @@ -6379,6 +6694,7 @@ paths: enum: - prorate_immediately - none + type: string description: How to handle proration when updating an existing subscription. 'prorate_immediately' charges/credits prorated amounts now, 'none' skips creating any charges. @@ -6387,6 +6703,7 @@ paths: - always - if_required - never + type: string description: Controls when to return a checkout URL. 'always' returns a URL even if payment succeeds, 'if_required' only when payment action is needed, 'never' disables redirects. @@ -6423,6 +6740,7 @@ paths: enum: - immediate - end_of_cycle + type: string description: When the plan change should take effect. 'immediate' applies now, 'end_of_cycle' schedules for the end of the current billing cycle. By default, upgrades are immediate and downgrades are @@ -6554,6 +6872,7 @@ paths: - 3ds_required - payment_method_required - payment_failed + type: string description: The type of action required to complete the payment. reason: type: string @@ -6657,6 +6976,7 @@ paths: - quarter - semi_annual - year + type: string description: Billing interval (e.g. 'month', 'year'). interval_count: type: number @@ -6698,6 +7018,7 @@ paths: - quarter - semi_annual - year + type: string description: Interval at which balance resets (e.g. 'month', 'year'). For consumable features only. interval_count: @@ -6734,6 +7055,7 @@ paths: enum: - graduated - volume + type: string interval: enum: - one_off @@ -6742,6 +7064,7 @@ paths: - quarter - semi_annual - year + type: string description: Billing interval. For consumable features, should match reset.interval. interval_count: @@ -6758,6 +7081,7 @@ paths: enum: - prepaid - usage_based + type: string description: "'prepaid' for upfront payment (seats), 'usage_based' for pay-as-you-go." max_purchase: @@ -6777,6 +7101,7 @@ paths: - prorate_immediately - prorate_next_cycle - bill_next_cycle + type: string description: Billing behavior when quantity increases mid-cycle. on_decrease: enum: @@ -6785,6 +7110,7 @@ paths: - prorate_next_cycle - none - no_prorations + type: string description: Credit behavior when quantity decreases mid-cycle. required: - on_increase @@ -6801,6 +7127,7 @@ paths: enum: - month - forever + type: string description: When rolled over units expire. expiry_duration_length: type: number @@ -6859,6 +7186,7 @@ paths: - day - month - year + type: string default: month description: Unit of time for the trial ('day', 'month', 'year'). card_required: @@ -6925,6 +7253,7 @@ paths: - always - if_required - never + type: string description: Controls when to return a checkout URL. 'always' returns a URL even if payment succeeds, 'if_required' only when payment action is needed, 'never' disables redirects. @@ -6965,6 +7294,40 @@ paths: minimum: 0 description: Maximum allowed overage spend for the target feature. description: List of overage spend limits per feature. + usage_alerts: + type: array + items: + type: object + properties: + feature_id: + type: string + description: The feature ID this alert applies to. If omitted, the alert applies + globally. + enabled: + type: boolean + default: true + description: Whether this usage alert is enabled. + threshold: + type: number + minimum: 0 + description: The threshold value that triggers the alert. For usage, this is an + absolute count. For usage_percentage, this is + a percentage (0-100). + threshold_type: + enum: + - usage + - usage_percentage + type: string + description: Whether the threshold is an absolute usage count or a percentage of + the usage allowance. + name: + type: string + description: Optional user-defined label to distinguish multiple alerts on the + same feature. + required: + - threshold + - threshold_type + description: List of usage alert configurations per feature. description: Billing controls for the entity. required: - feature_id @@ -7041,6 +7404,7 @@ paths: - 3ds_required - payment_method_required - payment_failed + type: string description: The type of action required to complete the payment. reason: type: string @@ -7195,6 +7559,7 @@ paths: - quarter - semi_annual - year + type: string description: Billing interval (e.g. 'month', 'year'). interval_count: type: number @@ -7236,6 +7601,7 @@ paths: - quarter - semi_annual - year + type: string description: Interval at which balance resets (e.g. 'month', 'year'). For consumable features only. interval_count: @@ -7272,6 +7638,7 @@ paths: enum: - graduated - volume + type: string interval: enum: - one_off @@ -7280,6 +7647,7 @@ paths: - quarter - semi_annual - year + type: string description: Billing interval. For consumable features, should match reset.interval. interval_count: @@ -7295,6 +7663,7 @@ paths: enum: - prepaid - usage_based + type: string description: "'prepaid' for upfront payment (seats), 'usage_based' for pay-as-you-go." max_purchase: @@ -7314,6 +7683,7 @@ paths: - prorate_immediately - prorate_next_cycle - bill_next_cycle + type: string description: Billing behavior when quantity increases mid-cycle. on_decrease: enum: @@ -7322,6 +7692,7 @@ paths: - prorate_next_cycle - none - no_prorations + type: string description: Credit behavior when quantity decreases mid-cycle. required: - on_increase @@ -7338,6 +7709,7 @@ paths: enum: - month - forever + type: string description: When rolled over units expire. expiry_duration_length: type: number @@ -7364,6 +7736,7 @@ paths: - day - month - year + type: string default: month description: Unit of time for the trial ('day', 'month', 'year'). card_required: @@ -7407,6 +7780,7 @@ paths: enum: - prorate_immediately - none + type: string description: How to handle proration when updating an existing subscription. 'prorate_immediately' charges/credits prorated amounts now, 'none' skips creating any charges. @@ -7415,6 +7789,7 @@ paths: - always - if_required - never + type: string description: Controls when to return a checkout URL. 'always' returns a URL even if payment succeeds, 'if_required' only when payment action is needed, 'never' disables redirects. @@ -7451,6 +7826,7 @@ paths: enum: - immediate - end_of_cycle + type: string description: When the plan change should take effect. 'immediate' applies now, 'end_of_cycle' schedules for the end of the current billing cycle. By default, upgrades are immediate and downgrades are @@ -7776,10 +8152,24 @@ paths: - type: "null" description: When this change takes effect, in milliseconds since the Unix epoch, or null if it applies immediately. + canceled_at: + anyOf: + - type: number + - type: "null" + description: When this plan was canceled, in milliseconds since the Unix epoch, + or null if it is not canceled. + expires_at: + anyOf: + - type: number + - type: "null" + description: When this plan expires, in milliseconds since the Unix epoch, or + null if it does not expire. required: - plan_id - feature_quantities - effective_at + - canceled_at + - expires_at description: Products or subscription changes being added or updated. outgoing: type: array @@ -7813,10 +8203,24 @@ paths: - type: "null" description: When this change takes effect, in milliseconds since the Unix epoch, or null if it applies immediately. + canceled_at: + anyOf: + - type: number + - type: "null" + description: When this plan was canceled, in milliseconds since the Unix epoch, + or null if it is not canceled. + expires_at: + anyOf: + - type: number + - type: "null" + description: When this plan expires, in milliseconds since the Unix epoch, or + null if it does not expire. required: - plan_id - feature_quantities - effective_at + - canceled_at + - expires_at description: Products or subscription changes being removed or ended. required: - customer_id @@ -7924,6 +8328,7 @@ paths: - quarter - semi_annual - year + type: string description: Billing interval (e.g. 'month', 'year'). interval_count: type: number @@ -7965,6 +8370,7 @@ paths: - quarter - semi_annual - year + type: string description: Interval at which balance resets (e.g. 'month', 'year'). For consumable features only. interval_count: @@ -8001,6 +8407,7 @@ paths: enum: - graduated - volume + type: string interval: enum: - one_off @@ -8009,6 +8416,7 @@ paths: - quarter - semi_annual - year + type: string description: Billing interval. For consumable features, should match reset.interval. interval_count: @@ -8025,6 +8433,7 @@ paths: enum: - prepaid - usage_based + type: string description: "'prepaid' for upfront payment (seats), 'usage_based' for pay-as-you-go." max_purchase: @@ -8044,6 +8453,7 @@ paths: - prorate_immediately - prorate_next_cycle - bill_next_cycle + type: string description: Billing behavior when quantity increases mid-cycle. on_decrease: enum: @@ -8052,6 +8462,7 @@ paths: - prorate_next_cycle - none - no_prorations + type: string description: Credit behavior when quantity decreases mid-cycle. required: - on_increase @@ -8068,6 +8479,7 @@ paths: enum: - month - forever + type: string description: When rolled over units expire. expiry_duration_length: type: number @@ -8126,6 +8538,7 @@ paths: - day - month - year + type: string default: month description: Unit of time for the trial ('day', 'month', 'year'). card_required: @@ -8192,6 +8605,7 @@ paths: - always - if_required - never + type: string description: Controls when to return a checkout URL. 'always' returns a URL even if payment succeeds, 'if_required' only when payment action is needed, 'never' disables redirects. @@ -8232,6 +8646,40 @@ paths: minimum: 0 description: Maximum allowed overage spend for the target feature. description: List of overage spend limits per feature. + usage_alerts: + type: array + items: + type: object + properties: + feature_id: + type: string + description: The feature ID this alert applies to. If omitted, the alert applies + globally. + enabled: + type: boolean + default: true + description: Whether this usage alert is enabled. + threshold: + type: number + minimum: 0 + description: The threshold value that triggers the alert. For usage, this is an + absolute count. For usage_percentage, this is + a percentage (0-100). + threshold_type: + enum: + - usage + - usage_percentage + type: string + description: Whether the threshold is an absolute usage count or a percentage of + the usage allowance. + name: + type: string + description: Optional user-defined label to distinguish multiple alerts on the + same feature. + required: + - threshold + - threshold_type + description: List of usage alert configurations per feature. description: Billing controls for the entity. required: - feature_id @@ -8502,10 +8950,24 @@ paths: - type: "null" description: When this change takes effect, in milliseconds since the Unix epoch, or null if it applies immediately. + canceled_at: + anyOf: + - type: number + - type: "null" + description: When this plan was canceled, in milliseconds since the Unix epoch, + or null if it is not canceled. + expires_at: + anyOf: + - type: number + - type: "null" + description: When this plan expires, in milliseconds since the Unix epoch, or + null if it does not expire. required: - plan_id - feature_quantities - effective_at + - canceled_at + - expires_at description: Products or subscription changes being added or updated. outgoing: type: array @@ -8539,10 +9001,24 @@ paths: - type: "null" description: When this change takes effect, in milliseconds since the Unix epoch, or null if it applies immediately. + canceled_at: + anyOf: + - type: number + - type: "null" + description: When this plan was canceled, in milliseconds since the Unix epoch, + or null if it is not canceled. + expires_at: + anyOf: + - type: number + - type: "null" + description: When this plan expires, in milliseconds since the Unix epoch, or + null if it does not expire. required: - plan_id - feature_quantities - effective_at + - canceled_at + - expires_at description: Products or subscription changes being removed or ended. required: - customer_id @@ -8697,6 +9173,7 @@ paths: - quarter - semi_annual - year + type: string description: Billing interval (e.g. 'month', 'year'). interval_count: type: number @@ -8738,6 +9215,7 @@ paths: - quarter - semi_annual - year + type: string description: Interval at which balance resets (e.g. 'month', 'year'). For consumable features only. interval_count: @@ -8774,6 +9252,7 @@ paths: enum: - graduated - volume + type: string interval: enum: - one_off @@ -8782,6 +9261,7 @@ paths: - quarter - semi_annual - year + type: string description: Billing interval. For consumable features, should match reset.interval. interval_count: @@ -8797,6 +9277,7 @@ paths: enum: - prepaid - usage_based + type: string description: "'prepaid' for upfront payment (seats), 'usage_based' for pay-as-you-go." max_purchase: @@ -8816,6 +9297,7 @@ paths: - prorate_immediately - prorate_next_cycle - bill_next_cycle + type: string description: Billing behavior when quantity increases mid-cycle. on_decrease: enum: @@ -8824,6 +9306,7 @@ paths: - prorate_next_cycle - none - no_prorations + type: string description: Credit behavior when quantity decreases mid-cycle. required: - on_increase @@ -8840,6 +9323,7 @@ paths: enum: - month - forever + type: string description: When rolled over units expire. expiry_duration_length: type: number @@ -8866,6 +9350,7 @@ paths: - day - month - year + type: string default: month description: Unit of time for the trial ('day', 'month', 'year'). card_required: @@ -8909,6 +9394,7 @@ paths: enum: - prorate_immediately - none + type: string description: How to handle proration when updating an existing subscription. 'prorate_immediately' charges/credits prorated amounts now, 'none' skips creating any charges. @@ -8917,6 +9403,7 @@ paths: - always - if_required - never + type: string description: Controls when to return a checkout URL. 'always' returns a URL even if payment succeeds, 'if_required' only when payment action is needed, 'never' disables redirects. @@ -8931,6 +9418,7 @@ paths: - cancel_immediately - cancel_end_of_cycle - uncancel + type: string description: Action to perform for cancellation. 'cancel_immediately' cancels now with prorated refund, 'cancel_end_of_cycle' cancels at period end, 'uncancel' reverses a pending cancellation. @@ -8938,6 +9426,17 @@ paths: type: boolean description: If true, the subscription is updated internally without applying billing changes in Stripe. + recalculate_balances: + type: object + properties: + enabled: + type: boolean + description: If true, recalculates balances during the subscription update. Only + applicable when updating feature quantities. + required: + - enabled + description: Controls whether balances should be recalculated during the + subscription update. required: - customer_id title: UpdateSubscriptionParams @@ -9008,6 +9507,7 @@ paths: - 3ds_required - payment_method_required - payment_failed + type: string description: The type of action required to complete the payment. reason: type: string @@ -9149,6 +9649,7 @@ paths: - quarter - semi_annual - year + type: string description: Billing interval (e.g. 'month', 'year'). interval_count: type: number @@ -9190,6 +9691,7 @@ paths: - quarter - semi_annual - year + type: string description: Interval at which balance resets (e.g. 'month', 'year'). For consumable features only. interval_count: @@ -9226,6 +9728,7 @@ paths: enum: - graduated - volume + type: string interval: enum: - one_off @@ -9234,6 +9737,7 @@ paths: - quarter - semi_annual - year + type: string description: Billing interval. For consumable features, should match reset.interval. interval_count: @@ -9249,6 +9753,7 @@ paths: enum: - prepaid - usage_based + type: string description: "'prepaid' for upfront payment (seats), 'usage_based' for pay-as-you-go." max_purchase: @@ -9268,6 +9773,7 @@ paths: - prorate_immediately - prorate_next_cycle - bill_next_cycle + type: string description: Billing behavior when quantity increases mid-cycle. on_decrease: enum: @@ -9276,6 +9782,7 @@ paths: - prorate_next_cycle - none - no_prorations + type: string description: Credit behavior when quantity decreases mid-cycle. required: - on_increase @@ -9292,6 +9799,7 @@ paths: enum: - month - forever + type: string description: When rolled over units expire. expiry_duration_length: type: number @@ -9318,6 +9826,7 @@ paths: - day - month - year + type: string default: month description: Unit of time for the trial ('day', 'month', 'year'). card_required: @@ -9361,6 +9870,7 @@ paths: enum: - prorate_immediately - none + type: string description: How to handle proration when updating an existing subscription. 'prorate_immediately' charges/credits prorated amounts now, 'none' skips creating any charges. @@ -9369,6 +9879,7 @@ paths: - always - if_required - never + type: string description: Controls when to return a checkout URL. 'always' returns a URL even if payment succeeds, 'if_required' only when payment action is needed, 'never' disables redirects. @@ -9383,6 +9894,7 @@ paths: - cancel_immediately - cancel_end_of_cycle - uncancel + type: string description: Action to perform for cancellation. 'cancel_immediately' cancels now with prorated refund, 'cancel_end_of_cycle' cancels at period end, 'uncancel' reverses a pending cancellation. @@ -9390,6 +9902,17 @@ paths: type: boolean description: If true, the subscription is updated internally without applying billing changes in Stripe. + recalculate_balances: + type: object + properties: + enabled: + type: boolean + description: If true, recalculates balances during the subscription update. Only + applicable when updating feature quantities. + required: + - enabled + description: Controls whether balances should be recalculated during the + subscription update. required: - customer_id title: PreviewUpdateParams @@ -9654,10 +10177,24 @@ paths: - type: "null" description: When this change takes effect, in milliseconds since the Unix epoch, or null if it applies immediately. + canceled_at: + anyOf: + - type: number + - type: "null" + description: When this plan was canceled, in milliseconds since the Unix epoch, + or null if it is not canceled. + expires_at: + anyOf: + - type: number + - type: "null" + description: When this plan expires, in milliseconds since the Unix epoch, or + null if it does not expire. required: - plan_id - feature_quantities - effective_at + - canceled_at + - expires_at description: Products or subscription changes being added or updated. outgoing: type: array @@ -9691,10 +10228,24 @@ paths: - type: "null" description: When this change takes effect, in milliseconds since the Unix epoch, or null if it applies immediately. + canceled_at: + anyOf: + - type: number + - type: "null" + description: When this plan was canceled, in milliseconds since the Unix epoch, + or null if it is not canceled. + expires_at: + anyOf: + - type: number + - type: "null" + description: When this plan expires, in milliseconds since the Unix epoch, or + null if it does not expire. required: - plan_id - feature_quantities - effective_at + - canceled_at + - expires_at description: Products or subscription changes being removed or ended. intent: enum: @@ -9704,6 +10255,7 @@ paths: - cancel_end_of_cycle - uncancel - none + type: string required: - customer_id - line_items @@ -9926,6 +10478,7 @@ paths: - quarter - semi_annual - year + type: string description: Billing interval (e.g. 'month', 'year'). interval_count: type: number @@ -9967,6 +10520,7 @@ paths: - quarter - semi_annual - year + type: string description: Interval at which balance resets (e.g. 'month', 'year'). For consumable features only. interval_count: @@ -10003,6 +10557,7 @@ paths: enum: - graduated - volume + type: string interval: enum: - one_off @@ -10011,6 +10566,7 @@ paths: - quarter - semi_annual - year + type: string description: Billing interval. For consumable features, should match reset.interval. interval_count: @@ -10026,6 +10582,7 @@ paths: enum: - prepaid - usage_based + type: string description: "'prepaid' for upfront payment (seats), 'usage_based' for pay-as-you-go." max_purchase: @@ -10045,6 +10602,7 @@ paths: - prorate_immediately - prorate_next_cycle - bill_next_cycle + type: string description: Billing behavior when quantity increases mid-cycle. on_decrease: enum: @@ -10053,6 +10611,7 @@ paths: - prorate_next_cycle - none - no_prorations + type: string description: Credit behavior when quantity decreases mid-cycle. required: - on_increase @@ -10069,6 +10628,7 @@ paths: enum: - month - forever + type: string description: When rolled over units expire. expiry_duration_length: type: number @@ -10095,6 +10655,7 @@ paths: - day - month - year + type: string default: month description: Unit of time for the trial ('day', 'month', 'year'). card_required: @@ -10115,6 +10676,7 @@ paths: enum: - prorate_immediately - none + type: string description: How to handle proration when updating an existing subscription. 'prorate_immediately' charges/credits prorated amounts now, 'none' skips creating any charges. @@ -10312,6 +10874,7 @@ paths: - quarter - semi_annual - year + type: string description: The interval at which the balance resets (e.g., 'month', 'day', 'year'). interval_count: @@ -10439,6 +11002,7 @@ paths: - quarter - semi_annual - year + type: string description: Target a specific balance by its reset interval. Use when the customer has multiple balances for the same feature with different reset intervals. @@ -10548,6 +11112,7 @@ paths: - quarter - semi_annual - year + type: string description: Target a specific balance by its reset interval. Use when the customer has multiple balances for the same feature with different reset intervals. @@ -10624,6 +11189,7 @@ paths: enum: - confirm - release + type: string description: Use 'confirm' to commit the deduction, or 'release' to return the held balance. override_value: @@ -10838,6 +11404,7 @@ paths: - boolean - metered - credit_system + type: string description: "Feature type: 'boolean' for on/off access, 'metered' for usage-tracked features, 'credit_system' for unified credit pools." @@ -10912,6 +11479,7 @@ paths: enum: - usage_limit - feature_flag + type: string description: The reason access was denied. 'usage_limit' means the customer exceeded their balance, 'feature_flag' means the feature is not included in their plan. @@ -10947,6 +11515,7 @@ paths: enum: - sandbox - live + type: string description: The environment of the product is_add_on: type: boolean @@ -10976,6 +11545,7 @@ paths: - feature - priced_feature - price + type: string - type: "null" description: The type of the product item feature_id: @@ -10991,6 +11561,7 @@ paths: - continuous_use - boolean - static + type: string - type: "null" description: Single use features are used once and then depleted, like API calls or credits. Continuous use features are @@ -11014,6 +11585,7 @@ paths: - quarter - semi_annual - year + type: string - type: "null" description: The reset or billing interval of the product item. If null, feature will have no reset date, and if there's a @@ -11044,6 +11616,7 @@ paths: - enum: - graduated - volume + type: string - type: "null" description: "How tiers are applied: graduated (split across bands) or volume (flat rate for the matched tier). Defaults @@ -11053,6 +11626,7 @@ paths: - enum: - prepaid - pay_per_use + type: string - type: "null" description: Whether the feature should be prepaid upfront or billed for how much they use end of billing period. @@ -11113,6 +11687,7 @@ paths: enum: - month - forever + type: string default: month length: type: number @@ -11127,6 +11702,7 @@ paths: - prorate_immediately - prorate_next_cycle - bill_next_cycle + type: string - type: "null" on_decrease: anyOf: @@ -11136,6 +11712,7 @@ paths: - prorate_next_cycle - none - no_prorations + type: string - type: "null" - type: "null" description: Configuration for rollover and proration behavior of the feature. @@ -11151,6 +11728,7 @@ paths: - day - month - year + type: string description: The duration type of the free trial length: type: number @@ -11195,6 +11773,7 @@ paths: - cancel - expired - past_due + type: string description: Scenario for when this product is used in attach flows properties: type: object @@ -11701,6 +12280,7 @@ paths: - last_cycle - 1bc - 3bc + type: string description: Time range to aggregate events for. Either range or custom_range must be provided bin_size: @@ -11708,6 +12288,7 @@ paths: - day - hour - month + type: string default: day description: Size of the time bins to aggregate events for. Defaults to hour if range is 24h, otherwise day @@ -11930,6 +12511,40 @@ paths: minimum: 0 description: Maximum allowed overage spend for the target feature. description: List of overage spend limits per feature. + usage_alerts: + type: array + items: + type: object + properties: + feature_id: + type: string + description: The feature ID this alert applies to. If omitted, the alert applies + globally. + enabled: + type: boolean + default: true + description: Whether this usage alert is enabled. + threshold: + type: number + minimum: 0 + description: The threshold value that triggers the alert. For usage, this is an + absolute count. For usage_percentage, this is a + percentage (0-100). + threshold_type: + enum: + - usage + - usage_percentage + type: string + description: Whether the threshold is an absolute usage count or a percentage of + the usage allowance. + name: + type: string + description: Optional user-defined label to distinguish multiple alerts on the + same feature. + required: + - threshold + - threshold_type + description: List of usage alert configurations per feature. description: Billing controls for the entity. customer_data: $ref: "#/components/schemas/CustomerData" @@ -11988,6 +12603,7 @@ paths: enum: - sandbox - live + type: string description: The environment (sandbox/live) subscriptions: type: array @@ -12015,6 +12631,7 @@ paths: enum: - active - scheduled + type: string description: Current status of the subscription. past_due: type: boolean @@ -12138,6 +12755,7 @@ paths: - boolean - metered - credit_system + type: string description: "Feature type: 'boolean' for on/off access, 'metered' for usage-tracked features, 'credit_system' for unified credit pools." @@ -12223,6 +12841,40 @@ paths: minimum: 0 description: Maximum allowed overage spend for the target feature. description: List of overage spend limits per feature. + usage_alerts: + type: array + items: + type: object + properties: + feature_id: + type: string + description: The feature ID this alert applies to. If omitted, the alert applies + globally. + enabled: + type: boolean + default: true + description: Whether this usage alert is enabled. + threshold: + type: number + minimum: 0 + description: The threshold value that triggers the alert. For usage, this is an + absolute count. For usage_percentage, this is a + percentage (0-100). + threshold_type: + enum: + - usage + - usage_percentage + type: string + description: Whether the threshold is an absolute usage count or a percentage of + the usage allowance. + name: + type: string + description: Optional user-defined label to distinguish multiple alerts on the + same feature. + required: + - threshold + - threshold_type + description: List of usage alert configurations per feature. description: Billing controls for the entity. invoices: type: array @@ -12422,6 +13074,7 @@ paths: enum: - sandbox - live + type: string description: The environment (sandbox/live) subscriptions: type: array @@ -12449,6 +13102,7 @@ paths: enum: - active - scheduled + type: string description: Current status of the subscription. past_due: type: boolean @@ -12572,6 +13226,7 @@ paths: - boolean - metered - credit_system + type: string description: "Feature type: 'boolean' for on/off access, 'metered' for usage-tracked features, 'credit_system' for unified credit pools." @@ -12657,6 +13312,40 @@ paths: minimum: 0 description: Maximum allowed overage spend for the target feature. description: List of overage spend limits per feature. + usage_alerts: + type: array + items: + type: object + properties: + feature_id: + type: string + description: The feature ID this alert applies to. If omitted, the alert applies + globally. + enabled: + type: boolean + default: true + description: Whether this usage alert is enabled. + threshold: + type: number + minimum: 0 + description: The threshold value that triggers the alert. For usage, this is an + absolute count. For usage_percentage, this is a + percentage (0-100). + threshold_type: + enum: + - usage + - usage_percentage + type: string + description: Whether the threshold is an absolute usage count or a percentage of + the usage allowance. + name: + type: string + description: Optional user-defined label to distinguish multiple alerts on the + same feature. + required: + - threshold + - threshold_type + description: List of usage alert configurations per feature. description: Billing controls for the entity. invoices: type: array @@ -12824,6 +13513,40 @@ paths: minimum: 0 description: Maximum allowed overage spend for the target feature. description: List of overage spend limits per feature. + usage_alerts: + type: array + items: + type: object + properties: + feature_id: + type: string + description: The feature ID this alert applies to. If omitted, the alert applies + globally. + enabled: + type: boolean + default: true + description: Whether this usage alert is enabled. + threshold: + type: number + minimum: 0 + description: The threshold value that triggers the alert. For usage, this is an + absolute count. For usage_percentage, this is a + percentage (0-100). + threshold_type: + enum: + - usage + - usage_percentage + type: string + description: Whether the threshold is an absolute usage count or a percentage of + the usage allowance. + name: + type: string + description: Optional user-defined label to distinguish multiple alerts on the + same feature. + required: + - threshold + - threshold_type + description: List of usage alert configurations per feature. description: Billing controls to replace on the entity. required: - entity_id @@ -12873,6 +13596,7 @@ paths: enum: - sandbox - live + type: string description: The environment (sandbox/live) subscriptions: type: array @@ -12900,6 +13624,7 @@ paths: enum: - active - scheduled + type: string description: Current status of the subscription. past_due: type: boolean @@ -13023,6 +13748,7 @@ paths: - boolean - metered - credit_system + type: string description: "Feature type: 'boolean' for on/off access, 'metered' for usage-tracked features, 'credit_system' for unified credit pools." @@ -13108,6 +13834,40 @@ paths: minimum: 0 description: Maximum allowed overage spend for the target feature. description: List of overage spend limits per feature. + usage_alerts: + type: array + items: + type: object + properties: + feature_id: + type: string + description: The feature ID this alert applies to. If omitted, the alert applies + globally. + enabled: + type: boolean + default: true + description: Whether this usage alert is enabled. + threshold: + type: number + minimum: 0 + description: The threshold value that triggers the alert. For usage, this is an + absolute count. For usage_percentage, this is a + percentage (0-100). + threshold_type: + enum: + - usage + - usage_percentage + type: string + description: Whether the threshold is an absolute usage count or a percentage of + the usage allowance. + name: + type: string + description: Optional user-defined label to distinguish multiple alerts on the + same feature. + required: + - threshold + - threshold_type + description: List of usage alert configurations per feature. description: Billing controls for the entity. invoices: type: array @@ -13518,3 +14278,317 @@ x-speakeasy-globals: type: string default: 2.2.0 x-speakeasy-globals-hidden: true +webhooks: + balances.usage_alert_triggered: + post: + operationId: balancesUsageAlertTriggered + summary: Usage Alert Triggered + description: Fired when a customer crosses a configured usage alert threshold. + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - type + - data + properties: + type: + type: string + const: balances.usage_alert_triggered + description: The webhook event type. + data: + examples: + - customer_id: org_123 + feature_id: api_calls + entity_id: workspace_abc + usage_alert: + name: 80% usage warning + threshold: 80 + threshold_type: usage_percentage_threshold + type: object + properties: + customer_id: + description: The ID of the customer whose usage alert was triggered. + type: string + feature_id: + description: The feature ID the alert applies to. + type: string + entity_id: + description: The entity ID the alert applies to, if the usage was entity-scoped. + type: string + usage_alert: + description: Details of the usage alert that was triggered. + type: object + properties: + name: + description: User-defined label for the alert, if provided. + type: string + threshold: + description: The threshold value that was crossed. + type: number + threshold_type: + description: Whether the threshold is an absolute usage count or a percentage. + type: string + enum: + - usage + - usage_percentage + required: + - threshold + - threshold_type + additionalProperties: false + required: + - customer_id + - feature_id + - usage_alert + additionalProperties: false + example: + type: balances.usage_alert_triggered + data: + customer_id: org_123 + feature_id: api_calls + entity_id: workspace_abc + usage_alert: + name: 80% usage warning + threshold: 80 + threshold_type: usage_percentage_threshold + responses: + "200": + description: Webhook received successfully. + balances.limit_reached: + post: + operationId: balancesLimitReached + summary: Limit Reached + description: Fired when a customer reaches the limit for a feature (included + allowance, max purchase, or spend limit). + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - type + - data + properties: + type: + type: string + const: balances.limit_reached + description: The webhook event type. + data: + examples: + - customer_id: org_123 + entity_id: workspace_abc + feature_id: api_calls + limit_type: included + type: object + properties: + customer_id: + description: The ID of the customer who hit the limit. + type: string + entity_id: + description: The entity ID, if the limit was reached on a specific entity. + type: string + feature_id: + description: The feature ID whose limit was reached. + type: string + limit_type: + description: "Which limit was hit: included allowance, max purchase cap, or + spend limit." + type: string + enum: + - included + - max_purchase + - spend_limit + required: + - customer_id + - feature_id + - limit_type + additionalProperties: false + example: + type: balances.limit_reached + data: + customer_id: org_123 + entity_id: workspace_abc + feature_id: api_calls + limit_type: included + responses: + "200": + description: Webhook received successfully. + vercel.resources.deleted: + post: + operationId: vercelResourcesDeleted + summary: Resource Deleted + description: When a Vercel resource is deleted, you'll need to handle + de-provisioning any API keys or other non-Autumn controlled data for + this user. + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - type + - data + properties: + type: + type: string + const: vercel.resources.deleted + description: The webhook event type. + data: + type: object + properties: + resource: + description: The resource that was deleted. + type: object + properties: + id: + description: The unique identifier of the deleted resource. + type: string + required: + - id + additionalProperties: false + installation_id: + description: The Vercel integration configuration ID. + type: string + required: + - resource + - installation_id + additionalProperties: false + responses: + "200": + description: Webhook received successfully. + vercel.resources.provisioned: + post: + operationId: vercelResourcesProvisioned + summary: Resource Provisioned + description: When a Vercel resource is created, you'll need to provision a + secret key for your service. Then you can use the provided access token + to patch the resource's secrets. + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - type + - data + properties: + type: + type: string + const: vercel.resources.provisioned + description: The webhook event type. + data: + type: object + properties: + resource: + description: The resource that was provisioned. + type: object + properties: + id: + description: The unique identifier of the provisioned resource. + type: string + name: + description: The display name of the provisioned resource. + type: string + required: + - id + - name + additionalProperties: false + installation_id: + description: The Vercel integration configuration ID. + type: string + access_token: + description: An access token that can be used to patch the resource's secrets. + type: string + required: + - resource + - installation_id + - access_token + additionalProperties: false + responses: + "200": + description: Webhook received successfully. + vercel.resources.rotate_secrets: + post: + operationId: vercelResourcesRotateSecrets + summary: Rotate Secrets + description: This event is sent when Vercel requires a resource's secrets to be + rotated. + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - type + - data + properties: + type: + type: string + const: vercel.resources.rotate_secrets + description: The webhook event type. + data: + type: object + properties: + resource: + description: The resource whose secrets should be rotated. + type: object + properties: + id: + description: The unique identifier of the resource. + type: string + required: + - id + additionalProperties: false + installation_id: + description: The Vercel integration configuration ID. + type: string + vercel_request_body: + description: The raw request body from Vercel's rotation request. + required: + - resource + - installation_id + - vercel_request_body + additionalProperties: false + responses: + "200": + description: Webhook received successfully. + vercel.webhooks.event: + post: + operationId: vercelWebhooksEvent + summary: Webhook Event + description: Passthrough webhook for Vercel events. + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - type + - data + properties: + type: + type: string + const: vercel.webhooks.event + description: The webhook event type. + data: + type: object + properties: + installation_id: + description: The Vercel integration configuration ID. + type: string + event: + description: The raw Vercel webhook event payload. + required: + - installation_id + - event + additionalProperties: false + responses: + "200": + description: Webhook received successfully. diff --git a/apps/docs/mintlify/docs.json b/apps/docs/mintlify/docs.json index 6ad9cc794..e6120fe64 100644 --- a/apps/docs/mintlify/docs.json +++ b/apps/docs/mintlify/docs.json @@ -12,7 +12,11 @@ "strict": false }, "contextual": { - "options": ["copy", "cursor", "view"] + "options": [ + "copy", + "cursor", + "view" + ] }, "banner": { "content": "You're viewing the docs for Autumn's v2 API. You can find the previous API version [here](https://docs-v1.useautumn.com).", @@ -167,7 +171,11 @@ { "tab": "CLI", "icon": "square-terminal", - "pages": ["cli/getting-started", "cli/config", "cli/commands"] + "pages": [ + "cli/getting-started", + "cli/config", + "cli/commands" + ] }, { "tab": "API Reference", @@ -242,7 +250,6 @@ "api-reference/features/deleteFeature" ] }, - { "group": "Referrals", "pages": [ @@ -250,6 +257,27 @@ "api-reference/referrals/redeemReferralCode" ] }, + { + "group": "Webhook Events", + "pages": [ + { + "group": "Balances", + "pages": [ + "api-reference/webhooks/balancesUsageAlertTriggered", + "api-reference/webhooks/balancesLimitReached" + ] + }, + { + "group": "Vercel", + "pages": [ + "api-reference/webhooks/vercelResourcesDeleted", + "api-reference/webhooks/vercelResourcesProvisioned", + "api-reference/webhooks/vercelResourcesRotateSecrets", + "api-reference/webhooks/vercelWebhooksEvent" + ] + } + ] + }, { "group": "Platform (Beta)", "pages": [ @@ -266,7 +294,9 @@ { "tab": "Changelog", "icon": "list-ol", - "pages": ["changelog/changelog"] + "pages": [ + "changelog/changelog" + ] } ] }, @@ -279,7 +309,11 @@ "display": "interactive" }, "examples": { - "languages": ["typescript", "python", "bash"] + "languages": [ + "typescript", + "python", + "bash" + ] } }, "background": { diff --git a/apps/docs/mintlify/documentation/webhooks.mdx b/apps/docs/mintlify/documentation/webhooks.mdx index c87fa07b3..8adf4abcd 100644 --- a/apps/docs/mintlify/documentation/webhooks.mdx +++ b/apps/docs/mintlify/documentation/webhooks.mdx @@ -60,36 +60,64 @@ Fired when a customer's product or plan changes. The `scenario` field indicates } ``` -### customer.threshold_reached +### balances.limit_reached -Fired when a customer reaches a usage threshold for a feature. This is useful for notifying users before they hit hard limits. +Fired when a customer hits a usage limit for a feature. A limit can be the included allowance, a max purchase cap, or a spend limit. -| Threshold Type | Description | -|----------------|-------------| -| `limit_reached` | Customer has reached their usage limit | -| `allowance_used` | Customer has exhausted their allowance | - -In most cases, these events will fire at the same time, as the included allowance is the same as the user's usage limit. However, you may have a feature with a different included allowance and a different "max purchase" limit. - -Eg: 100 API calls included, then 0.1 per API call, with a maximum purchase limit of 1000 API calls. +| Limit Type | Description | +|------------|-------------| +| `included` | Customer has exhausted their included allowance | +| `max_purchase` | Customer has reached the maximum purchase cap for overage | +| `spend_limit` | Customer has hit their configured spend limit | **Example payload:** ```json expandable { - "type": "customer.threshold_reached", + "type": "balances.limit_reached", "data": { - "threshold_type": "limit_reached", - "customer": { - "id": "user_123", - "name": "John Doe", - "email": "john@example.com", - "balances": { ... } - }, - "feature": { - "id": "api_calls", - "name": "API Calls", - "type": "metered" + "customer_id": "user_123", + "feature_id": "api_calls", + "limit_type": "included" + } +} +``` + +For entity-scoped usage, the payload will also include an `entity_id`: + +```json expandable +{ + "type": "balances.limit_reached", + "data": { + "customer_id": "user_123", + "feature_id": "api_calls", + "entity_id": "team_456", + "limit_type": "max_purchase" + } +} +``` + +### balances.usage_alert_triggered + +Fired when a customer crosses a configured usage alert threshold. Usage alerts let you monitor when customers approach or exceed specific usage levels for a feature. + +| Alert Threshold Type | Description | +|---------------------|-------------| +| `usage` | An absolute usage count was crossed | +| `usage_percentage` | A percentage of the usage allowance was crossed | + +**Example payload:** + +```json expandable +{ + "type": "balances.usage_alert_triggered", + "data": { + "customer_id": "user_123", + "feature_id": "api_calls", + "usage_alert": { + "name": "80% usage warning", + "threshold": 80, + "threshold_type": "usage_percentage" } } } diff --git a/bun.lock b/bun.lock index edcd28a85..2c6fccad6 100644 --- a/bun.lock +++ b/bun.lock @@ -224,6 +224,8 @@ "@orpc/contract": "catalog:", "@orpc/openapi": "^1.13.4", "@orpc/zod": "^1.13.4", + "dotenv": "^17.3.1", + "svix": "^1.89.0", "yaml": "^2.8.1", "zod-openapi": "^5.4.1", }, @@ -246,7 +248,7 @@ "@eslint/js": "^9.26.0", "eslint": "^9.26.0", "globals": "^15.14.0", - "tshy": "^3.3.2", + "tshy": "^2.0.0", "typescript": "~5.8.3", "typescript-eslint": "^8.26.0", }, @@ -3266,7 +3268,7 @@ "for-each": ["for-each@0.3.5", "", { "dependencies": { "is-callable": "^1.2.7" } }, "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg=="], - "foreground-child": ["foreground-child@4.0.3", "", { "dependencies": { "signal-exit": "^4.0.1" } }, "sha512-yeXZaNbCBGaT9giTpLPBdtedzjwhlJBUoL/R4BVQU5mn0TQXOHwVIl1Q2DMuBIdNno4ktA1abZ7dQFVxD6uHxw=="], + "foreground-child": ["foreground-child@3.3.1", "", { "dependencies": { "cross-spawn": "^7.0.6", "signal-exit": "^4.0.1" } }, "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw=="], "form-data": ["form-data@4.0.5", "", { "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "es-set-tostringtag": "^2.1.0", "hasown": "^2.0.2", "mime-types": "^2.1.12" } }, "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w=="], @@ -3764,8 +3766,6 @@ "jsonc-parser": ["jsonc-parser@2.2.1", "", {}, "sha512-o6/yDBYccGvTz1+QFevz6l6OBZ2+fMVu2JZ9CIhzsYRX4mjaK5IyX9eldUdCmga16zlgQxyrj5pt9kzuj2C02w=="], - "jsonc-simple-parser": ["jsonc-simple-parser@3.0.0", "", { "dependencies": { "reghex": "^3.0.2" } }, "sha512-0qi9Kuj4JPar4/3b9wZteuPZrTeFzXsQyOZj7hksnReCZN3Vr17Doz7w/i3E9XH7vRkVTHhHES+r1h97I+hfww=="], - "jsonfile": ["jsonfile@6.2.0", "", { "dependencies": { "universalify": "^2.0.0" }, "optionalDependencies": { "graceful-fs": "^4.1.6" } }, "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg=="], "jsonpath-plus": ["jsonpath-plus@10.4.0", "", { "dependencies": { "@jsep-plugin/assignment": "^1.3.0", "@jsep-plugin/regex": "^1.0.4", "jsep": "^1.4.0" }, "bin": { "jsonpath": "bin/jsonpath-cli.js", "jsonpath-plus": "bin/jsonpath-cli.js" } }, "sha512-T92WWatJXmhBbKsgH/0hl+jxjdXrifi5IKeMY02DWggRxX0UElcbVzPlmgLTbvsPeW1PasQ6xE2Q75stkhGbsA=="], @@ -4610,8 +4610,6 @@ "regexpp": ["regexpp@3.2.0", "", {}, "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg=="], - "reghex": ["reghex@3.0.2", "", {}, "sha512-Zb9DJ5u6GhgqRSBnxV2QSnLqEwcKxHWFA1N2yUa4ZUAO1P8jlWKYtWZ6/ooV6yylspGXJX0O/uNzEv0xrCtwaA=="], - "rehype-harden": ["rehype-harden@1.1.8", "", { "dependencies": { "unist-util-visit": "^5.0.0" } }, "sha512-Qn7vR1xrf6fZCrkm9TDWi/AB4ylrHy+jqsNm1EHOAmbARYA6gsnVJBq/sdBh6kmT4NEZxH5vgIjrscefJAOXcw=="], "rehype-katex": ["rehype-katex@7.0.1", "", { "dependencies": { "@types/hast": "^3.0.0", "@types/katex": "^0.16.0", "hast-util-from-html-isomorphic": "^2.0.0", "hast-util-to-text": "^4.0.0", "katex": "^0.16.0", "unist-util-visit-parents": "^6.0.0", "vfile": "^6.0.0" } }, "sha512-OiM2wrZ/wuhKkigASodFoo8wimG3H12LWQaH8qSPVJn9apWKFSH3YOCtbKpBorTVw/eI7cuT21XBbvwEswbIOA=="], @@ -4678,7 +4676,7 @@ "resolve-from": ["resolve-from@5.0.0", "", {}, "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw=="], - "resolve-import": ["resolve-import@2.4.0", "", { "dependencies": { "glob": "^13.0.0", "walk-up-path": "^4.0.0" } }, "sha512-gLWKdA5tiv5j/D7ipR47u3ovbVfzFPrctTdw2Ulnpmr6PPVVSvPKGNWu09jXVNlOSLLAeD6CA13bjIelpWttSw=="], + "resolve-import": ["resolve-import@1.4.6", "", { "dependencies": { "glob": "^10.3.3", "walk-up-path": "^3.0.1" } }, "sha512-CIw9e64QcKcCFUj9+KxUCJPy8hYofv6eVfo3U9wdhCm2E4IjvFnZ6G4/yIC4yP3f11+h6uU5b3LdS7O64LgqrA=="], "resolve-pkg-maps": ["resolve-pkg-maps@1.0.0", "", {}, "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw=="], @@ -4702,7 +4700,7 @@ "rfdc": ["rfdc@1.4.1", "", {}, "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA=="], - "rimraf": ["rimraf@6.1.3", "", { "dependencies": { "glob": "^13.0.3", "package-json-from-dist": "^1.0.1" }, "bin": { "rimraf": "dist/esm/bin.mjs" } }, "sha512-LKg+Cr2ZF61fkcaK1UdkH2yEBBKnYjTyWzTJT6KNPcSPaiT7HSdhtMXQuN5wkTX0Xu72KQ1l8S42rlmexS2hSA=="], + "rimraf": ["rimraf@5.0.10", "", { "dependencies": { "glob": "^10.3.7" }, "bin": { "rimraf": "dist/esm/bin.mjs" } }, "sha512-l0OE8wL34P4nJH/H2ffoaniAokM2qSmrtXHmlpvYr5AVVX8msAyW0l8NVJFDxlSK4u3Uh/f41cQheDVdnYijwQ=="], "robust-predicates": ["robust-predicates@3.0.3", "", {}, "sha512-NS3levdsRIUOmiJ8FZWCP7LG3QpJyrs/TE0Zpf1yvZu8cAJJ6QMW92H1c7kWpdIHo8RvmLxN/o2JXTKHp74lUA=="], @@ -4952,7 +4950,7 @@ "swr": ["swr@2.4.1", "", { "dependencies": { "dequal": "^2.0.3", "use-sync-external-store": "^1.6.0" }, "peerDependencies": { "react": "^16.11.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-2CC6CiKQtEwaEeNiqWTAw9PGykW8SR5zZX8MZk6TeAvEAnVS7Visz8WzphqgtQ8v2xz/4Q5K+j+SeMaKXeeQIA=="], - "sync-content": ["sync-content@2.0.4", "", { "dependencies": { "glob": "^13.0.1", "mkdirp": "^3.0.1", "path-scurry": "^2.0.0", "rimraf": "^6.0.0" }, "bin": { "sync-content": "dist/esm/bin.mjs" } }, "sha512-w3ioiBmbaogob33WdLnuwFk+8tpePI58CTWKqtdAgEqc2hfGuSwP02gPETqNX/3PLS5skv5a1wQR0gbaa2W0XQ=="], + "sync-content": ["sync-content@1.0.2", "", { "dependencies": { "glob": "^10.2.6", "mkdirp": "^3.0.1", "path-scurry": "^1.9.2", "rimraf": "^5.0.1" }, "bin": { "sync-content": "dist/mjs/bin.mjs" } }, "sha512-znd3rYiiSxU3WteWyS9a6FXkTA/Wjk8WQsOyzHbineeL837dLn3DA4MRhsIX3qGcxDMH6+uuFV4axztssk7wEQ=="], "system-architecture": ["system-architecture@0.1.0", "", {}, "sha512-ulAk51I9UVUyJgxlv9M6lFot2WP3e7t8Kz9+IS6D4rVba1tR9kON+Ey69f+1R4Q8cd45Lod6a4IcJIxnzGc/zA=="], @@ -5108,7 +5106,7 @@ "tsconfig-paths": ["tsconfig-paths@4.2.0", "", { "dependencies": { "json5": "^2.2.2", "minimist": "^1.2.6", "strip-bom": "^3.0.0" } }, "sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg=="], - "tshy": ["tshy@3.3.2", "", { "dependencies": { "@typescript/native-preview": "^7.0.0-dev.20260218.1", "chalk": "^5.6.2", "chokidar": "^4.0.3", "foreground-child": "^4.0.0", "jsonc-simple-parser": "^3.0.0", "minimatch": "^10.0.3", "mkdirp": "^3.0.1", "polite-json": "^5.0.0", "resolve-import": "^2.4.0", "rimraf": "^6.1.2", "sync-content": "^2.0.3", "typescript": "^5.9.3", "walk-up-path": "^4.0.0" }, "bin": { "tshy": "dist/esm/bin-min.mjs" } }, "sha512-vOIXkqMtBWNjKUR/c99+6N50LhWdnKG1xE3+5wf8IPdzxx2lcIFPvbGgFdBBgoTMbdNb8mz06MUm7hY+TFnJcw=="], + "tshy": ["tshy@2.0.1", "", { "dependencies": { "chalk": "^5.3.0", "chokidar": "^3.6.0", "foreground-child": "^3.1.1", "minimatch": "^9.0.4", "mkdirp": "^3.0.1", "polite-json": "^5.0.0", "resolve-import": "^1.4.5", "rimraf": "^5.0.1", "sync-content": "^1.0.2", "typescript": "5", "walk-up-path": "^3.0.1" }, "bin": { "tshy": "dist/esm/index.js" } }, "sha512-U5fC+3pMaGfmULhPTVpxKMd62AcX13yfsFrjhAP/daTLG6LFRLIuxqYOmkejJ4MT/s5bEa29+1Jy/9mXkMiMfA=="], "tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="], @@ -5232,7 +5230,7 @@ "utils-merge": ["utils-merge@1.0.1", "", {}, "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA=="], - "uuid": ["uuid@11.1.0", "", { "bin": { "uuid": "dist/esm/bin/uuid" } }, "sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A=="], + "uuid": ["uuid@10.0.0", "", { "bin": { "uuid": "dist/bin/uuid" } }, "sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ=="], "v8-compile-cache-lib": ["v8-compile-cache-lib@3.0.1", "", {}, "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg=="], @@ -5274,7 +5272,7 @@ "walk-sync": ["walk-sync@0.2.7", "", { "dependencies": { "ensure-posix-path": "^1.0.0", "matcher-collection": "^1.0.0" } }, "sha512-OH8GdRMowEFr0XSHQeX5fGweO6zSVHo7bG/0yJQx6LAj9Oukz0C8heI3/FYectT66gY0IPGe89kOvU410/UNpg=="], - "walk-up-path": ["walk-up-path@4.0.0", "", {}, "sha512-3hu+tD8YzSLGuFYtPRb48vdhKMi0KQV5sn+uWr8+7dMEq/2G/dtLrdDinkLjqq5TIbIBjYJ4Ax/n3YiaW7QM8A=="], + "walk-up-path": ["walk-up-path@3.0.1", "", {}, "sha512-9YlCL/ynK3CTlrSRrDxZvUauLzAswPCrsaCgilqFevUYpeEW0/3ScEjaa3kbW/T0ghhkEr7mv+fpjqn1Y1YuTA=="], "watchpack": ["watchpack@2.5.1", "", { "dependencies": { "glob-to-regexp": "^0.4.1", "graceful-fs": "^4.1.2" } }, "sha512-Zn5uXdcFNIA1+1Ei5McRd+iRzfhENPCe7LeABkJtNulSxjma+l7ltNx55BWZkRlwRnpOgHqxnjyaDgJnNXnqzg=="], @@ -5404,6 +5402,8 @@ "@artilleryio/int-core/https-proxy-agent": ["https-proxy-agent@5.0.1", "", { "dependencies": { "agent-base": "6", "debug": "4" } }, "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA=="], + "@artilleryio/int-core/uuid": ["uuid@11.1.0", "", { "bin": { "uuid": "dist/esm/bin/uuid" } }, "sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A=="], + "@artilleryio/int-core/ws": ["ws@7.5.10", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": "^5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ=="], "@asyncapi/parser/ajv": ["ajv@8.18.0", "", { "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2" } }, "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A=="], @@ -5414,8 +5414,12 @@ "@asyncapi/parser/node-fetch": ["node-fetch@2.6.7", "", { "dependencies": { "whatwg-url": "^5.0.0" }, "peerDependencies": { "encoding": "^0.1.0" }, "optionalPeers": ["encoding"] }, "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ=="], + "@autumn/openapi/dotenv": ["dotenv@17.3.1", "", {}, "sha512-IO8C/dzEb6O3F9/twg6ZLXz164a2fhTnEWb95H23Dm4OuN+92NmEAlTrupP9VW6Jm3sO26tQlqyvyi4CsnY9GA=="], + "@autumn/server/@types/node": ["@types/node@25.5.0", "", { "dependencies": { "undici-types": "~7.18.0" } }, "sha512-jp2P3tQMSxWugkCUKLRPVUpGaL5MVFwF8RDuSRztfwgN1wmqJeMSbKlnEtQqU8UrhTmzEmZdu2I6v2dpp7XIxw=="], + "@autumn/server/@typescript/native-preview": ["@typescript/native-preview@7.0.0-dev.20260323.1", "", { "optionalDependencies": { "@typescript/native-preview-darwin-arm64": "7.0.0-dev.20260323.1", "@typescript/native-preview-darwin-x64": "7.0.0-dev.20260323.1", "@typescript/native-preview-linux-arm": "7.0.0-dev.20260323.1", "@typescript/native-preview-linux-arm64": "7.0.0-dev.20260323.1", "@typescript/native-preview-linux-x64": "7.0.0-dev.20260323.1", "@typescript/native-preview-win32-arm64": "7.0.0-dev.20260323.1", "@typescript/native-preview-win32-x64": "7.0.0-dev.20260323.1" }, "bin": { "tsgo": "bin/tsgo.js" } }, "sha512-e8rnqL5I4DUSjiy6jiWqYFKcgKq8tC4S+uEmJwWiyTgSIGDhaRUujJ2pb6EXmi+NPeXoES6vIG7e9BsEV0WSow=="], + "@autumn/server/autumn-js": ["autumn-js@0.1.85", "", { "dependencies": { "query-string": "^9.2.2", "rou3": "^0.6.1", "swr": "^2.3.3", "zod": "^4.0.0" }, "peerDependencies": { "better-auth": "^1.3.17", "better-call": "^1.0.12", "convex": "^1.25.4" }, "optionalPeers": ["better-auth", "better-call", "convex"] }, "sha512-PDud/t8z5bDJcD7ptyHzTaoJ0A8zkxvQ4TYcJ48RtgKDdOkVY36D1T6udVLwLDnWw4J5KXwJgEuGxHdd+cuABw=="], "@autumn/server/ink": ["ink@6.8.0", "", { "dependencies": { "@alcalzone/ansi-tokenize": "^0.2.4", "ansi-escapes": "^7.3.0", "ansi-styles": "^6.2.1", "auto-bind": "^5.0.1", "chalk": "^5.6.0", "cli-boxes": "^3.0.0", "cli-cursor": "^4.0.0", "cli-truncate": "^5.1.1", "code-excerpt": "^4.0.0", "es-toolkit": "^1.39.10", "indent-string": "^5.0.0", "is-in-ci": "^2.0.0", "patch-console": "^2.0.0", "react-reconciler": "^0.33.0", "scheduler": "^0.27.0", "signal-exit": "^3.0.7", "slice-ansi": "^8.0.0", "stack-utils": "^2.0.6", "string-width": "^8.1.1", "terminal-size": "^4.0.1", "type-fest": "^5.4.1", "widest-line": "^6.0.0", "wrap-ansi": "^9.0.0", "ws": "^8.18.0", "yoga-layout": "~3.2.1" }, "peerDependencies": { "@types/react": ">=19.0.0", "react": ">=19.0.0", "react-devtools-core": ">=6.1.2" }, "optionalPeers": ["@types/react", "react-devtools-core"] }, "sha512-sbl1RdLOgkO9isK42WCZlJCFN9hb++sX9dsklOvfd1YQ3bQ2AiFu12Q6tFlr0HvEUvzraJntQCCpfEoUe9DSzA=="], @@ -5674,12 +5678,10 @@ "@langchain/core/decamelize": ["decamelize@1.2.0", "", {}, "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA=="], + "@langchain/core/uuid": ["uuid@11.1.0", "", { "bin": { "uuid": "dist/esm/bin/uuid" } }, "sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A=="], + "@langchain/core/zod": ["zod@4.3.6", "", {}, "sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg=="], - "@langchain/langgraph/uuid": ["uuid@10.0.0", "", { "bin": { "uuid": "dist/bin/uuid" } }, "sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ=="], - - "@langchain/langgraph-checkpoint/uuid": ["uuid@10.0.0", "", { "bin": { "uuid": "dist/bin/uuid" } }, "sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ=="], - "@langchain/langgraph-sdk/p-queue": ["p-queue@9.1.0", "", { "dependencies": { "eventemitter3": "^5.0.1", "p-timeout": "^7.0.0" } }, "sha512-O/ZPaXuQV29uSLbxWBGGZO1mCQXV2BLIwUr59JUU9SoH76mnYvtms7aafH/isNSNGwuEfP6W/4xD0/TJXxrizw=="], "@langchain/langgraph-sdk/p-retry": ["p-retry@7.1.1", "", { "dependencies": { "is-network-error": "^1.1.0" } }, "sha512-J5ApzjyRkkf601HpEeykoiCvzHQjWxPAHhyjFcEUP2SWq0+35NKh8TLhpLw+Dkq5TZBFvUM6UigdE9hIVYTl5w=="], @@ -5752,6 +5754,8 @@ "@mintlify/prebuild/unist-util-visit": ["unist-util-visit@4.1.2", "", { "dependencies": { "@types/unist": "^2.0.0", "unist-util-is": "^5.0.0", "unist-util-visit-parents": "^5.1.1" } }, "sha512-MSd8OUGISqHdVvfY9TPhyK2VdUrPgxkUtWSuMHF6XAAFuL4LokseigBnZtPnJMu+FbynTkFNnFlyjxpVKujMRg=="], + "@mintlify/prebuild/uuid": ["uuid@11.1.0", "", { "bin": { "uuid": "dist/esm/bin/uuid" } }, "sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A=="], + "@mintlify/previewing/chalk": ["chalk@5.2.0", "", {}, "sha512-ree3Gqw/nazQAPuJJEy+avdl7QfZMcUvmHIKgEZkGL+xOBzRvup5Hxo6LHuMceSxOabuJLJm5Yp/92R9eMmMvA=="], "@mintlify/previewing/chokidar": ["chokidar@3.5.3", "", { "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", "glob-parent": "~5.1.2", "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", "normalize-path": "~3.0.0", "readdirp": "~3.6.0" }, "optionalDependencies": { "fsevents": "~2.3.2" } }, "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw=="], @@ -5794,6 +5798,8 @@ "@mintlify/validation/object-hash": ["object-hash@3.0.0", "", {}, "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw=="], + "@mintlify/validation/uuid": ["uuid@11.1.0", "", { "bin": { "uuid": "dist/esm/bin/uuid" } }, "sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A=="], + "@mintlify/validation/zod": ["zod@3.24.0", "", {}, "sha512-Hz+wiY8yD0VLA2k/+nsg2Abez674dDGTai33SwNvMPuf9uIrBC9eFgIMQxBBbHFxVXi8W+5nX9DcAh9YNSQm/w=="], "@mintlify/validation/zod-to-json-schema": ["zod-to-json-schema@3.20.4", "", { "peerDependencies": { "zod": "^3.20.0" } }, "sha512-Un9+kInJ2Zt63n6Z7mLqBifzzPcOyX+b+Exuzf7L1+xqck9Q2EPByyTRduV3kmSPaXaRer1JCsucubpgL1fipg=="], @@ -6010,6 +6016,8 @@ "@posthog/ai/openai": ["openai@6.32.0", "", { "peerDependencies": { "ws": "^8.18.0", "zod": "^3.25 || ^4.0" }, "optionalPeers": ["ws", "zod"], "bin": { "openai": "bin/cli" } }, "sha512-j3k+BjydAf8yQlcOI7WUQMQTbbF5GEIMAE2iZYCOzwwB3S2pCheaWYp+XZRNAch4jWVc52PMDGRRjutao3lLCg=="], + "@posthog/ai/uuid": ["uuid@11.1.0", "", { "bin": { "uuid": "dist/esm/bin/uuid" } }, "sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A=="], + "@posthog/ai/zod": ["zod@4.3.6", "", {}, "sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg=="], "@prisma/instrumentation/@opentelemetry/instrumentation": ["@opentelemetry/instrumentation@0.207.0", "", { "dependencies": { "@opentelemetry/api-logs": "0.207.0", "import-in-the-middle": "^2.0.0", "require-in-the-middle": "^8.0.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-y6eeli9+TLKnznrR8AZlQMSJT7wILpXH+6EYq5Vf/4Ao+huI7EedxQHwRgVUOMLFbe7VFDvHJrX9/f4lcwnJsA=="], @@ -6168,6 +6176,8 @@ "@useautumn/sdk/typescript": ["typescript@5.8.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ=="], + "@useautumn/sdk/zod": ["zod@4.3.6", "", {}, "sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg=="], + "@vercel/sdk/zod": ["zod@4.3.6", "", {}, "sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg=="], "@vue/compiler-core/entities": ["entities@7.0.1", "", {}, "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA=="], @@ -6226,6 +6236,8 @@ "artillery-plugin-publish-metrics/prom-client": ["prom-client@14.2.0", "", { "dependencies": { "tdigest": "^0.1.1" } }, "sha512-sF308EhTenb/pDRPakm+WgiN+VdM/T1RaHj1x+MvAuT8UiQP8JmOEbxVqtkbfR4LrvOg5n7ic01kRBDGXjYikA=="], + "artillery-plugin-publish-metrics/uuid": ["uuid@11.1.0", "", { "bin": { "uuid": "dist/esm/bin/uuid" } }, "sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A=="], + "atmn/@tanstack/react-query": ["@tanstack/react-query@5.95.0", "", { "dependencies": { "@tanstack/query-core": "5.95.0" }, "peerDependencies": { "react": "^18 || ^19" } }, "sha512-EMP8B+BK9zvnAemT8M/y3z/WO0NjZ7fIUY3T3wnHYK6AA3qK/k33i7tPgCXCejhX0cd4I6bJIXN2GmjrHjDBzg=="], "atmn/@types/react": ["@types/react@19.2.14", "", { "dependencies": { "csstype": "^3.2.2" } }, "sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w=="], @@ -6280,6 +6292,8 @@ "bullmq/ioredis": ["ioredis@5.9.3", "", { "dependencies": { "@ioredis/commands": "1.5.0", "cluster-key-slot": "^1.1.0", "debug": "^4.3.4", "denque": "^2.1.0", "lodash.defaults": "^4.2.0", "lodash.isarguments": "^3.1.0", "redis-errors": "^1.2.0", "redis-parser": "^3.0.0", "standard-as-callback": "^2.1.0" } }, "sha512-VI5tMCdeoxZWU5vjHWsiE/Su76JGhBvWF1MJnV9ZtGltHk9BmD48oDq8Tj8haZ85aceXZMxLNDQZRVo5QKNgXA=="], + "bullmq/uuid": ["uuid@11.1.0", "", { "bin": { "uuid": "dist/esm/bin/uuid" } }, "sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A=="], + "bun-types/@types/node": ["@types/node@25.5.0", "", { "dependencies": { "undici-types": "~7.18.0" } }, "sha512-jp2P3tQMSxWugkCUKLRPVUpGaL5MVFwF8RDuSRztfwgN1wmqJeMSbKlnEtQqU8UrhTmzEmZdu2I6v2dpp7XIxw=="], "c12/chokidar": ["chokidar@5.0.0", "", { "dependencies": { "readdirp": "^5.0.0" } }, "sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw=="], @@ -6472,8 +6486,6 @@ "get-uri/data-uri-to-buffer": ["data-uri-to-buffer@6.0.2", "", {}, "sha512-7hvf7/GW8e86rW0ptuwS3OcBGDjIi6SZva7hCyWC0yYry2cOPmLIjXAUHI6DK2HsnwJd9ifmt57i8eV2n4YNpw=="], - "glob/foreground-child": ["foreground-child@3.3.1", "", { "dependencies": { "cross-spawn": "^7.0.6", "signal-exit": "^4.0.1" } }, "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw=="], - "globby/slash": ["slash@3.0.0", "", {}, "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q=="], "hosted-git-info/lru-cache": ["lru-cache@7.18.3", "", {}, "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA=="], @@ -6508,12 +6520,12 @@ "katex/commander": ["commander@8.3.0", "", {}, "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww=="], + "langchain/uuid": ["uuid@11.1.0", "", { "bin": { "uuid": "dist/esm/bin/uuid" } }, "sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A=="], + "langchain/zod": ["zod@4.3.6", "", {}, "sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg=="], "langium/chevrotain": ["chevrotain@11.1.2", "", { "dependencies": { "@chevrotain/cst-dts-gen": "11.1.2", "@chevrotain/gast": "11.1.2", "@chevrotain/regexp-to-ast": "11.1.2", "@chevrotain/types": "11.1.2", "@chevrotain/utils": "11.1.2", "lodash-es": "4.17.23" } }, "sha512-opLQzEVriiH1uUQ4Kctsd49bRoFDXGGSC4GUqj7pGyxM3RehRhvTlZJc1FL/Flew2p5uwxa1tUDWKzI4wNM8pg=="], - "langsmith/uuid": ["uuid@10.0.0", "", { "bin": { "uuid": "dist/bin/uuid" } }, "sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ=="], - "line-column-path/type-fest": ["type-fest@2.19.0", "", {}, "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA=="], "listr2/cli-truncate": ["cli-truncate@5.2.0", "", { "dependencies": { "slice-ansi": "^8.0.0", "string-width": "^8.2.0" } }, "sha512-xRwvIOMGrfOAnM1JYtqQImuaNtDEv9v6oIYAs4LIHwTiKee8uwvIi363igssOC0O5U04i4AlENs79LQLu9tEMw=="], @@ -6532,6 +6544,8 @@ "meow/type-fest": ["type-fest@3.13.1", "", {}, "sha512-tLq3bSNx+xSpwvAJnzrK0Ep5CLNWjvFTOp71URMaAEWBfRb9nnJiBoUe0tF8bI4ZFO3omgBR6NvnbzVUT3Ly4g=="], + "mermaid/uuid": ["uuid@11.1.0", "", { "bin": { "uuid": "dist/esm/bin/uuid" } }, "sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A=="], + "micromatch/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="], "minimist-options/arrify": ["arrify@1.0.1", "", {}, "sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA=="], @@ -6704,10 +6718,6 @@ "requirejs-config-file/stringify-object": ["stringify-object@3.3.0", "", { "dependencies": { "get-own-enumerable-property-symbols": "^3.0.0", "is-obj": "^1.0.1", "is-regexp": "^1.0.0" } }, "sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw=="], - "resolve-import/glob": ["glob@13.0.6", "", { "dependencies": { "minimatch": "^10.2.2", "minipass": "^7.1.3", "path-scurry": "^2.0.2" } }, "sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw=="], - - "rimraf/glob": ["glob@13.0.6", "", { "dependencies": { "minimatch": "^10.2.2", "minipass": "^7.1.3", "path-scurry": "^2.0.2" } }, "sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw=="], - "router/path-to-regexp": ["path-to-regexp@8.3.0", "", {}, "sha512-7jdwVIRtsP8MYpdXSwOS0YdD0Du+qOoF/AEPIt88PcCFrZCzx41oxku1jD88hZBwbNUIEfpqvuhjFaMAqMTWnA=="], "run-jxa/execa": ["execa@5.1.1", "", { "dependencies": { "cross-spawn": "^7.0.3", "get-stream": "^6.0.0", "human-signals": "^2.1.0", "is-stream": "^2.0.0", "merge-stream": "^2.0.0", "npm-run-path": "^4.0.1", "onetime": "^5.1.2", "signal-exit": "^3.0.3", "strip-final-newline": "^2.0.0" } }, "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg=="], @@ -6774,12 +6784,6 @@ "supports-hyperlinks/supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="], - "svix/uuid": ["uuid@10.0.0", "", { "bin": { "uuid": "dist/bin/uuid" } }, "sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ=="], - - "sync-content/glob": ["glob@13.0.6", "", { "dependencies": { "minimatch": "^10.2.2", "minipass": "^7.1.3", "path-scurry": "^2.0.2" } }, "sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw=="], - - "sync-content/path-scurry": ["path-scurry@2.0.2", "", { "dependencies": { "lru-cache": "^11.0.0", "minipass": "^7.1.2" } }, "sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg=="], - "tar/chownr": ["chownr@2.0.0", "", {}, "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ=="], "tar/minipass": ["minipass@5.0.0", "", {}, "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ=="], @@ -6804,9 +6808,7 @@ "tsc-alias/commander": ["commander@9.5.0", "", {}, "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ=="], - "tshy/@typescript/native-preview": ["@typescript/native-preview@7.0.0-dev.20260323.1", "", { "optionalDependencies": { "@typescript/native-preview-darwin-arm64": "7.0.0-dev.20260323.1", "@typescript/native-preview-darwin-x64": "7.0.0-dev.20260323.1", "@typescript/native-preview-linux-arm": "7.0.0-dev.20260323.1", "@typescript/native-preview-linux-arm64": "7.0.0-dev.20260323.1", "@typescript/native-preview-linux-x64": "7.0.0-dev.20260323.1", "@typescript/native-preview-win32-arm64": "7.0.0-dev.20260323.1", "@typescript/native-preview-win32-x64": "7.0.0-dev.20260323.1" }, "bin": { "tsgo": "bin/tsgo.js" } }, "sha512-e8rnqL5I4DUSjiy6jiWqYFKcgKq8tC4S+uEmJwWiyTgSIGDhaRUujJ2pb6EXmi+NPeXoES6vIG7e9BsEV0WSow=="], - - "tshy/minimatch": ["minimatch@10.2.4", "", { "dependencies": { "brace-expansion": "^5.0.2" } }, "sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg=="], + "tshy/chokidar": ["chokidar@3.6.0", "", { "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", "glob-parent": "~5.1.2", "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", "normalize-path": "~3.0.0", "readdirp": "~3.6.0" }, "optionalDependencies": { "fsevents": "~2.3.2" } }, "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw=="], "tsutils/tslib": ["tslib@1.14.1", "", {}, "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="], @@ -6958,6 +6960,20 @@ "@autumn/server/@types/node/undici-types": ["undici-types@7.18.2", "", {}, "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w=="], + "@autumn/server/@typescript/native-preview/@typescript/native-preview-darwin-arm64": ["@typescript/native-preview-darwin-arm64@7.0.0-dev.20260323.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-C3tQdgMaYn57xzRUWek+zNKMiP0z9j7fqbCjr0wlyiLNIh5jMwDArjBDKHlqSu58FKvZg7baqbqB5Mcepb3s6w=="], + + "@autumn/server/@typescript/native-preview/@typescript/native-preview-darwin-x64": ["@typescript/native-preview-darwin-x64@7.0.0-dev.20260323.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-YE6pD4wdMqNgaBkXicQBLFwABOEmLxDclSM7grl0fw4cQSbfVwFCbSlwFDkmISKdmsgtWdYeMohrsTU710ufpg=="], + + "@autumn/server/@typescript/native-preview/@typescript/native-preview-linux-arm": ["@typescript/native-preview-linux-arm@7.0.0-dev.20260323.1", "", { "os": "linux", "cpu": "arm" }, "sha512-6zFO/SF9Gu8rtRyEt1b10TNapQGq5b/wUjCLG14675n155r4EO3JFMgnltBViV2Eatnq7G+bXD65BUBk7Ixyhw=="], + + "@autumn/server/@typescript/native-preview/@typescript/native-preview-linux-arm64": ["@typescript/native-preview-linux-arm64@7.0.0-dev.20260323.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-Jzr2gBY0ifA3XejAl7kPeHLT72JFBfzLSafOAQbANh5Iag02uPl99k8ORMfKREbYgEMMOzqPpe+r6eaKy+VEfw=="], + + "@autumn/server/@typescript/native-preview/@typescript/native-preview-linux-x64": ["@typescript/native-preview-linux-x64@7.0.0-dev.20260323.1", "", { "os": "linux", "cpu": "x64" }, "sha512-UvsQdVI/LayXTowltMgtg2GHU/a/lcuOYbaAYm9+/nvgIs01VqVo0s1/lTSNBzepEk0y1EOYQ6SIsRM9lLGHxA=="], + + "@autumn/server/@typescript/native-preview/@typescript/native-preview-win32-arm64": ["@typescript/native-preview-win32-arm64@7.0.0-dev.20260323.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-3208Xoe+3Xblf6WLVTkIdyh6401zB2eXAhu1UaDpZY0rf8SMHCxKW3TSJDytpri5UivCotZ0CNC2wgJ1TlymUA=="], + + "@autumn/server/@typescript/native-preview/@typescript/native-preview-win32-x64": ["@typescript/native-preview-win32-x64@7.0.0-dev.20260323.1", "", { "os": "win32", "cpu": "x64" }, "sha512-DAiRqrcs58eXwjFOtbklbIHq70IpW7uYz1Bx3kNAzqoWlA7R4mC29N6G0kGEZDalGmj7f0HVuckq9AzaC1r6oQ=="], + "@autumn/server/autumn-js/zod": ["zod@4.3.6", "", {}, "sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg=="], "@autumn/server/ink/@alcalzone/ansi-tokenize": ["@alcalzone/ansi-tokenize@0.2.5", "", { "dependencies": { "ansi-styles": "^6.2.1", "is-fullwidth-code-point": "^5.0.0" } }, "sha512-3NX/MpTdroi0aKz134A6RC2Gb2iXVECN4QaAXnvCIxxIm3C3AVB1mkUe8NaaiyvOpDfsrqWhYtj+Q6a62RrTsw=="], @@ -7972,8 +7988,6 @@ "fs-minipass/minipass/yallist": ["yallist@4.0.0", "", {}, "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="], - "glob/foreground-child/signal-exit": ["signal-exit@4.1.0", "", {}, "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw=="], - "ink-confirm-input/ink-text-input/chalk": ["chalk@3.0.0", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg=="], "ink-confirm-input/ink-text-input/ink": ["ink@6.8.0", "", { "dependencies": { "@alcalzone/ansi-tokenize": "^0.2.4", "ansi-escapes": "^7.3.0", "ansi-styles": "^6.2.1", "auto-bind": "^5.0.1", "chalk": "^5.6.0", "cli-boxes": "^3.0.0", "cli-cursor": "^4.0.0", "cli-truncate": "^5.1.1", "code-excerpt": "^4.0.0", "es-toolkit": "^1.39.10", "indent-string": "^5.0.0", "is-in-ci": "^2.0.0", "patch-console": "^2.0.0", "react-reconciler": "^0.33.0", "scheduler": "^0.27.0", "signal-exit": "^3.0.7", "slice-ansi": "^8.0.0", "stack-utils": "^2.0.6", "string-width": "^8.1.1", "terminal-size": "^4.0.1", "type-fest": "^5.4.1", "widest-line": "^6.0.0", "wrap-ansi": "^9.0.0", "ws": "^8.18.0", "yoga-layout": "~3.2.1" }, "peerDependencies": { "@types/react": ">=19.0.0", "react": ">=19.0.0", "react-devtools-core": ">=6.1.2" }, "optionalPeers": ["@types/react", "react-devtools-core"] }, "sha512-sbl1RdLOgkO9isK42WCZlJCFN9hb++sX9dsklOvfd1YQ3bQ2AiFu12Q6tFlr0HvEUvzraJntQCCpfEoUe9DSzA=="], @@ -8144,8 +8158,6 @@ "puppeteer/puppeteer-core/chromium-bidi": ["chromium-bidi@0.6.2", "", { "dependencies": { "mitt": "3.0.1", "urlpattern-polyfill": "10.0.0", "zod": "3.23.8" }, "peerDependencies": { "devtools-protocol": "*" } }, "sha512-4WVBa6ijmUTVr9cZD4eicQD8Mdy/HCX3bzEIYYpmk0glqYLoWH+LqQEvV9RpDRzoQSbY1KJHloYXbDMXMbDPhg=="], - "react-email/glob/foreground-child": ["foreground-child@3.3.1", "", { "dependencies": { "cross-spawn": "^7.0.6", "signal-exit": "^4.0.1" } }, "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw=="], - "react-email/glob/jackspeak": ["jackspeak@4.2.3", "", { "dependencies": { "@isaacs/cliui": "^9.0.0" } }, "sha512-ykkVRwrYvFm1nb2AJfKKYPr0emF6IiXDYUaFx4Zn9ZuIH7MrzEZ3sD5RlqGXNRpHtvUHJyOnCEFxOlNDtGo7wg=="], "react-email/glob/minimatch": ["minimatch@10.2.4", "", { "dependencies": { "brace-expansion": "^5.0.2" } }, "sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg=="], @@ -8174,14 +8186,6 @@ "requirejs-config-file/stringify-object/is-regexp": ["is-regexp@1.0.0", "", {}, "sha512-7zjFAPO4/gwyQAAgRRmqeEeyIICSdmCqa3tsVHMdBzaXXRiqopZL4Cyghg/XulGWrtABTpbnYYzzIRffLkP4oA=="], - "resolve-import/glob/minimatch": ["minimatch@10.2.4", "", { "dependencies": { "brace-expansion": "^5.0.2" } }, "sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg=="], - - "resolve-import/glob/path-scurry": ["path-scurry@2.0.2", "", { "dependencies": { "lru-cache": "^11.0.0", "minipass": "^7.1.2" } }, "sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg=="], - - "rimraf/glob/minimatch": ["minimatch@10.2.4", "", { "dependencies": { "brace-expansion": "^5.0.2" } }, "sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg=="], - - "rimraf/glob/path-scurry": ["path-scurry@2.0.2", "", { "dependencies": { "lru-cache": "^11.0.0", "minipass": "^7.1.2" } }, "sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg=="], - "run-jxa/execa/get-stream": ["get-stream@6.0.1", "", {}, "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg=="], "run-jxa/execa/human-signals": ["human-signals@2.1.0", "", {}, "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw=="], @@ -8254,29 +8258,15 @@ "string-width-cjs/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], - "sync-content/glob/minimatch": ["minimatch@10.2.4", "", { "dependencies": { "brace-expansion": "^5.0.2" } }, "sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg=="], - "ts-to-zod/@clack/prompts/@clack/core": ["@clack/core@1.0.0-alpha.4", "", { "dependencies": { "picocolors": "^1.0.0", "sisteransi": "^1.0.5" } }, "sha512-VCtU+vjyKPMSakVrB9q1bOnXN7QW/w4+YQDQCOF59GrzydW+169i0fVx/qzRRXJgt8KGj/pZZ/JxXroFZIDByg=="], "tsc-alias/chokidar/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="], "tsc-alias/chokidar/readdirp": ["readdirp@3.6.0", "", { "dependencies": { "picomatch": "^2.2.1" } }, "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA=="], - "tshy/@typescript/native-preview/@typescript/native-preview-darwin-arm64": ["@typescript/native-preview-darwin-arm64@7.0.0-dev.20260323.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-C3tQdgMaYn57xzRUWek+zNKMiP0z9j7fqbCjr0wlyiLNIh5jMwDArjBDKHlqSu58FKvZg7baqbqB5Mcepb3s6w=="], + "tshy/chokidar/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="], - "tshy/@typescript/native-preview/@typescript/native-preview-darwin-x64": ["@typescript/native-preview-darwin-x64@7.0.0-dev.20260323.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-YE6pD4wdMqNgaBkXicQBLFwABOEmLxDclSM7grl0fw4cQSbfVwFCbSlwFDkmISKdmsgtWdYeMohrsTU710ufpg=="], - - "tshy/@typescript/native-preview/@typescript/native-preview-linux-arm": ["@typescript/native-preview-linux-arm@7.0.0-dev.20260323.1", "", { "os": "linux", "cpu": "arm" }, "sha512-6zFO/SF9Gu8rtRyEt1b10TNapQGq5b/wUjCLG14675n155r4EO3JFMgnltBViV2Eatnq7G+bXD65BUBk7Ixyhw=="], - - "tshy/@typescript/native-preview/@typescript/native-preview-linux-arm64": ["@typescript/native-preview-linux-arm64@7.0.0-dev.20260323.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-Jzr2gBY0ifA3XejAl7kPeHLT72JFBfzLSafOAQbANh5Iag02uPl99k8ORMfKREbYgEMMOzqPpe+r6eaKy+VEfw=="], - - "tshy/@typescript/native-preview/@typescript/native-preview-linux-x64": ["@typescript/native-preview-linux-x64@7.0.0-dev.20260323.1", "", { "os": "linux", "cpu": "x64" }, "sha512-UvsQdVI/LayXTowltMgtg2GHU/a/lcuOYbaAYm9+/nvgIs01VqVo0s1/lTSNBzepEk0y1EOYQ6SIsRM9lLGHxA=="], - - "tshy/@typescript/native-preview/@typescript/native-preview-win32-arm64": ["@typescript/native-preview-win32-arm64@7.0.0-dev.20260323.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-3208Xoe+3Xblf6WLVTkIdyh6401zB2eXAhu1UaDpZY0rf8SMHCxKW3TSJDytpri5UivCotZ0CNC2wgJ1TlymUA=="], - - "tshy/@typescript/native-preview/@typescript/native-preview-win32-x64": ["@typescript/native-preview-win32-x64@7.0.0-dev.20260323.1", "", { "os": "win32", "cpu": "x64" }, "sha512-DAiRqrcs58eXwjFOtbklbIHq70IpW7uYz1Bx3kNAzqoWlA7R4mC29N6G0kGEZDalGmj7f0HVuckq9AzaC1r6oQ=="], - - "tshy/minimatch/brace-expansion": ["brace-expansion@5.0.4", "", { "dependencies": { "balanced-match": "^4.0.2" } }, "sha512-h+DEnpVvxmfVefa4jFbCf5HdH5YMDXRsmKflpf1pILZWRFlTbJpxeU55nJl4Smt5HQaGzg1o6RHFPJaOqnmBDg=="], + "tshy/chokidar/readdirp": ["readdirp@3.6.0", "", { "dependencies": { "picomatch": "^2.2.1" } }, "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA=="], "type-is/mime-types/mime-db": ["mime-db@1.52.0", "", {}, "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="], @@ -8950,8 +8940,6 @@ "puppeteer/puppeteer-core/chromium-bidi/zod": ["zod@3.23.8", "", {}, "sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g=="], - "react-email/glob/foreground-child/signal-exit": ["signal-exit@4.1.0", "", {}, "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw=="], - "react-email/glob/jackspeak/@isaacs/cliui": ["@isaacs/cliui@9.0.0", "", {}, "sha512-AokJm4tuBHillT+FpMtxQ60n8ObyXBatq7jD2/JA9dxbDDokKQm8KMht5ibGzLVU9IJDIKK4TPKgMHEYMn3lMg=="], "react-email/glob/minimatch/brace-expansion": ["brace-expansion@5.0.4", "", { "dependencies": { "balanced-match": "^4.0.2" } }, "sha512-h+DEnpVvxmfVefa4jFbCf5HdH5YMDXRsmKflpf1pILZWRFlTbJpxeU55nJl4Smt5HQaGzg1o6RHFPJaOqnmBDg=="], @@ -8962,10 +8950,6 @@ "read-pkg-up/find-up/locate-path/p-locate": ["p-locate@4.1.0", "", { "dependencies": { "p-limit": "^2.2.0" } }, "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A=="], - "resolve-import/glob/minimatch/brace-expansion": ["brace-expansion@5.0.4", "", { "dependencies": { "balanced-match": "^4.0.2" } }, "sha512-h+DEnpVvxmfVefa4jFbCf5HdH5YMDXRsmKflpf1pILZWRFlTbJpxeU55nJl4Smt5HQaGzg1o6RHFPJaOqnmBDg=="], - - "rimraf/glob/minimatch/brace-expansion": ["brace-expansion@5.0.4", "", { "dependencies": { "balanced-match": "^4.0.2" } }, "sha512-h+DEnpVvxmfVefa4jFbCf5HdH5YMDXRsmKflpf1pILZWRFlTbJpxeU55nJl4Smt5HQaGzg1o6RHFPJaOqnmBDg=="], - "sdk-test/next/postcss/nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="], "shadcn/cosmiconfig/js-yaml/argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="], @@ -8974,11 +8958,9 @@ "shadcn/ora/log-symbols/is-unicode-supported": ["is-unicode-supported@1.3.0", "", {}, "sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ=="], - "sync-content/glob/minimatch/brace-expansion": ["brace-expansion@5.0.4", "", { "dependencies": { "balanced-match": "^4.0.2" } }, "sha512-h+DEnpVvxmfVefa4jFbCf5HdH5YMDXRsmKflpf1pILZWRFlTbJpxeU55nJl4Smt5HQaGzg1o6RHFPJaOqnmBDg=="], - "tsc-alias/chokidar/readdirp/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="], - "tshy/minimatch/brace-expansion/balanced-match": ["balanced-match@4.0.4", "", {}, "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA=="], + "tshy/chokidar/readdirp/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="], "unplugin/chokidar/readdirp/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="], @@ -9132,6 +9114,8 @@ "@mintlify/link-rot/@mintlify/scraping/@mintlify/common/@mintlify/validation/object-hash": ["object-hash@3.0.0", "", {}, "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw=="], + "@mintlify/link-rot/@mintlify/scraping/@mintlify/common/@mintlify/validation/uuid": ["uuid@11.1.0", "", { "bin": { "uuid": "dist/esm/bin/uuid" } }, "sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A=="], + "@mintlify/link-rot/@mintlify/scraping/@mintlify/common/@mintlify/validation/zod-to-json-schema": ["zod-to-json-schema@3.20.4", "", { "peerDependencies": { "zod": "^3.20.0" } }, "sha512-Un9+kInJ2Zt63n6Z7mLqBifzzPcOyX+b+Exuzf7L1+xqck9Q2EPByyTRduV3kmSPaXaRer1JCsucubpgL1fipg=="], "@mintlify/link-rot/@mintlify/scraping/@mintlify/common/hast-util-to-html/property-information": ["property-information@6.5.0", "", {}, "sha512-PgTgs/BlvHxOu8QuEN7wi5A0OmXaBcHpmCSTehcs6Uuu9IkDIEo13Hy7n898RHfrQ49vKCoGeWZSaAK01nwVig=="], @@ -9214,16 +9198,10 @@ "read-pkg-up/find-up/locate-path/p-locate/p-limit": ["p-limit@2.3.0", "", { "dependencies": { "p-try": "^2.0.0" } }, "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w=="], - "resolve-import/glob/minimatch/brace-expansion/balanced-match": ["balanced-match@4.0.4", "", {}, "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA=="], - - "rimraf/glob/minimatch/brace-expansion/balanced-match": ["balanced-match@4.0.4", "", {}, "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA=="], - "shadcn/ora/cli-cursor/restore-cursor/onetime": ["onetime@7.0.0", "", { "dependencies": { "mimic-function": "^5.0.0" } }, "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ=="], "shadcn/ora/cli-cursor/restore-cursor/signal-exit": ["signal-exit@4.1.0", "", {}, "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw=="], - "sync-content/glob/minimatch/brace-expansion/balanced-match": ["balanced-match@4.0.4", "", {}, "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA=="], - "xo/eslint/file-entry-cache/flat-cache/rimraf": ["rimraf@3.0.2", "", { "dependencies": { "glob": "^7.1.3" }, "bin": { "rimraf": "bin.js" } }, "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA=="], "xo/find-up/locate-path/p-locate/p-limit": ["p-limit@4.0.0", "", { "dependencies": { "yocto-queue": "^1.0.0" } }, "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ=="], diff --git a/others/python-sdk/.speakeasy/gen.lock b/others/python-sdk/.speakeasy/gen.lock index 360e791fe..abdfa8845 100644 --- a/others/python-sdk/.speakeasy/gen.lock +++ b/others/python-sdk/.speakeasy/gen.lock @@ -1,39 +1,39 @@ lockVersion: 2.0.0 id: 05940b80-1ef8-40f4-9878-822fb2792070 management: - docChecksum: e9a1af9607edac6c1042359d221d1141 + docChecksum: b2a039ee0808d119f6be0c0d1504525b docVersion: 2.2.0 - speakeasyVersion: 1.757.1 - generationVersion: 2.866.2 + speakeasyVersion: 1.719.0 + generationVersion: 2.824.1 releaseVersion: 0.4.18 configChecksum: 2263d20254e354a1792248274002f650 persistentEdits: - generation_id: 5858658a-2678-4017-b8dc-74ec22fe0fb8 - pristine_commit_hash: d45b5773db5440b0a047a2faf64ad8441e828090 - pristine_tree_hash: 7d74d0d79af27f14da5af574c8cfe6671deed4b8 + generation_id: cf955dd6-87ca-4610-b2e5-d305fef5523b + pristine_commit_hash: 192f7483eda75fc42bfeeb9b13aa9f5790ef8607 + pristine_tree_hash: a466b4e81e20d68c76a1721c9ade3187c3fedbb8 features: python: additionalDependencies: 1.0.0 - constsAndDefaults: 1.0.7 - core: 6.0.19 + constsAndDefaults: 1.0.6 + core: 6.0.5 defaultEnabledRetries: 0.2.0 - enumUnions: 0.1.1 + enumUnions: 0.1.0 envVarSecurityUsage: 0.3.2 flatRequests: 1.0.1 flattening: 3.1.1 globalSecurity: 3.0.5 globalSecurityCallbacks: 1.0.0 globalSecurityFlattening: 1.0.0 - globalServerURLs: 3.2.1 + globalServerURLs: 3.2.0 globals: 3.0.0 hiddenGlobals: 1.0.0 methodArguments: 1.0.2 - nameOverrides: 3.0.3 + nameOverrides: 3.0.1 nullables: 1.0.2 responseFormat: 1.1.0 - retries: 3.0.4 + retries: 3.0.3 sdkHooks: 1.2.1 - unions: 3.1.4 + unions: 3.1.3 trackedFiles: .gitattributes: id: 24139dae6567 @@ -49,8 +49,8 @@ trackedFiles: pristine_git_object: 338e57de579fc8a219b6580798c5632db01380b2 docs/models/action.md: id: 3b583d6a609e - last_write_checksum: sha1:098b94f92de64e0d8913334d0889fd85ebe460b6 - pristine_git_object: 7d100638aec1c657cb7cb6696ec0818b19661e80 + last_write_checksum: sha1:72773682ff50533bc180ba2562b9a99251b0ff46 + pristine_git_object: 2254d6362f569f198c928970f3bffa4a02a78730 docs/models/aggregateeventscustomrange.md: id: 6bcfabf82b0c last_write_checksum: sha1:db82c5b951354ad2d10f2346cf57b098402df524 @@ -73,8 +73,8 @@ trackedFiles: pristine_git_object: 2fd7b5fb0f426ec942cb43aa30d3a85287ef724a docs/models/attachaction.md: id: 984e5ad5e280 - last_write_checksum: sha1:162c4a0771f000b3835c06765eafdd843fb8d2a7 - pristine_git_object: e9209701657b1cdd903b97261db2df27102eb9d6 + last_write_checksum: sha1:04e00a9143d9f5d350f7bec1cfe6651e07217f90 + pristine_git_object: b358eec0b5b32c184314a5c9b170f3074d577a55 docs/models/attachattachdiscount.md: id: 1283b5fb2544 last_write_checksum: sha1:fe32155e714211074643a30f70794924db11d3d7 @@ -85,8 +85,8 @@ trackedFiles: pristine_git_object: f680f716064012181c133cd1e21fb92b1bfc0b60 docs/models/attachbillingmethod.md: id: 99e45152f80b - last_write_checksum: sha1:e983973f9ef8a20614a75371e4c3fd0d4c477274 - pristine_git_object: 9bcf8a8f9f309f3eb1dbd23a03ba9e96fc7b46ba + last_write_checksum: sha1:b8221621e406f78f522156e0fa70d60014ad368e + pristine_git_object: 674a4b1c6077466a9b4d228fe743054b34f21087 docs/models/attachcarryoverbalances.md: id: e9af90ccd79e last_write_checksum: sha1:b6d60b17d15773c512653245b70f4a218d6b8b3f @@ -97,8 +97,8 @@ trackedFiles: pristine_git_object: ad5200ea1d15b517606e8f16bb2af11982b62f5b docs/models/attachcode.md: id: 1d55f798a682 - last_write_checksum: sha1:fccfcfb5a4d6ca2d6e54086340042de8e6ec0897 - pristine_git_object: 278b7f044f6b8e69ba9eb7ebc9d584425b0b758c + last_write_checksum: sha1:dd5a0adc97a023eec27540fe9bb590334ebcdcc2 + pristine_git_object: 1a1195e26b91cbb4948aa79005efbc85197c4d1b docs/models/attachcustomize.md: id: 46261b03538b last_write_checksum: sha1:8ae92012b8fc0197f260af1dc249f6bcede5447f @@ -109,12 +109,12 @@ trackedFiles: pristine_git_object: eba02df5a4003fe30622c5d39f4f972b73db7943 docs/models/attachdurationtype.md: id: 9e410a17d56b - last_write_checksum: sha1:b4b984d5cfbc57a83e5c2b6250da03ff9d3b0367 - pristine_git_object: bccfc3c11061b31ae5def04e1c32fb1b0f717401 + last_write_checksum: sha1:201a2d77508a63c17506d5ba9370d2736a8e2024 + pristine_git_object: d9256b21f869bf4d7fab1915970481f152437e98 docs/models/attachexpirydurationtype.md: id: 524cd5ddcdd5 - last_write_checksum: sha1:e76e5ff587821238b170d53fa37eb6b21c4640c4 - pristine_git_object: 4886da097384dc3a6a110e0d94fd2208556db9a6 + last_write_checksum: sha1:91fadc6920cc988fe2e0b5b02e56a137a3973396 + pristine_git_object: 96116d8755118d92cc4250d33231226b17e56eb7 docs/models/attachfeaturequantity.md: id: 5c9fae37c74a last_write_checksum: sha1:7447c83e4931c61fa08d0576e7e4390a363b448c @@ -137,16 +137,16 @@ trackedFiles: pristine_git_object: 5d7416d60f95d5c4c61f875c61abc909fd861647 docs/models/attachitempriceinterval.md: id: da3ed38a03d3 - last_write_checksum: sha1:8617ac575d72925866f581409bbd40721bfc20c2 - pristine_git_object: 82da5075c879543564d63eb2ddd16b019ca3a731 + last_write_checksum: sha1:7dc2a9864c52c09ca9e59ff09f7527345794d372 + pristine_git_object: c49d88c4c7696afe17566afb55b3eacb85bdc1b5 docs/models/attachondecrease.md: id: dd7dd5f2b175 - last_write_checksum: sha1:2b0fce8cff2835de026a9efd8574d0af5e731b02 - pristine_git_object: 5f6880b990bf2a7d57c16a07531d1e6d22961417 + last_write_checksum: sha1:c3d1c6a51c901ed80d02d4449f70ce839bf062fa + pristine_git_object: 2eb0944df8025fc478b80f965b0bda2ec9556c18 docs/models/attachonincrease.md: id: 8db7e1552d9b - last_write_checksum: sha1:e761df4e98dba4e4241a20c48cdaea2bfd9d9c89 - pristine_git_object: 4b75b3d142ea7237687dd5d3dd6a0e463186bbcf + last_write_checksum: sha1:7b90839a3f71de9a1b928b5cbb973fefdc2e4b21 + pristine_git_object: 0640ae26af1990b129e9d92f1f84c5b93dbe91e4 docs/models/attachparams.md: id: cc19aeb7efcc last_write_checksum: sha1:9ed344bd9f8aad64f2d3da9ac3946f44808f6130 @@ -157,28 +157,28 @@ trackedFiles: pristine_git_object: b0c7d55d66c6f3db5395dbebbfe6184f5ad9a820 docs/models/attachplanschedule.md: id: 5dedfadc5aa9 - last_write_checksum: sha1:158769029df8d0c3b0d57f044c93bbe6ac07a6a9 - pristine_git_object: 9e9142dc8bb2ecce0d1202d6774b4177a545c282 + last_write_checksum: sha1:2a3ba63683284a780e3271e87fefa1b5454d6d14 + pristine_git_object: 50e9fb97e031ae1980846b152a3aa8f5d04e0793 docs/models/attachprice.md: id: 5ac4c60e2ff1 last_write_checksum: sha1:ce20a5bbb0abafc24c72e6ed2f9ceacad6679eab pristine_git_object: 82e6a2748fa31e66759be781b6a8c0cbe60345f6 docs/models/attachpriceinterval.md: id: 8f4444fe4a59 - last_write_checksum: sha1:2d6bad7161b52bc32eaea682a20c915c51d8d155 - pristine_git_object: 0a6a983e4d750e436c4cc8e3bc8f04d625f97f40 + last_write_checksum: sha1:667c436605831e4482ea2ec4d8c1f3412baf3f56 + pristine_git_object: 8dbf9d9e66ad45a3c9b7928ecdc563a6a6f33ac8 docs/models/attachproration.md: id: d92b4c3cafc9 last_write_checksum: sha1:afb0910fbce9bf9150b725ea18333deac67a86a4 pristine_git_object: e4108282ef057841da4ce7c0b86014b093540c6f docs/models/attachprorationbehavior.md: id: 47599392eeb0 - last_write_checksum: sha1:3a04d2f088bccd574f05d49d9c5c21e7b8ed0861 - pristine_git_object: 925ea57b3dc4fb417c734ad9eeb3c161d2cfe68a + last_write_checksum: sha1:dffce59b18293fa90357642373404b09c5075631 + pristine_git_object: 73d6811a4272a920eaaf4fe92b9b956fcf1e32a8 docs/models/attachredirectmode.md: id: 335591f45026 - last_write_checksum: sha1:37faaec09ff06df901b61d54bfda8d9ccc014322 - pristine_git_object: a339d05aa7f3974607b4a5a9cab52883ad9ac3a5 + last_write_checksum: sha1:41a62121f86f18752a935e6b0b53570187514d78 + pristine_git_object: 0ca0543fee7eea64ff4c3eba17957936af819f76 docs/models/attachrequiredaction.md: id: e8ac88409626 last_write_checksum: sha1:d6e507f9cd1e47e617c13b69ab474f8dacd63c36 @@ -189,8 +189,8 @@ trackedFiles: pristine_git_object: e406e5ad17a15e88a409c3b1d4715dc367d1c6dd docs/models/attachresetinterval.md: id: b66e6fdb0dff - last_write_checksum: sha1:5829670189f8f07b56ae9b4fdb45530b248fa234 - pristine_git_object: 55acc0c8bd8c0f0a1ef9a99ae165a6ea5346648a + last_write_checksum: sha1:ce7b9746fcc351e855e23a01da8b484d752fe68c + pristine_git_object: d3a411212a7c9a04e791258b5c7b4d5025abbe47 docs/models/attachresponse.md: id: 8badce83e7c2 last_write_checksum: sha1:9b71d935c1dc9f81b2e5f1e8718ba2fe7737e27c @@ -205,8 +205,8 @@ trackedFiles: pristine_git_object: ac25813f9c9cd40bafa3fb187e30e61df7d6bfad docs/models/attachtierbehavior.md: id: dd4442a54a75 - last_write_checksum: sha1:6962ba9fa9fc4bbc5f8441a596e76b580850783d - pristine_git_object: 00cce5677a649f8df640605da745bb08a9ae5a52 + last_write_checksum: sha1:933eae06cb0235ae6d3c89de2d3ee2ac1d9ea35a + pristine_git_object: 3a306087ef917c5715f0d6c98f54682299662e7d docs/models/attachto.md: id: 1b02aab4ff64 last_write_checksum: sha1:808ce310ce6ff60548951c33b708bd7b5ea9a67d @@ -217,8 +217,8 @@ trackedFiles: pristine_git_object: b1aefcb1047dfb9c731d1518cbdf74e9372b4e0f docs/models/balancebillingmethod.md: id: 76fb2d92a3f9 - last_write_checksum: sha1:63c9d33198f6096715f3eb15a0b95ca0577d3fbf - pristine_git_object: 18ddc4890f476436e7bfbfdd04678613368293d0 + last_write_checksum: sha1:43baa9646b3939427ae05abfca22cbdff74a35ea + pristine_git_object: c226bd34b47d5c7e7c2f7515545e739dd09c2e44 docs/models/balancecreditschema.md: id: dae51ba88e27 last_write_checksum: sha1:0a21dcca4349bae735898fc945098b921ae57892 @@ -233,8 +233,8 @@ trackedFiles: pristine_git_object: f2c3a195899b943768528924a018dd292e021fc7 docs/models/balanceintervalenum.md: id: ed4c1f705227 - last_write_checksum: sha1:77b828fd35efe794358527090fa4d9ad5e3e0049 - pristine_git_object: a61d3a48fc7daf0eb1e4db4626514a90a77b88b8 + last_write_checksum: sha1:e7904ec75c5f69afb14c17885ad9c89dbf9f0122 + pristine_git_object: a65f5523a040e8a83f482d5d4a257b3954615d3d docs/models/balanceprice.md: id: b299e024076f last_write_checksum: sha1:feab76c2289c4d0e195ac5a4c79def50190d3ca7 @@ -249,40 +249,40 @@ trackedFiles: pristine_git_object: 43c658b3efea42752d73bd913e72a865bb7d9125 docs/models/balancetierbehavior.md: id: c5d6d94e4c04 - last_write_checksum: sha1:b5b090556f2b01e915f8947d23cf3b86b035b49f - pristine_git_object: 90f2ca6d455e580585ed339a4eecc9552c55208a + last_write_checksum: sha1:8c6caa64e60d7c93bfaffaa25cb758b61547d75e + pristine_git_object: bdcf40add36d9f3a50497013067d69e50fd30724 docs/models/balancetype.md: id: 75c2cae544fe - last_write_checksum: sha1:09514e05b48bd58bd5f6a2bd6f33ba3f0b0ad957 - pristine_git_object: 15b56e6a26511479ac90168ff02e708073684ad4 + last_write_checksum: sha1:421b637d3c78e46253b1c7e2647f6ff87044445c + pristine_git_object: 593a752a830a4abd82ce47a483331b88395e9835 docs/models/billingupdatebaseprice.md: id: c632c15479cf last_write_checksum: sha1:f6208715f5d3eea0ffb73dc8bfd4135c9b278255 pristine_git_object: f26d6458df8d6d17c0e3d14b40cea37100ecbf6c docs/models/billingupdatebillingmethod.md: id: 12159f4a0d20 - last_write_checksum: sha1:0b777e760bec198d3424ac3264f729185d0404cf - pristine_git_object: 17c5fbf6b42345e437c1ea9acc642da096aff400 + last_write_checksum: sha1:21bba85f59699f5bf1e8497ecce35e67b70fcac0 + pristine_git_object: f3d2efee7277bf813f083016c499077f4c3bc474 docs/models/billingupdatecancelaction.md: id: db6ed95035d6 - last_write_checksum: sha1:602b218add93ba7c1321fae1519f4c71e742067a - pristine_git_object: de773d6ff842d49bad76dfb878a4f4a5b9f12425 + last_write_checksum: sha1:6781ff5f812623eb2d4c362ab478433515f16003 + pristine_git_object: 7e74a4b0dbbd3d2665ee3444031ca58e2f3262b9 docs/models/billingupdatecode.md: id: 9b4598eb634b - last_write_checksum: sha1:ab83e37b31683591f116c230145ba361bd2aba67 - pristine_git_object: b84d2bb18ea93dcf6314b5d3193dc413e94e897a + last_write_checksum: sha1:58ca1664740b44d0eca145f2222d801423c9ed22 + pristine_git_object: ed6a76be783d37f8b7dab9629f4e4b24dd944d0c docs/models/billingupdatecustomize.md: id: 72b14fed6d26 last_write_checksum: sha1:c87d10da6d0f4468644d1d6ded6f105bee61dc5f pristine_git_object: 52bbdf8edcc89477c447f910b8d8bf5e9f6a9684 docs/models/billingupdatedurationtype.md: id: fd1bfb929148 - last_write_checksum: sha1:4ecc7d22519fc4f6b45ca394942f2e2bb7d6e008 - pristine_git_object: be30454f05e84698e39999db581e7d41ceb6ef4f + last_write_checksum: sha1:bed8f44bace7e7187c9a6510549b1a25e0893db8 + pristine_git_object: 29c75dda04da8317052ea821f1a2954a9572958e docs/models/billingupdateexpirydurationtype.md: id: 53d2632a7c8a - last_write_checksum: sha1:47b570d582188a62b914297406dab2267111105a - pristine_git_object: d2c185e5c8ce8a6fe06f557bd9eb1c3c3b2d0c42 + last_write_checksum: sha1:7258e9d4c17f5966c6ceaa20e71963da5e77bfe4 + pristine_git_object: cf21b1895d1b383d88b984f4c62f881d11b8994f docs/models/billingupdatefeaturequantity.md: id: e799ad33bb5a last_write_checksum: sha1:c65f7f8271bdffbf5182af05e9ebdeecc37e42b1 @@ -305,16 +305,16 @@ trackedFiles: pristine_git_object: ccc987c410b54cdfd945b0a4c54020614b9d3e65 docs/models/billingupdateitempriceinterval.md: id: 0cec75e3f2ae - last_write_checksum: sha1:a0b1cee7b78bf47a51bdaa18f82fc83082474c5c - pristine_git_object: adf8b59604bd7afd87a739d39d30e1fb92aef798 + last_write_checksum: sha1:23f7e1aeb4061a35ca0ef1008a182d58d48ce07f + pristine_git_object: 876d9175009bf7588f4c069b81e9eaa9ce8c13c0 docs/models/billingupdateondecrease.md: id: 1524bf987a6a - last_write_checksum: sha1:ad8244fe62d4af25862d59c4ef2d70dcac190b7c - pristine_git_object: 0d76e192a32de2b827ebf629924e8fcc682d2094 + last_write_checksum: sha1:61be180db7fdabd7c4deb67c479101c5a2d71d3a + pristine_git_object: 20bd4b901deaa9b626423150dd187ce2d81846d8 docs/models/billingupdateonincrease.md: id: f43ba81c2c74 - last_write_checksum: sha1:8f355eda384db6aec10dbd583f2446689bb7dbf3 - pristine_git_object: 6b5a79d32eb477e8449f09e61cb2e758831cb858 + last_write_checksum: sha1:bde4ff3aac2375c4116af12c88c7a66cc7adabb3 + pristine_git_object: 2ae60a2cbc19c1d08f22485f371ef2eb49b3eab7 docs/models/billingupdateplanitem.md: id: 2a54ff8cadb0 last_write_checksum: sha1:1acd9eeebc8041d0298d79e4bfd8534b0b497aa6 @@ -325,20 +325,24 @@ trackedFiles: pristine_git_object: b7c4d7f98430c5f6cad62591307b6616aa9e19d2 docs/models/billingupdatepriceinterval.md: id: 35fa4e54bdfa - last_write_checksum: sha1:c0da44caf43fa226e1f4c61f66105a12dfaf7799 - pristine_git_object: 5bf583ddc236556a6cc1bf48870860d05db61adf + last_write_checksum: sha1:f800390f9ff92064f4cfd8a7a9e1a974e9735ae7 + pristine_git_object: fef99c2a4d614825ca172aac2fbad7232f797067 docs/models/billingupdateproration.md: id: ceef03cb88fe last_write_checksum: sha1:349ef125fcb651dc625984c657e2b2904443fdb4 pristine_git_object: b08ae1cb77d8adce2b494a8c9f8d82458b444e8a docs/models/billingupdateprorationbehavior.md: id: 59e4a7bd5f57 - last_write_checksum: sha1:4f839363f995381f5c7b5e9781970c7f6b89cac6 - pristine_git_object: 2fe315798c7425eea4b333ea5a3be11455a5e45d + last_write_checksum: sha1:25cc1dae82375b1355bb8c0258f8345a2ab2749a + pristine_git_object: 605a70dbef1054518e8bc4247cffb2cd78ca9f9e + docs/models/billingupdaterecalculatebalances.md: + id: 1efafc117462 + last_write_checksum: sha1:814d945540f0a000cd468ab8c050dc04af751cf8 + pristine_git_object: f23cde4509ce1e504a1bde766cb403ab35fd4d1e docs/models/billingupdateredirectmode.md: id: 9043a4aebf85 - last_write_checksum: sha1:225186c2fb33963411f365af1d6f4027e9090d8d - pristine_git_object: 98f3b96b091cd701813df6f7f5b1063fcd7c2c49 + last_write_checksum: sha1:ce637ed16ebd5095db5b5d3adcb8328018ad68e1 + pristine_git_object: 6a04e02359a17eab6227afff69b20d2d88b5708c docs/models/billingupdaterequiredaction.md: id: 3f84a7bd8718 last_write_checksum: sha1:999727446d5c53ece4c816c145063ce6f0ab0ee0 @@ -349,8 +353,8 @@ trackedFiles: pristine_git_object: 39ab16e4993be894423a09a9d2b726b40152cd21 docs/models/billingupdateresetinterval.md: id: 6031d36eb382 - last_write_checksum: sha1:b4e834b3638a22a0440ef50a13658936813746c9 - pristine_git_object: c60e227356d9d41dbde8517bdc61459c23f54165 + last_write_checksum: sha1:eeebd0210c9acebb03067c6ecea686ae95569312 + pristine_git_object: 8fbdcfac41ad16f89bf3ff8bdaaebb2dfeabaa72 docs/models/billingupdateresponse.md: id: 61961e78dc41 last_write_checksum: sha1:3c7a336951e5b2349ec5f69ff87fba2f894f98e2 @@ -365,16 +369,16 @@ trackedFiles: pristine_git_object: 36a8fe04fed81da560d7c510824a87772ea104c4 docs/models/billingupdatetierbehavior.md: id: e232f14f3859 - last_write_checksum: sha1:9255c48e25a922281551b4775e3876ed09e01173 - pristine_git_object: 93e790dd724353b2321f214c97c39131502c54a0 + last_write_checksum: sha1:e04c169893bec388a599fff7e60d82dbde0ff633 + pristine_git_object: 70caee9bb271631dfca70f5a09d91c4981249b85 docs/models/billingupdateto.md: id: 2dbc89773256 last_write_checksum: sha1:ac60ad0fd88dab5a347f21563cad039fdf8719c4 pristine_git_object: 1d40f1e0e3af491b7e67142f4d46d7e6bd68377d docs/models/binsize.md: id: 63f34acef7f6 - last_write_checksum: sha1:58322acf712532406cfae8aacc0011d342fc0e42 - pristine_git_object: 0d7ffd05f43810c7972b53983a26562cf1edf375 + last_write_checksum: sha1:310b19b9bf005367f9bb9b8522f236b116d4c8de + pristine_git_object: a5d47c7f43395017abd9061c252a8ff8ed986985 docs/models/breakdown.md: id: 786823ab8ff0 last_write_checksum: sha1:8d7542dc9cdab711fa44b08449f023cf51d0bf2e @@ -385,8 +389,8 @@ trackedFiles: pristine_git_object: 569f641aa37bd931f49d93ecc912d48d01ced164 docs/models/checkenv.md: id: badd8ba846d9 - last_write_checksum: sha1:cc58aa52d618d5718048c72c1d832c22f4fa4d44 - pristine_git_object: 2ecd490b20e9ddec41e2de895dc878bfe1e735f5 + last_write_checksum: sha1:0151f2e60f1949039194de96b878d440e0cbc7df + pristine_git_object: 063b53ed4d0dc95e2b45e40834f12b7da38014de docs/models/checkfeature.md: id: 578a088d181f last_write_checksum: sha1:79c138d673342ee61ffdbb8befdf15d35ef9a6da @@ -401,8 +405,8 @@ trackedFiles: pristine_git_object: db1b11678847be436d8d702b1dfe38fbadfc0b8c docs/models/checkinterval.md: id: 8d4fa19b99cf - last_write_checksum: sha1:1de9a5b6c8246013c331c029eff593c7d9107a0e - pristine_git_object: 7ab99824ba2b1ea51adcc3e6e1f8ed71b9a41f41 + last_write_checksum: sha1:190b1c37ca471b3afb3b61737b121032c99fa9bb + pristine_git_object: 188519a4cdc6cc4b616dbc0f4dc4c7284bd8a6d4 docs/models/checkitem.md: id: 17b1916ed078 last_write_checksum: sha1:777d0bcb69a475b1fdc64a491604f77c3892cbd4 @@ -413,12 +417,12 @@ trackedFiles: pristine_git_object: 6a029c8c5367cce65667868341d1026f540f416b docs/models/checkondecrease.md: id: 2c49735aaa4e - last_write_checksum: sha1:fbc0d73b600c664d71588db64a01f63ae9730c6f - pristine_git_object: cdbd3eee0b4829c3574a58eaee0919e3456de0c4 + last_write_checksum: sha1:957ef5f0c483f390fab1bd6bb9ad1f21697d1898 + pristine_git_object: 924902d404be8c5cca46410e8bd6d16858feb14d docs/models/checkonincrease.md: id: 72e23013a321 - last_write_checksum: sha1:285a9c0f5eedf50bf8345017cb5281054394fbf3 - pristine_git_object: 9e7cf1470360e6e191df1c53f875ddc2efce56b0 + last_write_checksum: sha1:72f018b178859f870d47e4c482ad9f734591d2c6 + pristine_git_object: 188c047ce6cdf1f916ff0e22079a8fed3e3d8916 docs/models/checkparams.md: id: 41de438d57cd last_write_checksum: sha1:ab7c54bfe0c657851a59fedd447c99bb3acdb4c2 @@ -437,8 +441,8 @@ trackedFiles: pristine_git_object: d41a6997c8fa42b8d2aba6ad2a63ad74af9ce769 docs/models/checktierbehavior.md: id: 9617428cc802 - last_write_checksum: sha1:50402db6b459dee47f0d1286dac1a86ca3608824 - pristine_git_object: 269d3333807ff7d70963551a083aa7ea5f8f397a + last_write_checksum: sha1:fa41c52ec15e0f7cb7d859c0fa26112ed11f5e91 + pristine_git_object: 07d0ee6f485f4056f4e301174ad0e7a37143e032 docs/models/config.md: id: bef254bf823c last_write_checksum: sha1:39b253e50c394f0b9bdf4f3edc73d874b5b1777c @@ -449,8 +453,8 @@ trackedFiles: pristine_git_object: e6e79f4e93370dc83282c623a6f44d19c89819eb docs/models/createbalanceinterval.md: id: bc0616b97b83 - last_write_checksum: sha1:30235488c4a82c0fe10fc60d7e8b6a918b72c823 - pristine_git_object: e39a9187a872a4ad57c7a08e78ef7c53dd344497 + last_write_checksum: sha1:1f4c49bd045c70e1562b1316837856a62e07a93b + pristine_git_object: e335f5306f33da5881881ffe48510fbc90672b3b docs/models/createbalanceparams.md: id: 9091a9b23319 last_write_checksum: sha1:bf6be59205f8f9574a5c0206f4e15551177407c8 @@ -465,12 +469,12 @@ trackedFiles: pristine_git_object: 073f7e796daafe7be8710624ee76d22d7a8b7145 docs/models/createentitybillingcontrolsrequest.md: id: 81bfb7ab2ff1 - last_write_checksum: sha1:27a4149c82ead6c1664c5a34bd7667d0ff0f1b69 - pristine_git_object: 15936d052b139c78f010480496ba4fd845b13169 + last_write_checksum: sha1:7c6cda7d6e0a41dc5c5323d527b4713fb621dcd3 + pristine_git_object: c23fef26c1dd8422d33747fcfb5ea11a5d9d54fa docs/models/createentitybillingcontrolsresponse.md: id: cb4c5b406c38 - last_write_checksum: sha1:810db06fba122ecec3b9dd10a51d5e3672262548 - pristine_git_object: 6594e1414eb2029f22426a9f623e4eb6b9ebbc97 + last_write_checksum: sha1:e70fdfd2f4229e07a06b58b22622e216bbfe2fd1 + pristine_git_object: 306b05bd5822b4dca5b488aa4c194bf3f06ac26e docs/models/createentitycreditschema.md: id: be01ed32c75d last_write_checksum: sha1:f5aff2afb245821c6acee3b54af1a9e03ddc7497 @@ -481,8 +485,8 @@ trackedFiles: pristine_git_object: 711fe44f735d330501bbbe76cd793b9c2755e0ea docs/models/createentityenv.md: id: 542876d21db6 - last_write_checksum: sha1:17bd7dd672b53ce44c9f54e5ef1b79aa4c98512d - pristine_git_object: 5d6211aeda9b6edf22bdacc3753cfad11b80126b + last_write_checksum: sha1:b73f6dc451b4e5ec7c9f9c71cd8bb517c176ad52 + pristine_git_object: 32f81e68dc328b00f43653be74163dcf7053f555 docs/models/createentityfeature.md: id: e029c7ffe3b3 last_write_checksum: sha1:bf16dd1e2a5f791e737caa9a6ad3a492be32ef0f @@ -521,16 +525,32 @@ trackedFiles: pristine_git_object: 4004ffb5832713e76b8a6b176469631039bba606 docs/models/createentitystatus.md: id: 145efa808359 - last_write_checksum: sha1:3695fcfd019e564c095560b4b1265643a5f9b285 - pristine_git_object: b3778ff16df6323f7493fd94455681c833b66091 + last_write_checksum: sha1:72bb5c58fea5e9dc436e93e1638e6817030ae3ce + pristine_git_object: 9a91415c612c744fbc62d49d23046320057421eb docs/models/createentitysubscription.md: id: 8aa96fa32fbf last_write_checksum: sha1:8ec950859a22ebd2187914d27bd442f3c0452116 pristine_git_object: 9586cfc0faabfe8e90fad4a79098f124ac3649ac + docs/models/createentitythresholdtyperequestbody.md: + id: ed52dc34947b + last_write_checksum: sha1:542ccbde26267fba9051a3d643fc40053732b573 + pristine_git_object: 78b02d2d87153b4fae5580a2bf322a3fe79e5885 + docs/models/createentitythresholdtyperesponse.md: + id: 52891c7cc403 + last_write_checksum: sha1:077929b1b4e38f3fda710be0aeee3d8cbce11112 + pristine_git_object: 6ad3db991458ca94aa4d0f6a2f5753ab9d872f41 docs/models/createentitytype.md: id: 32635d8bbeec - last_write_checksum: sha1:23b40023f5a46fd8d8309b7bd11cb2c16168601d - pristine_git_object: e9289481db3fca2916797cd0583a9b407c6c9dec + last_write_checksum: sha1:fba880b57b7e4267002a667047cbd7379b23ff05 + pristine_git_object: f761de0133e3ca5da5d7dc0809022ba2c2df72da + docs/models/createentityusagealertrequestbody.md: + id: 6c9e600d7cb2 + last_write_checksum: sha1:55bd55e606ab494a412d311cce18409109277fd8 + pristine_git_object: 80a9eadd5b83acbe72d53567ed277f36f8bca75e + docs/models/createentityusagealertresponse.md: + id: 19c3b14a71d4 + last_write_checksum: sha1:015e39c299a6a985eac38382b76fc917253bea9e + pristine_git_object: b7bed983dac8106af2f6327f1bc11e338900cf46 docs/models/createfeaturecreditschemarequest.md: id: 14932a0ada38 last_write_checksum: sha1:3ed6eb2080d0f207c81415025fca068be6dd3e6b @@ -561,24 +581,24 @@ trackedFiles: pristine_git_object: eaaac3dc55e7e703c2801c86f267cc84cd1463f2 docs/models/createfeaturetyperequest.md: id: fe6cd361268e - last_write_checksum: sha1:691716b1b97a99fd39d1c6fac575ad6e7d3a8d48 - pristine_git_object: 38d707117cd84c9b5fde3360d169f476107e9271 + last_write_checksum: sha1:f78d41e61f5bbe3251be89c0bbfa057d878d5309 + pristine_git_object: 7666bee271876460789f89488630ede75a34040e docs/models/createfeaturetyperesponse.md: id: b48617bd07bb - last_write_checksum: sha1:77ac606e5f0b689983ff6c609fdae20ef2ac2fec - pristine_git_object: e4428c360251496590101bafe621d2622acb8074 + last_write_checksum: sha1:cbae35ce696b95160ace214ff4a3729e9bb31620 + pristine_git_object: 6c35a4a0f2792209d946d20c80d30b2e024447fa docs/models/createplanattachaction.md: id: 51fddcdddcfe - last_write_checksum: sha1:9418a9072d39278ed789c16429958ee8b4e675d6 - pristine_git_object: 18912b7d8ea75eb28d8c7b26b260cbe0b7b3e5ac + last_write_checksum: sha1:76c48bcbf392473ff6f5a56106d3701bbd50f6fb + pristine_git_object: 345f2d19573e26f36c42cde6f8465c705184d1eb docs/models/createplanbillingmethodrequest.md: id: aad7cd71a9d2 - last_write_checksum: sha1:7ca5d093290ef5c5cfe9c1a912557e1712130470 - pristine_git_object: dbc67b61a533d4902f48db8a2858b5f6d7070d7e + last_write_checksum: sha1:1f2c67600db50f95337d7bf10c639e908c3fc303 + pristine_git_object: f29aef01df9f6dd537344c49f397a523c7501d9b docs/models/createplanbillingmethodresponse.md: id: b307da22d211 - last_write_checksum: sha1:cb2e4a736b4ecc159767a293453ff87f9ed0c9eb - pristine_git_object: 4a0d24cd6c7d3f100ff059751be33862a199c471 + last_write_checksum: sha1:3fcd6017bc7cb96ce77ca920fe451f9a4883a5c2 + pristine_git_object: 39cd257f0f31b76bcc61c394f1fe4bded4a0b382 docs/models/createplancreditschema.md: id: bda39f39fac9 last_write_checksum: sha1:8d3bf3dfd849ce3112674c8108d75e77bbf40d92 @@ -589,24 +609,24 @@ trackedFiles: pristine_git_object: d2a842647d543d4989a1efaafad2869698f7a2ac docs/models/createplandurationtyperequest.md: id: e21beb31d05d - last_write_checksum: sha1:2e1053332ad2fffa785d83b2abbd2a2c2819d83e - pristine_git_object: ec28bef94c8054678f4281cece7380def75172c2 + last_write_checksum: sha1:60840dd5ae3e89cfaa4c6ea23e8e5a604558a533 + pristine_git_object: 83013099132a30036afccf717a1c2c5d2b21bd23 docs/models/createplandurationtyperesponse.md: id: 1489338c4397 - last_write_checksum: sha1:56f707111b6879c0e705055c38a399d42245fe4a - pristine_git_object: a8382826dee5bb5e17d0ee5fd0382deebd31f738 + last_write_checksum: sha1:0f119191f861ab525cfc3408963d498ead41c6a4 + pristine_git_object: 19341d579df11c5ecd96cd8f2997df9b81677719 docs/models/createplanenv.md: id: 7ddb245035c3 - last_write_checksum: sha1:8f0361ff0433ad6468bfbd5f284cf446571cbcd9 - pristine_git_object: 7343391ed2b1ae2ad30b1f140c9616eeb77555f5 + last_write_checksum: sha1:8ac8cbf49092cb5887f4403fdad7b8bef8dfd247 + pristine_git_object: 0d52c5ca2a9e155d27feb55cc101f0b62c76d9ba docs/models/createplanexpirydurationtyperequest.md: id: 8bce768b39f2 - last_write_checksum: sha1:613b0344d6211e5da5ac517f69103bc7cf87f01c - pristine_git_object: 897223bad7e0b51d451ab358e47720e862274374 + last_write_checksum: sha1:628b35272d8ce2add899c6c19aa96be3d2a42a0a + pristine_git_object: 54bb9e36c6284852b4ce37e4149abb49ba3481bc docs/models/createplanexpirydurationtyperesponse.md: id: 00879e9d2363 - last_write_checksum: sha1:626ca951ef32e1019dc32dc7b8f183cc277366b2 - pristine_git_object: 0378b9b88c15b3dacf83838e35a47a7bd8e9ff54 + last_write_checksum: sha1:1310562642734128d164b805256f66a2dfa1950f + pristine_git_object: e752ec9afd9d7423ad5a5e52bba7c879930e5a0a docs/models/createplanfeature.md: id: b48fb179ae52 last_write_checksum: sha1:9b823d276ad5c6b6bd26d7802f91a83526c2f1f8 @@ -633,8 +653,8 @@ trackedFiles: pristine_git_object: bd384b452456016555d00559f6b3dab88c1ea4d2 docs/models/createplanitempriceintervalrequest.md: id: 18e0dca1ea6b - last_write_checksum: sha1:a789b4621eacdc2744f6257d3d2ec7c5a9c124ad - pristine_git_object: 5894f12d49cfaec84941e5612027928689d60d7c + last_write_checksum: sha1:f022dc04fb84189001d091aa855f585d0b912bc3 + pristine_git_object: 5ab2ea0a0a614abf498ef68a3365d1c64ac01613 docs/models/createplanitempricerequest.md: id: baaf8916c3b6 last_write_checksum: sha1:b3294dc1d5c7340bbecafacf66d64957b530a7d7 @@ -645,12 +665,12 @@ trackedFiles: pristine_git_object: 0e45fcef8a9c84780166602dc20ffbbbcd1463c1 docs/models/createplanondecrease.md: id: 13e92221faaf - last_write_checksum: sha1:afaf4c77970e09e2f8cba839ca6a5a4eab7ed028 - pristine_git_object: 43784ae3c14f6d07d58561744d304ff5c2a1f667 + last_write_checksum: sha1:c384c642ec8b7025a2e0fc74166e2153e417c173 + pristine_git_object: f4f2fd1c2dc8703409e66dc667956032309a2536 docs/models/createplanonincrease.md: id: de4cf324fe3c - last_write_checksum: sha1:66123ea9d2e41d8eec9df9dc11822c86dbed94df - pristine_git_object: a7cbec89d5e586f2e506b7fac6a14d299e227ee2 + last_write_checksum: sha1:5ff8337e204975963b88911abe70e986a40f7006 + pristine_git_object: 32d69248af29180c404ad5b0343a963e276ddcea docs/models/createplanparams.md: id: 83565eddc151 last_write_checksum: sha1:a585f44a9afc78624bda890e35c8fa50668c4248 @@ -665,16 +685,16 @@ trackedFiles: pristine_git_object: c329aa588b3946be41c98de8407001fad94759d1 docs/models/createplanpriceintervalrequest.md: id: e2978f16aade - last_write_checksum: sha1:be607cfb579147ddd94dd1a82a192fa825ae8355 - pristine_git_object: d15692141667a70c734901f70a0f7874748007ee + last_write_checksum: sha1:6a9bab6ba28f5b0b04f6343ddf478a3d0498f843 + pristine_git_object: 7d5a547c8168af9b4cfeba2fb9fa5c7b5c40a5a0 docs/models/createplanpriceintervalresponse.md: id: f872fc43537d - last_write_checksum: sha1:c4dcd437608e05903abbcaaa3b5436e89e2c3751 - pristine_git_object: 51398aaab5bd3094d490023e1a62bbc8f26752cd + last_write_checksum: sha1:79245427f2125d009533d4e932cb7fbf13040539 + pristine_git_object: 3b55edf3fd8d2f74378fa8f4a7d126fba60784e3 docs/models/createplanpriceitemintervalresponse.md: id: 24549a1388a1 - last_write_checksum: sha1:48389d49de582e1ce66bb73ac3a97e14f9d09421 - pristine_git_object: c1e2f83b4b2745109f05429dc564381e35566913 + last_write_checksum: sha1:2b92c1885222f908b45d789d0c35bc26f4f69fe1 + pristine_git_object: 505ffa29519c0299196f77893d21b1c03416ef1e docs/models/createplanpricerequest.md: id: f12e1c990ec1 last_write_checksum: sha1:78d33eb36c61df233aeed99741f184760683cca8 @@ -689,12 +709,12 @@ trackedFiles: pristine_git_object: fefa0c8a14e9b08d8317fc8d3733dbb42f1dca09 docs/models/createplanresetintervalrequest.md: id: 0cddef9265c3 - last_write_checksum: sha1:af71157c843c2697f551d58b091bbfce73b380b0 - pristine_git_object: 77e07403fee45b00512fc707de405b9000abf7dd + last_write_checksum: sha1:4bf315605d9c46fc8aeae11e89708c8013b0fc6b + pristine_git_object: b2afd01b4d40951ec598280850b0fd3ee874c956 docs/models/createplanresetintervalresponse.md: id: b17cd3a6cba7 - last_write_checksum: sha1:a7fc918adc597dd6a8091837d069ef23b783d966 - pristine_git_object: e23ed719cb9b9068ce42ba8db9a4256bb582faf3 + last_write_checksum: sha1:b2d389267bac50ef73d4cf4afa23752778aa245a + pristine_git_object: fde9015d34005ce408769d28469ff9bd824fff10 docs/models/createplanresetrequest.md: id: 4269e3fff10d last_write_checksum: sha1:81ba6a1a229a056e81142b59227d39db3a6b6f4f @@ -717,28 +737,28 @@ trackedFiles: pristine_git_object: 1036a2ba0f28e32f48985255aecfa3bb52a0f679 docs/models/createplanstatus.md: id: c67e48774d6f - last_write_checksum: sha1:0e73a49760bb7b7240413e82280e4bf14527e81f - pristine_git_object: 0a02b6243e4951579c5296f3b0de279a6734bb53 + last_write_checksum: sha1:c19eea42455c259881ea44f52e6329d11bc2b924 + pristine_git_object: 42bd2e4fcf5c2d89d65e13476f984c3ccf48f874 docs/models/createplantier.md: id: c582ff76d889 last_write_checksum: sha1:159c3f51cdcde0027f66b0dc8ee14e44a3400c39 pristine_git_object: 9cf6204964346d5215a14551c0cac01660077d29 docs/models/createplantierbehaviorrequest.md: id: 2a8236046547 - last_write_checksum: sha1:884fc740aad1e4d1929feac86e4f8b3984fd305b - pristine_git_object: da7dc3726e2780838412c24fc2d12bd92bbbb21e + last_write_checksum: sha1:8d6231303c39b89b6e22523bc59f340c51762a5d + pristine_git_object: ed54766809f122caf3b59dd08c1f424856dfcdbf docs/models/createplantierbehaviorresponse.md: id: 491d2246191a - last_write_checksum: sha1:6fb032a0cde153e82c9ac9770fcf90fc7b307275 - pristine_git_object: c20a82090b832368daed398af77dca93bf0c78fe + last_write_checksum: sha1:b193b869eaf1688500ecaafcd2bedd1bde2aebf9 + pristine_git_object: 7f8c20b4309c3e5c3169f8da82b30d7f6303ad9a docs/models/createplanto.md: id: 3833b33d43ec last_write_checksum: sha1:bcb546882173424d017121b0557a8ffeaa27ab55 pristine_git_object: 420a9bf4ba28c64093d17fc095b8af35fe9f0d8a docs/models/createplantype.md: id: d50ef0678a3b - last_write_checksum: sha1:a42c152f56d182a6561686883df41eb1530c3605 - pristine_git_object: e663cedb4dcf7df50c677067c84556d8da938492 + last_write_checksum: sha1:70cd59b183f2e587a037bc5485453286d1a32dce + pristine_git_object: 32d3faf1d3017535673cf37297dc291ae3bf19d9 docs/models/createreferralcodeglobals.md: id: 368eaec7a9b4 last_write_checksum: sha1:abfc0223ac79b4ce82dc286b7eaec9ee7003a10a @@ -761,8 +781,8 @@ trackedFiles: pristine_git_object: c6e96becb74aa8c2a46feabb115ee3a5e735e248 docs/models/customerbillingcontrols.md: id: 758d49afce18 - last_write_checksum: sha1:e67e19d12e17448784e78721acf3840df65858b4 - pristine_git_object: ca7bf388008cc62cafdae70d7a54ed07b4143430 + last_write_checksum: sha1:572699f4bfcc5fbdc163b02983aaf751c0ab2037 + pristine_git_object: caf99500eb9d21d73f870018ca43fca5e7c10bb5 docs/models/customercreditschema.md: id: 5d9998b21933 last_write_checksum: sha1:fcfbe3056729cff42c402b9619076db84ec6ffe3 @@ -777,12 +797,12 @@ trackedFiles: pristine_git_object: 5871d14cc4f423e29232741f509f84d2937d81da docs/models/customerdatabillingcontrols.md: id: 9a9f4fd47b8a - last_write_checksum: sha1:97a246baee322c664635c5bdbba0985df68a3f25 - pristine_git_object: 7edaea4795dd69bc57071089a71e6a911dfe84a5 + last_write_checksum: sha1:19d195343c43238015f387b0dcf153504f1e1fb2 + pristine_git_object: 8700212663dda7fba64d677c5f39cadda6b9c4cf docs/models/customerdatainterval.md: id: a79b8e0d599b - last_write_checksum: sha1:7edaa6ed15b9896fa1045791f15cdfa2c8ffb788 - pristine_git_object: fd98960fe70924ae085f3d9d4ffaf6715e1c5bd6 + last_write_checksum: sha1:f19b611ec3f7ebb76344457ab86412eaed888ad6 + pristine_git_object: 3356899bd9fb2ade4a84dc4dba3f5529f7a76501 docs/models/customerdatapurchaselimit.md: id: c415017a8c4d last_write_checksum: sha1:13ac00bcab77110548bcfacfc251d4b4972cd2b7 @@ -791,34 +811,42 @@ trackedFiles: id: efddd27334cc last_write_checksum: sha1:5e216993820eb4b9f994f6f5fd00d5dd36e1a2c2 pristine_git_object: bbc12b74a98a4afbad687b3ebf4d7d9c3486ce2d + docs/models/customerdatathresholdtype.md: + id: 9b731ba64207 + last_write_checksum: sha1:2723b21288c90712c180ed0c8f6a99fc04bcbe2e + pristine_git_object: 1fe92ece618b1ac10d97cc9d385c2a8a7343afb8 + docs/models/customerdatausagealert.md: + id: 5476e22ddcd6 + last_write_checksum: sha1:2c59cd3e3c7bcc5ac3e649fd0fe9f121af216e7c + pristine_git_object: 4706c3e4cf38b2b26f4c70d1e0781fc3d454cd2e docs/models/customerdisplay.md: id: 0afec61f7fd1 last_write_checksum: sha1:a3332a4b41b4be6018d42faa10f22f8082a327f1 pristine_git_object: 1ef71da1d5c2368ac687b9c2a6c24be24c3aa0e0 docs/models/customerdurationtype.md: id: dc88db3adc93 - last_write_checksum: sha1:e5274f776927c0d1ab9301bf2d03f61230af3420 - pristine_git_object: 4c8485d3ee0d1533e7b19e5c3b01a7363ed27322 + last_write_checksum: sha1:42f7f4090ec893457e1f58865a7499a419dfcf4c + pristine_git_object: 8816de7792fb2034f720195e14f1324cbe0e67ad docs/models/customereligibility.md: id: 6ad6cc047223 last_write_checksum: sha1:d51b278d8dfaf98858914d99e41aa1f8274c3e31 pristine_git_object: 3eab0b39b6e3bd249c42919a34d53518f03c8afe docs/models/customerenv.md: id: 714d5f271769 - last_write_checksum: sha1:baf1fd8c3368fd3602ef5feb2f97714e40a6ec00 - pristine_git_object: 795d79e59aeae504a77a2d3ca10217be880e23e3 + last_write_checksum: sha1:0339c99475930033694fa4b6d63c9d0266596379 + pristine_git_object: b5fddc48061d589c49c65ec0cd5b65c5a1891178 docs/models/customerfeature.md: id: e11a0acefe5f last_write_checksum: sha1:581d157d60440eb1422d1aeb94d8fb184be5982d pristine_git_object: 9649f4d473f68f78ef54b61170388b95fb903a94 docs/models/customerflagstype.md: id: 344522e4c604 - last_write_checksum: sha1:aa7f2fad97d746fa377eb63af23eee177efe47b9 - pristine_git_object: 3cda316c1c6606a7a3ca9969c9380ae88281a803 + last_write_checksum: sha1:fcf82df2a6d55566a69eb913184ce3377a90a654 + pristine_git_object: dd512b21e8be2a5ee7c70ac4a07cbebc03472631 docs/models/customerinterval.md: id: 97ea82daee70 - last_write_checksum: sha1:a163475d02069bd4dbfa4773eaa16ae8ff68cf02 - pristine_git_object: c420d3b5770d68e7bb334d69a916b6387f4e30b4 + last_write_checksum: sha1:f2e098f1e5fff90ea6c51786c9ac693f085e27cf + pristine_git_object: be72d787013fc0f4f5129786c74d70443cd2ec15 docs/models/customerpurchaselimit.md: id: ab270cf19799 last_write_checksum: sha1:a1564dc135f60dd28348428f3bdbfedac8315a8c @@ -829,16 +857,24 @@ trackedFiles: pristine_git_object: 0c4e2be60011b34987f51b9633c725fa2ab43812 docs/models/customerstatus.md: id: b4c4d15740d6 - last_write_checksum: sha1:3550b095a17cbe64c6bb0ba3d38848aac237a8af - pristine_git_object: d60e52acccc16a85833f8d5eaac188951ec8067f + last_write_checksum: sha1:d953eab2afc602b6b65d6e4d8a04ef689b2dd4c1 + pristine_git_object: cec44f4bba76366778d4b14facff277aa85ed911 + docs/models/customerthresholdtype.md: + id: d6d10aecbd62 + last_write_checksum: sha1:fa35d55f76b2564e200184d9bf933650f989456a + pristine_git_object: f78e407be5c7b5a9caeac538daea37d5f090ea78 + docs/models/customerusagealert.md: + id: 8a97d4d05384 + last_write_checksum: sha1:1540f5d2394b242694406e174a608d3409e310b2 + pristine_git_object: 5a7fb04c7601dafc205736b9a962e2ecfa02d7ba docs/models/deletebalanceglobals.md: id: 14fe0d876109 last_write_checksum: sha1:6cbb33a21e005f38ae518bdda4a3aaed87173b86 pristine_git_object: ca300d4f009ccfd44c0b0d8f995d6e0408d3eda6 docs/models/deletebalanceinterval.md: id: 781b7acbeb0f - last_write_checksum: sha1:a22e41d059876a8f9134a41ff2d0dfd0cc87c064 - pristine_git_object: 0acef4bd9acb2592b3342e386221b62b3a490981 + last_write_checksum: sha1:6ffd513f62bc7f95040951ac3ef602bd78ec7d98 + pristine_git_object: 89b9186dd3c2ccfe67fbbee3ce15a34fc7a664da docs/models/deletebalanceparams.md: id: 0bd1b6820267 last_write_checksum: sha1:6648fef91cb71e3064c49158b945ef26819eac11 @@ -905,8 +941,8 @@ trackedFiles: pristine_git_object: 13571b91f635c237d1c0e67aa3a39f2b0542b9d9 docs/models/entityenv.md: id: 5c026cde1184 - last_write_checksum: sha1:18b6be25de69c48ced637a6f6af1c220c472f8ef - pristine_git_object: 3c6a8b29b6df7ff5445d964e3fcb32bd7fbce60e + last_write_checksum: sha1:8a7e9be1424504f599c97ab269154498bc9c498a + pristine_git_object: 4791ce7334f87c2857cfc98e758fa7623cbed062 docs/models/eventsaggregateparams.md: id: d82804f4b722 last_write_checksum: sha1:ead9eb6aed3789a3c7176285f6e8f6b38be58324 @@ -917,12 +953,12 @@ trackedFiles: pristine_git_object: 81ab707fd50986600be0a0bc1cf4f8af1e6b6eb9 docs/models/expirydurationtype.md: id: 7ba992bf53cc - last_write_checksum: sha1:368f1d47012462b1ce9bd136fd0aa4a88cf419fb - pristine_git_object: 675c956152029541c6bfe8a49519e6ba21a95712 + last_write_checksum: sha1:621bdda28fc13c065067c82524420eaa28628bdd + pristine_git_object: 80366277f5fd22322c89d13a38562877f09df7e8 docs/models/featuretype.md: id: 9fd6a7ea7659 - last_write_checksum: sha1:a21f7ba709ab7f1cd5a2d83755064445d8b2c85a - pristine_git_object: 05ff42a520e8804d3d219809d835a13f5ed78bf5 + last_write_checksum: sha1:e78cc7c19a8c81fe196161343bfa5a508572a13b + pristine_git_object: b81adbcda5cd11189273956e2702422c649aa141 docs/models/finalizebalanceparams.md: id: 610af9b4049c last_write_checksum: sha1:9f6c1e1ac2c7c0670ee998fe33e2f633edfe5c0b @@ -949,24 +985,24 @@ trackedFiles: pristine_git_object: 7da619a9e958f42269a6a8c54394f6eb6fa390c3 docs/models/flagtype.md: id: aa8e2212e678 - last_write_checksum: sha1:5938613e76e9a428845bae6670d23526ffdb6245 - pristine_git_object: b4825143b8c900e99b90deb32551f61502cf3b5d + last_write_checksum: sha1:dbe645cdcbe5a43eb811fb5fee6030491747c911 + pristine_git_object: 64f21e86a3546517e7bcc622fa280367f538584a docs/models/freetrial.md: id: dc73eb37daef last_write_checksum: sha1:0f8ee227ca42edfb64780b836e99518a340e3d82 pristine_git_object: 589d1bb1e1cd47c62a789a8cff85528280df7e94 docs/models/freetrialduration.md: id: afd918f70308 - last_write_checksum: sha1:858ad3ce1678634743a1c702062787acadcda18b - pristine_git_object: b98731904496a288b0e3b0ac3574b5d26863f374 + last_write_checksum: sha1:55685a177c7e93c6a9806a7e7d0aa006276d9ac6 + pristine_git_object: 94300d74e7fc30cbf84fd822357b2fa2b60d3d0d docs/models/freetrialrequest.md: id: b3ecac09ef21 last_write_checksum: sha1:169d32a309bd509f208a93cbd32c494a5fb86040 pristine_git_object: 043bcd6a83e917e5245a2490db35ecf15c75e697 docs/models/getentitybillingcontrols.md: id: 4a2d7e54760e - last_write_checksum: sha1:ad9f93b779b330f3036469acdb15e9d6ecefa3f2 - pristine_git_object: f4e72b344aa1eb69b52854c1dbf10a919d2f703c + last_write_checksum: sha1:12fb71935e7acc7e4bdf5b5b4ecc5f26e29bbb45 + pristine_git_object: 846d3b5769ff7ece10edc2b6de7bf9c5b387158b docs/models/getentitycreditschema.md: id: 887b3eaf1c97 last_write_checksum: sha1:e0997dfddd5fdeeaa70773ed26d214132f097329 @@ -977,8 +1013,8 @@ trackedFiles: pristine_git_object: 2a77af15d5dff4f6f3f7ffd678ee41f101828ab0 docs/models/getentityenv.md: id: 446f208bb477 - last_write_checksum: sha1:f7b1e6834f0af7844263a35c619651a4cd69cb28 - pristine_git_object: 829882d267976886364436e4844c2efb99a2fb26 + last_write_checksum: sha1:5c573af95d0443415d84736118217658388bc1bd + pristine_git_object: 63a901b4fbfb4df8bd9ecaa0da5c1a9c7ac69418 docs/models/getentityfeature.md: id: 70f61caa19f2 last_write_checksum: sha1:6147805cbc0333d17b23cdbada931979c1d92e5e @@ -1013,16 +1049,24 @@ trackedFiles: pristine_git_object: a92ff6b9626913630cc43f3e3c9ea4d2db67d33f docs/models/getentitystatus.md: id: a9dc0fe0776b - last_write_checksum: sha1:c0084ca6aa06f12532d4d2a5d4389ed2c395b899 - pristine_git_object: f823deba8a676305bfe817193613486b58c6fce3 + last_write_checksum: sha1:0ef801e1509cec493b2185893c7ff7a6a8f071a9 + pristine_git_object: 9c9b61b2e49731c3618f2bba373b8c104d75e035 docs/models/getentitysubscription.md: id: 79bea398e954 last_write_checksum: sha1:8713b786fca38066c8a961fae76344a314db8d10 pristine_git_object: f07e2baae2a663c3d3e59b936f707e65bc5722d2 + docs/models/getentitythresholdtype.md: + id: dc124a35cc1d + last_write_checksum: sha1:017282736309684116699693c2c8df8f8a2e1c63 + pristine_git_object: abfefb9b4cb6b8351265e08253b154082ededfa4 docs/models/getentitytype.md: id: 18fa9d2e3acf - last_write_checksum: sha1:815cb6238ce71a6e2aa917ffa4962115e9ae501c - pristine_git_object: 7e2b494a58a6995cc91f8eb4587df9825bcef0f4 + last_write_checksum: sha1:5908ff1d81efbedb87596d2accb4883fe98ea4c8 + pristine_git_object: 48c3e34490024bdbcd60298e81e8362f6a3dbc51 + docs/models/getentityusagealert.md: + id: 0f1780b25c03 + last_write_checksum: sha1:d133be816f6deffbe6af091606cca271f126ac8c + pristine_git_object: 0ff5f721cc5ed51a37f7d7491b92e4ff2f5bfb13 docs/models/getfeaturecreditschema.md: id: ba9cb5483630 last_write_checksum: sha1:449f708f5ad09a53efad1ec07b65c0889a0b74ec @@ -1045,24 +1089,24 @@ trackedFiles: pristine_git_object: 517a8f8299a7fd6c192d7a0e1ee842ea6aacc804 docs/models/getfeaturetype.md: id: c54f4a256601 - last_write_checksum: sha1:b4139d96a66706eab122e9505e68fc158cb1a4c0 - pristine_git_object: b8894ad0c26ca43ce443ef4678ef6ebe6bbf9a8e + last_write_checksum: sha1:150f3eaf62699c8c37779ef9a445e52da3b4c9d4 + pristine_git_object: 68e731979e397111d285711a13691b49569cb515 docs/models/getorcreatecustomerautotopup.md: id: 2beff692c107 last_write_checksum: sha1:f9dbd5ab95ec0d4f0d86c3a2efe45782381488a8 pristine_git_object: 40ed50ae3d7019b658cd172a18723b61c096fad1 docs/models/getorcreatecustomerbillingcontrols.md: id: c863934c5751 - last_write_checksum: sha1:a8e666fdd1231039a4a57aee535f58944a4428f4 - pristine_git_object: 6d4136daef570c12ce721857821b9bb60157c118 + last_write_checksum: sha1:d1a6883a0191fb4e2ba75205dbdd639239cd00ea + pristine_git_object: ea80bafde22c0aa16e17ac4e4b3975280348e378 docs/models/getorcreatecustomerglobals.md: id: 1cab932654ad last_write_checksum: sha1:a98b6f0751961493a875cad885360ca4ab817955 pristine_git_object: 4e9384d4fa1e76e5f7072105ad37bd960b3aedfc docs/models/getorcreatecustomerinterval.md: id: bf93ecce87e0 - last_write_checksum: sha1:69c9049fea350c4aba58327a2cae94907470ef1a - pristine_git_object: 40ddcf6f88ed6fe3b00a09567e5e8f6a43a75e83 + last_write_checksum: sha1:a81b370c7073d5fba80652e4b6c55ddc182aacb0 + pristine_git_object: dd40392108052ed1300f552af9be3cad6dcebb89 docs/models/getorcreatecustomerparams.md: id: 6bb57e046821 last_write_checksum: sha1:ab5566304b1ac2b2045c9404f3b88ffdbfd38c84 @@ -1075,14 +1119,22 @@ trackedFiles: id: 1e9f20940ce9 last_write_checksum: sha1:0fad134904747354b93ba04bc4954dee8bbcbc23 pristine_git_object: ec08c25cedd9946144cde10d6ee95fa648e1095d + docs/models/getorcreatecustomerthresholdtype.md: + id: 20bb7fc3fcdb + last_write_checksum: sha1:84458f0c37931c8e022b12313f6d81b4c5f9958b + pristine_git_object: ac3fc92c583a43b07c0fb7697b6e4e6d80ec9d4b + docs/models/getorcreatecustomerusagealert.md: + id: 3b9d65693d28 + last_write_checksum: sha1:3240ed593eefdca0db5bf576bd396b2d0017fc6a + pristine_git_object: 122fe453fb8bd94bfffd63cbb8490a945235b883 docs/models/getplanattachaction.md: id: 0ce3131b10b7 - last_write_checksum: sha1:16ba837ca31d496b44863d2438f68d6fac18f397 - pristine_git_object: 3b8852a3d63ae0f3171ba54282c196eab871caa3 + last_write_checksum: sha1:6b469e1d017b1de218433d30100c0e843848d7a8 + pristine_git_object: 222e0a3893aa564e52943137e83669331ac037be docs/models/getplanbillingmethod.md: id: 5899381c0e82 - last_write_checksum: sha1:9762f5d1ab3cbd4d570c1b403171d3b7f3df6128 - pristine_git_object: 444e142954037161bd4aa63e788a71f75067a871 + last_write_checksum: sha1:93d35c83c757a6f8cc683ac6bbd7f84892568f37 + pristine_git_object: d8b089d97ce1e4230dcff81169bfca45d7f7fa36 docs/models/getplancreditschema.md: id: f70b7a9fd404 last_write_checksum: sha1:1ad49c99400c9f9c735bf18686e2c7f3a0715803 @@ -1093,16 +1145,16 @@ trackedFiles: pristine_git_object: 55ddaf7c1fd4b81efcfd565d217596cd3cfb7ba0 docs/models/getplandurationtype.md: id: 531b497ea20b - last_write_checksum: sha1:6367aa97323f629634099fb9d45375ba329e1c43 - pristine_git_object: 90909b13f3bc4b014c3993d84085b805a5ea6db6 + last_write_checksum: sha1:df5c7a55a41ba415e20ad5380cec7bfc25ac29ac + pristine_git_object: 5f29921945accc78755b28a5e69eb3e4a68acd18 docs/models/getplanenv.md: id: f83aac7b06d9 - last_write_checksum: sha1:06675b31e96de0c8f15d8b6eb89ab182be92cf36 - pristine_git_object: ca505312f8bc091467e81b6905b716d611d33225 + last_write_checksum: sha1:9a144c5d18e790a681bc72ccc8dc7dff6604d21a + pristine_git_object: b8d4c39f8242f3bd334456658defdde380e31d77 docs/models/getplanexpirydurationtype.md: id: 03a36cc18dfa - last_write_checksum: sha1:1ca4877e84edeafb35dc4bb81db5f19b9499f662 - pristine_git_object: 0a11d2d6659ca9b3962dcd4c245030a57e2b378a + last_write_checksum: sha1:8fbcd41010d7b858f04b035389387133fdfaaf20 + pristine_git_object: d127699651820a18616b4c971dd9488e96c07d3c docs/models/getplanfeature.md: id: c4414dd51a12 last_write_checksum: sha1:0f89828767697ba0086bcce9cbe0024876ae2dd2 @@ -1145,20 +1197,20 @@ trackedFiles: pristine_git_object: bcbad67a252e45ad1181c76834ea98b725ac56ec docs/models/getplanpriceinterval.md: id: 49e240107fc3 - last_write_checksum: sha1:9f664db6fef8de9266e28fc313a3ad87ce29f846 - pristine_git_object: 0fbbbe940a7d7be5272478f46c4c1fdc0a2c686e + last_write_checksum: sha1:46f284ab72a58f462848a006ea9dc26d944c59ce + pristine_git_object: 3370145b996fed00a85041e7c500c0271627c930 docs/models/getplanpriceiteminterval.md: id: f5a725b2b8d5 - last_write_checksum: sha1:02770e6af2a6ef10b45a4675e52f43d1db263067 - pristine_git_object: d70ae03da2d27de9c4932d44228dcad913386170 + last_write_checksum: sha1:b68a8c4fbaba805bc18f77116cdcb8776c267c05 + pristine_git_object: 4da7249fe8ada0c78fdbff11f1d2e57e9edf15c9 docs/models/getplanreset.md: id: 0d4683eac10d last_write_checksum: sha1:014167206a4a206315d9530426cd4d21903fbe90 pristine_git_object: 2ad13f83a372f25f8322245dc743e9c78114097c docs/models/getplanresetinterval.md: id: d518a38e6124 - last_write_checksum: sha1:2c4620e76372b625802d55c3188532ecc7a7f2ad - pristine_git_object: 893f1399489630534ab838e9507aa9ee95d98633 + last_write_checksum: sha1:1461a586f2956642f3ef7fb76697805710cc106e + pristine_git_object: f89ea0c6427dda0e3791eeba61089a4bb4f2a3d6 docs/models/getplanresponse.md: id: 2b0a620fdbb6 last_write_checksum: sha1:b3bc1ce22f83a8b78e3bcbd75e364c5615974584 @@ -1169,24 +1221,24 @@ trackedFiles: pristine_git_object: d6778e26ece0dd751384156f2417e3a87b435f7b docs/models/getplanstatus.md: id: e934416f9b0a - last_write_checksum: sha1:b366acc3392ec751e92a8e07dec9074a03a98297 - pristine_git_object: 8b1eb7d78f8b265ab13e1822740124794e4e4ff3 + last_write_checksum: sha1:c463eaca5076258ce803f4dde67e5872786893d9 + pristine_git_object: d6f47e9f63a25482f46524554d8fe0b43c09fafd docs/models/getplantierbehavior.md: id: 43d70b082849 - last_write_checksum: sha1:498f80b2248b63d64e57495ab64dd7c82941f8e3 - pristine_git_object: 512006d976e36f5a5bd72fb4520bbaf7b1696747 + last_write_checksum: sha1:8d33409091d654dfbe7d0cdb495289b363e3da7f + pristine_git_object: 74bac9d492b97f798091959496f6301daf1b8fe7 docs/models/getplantype.md: id: afbdf26f0f4b - last_write_checksum: sha1:6d5dfd04c5d95c235f56eb23e31f497c9ed91247 - pristine_git_object: 7390b496108568e19aba42d36c5c3b508e3d42b3 + last_write_checksum: sha1:7b11bca3ac08a5bd951768af39bc5a2d2867a1ac + pristine_git_object: 64f5d61046d023c2293fa50994151408e0ddcd06 docs/models/includedusage.md: id: e844c6f90fe1 last_write_checksum: sha1:f45eadc2eb0f9f2543fcfd3b0d671c8fc9e1c5a8 pristine_git_object: 6af710e8393ec0d5bd29b7bc2969174b69548d55 docs/models/intent.md: id: a4a6fa8818f7 - last_write_checksum: sha1:9079fedc03e6b5c3469c752774a972f27bdab857 - pristine_git_object: 2fb90b98293f058b3624f39b89a91915ddb73ba6 + last_write_checksum: sha1:7a2ffb6b28f1f53a993132b1d38e527ca4472d95 + pristine_git_object: 41e20497ed5f6838daa1c3b689bfdce018a5758f docs/models/internal/globals.md: id: 9c173b87f41f last_write_checksum: sha1:f1b8e7ce642026cd3ca1df79e67c7a011f487fca @@ -1209,8 +1261,8 @@ trackedFiles: pristine_git_object: c83159c6aebb5837df31c3af20a6dc463851f26b docs/models/listcustomersbillingcontrols.md: id: 7bf70880a06a - last_write_checksum: sha1:9a777a711c543fdc6093250fca24df1410356296 - pristine_git_object: d3e560e51af656c502e922155cb1ee6a1a4fdac0 + last_write_checksum: sha1:162f377e954d09d4151abc63360c9ab16c1d4499 + pristine_git_object: 14a51d6949a530cfbcb9b4f0c6ba2ee88eea7e48 docs/models/listcustomerscreditschema.md: id: 233b13b5c3ec last_write_checksum: sha1:cd18a266307472b08dc8f8bfe120d2134ef24577 @@ -1221,8 +1273,8 @@ trackedFiles: pristine_git_object: b63a253ef31d05f492f054307ec26cef6af31a36 docs/models/listcustomersenv.md: id: 4a356fa1f33b - last_write_checksum: sha1:f36e4a5d525b7e69e2dd2721b25b4451f272d383 - pristine_git_object: 9c87d7fb576ddebfd331368c52799c7f92eee799 + last_write_checksum: sha1:e883c9c38a73b9910ff2cbdd6adef00b226ff214 + pristine_git_object: 750e1fe57b24381eafec336a5d7d1a97980447b8 docs/models/listcustomersfeature.md: id: 0d1d6a29245e last_write_checksum: sha1:c2bc21d88712f18bbd4fbc5fa7f2085045a379b2 @@ -1237,8 +1289,8 @@ trackedFiles: pristine_git_object: 0c99ff068e87c00c04403bafdb526327c872e28d docs/models/listcustomersinterval.md: id: d395228928af - last_write_checksum: sha1:3ee69e14dabd31a795eb88fecbff0d52b0a6007d - pristine_git_object: d059fe1ed2f68a59ab081f0937d3629ba9135532 + last_write_checksum: sha1:7aee8978d9fb061b53cc3e5f028c5c9164864942 + pristine_git_object: 77c3c316e986ee99faee7c9fe10596e1b13d745a docs/models/listcustomerslist.md: id: d71dda8a696c last_write_checksum: sha1:ee8b36fbcaf8b08326a04eeb383c71e3bc10c1ad @@ -1269,16 +1321,24 @@ trackedFiles: pristine_git_object: e3b685690aa916dbd951480743e4ac07ef7d8834 docs/models/listcustomersstatus.md: id: ef9a6bf44535 - last_write_checksum: sha1:c55467eb7401c28e4bc671df976ae4e5672f5461 - pristine_git_object: a022d4645d783687e38950dbd3553f183027d264 + last_write_checksum: sha1:956f1e484cadbb76fe9bf2069fa624885e5dd2e3 + pristine_git_object: e11dcb9eae8b5df39a7f50c909eaf673d40984b4 docs/models/listcustomerssubscription.md: id: 563487abda41 last_write_checksum: sha1:fb3b140e7a41d14e1561e82043698326a31be834 pristine_git_object: f2257cb7235a82b97ba6a773a19a81345252e112 + docs/models/listcustomersthresholdtype.md: + id: 891ad14c54c6 + last_write_checksum: sha1:9405e2dfdd934a185fca4ced935dd0cdb8d252e4 + pristine_git_object: 90e2f92efebb8266b4d626a6ba266718ad13409f docs/models/listcustomerstype.md: id: 431485f373da - last_write_checksum: sha1:38c1bf892ba103e25ee8c0bda7b322c7b1c97150 - pristine_git_object: 408f48dfb01ee2b3f69e4d0486f3f6d5ef3626f5 + last_write_checksum: sha1:161036bc83c3eeea7c736af588e8523330cf7f30 + pristine_git_object: c045d3f1352a590fe35af661c5343ed9489e7347 + docs/models/listcustomersusagealert.md: + id: 3f57d100be4d + last_write_checksum: sha1:d98c87e661b0cade8fc6d6e09c67323dc6746f3a + pristine_git_object: 69f720b7645a59634c4d66c2b86a432bc1ffe424 docs/models/listeventscustomrange.md: id: 7fe97412d600 last_write_checksum: sha1:d9fe1ecd94b4360de822647bfc6d10319a6a11de @@ -1329,16 +1389,16 @@ trackedFiles: pristine_git_object: 6e6cfa9219fa9f0b24adc850386f46f8b6fbb0a3 docs/models/listfeaturestype.md: id: 38d27c59e570 - last_write_checksum: sha1:456db91e3466968ec933e354505445e480244a94 - pristine_git_object: 1d0e84005191feeaf5423baf5c29ebbe47f149ea + last_write_checksum: sha1:f53f04cb15375a2b0f35914aae8492ac09017fbd + pristine_git_object: fbbecc4872d8313dfb7097181436b0459abbb29e docs/models/listplansattachaction.md: id: ebea6c110ad3 - last_write_checksum: sha1:5a53c97c8e2f16407c174de56d2a17a1897d3fff - pristine_git_object: b99081a2408748dae1cff55e1fb7442ab5afa796 + last_write_checksum: sha1:6b8bc81c4558884f94437c679091829f6044f67b + pristine_git_object: bea25c4880ccfb2ab728c9500f018983ce9d5b80 docs/models/listplansbillingmethod.md: id: e3bc081b1871 - last_write_checksum: sha1:fe30367f3d3dc7caa417ffb1cb7eb41a233892be - pristine_git_object: 0a311a1a9fbd103a9796c9c96b056b48a17f593b + last_write_checksum: sha1:6dbd9106af5281ed0050a6079d13ac94a3be55c5 + pristine_git_object: fbfdc8106d7c545f591ccb1580698953c01bfd6a docs/models/listplanscreditschema.md: id: 8f4524699ea8 last_write_checksum: sha1:8264d803e53a657b5077baf27f79e86b9aca6c1d @@ -1349,16 +1409,16 @@ trackedFiles: pristine_git_object: 1a23815de5ab376a2f153cca506038f63181188d docs/models/listplansdurationtype.md: id: 9495db2c46d7 - last_write_checksum: sha1:6c48c9378be8d9a0b6bd38fabebf07742a149d42 - pristine_git_object: 90d99ae19a664379f001a33050a424b0958b9626 + last_write_checksum: sha1:0d6fd83d4998c2a27143e76d4b1b4126e4038822 + pristine_git_object: d717ad36f08313dd30dfacf50f6c006c70eb3141 docs/models/listplansenv.md: id: 31607dbe25dc - last_write_checksum: sha1:c62abd91d1c56eef136ed56af29175a7191ba25a - pristine_git_object: 4a8cffd6bfccbaa793894297baf9a5fe7eee5e32 + last_write_checksum: sha1:9830f7348ee862987f13efc4a01eb6a6796ede7a + pristine_git_object: 02c29dfc73212a614b5c8ec44f720bae159e389d docs/models/listplansexpirydurationtype.md: id: 95a054c2e519 - last_write_checksum: sha1:38648b272697d05f9eb685b1a8fccf76b1c8e4d9 - pristine_git_object: ed20a3beba9ff8fc24604939bf7e23a0c54d77cf + last_write_checksum: sha1:584ed1565d5e0e1526c1972a6f260a75b57b6635 + pristine_git_object: 1a2b7ca1f74cbb6ba3decaf7c4589617d3f530f0 docs/models/listplansfeature.md: id: 695e022227fd last_write_checksum: sha1:be788a1a590651cc99265529af796851f8295b7a @@ -1405,20 +1465,20 @@ trackedFiles: pristine_git_object: 183984624f5db2fa0531d6315e3a0992bc4c5bb2 docs/models/listplanspriceinterval.md: id: c6eed8ecd3ab - last_write_checksum: sha1:e0615391bccea8d12f365cd0b02c49656e215973 - pristine_git_object: d29ae18613bb21f1aeeb0140cc0e9b7217f76603 + last_write_checksum: sha1:a406660a86cea1ca01551fde8bc67a6692a79322 + pristine_git_object: 2a8a39f8ac58a6ab975be8c95656e259b4acba31 docs/models/listplanspriceiteminterval.md: id: 01ecfb4227c3 - last_write_checksum: sha1:cda215b4295d09c14413994ee52d9717ecfeb3c5 - pristine_git_object: 8f9e7ee9c4b285e26bff7fdfade3749dc9feb5bc + last_write_checksum: sha1:43ad14ac0b516caa6d79c4754be679cbeb13eeca + pristine_git_object: 9f629477abfff58f81bc131cc219559bb0696f83 docs/models/listplansreset.md: id: a094b1e8ad88 last_write_checksum: sha1:f393e47631d54b7ca392f89b6b8dd298044cafba pristine_git_object: d2d1fc44a5a802750cf3579fbe14acfa81d62705 docs/models/listplansresetinterval.md: id: d3e52a6a7150 - last_write_checksum: sha1:4181c23ae65d01de9ca04613fffb312efff27761 - pristine_git_object: fca8329375e116c297560104caa66e1ad0ddcae3 + last_write_checksum: sha1:0cc22e923ec5a7af4e9c5a34accc5be12d97a1ce + pristine_git_object: 3801f20f4a7442df7a92c79cb4391189da06b9a7 docs/models/listplansresponse.md: id: 36b6e3fa6daa last_write_checksum: sha1:9763e11551ddedad472de9cbce9e6751752265bc @@ -1429,16 +1489,16 @@ trackedFiles: pristine_git_object: b1465a838739806bf638ee8507880d90d397724b docs/models/listplansstatus.md: id: 0e36930afc34 - last_write_checksum: sha1:9d45881741f8a142247a4006d141aba297608c27 - pristine_git_object: 128b5ab6310da37fb03fe81aaf1af862329cea33 + last_write_checksum: sha1:e3b3e382985eba9756c25c1fe2290957e3652e67 + pristine_git_object: b8d6dc18c9d4545db0e3f36685f5fe71f5d67590 docs/models/listplanstierbehavior.md: id: f910370a1711 - last_write_checksum: sha1:6f4e9ec42f871e049b0b2932b24f1c148ff42d64 - pristine_git_object: c88a32bdd79e74b7a2f348248139d6b3f32df974 + last_write_checksum: sha1:cc7e6216d011b75eebfa959dd7a4c88422c9eae8 + pristine_git_object: 50649d135c09691831f63fe930cbd678240512a1 docs/models/listplanstype.md: id: c265fc1d3752 - last_write_checksum: sha1:ee4d791c463a7a530becba66e8f576b75b7ba217 - pristine_git_object: a105ee9d7d196ff96d7d56e990860f75cde637f3 + last_write_checksum: sha1:fee41af7544896b624de7a39fd20dadcf73d8dad + pristine_git_object: f5cdaa931dfd1225fc6e7e45b4c7df54934a462d docs/models/multiattachattachdiscount.md: id: 84b9e0a4d680 last_write_checksum: sha1:7f6655964faa1676f26c26520d23e42cd2eb8af6 @@ -1449,32 +1509,32 @@ trackedFiles: pristine_git_object: 290b9413b26177294f70e9beaadedcc9981cf6dc docs/models/multiattachbillingcontrols.md: id: 1b5ff234d470 - last_write_checksum: sha1:75ed3e4ae35ede58406e40e5142c80ea174dbdd5 - pristine_git_object: 325203724a8e3e6588e24fd6ceaeabfb7f2469f2 + last_write_checksum: sha1:f5a092b36b63401afd1d0cc3aff81d43421503f6 + pristine_git_object: 4647d12f7799a98561f249a38ff6d4f0772ab4aa docs/models/multiattachbillingmethod.md: id: 78bd00e832a8 - last_write_checksum: sha1:b71d8bbe717bfb4a1807f569ada8f10d6411cc6e - pristine_git_object: f77600fa9e3c31833d7e0070240eedeefca91039 + last_write_checksum: sha1:6b3e4bd84e01d8e880a8be15caa90484840cf064 + pristine_git_object: f7af35a930bb6948739c84aaa55b6793fd4056fd docs/models/multiattachcode.md: id: f423dbc408f7 - last_write_checksum: sha1:2f92a6cc4f83c35e4b26d376dc24494f9a717d57 - pristine_git_object: bbd3919960c0184383fbb4bda321f931fa81c0ba + last_write_checksum: sha1:f0a120e4cd18acd40974c037f768ce9e73b79fc3 + pristine_git_object: 47ba65d1e0c495fedda0f6d28fb79aaea9f89a3f docs/models/multiattachcustomize.md: id: 5f3ca0c4e8cd last_write_checksum: sha1:45fd9bec1e1233c2c7ae11ccc4fae5619dd06ec1 pristine_git_object: 295b2878cf8db291260aaac31fa5535b10661a27 docs/models/multiattachdurationtype.md: id: f5a45a0c8df0 - last_write_checksum: sha1:c5f27a80b42ce7a2a8c3f77b91061ad4795a9077 - pristine_git_object: a4948aaf9a86a6b83c4ebdd8633cf98dfce5b2a5 + last_write_checksum: sha1:0ac6362a2845051fff61ed4e77f7d711c689f575 + pristine_git_object: e81aa4ad0a612e36071ce045ca46d84b6d3dfc84 docs/models/multiattachentitydata.md: id: 59bc1e3bc662 last_write_checksum: sha1:0f7dd9929296d0c0d178e4220c05626b9eeb150b pristine_git_object: 44822b7ce7c29f2849b431630ed6cbe5240fb7eb docs/models/multiattachexpirydurationtype.md: id: 5515efd998cf - last_write_checksum: sha1:bfe29b5da73e5a32d8573c20382b14caa103d39e - pristine_git_object: fcfa7e53441dcb2503a93af52566ed34b410e9b1 + last_write_checksum: sha1:9d197dfe50cd37d043f9416f80072fa479053528 + pristine_git_object: 1a4762ca683493ac539f74fa6f1809c2aa121bd5 docs/models/multiattachfeaturequantity.md: id: 41d1fc07ea2b last_write_checksum: sha1:4e17966501c6555f7b28de4bdaf6e0a8d30d877b @@ -1497,16 +1557,16 @@ trackedFiles: pristine_git_object: ffc930cdd73dafe972deb77b4b8090cdee001cdb docs/models/multiattachitempriceinterval.md: id: 0030b6692fe1 - last_write_checksum: sha1:8ab49b031c75684ab2980f52e04ea8cc77978984 - pristine_git_object: 96afcc6bd84e6e1a1f94d698f806cdffeb56c41e + last_write_checksum: sha1:02e35cabef42fcd6e113495f3b860ce35eb572ea + pristine_git_object: 046a3f693366599cccd226ec67465e4de00077ee docs/models/multiattachondecrease.md: id: eb882098e74f - last_write_checksum: sha1:bdd219f50cad5e7bda7ef518ac765e75e8537d66 - pristine_git_object: 079850e4a5fdc18e3dd4d65b35bb40e91e49fbc9 + last_write_checksum: sha1:1825b557a75a40639c1b329d849a5ee50d0448c7 + pristine_git_object: 5dd8abe5f6fab10dd5b5fd0e1219c277fd52f49c docs/models/multiattachonincrease.md: id: 2645fe9f0f62 - last_write_checksum: sha1:e2e385491d1b02903c079e71f1b7922e8c6bcae6 - pristine_git_object: f2692e537169b9b000384c7749a5b9e9f6e3df2e + last_write_checksum: sha1:feaa98c20154520deefe1c89929f33b6365670c3 + pristine_git_object: ed7d58da3b22ac78c0a451435246bb87175e0c0b docs/models/multiattachparams.md: id: afacc821df4d last_write_checksum: sha1:ecc7a7de5997f0045534a255e263ac2a1d8e72d2 @@ -1525,16 +1585,16 @@ trackedFiles: pristine_git_object: f5035ac6fda1d63df18f9a22fdd0f565e9778627 docs/models/multiattachpriceinterval.md: id: 58fbae5e506d - last_write_checksum: sha1:573cc1cfafc85af26cd3bbf3143fac03a626b8d7 - pristine_git_object: 3409f9610bf4986b7ac4c71446801dcdcfecb449 + last_write_checksum: sha1:525bb8214350d1f4f120a381b8a36b32a3a3698a + pristine_git_object: 7bb54d92dd1dc404dccd12e692d2aa4c13c72290 docs/models/multiattachproration.md: id: a4ccd95a4f1f last_write_checksum: sha1:644594ce2e14ce35546f83ae9e185a066b359294 pristine_git_object: bdd561e1f8db63ed4a65fb25ac0bc8514ba94ecd docs/models/multiattachredirectmode.md: id: 6898b471cd23 - last_write_checksum: sha1:4b14153be4dcb9839614f549b0094da779ba2671 - pristine_git_object: ff721d72fdfdea39dbdf5b24629c2971718edcf0 + last_write_checksum: sha1:2e43963cb0c8ea821f8a78e1b030a68997bc0ff6 + pristine_git_object: 5012c8235c34d8d36b80a929ea9bd0ee4137896f docs/models/multiattachrequiredaction.md: id: d0c8ce104e28 last_write_checksum: sha1:b39367dbf7750b87fc30c1b5f90dc6a2ce5bd1cf @@ -1545,8 +1605,8 @@ trackedFiles: pristine_git_object: d10f501c27db623587ad477725f490326dd130ab docs/models/multiattachresetinterval.md: id: bc4b71af1ebb - last_write_checksum: sha1:38f6bd86601fbf385f79dc581d94b85bc052219d - pristine_git_object: 129f668a7e45b700cbf425f8a3807f384a01aa86 + last_write_checksum: sha1:cafeb533593f4635c3f18c941c88d6c9b884e6c8 + pristine_git_object: 34e299ea1a1a314bb95fc779778788fdebdd2eff docs/models/multiattachresponse.md: id: d919bee4ec6b last_write_checksum: sha1:7095fc0913192166bc2787e44664fa2cb48b038f @@ -1559,18 +1619,26 @@ trackedFiles: id: 88e2737dde1c last_write_checksum: sha1:e8c44943dc2d60ddbdd49a637cca46662b69b859 pristine_git_object: a471f442d7114497bd26bc26c10c594a8a247ca6 + docs/models/multiattachthresholdtype.md: + id: bf10e2aecdf0 + last_write_checksum: sha1:c5a4e24ac9bec396ec2f7ec0ff474caa1b2474d8 + pristine_git_object: e41887ca18f8a360e3f0e3d63b48863397c63a3d docs/models/multiattachtier.md: id: 8ffc11d3087a last_write_checksum: sha1:971921079fda10ca0dd9cdfd56e5ceb849c43ef5 pristine_git_object: 1a8295d39066a03867699c932ac0b9c8d296bb41 docs/models/multiattachtierbehavior.md: id: f61b0b7ebb2b - last_write_checksum: sha1:de3c8c01c2fb0c3b2dfe2425309608e93a45a671 - pristine_git_object: a3e5baedd30aab6f13641a6615af21c65fb8b1ad + last_write_checksum: sha1:360f87ccc7ab2f4d2190eed9159b43042fa22bf1 + pristine_git_object: a769fda3c10b70124aee1268b896486b4a05cc47 docs/models/multiattachto.md: id: 056e50c9e976 last_write_checksum: sha1:654078650712620389db0a568669db36597a309e pristine_git_object: 9a835b9ec832a90edf8b764f3deb58c76b310992 + docs/models/multiattachusagealert.md: + id: 645322c11b62 + last_write_checksum: sha1:8ce33b7ce6b3d2e5fc1b0757e46e75c898251258 + pristine_git_object: ef4d50d8835ef14da1eb8917e7ab8988c5e3e44d docs/models/opencustomerportalglobals.md: id: 9672e1095d8f last_write_checksum: sha1:128710c47318a46258c878691506ae599d1b55e3 @@ -1589,20 +1657,20 @@ trackedFiles: pristine_git_object: daea8b231352c8ae8fc3d23ab739ed3ce60df632 docs/models/planbillingmethod.md: id: ac90cee4f6c5 - last_write_checksum: sha1:1a7f86d46499a4f95ed7de36d79c3ff227baf98f - pristine_git_object: 8e4f8a8d96a6a110275c7b80ab0b93dfc9cd3ebf + last_write_checksum: sha1:30a815d6adf61aea6127d9edb4026936d13a4250 + pristine_git_object: 4aa20f7a70f16a7f437aa35b04841d8d4b19780a docs/models/plancreditschema.md: id: 510cd9d4f287 last_write_checksum: sha1:3929c72df37848348916c755926dd1de7c252b3e pristine_git_object: bcf7cd000ef324a7eccf32e58c7195627bf19a29 docs/models/plandurationtype.md: id: 7eb9a5f1eacb - last_write_checksum: sha1:7f711eb7f7240261214a728b8f62522b9463a7ed - pristine_git_object: c08021fe0315ee4efd0dd8fce71de18150612858 + last_write_checksum: sha1:81f41818daf55dd9dadc8e14e383ad2e62804905 + pristine_git_object: 251f2b661e3a9d65612ac18f0779bc04f515619d docs/models/planenv.md: id: 0e584adaa5a5 - last_write_checksum: sha1:eb12873dc0baecf10b0aa8d8e8dd4a58bb7a30bf - pristine_git_object: 7a5339582592990338e74eb735a180e4c4ecd7df + last_write_checksum: sha1:1afd6a72ed0428e605f36df7a4c8f7f24c728686 + pristine_git_object: 2357a78eff239943e206394ab2884612b88fd5a0 docs/models/planfeature.md: id: 81977f66cb0b last_write_checksum: sha1:22bc5373900e56f572d8e2e564bc9bbb6e5967f2 @@ -1629,36 +1697,36 @@ trackedFiles: pristine_git_object: b28dbe1c0b38e63dcabf1d16b2265b5a97d2665e docs/models/planpriceinterval.md: id: df92467f108c - last_write_checksum: sha1:4619925dd8e98bcf7b8b6d727dde8a4b95d252ff - pristine_git_object: 490e7c4dfc76d81dd6b7284c76d689d1b926bc48 + last_write_checksum: sha1:6da158925940c2762a89484fc02a197a45b84846 + pristine_git_object: 3c6bfe6cc9f917cfb28a90085e265b3b5a103584 docs/models/planpriceiteminterval.md: id: b41d93ad5140 - last_write_checksum: sha1:a6db3df878cf0834ba27d9017313d2a708010e55 - pristine_git_object: 7543c11b27caf7c212e0a837a41d80fd9801bbf2 + last_write_checksum: sha1:33f6566c42e361d3398e74011ea043ba92e27e61 + pristine_git_object: 6cab31656b0f63c55b9aee19b6f8aa3eef2b59f8 docs/models/planreset.md: id: 08cb2753f6e6 last_write_checksum: sha1:aa46714be96b570fdd130828a57235036711aac1 pristine_git_object: 03a0310de42bc4e702adbc197316ee0df9f31322 docs/models/planresetinterval.md: id: 1d0c7c8f25db - last_write_checksum: sha1:6e1c62bcb913f380ca6f967bdb40714bc99c6393 - pristine_git_object: cfd3fd0d99536ac7153a5740ccbea7248ebb7eae + last_write_checksum: sha1:e37a9e1141c5c4c9a398d5727e967cc7eab65203 + pristine_git_object: 0612c99bc608b137640e93683b223efe0a2ffed7 docs/models/planrollover.md: id: d432fcd32015 last_write_checksum: sha1:6a9d0e59d5e260cacebab72874b6f9b52cad8269 pristine_git_object: b24a347af2dd3725b201c0228c293c07296ad436 docs/models/planstatus.md: id: 1b32a1788a18 - last_write_checksum: sha1:74508405c05c6e93bbe1583facd1895c813f18f0 - pristine_git_object: 65802bc0e9baadd827bc460a5ad655acc1298888 + last_write_checksum: sha1:f1d88fb70f2b1828a393d8d48d061a46a4c40070 + pristine_git_object: 23f15ebf3bb4574dc2228b8b042095d477f3614c docs/models/plantierbehavior.md: id: eef000779cfa - last_write_checksum: sha1:53e33ecac045604feabfab5d02a5caebf791f03e - pristine_git_object: 9ae9f32d44709187aa8d6805f92489ab7934b60c + last_write_checksum: sha1:c0c1ce53d480992c255681103b9a3f8233b189ff + pristine_git_object: 563c3a51a6c8f347a65899fefcfca11d43139da7 docs/models/plantype.md: id: 4c86df78e60a - last_write_checksum: sha1:5246ebf75c009119cbfcd501cdeb659e9f3c6786 - pristine_git_object: 5add1a3cab3d01077452a4df8d9037c6279da319 + last_write_checksum: sha1:f78cd88fb5996e96029ce1c66c8b76f80a83a05e + pristine_git_object: cf233509e8cc1599a589dba1e68dda9e2d16400b docs/models/preview.md: id: ca71b601ef12 last_write_checksum: sha1:40aa929c88e329add6e7ca46d7a8a2035a292320 @@ -1673,8 +1741,8 @@ trackedFiles: pristine_git_object: 0161cbf90c9d6601844f3c10578fbf2ce2a7e8fd docs/models/previewattachbillingmethod.md: id: 4fbccec2190f - last_write_checksum: sha1:8b0d83a3e51808880340322fe4e928c15db8db80 - pristine_git_object: 51af469aa8274799746f5b5840dc83d9c6bc22cf + last_write_checksum: sha1:39e5c7556d0f2739d994e97698da4a0dba485cbf + pristine_git_object: 1646686d9a3177cf398ce904346a810566c681f7 docs/models/previewattachcarryoverbalances.md: id: 2f80251494f6 last_write_checksum: sha1:12f176856ea0429bd9a025357aaad945434e9c09 @@ -1697,12 +1765,12 @@ trackedFiles: pristine_git_object: 9af81284fbe5d16a90a7c2c6691207c556f1bd74 docs/models/previewattachdurationtype.md: id: b41ef967b1da - last_write_checksum: sha1:05fa10b05bcb98343d3e6a5c4af64714fa00e7e0 - pristine_git_object: dc12d9b4e678870280da54412df0ab657c29b7bb + last_write_checksum: sha1:fc6a07373e3dfeaa2d6232479146ffb8b1ab0881 + pristine_git_object: e9584b37ee5121b526d9dde85fef8232ee5f30e0 docs/models/previewattachexpirydurationtype.md: id: 0cb588a15167 - last_write_checksum: sha1:8044289f94f1aaee29febf2a20de8b6ca326eb59 - pristine_git_object: 2034fa2473708010cd8f25fe4fd21c4ec6351560 + last_write_checksum: sha1:e87687f7de9a6c1e425ed3adee650ce2d3ebc445 + pristine_git_object: 1ab76bb0e863b774266c81ea67f8fe98842deec5 docs/models/previewattachfeaturequantityrequest.md: id: c17c4de9916c last_write_checksum: sha1:877dfd0382ad30f95c6a47a3024cb7211b3449f0 @@ -1717,8 +1785,8 @@ trackedFiles: pristine_git_object: cb44702b2c3aa86727942ef1627f50a508365304 docs/models/previewattachincoming.md: id: fe006ad43864 - last_write_checksum: sha1:52844170ce012cf824496aa538e7f54dacdc3ae0 - pristine_git_object: 395dcbf05135f557846dc5732276c6441a5b0aa5 + last_write_checksum: sha1:7a863bc4b613f84a6ecad4b358d40f72af260db2 + pristine_git_object: 5caea4f0bf69332b63192d152cb733e8bca9d7ef docs/models/previewattachincomingfeaturequantity.md: id: 6cac4cb0ca48 last_write_checksum: sha1:697fd3000cdf5febf7a78846223b52fa115714aa @@ -1729,8 +1797,8 @@ trackedFiles: pristine_git_object: 52153f9fd9a587fd6e60b8ee15bbd9e661d7bb3c docs/models/previewattachitempriceinterval.md: id: 96eeb2602066 - last_write_checksum: sha1:fbe0200ede8f1c6acedfc320b2422a73c2b966b6 - pristine_git_object: 4d34aab005e0e16a8f9a250e0a76011bc679afe4 + last_write_checksum: sha1:dc3892f6e3cf2aca0e20c16f12972049b1dd9c5c + pristine_git_object: 7ebceccacfcc32aa5ad5eb937660ef3739ec7f82 docs/models/previewattachlineitem.md: id: 3411ba3438a0 last_write_checksum: sha1:7c2df8dabcaa3fc464ccda62846c7dbc36820be7 @@ -1757,16 +1825,16 @@ trackedFiles: pristine_git_object: b368084e508a42672d02974a249e4bed426a1bbb docs/models/previewattachondecrease.md: id: c3d14ec84b6b - last_write_checksum: sha1:6cc38137f4d3f59dfca3c40ed77938a82977c64f - pristine_git_object: 803832bf36aa416616d9e0bbb740b7c63b7087ae + last_write_checksum: sha1:c98eabf793906b34cf479e252ebb67d61a590999 + pristine_git_object: 6d8552af77f228f5f06a56035fee0e711310d94a docs/models/previewattachonincrease.md: id: 62e686313af6 - last_write_checksum: sha1:feb4f85815fb574e36cb16dd08d3046f14dea8b2 - pristine_git_object: 28ea912a0cbff919f7f93dcdd9b920d4e98b40f2 + last_write_checksum: sha1:79c9eeae5214b2e2d4800667d6b188537c7f46ee + pristine_git_object: 2fe65b7ad59a16fa648125ced2c2926f5ecbb8b9 docs/models/previewattachoutgoing.md: id: f07be0abfe91 - last_write_checksum: sha1:0127c67d98d394894962dc58bd0e421fbfba8bad - pristine_git_object: 3fa35595df2a36da3c72d98fc55533fee2669c7e + last_write_checksum: sha1:ab1374a15bcf61fb5bfc845e18e08a158b32536b + pristine_git_object: bfe2bf127938eee77b8111757ca59d5494a5d47f docs/models/previewattachoutgoingfeaturequantity.md: id: 962820e0d447 last_write_checksum: sha1:24ed539aa370712307b51b0b1514d95314e9bf3c @@ -1781,36 +1849,36 @@ trackedFiles: pristine_git_object: 582c2b96374f7dfba538a73d21776a7b1cb0eebd docs/models/previewattachplanschedule.md: id: 487cbb8bd9dc - last_write_checksum: sha1:6b50ca928452851bd01e971838cceab1eb76b8ba - pristine_git_object: 984afaf416460db09828280b11c62a08b2bf808a + last_write_checksum: sha1:d3b1ed2650f3c52cc1d9cd2e8b27b9d578e37904 + pristine_git_object: 7551150c582828b16198182257edd1605998c2b7 docs/models/previewattachprice.md: id: caa899534556 last_write_checksum: sha1:5c7bd82d2e4fe15f72769b958b47fa3ae78363d3 pristine_git_object: e3251f374a50de887dd74b891d22d21deba9ee5a docs/models/previewattachpriceinterval.md: id: 922bda88e1d8 - last_write_checksum: sha1:e1e1f147773cfc8dd61892c630dd97cfb7f689a7 - pristine_git_object: b2d88314d2a82c87c5b8d8d26268831ba98bf8cd + last_write_checksum: sha1:8e38cdd00dd58a77eb13cb133c4f5b31d865659e + pristine_git_object: 052b4f55f00c37535e83043f2ff325f09ffba1c0 docs/models/previewattachproration.md: id: 2d9f5cd09535 last_write_checksum: sha1:c92886c2a07120bd7c0750baa33f62352a8ef3cd pristine_git_object: 86fef8897a946a21a11d01bb7ef680ef4d5a689f docs/models/previewattachprorationbehavior.md: id: 657d60d9fd5f - last_write_checksum: sha1:921ed0bc580bea1048a91c8c5ca3427c4a5005fe - pristine_git_object: 1cc089658a20a07a4f3d3a449f7373cf36037a74 + last_write_checksum: sha1:564a23e8f0cf2f3f64e729bcff18a1325986d828 + pristine_git_object: 03ddbe49817478936f3c3998f6aadeb8a85cc8e8 docs/models/previewattachredirectmode.md: id: 91c46d6fca53 - last_write_checksum: sha1:e2cfe9849731a8211e6a3ef3363f697bef6d41b4 - pristine_git_object: 48572ba5199560cb72cd3b61cd0ba32522224985 + last_write_checksum: sha1:fb3c579d52cdcbd9a99e0c90f2b92a12d005c816 + pristine_git_object: 6c7e843b528997fe4f5d10a83aedabc5fb08b2ad docs/models/previewattachreset.md: id: 8a677b69d681 last_write_checksum: sha1:441c2f04c2ca1f41a7e0251a2cf448fa63b4df92 pristine_git_object: 9f0dbd39952d86ed4561fc5cf6f573cca79b9221 docs/models/previewattachresetinterval.md: id: 62df338dbcd1 - last_write_checksum: sha1:07d10d908f65ed24de6d6962a736d0bbe7b2b7e8 - pristine_git_object: f93e84304174b521a52bca93cb58a1adef492b4f + last_write_checksum: sha1:3a48a841957e79e2dca7307a4b7222f84bad1732 + pristine_git_object: 3e9b1be359f8832c3439cad7e04566bb40ceaed1 docs/models/previewattachresponse.md: id: a678e8dbf94c last_write_checksum: sha1:e9e75a12ec734c69bd71489f74ee3ffe501c5a04 @@ -1825,8 +1893,8 @@ trackedFiles: pristine_git_object: b19c21c8f9a0b093a22fa6125ab43cc78303ba81 docs/models/previewattachtierbehavior.md: id: 115ad37af215 - last_write_checksum: sha1:d973e49f3abd3214eac6c3d9e300afaed7112bdd - pristine_git_object: bffcbde309d5b3835199bd4a9e5781ee6f12c199 + last_write_checksum: sha1:718d895201d280573f54d2c4e1d0d913bec08399 + pristine_git_object: 997335a91b67a1088b21bd08dfd8086d5ac77d04 docs/models/previewattachto.md: id: 6eea2cad63db last_write_checksum: sha1:f942419300ba675c7fe00f0675f5af3dab8e0eba @@ -1849,12 +1917,12 @@ trackedFiles: pristine_git_object: 2562b1f2a43232ca2e683c75865c8c3dfd160e50 docs/models/previewmultiattachbillingcontrols.md: id: c19e8fa54bcb - last_write_checksum: sha1:560b387986c09d14d6467c6d74bda8737c2d2ea3 - pristine_git_object: 2724646baf3af08b856069e00fc2030d0e7c8799 + last_write_checksum: sha1:b2bbbafb91f36d0f6c5bf5037f65ccf308303d88 + pristine_git_object: 4e738a0c4a0c320c8069dbe54ed9c8985eb20a55 docs/models/previewmultiattachbillingmethod.md: id: c92637a0950c - last_write_checksum: sha1:5a2f38a6ff4b85777d401dec9b91b6d45eadfa30 - pristine_git_object: 91adfcd4a6f59f413eebeff295892db454459488 + last_write_checksum: sha1:b3b600448b1f704d40dab1df259d606c3e44ab5e + pristine_git_object: 8bb4488808e3af817c5331cebfd0fbc66fbc4323 docs/models/previewmultiattachcustomize.md: id: e2e0b7d3e939 last_write_checksum: sha1:31e8437aa83882d1f206b0203cdf25a7b37932f1 @@ -1865,16 +1933,16 @@ trackedFiles: pristine_git_object: b1c9a90323f5e33a46456439d20629a7906f68b9 docs/models/previewmultiattachdurationtype.md: id: 6cc4db1fee39 - last_write_checksum: sha1:21875f45ce0041e9fa694918b0394aa91a439980 - pristine_git_object: 1ca0708fa51d5438d6002860427998538f3cbc07 + last_write_checksum: sha1:f54782456671576c1838d7ce7da24792d364d867 + pristine_git_object: bb524f83d18fc034a1d880967f6527e5be51ab41 docs/models/previewmultiattachentitydata.md: id: 1ff14291b34a last_write_checksum: sha1:ae0bb74d18a762c6e56562c4ac846b28d8ea5b4e pristine_git_object: 1089f8e85315370f7048685132b775c5bfee526e docs/models/previewmultiattachexpirydurationtype.md: id: 44455bd096b8 - last_write_checksum: sha1:8b5ac7e334e3d6647bb4baaa4e758a5f11de33e0 - pristine_git_object: b99eb21cec335eba7578deeee4e7b1ec740821d3 + last_write_checksum: sha1:02af32c341d9fcfe16d35330de4e3088afe095b6 + pristine_git_object: 6be2390f331c2386a20edaa9bfb1eb18c93e998d docs/models/previewmultiattachfreetrialparams.md: id: 784eef5ce253 last_write_checksum: sha1:3965d49ac21ea4c59455be2aed5708d38a316e8f @@ -1885,8 +1953,8 @@ trackedFiles: pristine_git_object: 74932d096dad7119db816c3ce9b93c75a64dcf0b docs/models/previewmultiattachincoming.md: id: aac62231accc - last_write_checksum: sha1:ca52a1e1cb473cb50f3496f776a73b0d9c427553 - pristine_git_object: 10e5bba08891c6294a7328644a969dc730736ec8 + last_write_checksum: sha1:d4959b18c4aead16c5b59d85ad717d818bb3321b + pristine_git_object: 46ea37fa5e57ea99fa0efc3121747186a791841d docs/models/previewmultiattachincomingfeaturequantity.md: id: 0d1c8af25b06 last_write_checksum: sha1:ba7e32dc427387e3bdcb87f7b417c23bec9fa484 @@ -1897,8 +1965,8 @@ trackedFiles: pristine_git_object: 516159a7040694c7888368e96a319b35ebd29887 docs/models/previewmultiattachitempriceinterval.md: id: 8ca44d192cbe - last_write_checksum: sha1:92e48e53a5b39b07b98d248b8bf7cda63053c64b - pristine_git_object: 0d85a18353ad4537cda3cfd68537f0b8cd96a1a3 + last_write_checksum: sha1:a0d06f55cc6f7cbbe7be3c0154ecd36aa8281e2e + pristine_git_object: bc25b0798e2a53349a757957a31bc42b7ffca927 docs/models/previewmultiattachlineitem.md: id: 372c4f319256 last_write_checksum: sha1:16a0c4e95728c97567e80479d6fec964b275c6c4 @@ -1925,16 +1993,16 @@ trackedFiles: pristine_git_object: 7c466982c51bf23d41533d2bc7117aa3471cb679 docs/models/previewmultiattachondecrease.md: id: 21532d46903d - last_write_checksum: sha1:69cd2530ebc7ef3b0875a6167e5e3a3ad60a6be6 - pristine_git_object: 0db73ef90cb74f48674006c66d71f705f9a8ffa9 + last_write_checksum: sha1:4b591c017da9bcf618d7334146a826ec658da677 + pristine_git_object: afd67f7d33a2b32a6722dc13aaea972a1657693f docs/models/previewmultiattachonincrease.md: id: 49df4f246e99 - last_write_checksum: sha1:7aa7e4615fe336d4f4b8a257e9cdb2196707cebb - pristine_git_object: d002ec146cb44a309fe32ffa4480975ea764d936 + last_write_checksum: sha1:da305ad824c752a1c618eb8053ae955d3890bd28 + pristine_git_object: b13c6cba97d2aea223ed63097abbd628467c1b97 docs/models/previewmultiattachoutgoing.md: id: 8edd3579b543 - last_write_checksum: sha1:5a259c89a52e2e0510a4f43fa017421f6350ad15 - pristine_git_object: 673233ff66246c788df1abd9909acf38d9207652 + last_write_checksum: sha1:8d17a634d48de6a12be7887c0584b16c901e243f + pristine_git_object: 8181a24468879f2b4d103976c5cad2dac41d4256 docs/models/previewmultiattachoutgoingfeaturequantity.md: id: 7469536a99c4 last_write_checksum: sha1:fe2d8764755bdbea017ce1e595634b328dbd2243 @@ -1961,24 +2029,24 @@ trackedFiles: pristine_git_object: 3e020fd0292ca357afe2fc1639370799b060c530 docs/models/previewmultiattachpriceinterval.md: id: 2b2601649b6d - last_write_checksum: sha1:c2806dec52c16c53d5b9073cf810a42b30a854a8 - pristine_git_object: 40a72a65b17f2bc402302eb86fbfa202accccea9 + last_write_checksum: sha1:bf76a503f0cfbbfe4f0ca3baf62307ce38ee766a + pristine_git_object: 84dc91145b0cf810dc6f3508d439746eda6a3f55 docs/models/previewmultiattachproration.md: id: a3b6b1d2d9fb last_write_checksum: sha1:affa177d9b1b98eeadb94b3acbcc519dc46c4c01 pristine_git_object: 0a96249ff6158b25f29c66e7fd321fc0ed9a3251 docs/models/previewmultiattachredirectmode.md: id: 3190f18130dc - last_write_checksum: sha1:d6850eaf2f0434dbb0f29505ceb501e2c1ee2f92 - pristine_git_object: e5b39411e78efc936b169a8127b02bd221695852 + last_write_checksum: sha1:a342d6a1157e69b06e071933038bc018295ec72c + pristine_git_object: 57584818b587fe4012cc335c2271bf30d2d7baaa docs/models/previewmultiattachreset.md: id: 38ec56a354c4 last_write_checksum: sha1:6227feb0bf39f70a8bef3be1ce0ee31017916034 pristine_git_object: df7d0ec6a0095ea3e6d1d2989eb2fa826f920229 docs/models/previewmultiattachresetinterval.md: id: d0d871495a37 - last_write_checksum: sha1:3cdd8557b3415144f001b6dd8e107de1db3f6518 - pristine_git_object: 1848a0347c3b21aede196a3e3f4edeec7a25fc3f + last_write_checksum: sha1:ab91f083983445f20326eb03068a6209bed862d5 + pristine_git_object: ec56bdecfc8eac78fffde4302cee7caed963686a docs/models/previewmultiattachresponse.md: id: 122c343c9098 last_write_checksum: sha1:24a707473c614f9dc2140437bf133f0ca909d155 @@ -1991,18 +2059,26 @@ trackedFiles: id: b39c2ab7095d last_write_checksum: sha1:b80d2c15524fdafff223d739c771aebf698a907a pristine_git_object: b64826019f5623f8c027aec5e48276d47bfcf156 + docs/models/previewmultiattachthresholdtype.md: + id: e4eeccd64018 + last_write_checksum: sha1:4bb9f18b372ee5f1841f41362c356bf11d902bd6 + pristine_git_object: a0d6fcfa11a9c05c430f3100bffc81e956a79d5c docs/models/previewmultiattachtier.md: id: a075b8d3b1f1 last_write_checksum: sha1:912c2757ffd96b98d56d3b8f9aac64bde23fe83a pristine_git_object: 5645fbe7df82ded057a21286f80c5c1c84b80f28 docs/models/previewmultiattachtierbehavior.md: id: 698c1ad42dcd - last_write_checksum: sha1:fd279290c7cca361a118b2e28bb90cac20a47cc7 - pristine_git_object: 3a1e36ee96679f5c25318345e82f8b0a989f3046 + last_write_checksum: sha1:3d8257623eb02e7febc36d389be1d536e3137939 + pristine_git_object: 76548a276b8599730a680f9aba2add68b23b82af docs/models/previewmultiattachto.md: id: f34b59fd5a7b last_write_checksum: sha1:bdad4bc0149814f1518a28835e98401bd06d392d pristine_git_object: 00224614a0f4c3cdbedca57e04bbb8b36b11ce2b + docs/models/previewmultiattachusagealert.md: + id: 5240ad54b06d + last_write_checksum: sha1:3111977f86d50bb7c32041f334f39b6e386fc5fc + pristine_git_object: e2444fdf567e1b043c746965f0b90c61710b27e6 docs/models/previewmultiattachusagelineitem.md: id: fee1f87cb24e last_write_checksum: sha1:f10784c42022a6168338580e5a1b1d6f3f0b1aec @@ -2017,12 +2093,12 @@ trackedFiles: pristine_git_object: 201447b16faaf38aecc9d2deb0044a28b17899a9 docs/models/previewupdatebillingmethod.md: id: 1d817ab2aabc - last_write_checksum: sha1:a0b7a400f38299b5ce557377ff1a95bdc24864b4 - pristine_git_object: 73489cd257f46774a76c73aea4988873bb7c64da + last_write_checksum: sha1:d7eb39bc6e0796792c173162dbcc17b37bdec535 + pristine_git_object: c8f89cb2d5e4d8003fd01c88a0d27bb11a766a7f docs/models/previewupdatecancelaction.md: id: 1159f8f85008 - last_write_checksum: sha1:95466e097d9f94abf963baac67bc04ba1556ad70 - pristine_git_object: 41e8d142a8eb87255d707fd3a8d6adde82058735 + last_write_checksum: sha1:ad6cfa08615dffa789adb8e42f63ca30ea353582 + pristine_git_object: e5347d9975f47094bea63fad5e615812c2d8373e docs/models/previewupdatecustomize.md: id: f4f7d5f4d0a3 last_write_checksum: sha1:9b6be59710ddb51f409f42d09e58ebb3f81b49dc @@ -2033,12 +2109,12 @@ trackedFiles: pristine_git_object: 29c1b1e47f5f57e40598151b8e7413694014fc1a docs/models/previewupdatedurationtype.md: id: "791319033460" - last_write_checksum: sha1:02779e1548b69230ce75425e28f9b0b30f3a1816 - pristine_git_object: c63a6b7f1c0fa279cc6c523ff867a47a2ba3f4e6 + last_write_checksum: sha1:49c51941f13f003c3fdb5dc94030bdc9202217f7 + pristine_git_object: 8a52c0c6cd095240f50bfad29a802c3485c59504 docs/models/previewupdateexpirydurationtype.md: id: 6d5273579d32 - last_write_checksum: sha1:0d69e9b1163c93d4c4557329004ec27797ce40d6 - pristine_git_object: dfa228c4dc2e4a3ce94bde61fab7db93629e927d + last_write_checksum: sha1:18c52730d9304d9ae75a1f8e8506a687b4962690 + pristine_git_object: dd5866b2538407dbbe1274f8a38edaf9597f85ff docs/models/previewupdatefeaturequantityrequest.md: id: 8f682788e1d9 last_write_checksum: sha1:819aa474d07da86a55bfa1e42dbc66881bf42925 @@ -2053,8 +2129,8 @@ trackedFiles: pristine_git_object: a2643aff71680053edeb399aecdfd771e4ca4e07 docs/models/previewupdateincoming.md: id: d62db8877e6e - last_write_checksum: sha1:0d08d961875bbd9d756422f3851add546c2906ab - pristine_git_object: f97549d9733aedd7da98163b9417863d9bad2a90 + last_write_checksum: sha1:b2a24574247aaf1335909a4e29db2042c6811a92 + pristine_git_object: 7b4c5d968a5b4e84af9d7b8a381b33e0fd235ea5 docs/models/previewupdateincomingfeaturequantity.md: id: 76ae479acaa8 last_write_checksum: sha1:ac92bcc9ccc296703d0c839fd5c68bc59c00bd12 @@ -2065,8 +2141,8 @@ trackedFiles: pristine_git_object: 7210d48c7d789b0e78753c7280072daccf611894 docs/models/previewupdateitempriceinterval.md: id: 5317a2333cd5 - last_write_checksum: sha1:9439782c8faf5679e6dc27f749dae7d73f1fb9d7 - pristine_git_object: 7542efb89bf43f3561ffa9ceba43149394ba2b2c + last_write_checksum: sha1:783ba76f51c898f9fcfb9fc9cc9c0c681236fc56 + pristine_git_object: 4d03b6784e60f4848254431479f0c6af337aad0c docs/models/previewupdatelineitem.md: id: 74e43e80addb last_write_checksum: sha1:e5b6dfc60e56592fa18122d3407a3885d2eeb40a @@ -2093,24 +2169,24 @@ trackedFiles: pristine_git_object: 833e7fa1bfa9421f35c24e27e791ae66c5a76b21 docs/models/previewupdateondecrease.md: id: a9a3f1b4aa0b - last_write_checksum: sha1:0ef2771526ada399e393e0909fff9f780508d52c - pristine_git_object: d611229e7808124b73329fda44414ac630e755a3 + last_write_checksum: sha1:2aad8132e9e21f2ca8260e04df4811d8c404cb69 + pristine_git_object: 1ca348c8d2f4a676d111a18d74ac9d216cc84500 docs/models/previewupdateonincrease.md: id: 391e207385c1 - last_write_checksum: sha1:426b9792fc34751e6afdab45413d40075b4f92b5 - pristine_git_object: b4267c511b2c2438d04aaa25f05391bf9bcf4352 + last_write_checksum: sha1:f8d0c7936a1260b5d0dff01f8ce55e2407ed1c24 + pristine_git_object: a36f192fcdcb7733199531049b545b65609b7d50 docs/models/previewupdateoutgoing.md: id: e6bb92550ddf - last_write_checksum: sha1:d37af5e3339abb59af969a3b02c80326ffaec6cd - pristine_git_object: 370bb5c920ead8598b45098532738c832250311d + last_write_checksum: sha1:30c9e334b9ef67d769a66b1a7e771eb3d6b5e7ad + pristine_git_object: af492b12f6e967a5766a7ed15bb8fa41a86183bf docs/models/previewupdateoutgoingfeaturequantity.md: id: a48228c46fc8 last_write_checksum: sha1:12473723f7449656c018793c8dd4d60fd1b76d68 pristine_git_object: 539712ac6959711f463c590e0a1e981b1a01cbff docs/models/previewupdateparams.md: id: cf952c2251de - last_write_checksum: sha1:e55f62f04e137489f3c6e0d19d02dfffb587e353 - pristine_git_object: 28bfd625db69fb28d1bf6046f168d21c9b1b54f0 + last_write_checksum: sha1:a6c48474ad4eb209d986dd3432e7f61e9d6a12c7 + pristine_git_object: 5185840e5bd0c276789f463ea4016a79c07fc327 docs/models/previewupdateplanitem.md: id: 741880702ddb last_write_checksum: sha1:a5256a07545cdce6e0e068e491f3e5ed791201c0 @@ -2121,28 +2197,32 @@ trackedFiles: pristine_git_object: 636b73a20517aebee5661b5bee76b578c8adb2e0 docs/models/previewupdatepriceinterval.md: id: 300f908b2503 - last_write_checksum: sha1:c571ca192d0bb1b7b26cf6f450c1051aca1d9935 - pristine_git_object: e452757bb557a2095a402cb5b6e0b4127e194409 + last_write_checksum: sha1:9c8866732d1777ff53a167166429c484d451c997 + pristine_git_object: 14a103c8e7e3ee88d61dbd99759a9f803d14ef8b docs/models/previewupdateproration.md: id: c3e1d3131ff9 last_write_checksum: sha1:f75548bc7c94e834b8ec319bb98784f4abffc6d5 pristine_git_object: 2dcc8bc0df391567537a05ef4f50abf24a365483 docs/models/previewupdateprorationbehavior.md: id: 7989e21d8761 - last_write_checksum: sha1:472410fa4891707445cc134a4a2cab1028146a0e - pristine_git_object: f09eb4baade271cd90673805ea85230e5fbc9c49 + last_write_checksum: sha1:c93d8760bbfbe3a0f3b2bc2a1efa5424ef9373a6 + pristine_git_object: 3bad44b745b15ea8e77d39c9220596c650c079d5 + docs/models/previewupdaterecalculatebalances.md: + id: 33030c0b1996 + last_write_checksum: sha1:d8a148d9bf0ae35f8013c410e25119d8151b926b + pristine_git_object: 3f7e04f7509a9d64ead05c2ae326627cb8ccb088 docs/models/previewupdateredirectmode.md: id: e216ddc3986b - last_write_checksum: sha1:130d0647417b2cdd3b463aed2782977ee2d48a39 - pristine_git_object: b7fd0581ce5e2fc75f78a16f7068aa9a1a352580 + last_write_checksum: sha1:ecac0b945f80a6f1b79349c4e3e2963b8c2fa0e3 + pristine_git_object: 96d050edfd6010ce162f352cef87d7c75687f05b docs/models/previewupdatereset.md: id: 0575a09e5ac1 last_write_checksum: sha1:20aca504ecf7ce4d56eab0ebf69af981c7f2903b pristine_git_object: c85d5a3300fdaa77bb45b4d92321c92ddb1896f6 docs/models/previewupdateresetinterval.md: id: f23e968cc58e - last_write_checksum: sha1:e42956af55e53f45c47c152873d8235e29b7e48b - pristine_git_object: df69f8a61b19667d538abe303032542b39d111f5 + last_write_checksum: sha1:c4f1239d2233e77448908ff5eb78b17bbdd9ff94 + pristine_git_object: 8290e0f1adeceace60c5189e9d8a2cb0b11471fc docs/models/previewupdateresponse.md: id: 4a657c603c51 last_write_checksum: sha1:852ed327e9ff9a651f734d797a66089dca3f078f @@ -2157,8 +2237,8 @@ trackedFiles: pristine_git_object: 0c481f87403fa61b8209429b58cd9a89d70416e6 docs/models/previewupdatetierbehavior.md: id: e0ecb90f6fe5 - last_write_checksum: sha1:aed1b00821f049d0d02433e8e27d942ecf3d5888 - pristine_git_object: 9b656bbc1ac9af47ea43144e53f195f7510c8499 + last_write_checksum: sha1:a53cb1a4ea349f2d8f7b0c657c16a0035d379f59 + pristine_git_object: 8a5b3f74ff2494837ea1d6f2085569c78a960472 docs/models/previewupdateto.md: id: c8706fb2f15e last_write_checksum: sha1:ee0c86ede67f157bc7d60c0dbe8c11567ee98418 @@ -2181,20 +2261,20 @@ trackedFiles: pristine_git_object: 22e14f97a475eec1b273ba6e10063f0e777aa6b2 docs/models/productscenario.md: id: ab3587084a21 - last_write_checksum: sha1:c0d596fc265da91e77bd5be7962bf8738c6ffd6a - pristine_git_object: ef93f479e1993ff12a83734661ed5640d6d074c3 + last_write_checksum: sha1:34b69aa0f068905c5c668fef314d6d278865864e + pristine_git_object: 3c82690287597c8ab32ec97a8f6f4150aa78f58a docs/models/producttype.md: id: 2c019befb41d - last_write_checksum: sha1:978c5475fae093e6622a67c300c4caa3ca4f5323 - pristine_git_object: 9bdbe295958794c930d6056b4ecc8f1c448323cf + last_write_checksum: sha1:3dfda58f5087dfee73766c1a24dbf64bcd18a6e7 + pristine_git_object: ad0e92bda3041d17df41475adeca765b6cba81f2 docs/models/purchase.md: id: f872769b6939 last_write_checksum: sha1:b250603c69b08d953b6f2dde179eec8606d27ef9 pristine_git_object: 133bec63c1dce6f39d3954909e188dae71f3e2af docs/models/range.md: id: 0cae0c76762e - last_write_checksum: sha1:ae76473539105f50e728c1657bf5d2af3699da0d - pristine_git_object: 607ea6d29d56b0fa97a1a99a06d2b3caccda78f5 + last_write_checksum: sha1:617c58ce88db53abb0e38d60cf2027034fca69dc + pristine_git_object: 88e64b85535ba90767889f32db386fadd2d0b94b docs/models/redeemreferralcodeglobals.md: id: 5640df85921d last_write_checksum: sha1:44f830b7a0730a261b0403ebb6a949d9ef7f1918 @@ -2221,16 +2301,16 @@ trackedFiles: pristine_git_object: fcbd3790d73d6a7157b9665d8221be09af8822bf docs/models/rewardstype.md: id: 338992fe95d5 - last_write_checksum: sha1:224b80dbd92ef68bd770b3a80bf937ac43733556 - pristine_git_object: 8b34bbb0cd357bcc79eb45b0e7f4ce9b6399f846 + last_write_checksum: sha1:7eb06abf43f702403e324aeab931a3affd4a37ab + pristine_git_object: e3e5b0cff2939b70dd449114ac63bd2787ff8732 docs/models/rolloverduration.md: id: 6338776421bf - last_write_checksum: sha1:0fa5a19f470504e5ef7e45057d92f6481c2b7d3b - pristine_git_object: 1415e465a1f2966167dab17d9fdafde292816ba2 + last_write_checksum: sha1:74a9d6e9ee3291773a9010467a0d26721203f6a1 + pristine_git_object: 556f622fc78575df4efda34f58c9dc8c7da7318b docs/models/scenario.md: id: e3aad8ab5efa - last_write_checksum: sha1:6ce9a6e38f0a02622ae273bef4c8a6daa91794fc - pristine_git_object: b1f3a49d0d84ad314bb2103a706454e1314edc06 + last_write_checksum: sha1:132dfc4d6a03ff1073be4390633a64afd909c700 + pristine_git_object: 58c924cbae30e7c3a227a04ab9655c97381be99a docs/models/security.md: id: 452e4d4eb67a last_write_checksum: sha1:64787360e0bddbe1d2d2ede91992fa1a27c15a0e @@ -2245,8 +2325,8 @@ trackedFiles: pristine_git_object: 77867b1b1a7917f32c17387092ae69eed9f843d7 docs/models/setuppaymentbillingmethod.md: id: 3048b32fa76c - last_write_checksum: sha1:e848284bc3792e584e4478b9e56f338917c181d9 - pristine_git_object: 82e28aa321e92c94ae8b30336fce42dc3dd07042 + last_write_checksum: sha1:128a736c42e76a6af1eb0350ad3b99068867c400 + pristine_git_object: 50b7f326fbf3fc4125a453dd50422f5dcb80c296 docs/models/setuppaymentcarryoverbalances.md: id: b4b6d5e8b123 last_write_checksum: sha1:9b90774e7eea5c65992df6162ea394e7e81c714f @@ -2265,12 +2345,12 @@ trackedFiles: pristine_git_object: ef754a56df7fde8ddfe8a0f78afbe70876c82ccd docs/models/setuppaymentdurationtype.md: id: 05682f9ba3c6 - last_write_checksum: sha1:2b08dbc92d5b1619dc16528ddf535c0a068acb0c - pristine_git_object: 1e3214d3f28ec62115f8da3d243d536c6d27e4f2 + last_write_checksum: sha1:727d37a22da29f321f3b1104bf36a7ef09ca3d89 + pristine_git_object: 2f50fe56b53431668fcd8ffd939345127fee8f04 docs/models/setuppaymentexpirydurationtype.md: id: 31b912769b88 - last_write_checksum: sha1:39302c6bac58e2b7a336b1425b95851948188b66 - pristine_git_object: a0e7afc3066491ef449dac6931035965b66dd99f + last_write_checksum: sha1:59a3ed79a04580b80a36c7c4a3831358b50a2536 + pristine_git_object: 19b8fd2469069c21ab4b77f62c6b695ba3c0898d docs/models/setuppaymentfeaturequantity.md: id: d15328882840 last_write_checksum: sha1:4f1f0642102d637333d8db0db558ed7d3270b379 @@ -2285,16 +2365,16 @@ trackedFiles: pristine_git_object: e46150aa6597ad09d02461b1438d42eb20ad44cf docs/models/setuppaymentitempriceinterval.md: id: 6337a430ab96 - last_write_checksum: sha1:b663d2d0f2d126f86d87fabbc537e335d050c6c3 - pristine_git_object: 2087c3175fd1aef19a9ba7ab3674b30fccb6daf8 + last_write_checksum: sha1:8dc0e5678b2a0221859198122d57bd0cda7914d8 + pristine_git_object: bfce67601550f16b24bb69be2c62fb51043fcc98 docs/models/setuppaymentondecrease.md: id: 6d4113b4eb77 - last_write_checksum: sha1:b0f2265a18d59b4fe76be480d51e621e3377d25b - pristine_git_object: 1f77bb3aa11e1d1b2725b6e25fceeb5c431f03fa + last_write_checksum: sha1:0bf24f17cdaa4982333094dc508b2184ee030291 + pristine_git_object: e35ae42fa4a7566b81b292e0a697eb42cecb76ac docs/models/setuppaymentonincrease.md: id: fa8cbaeccdec - last_write_checksum: sha1:51d7a45047a57930db101284ae9306778d5282aa - pristine_git_object: 546483389b2445ebcd164757c3fc24f07b48a40a + last_write_checksum: sha1:6ab77cad16e4c3b6cb7ce4c216b4e921b2ff0d6e + pristine_git_object: 6888fb44e13c6ac1a3a20519abbc3c6b6da21c16 docs/models/setuppaymentparams.md: id: d71f82dde273 last_write_checksum: sha1:ea8794fe6f5c47f316256195dcffd9909982659b @@ -2309,24 +2389,24 @@ trackedFiles: pristine_git_object: a7b596ba76c3edb1f48295df565fea57f9e38ac4 docs/models/setuppaymentpriceinterval.md: id: 6dd9488b58f0 - last_write_checksum: sha1:52decddd27ae126eef3b0c7c92d9fc981188335a - pristine_git_object: cfdd9e7effddd9ef752ee10da99fe6bb83972f31 + last_write_checksum: sha1:7341e34bd16262a6ce0fe03f616f352960f45882 + pristine_git_object: ad04914a4bcce2413bdc5404219e4d58c31ac52a docs/models/setuppaymentproration.md: id: 05a134dd45fc last_write_checksum: sha1:5f4b5e93872db5597511d831a6e91b37fcccfc8d pristine_git_object: 03eea5cf24522fae92de2f3edf22afe4dcfbb9eb docs/models/setuppaymentprorationbehavior.md: id: 96ded50f9766 - last_write_checksum: sha1:dc675208709b51015d79c11ecbd6395e6cd7aa59 - pristine_git_object: b79cc25122d2f3e75b5504ac2ab52c1f1ff527cf + last_write_checksum: sha1:1453a79f84609625370edb54c99f5bc60da9fbfc + pristine_git_object: 4b78289cbfa4157f45b92da2382243db67e50abd docs/models/setuppaymentreset.md: id: 1136ec30628f last_write_checksum: sha1:a650b96cb252f1d62f5d6a5e23ebea94959a0224 pristine_git_object: 76cd91f39a87211852c4f8cfffba2ecc0d75437f docs/models/setuppaymentresetinterval.md: id: 38c4d903d5d0 - last_write_checksum: sha1:c45a6d03853d6a37e802f35ab5b5bf29f374e9d7 - pristine_git_object: 6e3c3291a679aff2fe6fe899f354ea0b70bd9c5c + last_write_checksum: sha1:5e333d5badbb195def783ce1511ae61406310b55 + pristine_git_object: d3eb8e68ecc6a857af27ff4918df0bdfb3127a62 docs/models/setuppaymentresponse.md: id: a0fe36809906 last_write_checksum: sha1:0506cb5fd620fb73affa03da445160a245e94fd6 @@ -2341,8 +2421,8 @@ trackedFiles: pristine_git_object: f1184c11fee3ca95c2d182d8952e696f44b3163b docs/models/setuppaymenttierbehavior.md: id: 882d41b17f9b - last_write_checksum: sha1:9624300c291a6abdbfdf023b6e9405d87c03b2e0 - pristine_git_object: a87822d8489977cf4150eebfe1e6ef53ef5b3812 + last_write_checksum: sha1:490c71713c9d35c83684d140e282e6706d219a77 + pristine_git_object: 403b2ac9f33aafaaed978d9958cbbc3d563e795d docs/models/setuppaymentto.md: id: 06660d546541 last_write_checksum: sha1:f8a7cc7213fad6d967cdd1db038ec6eef381ba84 @@ -2353,8 +2433,8 @@ trackedFiles: pristine_git_object: 5bb9f22b2f50cb4c2ba4d8172fdc21b7842cd607 docs/models/subscriptionstatus.md: id: 5f08d32c769a - last_write_checksum: sha1:9daad10a8b01ca11973e1b5e9a35f87ea63bbfaa - pristine_git_object: e4179dfd1a9d9cf69a2829c1d5ad97b9548bb258 + last_write_checksum: sha1:3cfa48d8a7dff1b56bd411ce40c4286ca788de54 + pristine_git_object: 6751a76861dda8aafb85e42820a94f0f302c4dcc docs/models/total.md: id: f4060c3b4657 last_write_checksum: sha1:08c2c14481fcae1bcc1c550d6e2c95f14bb1efb0 @@ -2385,8 +2465,8 @@ trackedFiles: pristine_git_object: 7f44dc945c43a94cd7430babc830c88411354c6f docs/models/updatebalanceinterval.md: id: 1d9c4657f238 - last_write_checksum: sha1:d9ca8e749fd902d267a743daec975852be7833ae - pristine_git_object: bba342bc8878dc61f2d7d3a3c6b306310bce255c + last_write_checksum: sha1:147408360253aa9509de87d41c391d60c8862ed4 + pristine_git_object: b4afc96b118bffa16de417ced419af3984696a68 docs/models/updatebalanceparams.md: id: 8bb20f144794 last_write_checksum: sha1:ec39ca7cb018bbdc4bd0becfc32c6f4dd6f59e6b @@ -2405,12 +2485,12 @@ trackedFiles: pristine_git_object: 78fe38b1840b318e9a42271326249c30be7ae3ae docs/models/updatecustomerbillingcontrolsrequest.md: id: 5c18ec5ef144 - last_write_checksum: sha1:c20ba3a8af94953fa1a381480346d27ad0529bc9 - pristine_git_object: e715ac73cb35146c11e6bf6db939cd3a1465be4e + last_write_checksum: sha1:b0438b946525e8bc97c299211f460acb046dddc9 + pristine_git_object: 96ef36eb666e0a3902c973ed1c92ea36c27b797c docs/models/updatecustomerbillingcontrolsresponse.md: id: e37df91f0df9 - last_write_checksum: sha1:727828070e95dd6404de2c4d02491f1ceb0bffab - pristine_git_object: 8950bc4f42038ff14328222cb81492ccd01a3212 + last_write_checksum: sha1:3952942c32006c9bb9ba45578387416586615085 + pristine_git_object: ceff7c91eb958dc9ceaf64db1535e7a843dc7ef1 docs/models/updatecustomercreditschema.md: id: 9ed2810c66f9 last_write_checksum: sha1:227267de049542b40c7600fff384205cfd8b0d14 @@ -2421,8 +2501,8 @@ trackedFiles: pristine_git_object: 3f8f425694448a3d57a7f45da5185b1ea80cb928 docs/models/updatecustomerenv.md: id: ee8d2224eeb3 - last_write_checksum: sha1:4f41776f1ec13d3cedaefad2f5c913456cdf69f7 - pristine_git_object: 15447cc6e29a6523fe3367bba9bed19fcb10bb5b + last_write_checksum: sha1:2d3ebb5ec7bd7948a7a9b1aa12505b5e725fe3c6 + pristine_git_object: 93eb528d888c1d94f2f243e20d732466bff2d175 docs/models/updatecustomerfeature.md: id: fea7c9019bce last_write_checksum: sha1:6f951a1a22bc74d3c1460f281af27fe01b7940fc @@ -2437,12 +2517,12 @@ trackedFiles: pristine_git_object: 5010263b034bbc3eaddad96700c1088373e6b6d5 docs/models/updatecustomerintervalrequest.md: id: 148680817ee5 - last_write_checksum: sha1:db7d05cc49e59dfdf529bb035474ea200383e25d - pristine_git_object: 3574243b504d51ea32f3ffc1535d7a222f5fa8d2 + last_write_checksum: sha1:fe7148b2ecadcdc72b6ec7d2c86fc9730b81d42b + pristine_git_object: b6e6cc4fd79bb027e4b5f39ee541e5f09a03baa7 docs/models/updatecustomerintervalresponse.md: id: 1dc4aa6e2084 - last_write_checksum: sha1:22ce98772b76a1a75178149d0856e938f510b1f7 - pristine_git_object: 378867d636156a79358809a0e255888423dc0807 + last_write_checksum: sha1:3f5d3bd2b6973514faba2e1602b04296105c36eb + pristine_git_object: 479bb5714d9890ecfa4421845309690f620267a6 docs/models/updatecustomerparams.md: id: 4015e931c04e last_write_checksum: sha1:8a84f9121bac84ad44b20595ab1f9cf3b8d824a6 @@ -2473,24 +2553,40 @@ trackedFiles: pristine_git_object: f604c4499e1547fa5b8d57c1f156d397d4aeff7e docs/models/updatecustomerstatus.md: id: 12e6ef4fbad5 - last_write_checksum: sha1:2cded2d0b887d162dcc8a3b856b5b8e093337064 - pristine_git_object: ed8a2aaa3204d2e6059a244b31379b4740cd2663 + last_write_checksum: sha1:f2aa61050f39ca17d657955339d3f6b81c9b1bc7 + pristine_git_object: 991481f1ae5a7c363ae39cd5f46672548fdde0c7 docs/models/updatecustomersubscription.md: id: 23620d1508c4 last_write_checksum: sha1:9c40c57f10465741cb0f291015c5ab5a289c962b pristine_git_object: 114aba943de596f1b88f17934c479354d739abd4 + docs/models/updatecustomerthresholdtyperequestbody.md: + id: abdb64acf98d + last_write_checksum: sha1:e8bf59424ba1e6407befbfa31569508c41af3828 + pristine_git_object: 45a3eed0c7a07fd7828c994d33e6757138ca31ba + docs/models/updatecustomerthresholdtyperesponse.md: + id: 9139edd2c355 + last_write_checksum: sha1:889f3d456dbe2799b6336d1dabd577cb66e173a4 + pristine_git_object: 22691efd44fb1ea1d967fc058fb2124ce0e86e80 docs/models/updatecustomertype.md: id: ade4d76bc6b0 - last_write_checksum: sha1:fe24ab4f286b788135bd5a2eef54ba192931c40e - pristine_git_object: 1bba5fdc5ccf2638a23acd427b9ed701db73898f + last_write_checksum: sha1:b3872c822e4de81396b9fddc5a49030ff3ad1ff8 + pristine_git_object: f61c05f4e8df8652c6239d6663320da08c19835f + docs/models/updatecustomerusagealertrequestbody.md: + id: 048dc0a2be61 + last_write_checksum: sha1:61770e61771d9b3711a5fa63f60014588dc6da13 + pristine_git_object: c8abd91efd75d0da0c2ba9f282ed2ed44d6d1262 + docs/models/updatecustomerusagealertresponse.md: + id: 7db234ab2581 + last_write_checksum: sha1:78df4f4b709e90bab51a9f7777646024dc157fa6 + pristine_git_object: 1c6e7862b0d9a3d8eb16c96534e3c7922758ddeb docs/models/updateentitybillingcontrolsrequest.md: id: 242c37ce54ce - last_write_checksum: sha1:aa1d39a556b90836af79d6f4c47c12d04aedffe7 - pristine_git_object: 0d1c8f5f64c87d52bf3cf9b7444995b7b3832e1b + last_write_checksum: sha1:8c96dec3e66340d343ec63050c0647d2764f9997 + pristine_git_object: 0125c7a70be7ccc3f24914a3427d8c572a7988a0 docs/models/updateentitybillingcontrolsresponse.md: id: 81d4144625f4 - last_write_checksum: sha1:3fadd5a3dca61bd0cff2ee23975f116053bab3e8 - pristine_git_object: 3cc4ecc1c60a22a57cd6f46854add30d600a2dd5 + last_write_checksum: sha1:f287277db020ccd2052530bebf9b64aab8079c76 + pristine_git_object: 760b0709f0a45a8bffd9a5a65fad7780008f5bce docs/models/updateentitycreditschema.md: id: f48eff237987 last_write_checksum: sha1:0a70801cc38b60162a31657a975d8aabb25b324f @@ -2501,8 +2597,8 @@ trackedFiles: pristine_git_object: 012a9e3a034af846c2c5c5c2fcf0d9befd1a9ca5 docs/models/updateentityenv.md: id: fb351a5af38a - last_write_checksum: sha1:6b6a3d581e16f964b2ed11949e11f72575f2539e - pristine_git_object: df5e9c11ec6ca45e6913af5ef3b1636bacce3c92 + last_write_checksum: sha1:28f989108d327ca7f57448689ef3fe098ae4de08 + pristine_git_object: 8920137285e76a70a5c115b267d3e5d31cd8a4f7 docs/models/updateentityfeature.md: id: 30b1d308d00d last_write_checksum: sha1:993ad4f4aa1ef7ad0ba334265ed0dcfbfde7845d @@ -2541,16 +2637,32 @@ trackedFiles: pristine_git_object: aef36c7c11ca063a7ecdaa72d728bff3fdce4eba docs/models/updateentitystatus.md: id: 3b12d3261c1d - last_write_checksum: sha1:fc8b090bb4620edd0e6c8a97318180fe0d76450a - pristine_git_object: 6a6259482772250caa0ab22ff5f9e0a9d93d9cc6 + last_write_checksum: sha1:c3066481e8b3834a8028c56b595a7a9136734f13 + pristine_git_object: 85d40b65417a2f06d51f1e10541cca44c1585b1a docs/models/updateentitysubscription.md: id: 6b6242a7771b last_write_checksum: sha1:ce6f7693abaed603bc7c0c41572bf95a337ca456 pristine_git_object: c41d09e86e84d272182a57180616fca862dc3033 + docs/models/updateentitythresholdtyperequestbody.md: + id: 9db8438c9a7c + last_write_checksum: sha1:75a2fe8b6aa1ed7c72f006d18b52f8c7621af3bb + pristine_git_object: ef7e1e82f4eeb486674d6032a8f785abe60182db + docs/models/updateentitythresholdtyperesponse.md: + id: f7e69615a268 + last_write_checksum: sha1:0f07ae539ccf6c8d33c47aa0fe109bcfc63af6ce + pristine_git_object: ad6f9f1a763d36d80bc84e5f0ba5c3a6932d1dcb docs/models/updateentitytype.md: id: c63e96d62ca8 - last_write_checksum: sha1:a683e322f2f743930a39dcd27d964917c82831a0 - pristine_git_object: 32f4009a0753446d5f977c1633d303dccc83a7df + last_write_checksum: sha1:2eeca832531a33c7b59607dc6f088c739ed4979e + pristine_git_object: adb0e993b332774500b4e7facaa36c413799ab5b + docs/models/updateentityusagealertrequestbody.md: + id: 0b89a7c9e9e7 + last_write_checksum: sha1:af0e170c400213d375b39133a5170512e99a9a79 + pristine_git_object: 1df705d8005d7b97f6fd4f5b1504ceb302c375af + docs/models/updateentityusagealertresponse.md: + id: 13b4ce2e62c3 + last_write_checksum: sha1:cb78b072a48bd54af9266301c1e7391f6b150c71 + pristine_git_object: 447bc8cec4727f2b60c47cb17f2e9a7d456df152 docs/models/updatefeaturecreditschemarequest.md: id: 44ff205415c8 last_write_checksum: sha1:83a7d17ecd1bf259e95f29a1b56e901f519df814 @@ -2581,28 +2693,28 @@ trackedFiles: pristine_git_object: 846deae07339f3b6ca8b069c0220ef684dc58505 docs/models/updatefeaturetyperequest.md: id: 9dfd1c01e1fe - last_write_checksum: sha1:c29c39e961d308b69828e02d7a8db5dc5f620e6a - pristine_git_object: ccc1bfb836abfeb960f654facb15ff71012e8783 + last_write_checksum: sha1:d993e2a8a7150c1ec34a507f1ec763c3878a39e4 + pristine_git_object: 820adbfdef4578fcaa76d590264b24e521f3ec55 docs/models/updatefeaturetyperesponse.md: id: 0ba0a862dcca - last_write_checksum: sha1:fb11dd3937490037fac83c816866d13881012cbf - pristine_git_object: 36459374751ba3aad0777c2ccba570553a0d7864 + last_write_checksum: sha1:cce928a20c3fccdaa2d05f1cd9f4d24d01ef6eb1 + pristine_git_object: 7ded05a41034ccfa5be6f65118f23d14503dfcdd docs/models/updateplanattachaction.md: id: 606933a404e1 - last_write_checksum: sha1:d81a7652fc07d342634ecd173e8b6f9aed9fa43d - pristine_git_object: ad36f93503838af401489616dfce1916dccb08f4 + last_write_checksum: sha1:f2c212d4b1a791b85c9098386e7583b692ddd8eb + pristine_git_object: b55e8df430d21db509a8840f5e31ec68eda1301e docs/models/updateplanbaseprice.md: id: 61443f3c272a last_write_checksum: sha1:b554cc0015982aca7e2ab60294743f8da9d90290 pristine_git_object: f8cdc4ea1952336cc36aba8e9631925a3c4eb88e docs/models/updateplanbillingmethodrequest.md: id: 9ece57bad5bb - last_write_checksum: sha1:194172cd5d620f3a2f7f0ec3ae3e967702d32d9c - pristine_git_object: 9965276937c54b62becfae3b972bae91490cd003 + last_write_checksum: sha1:cfa1e131cdd0a2fb39157b1f4dfab588dbff01b4 + pristine_git_object: a59277cc10586f7b3937a81ad5d853f5c5e5fa99 docs/models/updateplanbillingmethodresponse.md: id: 1f6a0cc6dd9d - last_write_checksum: sha1:1daaa2ce4ac4ec4dee50322a96f784fb93c7bb55 - pristine_git_object: b374ca2fe3d81b9837259cbd754be60742de24e9 + last_write_checksum: sha1:c43d4eafa56f7696011abfbe2a653e6da459d66f + pristine_git_object: 336643d69469be6447c4b155b0b2582cf2bfc4b0 docs/models/updateplancreditschema.md: id: 00c090e1bf26 last_write_checksum: sha1:38829677cb91237900845a612c71c5341cecb59a @@ -2613,24 +2725,24 @@ trackedFiles: pristine_git_object: b1f0a8a0df11b847fc9798ad43ac5f468238288d docs/models/updateplandurationtyperequest.md: id: a2b05beb83e5 - last_write_checksum: sha1:11307befb98f5b62bd822aa3f544c59a88d66176 - pristine_git_object: adebfb3fc4d77cd2f7604dfadcce42562830a334 + last_write_checksum: sha1:749717a358e65ef0d99188b259bb443fb3baeb5e + pristine_git_object: a5e74c2711474666844909fd7723b7054d3d908e docs/models/updateplandurationtyperesponse.md: id: f7bb7d7c64e1 - last_write_checksum: sha1:f4ae1cfe19a60a83b35acd4f5251dd44a99e06b0 - pristine_git_object: 094a56d4a76d9b1327b6e1125941defde6198b09 + last_write_checksum: sha1:853186bdefa8008db9bbcda97cd1b5c8da7cedd6 + pristine_git_object: a6655d3f8cded4515f58037409612e985ffd3a41 docs/models/updateplanenv.md: id: 7b54ca1834fa - last_write_checksum: sha1:59dfc5df1f8712bed19b33c7953ed726c325219c - pristine_git_object: 9bf11e71cbf7d9dcf7bc6fc2fda970bd9cbec6bf + last_write_checksum: sha1:aeb7637ae4d1aa4d4d9163a90d5525f575781669 + pristine_git_object: 4d2737b1c882b506c026e01fdd63b66b9dbd16d4 docs/models/updateplanexpirydurationtyperequest.md: id: c44c66c550dc - last_write_checksum: sha1:22164f6840d087c3a7a8a73fa79cd846324a9e71 - pristine_git_object: eb290fc03e6bea2612f70e4b9bade7e50f5411ad + last_write_checksum: sha1:67d347bce270f142bf537e3e10095f385d9c0f62 + pristine_git_object: 4cb0c3b037641bed277eb928ae0241f10c3e17c0 docs/models/updateplanexpirydurationtyperesponse.md: id: 3801fddf678d - last_write_checksum: sha1:2e2e826b274e905bb1e75738004335828c74ba01 - pristine_git_object: ec6b74b92b0701d9c7ddce8d9c20ad6977b2ae24 + last_write_checksum: sha1:f7cb607bcb647cb6d995ac8033f9f488aa073554 + pristine_git_object: 0d56ea783952da17b628f6a750aac9a683fae797 docs/models/updateplanfeature.md: id: 0e58961a26f1 last_write_checksum: sha1:940e0421db24f039755d98a9769d68a39dfdb305 @@ -2661,20 +2773,20 @@ trackedFiles: pristine_git_object: 21629fa6207463ffa51a8292ea306694bb3702f0 docs/models/updateplanitempriceintervalrequest.md: id: 4ba82cce682a - last_write_checksum: sha1:c8ef5380b001a3e91ea378b900409e440661729e - pristine_git_object: 29d2f0b6c460c22e783b7806d7fce00ed59c57a6 + last_write_checksum: sha1:e0c021f6936b3a52d8dc5652fe4e8aaa569d5b46 + pristine_git_object: 01a0ae3b5e94f3e919869282da57d52b4ced9f1d docs/models/updateplanitempriceresponse.md: id: ad114972ca0e last_write_checksum: sha1:2276382a193c330dfba34b277b4ed02a71bcd3c0 pristine_git_object: 031e00002ab60c3dff8d4a63d6f732ea0aeee1b3 docs/models/updateplanondecrease.md: id: 02ccbf603191 - last_write_checksum: sha1:b0db07b2c7b2e3c2fe5c07c9f62e1afbb48f26b1 - pristine_git_object: 55590da8bf6e4054fa7050af24eb46b47db849db + last_write_checksum: sha1:2fd6b7131d7b287b55e4933cf56460a282e912dc + pristine_git_object: d21cecf98d8d4914ff936c09a63ab7687292c6fe docs/models/updateplanonincrease.md: id: 764d851d7cca - last_write_checksum: sha1:d42b6434ea9c72ba8c8f8f51faeb17ee30da9e4f - pristine_git_object: 0c2d7187551a45b5d678265295d3521f5286c11c + last_write_checksum: sha1:40bf70c3e175e1d46508f9f250c7b4aa0c2222c8 + pristine_git_object: 04577435bf75320ae14c441d963a401faa3cdc85 docs/models/updateplanparams.md: id: ca9b432d1066 last_write_checksum: sha1:3626993a9b2e8d98b67aeb5b39ae321e6bb90f3a @@ -2689,16 +2801,16 @@ trackedFiles: pristine_git_object: acb2e90916dba40e2bf46027f5a9288945633565 docs/models/updateplanpriceintervalrequest.md: id: 616fa0a68bae - last_write_checksum: sha1:1a1639a4c538495479296e58794345164c2ba0f3 - pristine_git_object: 4461a24c16d64e87b6c3c2ace5c2477f426b3d84 + last_write_checksum: sha1:56b5b2ca99d7033ad6fe94cc4ecc441414e9ab80 + pristine_git_object: 243d5c0620ab4625e02283cce16f978dbe889573 docs/models/updateplanpriceintervalresponse.md: id: fd5b2b703739 - last_write_checksum: sha1:59cc2039b96d0c12ca4013f26e210a4091349383 - pristine_git_object: 69f32259ff488d46da5fbea7f2dc22dc0163d49f + last_write_checksum: sha1:52fc0ea4df6fcaaaf341c737ae7d140db12eca4c + pristine_git_object: 74b3b32e7e92194886ba12877681f19587af3ca7 docs/models/updateplanpriceitemintervalresponse.md: id: d6754f53396d - last_write_checksum: sha1:85e7f34795a8d10bbfdab502835e26ff549e3abe - pristine_git_object: 6abd0556d5f46c9bd9191b2e8175776f298acfae + last_write_checksum: sha1:11791b341094597d0d24d633fb4a44d97e258072 + pristine_git_object: 97de36201b0ea99623c236027ac84971540b259b docs/models/updateplanpricerequest.md: id: 768f8e75b84e last_write_checksum: sha1:62d78bf601e6d1ec1c7898b7e90ad2969f435808 @@ -2713,12 +2825,12 @@ trackedFiles: pristine_git_object: 2d494ae9f039b1cc5e0ce0744f92a4f8207c8eb8 docs/models/updateplanresetintervalrequest.md: id: 7c76042b1bd9 - last_write_checksum: sha1:baecc78ee81e32ab991330160f1ac34719be171c - pristine_git_object: e6e4563ea3e98ed341548c2bba5fcd30148b1e0a + last_write_checksum: sha1:2ffe8a420f674dd4812f921af3a4d8f606c0151a + pristine_git_object: da79d525d03183817af5fd1d86797de83a58e670 docs/models/updateplanresetintervalresponse.md: id: ce0550104677 - last_write_checksum: sha1:859cf2ee39c30e833c8303c7a21deef66a0c9544 - pristine_git_object: 1656ae6671cc4548ebf28a35ebe24b636e96466b + last_write_checksum: sha1:a3e94d39ec09299488530f04d34333aabd42ccae + pristine_git_object: ead7fffc15f6affb3580165d36b3afbd0cd8c601 docs/models/updateplanresetrequest.md: id: e5a7572f3d0c last_write_checksum: sha1:7696cc75c02ddc1747d11d277ae1c39c98f33eed @@ -2741,36 +2853,36 @@ trackedFiles: pristine_git_object: c9c19d637b8d395bf116699d8ea2d732dfa0e707 docs/models/updateplanstatus.md: id: 9fcfb9af1504 - last_write_checksum: sha1:3d9a8b948f1dab91b439b25fe04f05a6cd8d3a40 - pristine_git_object: 3875a75e71fe148db0cc5710ad55a4e86070312f + last_write_checksum: sha1:b5738fed6e1cdc2bca862c277726a4992833d2dd + pristine_git_object: a41b7d601dd6a602601bbaac0211037111d0a983 docs/models/updateplantier.md: id: a0a2771747e8 last_write_checksum: sha1:500cef705b585c0b909d21b60383ca6d0646f5b3 pristine_git_object: bda0ee7ce74ebd4e280de314c55693b14198b20b docs/models/updateplantierbehaviorrequest.md: id: 73b92d1c113f - last_write_checksum: sha1:b1a89235e395df20de6baaba1caadb81d5824f6d - pristine_git_object: 6782a3ee1dc8a1d4d242b46eaa9c7b488e20a8b3 + last_write_checksum: sha1:302dc2df6776fa7a58b457c96b0cdf18b9929684 + pristine_git_object: d686303fb8b882a57f194b1de35bfd2c9ec3c0d2 docs/models/updateplantierbehaviorresponse.md: id: 4cf0cabdcb8d - last_write_checksum: sha1:fcbde197f9ffb6189dc6164ba517dd80c4380521 - pristine_git_object: 1d073f866f2e50853948d8cfed3a796802f3d30a + last_write_checksum: sha1:089f2448f428d3bbf1e4578e9d8da9e2ef15ff7a + pristine_git_object: 24ed2e85cb8ee0323c161b19948b70eb4ce73e20 docs/models/updateplanto.md: id: e0ac738348d2 last_write_checksum: sha1:44502fbd923cf1209624e883c4cb06c757171410 pristine_git_object: de7349c14ecaa21bc7ec57d5c2f6667537ff0e46 docs/models/updateplantype.md: id: edd98356600c - last_write_checksum: sha1:b0a891101d766bd45726dd49d9e48dd4b8948055 - pristine_git_object: e058f74c3f1ca285380a040c69c6a208a90d503f + last_write_checksum: sha1:4c871c437a31b5f2547081f5b0f5eaee1f70ca19 + pristine_git_object: b9d2352c615bcb39513c4cb64ff5ea5278814710 docs/models/updatesubscriptionparams.md: id: df1b06618f8b - last_write_checksum: sha1:16496d5a4b9dbe46025405f29265b2852df35e90 - pristine_git_object: 5863c4f1e99ac8b3d0425be69dc215cd3184d3cb + last_write_checksum: sha1:6af36f14afab7a845be5ce6ebce9896a921f2e70 + pristine_git_object: 3e48baa7c98f173dba9e81cc3eda5f08c519e4cd docs/models/usagemodel.md: id: 1e12a2a8fc52 - last_write_checksum: sha1:0aae39e704f2d84d1ca66c0ff3e0bbdd5dba61cf - pristine_git_object: 1c478ab31dc35e34bc4fc7eee7c0078f31ceb35b + last_write_checksum: sha1:6e6803b39c0b8d88be49568c7a1bbcf8b4dba4c1 + pristine_git_object: 04bed5b0edb595538e12de13f5b395a74ecdbe2e docs/models/utils/retryconfig.md: id: 4343ac43161c last_write_checksum: sha1:562c0f21e308ad10c27f85f75704c15592c6929d @@ -2785,8 +2897,8 @@ trackedFiles: pristine_git_object: 2d96280cb4f0e2da0ac93bb8c9ca2ea1e515b92f docs/sdks/billing/README.md: id: dc915331dd9d - last_write_checksum: sha1:cc77d117d36e0fccaf5a3a2fd26dae271707638f - pristine_git_object: e68a5a424f93179a8b754ad53a6dabc146048af7 + last_write_checksum: sha1:1ebecb2f17f53704d40cc64d2cc24021f192f1c0 + pristine_git_object: 3f7a8648ac93ed289da197b41be2772b3281cfd1 docs/sdks/customers/README.md: id: 9332759cffc2 last_write_checksum: sha1:6afa5d58ebf54f5c89b04add33684673976d8a82 @@ -2817,8 +2929,8 @@ trackedFiles: pristine_git_object: 3e38f1a929f7d6b1d6de74604aa87e3d8f010544 pylintrc: id: 7ce8b9f946e6 - last_write_checksum: sha1:245d4be24271141847add79be121c9b05f7cd993 - pristine_git_object: 32f489a86f8bdc09713a8cf9647393a3005f8b05 + last_write_checksum: sha1:df60ab94013c483f71ff98c51f349a016c15a117 + pristine_git_object: 5650f49e06066f8a1338afdbc0e155f5277152df pyproject.toml: id: 5d07e7d72637 last_write_checksum: sha1:fd0badc54d2c51c633d02cacda0e7a9fd5abaa00 @@ -2845,8 +2957,8 @@ trackedFiles: pristine_git_object: 3e604651c1eae73d815b276806e73b2f1334bb79 src/autumn_sdk/_version.py: id: a98babfdf4fc - last_write_checksum: sha1:aaca892b083d842552de2cf356665518d2b0d2c5 - pristine_git_object: 0901a0364951c52154c73af4e9a14e2612d054a9 + last_write_checksum: sha1:4ff651eb790585bc44591e3e253c60a52f5e49ea + pristine_git_object: af61685f99a494e0162b7b20f822b514788ac030 src/autumn_sdk/balances.py: id: 0a15be654dad last_write_checksum: sha1:46067ffca43331f7efed02bf80a3102557f69400 @@ -2857,8 +2969,8 @@ trackedFiles: pristine_git_object: b8da96bd89ddafaedb32f4ecac64c27027fcca79 src/autumn_sdk/billing.py: id: e6cffdbf2221 - last_write_checksum: sha1:19fb0b466cba919e5e17a8ee25224d320b8e136c - pristine_git_object: 20bf99967845b3d3b036216e1c3b23da887a0253 + last_write_checksum: sha1:8f146a83f1c427e423ae2e0a43d2b20a6d63a803 + pristine_git_object: 0c532d365672a836909daee34a99fe25fe71c0db src/autumn_sdk/customers.py: id: 5c5a0a07a433 last_write_checksum: sha1:c845e37685e7d5b126c2c0d085d675b3befd527c @@ -2869,8 +2981,8 @@ trackedFiles: pristine_git_object: f6b57b6c0194f874f0ba24d8f2c0175669189983 src/autumn_sdk/errors/__init__.py: id: 242853123cf2 - last_write_checksum: sha1:1c4f4e0181a6598b531c2621340548b003df6e2a - pristine_git_object: 3c83f2947cf86f28759fe6a53700d40dd5bc7be7 + last_write_checksum: sha1:3185fbf12ed61a9845f94127cb110bce8f7f8f66 + pristine_git_object: 712bfe798f42e653816668fe6a5f13e2957f12a2 src/autumn_sdk/errors/autumndefaulterror.py: id: 4c2d6cac83ee last_write_checksum: sha1:f45d500766d652f899f6cacbfaab5669e190f19e @@ -2901,180 +3013,180 @@ trackedFiles: pristine_git_object: 89560b566073785535643e694c112bedbd3db13d src/autumn_sdk/models/__init__.py: id: bcf3802243ff - last_write_checksum: sha1:9b8562f6c752838c9bcec68ce099993a049671a3 - pristine_git_object: 0127c6be31631977ece679d8e896ed739df0dcfa + last_write_checksum: sha1:ff258b03469e08db7b70dd3c780b34cad56667e4 + pristine_git_object: b397b6b41232d533068c68ad67c5e4f3b30ccded src/autumn_sdk/models/aggregateeventsop.py: id: 01321099f2a5 - last_write_checksum: sha1:d5605f1074da718e5da0195eb951ffc1c9d0fc20 - pristine_git_object: b62e4c6171ad275106314421884848714645ae13 + last_write_checksum: sha1:eef6ab478132141f11c820ee80cbacaa4bc74870 + pristine_git_object: c6a100bbd09941de44de909199a510fc0f8274d3 src/autumn_sdk/models/attachop.py: id: ebb59e06476c - last_write_checksum: sha1:400be2baf57968dec4da86b47890d48bb1a763c7 - pristine_git_object: 434a571efced4fa2a36c4d1cc134d3d573da5e01 + last_write_checksum: sha1:bab7654856f352189edd8a71be3534b3b1270b52 + pristine_git_object: 12b3c3c9c6dce58f1adea685c1373c298e63286f src/autumn_sdk/models/balance.py: id: a6354d7c4b97 - last_write_checksum: sha1:dde97ce288519d7caba988d09f419bb0a79719f9 - pristine_git_object: f08b03da984fb8dd469b339054ceb805e122a3b1 + last_write_checksum: sha1:de11fef2010f8b21ece416a3f69c0ec9cfdaab4e + pristine_git_object: 9e4d3d82cb0fa84ec6354e19107bae5297796fd7 src/autumn_sdk/models/billingupdateop.py: id: a2f17c75cfd3 - last_write_checksum: sha1:fa6e28eee9bd7650ad19df1041cb4469e6a55362 - pristine_git_object: 944115475eaff185903df3a54961a9cbf51b9a49 + last_write_checksum: sha1:1bdebd3dff7ce5d6abe5c067ffc5b3f57eb88afc + pristine_git_object: 52804986febccc71330da173cc9156a672e742ea src/autumn_sdk/models/checkop.py: id: 31c2f84723c6 - last_write_checksum: sha1:eab1a08cedd5cd932e5cf2e7c29ed1569500495a - pristine_git_object: 0d0e2e97721b336211a33b28b6a166abf980ebcf + last_write_checksum: sha1:6afa24e310c28a61a76df8d6facf30c1deb04168 + pristine_git_object: 81008db9ba697d832b045ee8f0181823451f238d src/autumn_sdk/models/createbalanceop.py: id: 27daf4da75bf - last_write_checksum: sha1:336706059035f2c2de5f3fd259a3079ef2e5efe3 - pristine_git_object: 5f8b89b4b876a9c96f3e4ee8cc5d642d709cf496 + last_write_checksum: sha1:6d5d0bec52c288ecce41f5aabda3954f64645d31 + pristine_git_object: 674607646f18d0d09b25609c80ed43fe3f3a9bb0 src/autumn_sdk/models/createentityop.py: id: bf9521c0cfec - last_write_checksum: sha1:e1c2c16053fa252c7c6eef13e6e00b82325259e7 - pristine_git_object: 006b843c49c037a15a1b8d5496d36280cd315ab8 + last_write_checksum: sha1:e71077c85ce6ebc5ebac3a7be7ab0de4fdd15b00 + pristine_git_object: 29bc6efc354562e569195550ccc1eb7c7ac9396e src/autumn_sdk/models/createfeatureop.py: id: 68487033fbe5 - last_write_checksum: sha1:7700b9041190ce954caa13d6981c0c1460e5ee20 - pristine_git_object: 35a43e4dd6ea06d0ffbbde5ffaead959ce207632 + last_write_checksum: sha1:a6af9e8d51d99eeff68bed6c8d9f0915c6fdd54e + pristine_git_object: b6be52d60ce2ba4330e8de7a1dc0976677471e4d src/autumn_sdk/models/createplanop.py: id: 077e6c7db2ad - last_write_checksum: sha1:4a1bc73c0314c2614a0fae7e486469d987b8a0a8 - pristine_git_object: 68ffef8988f54d8c18b5d0a92db6fae4f16b2479 + last_write_checksum: sha1:ef6cedb4fe855e07f446707e725d0d8dcbd447ef + pristine_git_object: 3188aa943169ea519cd6aa365e3a254fcc403332 src/autumn_sdk/models/createreferralcodeop.py: id: 2f5f7b136c39 - last_write_checksum: sha1:aee36f911153fc0dab9fd096dbb82d1083a61d28 - pristine_git_object: cd3ad48900dab5fd4b07db41d62388e68a1818b2 + last_write_checksum: sha1:0a200e513da7332ed334d61d4ab60f0fecebbad2 + pristine_git_object: 60bb089e74dc86d08cc861e85afa93a1a9c6955f src/autumn_sdk/models/customer.py: id: 8ed0174f7272 - last_write_checksum: sha1:6b4a7655b21dd6a4f35356283411005341e0d69e - pristine_git_object: e041b7cf16303815fb6d2f1c75a9700e05887edf + last_write_checksum: sha1:3ddbea2db4a76ac98ac5884f6cb0602cdcbadd43 + pristine_git_object: 52b3cda1122ae1cbdfa275d160de11cc296638e4 src/autumn_sdk/models/customerdata.py: id: 9d88118f2123 - last_write_checksum: sha1:a42f21606d9e2499a63588f909714e723eafd384 - pristine_git_object: 192060327ebe9828b5a2a0556b18585c01911c93 + last_write_checksum: sha1:5205991e85a0dc3e85fc2fdeb55fe300aba31027 + pristine_git_object: 78cb71f16bdcf60d26f0beb1aeb37a309caa035d src/autumn_sdk/models/deletebalanceop.py: id: 97d06f64852a - last_write_checksum: sha1:d8e94ba342b57ee31d54cb7c2d45bfb2b840e095 - pristine_git_object: e93512ba6bd77160a145debfa5131fc372538c75 + last_write_checksum: sha1:47587f11ca64dd8f9613e1be744740b81a6783a4 + pristine_git_object: 8d28358187140887712b7c908df799b21f01f7c2 src/autumn_sdk/models/deletecustomerop.py: id: dc7a1e2cc90b - last_write_checksum: sha1:8b345d4715c2fa291674b86287439e824cd479ce - pristine_git_object: f731ec176a58301941259ea8c4b36353703802bb + last_write_checksum: sha1:830f779b77d3d232450c6a1d16691384caf534a8 + pristine_git_object: 360a0ca57ef52d3fbffe68234c71fb4c7378ed78 src/autumn_sdk/models/deleteentityop.py: id: f875e07e0401 - last_write_checksum: sha1:a596e590cb293b64f97549972cb674f0ea6661c0 - pristine_git_object: 994654d79145e1b31ccf1bb2400732e13060c11c + last_write_checksum: sha1:84736474b4e695a5c3f22b1a13401a21ef1e8953 + pristine_git_object: 3aec2ed90dff25e3a63c8bfc949fb76c34cb144a src/autumn_sdk/models/deletefeatureop.py: id: 2cde77bc8684 - last_write_checksum: sha1:eb0e3de24676ed9ca638050e753adcf77d9e9273 - pristine_git_object: d16ff515bd2fd4ae2c67c7b3099b9bbc981e966d + last_write_checksum: sha1:44c38cc8b9873f1bdb161b80d906c601353741c2 + pristine_git_object: 1cb236ef47598596874e93325f6d21b81f90117c src/autumn_sdk/models/deleteplanop.py: id: 4dd8168b93d3 - last_write_checksum: sha1:b66060053ba95103b6f9c21583c837aff5bf4f5b - pristine_git_object: 8399927609dfaba9ca603a77e3f85ada3861d2f2 + last_write_checksum: sha1:ce4b60376e96d39301d8d2cd56d6588dbdce973d + pristine_git_object: 8d60176d44a69f0b5d4f152bd7acf52f0e43cfba src/autumn_sdk/models/finalizelockop.py: id: 8ae2484b0916 - last_write_checksum: sha1:e8db3e126ea7a98e56c992067ad838474aaaea90 - pristine_git_object: 5ca71e3f0ae7d38ab7d8c37d6a1dc3e4a6b04ef5 + last_write_checksum: sha1:732c896663074ddde0026cd9940c8c24635cfa00 + pristine_git_object: 7fe4a83808fec9903c805bb9a423e5d0322f726e src/autumn_sdk/models/getentityop.py: id: 6a624594b41f - last_write_checksum: sha1:fe0810227dc692312a3eb0a5b8ee5510f357c6c1 - pristine_git_object: 956fe9aac5639a9e06aa43453fb523da4e026b36 + last_write_checksum: sha1:1afed1a14318807b72c294316fcfd036cc24a326 + pristine_git_object: 828874eab4d48617b285d060e753714d5a012bcd src/autumn_sdk/models/getfeatureop.py: id: 72b158789497 - last_write_checksum: sha1:89a9f44a1af9b36cf229f80000cae16054da17a5 - pristine_git_object: 63aec0714ea5d7f98ffdb2d7125d0b9db6fe8537 + last_write_checksum: sha1:280bb7e8829a45480171f13f82925f2eae111787 + pristine_git_object: 6a02216300e81c94571a208bc78ca3381b638c2a src/autumn_sdk/models/getorcreatecustomerop.py: id: acfac0d7be14 - last_write_checksum: sha1:6b826257afb8592b3d5ac41d8deb9837e18e13ac - pristine_git_object: a26722bad46da59260e383d531d57d854fb03ecf + last_write_checksum: sha1:67f6e3e9e748c3610094819df6ffb895623a4c39 + pristine_git_object: c9070631520968855a271dafe454ce083df842b1 src/autumn_sdk/models/getplanop.py: id: 590fb77ac88d - last_write_checksum: sha1:eafc7c00dd453d1ddf25c531a1ef44c38267219b - pristine_git_object: 03d634d43cb00c85bd0fadeaa0491585193a619e + last_write_checksum: sha1:5baf6dcfbdd99fe10f0ceda6e1da09744f306ef6 + pristine_git_object: 1c7980ff786736806ff290f2f5323b6289ff1fe8 src/autumn_sdk/models/internal/__init__.py: id: 2906fe7f2cde - last_write_checksum: sha1:1905b58b74ecc52346d8f5c24ded2b6d6e1dad4a - pristine_git_object: ceabb1b83cb7cc1e21e65639c69c30749d36f6e2 + last_write_checksum: sha1:5beaf7e5a713d3eead465c6edcfdeb7f8076175c + pristine_git_object: e7070a1222c2ed3fa3f6f54e6f122cae7ff9a449 src/autumn_sdk/models/internal/globals.py: id: 4e33eb99f463 - last_write_checksum: sha1:a201fca661b6d4cc20fb9e3d2f6c1221b78a43d6 - pristine_git_object: 72107ef2601ee3f268b011e90c488b8a69512588 + last_write_checksum: sha1:789b88114444bbdba50c5f94259c79a8d8df2012 + pristine_git_object: 9b32efedd583899e465fab5f305b08fb51a14eff src/autumn_sdk/models/listcustomersop.py: id: d7074740b8b0 - last_write_checksum: sha1:e3e50114c2141b4265190928e8b2788d1c775ca3 - pristine_git_object: 94dfc819f354d92464e52c1ee2bf856467b270b3 + last_write_checksum: sha1:1fb9535206d3ef16ed66fb77f4991646dbd3ba0a + pristine_git_object: 701f0a5aa121ba18c7c07fed0ea1bdbcce6f6d10 src/autumn_sdk/models/listeventsop.py: id: 751b0200d91d - last_write_checksum: sha1:58643d5dedb4f9f82aa8ddd15ac9f4bb284189cd - pristine_git_object: 98b7f60ad8e09f596765297fb8c7c698781933b6 + last_write_checksum: sha1:b858631e46a26812ce801465327c2c1c13ba5cf3 + pristine_git_object: 52845e969536256171c956511d3d149bf11e3261 src/autumn_sdk/models/listfeaturesop.py: id: 95f88614bd8e - last_write_checksum: sha1:983c9bab14d984cdc250fd5822ca98dc373c3cae - pristine_git_object: 710a3e36719b112a82fa98903073bb090f72c2ec + last_write_checksum: sha1:25371d9c007ba3a95672f923f48848e36191eeef + pristine_git_object: b6731d7f7a630c7fc7fabb4f72d626a02fb9166a src/autumn_sdk/models/listplansop.py: id: fdf892c403f4 - last_write_checksum: sha1:d46b12a22952de5878253363f0d83b79c972432b - pristine_git_object: bd090552f6a528ed73eae357c82556edda7571ca + last_write_checksum: sha1:1943ae6de4ef7e01dd7c431eee1f370c0df9540d + pristine_git_object: 55bab58d8d42ebec2f74feb34150af66ef855fa0 src/autumn_sdk/models/multiattachop.py: id: dfdf7952c870 - last_write_checksum: sha1:80f78c9baae1f0bbb0b3d8195a55a9b68a0e9b70 - pristine_git_object: bb5ed660bb324addd80ca4532837ec7327a2188e + last_write_checksum: sha1:a0cdc68ee60d1598d35bcfef46b0eb7d93fd5cad + pristine_git_object: 2b48c43afdbc6289a27960efa9e8ba9b4b4ce6b6 src/autumn_sdk/models/opencustomerportalop.py: id: 004cc9a6466f - last_write_checksum: sha1:b190ddc8e45b3198fa12ae5f49deb9d8cac20a5e - pristine_git_object: 8383509aa89e0c11988baef8e424f5ae682d5c8e + last_write_checksum: sha1:16d5efefb01ca9588607ac1f4d847a9685d96308 + pristine_git_object: bbf47f20ccf883e55c503f03a985f11e62e6b3e8 src/autumn_sdk/models/plan.py: id: f85c4e07540d - last_write_checksum: sha1:5225479c27d1013d35008ade2fe906918724eeef - pristine_git_object: 20844c9b66feb17e013bb74dfc01d2bd845083d3 + last_write_checksum: sha1:9c36e49961c10f98bc69bcdc1788607f9f25813b + pristine_git_object: 56a42a2d22eb3a21547ee87870f73f7c247aefa3 src/autumn_sdk/models/previewattachop.py: id: 2b361be4bfa8 - last_write_checksum: sha1:43579c12cb7281ab40052160e18303667bf39a4b - pristine_git_object: 60df178cfb8963b82340e7d14029b9532519a7d8 + last_write_checksum: sha1:5bb1e64fd73f058a43b900c665809c0dc952cb27 + pristine_git_object: dacc7ba980a8f9701af6f1534227cfea36765d44 src/autumn_sdk/models/previewmultiattachop.py: id: 963ffcd646a4 - last_write_checksum: sha1:4410aca7163a9a25a7eae4ce815204e00bc63036 - pristine_git_object: 187099042034d8ea1296f7b3e16524c0acf201c7 + last_write_checksum: sha1:a4f24fcc5db4c927f48a32688652117a890ea17f + pristine_git_object: 06df124f54e5a536317aeda045079cbb83a79534 src/autumn_sdk/models/previewupdateop.py: id: 081d5f08508d - last_write_checksum: sha1:6b328c94ef12dfc233e975fb46a94353c0c992ef - pristine_git_object: 2c257a59efad61dbfd075e917b50089e7412986c + last_write_checksum: sha1:c526e015b5085720840a5e38e2c8e41968ed9f16 + pristine_git_object: 0602a85b6efe3b2cba082acb224da1daf45ba491 src/autumn_sdk/models/redeemreferralcodeop.py: id: 0abd7bfae718 - last_write_checksum: sha1:df1248aa8876e069c8094cba0541acc4911db620 - pristine_git_object: 2e67e9b952a5107efcb3d79f2d9b6b63c06b4030 + last_write_checksum: sha1:4cb2bfcd36fbd8fa3ab02ac090083e0eabcc0008 + pristine_git_object: 6f1c6e085581e47da9aac794a0e8a0e5d6cfd595 src/autumn_sdk/models/security.py: id: 27d01b755fbe last_write_checksum: sha1:e5ac2e52ed9c2db46d4989c4744c230dd12bdf01 pristine_git_object: aa686dd6f85ae1e27450392fcfe02527adfe8e61 src/autumn_sdk/models/setuppaymentop.py: id: 603339ee67e3 - last_write_checksum: sha1:4944e08928a54c16fdafc93ebadd0b5fce2da229 - pristine_git_object: 195e95672325f6748f852a838e4f6953c8c2bccf + last_write_checksum: sha1:d45e699c2ff5a888cac83c2cd1d4a8d56bf8d95f + pristine_git_object: a3f5643d553197932dfe2a3b9ce8f8ad17c69170 src/autumn_sdk/models/trackop.py: id: 2a744315e781 - last_write_checksum: sha1:e9f1d9c4bbfc47eb5c942f8cfca4a760818bf79d - pristine_git_object: e3581f4139bb985c5c5c058754288bc340d022d1 + last_write_checksum: sha1:adc81955c49e19b435f3d774bcd08ef705a4ba94 + pristine_git_object: a0e92d5bcced974143d3dd24664136a65cf63cf1 src/autumn_sdk/models/updatebalanceop.py: id: cd80d90d4cae - last_write_checksum: sha1:7b6b881cc82b937e93cfd58f17d7f3d83bdb39f1 - pristine_git_object: d69bad2bc308f31e4983cf5e2cd0639cedd9c9aa + last_write_checksum: sha1:ad346cbd8f6ee5e62996b3387ab652fec7e2dc8b + pristine_git_object: 39682e946abe0062ac2b57ed659a48bdb412e7ae src/autumn_sdk/models/updatecustomerop.py: id: 28b9d5b59bae - last_write_checksum: sha1:bcf63fac8c44c1660dae509483ebfe90f9f2ee54 - pristine_git_object: 677b65cdff9d49eaad1172d21b492b91df24293d + last_write_checksum: sha1:f2f546a4d870c3ecbff3eba59ff90f49fe382390 + pristine_git_object: 0b4d17dba201395fccfadd07c8456d19da6914be src/autumn_sdk/models/updateentityop.py: id: a49305af1e2e - last_write_checksum: sha1:a8b07e324b551a3e4dc50efb0b5fbb343d3db6cb - pristine_git_object: 3f7d90a4b52f6957fbdd0f5ed3d0b00a88978ea2 + last_write_checksum: sha1:a88c0b9c38898ae078f806bc0935da16816d1ab2 + pristine_git_object: 8ac0c68348f2c86e60f2a6971399fd1bd9a822ba src/autumn_sdk/models/updatefeatureop.py: id: 2fdfed4aa2f2 - last_write_checksum: sha1:67e6bcbdf14980e19787d10e0ab42485acff0862 - pristine_git_object: 9507c8601dca2cefbc0b8b7d423a38a8272fe580 + last_write_checksum: sha1:38437d262ccbb2a4ad23ef30537bbf2701e7a21f + pristine_git_object: d21c033e2dc2425ce2b98c3b0f77b7017c37ab02 src/autumn_sdk/models/updateplanop.py: id: 753ddf45ca40 - last_write_checksum: sha1:921296bbddba4def95223eb8eae068da86820ce1 - pristine_git_object: bec31e36dab1b7ec384d1a11302aec8dbdddcba6 + last_write_checksum: sha1:190ee64258ef11362f040b574319d3132c2f9f41 + pristine_git_object: 0ba234f795d704061dad65554698f702af96ff7d src/autumn_sdk/plans.py: id: cf1ebabb687c last_write_checksum: sha1:44a5f21bcc8df9df4590ec75c3296e7c0b726323 @@ -3089,8 +3201,8 @@ trackedFiles: pristine_git_object: 4fde94822b61d8a600b721fcbda99116c0e7a6ad src/autumn_sdk/sdk.py: id: 9e733b372628 - last_write_checksum: sha1:0ef7a3d1e8091af849e512c3bddbfface4e8f827 - pristine_git_object: 8e3f647ff341dba96c3dbdd9bdaa5b177bca794b + last_write_checksum: sha1:a22754bfcc074a201e15b76ba4982128d16f5251 + pristine_git_object: 285140a4af75927b60618366985919de071d720e src/autumn_sdk/sdkconfiguration.py: id: e65df2e44fc0 last_write_checksum: sha1:233b710dff940202f00e389e0c8fa6a33f6ae7b4 @@ -3105,8 +3217,8 @@ trackedFiles: pristine_git_object: a9a640a1a7048736383f96c67c6290c86bf536ee src/autumn_sdk/utils/__init__.py: id: e8add1cf9e39 - last_write_checksum: sha1:1970816f2234ecb8785798240b0edced961de971 - pristine_git_object: 0498cb8dabf249b39609f81fb10cddc30f1b78b5 + last_write_checksum: sha1:a1f6ae620fb6a3ccc30e99b427e49a0c8be463af + pristine_git_object: 15394a08a7e30033d319e44dd5734664ddb587e5 src/autumn_sdk/utils/annotations.py: id: 781e615bef82 last_write_checksum: sha1:a4824ad65f730303e4e1e3ec1febf87b4eb46dbc @@ -3115,18 +3227,14 @@ trackedFiles: id: ae6f3bef0a07 last_write_checksum: sha1:c721e4123000e7dc61ec52b28a739439d9e17341 pristine_git_object: a6c52cd61bbe2d459046c940ce5e8c469f2f0664 - src/autumn_sdk/utils/dynamic_imports.py: - id: 88e374972bee - last_write_checksum: sha1:a1940c63feb8eddfd8026de53384baf5056d5dcc - pristine_git_object: 673edf82a97d0fea7295625d3e092ea369a36b79 src/autumn_sdk/utils/enums.py: id: 6274197449b4 last_write_checksum: sha1:bc8c3c1285ae09ba8a094ee5c3d9c7f41fa1284d pristine_git_object: 3324e1bc2668c54c4d5f5a1a845675319757a828 src/autumn_sdk/utils/eventstreaming.py: id: 987e3dcdf32d - last_write_checksum: sha1:620d78a8b4e3b854e08d136e02e40a01a786bd70 - pristine_git_object: 3bdcd6d3d4fc772cb7f5fca8685dcdc8c85e13e8 + last_write_checksum: sha1:ffa870a25a7e4e2015bfd7a467ccd3aa1de97f0e + pristine_git_object: f2052fc22d9fd6c663ba3dce019fe234ca37108b src/autumn_sdk/utils/forms.py: id: 62fce1e7404c last_write_checksum: sha1:0ca31459b99f761fcc6d0557a0a38daac4ad50f4 @@ -3153,8 +3261,8 @@ trackedFiles: pristine_git_object: 1de32b6d26f46590232f398fdba6ce0072f1659c src/autumn_sdk/utils/retries.py: id: 7b3d494f85a1 - last_write_checksum: sha1:471372f5c5d1dd5583239c9cf3c75f1b636e5d87 - pristine_git_object: af07d4e941007af4213c5ec9047ef8a2fca04e5e + last_write_checksum: sha1:5b97ac4f59357d70c2529975d50364c88bcad607 + pristine_git_object: 88a91b10cd2076b4a2c6cff2ac6bfaa5e3c5ad13 src/autumn_sdk/utils/security.py: id: 205e1b4aa7c9 last_write_checksum: sha1:435dd8b180cefcd733e635b9fa45512da091d9c0 @@ -3661,7 +3769,7 @@ examples: application/json: {"customer_id": "cus_123", "plans": [{"plan_id": "pro_plan"}, {"plan_id": "addon_seats", "feature_quantities": [{"feature_id": "seats", "quantity": 5}]}], "redirect_mode": "if_required"} responses: "200": - application/json: {"customer_id": "", "line_items": [{"display_name": "Percival_Towne81", "description": "as unfortunately wherever crest", "subtotal": 1273.44, "total": 7630.04, "plan_id": "", "feature_id": null, "quantity": 1062.24}], "subtotal": 20, "total": 20, "currency": "usd", "incoming": [{"plan_id": "", "feature_quantities": [], "effective_at": 1983.1}], "outgoing": []} + application/json: {"customer_id": "", "line_items": [{"display_name": "Percival_Towne81", "description": "as unfortunately wherever crest", "subtotal": 1273.44, "total": 7630.04, "plan_id": "", "feature_id": null, "quantity": 1062.24}], "subtotal": 20, "total": 20, "currency": "usd", "incoming": [{"plan_id": "", "feature_quantities": [], "effective_at": 1983.1, "canceled_at": 2257.08, "expires_at": 7910.67}], "outgoing": []} multiAttach: speakeasy-default-multi-attach: parameters: diff --git a/others/python-sdk/pylintrc b/others/python-sdk/pylintrc index 32f489a86..5650f49e0 100644 --- a/others/python-sdk/pylintrc +++ b/others/python-sdk/pylintrc @@ -459,8 +459,7 @@ disable=raw-checker-failed, consider-using-with, wildcard-import, unused-wildcard-import, - too-many-return-statements, - redefined-builtin + too-many-return-statements # Enable the message, report, category or checker with the given id(s). You can # either give multiple identifier separated by comma (,) or put this option diff --git a/others/python-sdk/src/autumn_sdk/_version.py b/others/python-sdk/src/autumn_sdk/_version.py index 0901a0364..af61685f9 100644 --- a/others/python-sdk/src/autumn_sdk/_version.py +++ b/others/python-sdk/src/autumn_sdk/_version.py @@ -5,8 +5,8 @@ import importlib.metadata __title__: str = "autumn-sdk" __version__: str = "0.4.18" __openapi_doc_version__: str = "2.2.0" -__gen_version__: str = "2.866.2" -__user_agent__: str = "speakeasy-sdk/python 0.4.18 2.866.2 2.2.0 autumn-sdk" +__gen_version__: str = "2.824.1" +__user_agent__: str = "speakeasy-sdk/python 0.4.18 2.824.1 2.2.0 autumn-sdk" try: if __package__ is not None: diff --git a/others/python-sdk/src/autumn_sdk/billing.py b/others/python-sdk/src/autumn_sdk/billing.py index 20bf99967..0c532d365 100644 --- a/others/python-sdk/src/autumn_sdk/billing.py +++ b/others/python-sdk/src/autumn_sdk/billing.py @@ -1418,6 +1418,12 @@ class Billing(BaseSDK): subscription_id: Optional[str] = None, cancel_action: Optional[models.BillingUpdateCancelAction] = None, no_billing_changes: Optional[bool] = None, + recalculate_balances: Optional[ + Union[ + models.BillingUpdateRecalculateBalances, + models.BillingUpdateRecalculateBalancesTypedDict, + ] + ] = None, retries: OptionalNullable[utils.RetryConfig] = UNSET, server_url: Optional[str] = None, timeout_ms: Optional[int] = None, @@ -1439,6 +1445,7 @@ class Billing(BaseSDK): :param subscription_id: A unique ID to identify this subscription. Can be used to target specific subscriptions in update operations when a customer has multiple products with the same plan. :param cancel_action: Action to perform for cancellation. 'cancel_immediately' cancels now with prorated refund, 'cancel_end_of_cycle' cancels at period end, 'uncancel' reverses a pending cancellation. :param no_billing_changes: If true, the subscription is updated internally without applying billing changes in Stripe. + :param recalculate_balances: Controls whether balances should be recalculated during the subscription update. :param retries: Override the default retry configuration for this method :param server_url: Override the default server URL for this method :param timeout_ms: Override the default request timeout configuration for this method in milliseconds @@ -1473,6 +1480,9 @@ class Billing(BaseSDK): subscription_id=subscription_id, cancel_action=cancel_action, no_billing_changes=no_billing_changes, + recalculate_balances=utils.get_pydantic_model( + recalculate_balances, Optional[models.BillingUpdateRecalculateBalances] + ), ) req = self._build_request( @@ -1561,6 +1571,12 @@ class Billing(BaseSDK): subscription_id: Optional[str] = None, cancel_action: Optional[models.BillingUpdateCancelAction] = None, no_billing_changes: Optional[bool] = None, + recalculate_balances: Optional[ + Union[ + models.BillingUpdateRecalculateBalances, + models.BillingUpdateRecalculateBalancesTypedDict, + ] + ] = None, retries: OptionalNullable[utils.RetryConfig] = UNSET, server_url: Optional[str] = None, timeout_ms: Optional[int] = None, @@ -1582,6 +1598,7 @@ class Billing(BaseSDK): :param subscription_id: A unique ID to identify this subscription. Can be used to target specific subscriptions in update operations when a customer has multiple products with the same plan. :param cancel_action: Action to perform for cancellation. 'cancel_immediately' cancels now with prorated refund, 'cancel_end_of_cycle' cancels at period end, 'uncancel' reverses a pending cancellation. :param no_billing_changes: If true, the subscription is updated internally without applying billing changes in Stripe. + :param recalculate_balances: Controls whether balances should be recalculated during the subscription update. :param retries: Override the default retry configuration for this method :param server_url: Override the default server URL for this method :param timeout_ms: Override the default request timeout configuration for this method in milliseconds @@ -1616,6 +1633,9 @@ class Billing(BaseSDK): subscription_id=subscription_id, cancel_action=cancel_action, no_billing_changes=no_billing_changes, + recalculate_balances=utils.get_pydantic_model( + recalculate_balances, Optional[models.BillingUpdateRecalculateBalances] + ), ) req = self._build_request_async( @@ -1704,6 +1724,12 @@ class Billing(BaseSDK): subscription_id: Optional[str] = None, cancel_action: Optional[models.PreviewUpdateCancelAction] = None, no_billing_changes: Optional[bool] = None, + recalculate_balances: Optional[ + Union[ + models.PreviewUpdateRecalculateBalances, + models.PreviewUpdateRecalculateBalancesTypedDict, + ] + ] = None, retries: OptionalNullable[utils.RetryConfig] = UNSET, server_url: Optional[str] = None, timeout_ms: Optional[int] = None, @@ -1725,6 +1751,7 @@ class Billing(BaseSDK): :param subscription_id: A unique ID to identify this subscription. Can be used to target specific subscriptions in update operations when a customer has multiple products with the same plan. :param cancel_action: Action to perform for cancellation. 'cancel_immediately' cancels now with prorated refund, 'cancel_end_of_cycle' cancels at period end, 'uncancel' reverses a pending cancellation. :param no_billing_changes: If true, the subscription is updated internally without applying billing changes in Stripe. + :param recalculate_balances: Controls whether balances should be recalculated during the subscription update. :param retries: Override the default retry configuration for this method :param server_url: Override the default server URL for this method :param timeout_ms: Override the default request timeout configuration for this method in milliseconds @@ -1760,6 +1787,9 @@ class Billing(BaseSDK): subscription_id=subscription_id, cancel_action=cancel_action, no_billing_changes=no_billing_changes, + recalculate_balances=utils.get_pydantic_model( + recalculate_balances, Optional[models.PreviewUpdateRecalculateBalances] + ), ) req = self._build_request( @@ -1848,6 +1878,12 @@ class Billing(BaseSDK): subscription_id: Optional[str] = None, cancel_action: Optional[models.PreviewUpdateCancelAction] = None, no_billing_changes: Optional[bool] = None, + recalculate_balances: Optional[ + Union[ + models.PreviewUpdateRecalculateBalances, + models.PreviewUpdateRecalculateBalancesTypedDict, + ] + ] = None, retries: OptionalNullable[utils.RetryConfig] = UNSET, server_url: Optional[str] = None, timeout_ms: Optional[int] = None, @@ -1869,6 +1905,7 @@ class Billing(BaseSDK): :param subscription_id: A unique ID to identify this subscription. Can be used to target specific subscriptions in update operations when a customer has multiple products with the same plan. :param cancel_action: Action to perform for cancellation. 'cancel_immediately' cancels now with prorated refund, 'cancel_end_of_cycle' cancels at period end, 'uncancel' reverses a pending cancellation. :param no_billing_changes: If true, the subscription is updated internally without applying billing changes in Stripe. + :param recalculate_balances: Controls whether balances should be recalculated during the subscription update. :param retries: Override the default retry configuration for this method :param server_url: Override the default server URL for this method :param timeout_ms: Override the default request timeout configuration for this method in milliseconds @@ -1904,6 +1941,9 @@ class Billing(BaseSDK): subscription_id=subscription_id, cancel_action=cancel_action, no_billing_changes=no_billing_changes, + recalculate_balances=utils.get_pydantic_model( + recalculate_balances, Optional[models.PreviewUpdateRecalculateBalances] + ), ) req = self._build_request_async( diff --git a/others/python-sdk/src/autumn_sdk/errors/__init__.py b/others/python-sdk/src/autumn_sdk/errors/__init__.py index 3c83f2947..712bfe798 100644 --- a/others/python-sdk/src/autumn_sdk/errors/__init__.py +++ b/others/python-sdk/src/autumn_sdk/errors/__init__.py @@ -1,9 +1,10 @@ """Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" from .autumnerror import AutumnError -from typing import Any, TYPE_CHECKING - -from autumn_sdk.utils.dynamic_imports import lazy_getattr, lazy_dir +from typing import TYPE_CHECKING +from importlib import import_module +import builtins +import sys if TYPE_CHECKING: from .autumndefaulterror import AutumnDefaultError @@ -24,11 +25,39 @@ _dynamic_imports: dict[str, str] = { } -def __getattr__(attr_name: str) -> Any: - return lazy_getattr( - attr_name, package=__package__, dynamic_imports=_dynamic_imports - ) +def dynamic_import(modname, retries=3): + for attempt in range(retries): + try: + return import_module(modname, __package__) + except KeyError: + # Clear any half-initialized module and retry + sys.modules.pop(modname, None) + if attempt == retries - 1: + break + raise KeyError(f"Failed to import module '{modname}' after {retries} attempts") + + +def __getattr__(attr_name: str) -> object: + module_name = _dynamic_imports.get(attr_name) + if module_name is None: + raise AttributeError( + f"No {attr_name} found in _dynamic_imports for module name -> {__name__} " + ) + + try: + module = dynamic_import(module_name) + result = getattr(module, attr_name) + return result + except ImportError as e: + raise ImportError( + f"Failed to import {attr_name} from {module_name}: {e}" + ) from e + except AttributeError as e: + raise AttributeError( + f"Failed to get {attr_name} from {module_name}: {e}" + ) from e def __dir__(): - return lazy_dir(dynamic_imports=_dynamic_imports) + lazy_attrs = builtins.list(_dynamic_imports.keys()) + return builtins.sorted(lazy_attrs) diff --git a/others/python-sdk/src/autumn_sdk/models/__init__.py b/others/python-sdk/src/autumn_sdk/models/__init__.py index 0127c6be3..b397b6b41 100644 --- a/others/python-sdk/src/autumn_sdk/models/__init__.py +++ b/others/python-sdk/src/autumn_sdk/models/__init__.py @@ -1,8 +1,9 @@ """Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" -from typing import Any, TYPE_CHECKING - -from autumn_sdk.utils.dynamic_imports import lazy_getattr, lazy_dir +from typing import TYPE_CHECKING +from importlib import import_module +import builtins +import sys if TYPE_CHECKING: from .aggregateeventsop import ( @@ -135,6 +136,8 @@ if TYPE_CHECKING: BillingUpdateProration, BillingUpdateProrationBehavior, BillingUpdateProrationTypedDict, + BillingUpdateRecalculateBalances, + BillingUpdateRecalculateBalancesTypedDict, BillingUpdateRedirectMode, BillingUpdateRequiredAction, BillingUpdateRequiredActionTypedDict, @@ -244,7 +247,13 @@ if TYPE_CHECKING: CreateEntityStatus, CreateEntitySubscription, CreateEntitySubscriptionTypedDict, + CreateEntityThresholdTypeRequestBody, + CreateEntityThresholdTypeResponse, CreateEntityType, + CreateEntityUsageAlertRequestBody, + CreateEntityUsageAlertRequestBodyTypedDict, + CreateEntityUsageAlertResponse, + CreateEntityUsageAlertResponseTypedDict, ) from .createfeatureop import ( CreateFeatureCreditSchemaRequest, @@ -363,7 +372,10 @@ if TYPE_CHECKING: CustomerSpendLimit, CustomerSpendLimitTypedDict, CustomerStatus, + CustomerThresholdType, CustomerTypedDict, + CustomerUsageAlert, + CustomerUsageAlertTypedDict, Discount, DiscountTypedDict, Entity, @@ -398,7 +410,10 @@ if TYPE_CHECKING: CustomerDataPurchaseLimitTypedDict, CustomerDataSpendLimit, CustomerDataSpendLimitTypedDict, + CustomerDataThresholdType, CustomerDataTypedDict, + CustomerDataUsageAlert, + CustomerDataUsageAlertTypedDict, ) from .deletebalanceop import ( DeleteBalanceGlobals, @@ -477,7 +492,10 @@ if TYPE_CHECKING: GetEntityStatus, GetEntitySubscription, GetEntitySubscriptionTypedDict, + GetEntityThresholdType, GetEntityType, + GetEntityUsageAlert, + GetEntityUsageAlertTypedDict, ) from .getfeatureop import ( GetFeatureCreditSchema, @@ -506,6 +524,9 @@ if TYPE_CHECKING: GetOrCreateCustomerPurchaseLimitTypedDict, GetOrCreateCustomerSpendLimit, GetOrCreateCustomerSpendLimitTypedDict, + GetOrCreateCustomerThresholdType, + GetOrCreateCustomerUsageAlert, + GetOrCreateCustomerUsageAlertTypedDict, ) from .getplanop import ( GetPlanAttachAction, @@ -584,7 +605,10 @@ if TYPE_CHECKING: ListCustomersStatus, ListCustomersSubscription, ListCustomersSubscriptionTypedDict, + ListCustomersThresholdType, ListCustomersType, + ListCustomersUsageAlert, + ListCustomersUsageAlertTypedDict, SubscriptionStatus, ) from .listeventsop import ( @@ -714,11 +738,14 @@ if TYPE_CHECKING: MultiAttachRolloverTypedDict, MultiAttachSpendLimit, MultiAttachSpendLimitTypedDict, + MultiAttachThresholdType, MultiAttachTier, MultiAttachTierBehavior, MultiAttachTierTypedDict, MultiAttachTo, MultiAttachToTypedDict, + MultiAttachUsageAlert, + MultiAttachUsageAlertTypedDict, ) from .opencustomerportalop import ( OpenCustomerPortalGlobals, @@ -913,11 +940,14 @@ if TYPE_CHECKING: PreviewMultiAttachRolloverTypedDict, PreviewMultiAttachSpendLimit, PreviewMultiAttachSpendLimitTypedDict, + PreviewMultiAttachThresholdType, PreviewMultiAttachTier, PreviewMultiAttachTierBehavior, PreviewMultiAttachTierTypedDict, PreviewMultiAttachTo, PreviewMultiAttachToTypedDict, + PreviewMultiAttachUsageAlert, + PreviewMultiAttachUsageAlertTypedDict, PreviewMultiAttachUsageLineItem, PreviewMultiAttachUsageLineItemPeriod, PreviewMultiAttachUsageLineItemPeriodTypedDict, @@ -976,6 +1006,8 @@ if TYPE_CHECKING: PreviewUpdateProration, PreviewUpdateProrationBehavior, PreviewUpdateProrationTypedDict, + PreviewUpdateRecalculateBalances, + PreviewUpdateRecalculateBalancesTypedDict, PreviewUpdateRedirectMode, PreviewUpdateReset, PreviewUpdateResetInterval, @@ -1109,7 +1141,13 @@ if TYPE_CHECKING: UpdateCustomerStatus, UpdateCustomerSubscription, UpdateCustomerSubscriptionTypedDict, + UpdateCustomerThresholdTypeRequestBody, + UpdateCustomerThresholdTypeResponse, UpdateCustomerType, + UpdateCustomerUsageAlertRequestBody, + UpdateCustomerUsageAlertRequestBodyTypedDict, + UpdateCustomerUsageAlertResponse, + UpdateCustomerUsageAlertResponseTypedDict, ) from .updateentityop import ( UpdateEntityBillingControlsRequest, @@ -1142,7 +1180,13 @@ if TYPE_CHECKING: UpdateEntityStatus, UpdateEntitySubscription, UpdateEntitySubscriptionTypedDict, + UpdateEntityThresholdTypeRequestBody, + UpdateEntityThresholdTypeResponse, UpdateEntityType, + UpdateEntityUsageAlertRequestBody, + UpdateEntityUsageAlertRequestBodyTypedDict, + UpdateEntityUsageAlertResponse, + UpdateEntityUsageAlertResponseTypedDict, ) from .updatefeatureop import ( UpdateFeatureCreditSchemaRequest, @@ -1232,7 +1276,6 @@ if TYPE_CHECKING: UpdatePlanToTypedDict, UpdatePlanType, ) - from . import internal __all__ = [ "Action", @@ -1350,6 +1393,8 @@ __all__ = [ "BillingUpdateProration", "BillingUpdateProrationBehavior", "BillingUpdateProrationTypedDict", + "BillingUpdateRecalculateBalances", + "BillingUpdateRecalculateBalancesTypedDict", "BillingUpdateRedirectMode", "BillingUpdateRequiredAction", "BillingUpdateRequiredActionTypedDict", @@ -1434,7 +1479,13 @@ __all__ = [ "CreateEntityStatus", "CreateEntitySubscription", "CreateEntitySubscriptionTypedDict", + "CreateEntityThresholdTypeRequestBody", + "CreateEntityThresholdTypeResponse", "CreateEntityType", + "CreateEntityUsageAlertRequestBody", + "CreateEntityUsageAlertRequestBodyTypedDict", + "CreateEntityUsageAlertResponse", + "CreateEntityUsageAlertResponseTypedDict", "CreateFeatureCreditSchemaRequest", "CreateFeatureCreditSchemaRequestTypedDict", "CreateFeatureCreditSchemaResponse", @@ -1540,7 +1591,10 @@ __all__ = [ "CustomerDataPurchaseLimitTypedDict", "CustomerDataSpendLimit", "CustomerDataSpendLimitTypedDict", + "CustomerDataThresholdType", "CustomerDataTypedDict", + "CustomerDataUsageAlert", + "CustomerDataUsageAlertTypedDict", "CustomerDisplay", "CustomerDisplayTypedDict", "CustomerDurationType", @@ -1556,7 +1610,10 @@ __all__ = [ "CustomerSpendLimit", "CustomerSpendLimitTypedDict", "CustomerStatus", + "CustomerThresholdType", "CustomerTypedDict", + "CustomerUsageAlert", + "CustomerUsageAlertTypedDict", "DeleteBalanceGlobals", "DeleteBalanceGlobalsTypedDict", "DeleteBalanceInterval", @@ -1643,7 +1700,10 @@ __all__ = [ "GetEntityStatus", "GetEntitySubscription", "GetEntitySubscriptionTypedDict", + "GetEntityThresholdType", "GetEntityType", + "GetEntityUsageAlert", + "GetEntityUsageAlertTypedDict", "GetFeatureCreditSchema", "GetFeatureCreditSchemaTypedDict", "GetFeatureDisplay", @@ -1668,6 +1728,9 @@ __all__ = [ "GetOrCreateCustomerPurchaseLimitTypedDict", "GetOrCreateCustomerSpendLimit", "GetOrCreateCustomerSpendLimitTypedDict", + "GetOrCreateCustomerThresholdType", + "GetOrCreateCustomerUsageAlert", + "GetOrCreateCustomerUsageAlertTypedDict", "GetPlanAttachAction", "GetPlanBillingMethod", "GetPlanCreditSchema", @@ -1751,7 +1814,10 @@ __all__ = [ "ListCustomersStatus", "ListCustomersSubscription", "ListCustomersSubscriptionTypedDict", + "ListCustomersThresholdType", "ListCustomersType", + "ListCustomersUsageAlert", + "ListCustomersUsageAlertTypedDict", "ListEventsCustomRange", "ListEventsCustomRangeTypedDict", "ListEventsFeatureID", @@ -1870,11 +1936,14 @@ __all__ = [ "MultiAttachRolloverTypedDict", "MultiAttachSpendLimit", "MultiAttachSpendLimitTypedDict", + "MultiAttachThresholdType", "MultiAttachTier", "MultiAttachTierBehavior", "MultiAttachTierTypedDict", "MultiAttachTo", "MultiAttachToTypedDict", + "MultiAttachUsageAlert", + "MultiAttachUsageAlertTypedDict", "OpenCustomerPortalGlobals", "OpenCustomerPortalGlobalsTypedDict", "OpenCustomerPortalParams", @@ -2054,11 +2123,14 @@ __all__ = [ "PreviewMultiAttachRolloverTypedDict", "PreviewMultiAttachSpendLimit", "PreviewMultiAttachSpendLimitTypedDict", + "PreviewMultiAttachThresholdType", "PreviewMultiAttachTier", "PreviewMultiAttachTierBehavior", "PreviewMultiAttachTierTypedDict", "PreviewMultiAttachTo", "PreviewMultiAttachToTypedDict", + "PreviewMultiAttachUsageAlert", + "PreviewMultiAttachUsageAlertTypedDict", "PreviewMultiAttachUsageLineItem", "PreviewMultiAttachUsageLineItemPeriod", "PreviewMultiAttachUsageLineItemPeriodTypedDict", @@ -2115,6 +2187,8 @@ __all__ = [ "PreviewUpdateProration", "PreviewUpdateProrationBehavior", "PreviewUpdateProrationTypedDict", + "PreviewUpdateRecalculateBalances", + "PreviewUpdateRecalculateBalancesTypedDict", "PreviewUpdateRedirectMode", "PreviewUpdateReset", "PreviewUpdateResetInterval", @@ -2264,7 +2338,13 @@ __all__ = [ "UpdateCustomerStatus", "UpdateCustomerSubscription", "UpdateCustomerSubscriptionTypedDict", + "UpdateCustomerThresholdTypeRequestBody", + "UpdateCustomerThresholdTypeResponse", "UpdateCustomerType", + "UpdateCustomerUsageAlertRequestBody", + "UpdateCustomerUsageAlertRequestBodyTypedDict", + "UpdateCustomerUsageAlertResponse", + "UpdateCustomerUsageAlertResponseTypedDict", "UpdateEntityBillingControlsRequest", "UpdateEntityBillingControlsRequestTypedDict", "UpdateEntityBillingControlsResponse", @@ -2295,7 +2375,13 @@ __all__ = [ "UpdateEntityStatus", "UpdateEntitySubscription", "UpdateEntitySubscriptionTypedDict", + "UpdateEntityThresholdTypeRequestBody", + "UpdateEntityThresholdTypeResponse", "UpdateEntityType", + "UpdateEntityUsageAlertRequestBody", + "UpdateEntityUsageAlertRequestBodyTypedDict", + "UpdateEntityUsageAlertResponse", + "UpdateEntityUsageAlertResponseTypedDict", "UpdateFeatureCreditSchemaRequest", "UpdateFeatureCreditSchemaRequestTypedDict", "UpdateFeatureCreditSchemaResponse", @@ -2509,6 +2595,8 @@ _dynamic_imports: dict[str, str] = { "BillingUpdateProration": ".billingupdateop", "BillingUpdateProrationBehavior": ".billingupdateop", "BillingUpdateProrationTypedDict": ".billingupdateop", + "BillingUpdateRecalculateBalances": ".billingupdateop", + "BillingUpdateRecalculateBalancesTypedDict": ".billingupdateop", "BillingUpdateRedirectMode": ".billingupdateop", "BillingUpdateRequiredAction": ".billingupdateop", "BillingUpdateRequiredActionTypedDict": ".billingupdateop", @@ -2612,7 +2700,13 @@ _dynamic_imports: dict[str, str] = { "CreateEntityStatus": ".createentityop", "CreateEntitySubscription": ".createentityop", "CreateEntitySubscriptionTypedDict": ".createentityop", + "CreateEntityThresholdTypeRequestBody": ".createentityop", + "CreateEntityThresholdTypeResponse": ".createentityop", "CreateEntityType": ".createentityop", + "CreateEntityUsageAlertRequestBody": ".createentityop", + "CreateEntityUsageAlertRequestBodyTypedDict": ".createentityop", + "CreateEntityUsageAlertResponse": ".createentityop", + "CreateEntityUsageAlertResponseTypedDict": ".createentityop", "CreateFeatureCreditSchemaRequest": ".createfeatureop", "CreateFeatureCreditSchemaRequestTypedDict": ".createfeatureop", "CreateFeatureCreditSchemaResponse": ".createfeatureop", @@ -2723,7 +2817,10 @@ _dynamic_imports: dict[str, str] = { "CustomerSpendLimit": ".customer", "CustomerSpendLimitTypedDict": ".customer", "CustomerStatus": ".customer", + "CustomerThresholdType": ".customer", "CustomerTypedDict": ".customer", + "CustomerUsageAlert": ".customer", + "CustomerUsageAlertTypedDict": ".customer", "Discount": ".customer", "DiscountTypedDict": ".customer", "Entity": ".customer", @@ -2756,7 +2853,10 @@ _dynamic_imports: dict[str, str] = { "CustomerDataPurchaseLimitTypedDict": ".customerdata", "CustomerDataSpendLimit": ".customerdata", "CustomerDataSpendLimitTypedDict": ".customerdata", + "CustomerDataThresholdType": ".customerdata", "CustomerDataTypedDict": ".customerdata", + "CustomerDataUsageAlert": ".customerdata", + "CustomerDataUsageAlertTypedDict": ".customerdata", "DeleteBalanceGlobals": ".deletebalanceop", "DeleteBalanceGlobalsTypedDict": ".deletebalanceop", "DeleteBalanceInterval": ".deletebalanceop", @@ -2821,7 +2921,10 @@ _dynamic_imports: dict[str, str] = { "GetEntityStatus": ".getentityop", "GetEntitySubscription": ".getentityop", "GetEntitySubscriptionTypedDict": ".getentityop", + "GetEntityThresholdType": ".getentityop", "GetEntityType": ".getentityop", + "GetEntityUsageAlert": ".getentityop", + "GetEntityUsageAlertTypedDict": ".getentityop", "GetFeatureCreditSchema": ".getfeatureop", "GetFeatureCreditSchemaTypedDict": ".getfeatureop", "GetFeatureDisplay": ".getfeatureop", @@ -2846,6 +2949,9 @@ _dynamic_imports: dict[str, str] = { "GetOrCreateCustomerPurchaseLimitTypedDict": ".getorcreatecustomerop", "GetOrCreateCustomerSpendLimit": ".getorcreatecustomerop", "GetOrCreateCustomerSpendLimitTypedDict": ".getorcreatecustomerop", + "GetOrCreateCustomerThresholdType": ".getorcreatecustomerop", + "GetOrCreateCustomerUsageAlert": ".getorcreatecustomerop", + "GetOrCreateCustomerUsageAlertTypedDict": ".getorcreatecustomerop", "GetPlanAttachAction": ".getplanop", "GetPlanBillingMethod": ".getplanop", "GetPlanCreditSchema": ".getplanop", @@ -2920,7 +3026,10 @@ _dynamic_imports: dict[str, str] = { "ListCustomersStatus": ".listcustomersop", "ListCustomersSubscription": ".listcustomersop", "ListCustomersSubscriptionTypedDict": ".listcustomersop", + "ListCustomersThresholdType": ".listcustomersop", "ListCustomersType": ".listcustomersop", + "ListCustomersUsageAlert": ".listcustomersop", + "ListCustomersUsageAlertTypedDict": ".listcustomersop", "SubscriptionStatus": ".listcustomersop", "EventsListParams": ".listeventsop", "EventsListParamsTypedDict": ".listeventsop", @@ -3042,11 +3151,14 @@ _dynamic_imports: dict[str, str] = { "MultiAttachRolloverTypedDict": ".multiattachop", "MultiAttachSpendLimit": ".multiattachop", "MultiAttachSpendLimitTypedDict": ".multiattachop", + "MultiAttachThresholdType": ".multiattachop", "MultiAttachTier": ".multiattachop", "MultiAttachTierBehavior": ".multiattachop", "MultiAttachTierTypedDict": ".multiattachop", "MultiAttachTo": ".multiattachop", "MultiAttachToTypedDict": ".multiattachop", + "MultiAttachUsageAlert": ".multiattachop", + "MultiAttachUsageAlertTypedDict": ".multiattachop", "OpenCustomerPortalGlobals": ".opencustomerportalop", "OpenCustomerPortalGlobalsTypedDict": ".opencustomerportalop", "OpenCustomerPortalParams": ".opencustomerportalop", @@ -3233,11 +3345,14 @@ _dynamic_imports: dict[str, str] = { "PreviewMultiAttachRolloverTypedDict": ".previewmultiattachop", "PreviewMultiAttachSpendLimit": ".previewmultiattachop", "PreviewMultiAttachSpendLimitTypedDict": ".previewmultiattachop", + "PreviewMultiAttachThresholdType": ".previewmultiattachop", "PreviewMultiAttachTier": ".previewmultiattachop", "PreviewMultiAttachTierBehavior": ".previewmultiattachop", "PreviewMultiAttachTierTypedDict": ".previewmultiattachop", "PreviewMultiAttachTo": ".previewmultiattachop", "PreviewMultiAttachToTypedDict": ".previewmultiattachop", + "PreviewMultiAttachUsageAlert": ".previewmultiattachop", + "PreviewMultiAttachUsageAlertTypedDict": ".previewmultiattachop", "PreviewMultiAttachUsageLineItem": ".previewmultiattachop", "PreviewMultiAttachUsageLineItemPeriod": ".previewmultiattachop", "PreviewMultiAttachUsageLineItemPeriodTypedDict": ".previewmultiattachop", @@ -3294,6 +3409,8 @@ _dynamic_imports: dict[str, str] = { "PreviewUpdateProration": ".previewupdateop", "PreviewUpdateProrationBehavior": ".previewupdateop", "PreviewUpdateProrationTypedDict": ".previewupdateop", + "PreviewUpdateRecalculateBalances": ".previewupdateop", + "PreviewUpdateRecalculateBalancesTypedDict": ".previewupdateop", "PreviewUpdateRedirectMode": ".previewupdateop", "PreviewUpdateReset": ".previewupdateop", "PreviewUpdateResetInterval": ".previewupdateop", @@ -3418,7 +3535,13 @@ _dynamic_imports: dict[str, str] = { "UpdateCustomerStatus": ".updatecustomerop", "UpdateCustomerSubscription": ".updatecustomerop", "UpdateCustomerSubscriptionTypedDict": ".updatecustomerop", + "UpdateCustomerThresholdTypeRequestBody": ".updatecustomerop", + "UpdateCustomerThresholdTypeResponse": ".updatecustomerop", "UpdateCustomerType": ".updatecustomerop", + "UpdateCustomerUsageAlertRequestBody": ".updatecustomerop", + "UpdateCustomerUsageAlertRequestBodyTypedDict": ".updatecustomerop", + "UpdateCustomerUsageAlertResponse": ".updatecustomerop", + "UpdateCustomerUsageAlertResponseTypedDict": ".updatecustomerop", "UpdateEntityBillingControlsRequest": ".updateentityop", "UpdateEntityBillingControlsRequestTypedDict": ".updateentityop", "UpdateEntityBillingControlsResponse": ".updateentityop", @@ -3449,7 +3572,13 @@ _dynamic_imports: dict[str, str] = { "UpdateEntityStatus": ".updateentityop", "UpdateEntitySubscription": ".updateentityop", "UpdateEntitySubscriptionTypedDict": ".updateentityop", + "UpdateEntityThresholdTypeRequestBody": ".updateentityop", + "UpdateEntityThresholdTypeResponse": ".updateentityop", "UpdateEntityType": ".updateentityop", + "UpdateEntityUsageAlertRequestBody": ".updateentityop", + "UpdateEntityUsageAlertRequestBodyTypedDict": ".updateentityop", + "UpdateEntityUsageAlertResponse": ".updateentityop", + "UpdateEntityUsageAlertResponseTypedDict": ".updateentityop", "UpdateFeatureCreditSchemaRequest": ".updatefeatureop", "UpdateFeatureCreditSchemaRequestTypedDict": ".updatefeatureop", "UpdateFeatureCreditSchemaResponse": ".updatefeatureop", @@ -3536,17 +3665,40 @@ _dynamic_imports: dict[str, str] = { "UpdatePlanType": ".updateplanop", } -_sub_packages = ["internal"] + +def dynamic_import(modname, retries=3): + for attempt in range(retries): + try: + return import_module(modname, __package__) + except KeyError: + # Clear any half-initialized module and retry + sys.modules.pop(modname, None) + if attempt == retries - 1: + break + raise KeyError(f"Failed to import module '{modname}' after {retries} attempts") -def __getattr__(attr_name: str) -> Any: - return lazy_getattr( - attr_name, - package=__package__, - dynamic_imports=_dynamic_imports, - sub_packages=_sub_packages, - ) +def __getattr__(attr_name: str) -> object: + module_name = _dynamic_imports.get(attr_name) + if module_name is None: + raise AttributeError( + f"No {attr_name} found in _dynamic_imports for module name -> {__name__} " + ) + + try: + module = dynamic_import(module_name) + result = getattr(module, attr_name) + return result + except ImportError as e: + raise ImportError( + f"Failed to import {attr_name} from {module_name}: {e}" + ) from e + except AttributeError as e: + raise AttributeError( + f"Failed to get {attr_name} from {module_name}: {e}" + ) from e def __dir__(): - return lazy_dir(dynamic_imports=_dynamic_imports, sub_packages=_sub_packages) + lazy_attrs = builtins.list(_dynamic_imports.keys()) + return builtins.sorted(lazy_attrs) diff --git a/others/python-sdk/src/autumn_sdk/models/aggregateeventsop.py b/others/python-sdk/src/autumn_sdk/models/aggregateeventsop.py index b62e4c617..c6a100bbd 100644 --- a/others/python-sdk/src/autumn_sdk/models/aggregateeventsop.py +++ b/others/python-sdk/src/autumn_sdk/models/aggregateeventsop.py @@ -28,7 +28,7 @@ class AggregateEventsGlobals(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -140,7 +140,7 @@ class EventsAggregateParams(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -176,7 +176,7 @@ class AggregateEventsList(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: diff --git a/others/python-sdk/src/autumn_sdk/models/attachop.py b/others/python-sdk/src/autumn_sdk/models/attachop.py index 434a571ef..12b3c3c9c 100644 --- a/others/python-sdk/src/autumn_sdk/models/attachop.py +++ b/others/python-sdk/src/autumn_sdk/models/attachop.py @@ -35,7 +35,7 @@ class AttachGlobals(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -75,7 +75,7 @@ class AttachFeatureQuantity(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -126,7 +126,7 @@ class AttachBasePrice(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -175,7 +175,7 @@ class AttachReset(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -211,7 +211,7 @@ class AttachTier(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -307,7 +307,7 @@ class AttachPrice(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -392,7 +392,7 @@ class AttachRollover(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -454,7 +454,7 @@ class AttachPlanItem(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -502,7 +502,7 @@ class AttachFreeTrialParams(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -543,7 +543,7 @@ class AttachCustomize(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) is_nullable_and_explicitly_set = ( k in nullable_fields and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member @@ -591,7 +591,7 @@ class AttachInvoiceMode(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -641,7 +641,7 @@ class AttachAttachDiscount(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -698,7 +698,7 @@ class AttachCarryOverBalances(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -733,7 +733,7 @@ class AttachCarryOverUsages(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -869,7 +869,7 @@ class AttachParams(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -918,7 +918,7 @@ class AttachInvoice(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: m[k] = val @@ -998,7 +998,7 @@ class AttachResponse(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) is_nullable_and_explicitly_set = ( k in nullable_fields and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member diff --git a/others/python-sdk/src/autumn_sdk/models/balance.py b/others/python-sdk/src/autumn_sdk/models/balance.py index f08b03da9..9e4d3d82c 100644 --- a/others/python-sdk/src/autumn_sdk/models/balance.py +++ b/others/python-sdk/src/autumn_sdk/models/balance.py @@ -67,7 +67,7 @@ class BalanceDisplay(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) is_nullable_and_explicitly_set = ( k in nullable_fields and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member @@ -140,7 +140,7 @@ class BalanceFeature(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -201,7 +201,7 @@ class BalanceReset(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) is_nullable_and_explicitly_set = ( k in nullable_fields and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member @@ -281,7 +281,7 @@ class BalancePrice(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) is_nullable_and_explicitly_set = ( k in nullable_fields and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member @@ -361,7 +361,7 @@ class Breakdown(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) is_nullable_and_explicitly_set = ( k in nullable_fields and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member @@ -461,7 +461,7 @@ class Balance(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) is_nullable_and_explicitly_set = ( k in nullable_fields and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member diff --git a/others/python-sdk/src/autumn_sdk/models/billingupdateop.py b/others/python-sdk/src/autumn_sdk/models/billingupdateop.py index 944115475..52804986f 100644 --- a/others/python-sdk/src/autumn_sdk/models/billingupdateop.py +++ b/others/python-sdk/src/autumn_sdk/models/billingupdateop.py @@ -35,7 +35,7 @@ class BillingUpdateGlobals(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -75,7 +75,7 @@ class BillingUpdateFeatureQuantity(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -126,7 +126,7 @@ class BillingUpdateBasePrice(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -175,7 +175,7 @@ class BillingUpdateReset(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -211,7 +211,7 @@ class BillingUpdateTier(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -307,7 +307,7 @@ class BillingUpdatePrice(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -392,7 +392,7 @@ class BillingUpdateRollover(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -454,7 +454,7 @@ class BillingUpdatePlanItem(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -502,7 +502,7 @@ class BillingUpdateFreeTrialParams(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -543,7 +543,7 @@ class BillingUpdateCustomize(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) is_nullable_and_explicitly_set = ( k in nullable_fields and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member @@ -591,7 +591,7 @@ class BillingUpdateInvoiceMode(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -623,6 +623,20 @@ BillingUpdateCancelAction = Literal[ r"""Action to perform for cancellation. 'cancel_immediately' cancels now with prorated refund, 'cancel_end_of_cycle' cancels at period end, 'uncancel' reverses a pending cancellation.""" +class BillingUpdateRecalculateBalancesTypedDict(TypedDict): + r"""Controls whether balances should be recalculated during the subscription update.""" + + enabled: bool + r"""If true, recalculates balances during the subscription update. Only applicable when updating feature quantities.""" + + +class BillingUpdateRecalculateBalances(BaseModel): + r"""Controls whether balances should be recalculated during the subscription update.""" + + enabled: bool + r"""If true, recalculates balances during the subscription update. Only applicable when updating feature quantities.""" + + class UpdateSubscriptionParamsTypedDict(TypedDict): customer_id: str r"""The ID of the customer to attach the plan to.""" @@ -648,6 +662,8 @@ class UpdateSubscriptionParamsTypedDict(TypedDict): r"""Action to perform for cancellation. 'cancel_immediately' cancels now with prorated refund, 'cancel_end_of_cycle' cancels at period end, 'uncancel' reverses a pending cancellation.""" no_billing_changes: NotRequired[bool] r"""If true, the subscription is updated internally without applying billing changes in Stripe.""" + recalculate_balances: NotRequired[BillingUpdateRecalculateBalancesTypedDict] + r"""Controls whether balances should be recalculated during the subscription update.""" class UpdateSubscriptionParams(BaseModel): @@ -687,6 +703,9 @@ class UpdateSubscriptionParams(BaseModel): no_billing_changes: Optional[bool] = None r"""If true, the subscription is updated internally without applying billing changes in Stripe.""" + recalculate_balances: Optional[BillingUpdateRecalculateBalances] = None + r"""Controls whether balances should be recalculated during the subscription update.""" + @model_serializer(mode="wrap") def serialize_model(self, handler): optional_fields = set( @@ -702,6 +721,7 @@ class UpdateSubscriptionParams(BaseModel): "subscription_id", "cancel_action", "no_billing_changes", + "recalculate_balances", ] ) serialized = handler(self) @@ -709,7 +729,7 @@ class UpdateSubscriptionParams(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -758,7 +778,7 @@ class BillingUpdateInvoice(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: m[k] = val @@ -838,7 +858,7 @@ class BillingUpdateResponse(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) is_nullable_and_explicitly_set = ( k in nullable_fields and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member diff --git a/others/python-sdk/src/autumn_sdk/models/checkop.py b/others/python-sdk/src/autumn_sdk/models/checkop.py index 0d0e2e977..81008db9b 100644 --- a/others/python-sdk/src/autumn_sdk/models/checkop.py +++ b/others/python-sdk/src/autumn_sdk/models/checkop.py @@ -37,7 +37,7 @@ class CheckGlobals(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -80,7 +80,7 @@ class CheckLock(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -150,7 +150,7 @@ class CheckParams(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -212,7 +212,7 @@ class FlagDisplay(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) is_nullable_and_explicitly_set = ( k in nullable_fields and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member @@ -285,7 +285,7 @@ class CheckFeature(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -332,7 +332,7 @@ class Flag(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) is_nullable_and_explicitly_set = ( k in nullable_fields and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member @@ -448,7 +448,7 @@ class ProductDisplay(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) is_nullable_and_explicitly_set = ( k in nullable_fields and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member @@ -496,7 +496,7 @@ class CheckRollover(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) is_nullable_and_explicitly_set = ( k in nullable_fields and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member @@ -558,7 +558,7 @@ class Config(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) is_nullable_and_explicitly_set = ( k in nullable_fields and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member @@ -717,7 +717,7 @@ class CheckItem(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) is_nullable_and_explicitly_set = ( k in nullable_fields and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member @@ -783,7 +783,7 @@ class CheckFreeTrial(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) is_nullable_and_explicitly_set = ( k in nullable_fields and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member @@ -855,7 +855,7 @@ class CheckProperties(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) is_nullable_and_explicitly_set = ( k in nullable_fields and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member @@ -953,7 +953,7 @@ class Product(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) is_nullable_and_explicitly_set = ( k in nullable_fields and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member @@ -1061,7 +1061,7 @@ class CheckResponse(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) is_nullable_and_explicitly_set = ( k in nullable_fields and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member diff --git a/others/python-sdk/src/autumn_sdk/models/createbalanceop.py b/others/python-sdk/src/autumn_sdk/models/createbalanceop.py index 5f8b89b4b..674607646 100644 --- a/others/python-sdk/src/autumn_sdk/models/createbalanceop.py +++ b/others/python-sdk/src/autumn_sdk/models/createbalanceop.py @@ -28,7 +28,7 @@ class CreateBalanceGlobals(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -77,7 +77,7 @@ class CreateBalanceReset(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -147,7 +147,7 @@ class CreateBalanceParams(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: diff --git a/others/python-sdk/src/autumn_sdk/models/createentityop.py b/others/python-sdk/src/autumn_sdk/models/createentityop.py index 006b843c4..29bc6efc3 100644 --- a/others/python-sdk/src/autumn_sdk/models/createentityop.py +++ b/others/python-sdk/src/autumn_sdk/models/createentityop.py @@ -38,7 +38,7 @@ class CreateEntityGlobals(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -74,7 +74,60 @@ class CreateEntitySpendLimitRequest(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) + + if val != UNSET_SENTINEL: + if val is not None or k not in optional_fields: + m[k] = val + + return m + + +CreateEntityThresholdTypeRequestBody = Literal[ + "usage", + "usage_percentage", +] +r"""Whether the threshold is an absolute usage count or a percentage of the usage allowance.""" + + +class CreateEntityUsageAlertRequestBodyTypedDict(TypedDict): + threshold: float + r"""The threshold value that triggers the alert. For usage, this is an absolute count. For usage_percentage, this is a percentage (0-100).""" + threshold_type: CreateEntityThresholdTypeRequestBody + r"""Whether the threshold is an absolute usage count or a percentage of the usage allowance.""" + feature_id: NotRequired[str] + r"""The feature ID this alert applies to. If omitted, the alert applies globally.""" + enabled: NotRequired[bool] + r"""Whether this usage alert is enabled.""" + name: NotRequired[str] + r"""Optional user-defined label to distinguish multiple alerts on the same feature.""" + + +class CreateEntityUsageAlertRequestBody(BaseModel): + threshold: float + r"""The threshold value that triggers the alert. For usage, this is an absolute count. For usage_percentage, this is a percentage (0-100).""" + + threshold_type: CreateEntityThresholdTypeRequestBody + r"""Whether the threshold is an absolute usage count or a percentage of the usage allowance.""" + + feature_id: Optional[str] = None + r"""The feature ID this alert applies to. If omitted, the alert applies globally.""" + + enabled: Optional[bool] = True + r"""Whether this usage alert is enabled.""" + + name: Optional[str] = None + r"""Optional user-defined label to distinguish multiple alerts on the same feature.""" + + @model_serializer(mode="wrap") + def serialize_model(self, handler): + optional_fields = set(["feature_id", "enabled", "name"]) + serialized = handler(self) + m = {} + + for n, f in type(self).model_fields.items(): + k = f.alias or n + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -88,6 +141,8 @@ class CreateEntityBillingControlsRequestTypedDict(TypedDict): spend_limits: NotRequired[List[CreateEntitySpendLimitRequestTypedDict]] r"""List of overage spend limits per feature.""" + usage_alerts: NotRequired[List[CreateEntityUsageAlertRequestBodyTypedDict]] + r"""List of usage alert configurations per feature.""" class CreateEntityBillingControlsRequest(BaseModel): @@ -96,15 +151,18 @@ class CreateEntityBillingControlsRequest(BaseModel): spend_limits: Optional[List[CreateEntitySpendLimitRequest]] = None r"""List of overage spend limits per feature.""" + usage_alerts: Optional[List[CreateEntityUsageAlertRequestBody]] = None + r"""List of usage alert configurations per feature.""" + @model_serializer(mode="wrap") def serialize_model(self, handler): - optional_fields = set(["spend_limits"]) + optional_fields = set(["spend_limits", "usage_alerts"]) serialized = handler(self) m = {} for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -156,7 +214,7 @@ class CreateEntityParams(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) is_nullable_and_explicitly_set = ( k in nullable_fields and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member @@ -282,7 +340,7 @@ class CreateEntitySubscription(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) is_nullable_and_explicitly_set = ( k in nullable_fields and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member @@ -335,7 +393,7 @@ class CreateEntityPurchase(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) is_nullable_and_explicitly_set = ( k in nullable_fields and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member @@ -405,7 +463,7 @@ class CreateEntityDisplay(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) is_nullable_and_explicitly_set = ( k in nullable_fields and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member @@ -478,7 +536,7 @@ class CreateEntityFeature(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -525,7 +583,7 @@ class CreateEntityFlags(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) is_nullable_and_explicitly_set = ( k in nullable_fields and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member @@ -569,7 +627,63 @@ class CreateEntitySpendLimitResponse(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) + + if val != UNSET_SENTINEL: + if val is not None or k not in optional_fields: + m[k] = val + + return m + + +CreateEntityThresholdTypeResponse = Union[ + Literal[ + "usage", + "usage_percentage", + ], + UnrecognizedStr, +] +r"""Whether the threshold is an absolute usage count or a percentage of the usage allowance.""" + + +class CreateEntityUsageAlertResponseTypedDict(TypedDict): + threshold: float + r"""The threshold value that triggers the alert. For usage, this is an absolute count. For usage_percentage, this is a percentage (0-100).""" + threshold_type: CreateEntityThresholdTypeResponse + r"""Whether the threshold is an absolute usage count or a percentage of the usage allowance.""" + feature_id: NotRequired[str] + r"""The feature ID this alert applies to. If omitted, the alert applies globally.""" + enabled: NotRequired[bool] + r"""Whether this usage alert is enabled.""" + name: NotRequired[str] + r"""Optional user-defined label to distinguish multiple alerts on the same feature.""" + + +class CreateEntityUsageAlertResponse(BaseModel): + threshold: float + r"""The threshold value that triggers the alert. For usage, this is an absolute count. For usage_percentage, this is a percentage (0-100).""" + + threshold_type: CreateEntityThresholdTypeResponse + r"""Whether the threshold is an absolute usage count or a percentage of the usage allowance.""" + + feature_id: Optional[str] = None + r"""The feature ID this alert applies to. If omitted, the alert applies globally.""" + + enabled: Optional[bool] = True + r"""Whether this usage alert is enabled.""" + + name: Optional[str] = None + r"""Optional user-defined label to distinguish multiple alerts on the same feature.""" + + @model_serializer(mode="wrap") + def serialize_model(self, handler): + optional_fields = set(["feature_id", "enabled", "name"]) + serialized = handler(self) + m = {} + + for n, f in type(self).model_fields.items(): + k = f.alias or n + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -583,6 +697,8 @@ class CreateEntityBillingControlsResponseTypedDict(TypedDict): spend_limits: NotRequired[List[CreateEntitySpendLimitResponseTypedDict]] r"""List of overage spend limits per feature.""" + usage_alerts: NotRequired[List[CreateEntityUsageAlertResponseTypedDict]] + r"""List of usage alert configurations per feature.""" class CreateEntityBillingControlsResponse(BaseModel): @@ -591,15 +707,18 @@ class CreateEntityBillingControlsResponse(BaseModel): spend_limits: Optional[List[CreateEntitySpendLimitResponse]] = None r"""List of overage spend limits per feature.""" + usage_alerts: Optional[List[CreateEntityUsageAlertResponse]] = None + r"""List of usage alert configurations per feature.""" + @model_serializer(mode="wrap") def serialize_model(self, handler): - optional_fields = set(["spend_limits"]) + optional_fields = set(["spend_limits", "usage_alerts"]) serialized = handler(self) m = {} for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -656,7 +775,7 @@ class CreateEntityInvoice(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) is_nullable_and_explicitly_set = ( k in nullable_fields and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member @@ -744,7 +863,7 @@ class CreateEntityResponse(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) is_nullable_and_explicitly_set = ( k in nullable_fields and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member diff --git a/others/python-sdk/src/autumn_sdk/models/createfeatureop.py b/others/python-sdk/src/autumn_sdk/models/createfeatureop.py index 35a43e4dd..b6be52d60 100644 --- a/others/python-sdk/src/autumn_sdk/models/createfeatureop.py +++ b/others/python-sdk/src/autumn_sdk/models/createfeatureop.py @@ -35,7 +35,7 @@ class CreateFeatureGlobals(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -123,7 +123,7 @@ class CreateFeatureParams(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -185,7 +185,7 @@ class CreateFeatureDisplayResponse(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) is_nullable_and_explicitly_set = ( k in nullable_fields and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member @@ -258,7 +258,7 @@ class CreateFeatureResponse(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: diff --git a/others/python-sdk/src/autumn_sdk/models/createplanop.py b/others/python-sdk/src/autumn_sdk/models/createplanop.py index 68ffef898..3188aa943 100644 --- a/others/python-sdk/src/autumn_sdk/models/createplanop.py +++ b/others/python-sdk/src/autumn_sdk/models/createplanop.py @@ -35,7 +35,7 @@ class CreatePlanGlobals(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -86,7 +86,7 @@ class CreatePlanPriceRequest(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -135,7 +135,7 @@ class CreatePlanResetRequest(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -171,7 +171,7 @@ class CreatePlanTier(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -267,7 +267,7 @@ class CreatePlanItemPriceRequest(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -352,7 +352,7 @@ class CreatePlanRolloverRequest(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -414,7 +414,7 @@ class CreatePlanPlanItem(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -462,7 +462,7 @@ class FreeTrialRequest(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -539,7 +539,7 @@ class CreatePlanParams(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) is_nullable_and_explicitly_set = ( k in nullable_fields and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member @@ -596,7 +596,7 @@ class CreatePlanPriceDisplay(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -637,7 +637,7 @@ class CreatePlanPriceResponse(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -736,7 +736,7 @@ class CreatePlanFeature(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) is_nullable_and_explicitly_set = ( k in nullable_fields and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member @@ -792,7 +792,7 @@ class CreatePlanResetResponse(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -885,7 +885,7 @@ class CreatePlanItemPriceResponse(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) is_nullable_and_explicitly_set = ( k in nullable_fields and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member @@ -928,7 +928,7 @@ class CreatePlanItemDisplay(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -979,7 +979,7 @@ class CreatePlanRolloverResponse(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) is_nullable_and_explicitly_set = ( k in nullable_fields and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member @@ -1049,7 +1049,7 @@ class CreatePlanItem(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) is_nullable_and_explicitly_set = ( k in nullable_fields and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member @@ -1171,7 +1171,7 @@ class CreatePlanCustomerEligibility(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -1270,7 +1270,7 @@ class CreatePlanResponse(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) is_nullable_and_explicitly_set = ( k in nullable_fields and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member diff --git a/others/python-sdk/src/autumn_sdk/models/createreferralcodeop.py b/others/python-sdk/src/autumn_sdk/models/createreferralcodeop.py index cd3ad4890..60bb089e7 100644 --- a/others/python-sdk/src/autumn_sdk/models/createreferralcodeop.py +++ b/others/python-sdk/src/autumn_sdk/models/createreferralcodeop.py @@ -28,7 +28,7 @@ class CreateReferralCodeGlobals(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: diff --git a/others/python-sdk/src/autumn_sdk/models/customer.py b/others/python-sdk/src/autumn_sdk/models/customer.py index e041b7cf1..52b3cda11 100644 --- a/others/python-sdk/src/autumn_sdk/models/customer.py +++ b/others/python-sdk/src/autumn_sdk/models/customer.py @@ -69,7 +69,7 @@ class CustomerPurchaseLimit(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -115,7 +115,7 @@ class CustomerAutoTopup(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -151,7 +151,63 @@ class CustomerSpendLimit(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) + + if val != UNSET_SENTINEL: + if val is not None or k not in optional_fields: + m[k] = val + + return m + + +CustomerThresholdType = Union[ + Literal[ + "usage", + "usage_percentage", + ], + UnrecognizedStr, +] +r"""Whether the threshold is an absolute usage count or a percentage of the usage allowance.""" + + +class CustomerUsageAlertTypedDict(TypedDict): + threshold: float + r"""The threshold value that triggers the alert. For usage, this is an absolute count. For usage_percentage, this is a percentage (0-100).""" + threshold_type: CustomerThresholdType + r"""Whether the threshold is an absolute usage count or a percentage of the usage allowance.""" + feature_id: NotRequired[str] + r"""The feature ID this alert applies to. If omitted, the alert applies globally.""" + enabled: NotRequired[bool] + r"""Whether this usage alert is enabled.""" + name: NotRequired[str] + r"""Optional user-defined label to distinguish multiple alerts on the same feature.""" + + +class CustomerUsageAlert(BaseModel): + threshold: float + r"""The threshold value that triggers the alert. For usage, this is an absolute count. For usage_percentage, this is a percentage (0-100).""" + + threshold_type: CustomerThresholdType + r"""Whether the threshold is an absolute usage count or a percentage of the usage allowance.""" + + feature_id: Optional[str] = None + r"""The feature ID this alert applies to. If omitted, the alert applies globally.""" + + enabled: Optional[bool] = True + r"""Whether this usage alert is enabled.""" + + name: Optional[str] = None + r"""Optional user-defined label to distinguish multiple alerts on the same feature.""" + + @model_serializer(mode="wrap") + def serialize_model(self, handler): + optional_fields = set(["feature_id", "enabled", "name"]) + serialized = handler(self) + m = {} + + for n, f in type(self).model_fields.items(): + k = f.alias or n + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -167,6 +223,8 @@ class CustomerBillingControlsTypedDict(TypedDict): r"""List of auto top-up configurations per feature.""" spend_limits: NotRequired[List[CustomerSpendLimitTypedDict]] r"""List of overage spend limits per feature.""" + usage_alerts: NotRequired[List[CustomerUsageAlertTypedDict]] + r"""List of usage alert configurations per feature.""" class CustomerBillingControls(BaseModel): @@ -178,15 +236,18 @@ class CustomerBillingControls(BaseModel): spend_limits: Optional[List[CustomerSpendLimit]] = None r"""List of overage spend limits per feature.""" + usage_alerts: Optional[List[CustomerUsageAlert]] = None + r"""List of usage alert configurations per feature.""" + @model_serializer(mode="wrap") def serialize_model(self, handler): - optional_fields = set(["auto_topups", "spend_limits"]) + optional_fields = set(["auto_topups", "spend_limits", "usage_alerts"]) serialized = handler(self) m = {} for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -294,7 +355,7 @@ class Subscription(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) is_nullable_and_explicitly_set = ( k in nullable_fields and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member @@ -347,7 +408,7 @@ class Purchase(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) is_nullable_and_explicitly_set = ( k in nullable_fields and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member @@ -417,7 +478,7 @@ class CustomerDisplay(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) is_nullable_and_explicitly_set = ( k in nullable_fields and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member @@ -490,7 +551,7 @@ class CustomerFeature(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -537,7 +598,7 @@ class Flags(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) is_nullable_and_explicitly_set = ( k in nullable_fields and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member @@ -602,7 +663,7 @@ class Invoice(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) is_nullable_and_explicitly_set = ( k in nullable_fields and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member @@ -672,7 +733,7 @@ class Entity(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) is_nullable_and_explicitly_set = ( k in nullable_fields and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member @@ -711,7 +772,7 @@ class TrialsUsed(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) is_nullable_and_explicitly_set = ( k in nullable_fields and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member @@ -837,7 +898,7 @@ class Discount(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) is_nullable_and_explicitly_set = ( k in nullable_fields and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member @@ -886,7 +947,7 @@ class ReferralCustomer(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) is_nullable_and_explicitly_set = ( k in nullable_fields and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member @@ -1052,7 +1113,7 @@ class Customer(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) is_nullable_and_explicitly_set = ( k in nullable_fields and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member diff --git a/others/python-sdk/src/autumn_sdk/models/customerdata.py b/others/python-sdk/src/autumn_sdk/models/customerdata.py index 192060327..78cb71f16 100644 --- a/others/python-sdk/src/autumn_sdk/models/customerdata.py +++ b/others/python-sdk/src/autumn_sdk/models/customerdata.py @@ -53,7 +53,7 @@ class CustomerDataPurchaseLimit(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -99,7 +99,7 @@ class CustomerDataAutoTopup(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -135,7 +135,60 @@ class CustomerDataSpendLimit(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) + + if val != UNSET_SENTINEL: + if val is not None or k not in optional_fields: + m[k] = val + + return m + + +CustomerDataThresholdType = Literal[ + "usage", + "usage_percentage", +] +r"""Whether the threshold is an absolute usage count or a percentage of the usage allowance.""" + + +class CustomerDataUsageAlertTypedDict(TypedDict): + threshold: float + r"""The threshold value that triggers the alert. For usage, this is an absolute count. For usage_percentage, this is a percentage (0-100).""" + threshold_type: CustomerDataThresholdType + r"""Whether the threshold is an absolute usage count or a percentage of the usage allowance.""" + feature_id: NotRequired[str] + r"""The feature ID this alert applies to. If omitted, the alert applies globally.""" + enabled: NotRequired[bool] + r"""Whether this usage alert is enabled.""" + name: NotRequired[str] + r"""Optional user-defined label to distinguish multiple alerts on the same feature.""" + + +class CustomerDataUsageAlert(BaseModel): + threshold: float + r"""The threshold value that triggers the alert. For usage, this is an absolute count. For usage_percentage, this is a percentage (0-100).""" + + threshold_type: CustomerDataThresholdType + r"""Whether the threshold is an absolute usage count or a percentage of the usage allowance.""" + + feature_id: Optional[str] = None + r"""The feature ID this alert applies to. If omitted, the alert applies globally.""" + + enabled: Optional[bool] = True + r"""Whether this usage alert is enabled.""" + + name: Optional[str] = None + r"""Optional user-defined label to distinguish multiple alerts on the same feature.""" + + @model_serializer(mode="wrap") + def serialize_model(self, handler): + optional_fields = set(["feature_id", "enabled", "name"]) + serialized = handler(self) + m = {} + + for n, f in type(self).model_fields.items(): + k = f.alias or n + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -151,6 +204,8 @@ class CustomerDataBillingControlsTypedDict(TypedDict): r"""List of auto top-up configurations per feature.""" spend_limits: NotRequired[List[CustomerDataSpendLimitTypedDict]] r"""List of overage spend limits per feature.""" + usage_alerts: NotRequired[List[CustomerDataUsageAlertTypedDict]] + r"""List of usage alert configurations per feature.""" class CustomerDataBillingControls(BaseModel): @@ -162,15 +217,18 @@ class CustomerDataBillingControls(BaseModel): spend_limits: Optional[List[CustomerDataSpendLimit]] = None r"""List of overage spend limits per feature.""" + usage_alerts: Optional[List[CustomerDataUsageAlert]] = None + r"""List of usage alert configurations per feature.""" + @model_serializer(mode="wrap") def serialize_model(self, handler): - optional_fields = set(["auto_topups", "spend_limits"]) + optional_fields = set(["auto_topups", "spend_limits", "usage_alerts"]) serialized = handler(self) m = {} for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -253,7 +311,7 @@ class CustomerData(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) is_nullable_and_explicitly_set = ( k in nullable_fields and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member diff --git a/others/python-sdk/src/autumn_sdk/models/deletebalanceop.py b/others/python-sdk/src/autumn_sdk/models/deletebalanceop.py index e93512ba6..8d2835818 100644 --- a/others/python-sdk/src/autumn_sdk/models/deletebalanceop.py +++ b/others/python-sdk/src/autumn_sdk/models/deletebalanceop.py @@ -28,7 +28,7 @@ class DeleteBalanceGlobals(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -88,7 +88,7 @@ class DeleteBalanceParams(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: diff --git a/others/python-sdk/src/autumn_sdk/models/deletecustomerop.py b/others/python-sdk/src/autumn_sdk/models/deletecustomerop.py index f731ec176..360a0ca57 100644 --- a/others/python-sdk/src/autumn_sdk/models/deletecustomerop.py +++ b/others/python-sdk/src/autumn_sdk/models/deletecustomerop.py @@ -28,7 +28,7 @@ class DeleteCustomerGlobals(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -59,7 +59,7 @@ class DeleteCustomerParams(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: diff --git a/others/python-sdk/src/autumn_sdk/models/deleteentityop.py b/others/python-sdk/src/autumn_sdk/models/deleteentityop.py index 994654d79..3aec2ed90 100644 --- a/others/python-sdk/src/autumn_sdk/models/deleteentityop.py +++ b/others/python-sdk/src/autumn_sdk/models/deleteentityop.py @@ -28,7 +28,7 @@ class DeleteEntityGlobals(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -59,7 +59,7 @@ class DeleteEntityParams(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: diff --git a/others/python-sdk/src/autumn_sdk/models/deletefeatureop.py b/others/python-sdk/src/autumn_sdk/models/deletefeatureop.py index d16ff515b..1cb236ef4 100644 --- a/others/python-sdk/src/autumn_sdk/models/deletefeatureop.py +++ b/others/python-sdk/src/autumn_sdk/models/deletefeatureop.py @@ -28,7 +28,7 @@ class DeleteFeatureGlobals(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: diff --git a/others/python-sdk/src/autumn_sdk/models/deleteplanop.py b/others/python-sdk/src/autumn_sdk/models/deleteplanop.py index 839992760..8d60176d4 100644 --- a/others/python-sdk/src/autumn_sdk/models/deleteplanop.py +++ b/others/python-sdk/src/autumn_sdk/models/deleteplanop.py @@ -28,7 +28,7 @@ class DeletePlanGlobals(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -59,7 +59,7 @@ class DeletePlanParams(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: diff --git a/others/python-sdk/src/autumn_sdk/models/finalizelockop.py b/others/python-sdk/src/autumn_sdk/models/finalizelockop.py index 5ca71e3f0..7fe4a8380 100644 --- a/others/python-sdk/src/autumn_sdk/models/finalizelockop.py +++ b/others/python-sdk/src/autumn_sdk/models/finalizelockop.py @@ -28,7 +28,7 @@ class FinalizeLockGlobals(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -76,7 +76,7 @@ class FinalizeBalanceParams(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: diff --git a/others/python-sdk/src/autumn_sdk/models/getentityop.py b/others/python-sdk/src/autumn_sdk/models/getentityop.py index 956fe9aac..828874eab 100644 --- a/others/python-sdk/src/autumn_sdk/models/getentityop.py +++ b/others/python-sdk/src/autumn_sdk/models/getentityop.py @@ -37,7 +37,7 @@ class GetEntityGlobals(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -68,7 +68,7 @@ class GetEntityParams(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -186,7 +186,7 @@ class GetEntitySubscription(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) is_nullable_and_explicitly_set = ( k in nullable_fields and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member @@ -239,7 +239,7 @@ class GetEntityPurchase(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) is_nullable_and_explicitly_set = ( k in nullable_fields and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member @@ -309,7 +309,7 @@ class GetEntityDisplay(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) is_nullable_and_explicitly_set = ( k in nullable_fields and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member @@ -382,7 +382,7 @@ class GetEntityFeature(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -429,7 +429,7 @@ class GetEntityFlags(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) is_nullable_and_explicitly_set = ( k in nullable_fields and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member @@ -473,7 +473,63 @@ class GetEntitySpendLimit(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) + + if val != UNSET_SENTINEL: + if val is not None or k not in optional_fields: + m[k] = val + + return m + + +GetEntityThresholdType = Union[ + Literal[ + "usage", + "usage_percentage", + ], + UnrecognizedStr, +] +r"""Whether the threshold is an absolute usage count or a percentage of the usage allowance.""" + + +class GetEntityUsageAlertTypedDict(TypedDict): + threshold: float + r"""The threshold value that triggers the alert. For usage, this is an absolute count. For usage_percentage, this is a percentage (0-100).""" + threshold_type: GetEntityThresholdType + r"""Whether the threshold is an absolute usage count or a percentage of the usage allowance.""" + feature_id: NotRequired[str] + r"""The feature ID this alert applies to. If omitted, the alert applies globally.""" + enabled: NotRequired[bool] + r"""Whether this usage alert is enabled.""" + name: NotRequired[str] + r"""Optional user-defined label to distinguish multiple alerts on the same feature.""" + + +class GetEntityUsageAlert(BaseModel): + threshold: float + r"""The threshold value that triggers the alert. For usage, this is an absolute count. For usage_percentage, this is a percentage (0-100).""" + + threshold_type: GetEntityThresholdType + r"""Whether the threshold is an absolute usage count or a percentage of the usage allowance.""" + + feature_id: Optional[str] = None + r"""The feature ID this alert applies to. If omitted, the alert applies globally.""" + + enabled: Optional[bool] = True + r"""Whether this usage alert is enabled.""" + + name: Optional[str] = None + r"""Optional user-defined label to distinguish multiple alerts on the same feature.""" + + @model_serializer(mode="wrap") + def serialize_model(self, handler): + optional_fields = set(["feature_id", "enabled", "name"]) + serialized = handler(self) + m = {} + + for n, f in type(self).model_fields.items(): + k = f.alias or n + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -487,6 +543,8 @@ class GetEntityBillingControlsTypedDict(TypedDict): spend_limits: NotRequired[List[GetEntitySpendLimitTypedDict]] r"""List of overage spend limits per feature.""" + usage_alerts: NotRequired[List[GetEntityUsageAlertTypedDict]] + r"""List of usage alert configurations per feature.""" class GetEntityBillingControls(BaseModel): @@ -495,15 +553,18 @@ class GetEntityBillingControls(BaseModel): spend_limits: Optional[List[GetEntitySpendLimit]] = None r"""List of overage spend limits per feature.""" + usage_alerts: Optional[List[GetEntityUsageAlert]] = None + r"""List of usage alert configurations per feature.""" + @model_serializer(mode="wrap") def serialize_model(self, handler): - optional_fields = set(["spend_limits"]) + optional_fields = set(["spend_limits", "usage_alerts"]) serialized = handler(self) m = {} for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -560,7 +621,7 @@ class GetEntityInvoice(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) is_nullable_and_explicitly_set = ( k in nullable_fields and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member @@ -648,7 +709,7 @@ class GetEntityResponse(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) is_nullable_and_explicitly_set = ( k in nullable_fields and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member diff --git a/others/python-sdk/src/autumn_sdk/models/getfeatureop.py b/others/python-sdk/src/autumn_sdk/models/getfeatureop.py index 63aec0714..6a0221630 100644 --- a/others/python-sdk/src/autumn_sdk/models/getfeatureop.py +++ b/others/python-sdk/src/autumn_sdk/models/getfeatureop.py @@ -35,7 +35,7 @@ class GetFeatureGlobals(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -107,7 +107,7 @@ class GetFeatureDisplay(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) is_nullable_and_explicitly_set = ( k in nullable_fields and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member @@ -180,7 +180,7 @@ class GetFeatureResponse(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: diff --git a/others/python-sdk/src/autumn_sdk/models/getorcreatecustomerop.py b/others/python-sdk/src/autumn_sdk/models/getorcreatecustomerop.py index a26722bad..c90706315 100644 --- a/others/python-sdk/src/autumn_sdk/models/getorcreatecustomerop.py +++ b/others/python-sdk/src/autumn_sdk/models/getorcreatecustomerop.py @@ -34,7 +34,7 @@ class GetOrCreateCustomerGlobals(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -83,7 +83,7 @@ class GetOrCreateCustomerPurchaseLimit(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -129,7 +129,7 @@ class GetOrCreateCustomerAutoTopup(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -165,7 +165,60 @@ class GetOrCreateCustomerSpendLimit(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) + + if val != UNSET_SENTINEL: + if val is not None or k not in optional_fields: + m[k] = val + + return m + + +GetOrCreateCustomerThresholdType = Literal[ + "usage", + "usage_percentage", +] +r"""Whether the threshold is an absolute usage count or a percentage of the usage allowance.""" + + +class GetOrCreateCustomerUsageAlertTypedDict(TypedDict): + threshold: float + r"""The threshold value that triggers the alert. For usage, this is an absolute count. For usage_percentage, this is a percentage (0-100).""" + threshold_type: GetOrCreateCustomerThresholdType + r"""Whether the threshold is an absolute usage count or a percentage of the usage allowance.""" + feature_id: NotRequired[str] + r"""The feature ID this alert applies to. If omitted, the alert applies globally.""" + enabled: NotRequired[bool] + r"""Whether this usage alert is enabled.""" + name: NotRequired[str] + r"""Optional user-defined label to distinguish multiple alerts on the same feature.""" + + +class GetOrCreateCustomerUsageAlert(BaseModel): + threshold: float + r"""The threshold value that triggers the alert. For usage, this is an absolute count. For usage_percentage, this is a percentage (0-100).""" + + threshold_type: GetOrCreateCustomerThresholdType + r"""Whether the threshold is an absolute usage count or a percentage of the usage allowance.""" + + feature_id: Optional[str] = None + r"""The feature ID this alert applies to. If omitted, the alert applies globally.""" + + enabled: Optional[bool] = True + r"""Whether this usage alert is enabled.""" + + name: Optional[str] = None + r"""Optional user-defined label to distinguish multiple alerts on the same feature.""" + + @model_serializer(mode="wrap") + def serialize_model(self, handler): + optional_fields = set(["feature_id", "enabled", "name"]) + serialized = handler(self) + m = {} + + for n, f in type(self).model_fields.items(): + k = f.alias or n + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -181,6 +234,8 @@ class GetOrCreateCustomerBillingControlsTypedDict(TypedDict): r"""List of auto top-up configurations per feature.""" spend_limits: NotRequired[List[GetOrCreateCustomerSpendLimitTypedDict]] r"""List of overage spend limits per feature.""" + usage_alerts: NotRequired[List[GetOrCreateCustomerUsageAlertTypedDict]] + r"""List of usage alert configurations per feature.""" class GetOrCreateCustomerBillingControls(BaseModel): @@ -192,15 +247,18 @@ class GetOrCreateCustomerBillingControls(BaseModel): spend_limits: Optional[List[GetOrCreateCustomerSpendLimit]] = None r"""List of overage spend limits per feature.""" + usage_alerts: Optional[List[GetOrCreateCustomerUsageAlert]] = None + r"""List of usage alert configurations per feature.""" + @model_serializer(mode="wrap") def serialize_model(self, handler): - optional_fields = set(["auto_topups", "spend_limits"]) + optional_fields = set(["auto_topups", "spend_limits", "usage_alerts"]) serialized = handler(self) m = {} for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -290,7 +348,7 @@ class GetOrCreateCustomerParams(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) is_nullable_and_explicitly_set = ( k in nullable_fields and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member diff --git a/others/python-sdk/src/autumn_sdk/models/getplanop.py b/others/python-sdk/src/autumn_sdk/models/getplanop.py index 03d634d43..1c7980ff7 100644 --- a/others/python-sdk/src/autumn_sdk/models/getplanop.py +++ b/others/python-sdk/src/autumn_sdk/models/getplanop.py @@ -35,7 +35,7 @@ class GetPlanGlobals(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -66,7 +66,7 @@ class GetPlanParams(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -115,7 +115,7 @@ class GetPlanPriceDisplay(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -156,7 +156,7 @@ class GetPlanPrice(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -255,7 +255,7 @@ class GetPlanFeature(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) is_nullable_and_explicitly_set = ( k in nullable_fields and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member @@ -311,7 +311,7 @@ class GetPlanReset(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -404,7 +404,7 @@ class GetPlanItemPrice(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) is_nullable_and_explicitly_set = ( k in nullable_fields and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member @@ -447,7 +447,7 @@ class GetPlanItemDisplay(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -498,7 +498,7 @@ class GetPlanRollover(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) is_nullable_and_explicitly_set = ( k in nullable_fields and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member @@ -568,7 +568,7 @@ class GetPlanItem(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) is_nullable_and_explicitly_set = ( k in nullable_fields and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member @@ -690,7 +690,7 @@ class GetPlanCustomerEligibility(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -789,7 +789,7 @@ class GetPlanResponse(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) is_nullable_and_explicitly_set = ( k in nullable_fields and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member diff --git a/others/python-sdk/src/autumn_sdk/models/internal/__init__.py b/others/python-sdk/src/autumn_sdk/models/internal/__init__.py index ceabb1b83..e7070a122 100644 --- a/others/python-sdk/src/autumn_sdk/models/internal/__init__.py +++ b/others/python-sdk/src/autumn_sdk/models/internal/__init__.py @@ -1,8 +1,9 @@ """Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" -from typing import Any, TYPE_CHECKING - -from autumn_sdk.utils.dynamic_imports import lazy_getattr, lazy_dir +from typing import TYPE_CHECKING +from importlib import import_module +import builtins +import sys if TYPE_CHECKING: from .globals import Globals, GlobalsTypedDict @@ -15,11 +16,39 @@ _dynamic_imports: dict[str, str] = { } -def __getattr__(attr_name: str) -> Any: - return lazy_getattr( - attr_name, package=__package__, dynamic_imports=_dynamic_imports - ) +def dynamic_import(modname, retries=3): + for attempt in range(retries): + try: + return import_module(modname, __package__) + except KeyError: + # Clear any half-initialized module and retry + sys.modules.pop(modname, None) + if attempt == retries - 1: + break + raise KeyError(f"Failed to import module '{modname}' after {retries} attempts") + + +def __getattr__(attr_name: str) -> object: + module_name = _dynamic_imports.get(attr_name) + if module_name is None: + raise AttributeError( + f"No {attr_name} found in _dynamic_imports for module name -> {__name__} " + ) + + try: + module = dynamic_import(module_name) + result = getattr(module, attr_name) + return result + except ImportError as e: + raise ImportError( + f"Failed to import {attr_name} from {module_name}: {e}" + ) from e + except AttributeError as e: + raise AttributeError( + f"Failed to get {attr_name} from {module_name}: {e}" + ) from e def __dir__(): - return lazy_dir(dynamic_imports=_dynamic_imports) + lazy_attrs = builtins.list(_dynamic_imports.keys()) + return builtins.sorted(lazy_attrs) diff --git a/others/python-sdk/src/autumn_sdk/models/internal/globals.py b/others/python-sdk/src/autumn_sdk/models/internal/globals.py index 72107ef26..9b32efedd 100644 --- a/others/python-sdk/src/autumn_sdk/models/internal/globals.py +++ b/others/python-sdk/src/autumn_sdk/models/internal/globals.py @@ -28,7 +28,7 @@ class Globals(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: diff --git a/others/python-sdk/src/autumn_sdk/models/listcustomersop.py b/others/python-sdk/src/autumn_sdk/models/listcustomersop.py index 94dfc819f..701f0a5aa 100644 --- a/others/python-sdk/src/autumn_sdk/models/listcustomersop.py +++ b/others/python-sdk/src/autumn_sdk/models/listcustomersop.py @@ -37,7 +37,7 @@ class ListCustomersGlobals(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -64,7 +64,7 @@ class ListCustomersPlan(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -119,7 +119,7 @@ class ListCustomersParams(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -181,7 +181,7 @@ class ListCustomersPurchaseLimit(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -227,7 +227,7 @@ class ListCustomersAutoTopup(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -263,7 +263,63 @@ class ListCustomersSpendLimit(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) + + if val != UNSET_SENTINEL: + if val is not None or k not in optional_fields: + m[k] = val + + return m + + +ListCustomersThresholdType = Union[ + Literal[ + "usage", + "usage_percentage", + ], + UnrecognizedStr, +] +r"""Whether the threshold is an absolute usage count or a percentage of the usage allowance.""" + + +class ListCustomersUsageAlertTypedDict(TypedDict): + threshold: float + r"""The threshold value that triggers the alert. For usage, this is an absolute count. For usage_percentage, this is a percentage (0-100).""" + threshold_type: ListCustomersThresholdType + r"""Whether the threshold is an absolute usage count or a percentage of the usage allowance.""" + feature_id: NotRequired[str] + r"""The feature ID this alert applies to. If omitted, the alert applies globally.""" + enabled: NotRequired[bool] + r"""Whether this usage alert is enabled.""" + name: NotRequired[str] + r"""Optional user-defined label to distinguish multiple alerts on the same feature.""" + + +class ListCustomersUsageAlert(BaseModel): + threshold: float + r"""The threshold value that triggers the alert. For usage, this is an absolute count. For usage_percentage, this is a percentage (0-100).""" + + threshold_type: ListCustomersThresholdType + r"""Whether the threshold is an absolute usage count or a percentage of the usage allowance.""" + + feature_id: Optional[str] = None + r"""The feature ID this alert applies to. If omitted, the alert applies globally.""" + + enabled: Optional[bool] = True + r"""Whether this usage alert is enabled.""" + + name: Optional[str] = None + r"""Optional user-defined label to distinguish multiple alerts on the same feature.""" + + @model_serializer(mode="wrap") + def serialize_model(self, handler): + optional_fields = set(["feature_id", "enabled", "name"]) + serialized = handler(self) + m = {} + + for n, f in type(self).model_fields.items(): + k = f.alias or n + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -279,6 +335,8 @@ class ListCustomersBillingControlsTypedDict(TypedDict): r"""List of auto top-up configurations per feature.""" spend_limits: NotRequired[List[ListCustomersSpendLimitTypedDict]] r"""List of overage spend limits per feature.""" + usage_alerts: NotRequired[List[ListCustomersUsageAlertTypedDict]] + r"""List of usage alert configurations per feature.""" class ListCustomersBillingControls(BaseModel): @@ -290,15 +348,18 @@ class ListCustomersBillingControls(BaseModel): spend_limits: Optional[List[ListCustomersSpendLimit]] = None r"""List of overage spend limits per feature.""" + usage_alerts: Optional[List[ListCustomersUsageAlert]] = None + r"""List of usage alert configurations per feature.""" + @model_serializer(mode="wrap") def serialize_model(self, handler): - optional_fields = set(["auto_topups", "spend_limits"]) + optional_fields = set(["auto_topups", "spend_limits", "usage_alerts"]) serialized = handler(self) m = {} for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -406,7 +467,7 @@ class ListCustomersSubscription(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) is_nullable_and_explicitly_set = ( k in nullable_fields and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member @@ -459,7 +520,7 @@ class ListCustomersPurchase(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) is_nullable_and_explicitly_set = ( k in nullable_fields and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member @@ -529,7 +590,7 @@ class ListCustomersDisplay(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) is_nullable_and_explicitly_set = ( k in nullable_fields and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member @@ -602,7 +663,7 @@ class ListCustomersFeature(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -649,7 +710,7 @@ class ListCustomersFlags(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) is_nullable_and_explicitly_set = ( k in nullable_fields and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member @@ -747,7 +808,7 @@ class ListCustomersList(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: m[k] = val diff --git a/others/python-sdk/src/autumn_sdk/models/listeventsop.py b/others/python-sdk/src/autumn_sdk/models/listeventsop.py index 98b7f60ad..52845e969 100644 --- a/others/python-sdk/src/autumn_sdk/models/listeventsop.py +++ b/others/python-sdk/src/autumn_sdk/models/listeventsop.py @@ -28,7 +28,7 @@ class ListEventsGlobals(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -73,7 +73,7 @@ class ListEventsCustomRange(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -133,7 +133,7 @@ class EventsListParams(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: diff --git a/others/python-sdk/src/autumn_sdk/models/listfeaturesop.py b/others/python-sdk/src/autumn_sdk/models/listfeaturesop.py index 710a3e367..b6731d7f7 100644 --- a/others/python-sdk/src/autumn_sdk/models/listfeaturesop.py +++ b/others/python-sdk/src/autumn_sdk/models/listfeaturesop.py @@ -35,7 +35,7 @@ class ListFeaturesGlobals(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -105,7 +105,7 @@ class ListFeaturesDisplay(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) is_nullable_and_explicitly_set = ( k in nullable_fields and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member @@ -174,7 +174,7 @@ class ListFeaturesList(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: diff --git a/others/python-sdk/src/autumn_sdk/models/listplansop.py b/others/python-sdk/src/autumn_sdk/models/listplansop.py index bd090552f..55bab58d8 100644 --- a/others/python-sdk/src/autumn_sdk/models/listplansop.py +++ b/others/python-sdk/src/autumn_sdk/models/listplansop.py @@ -35,7 +35,7 @@ class ListPlansGlobals(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -71,7 +71,7 @@ class ListPlansParams(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -120,7 +120,7 @@ class ListPlansPriceDisplay(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -161,7 +161,7 @@ class ListPlansPrice(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -260,7 +260,7 @@ class ListPlansFeature(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) is_nullable_and_explicitly_set = ( k in nullable_fields and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member @@ -316,7 +316,7 @@ class ListPlansReset(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -409,7 +409,7 @@ class ListPlansItemPrice(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) is_nullable_and_explicitly_set = ( k in nullable_fields and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member @@ -452,7 +452,7 @@ class ListPlansItemDisplay(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -503,7 +503,7 @@ class ListPlansRollover(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) is_nullable_and_explicitly_set = ( k in nullable_fields and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member @@ -573,7 +573,7 @@ class ListPlansItem(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) is_nullable_and_explicitly_set = ( k in nullable_fields and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member @@ -695,7 +695,7 @@ class ListPlansCustomerEligibility(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -794,7 +794,7 @@ class ListPlansList(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) is_nullable_and_explicitly_set = ( k in nullable_fields and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member diff --git a/others/python-sdk/src/autumn_sdk/models/multiattachop.py b/others/python-sdk/src/autumn_sdk/models/multiattachop.py index bb5ed660b..2b48c43af 100644 --- a/others/python-sdk/src/autumn_sdk/models/multiattachop.py +++ b/others/python-sdk/src/autumn_sdk/models/multiattachop.py @@ -36,7 +36,7 @@ class MultiAttachGlobals(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -87,7 +87,7 @@ class MultiAttachBasePrice(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -136,7 +136,7 @@ class MultiAttachReset(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -172,7 +172,7 @@ class MultiAttachTier(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -268,7 +268,7 @@ class MultiAttachPrice(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -353,7 +353,7 @@ class MultiAttachRollover(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -415,7 +415,7 @@ class MultiAttachPlanItem(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -451,7 +451,7 @@ class MultiAttachCustomize(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) is_nullable_and_explicitly_set = ( k in nullable_fields and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member @@ -499,7 +499,7 @@ class MultiAttachFeatureQuantity(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -547,7 +547,7 @@ class MultiAttachPlan(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -595,7 +595,7 @@ class MultiAttachFreeTrialParams(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -635,7 +635,7 @@ class MultiAttachInvoiceMode(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -670,7 +670,7 @@ class MultiAttachAttachDiscount(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -714,7 +714,60 @@ class MultiAttachSpendLimit(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) + + if val != UNSET_SENTINEL: + if val is not None or k not in optional_fields: + m[k] = val + + return m + + +MultiAttachThresholdType = Literal[ + "usage", + "usage_percentage", +] +r"""Whether the threshold is an absolute usage count or a percentage of the usage allowance.""" + + +class MultiAttachUsageAlertTypedDict(TypedDict): + threshold: float + r"""The threshold value that triggers the alert. For usage, this is an absolute count. For usage_percentage, this is a percentage (0-100).""" + threshold_type: MultiAttachThresholdType + r"""Whether the threshold is an absolute usage count or a percentage of the usage allowance.""" + feature_id: NotRequired[str] + r"""The feature ID this alert applies to. If omitted, the alert applies globally.""" + enabled: NotRequired[bool] + r"""Whether this usage alert is enabled.""" + name: NotRequired[str] + r"""Optional user-defined label to distinguish multiple alerts on the same feature.""" + + +class MultiAttachUsageAlert(BaseModel): + threshold: float + r"""The threshold value that triggers the alert. For usage, this is an absolute count. For usage_percentage, this is a percentage (0-100).""" + + threshold_type: MultiAttachThresholdType + r"""Whether the threshold is an absolute usage count or a percentage of the usage allowance.""" + + feature_id: Optional[str] = None + r"""The feature ID this alert applies to. If omitted, the alert applies globally.""" + + enabled: Optional[bool] = True + r"""Whether this usage alert is enabled.""" + + name: Optional[str] = None + r"""Optional user-defined label to distinguish multiple alerts on the same feature.""" + + @model_serializer(mode="wrap") + def serialize_model(self, handler): + optional_fields = set(["feature_id", "enabled", "name"]) + serialized = handler(self) + m = {} + + for n, f in type(self).model_fields.items(): + k = f.alias or n + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -728,6 +781,8 @@ class MultiAttachBillingControlsTypedDict(TypedDict): spend_limits: NotRequired[List[MultiAttachSpendLimitTypedDict]] r"""List of overage spend limits per feature.""" + usage_alerts: NotRequired[List[MultiAttachUsageAlertTypedDict]] + r"""List of usage alert configurations per feature.""" class MultiAttachBillingControls(BaseModel): @@ -736,15 +791,18 @@ class MultiAttachBillingControls(BaseModel): spend_limits: Optional[List[MultiAttachSpendLimit]] = None r"""List of overage spend limits per feature.""" + usage_alerts: Optional[List[MultiAttachUsageAlert]] = None + r"""List of usage alert configurations per feature.""" + @model_serializer(mode="wrap") def serialize_model(self, handler): - optional_fields = set(["spend_limits"]) + optional_fields = set(["spend_limits", "usage_alerts"]) serialized = handler(self) m = {} for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -780,7 +838,7 @@ class MultiAttachEntityData(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -873,7 +931,7 @@ class MultiAttachParams(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) is_nullable_and_explicitly_set = ( k in nullable_fields and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member @@ -930,7 +988,7 @@ class MultiAttachInvoice(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: m[k] = val @@ -1010,7 +1068,7 @@ class MultiAttachResponse(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) is_nullable_and_explicitly_set = ( k in nullable_fields and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member diff --git a/others/python-sdk/src/autumn_sdk/models/opencustomerportalop.py b/others/python-sdk/src/autumn_sdk/models/opencustomerportalop.py index 8383509aa..bbf47f20c 100644 --- a/others/python-sdk/src/autumn_sdk/models/opencustomerportalop.py +++ b/others/python-sdk/src/autumn_sdk/models/opencustomerportalop.py @@ -28,7 +28,7 @@ class OpenCustomerPortalGlobals(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -64,7 +64,7 @@ class OpenCustomerPortalParams(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: diff --git a/others/python-sdk/src/autumn_sdk/models/plan.py b/others/python-sdk/src/autumn_sdk/models/plan.py index 20844c9b6..56a42a2d2 100644 --- a/others/python-sdk/src/autumn_sdk/models/plan.py +++ b/others/python-sdk/src/autumn_sdk/models/plan.py @@ -54,7 +54,7 @@ class PlanPriceDisplay(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -95,7 +95,7 @@ class PlanPrice(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -194,7 +194,7 @@ class PlanFeature(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) is_nullable_and_explicitly_set = ( k in nullable_fields and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member @@ -250,7 +250,7 @@ class PlanReset(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -343,7 +343,7 @@ class PlanItemPrice(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) is_nullable_and_explicitly_set = ( k in nullable_fields and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member @@ -386,7 +386,7 @@ class PlanItemDisplay(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -437,7 +437,7 @@ class PlanRollover(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) is_nullable_and_explicitly_set = ( k in nullable_fields and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member @@ -507,7 +507,7 @@ class Item(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) is_nullable_and_explicitly_set = ( k in nullable_fields and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member @@ -629,7 +629,7 @@ class CustomerEligibility(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -724,7 +724,7 @@ class Plan(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) is_nullable_and_explicitly_set = ( k in nullable_fields and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member diff --git a/others/python-sdk/src/autumn_sdk/models/previewattachop.py b/others/python-sdk/src/autumn_sdk/models/previewattachop.py index 60df178cf..dacc7ba98 100644 --- a/others/python-sdk/src/autumn_sdk/models/previewattachop.py +++ b/others/python-sdk/src/autumn_sdk/models/previewattachop.py @@ -35,7 +35,7 @@ class PreviewAttachGlobals(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -75,7 +75,7 @@ class PreviewAttachFeatureQuantityRequest(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -126,7 +126,7 @@ class PreviewAttachBasePrice(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -175,7 +175,7 @@ class PreviewAttachReset(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -211,7 +211,7 @@ class PreviewAttachTier(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -307,7 +307,7 @@ class PreviewAttachPrice(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -392,7 +392,7 @@ class PreviewAttachRollover(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -454,7 +454,7 @@ class PreviewAttachPlanItem(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -502,7 +502,7 @@ class PreviewAttachFreeTrialParams(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -543,7 +543,7 @@ class PreviewAttachCustomize(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) is_nullable_and_explicitly_set = ( k in nullable_fields and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member @@ -591,7 +591,7 @@ class PreviewAttachInvoiceMode(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -641,7 +641,7 @@ class PreviewAttachAttachDiscount(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -698,7 +698,7 @@ class PreviewAttachCarryOverBalances(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -733,7 +733,7 @@ class PreviewAttachCarryOverUsages(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -869,7 +869,7 @@ class PreviewAttachParams(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -902,7 +902,7 @@ class PreviewAttachDiscount(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -988,7 +988,7 @@ class PreviewAttachLineItem(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) is_nullable_and_explicitly_set = ( k in nullable_fields and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member @@ -1029,7 +1029,7 @@ class PreviewAttachNextCycleDiscount(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -1115,7 +1115,7 @@ class PreviewAttachNextCycleLineItem(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) is_nullable_and_explicitly_set = ( k in nullable_fields and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member @@ -1184,7 +1184,7 @@ class PreviewAttachUsageLineItem(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) is_nullable_and_explicitly_set = ( k in nullable_fields and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member @@ -1257,6 +1257,10 @@ class PreviewAttachIncomingTypedDict(TypedDict): r"""The feature quantity selections associated with this plan change.""" effective_at: Nullable[float] r"""When this change takes effect, in milliseconds since the Unix epoch, or null if it applies immediately.""" + canceled_at: Nullable[float] + r"""When this plan was canceled, in milliseconds since the Unix epoch, or null if it is not canceled.""" + expires_at: Nullable[float] + r"""When this plan expires, in milliseconds since the Unix epoch, or null if it does not expire.""" plan: NotRequired[PlanTypedDict] @@ -1270,18 +1274,24 @@ class PreviewAttachIncoming(BaseModel): effective_at: Nullable[float] r"""When this change takes effect, in milliseconds since the Unix epoch, or null if it applies immediately.""" + canceled_at: Nullable[float] + r"""When this plan was canceled, in milliseconds since the Unix epoch, or null if it is not canceled.""" + + expires_at: Nullable[float] + r"""When this plan expires, in milliseconds since the Unix epoch, or null if it does not expire.""" + plan: Optional[Plan] = None @model_serializer(mode="wrap") def serialize_model(self, handler): optional_fields = set(["plan"]) - nullable_fields = set(["effective_at"]) + nullable_fields = set(["effective_at", "canceled_at", "expires_at"]) serialized = handler(self) m = {} for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) is_nullable_and_explicitly_set = ( k in nullable_fields and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member @@ -1320,6 +1330,10 @@ class PreviewAttachOutgoingTypedDict(TypedDict): r"""The feature quantity selections associated with this plan change.""" effective_at: Nullable[float] r"""When this change takes effect, in milliseconds since the Unix epoch, or null if it applies immediately.""" + canceled_at: Nullable[float] + r"""When this plan was canceled, in milliseconds since the Unix epoch, or null if it is not canceled.""" + expires_at: Nullable[float] + r"""When this plan expires, in milliseconds since the Unix epoch, or null if it does not expire.""" plan: NotRequired[PlanTypedDict] @@ -1333,18 +1347,24 @@ class PreviewAttachOutgoing(BaseModel): effective_at: Nullable[float] r"""When this change takes effect, in milliseconds since the Unix epoch, or null if it applies immediately.""" + canceled_at: Nullable[float] + r"""When this plan was canceled, in milliseconds since the Unix epoch, or null if it is not canceled.""" + + expires_at: Nullable[float] + r"""When this plan expires, in milliseconds since the Unix epoch, or null if it does not expire.""" + plan: Optional[Plan] = None @model_serializer(mode="wrap") def serialize_model(self, handler): optional_fields = set(["plan"]) - nullable_fields = set(["effective_at"]) + nullable_fields = set(["effective_at", "canceled_at", "expires_at"]) serialized = handler(self) m = {} for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) is_nullable_and_explicitly_set = ( k in nullable_fields and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member @@ -1422,7 +1442,7 @@ class PreviewAttachResponse(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: diff --git a/others/python-sdk/src/autumn_sdk/models/previewmultiattachop.py b/others/python-sdk/src/autumn_sdk/models/previewmultiattachop.py index 187099042..06df124f5 100644 --- a/others/python-sdk/src/autumn_sdk/models/previewmultiattachop.py +++ b/others/python-sdk/src/autumn_sdk/models/previewmultiattachop.py @@ -36,7 +36,7 @@ class PreviewMultiAttachGlobals(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -87,7 +87,7 @@ class PreviewMultiAttachBasePrice(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -136,7 +136,7 @@ class PreviewMultiAttachReset(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -174,7 +174,7 @@ class PreviewMultiAttachTier(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -270,7 +270,7 @@ class PreviewMultiAttachPrice(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -355,7 +355,7 @@ class PreviewMultiAttachRollover(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -417,7 +417,7 @@ class PreviewMultiAttachPlanItem(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -453,7 +453,7 @@ class PreviewMultiAttachCustomize(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) is_nullable_and_explicitly_set = ( k in nullable_fields and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member @@ -501,7 +501,7 @@ class PreviewMultiAttachPlanFeatureQuantity(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -551,7 +551,7 @@ class PreviewMultiAttachPlan(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -599,7 +599,7 @@ class PreviewMultiAttachFreeTrialParams(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -639,7 +639,7 @@ class PreviewMultiAttachInvoiceMode(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -674,7 +674,7 @@ class PreviewMultiAttachAttachDiscount(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -718,7 +718,60 @@ class PreviewMultiAttachSpendLimit(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) + + if val != UNSET_SENTINEL: + if val is not None or k not in optional_fields: + m[k] = val + + return m + + +PreviewMultiAttachThresholdType = Literal[ + "usage", + "usage_percentage", +] +r"""Whether the threshold is an absolute usage count or a percentage of the usage allowance.""" + + +class PreviewMultiAttachUsageAlertTypedDict(TypedDict): + threshold: float + r"""The threshold value that triggers the alert. For usage, this is an absolute count. For usage_percentage, this is a percentage (0-100).""" + threshold_type: PreviewMultiAttachThresholdType + r"""Whether the threshold is an absolute usage count or a percentage of the usage allowance.""" + feature_id: NotRequired[str] + r"""The feature ID this alert applies to. If omitted, the alert applies globally.""" + enabled: NotRequired[bool] + r"""Whether this usage alert is enabled.""" + name: NotRequired[str] + r"""Optional user-defined label to distinguish multiple alerts on the same feature.""" + + +class PreviewMultiAttachUsageAlert(BaseModel): + threshold: float + r"""The threshold value that triggers the alert. For usage, this is an absolute count. For usage_percentage, this is a percentage (0-100).""" + + threshold_type: PreviewMultiAttachThresholdType + r"""Whether the threshold is an absolute usage count or a percentage of the usage allowance.""" + + feature_id: Optional[str] = None + r"""The feature ID this alert applies to. If omitted, the alert applies globally.""" + + enabled: Optional[bool] = True + r"""Whether this usage alert is enabled.""" + + name: Optional[str] = None + r"""Optional user-defined label to distinguish multiple alerts on the same feature.""" + + @model_serializer(mode="wrap") + def serialize_model(self, handler): + optional_fields = set(["feature_id", "enabled", "name"]) + serialized = handler(self) + m = {} + + for n, f in type(self).model_fields.items(): + k = f.alias or n + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -732,6 +785,8 @@ class PreviewMultiAttachBillingControlsTypedDict(TypedDict): spend_limits: NotRequired[List[PreviewMultiAttachSpendLimitTypedDict]] r"""List of overage spend limits per feature.""" + usage_alerts: NotRequired[List[PreviewMultiAttachUsageAlertTypedDict]] + r"""List of usage alert configurations per feature.""" class PreviewMultiAttachBillingControls(BaseModel): @@ -740,15 +795,18 @@ class PreviewMultiAttachBillingControls(BaseModel): spend_limits: Optional[List[PreviewMultiAttachSpendLimit]] = None r"""List of overage spend limits per feature.""" + usage_alerts: Optional[List[PreviewMultiAttachUsageAlert]] = None + r"""List of usage alert configurations per feature.""" + @model_serializer(mode="wrap") def serialize_model(self, handler): - optional_fields = set(["spend_limits"]) + optional_fields = set(["spend_limits", "usage_alerts"]) serialized = handler(self) m = {} for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -784,7 +842,7 @@ class PreviewMultiAttachEntityData(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -877,7 +935,7 @@ class PreviewMultiAttachParams(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) is_nullable_and_explicitly_set = ( k in nullable_fields and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member @@ -918,7 +976,7 @@ class PreviewMultiAttachDiscount(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -1004,7 +1062,7 @@ class PreviewMultiAttachLineItem(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) is_nullable_and_explicitly_set = ( k in nullable_fields and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member @@ -1045,7 +1103,7 @@ class PreviewMultiAttachNextCycleDiscount(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -1131,7 +1189,7 @@ class PreviewMultiAttachNextCycleLineItem(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) is_nullable_and_explicitly_set = ( k in nullable_fields and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member @@ -1200,7 +1258,7 @@ class PreviewMultiAttachUsageLineItem(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) is_nullable_and_explicitly_set = ( k in nullable_fields and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member @@ -1273,6 +1331,10 @@ class PreviewMultiAttachIncomingTypedDict(TypedDict): r"""The feature quantity selections associated with this plan change.""" effective_at: Nullable[float] r"""When this change takes effect, in milliseconds since the Unix epoch, or null if it applies immediately.""" + canceled_at: Nullable[float] + r"""When this plan was canceled, in milliseconds since the Unix epoch, or null if it is not canceled.""" + expires_at: Nullable[float] + r"""When this plan expires, in milliseconds since the Unix epoch, or null if it does not expire.""" plan: NotRequired[PlanTypedDict] @@ -1286,18 +1348,24 @@ class PreviewMultiAttachIncoming(BaseModel): effective_at: Nullable[float] r"""When this change takes effect, in milliseconds since the Unix epoch, or null if it applies immediately.""" + canceled_at: Nullable[float] + r"""When this plan was canceled, in milliseconds since the Unix epoch, or null if it is not canceled.""" + + expires_at: Nullable[float] + r"""When this plan expires, in milliseconds since the Unix epoch, or null if it does not expire.""" + plan: Optional[Plan] = None @model_serializer(mode="wrap") def serialize_model(self, handler): optional_fields = set(["plan"]) - nullable_fields = set(["effective_at"]) + nullable_fields = set(["effective_at", "canceled_at", "expires_at"]) serialized = handler(self) m = {} for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) is_nullable_and_explicitly_set = ( k in nullable_fields and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member @@ -1336,6 +1404,10 @@ class PreviewMultiAttachOutgoingTypedDict(TypedDict): r"""The feature quantity selections associated with this plan change.""" effective_at: Nullable[float] r"""When this change takes effect, in milliseconds since the Unix epoch, or null if it applies immediately.""" + canceled_at: Nullable[float] + r"""When this plan was canceled, in milliseconds since the Unix epoch, or null if it is not canceled.""" + expires_at: Nullable[float] + r"""When this plan expires, in milliseconds since the Unix epoch, or null if it does not expire.""" plan: NotRequired[PlanTypedDict] @@ -1349,18 +1421,24 @@ class PreviewMultiAttachOutgoing(BaseModel): effective_at: Nullable[float] r"""When this change takes effect, in milliseconds since the Unix epoch, or null if it applies immediately.""" + canceled_at: Nullable[float] + r"""When this plan was canceled, in milliseconds since the Unix epoch, or null if it is not canceled.""" + + expires_at: Nullable[float] + r"""When this plan expires, in milliseconds since the Unix epoch, or null if it does not expire.""" + plan: Optional[Plan] = None @model_serializer(mode="wrap") def serialize_model(self, handler): optional_fields = set(["plan"]) - nullable_fields = set(["effective_at"]) + nullable_fields = set(["effective_at", "canceled_at", "expires_at"]) serialized = handler(self) m = {} for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) is_nullable_and_explicitly_set = ( k in nullable_fields and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member @@ -1438,7 +1516,7 @@ class PreviewMultiAttachResponse(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: diff --git a/others/python-sdk/src/autumn_sdk/models/previewupdateop.py b/others/python-sdk/src/autumn_sdk/models/previewupdateop.py index 2c257a59e..0602a85b6 100644 --- a/others/python-sdk/src/autumn_sdk/models/previewupdateop.py +++ b/others/python-sdk/src/autumn_sdk/models/previewupdateop.py @@ -36,7 +36,7 @@ class PreviewUpdateGlobals(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -76,7 +76,7 @@ class PreviewUpdateFeatureQuantityRequest(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -127,7 +127,7 @@ class PreviewUpdateBasePrice(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -176,7 +176,7 @@ class PreviewUpdateReset(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -212,7 +212,7 @@ class PreviewUpdateTier(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -308,7 +308,7 @@ class PreviewUpdatePrice(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -393,7 +393,7 @@ class PreviewUpdateRollover(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -455,7 +455,7 @@ class PreviewUpdatePlanItem(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -503,7 +503,7 @@ class PreviewUpdateFreeTrialParams(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -544,7 +544,7 @@ class PreviewUpdateCustomize(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) is_nullable_and_explicitly_set = ( k in nullable_fields and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member @@ -592,7 +592,7 @@ class PreviewUpdateInvoiceMode(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -624,6 +624,20 @@ PreviewUpdateCancelAction = Literal[ r"""Action to perform for cancellation. 'cancel_immediately' cancels now with prorated refund, 'cancel_end_of_cycle' cancels at period end, 'uncancel' reverses a pending cancellation.""" +class PreviewUpdateRecalculateBalancesTypedDict(TypedDict): + r"""Controls whether balances should be recalculated during the subscription update.""" + + enabled: bool + r"""If true, recalculates balances during the subscription update. Only applicable when updating feature quantities.""" + + +class PreviewUpdateRecalculateBalances(BaseModel): + r"""Controls whether balances should be recalculated during the subscription update.""" + + enabled: bool + r"""If true, recalculates balances during the subscription update. Only applicable when updating feature quantities.""" + + class PreviewUpdateParamsTypedDict(TypedDict): customer_id: str r"""The ID of the customer to attach the plan to.""" @@ -649,6 +663,8 @@ class PreviewUpdateParamsTypedDict(TypedDict): r"""Action to perform for cancellation. 'cancel_immediately' cancels now with prorated refund, 'cancel_end_of_cycle' cancels at period end, 'uncancel' reverses a pending cancellation.""" no_billing_changes: NotRequired[bool] r"""If true, the subscription is updated internally without applying billing changes in Stripe.""" + recalculate_balances: NotRequired[PreviewUpdateRecalculateBalancesTypedDict] + r"""Controls whether balances should be recalculated during the subscription update.""" class PreviewUpdateParams(BaseModel): @@ -688,6 +704,9 @@ class PreviewUpdateParams(BaseModel): no_billing_changes: Optional[bool] = None r"""If true, the subscription is updated internally without applying billing changes in Stripe.""" + recalculate_balances: Optional[PreviewUpdateRecalculateBalances] = None + r"""Controls whether balances should be recalculated during the subscription update.""" + @model_serializer(mode="wrap") def serialize_model(self, handler): optional_fields = set( @@ -703,6 +722,7 @@ class PreviewUpdateParams(BaseModel): "subscription_id", "cancel_action", "no_billing_changes", + "recalculate_balances", ] ) serialized = handler(self) @@ -710,7 +730,7 @@ class PreviewUpdateParams(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -743,7 +763,7 @@ class PreviewUpdateDiscount(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -829,7 +849,7 @@ class PreviewUpdateLineItem(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) is_nullable_and_explicitly_set = ( k in nullable_fields and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member @@ -870,7 +890,7 @@ class PreviewUpdateNextCycleDiscount(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -956,7 +976,7 @@ class PreviewUpdateNextCycleLineItem(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) is_nullable_and_explicitly_set = ( k in nullable_fields and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member @@ -1025,7 +1045,7 @@ class PreviewUpdateUsageLineItem(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) is_nullable_and_explicitly_set = ( k in nullable_fields and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member @@ -1098,6 +1118,10 @@ class PreviewUpdateIncomingTypedDict(TypedDict): r"""The feature quantity selections associated with this plan change.""" effective_at: Nullable[float] r"""When this change takes effect, in milliseconds since the Unix epoch, or null if it applies immediately.""" + canceled_at: Nullable[float] + r"""When this plan was canceled, in milliseconds since the Unix epoch, or null if it is not canceled.""" + expires_at: Nullable[float] + r"""When this plan expires, in milliseconds since the Unix epoch, or null if it does not expire.""" plan: NotRequired[PlanTypedDict] @@ -1111,18 +1135,24 @@ class PreviewUpdateIncoming(BaseModel): effective_at: Nullable[float] r"""When this change takes effect, in milliseconds since the Unix epoch, or null if it applies immediately.""" + canceled_at: Nullable[float] + r"""When this plan was canceled, in milliseconds since the Unix epoch, or null if it is not canceled.""" + + expires_at: Nullable[float] + r"""When this plan expires, in milliseconds since the Unix epoch, or null if it does not expire.""" + plan: Optional[Plan] = None @model_serializer(mode="wrap") def serialize_model(self, handler): optional_fields = set(["plan"]) - nullable_fields = set(["effective_at"]) + nullable_fields = set(["effective_at", "canceled_at", "expires_at"]) serialized = handler(self) m = {} for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) is_nullable_and_explicitly_set = ( k in nullable_fields and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member @@ -1161,6 +1191,10 @@ class PreviewUpdateOutgoingTypedDict(TypedDict): r"""The feature quantity selections associated with this plan change.""" effective_at: Nullable[float] r"""When this change takes effect, in milliseconds since the Unix epoch, or null if it applies immediately.""" + canceled_at: Nullable[float] + r"""When this plan was canceled, in milliseconds since the Unix epoch, or null if it is not canceled.""" + expires_at: Nullable[float] + r"""When this plan expires, in milliseconds since the Unix epoch, or null if it does not expire.""" plan: NotRequired[PlanTypedDict] @@ -1174,18 +1208,24 @@ class PreviewUpdateOutgoing(BaseModel): effective_at: Nullable[float] r"""When this change takes effect, in milliseconds since the Unix epoch, or null if it applies immediately.""" + canceled_at: Nullable[float] + r"""When this plan was canceled, in milliseconds since the Unix epoch, or null if it is not canceled.""" + + expires_at: Nullable[float] + r"""When this plan expires, in milliseconds since the Unix epoch, or null if it does not expire.""" + plan: Optional[Plan] = None @model_serializer(mode="wrap") def serialize_model(self, handler): optional_fields = set(["plan"]) - nullable_fields = set(["effective_at"]) + nullable_fields = set(["effective_at", "canceled_at", "expires_at"]) serialized = handler(self) m = {} for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) is_nullable_and_explicitly_set = ( k in nullable_fields and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member @@ -1279,7 +1319,7 @@ class PreviewUpdateResponse(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: diff --git a/others/python-sdk/src/autumn_sdk/models/redeemreferralcodeop.py b/others/python-sdk/src/autumn_sdk/models/redeemreferralcodeop.py index 2e67e9b95..6f1c6e085 100644 --- a/others/python-sdk/src/autumn_sdk/models/redeemreferralcodeop.py +++ b/others/python-sdk/src/autumn_sdk/models/redeemreferralcodeop.py @@ -28,7 +28,7 @@ class RedeemReferralCodeGlobals(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: diff --git a/others/python-sdk/src/autumn_sdk/models/setuppaymentop.py b/others/python-sdk/src/autumn_sdk/models/setuppaymentop.py index 195e95672..a3f5643d5 100644 --- a/others/python-sdk/src/autumn_sdk/models/setuppaymentop.py +++ b/others/python-sdk/src/autumn_sdk/models/setuppaymentop.py @@ -34,7 +34,7 @@ class SetupPaymentGlobals(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -74,7 +74,7 @@ class SetupPaymentFeatureQuantity(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -125,7 +125,7 @@ class SetupPaymentBasePrice(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -174,7 +174,7 @@ class SetupPaymentReset(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -210,7 +210,7 @@ class SetupPaymentTier(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -306,7 +306,7 @@ class SetupPaymentPrice(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -391,7 +391,7 @@ class SetupPaymentRollover(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -453,7 +453,7 @@ class SetupPaymentPlanItem(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -501,7 +501,7 @@ class SetupPaymentFreeTrialParams(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -542,7 +542,7 @@ class SetupPaymentCustomize(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) is_nullable_and_explicitly_set = ( k in nullable_fields and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member @@ -592,7 +592,7 @@ class SetupPaymentAttachDiscount(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -642,7 +642,7 @@ class SetupPaymentCarryOverBalances(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -677,7 +677,7 @@ class SetupPaymentCarryOverUsages(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -790,7 +790,7 @@ class SetupPaymentParams(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -830,7 +830,7 @@ class SetupPaymentResponse(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: diff --git a/others/python-sdk/src/autumn_sdk/models/trackop.py b/others/python-sdk/src/autumn_sdk/models/trackop.py index e3581f413..a0e92d5bc 100644 --- a/others/python-sdk/src/autumn_sdk/models/trackop.py +++ b/others/python-sdk/src/autumn_sdk/models/trackop.py @@ -30,7 +30,7 @@ class TrackGlobals(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -69,7 +69,7 @@ class TrackLock(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -125,7 +125,7 @@ class TrackParams(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -181,7 +181,7 @@ class TrackResponse(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) is_nullable_and_explicitly_set = ( k in nullable_fields and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member diff --git a/others/python-sdk/src/autumn_sdk/models/updatebalanceop.py b/others/python-sdk/src/autumn_sdk/models/updatebalanceop.py index d69bad2bc..39682e946 100644 --- a/others/python-sdk/src/autumn_sdk/models/updatebalanceop.py +++ b/others/python-sdk/src/autumn_sdk/models/updatebalanceop.py @@ -28,7 +28,7 @@ class UpdateBalanceGlobals(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -124,7 +124,7 @@ class UpdateBalanceParams(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: diff --git a/others/python-sdk/src/autumn_sdk/models/updatecustomerop.py b/others/python-sdk/src/autumn_sdk/models/updatecustomerop.py index 677b65cdf..0b4d17dba 100644 --- a/others/python-sdk/src/autumn_sdk/models/updatecustomerop.py +++ b/others/python-sdk/src/autumn_sdk/models/updatecustomerop.py @@ -37,7 +37,7 @@ class UpdateCustomerGlobals(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -86,7 +86,7 @@ class UpdateCustomerPurchaseLimitRequest(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -132,7 +132,7 @@ class UpdateCustomerAutoTopupRequest(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -168,7 +168,60 @@ class UpdateCustomerSpendLimitRequest(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) + + if val != UNSET_SENTINEL: + if val is not None or k not in optional_fields: + m[k] = val + + return m + + +UpdateCustomerThresholdTypeRequestBody = Literal[ + "usage", + "usage_percentage", +] +r"""Whether the threshold is an absolute usage count or a percentage of the usage allowance.""" + + +class UpdateCustomerUsageAlertRequestBodyTypedDict(TypedDict): + threshold: float + r"""The threshold value that triggers the alert. For usage, this is an absolute count. For usage_percentage, this is a percentage (0-100).""" + threshold_type: UpdateCustomerThresholdTypeRequestBody + r"""Whether the threshold is an absolute usage count or a percentage of the usage allowance.""" + feature_id: NotRequired[str] + r"""The feature ID this alert applies to. If omitted, the alert applies globally.""" + enabled: NotRequired[bool] + r"""Whether this usage alert is enabled.""" + name: NotRequired[str] + r"""Optional user-defined label to distinguish multiple alerts on the same feature.""" + + +class UpdateCustomerUsageAlertRequestBody(BaseModel): + threshold: float + r"""The threshold value that triggers the alert. For usage, this is an absolute count. For usage_percentage, this is a percentage (0-100).""" + + threshold_type: UpdateCustomerThresholdTypeRequestBody + r"""Whether the threshold is an absolute usage count or a percentage of the usage allowance.""" + + feature_id: Optional[str] = None + r"""The feature ID this alert applies to. If omitted, the alert applies globally.""" + + enabled: Optional[bool] = True + r"""Whether this usage alert is enabled.""" + + name: Optional[str] = None + r"""Optional user-defined label to distinguish multiple alerts on the same feature.""" + + @model_serializer(mode="wrap") + def serialize_model(self, handler): + optional_fields = set(["feature_id", "enabled", "name"]) + serialized = handler(self) + m = {} + + for n, f in type(self).model_fields.items(): + k = f.alias or n + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -184,6 +237,8 @@ class UpdateCustomerBillingControlsRequestTypedDict(TypedDict): r"""List of auto top-up configurations per feature.""" spend_limits: NotRequired[List[UpdateCustomerSpendLimitRequestTypedDict]] r"""List of overage spend limits per feature.""" + usage_alerts: NotRequired[List[UpdateCustomerUsageAlertRequestBodyTypedDict]] + r"""List of usage alert configurations per feature.""" class UpdateCustomerBillingControlsRequest(BaseModel): @@ -195,15 +250,18 @@ class UpdateCustomerBillingControlsRequest(BaseModel): spend_limits: Optional[List[UpdateCustomerSpendLimitRequest]] = None r"""List of overage spend limits per feature.""" + usage_alerts: Optional[List[UpdateCustomerUsageAlertRequestBody]] = None + r"""List of usage alert configurations per feature.""" + @model_serializer(mode="wrap") def serialize_model(self, handler): - optional_fields = set(["auto_topups", "spend_limits"]) + optional_fields = set(["auto_topups", "spend_limits", "usage_alerts"]) serialized = handler(self) m = {} for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -281,7 +339,7 @@ class UpdateCustomerParams(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) is_nullable_and_explicitly_set = ( k in nullable_fields and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member @@ -351,7 +409,7 @@ class UpdateCustomerPurchaseLimitResponse(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -397,7 +455,7 @@ class UpdateCustomerAutoTopupResponse(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -433,7 +491,63 @@ class UpdateCustomerSpendLimitResponse(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) + + if val != UNSET_SENTINEL: + if val is not None or k not in optional_fields: + m[k] = val + + return m + + +UpdateCustomerThresholdTypeResponse = Union[ + Literal[ + "usage", + "usage_percentage", + ], + UnrecognizedStr, +] +r"""Whether the threshold is an absolute usage count or a percentage of the usage allowance.""" + + +class UpdateCustomerUsageAlertResponseTypedDict(TypedDict): + threshold: float + r"""The threshold value that triggers the alert. For usage, this is an absolute count. For usage_percentage, this is a percentage (0-100).""" + threshold_type: UpdateCustomerThresholdTypeResponse + r"""Whether the threshold is an absolute usage count or a percentage of the usage allowance.""" + feature_id: NotRequired[str] + r"""The feature ID this alert applies to. If omitted, the alert applies globally.""" + enabled: NotRequired[bool] + r"""Whether this usage alert is enabled.""" + name: NotRequired[str] + r"""Optional user-defined label to distinguish multiple alerts on the same feature.""" + + +class UpdateCustomerUsageAlertResponse(BaseModel): + threshold: float + r"""The threshold value that triggers the alert. For usage, this is an absolute count. For usage_percentage, this is a percentage (0-100).""" + + threshold_type: UpdateCustomerThresholdTypeResponse + r"""Whether the threshold is an absolute usage count or a percentage of the usage allowance.""" + + feature_id: Optional[str] = None + r"""The feature ID this alert applies to. If omitted, the alert applies globally.""" + + enabled: Optional[bool] = True + r"""Whether this usage alert is enabled.""" + + name: Optional[str] = None + r"""Optional user-defined label to distinguish multiple alerts on the same feature.""" + + @model_serializer(mode="wrap") + def serialize_model(self, handler): + optional_fields = set(["feature_id", "enabled", "name"]) + serialized = handler(self) + m = {} + + for n, f in type(self).model_fields.items(): + k = f.alias or n + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -449,6 +563,8 @@ class UpdateCustomerBillingControlsResponseTypedDict(TypedDict): r"""List of auto top-up configurations per feature.""" spend_limits: NotRequired[List[UpdateCustomerSpendLimitResponseTypedDict]] r"""List of overage spend limits per feature.""" + usage_alerts: NotRequired[List[UpdateCustomerUsageAlertResponseTypedDict]] + r"""List of usage alert configurations per feature.""" class UpdateCustomerBillingControlsResponse(BaseModel): @@ -460,15 +576,18 @@ class UpdateCustomerBillingControlsResponse(BaseModel): spend_limits: Optional[List[UpdateCustomerSpendLimitResponse]] = None r"""List of overage spend limits per feature.""" + usage_alerts: Optional[List[UpdateCustomerUsageAlertResponse]] = None + r"""List of usage alert configurations per feature.""" + @model_serializer(mode="wrap") def serialize_model(self, handler): - optional_fields = set(["auto_topups", "spend_limits"]) + optional_fields = set(["auto_topups", "spend_limits", "usage_alerts"]) serialized = handler(self) m = {} for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -576,7 +695,7 @@ class UpdateCustomerSubscription(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) is_nullable_and_explicitly_set = ( k in nullable_fields and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member @@ -629,7 +748,7 @@ class UpdateCustomerPurchase(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) is_nullable_and_explicitly_set = ( k in nullable_fields and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member @@ -699,7 +818,7 @@ class UpdateCustomerDisplay(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) is_nullable_and_explicitly_set = ( k in nullable_fields and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member @@ -772,7 +891,7 @@ class UpdateCustomerFeature(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -819,7 +938,7 @@ class UpdateCustomerFlags(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) is_nullable_and_explicitly_set = ( k in nullable_fields and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member @@ -921,7 +1040,7 @@ class UpdateCustomerResponse(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: m[k] = val diff --git a/others/python-sdk/src/autumn_sdk/models/updateentityop.py b/others/python-sdk/src/autumn_sdk/models/updateentityop.py index 3f7d90a4b..8ac0c6834 100644 --- a/others/python-sdk/src/autumn_sdk/models/updateentityop.py +++ b/others/python-sdk/src/autumn_sdk/models/updateentityop.py @@ -37,7 +37,7 @@ class UpdateEntityGlobals(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -73,7 +73,60 @@ class UpdateEntitySpendLimitRequest(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) + + if val != UNSET_SENTINEL: + if val is not None or k not in optional_fields: + m[k] = val + + return m + + +UpdateEntityThresholdTypeRequestBody = Literal[ + "usage", + "usage_percentage", +] +r"""Whether the threshold is an absolute usage count or a percentage of the usage allowance.""" + + +class UpdateEntityUsageAlertRequestBodyTypedDict(TypedDict): + threshold: float + r"""The threshold value that triggers the alert. For usage, this is an absolute count. For usage_percentage, this is a percentage (0-100).""" + threshold_type: UpdateEntityThresholdTypeRequestBody + r"""Whether the threshold is an absolute usage count or a percentage of the usage allowance.""" + feature_id: NotRequired[str] + r"""The feature ID this alert applies to. If omitted, the alert applies globally.""" + enabled: NotRequired[bool] + r"""Whether this usage alert is enabled.""" + name: NotRequired[str] + r"""Optional user-defined label to distinguish multiple alerts on the same feature.""" + + +class UpdateEntityUsageAlertRequestBody(BaseModel): + threshold: float + r"""The threshold value that triggers the alert. For usage, this is an absolute count. For usage_percentage, this is a percentage (0-100).""" + + threshold_type: UpdateEntityThresholdTypeRequestBody + r"""Whether the threshold is an absolute usage count or a percentage of the usage allowance.""" + + feature_id: Optional[str] = None + r"""The feature ID this alert applies to. If omitted, the alert applies globally.""" + + enabled: Optional[bool] = True + r"""Whether this usage alert is enabled.""" + + name: Optional[str] = None + r"""Optional user-defined label to distinguish multiple alerts on the same feature.""" + + @model_serializer(mode="wrap") + def serialize_model(self, handler): + optional_fields = set(["feature_id", "enabled", "name"]) + serialized = handler(self) + m = {} + + for n, f in type(self).model_fields.items(): + k = f.alias or n + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -87,6 +140,8 @@ class UpdateEntityBillingControlsRequestTypedDict(TypedDict): spend_limits: NotRequired[List[UpdateEntitySpendLimitRequestTypedDict]] r"""List of overage spend limits per feature.""" + usage_alerts: NotRequired[List[UpdateEntityUsageAlertRequestBodyTypedDict]] + r"""List of usage alert configurations per feature.""" class UpdateEntityBillingControlsRequest(BaseModel): @@ -95,15 +150,18 @@ class UpdateEntityBillingControlsRequest(BaseModel): spend_limits: Optional[List[UpdateEntitySpendLimitRequest]] = None r"""List of overage spend limits per feature.""" + usage_alerts: Optional[List[UpdateEntityUsageAlertRequestBody]] = None + r"""List of usage alert configurations per feature.""" + @model_serializer(mode="wrap") def serialize_model(self, handler): - optional_fields = set(["spend_limits"]) + optional_fields = set(["spend_limits", "usage_alerts"]) serialized = handler(self) m = {} for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -139,7 +197,7 @@ class UpdateEntityParams(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -257,7 +315,7 @@ class UpdateEntitySubscription(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) is_nullable_and_explicitly_set = ( k in nullable_fields and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member @@ -310,7 +368,7 @@ class UpdateEntityPurchase(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) is_nullable_and_explicitly_set = ( k in nullable_fields and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member @@ -380,7 +438,7 @@ class UpdateEntityDisplay(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) is_nullable_and_explicitly_set = ( k in nullable_fields and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member @@ -453,7 +511,7 @@ class UpdateEntityFeature(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -500,7 +558,7 @@ class UpdateEntityFlags(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) is_nullable_and_explicitly_set = ( k in nullable_fields and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member @@ -544,7 +602,63 @@ class UpdateEntitySpendLimitResponse(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) + + if val != UNSET_SENTINEL: + if val is not None or k not in optional_fields: + m[k] = val + + return m + + +UpdateEntityThresholdTypeResponse = Union[ + Literal[ + "usage", + "usage_percentage", + ], + UnrecognizedStr, +] +r"""Whether the threshold is an absolute usage count or a percentage of the usage allowance.""" + + +class UpdateEntityUsageAlertResponseTypedDict(TypedDict): + threshold: float + r"""The threshold value that triggers the alert. For usage, this is an absolute count. For usage_percentage, this is a percentage (0-100).""" + threshold_type: UpdateEntityThresholdTypeResponse + r"""Whether the threshold is an absolute usage count or a percentage of the usage allowance.""" + feature_id: NotRequired[str] + r"""The feature ID this alert applies to. If omitted, the alert applies globally.""" + enabled: NotRequired[bool] + r"""Whether this usage alert is enabled.""" + name: NotRequired[str] + r"""Optional user-defined label to distinguish multiple alerts on the same feature.""" + + +class UpdateEntityUsageAlertResponse(BaseModel): + threshold: float + r"""The threshold value that triggers the alert. For usage, this is an absolute count. For usage_percentage, this is a percentage (0-100).""" + + threshold_type: UpdateEntityThresholdTypeResponse + r"""Whether the threshold is an absolute usage count or a percentage of the usage allowance.""" + + feature_id: Optional[str] = None + r"""The feature ID this alert applies to. If omitted, the alert applies globally.""" + + enabled: Optional[bool] = True + r"""Whether this usage alert is enabled.""" + + name: Optional[str] = None + r"""Optional user-defined label to distinguish multiple alerts on the same feature.""" + + @model_serializer(mode="wrap") + def serialize_model(self, handler): + optional_fields = set(["feature_id", "enabled", "name"]) + serialized = handler(self) + m = {} + + for n, f in type(self).model_fields.items(): + k = f.alias or n + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -558,6 +672,8 @@ class UpdateEntityBillingControlsResponseTypedDict(TypedDict): spend_limits: NotRequired[List[UpdateEntitySpendLimitResponseTypedDict]] r"""List of overage spend limits per feature.""" + usage_alerts: NotRequired[List[UpdateEntityUsageAlertResponseTypedDict]] + r"""List of usage alert configurations per feature.""" class UpdateEntityBillingControlsResponse(BaseModel): @@ -566,15 +682,18 @@ class UpdateEntityBillingControlsResponse(BaseModel): spend_limits: Optional[List[UpdateEntitySpendLimitResponse]] = None r"""List of overage spend limits per feature.""" + usage_alerts: Optional[List[UpdateEntityUsageAlertResponse]] = None + r"""List of usage alert configurations per feature.""" + @model_serializer(mode="wrap") def serialize_model(self, handler): - optional_fields = set(["spend_limits"]) + optional_fields = set(["spend_limits", "usage_alerts"]) serialized = handler(self) m = {} for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -631,7 +750,7 @@ class UpdateEntityInvoice(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) is_nullable_and_explicitly_set = ( k in nullable_fields and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member @@ -719,7 +838,7 @@ class UpdateEntityResponse(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) is_nullable_and_explicitly_set = ( k in nullable_fields and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member diff --git a/others/python-sdk/src/autumn_sdk/models/updatefeatureop.py b/others/python-sdk/src/autumn_sdk/models/updatefeatureop.py index 9507c8601..d21c033e2 100644 --- a/others/python-sdk/src/autumn_sdk/models/updatefeatureop.py +++ b/others/python-sdk/src/autumn_sdk/models/updatefeatureop.py @@ -35,7 +35,7 @@ class UpdateFeatureGlobals(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -144,7 +144,7 @@ class UpdateFeatureParams(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -206,7 +206,7 @@ class UpdateFeatureDisplayResponse(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) is_nullable_and_explicitly_set = ( k in nullable_fields and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member @@ -279,7 +279,7 @@ class UpdateFeatureResponse(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: diff --git a/others/python-sdk/src/autumn_sdk/models/updateplanop.py b/others/python-sdk/src/autumn_sdk/models/updateplanop.py index bec31e36d..0ba234f79 100644 --- a/others/python-sdk/src/autumn_sdk/models/updateplanop.py +++ b/others/python-sdk/src/autumn_sdk/models/updateplanop.py @@ -35,7 +35,7 @@ class UpdatePlanGlobals(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -86,7 +86,7 @@ class UpdatePlanBasePrice(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -135,7 +135,7 @@ class UpdatePlanResetRequest(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -171,7 +171,7 @@ class UpdatePlanTier(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -267,7 +267,7 @@ class UpdatePlanPriceRequest(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -352,7 +352,7 @@ class UpdatePlanRolloverRequest(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -414,7 +414,7 @@ class UpdatePlanPlanItem(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -462,7 +462,7 @@ class UpdatePlanFreeTrialParams(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -552,7 +552,7 @@ class UpdatePlanParams(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) is_nullable_and_explicitly_set = ( k in nullable_fields and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member @@ -609,7 +609,7 @@ class UpdatePlanPriceDisplay(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -650,7 +650,7 @@ class UpdatePlanPriceResponse(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -749,7 +749,7 @@ class UpdatePlanFeature(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) is_nullable_and_explicitly_set = ( k in nullable_fields and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member @@ -805,7 +805,7 @@ class UpdatePlanResetResponse(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -898,7 +898,7 @@ class UpdatePlanItemPriceResponse(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) is_nullable_and_explicitly_set = ( k in nullable_fields and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member @@ -941,7 +941,7 @@ class UpdatePlanItemDisplay(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -992,7 +992,7 @@ class UpdatePlanRolloverResponse(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) is_nullable_and_explicitly_set = ( k in nullable_fields and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member @@ -1062,7 +1062,7 @@ class UpdatePlanItem(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) is_nullable_and_explicitly_set = ( k in nullable_fields and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member @@ -1184,7 +1184,7 @@ class UpdatePlanCustomerEligibility(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) if val != UNSET_SENTINEL: if val is not None or k not in optional_fields: @@ -1283,7 +1283,7 @@ class UpdatePlanResponse(BaseModel): for n, f in type(self).model_fields.items(): k = f.alias or n - val = serialized.get(k, serialized.get(n)) + val = serialized.get(k) is_nullable_and_explicitly_set = ( k in nullable_fields and (self.__pydantic_fields_set__.intersection({n})) # pylint: disable=no-member diff --git a/others/python-sdk/src/autumn_sdk/sdk.py b/others/python-sdk/src/autumn_sdk/sdk.py index 2a22c67c7..b31b126ba 100644 --- a/others/python-sdk/src/autumn_sdk/sdk.py +++ b/others/python-sdk/src/autumn_sdk/sdk.py @@ -52,8 +52,8 @@ class Autumn(BaseSDK): secret_key: Union[str, Callable[[], str]], x_api_version: Optional[str] = None, server_idx: Optional[int] = None, - url_params: Optional[Dict[str, str]] = None, server_url: Optional[str] = None, + url_params: Optional[Dict[str, str]] = None, client: Optional[HttpClient] = None, async_client: Optional[AsyncHttpClient] = None, retry_config: OptionalNullable[RetryConfig] = UNSET, diff --git a/others/python-sdk/src/autumn_sdk/utils/__init__.py b/others/python-sdk/src/autumn_sdk/utils/__init__.py index 0498cb8da..15394a08a 100644 --- a/others/python-sdk/src/autumn_sdk/utils/__init__.py +++ b/others/python-sdk/src/autumn_sdk/utils/__init__.py @@ -1,9 +1,10 @@ """Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" -from typing import Any, TYPE_CHECKING, Callable, TypeVar +from typing import TYPE_CHECKING, Callable, TypeVar +from importlib import import_module import asyncio - -from .dynamic_imports import lazy_getattr, lazy_dir +import builtins +import sys _T = TypeVar("_T") @@ -165,11 +166,38 @@ _dynamic_imports: dict[str, str] = { } -def __getattr__(attr_name: str) -> Any: - return lazy_getattr( - attr_name, package=__package__, dynamic_imports=_dynamic_imports - ) +def dynamic_import(modname, retries=3): + for attempt in range(retries): + try: + return import_module(modname, __package__) + except KeyError: + # Clear any half-initialized module and retry + sys.modules.pop(modname, None) + if attempt == retries - 1: + break + raise KeyError(f"Failed to import module '{modname}' after {retries} attempts") + + +def __getattr__(attr_name: str) -> object: + module_name = _dynamic_imports.get(attr_name) + if module_name is None: + raise AttributeError( + f"no {attr_name} found in _dynamic_imports, module name -> {__name__} " + ) + + try: + module = dynamic_import(module_name) + return getattr(module, attr_name) + except ImportError as e: + raise ImportError( + f"Failed to import {attr_name} from {module_name}: {e}" + ) from e + except AttributeError as e: + raise AttributeError( + f"Failed to get {attr_name} from {module_name}: {e}" + ) from e def __dir__(): - return lazy_dir(dynamic_imports=_dynamic_imports) + lazy_attrs = builtins.list(_dynamic_imports.keys()) + return builtins.sorted(lazy_attrs) diff --git a/others/python-sdk/src/autumn_sdk/utils/dynamic_imports.py b/others/python-sdk/src/autumn_sdk/utils/dynamic_imports.py deleted file mode 100644 index 673edf82a..000000000 --- a/others/python-sdk/src/autumn_sdk/utils/dynamic_imports.py +++ /dev/null @@ -1,54 +0,0 @@ -"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" - -from importlib import import_module -import builtins -import sys - - -def dynamic_import(package, modname, retries=3): - """Import a module relative to package, retrying on KeyError from half-initialized modules.""" - for attempt in range(retries): - try: - return import_module(modname, package) - except KeyError: - sys.modules.pop(modname, None) - if attempt == retries - 1: - break - raise KeyError(f"Failed to import module '{modname}' after {retries} attempts") - - -def lazy_getattr(attr_name, *, package, dynamic_imports, sub_packages=None): - """Module-level __getattr__ that lazily loads from a dynamic_imports mapping. - - Args: - attr_name: The attribute being looked up. - package: The caller's __package__ (for relative imports). - dynamic_imports: Dict mapping attribute names to relative module paths. - sub_packages: Optional list of subpackage names to lazy-load. - """ - module_name = dynamic_imports.get(attr_name) - if module_name is not None: - try: - module = dynamic_import(package, module_name) - return getattr(module, attr_name) - except ImportError as e: - raise ImportError( - f"Failed to import {attr_name} from {module_name}: {e}" - ) from e - except AttributeError as e: - raise AttributeError( - f"Failed to get {attr_name} from {module_name}: {e}" - ) from e - - if sub_packages and attr_name in sub_packages: - return import_module(f".{attr_name}", package) - - raise AttributeError(f"module '{package}' has no attribute '{attr_name}'") - - -def lazy_dir(*, dynamic_imports, sub_packages=None): - """Module-level __dir__ that lists lazily-loadable attributes.""" - lazy_attrs = builtins.list(dynamic_imports.keys()) - if sub_packages: - lazy_attrs.extend(sub_packages) - return builtins.sorted(lazy_attrs) diff --git a/others/python-sdk/src/autumn_sdk/utils/eventstreaming.py b/others/python-sdk/src/autumn_sdk/utils/eventstreaming.py index 3bdcd6d3d..f2052fc22 100644 --- a/others/python-sdk/src/autumn_sdk/utils/eventstreaming.py +++ b/others/python-sdk/src/autumn_sdk/utils/eventstreaming.py @@ -32,12 +32,9 @@ class EventStream(Generic[T]): decoder: Callable[[str], T], sentinel: Optional[str] = None, client_ref: Optional[object] = None, - data_required: bool = True, ): self.response = response - self.generator = stream_events( - response, decoder, sentinel, data_required=data_required - ) + self.generator = stream_events(response, decoder, sentinel) self.client_ref = client_ref self._closed = False @@ -71,12 +68,9 @@ class EventStreamAsync(Generic[T]): decoder: Callable[[str], T], sentinel: Optional[str] = None, client_ref: Optional[object] = None, - data_required: bool = True, ): self.response = response - self.generator = stream_events_async( - response, decoder, sentinel, data_required=data_required - ) + self.generator = stream_events_async(response, decoder, sentinel) self.client_ref = client_ref self._closed = False @@ -122,7 +116,6 @@ async def stream_events_async( response: httpx.Response, decoder: Callable[[str], T], sentinel: Optional[str] = None, - data_required: bool = True, ) -> AsyncGenerator[T, None]: buffer = bytearray() position = 0 @@ -145,11 +138,7 @@ async def stream_events_async( block = buffer[position:i] position = i + len(seq) event, discard, event_id = _parse_event( - raw=block, - decoder=decoder, - sentinel=sentinel, - event_id=event_id, - data_required=data_required, + raw=block, decoder=decoder, sentinel=sentinel, event_id=event_id ) if event is not None: yield event @@ -162,11 +151,7 @@ async def stream_events_async( position = 0 event, discard, _ = _parse_event( - raw=buffer, - decoder=decoder, - sentinel=sentinel, - event_id=event_id, - data_required=data_required, + raw=buffer, decoder=decoder, sentinel=sentinel, event_id=event_id ) if event is not None: yield event @@ -176,7 +161,6 @@ def stream_events( response: httpx.Response, decoder: Callable[[str], T], sentinel: Optional[str] = None, - data_required: bool = True, ) -> Generator[T, None, None]: buffer = bytearray() position = 0 @@ -199,11 +183,7 @@ def stream_events( block = buffer[position:i] position = i + len(seq) event, discard, event_id = _parse_event( - raw=block, - decoder=decoder, - sentinel=sentinel, - event_id=event_id, - data_required=data_required, + raw=block, decoder=decoder, sentinel=sentinel, event_id=event_id ) if event is not None: yield event @@ -216,11 +196,7 @@ def stream_events( position = 0 event, discard, _ = _parse_event( - raw=buffer, - decoder=decoder, - sentinel=sentinel, - event_id=event_id, - data_required=data_required, + raw=buffer, decoder=decoder, sentinel=sentinel, event_id=event_id ) if event is not None: yield event @@ -232,7 +208,6 @@ def _parse_event( decoder: Callable[[str], T], sentinel: Optional[str] = None, event_id: Optional[str] = None, - data_required: bool = True, ) -> Tuple[Optional[T], bool, Optional[str]]: block = raw.decode() lines = re.split(r"\r?\n|\r", block) @@ -275,10 +250,6 @@ def _parse_event( if sentinel and data == f"{sentinel}\n": return None, True, event_id - # Skip data-less events when data is required - if not data and publish and data_required: - return None, False, event_id - if data: data = data[:-1] try: diff --git a/others/python-sdk/src/autumn_sdk/utils/retries.py b/others/python-sdk/src/autumn_sdk/utils/retries.py index af07d4e94..88a91b10c 100644 --- a/others/python-sdk/src/autumn_sdk/utils/retries.py +++ b/others/python-sdk/src/autumn_sdk/utils/retries.py @@ -144,7 +144,12 @@ def retry(func, retries: Retries): if res.status_code == parsed_code: raise TemporaryError(res) - except (httpx.NetworkError, httpx.TimeoutException) as exception: + except httpx.ConnectError as exception: + if retries.config.retry_connection_errors: + raise + + raise PermanentError(exception) from exception + except httpx.TimeoutException as exception: if retries.config.retry_connection_errors: raise @@ -188,7 +193,12 @@ async def retry_async(func, retries: Retries): if res.status_code == parsed_code: raise TemporaryError(res) - except (httpx.NetworkError, httpx.TimeoutException) as exception: + except httpx.ConnectError as exception: + if retries.config.retry_connection_errors: + raise + + raise PermanentError(exception) from exception + except httpx.TimeoutException as exception: if retries.config.retry_connection_errors: raise diff --git a/package.json b/package.json index caf6fa971..1fecf8082 100644 --- a/package.json +++ b/package.json @@ -92,6 +92,8 @@ "knip:fix-all": "knip --fix --allow-remove-files", "prepare": "husky", "api": "cd packages/openapi && bun generate", + "svix:push": "infisical run --env=dev -- bun packages/openapi/scripts/svixPush.ts", + "svix:push:prod": "infisical run --env=prod -- bun packages/openapi/scripts/svixPush.ts", "docs:pull": "bun -F @autumn/docs pull", "docs": "bun -F @autumn/docs dev", "docs:build": "bun -F @autumn/docs build", diff --git a/packages/autumn-js/src/generated/getOrCreateCustomerSchemas.ts b/packages/autumn-js/src/generated/getOrCreateCustomerSchemas.ts index d91e98d4f..6c355b30c 100644 --- a/packages/autumn-js/src/generated/getOrCreateCustomerSchemas.ts +++ b/packages/autumn-js/src/generated/getOrCreateCustomerSchemas.ts @@ -33,6 +33,14 @@ export const getOrCreateCustomerSpendLimitOutboundSchema = z.object({ overage_limit: z.union([z.number(), z.undefined()]).optional(), }); +export const getOrCreateCustomerUsageAlertOutboundSchema = z.object({ + feature_id: z.union([z.string(), z.undefined()]).optional(), + enabled: z.boolean(), + threshold: z.number(), + threshold_type: z.string(), + name: z.union([z.string(), z.undefined()]).optional(), +}); + export const getOrCreateCustomerBillingControlsOutboundSchema = z.object({ auto_topups: z .union([z.array(getOrCreateCustomerAutoTopupOutboundSchema), z.undefined()]) @@ -43,6 +51,12 @@ export const getOrCreateCustomerBillingControlsOutboundSchema = z.object({ z.undefined(), ]) .optional(), + usage_alerts: z + .union([ + z.array(getOrCreateCustomerUsageAlertOutboundSchema), + z.undefined(), + ]) + .optional(), }); export const getOrCreateCustomerParamsOutboundSchema = z.object({ @@ -84,6 +98,16 @@ export const getOrCreateCustomerAutoTopupSchema = z.object({ .optional(), }); +export const getOrCreateCustomerThresholdTypeSchema = closedEnumSchema; + +export const getOrCreateCustomerUsageAlertSchema = z.object({ + featureId: z.union([z.string(), z.undefined()]).optional(), + enabled: z.union([z.boolean(), z.undefined()]).optional(), + threshold: z.number(), + thresholdType: getOrCreateCustomerThresholdTypeSchema, + name: z.union([z.string(), z.undefined()]).optional(), +}); + export const getOrCreateCustomerBillingControlsSchema = z.object({ autoTopups: z .union([z.array(getOrCreateCustomerAutoTopupSchema), z.undefined()]) @@ -91,6 +115,9 @@ export const getOrCreateCustomerBillingControlsSchema = z.object({ spendLimits: z .union([z.array(getOrCreateCustomerSpendLimitSchema), z.undefined()]) .optional(), + usageAlerts: z + .union([z.array(getOrCreateCustomerUsageAlertSchema), z.undefined()]) + .optional(), }); export const getOrCreateCustomerParamsSchema = z.object({ diff --git a/packages/autumn-js/src/generated/multiAttachSchemas.ts b/packages/autumn-js/src/generated/multiAttachSchemas.ts index cd501de02..8a1bea4ff 100644 --- a/packages/autumn-js/src/generated/multiAttachSchemas.ts +++ b/packages/autumn-js/src/generated/multiAttachSchemas.ts @@ -36,20 +36,6 @@ export const multiAttachSpendLimitSchema = z.object({ overageLimit: z.union([z.number(), z.undefined()]).optional(), }); -export const multiAttachBillingControlsSchema = z.object({ - spendLimits: z - .union([z.array(multiAttachSpendLimitSchema), z.undefined()]) - .optional(), -}); - -export const multiAttachEntityDataSchema = z.object({ - featureId: z.string(), - name: z.union([z.string(), z.undefined()]).optional(), - billingControls: z - .union([multiAttachBillingControlsSchema, z.undefined()]) - .optional(), -}); - export const multiAttachInvoiceSchema = z.object({ status: z.string().nullable(), stripeId: z.string(), @@ -166,10 +152,21 @@ export const multiAttachSpendLimitOutboundSchema = z.object({ overage_limit: z.union([z.number(), z.undefined()]).optional(), }); +export const multiAttachUsageAlertOutboundSchema = z.object({ + feature_id: z.union([z.string(), z.undefined()]).optional(), + enabled: z.boolean(), + threshold: z.number(), + threshold_type: z.string(), + name: z.union([z.string(), z.undefined()]).optional(), +}); + export const multiAttachBillingControlsOutboundSchema = z.object({ spend_limits: z .union([z.array(multiAttachSpendLimitOutboundSchema), z.undefined()]) .optional(), + usage_alerts: z + .union([z.array(multiAttachUsageAlertOutboundSchema), z.undefined()]) + .optional(), }); export const multiAttachEntityDataOutboundSchema = z.object({ @@ -281,6 +278,33 @@ export const multiAttachFreeTrialParamsSchema = z.object({ export const multiAttachRedirectModeSchema = closedEnumSchema; +export const multiAttachThresholdTypeSchema = closedEnumSchema; + +export const multiAttachUsageAlertSchema = z.object({ + featureId: z.union([z.string(), z.undefined()]).optional(), + enabled: z.union([z.boolean(), z.undefined()]).optional(), + threshold: z.number(), + thresholdType: multiAttachThresholdTypeSchema, + name: z.union([z.string(), z.undefined()]).optional(), +}); + +export const multiAttachBillingControlsSchema = z.object({ + spendLimits: z + .union([z.array(multiAttachSpendLimitSchema), z.undefined()]) + .optional(), + usageAlerts: z + .union([z.array(multiAttachUsageAlertSchema), z.undefined()]) + .optional(), +}); + +export const multiAttachEntityDataSchema = z.object({ + featureId: z.string(), + name: z.union([z.string(), z.undefined()]).optional(), + billingControls: z + .union([multiAttachBillingControlsSchema, z.undefined()]) + .optional(), +}); + export const multiAttachParamsSchema = z.object({ customerId: z.string(), entityId: z.union([z.string(), z.undefined()]).optional(), diff --git a/packages/autumn-js/src/generated/previewAttachSchemas.ts b/packages/autumn-js/src/generated/previewAttachSchemas.ts index 5ae0bb781..8d47c706a 100644 --- a/packages/autumn-js/src/generated/previewAttachSchemas.ts +++ b/packages/autumn-js/src/generated/previewAttachSchemas.ts @@ -425,6 +425,8 @@ export const previewAttachIncomingSchema = z.object({ plan: z.union([planSchema, z.undefined()]).optional(), featureQuantities: z.array(previewAttachIncomingFeatureQuantitySchema), effectiveAt: z.number().nullable(), + canceledAt: z.number().nullable(), + expiresAt: z.number().nullable(), }); export const previewAttachOutgoingSchema = z.object({ @@ -432,6 +434,8 @@ export const previewAttachOutgoingSchema = z.object({ plan: z.union([planSchema, z.undefined()]).optional(), featureQuantities: z.array(previewAttachOutgoingFeatureQuantitySchema), effectiveAt: z.number().nullable(), + canceledAt: z.number().nullable(), + expiresAt: z.number().nullable(), }); export const previewAttachResponseSchema = z.object({ diff --git a/packages/autumn-js/src/generated/previewMultiAttachSchemas.ts b/packages/autumn-js/src/generated/previewMultiAttachSchemas.ts index 1cad6613d..72c523cea 100644 --- a/packages/autumn-js/src/generated/previewMultiAttachSchemas.ts +++ b/packages/autumn-js/src/generated/previewMultiAttachSchemas.ts @@ -36,20 +36,6 @@ export const previewMultiAttachSpendLimitSchema = z.object({ overageLimit: z.union([z.number(), z.undefined()]).optional(), }); -export const previewMultiAttachBillingControlsSchema = z.object({ - spendLimits: z - .union([z.array(previewMultiAttachSpendLimitSchema), z.undefined()]) - .optional(), -}); - -export const previewMultiAttachEntityDataSchema = z.object({ - featureId: z.string(), - name: z.union([z.string(), z.undefined()]).optional(), - billingControls: z - .union([previewMultiAttachBillingControlsSchema, z.undefined()]) - .optional(), -}); - export const previewMultiAttachDiscountSchema = z.object({ amountOff: z.number(), percentOff: z.union([z.number(), z.undefined()]).optional(), @@ -256,10 +242,21 @@ export const previewMultiAttachSpendLimitOutboundSchema = z.object({ overage_limit: z.union([z.number(), z.undefined()]).optional(), }); +export const previewMultiAttachUsageAlertOutboundSchema = z.object({ + feature_id: z.union([z.string(), z.undefined()]).optional(), + enabled: z.boolean(), + threshold: z.number(), + threshold_type: z.string(), + name: z.union([z.string(), z.undefined()]).optional(), +}); + export const previewMultiAttachBillingControlsOutboundSchema = z.object({ spend_limits: z .union([z.array(previewMultiAttachSpendLimitOutboundSchema), z.undefined()]) .optional(), + usage_alerts: z + .union([z.array(previewMultiAttachUsageAlertOutboundSchema), z.undefined()]) + .optional(), }); export const previewMultiAttachEntityDataOutboundSchema = z.object({ @@ -382,6 +379,33 @@ export const previewMultiAttachFreeTrialParamsSchema = z.object({ export const previewMultiAttachRedirectModeSchema = closedEnumSchema; +export const previewMultiAttachThresholdTypeSchema = closedEnumSchema; + +export const previewMultiAttachUsageAlertSchema = z.object({ + featureId: z.union([z.string(), z.undefined()]).optional(), + enabled: z.union([z.boolean(), z.undefined()]).optional(), + threshold: z.number(), + thresholdType: previewMultiAttachThresholdTypeSchema, + name: z.union([z.string(), z.undefined()]).optional(), +}); + +export const previewMultiAttachBillingControlsSchema = z.object({ + spendLimits: z + .union([z.array(previewMultiAttachSpendLimitSchema), z.undefined()]) + .optional(), + usageAlerts: z + .union([z.array(previewMultiAttachUsageAlertSchema), z.undefined()]) + .optional(), +}); + +export const previewMultiAttachEntityDataSchema = z.object({ + featureId: z.string(), + name: z.union([z.string(), z.undefined()]).optional(), + billingControls: z + .union([previewMultiAttachBillingControlsSchema, z.undefined()]) + .optional(), +}); + export const previewMultiAttachParamsSchema = z.object({ customerId: z.string(), entityId: z.union([z.string(), z.undefined()]).optional(), @@ -415,6 +439,8 @@ export const previewMultiAttachIncomingSchema = z.object({ plan: z.union([planSchema, z.undefined()]).optional(), featureQuantities: z.array(previewMultiAttachIncomingFeatureQuantitySchema), effectiveAt: z.number().nullable(), + canceledAt: z.number().nullable(), + expiresAt: z.number().nullable(), }); export const previewMultiAttachOutgoingSchema = z.object({ @@ -422,6 +448,8 @@ export const previewMultiAttachOutgoingSchema = z.object({ plan: z.union([planSchema, z.undefined()]).optional(), featureQuantities: z.array(previewMultiAttachOutgoingFeatureQuantitySchema), effectiveAt: z.number().nullable(), + canceledAt: z.number().nullable(), + expiresAt: z.number().nullable(), }); export const previewMultiAttachResponseSchema = z.object({ diff --git a/packages/autumn-js/src/generated/previewUpdateSubscriptionSchemas.ts b/packages/autumn-js/src/generated/previewUpdateSubscriptionSchemas.ts index 7078c7f24..b5bf1c187 100644 --- a/packages/autumn-js/src/generated/previewUpdateSubscriptionSchemas.ts +++ b/packages/autumn-js/src/generated/previewUpdateSubscriptionSchemas.ts @@ -25,6 +25,10 @@ export const previewUpdateInvoiceModeSchema = z.object({ finalize: z.union([z.boolean(), z.undefined()]).optional(), }); +export const previewUpdateRecalculateBalancesSchema = z.object({ + enabled: z.boolean(), +}); + export const previewUpdateDiscountSchema = z.object({ amountOff: z.number(), percentOff: z.union([z.number(), z.undefined()]).optional(), @@ -202,6 +206,10 @@ export const previewUpdateInvoiceModeOutboundSchema = z.object({ finalize: z.boolean(), }); +export const previewUpdateRecalculateBalancesOutboundSchema = z.object({ + enabled: z.boolean(), +}); + export const previewUpdateParamsOutboundSchema = z.object({ customer_id: z.string(), entity_id: z.union([z.string(), z.undefined()]).optional(), @@ -224,6 +232,9 @@ export const previewUpdateParamsOutboundSchema = z.object({ subscription_id: z.union([z.string(), z.undefined()]).optional(), cancel_action: z.union([z.string(), z.undefined()]).optional(), no_billing_changes: z.union([z.boolean(), z.undefined()]).optional(), + recalculate_balances: z + .union([previewUpdateRecalculateBalancesOutboundSchema, z.undefined()]) + .optional(), }); const closedEnumSchema = z.any(); @@ -346,6 +357,9 @@ export const previewUpdateParamsSchema = z.object({ .union([previewUpdateCancelActionSchema, z.undefined()]) .optional(), noBillingChanges: z.union([z.boolean(), z.undefined()]).optional(), + recalculateBalances: z + .union([previewUpdateRecalculateBalancesSchema, z.undefined()]) + .optional(), }); export const previewUpdateIncomingSchema = z.object({ @@ -353,6 +367,8 @@ export const previewUpdateIncomingSchema = z.object({ plan: z.union([planSchema, z.undefined()]).optional(), featureQuantities: z.array(previewUpdateIncomingFeatureQuantitySchema), effectiveAt: z.number().nullable(), + canceledAt: z.number().nullable(), + expiresAt: z.number().nullable(), }); export const previewUpdateOutgoingSchema = z.object({ @@ -360,6 +376,8 @@ export const previewUpdateOutgoingSchema = z.object({ plan: z.union([planSchema, z.undefined()]).optional(), featureQuantities: z.array(previewUpdateOutgoingFeatureQuantitySchema), effectiveAt: z.number().nullable(), + canceledAt: z.number().nullable(), + expiresAt: z.number().nullable(), }); export const intentSchema = openEnumSchema; diff --git a/packages/autumn-js/src/generated/updateSubscriptionSchemas.ts b/packages/autumn-js/src/generated/updateSubscriptionSchemas.ts index 609856c01..b99dca46b 100644 --- a/packages/autumn-js/src/generated/updateSubscriptionSchemas.ts +++ b/packages/autumn-js/src/generated/updateSubscriptionSchemas.ts @@ -25,6 +25,10 @@ export const billingUpdateInvoiceModeSchema = z.object({ finalize: z.union([z.boolean(), z.undefined()]).optional(), }); +export const billingUpdateRecalculateBalancesSchema = z.object({ + enabled: z.boolean(), +}); + export const billingUpdateInvoiceSchema = z.object({ status: z.string().nullable(), stripeId: z.string(), @@ -122,6 +126,10 @@ export const billingUpdateInvoiceModeOutboundSchema = z.object({ finalize: z.boolean(), }); +export const billingUpdateRecalculateBalancesOutboundSchema = z.object({ + enabled: z.boolean(), +}); + export const updateSubscriptionParamsOutboundSchema = z.object({ customer_id: z.string(), entity_id: z.union([z.string(), z.undefined()]).optional(), @@ -141,6 +149,9 @@ export const updateSubscriptionParamsOutboundSchema = z.object({ subscription_id: z.union([z.string(), z.undefined()]).optional(), cancel_action: z.union([z.string(), z.undefined()]).optional(), no_billing_changes: z.union([z.boolean(), z.undefined()]).optional(), + recalculate_balances: z + .union([billingUpdateRecalculateBalancesOutboundSchema, z.undefined()]) + .optional(), }); const closedEnumSchema = z.any(); @@ -261,6 +272,9 @@ export const updateSubscriptionParamsSchema = z.object({ .union([billingUpdateCancelActionSchema, z.undefined()]) .optional(), noBillingChanges: z.union([z.boolean(), z.undefined()]).optional(), + recalculateBalances: z + .union([billingUpdateRecalculateBalancesSchema, z.undefined()]) + .optional(), }); export const billingUpdateCodeSchema = openEnumSchema; diff --git a/packages/openapi/openapi-stripped.yml b/packages/openapi/openapi-stripped.yml index 49a935195..131c6dde6 100644 --- a/packages/openapi/openapi-stripped.yml +++ b/packages/openapi/openapi-stripped.yml @@ -86,6 +86,7 @@ components: - day - week - month + type: string description: The time interval for the purchase limit window. interval_count: type: number @@ -122,6 +123,40 @@ components: minimum: 0 description: Maximum allowed overage spend for the target feature. description: List of overage spend limits per feature. + usage_alerts: + type: array + items: + type: object + properties: + feature_id: + type: string + description: The feature ID this alert applies to. If omitted, the alert applies + globally. + enabled: + type: boolean + default: true + description: Whether this usage alert is enabled. + threshold: + type: number + minimum: 0 + description: The threshold value that triggers the alert. For usage, this is an + absolute count. For usage_percentage, this is a percentage + (0-100). + threshold_type: + enum: + - usage + - usage_percentage + type: string + description: Whether the threshold is an absolute usage count or a percentage of + the usage allowance. + name: + type: string + description: Optional user-defined label to distinguish multiple alerts on the + same feature. + required: + - threshold + - threshold_type + description: List of usage alert configurations per feature. description: Billing controls for the customer (auto top-ups, etc.) title: CustomerData description: Customer details to set when creating a customer @@ -137,6 +172,7 @@ components: - purchases.plan - balances.feature - flags.feature + type: string title: CustomerExpand Customer: type: object @@ -174,6 +210,7 @@ components: enum: - sandbox - live + type: string description: The environment this customer was created in. metadata: type: object @@ -216,6 +253,7 @@ components: - day - week - month + type: string description: The time interval for the purchase limit window. interval_count: type: number @@ -252,6 +290,40 @@ components: minimum: 0 description: Maximum allowed overage spend for the target feature. description: List of overage spend limits per feature. + usage_alerts: + type: array + items: + type: object + properties: + feature_id: + type: string + description: The feature ID this alert applies to. If omitted, the alert applies + globally. + enabled: + type: boolean + default: true + description: Whether this usage alert is enabled. + threshold: + type: number + minimum: 0 + description: The threshold value that triggers the alert. For usage, this is an + absolute count. For usage_percentage, this is a percentage + (0-100). + threshold_type: + enum: + - usage + - usage_percentage + type: string + description: Whether the threshold is an absolute usage count or a percentage of + the usage allowance. + name: + type: string + description: Optional user-defined label to distinguish multiple alerts on the + same feature. + required: + - threshold + - threshold_type + description: List of usage alert configurations per feature. description: Billing controls for the customer (auto top-ups, etc.) subscriptions: type: array @@ -279,6 +351,7 @@ components: enum: - active - scheduled + type: string description: Current status of the subscription. past_due: type: boolean @@ -406,6 +479,7 @@ components: - boolean - metered - credit_system + type: string description: "Feature type: 'boolean' for on/off access, 'metered' for usage-tracked features, 'credit_system' for unified credit pools." @@ -543,6 +617,7 @@ components: enum: - sandbox - live + type: string description: The environment (sandbox/live) required: - id @@ -588,6 +663,7 @@ components: - fixed_discount - free_product - invoice_credits + type: string description: The type of reward discount_value: type: number @@ -597,6 +673,7 @@ components: - one_off - months - forever + type: string description: How long the discount lasts duration_value: anyOf: @@ -795,6 +872,7 @@ components: - quarter - semi_annual - year + type: string description: Billing interval (e.g. 'month', 'year'). interval_count: type: number @@ -844,6 +922,7 @@ components: - single_use - continuous_use - credit_system + type: string description: The type of the feature display: anyOf: @@ -908,6 +987,7 @@ components: - quarter - semi_annual - year + type: string description: The interval at which the feature balance resets (e.g. 'month', 'year'). For consumable features, usage resets to 0 and included units are restored. @@ -941,6 +1021,7 @@ components: enum: - graduated - volume + type: string interval: enum: - one_off @@ -949,6 +1030,7 @@ components: - quarter - semi_annual - year + type: string description: Billing interval for this price. For consumable features, should match reset.interval. interval_count: @@ -963,6 +1045,7 @@ components: enum: - prepaid - usage_based + type: string description: "'prepaid' for features like seats where customers pay upfront, 'usage_based' for pay-as-you-go after included usage." max_purchase: @@ -1005,6 +1088,7 @@ components: enum: - month - forever + type: string description: When rolled over units expire. expiry_duration_length: type: number @@ -1033,6 +1117,7 @@ components: - day - month - year + type: string description: Unit of time for the trial duration ('day', 'month', 'year'). card_required: type: boolean @@ -1051,6 +1136,7 @@ components: enum: - sandbox - live + type: string description: Environment this plan belongs to ('sandbox' or 'live'). archived: type: boolean @@ -1073,6 +1159,7 @@ components: enum: - active - scheduled + type: string description: The customer's current status with this plan. 'active' if attached, 'scheduled' if pending activation. canceling: @@ -1089,6 +1176,7 @@ components: - downgrade - none - purchase + type: string description: The action that would occur if this plan were attached to the customer. required: @@ -1128,6 +1216,7 @@ components: - boolean - metered - credit_system + type: string description: "Feature type: 'boolean' for on/off access, 'metered' for usage-tracked features, 'credit_system' for unified credit pools." @@ -1257,6 +1346,7 @@ components: - quarter - semi_annual - year + type: string - const: multiple description: The reset interval (hour, day, week, month, etc.) or 'multiple' if combined from different intervals. @@ -1291,6 +1381,7 @@ components: enum: - graduated - volume + type: string description: "How tiers are applied: graduated (split across bands) or volume (flat rate for the matched tier)." billing_units: @@ -1300,6 +1391,7 @@ components: enum: - prepaid - usage_based + type: string description: Whether usage is prepaid or billed pay-per-use. max_purchase: anyOf: @@ -1476,6 +1568,7 @@ paths: - day - week - month + type: string description: The time interval for the purchase limit window. interval_count: type: number @@ -1512,6 +1605,40 @@ paths: minimum: 0 description: Maximum allowed overage spend for the target feature. description: List of overage spend limits per feature. + usage_alerts: + type: array + items: + type: object + properties: + feature_id: + type: string + description: The feature ID this alert applies to. If omitted, the alert applies + globally. + enabled: + type: boolean + default: true + description: Whether this usage alert is enabled. + threshold: + type: number + minimum: 0 + description: The threshold value that triggers the alert. For usage, this is an + absolute count. For usage_percentage, this is a + percentage (0-100). + threshold_type: + enum: + - usage + - usage_percentage + type: string + description: Whether the threshold is an absolute usage count or a percentage of + the usage allowance. + name: + type: string + description: Optional user-defined label to distinguish multiple alerts on the + same feature. + required: + - threshold + - threshold_type + description: List of usage alert configurations per feature. description: Billing controls for the customer (auto top-ups, etc.) expand: type: array @@ -1591,6 +1718,7 @@ paths: enum: - active - scheduled + type: string description: Filter by customer product status. Defaults to active and scheduled search: type: string @@ -1648,6 +1776,7 @@ paths: enum: - sandbox - live + type: string description: The environment this customer was created in. metadata: type: object @@ -1690,6 +1819,7 @@ paths: - day - week - month + type: string description: The time interval for the purchase limit window. interval_count: type: number @@ -1726,6 +1856,40 @@ paths: minimum: 0 description: Maximum allowed overage spend for the target feature. description: List of overage spend limits per feature. + usage_alerts: + type: array + items: + type: object + properties: + feature_id: + type: string + description: The feature ID this alert applies to. If omitted, the alert applies + globally. + enabled: + type: boolean + default: true + description: Whether this usage alert is enabled. + threshold: + type: number + minimum: 0 + description: The threshold value that triggers the alert. For usage, this is an + absolute count. For usage_percentage, this + is a percentage (0-100). + threshold_type: + enum: + - usage + - usage_percentage + type: string + description: Whether the threshold is an absolute usage count or a percentage of + the usage allowance. + name: + type: string + description: Optional user-defined label to distinguish multiple alerts on the + same feature. + required: + - threshold + - threshold_type + description: List of usage alert configurations per feature. description: Billing controls for the customer (auto top-ups, etc.) subscriptions: type: array @@ -1753,6 +1917,7 @@ paths: enum: - active - scheduled + type: string description: Current status of the subscription. past_due: type: boolean @@ -1881,6 +2046,7 @@ paths: - boolean - metered - credit_system + type: string description: "Feature type: 'boolean' for on/off access, 'metered' for usage-tracked features, 'credit_system' for unified credit pools." @@ -2185,6 +2351,7 @@ paths: - day - week - month + type: string description: The time interval for the purchase limit window. interval_count: type: number @@ -2221,6 +2388,40 @@ paths: minimum: 0 description: Maximum allowed overage spend for the target feature. description: List of overage spend limits per feature. + usage_alerts: + type: array + items: + type: object + properties: + feature_id: + type: string + description: The feature ID this alert applies to. If omitted, the alert applies + globally. + enabled: + type: boolean + default: true + description: Whether this usage alert is enabled. + threshold: + type: number + minimum: 0 + description: The threshold value that triggers the alert. For usage, this is an + absolute count. For usage_percentage, this is a + percentage (0-100). + threshold_type: + enum: + - usage + - usage_percentage + type: string + description: Whether the threshold is an absolute usage count or a percentage of + the usage allowance. + name: + type: string + description: Optional user-defined label to distinguish multiple alerts on the + same feature. + required: + - threshold + - threshold_type + description: List of usage alert configurations per feature. description: Billing controls for the customer (auto top-ups, etc.) new_customer_id: $ref: "#/components/schemas/CustomerId" @@ -2275,6 +2476,7 @@ paths: enum: - sandbox - live + type: string description: The environment this customer was created in. metadata: type: object @@ -2317,6 +2519,7 @@ paths: - day - week - month + type: string description: The time interval for the purchase limit window. interval_count: type: number @@ -2353,6 +2556,40 @@ paths: minimum: 0 description: Maximum allowed overage spend for the target feature. description: List of overage spend limits per feature. + usage_alerts: + type: array + items: + type: object + properties: + feature_id: + type: string + description: The feature ID this alert applies to. If omitted, the alert applies + globally. + enabled: + type: boolean + default: true + description: Whether this usage alert is enabled. + threshold: + type: number + minimum: 0 + description: The threshold value that triggers the alert. For usage, this is an + absolute count. For usage_percentage, this is a + percentage (0-100). + threshold_type: + enum: + - usage + - usage_percentage + type: string + description: Whether the threshold is an absolute usage count or a percentage of + the usage allowance. + name: + type: string + description: Optional user-defined label to distinguish multiple alerts on the + same feature. + required: + - threshold + - threshold_type + description: List of usage alert configurations per feature. description: Billing controls for the customer (auto top-ups, etc.) subscriptions: type: array @@ -2380,6 +2617,7 @@ paths: enum: - active - scheduled + type: string description: Current status of the subscription. past_due: type: boolean @@ -2508,6 +2746,7 @@ paths: - boolean - metered - credit_system + type: string description: "Feature type: 'boolean' for on/off access, 'metered' for usage-tracked features, 'credit_system' for unified credit pools." @@ -2758,6 +2997,7 @@ paths: - quarter - semi_annual - year + type: string description: Billing interval (e.g. 'month', 'year'). interval_count: type: number @@ -2796,6 +3036,7 @@ paths: - quarter - semi_annual - year + type: string description: Interval at which balance resets (e.g. 'month', 'year'). For consumable features only. interval_count: @@ -2832,6 +3073,7 @@ paths: enum: - graduated - volume + type: string interval: enum: - one_off @@ -2840,6 +3082,7 @@ paths: - quarter - semi_annual - year + type: string description: Billing interval. For consumable features, should match reset.interval. interval_count: @@ -2855,6 +3098,7 @@ paths: enum: - prepaid - usage_based + type: string description: "'prepaid' for upfront payment (seats), 'usage_based' for pay-as-you-go." max_purchase: @@ -2874,6 +3118,7 @@ paths: - prorate_immediately - prorate_next_cycle - bill_next_cycle + type: string description: Billing behavior when quantity increases mid-cycle. on_decrease: enum: @@ -2882,6 +3127,7 @@ paths: - prorate_next_cycle - none - no_prorations + type: string description: Credit behavior when quantity decreases mid-cycle. required: - on_increase @@ -2898,6 +3144,7 @@ paths: enum: - month - forever + type: string description: When rolled over units expire. expiry_duration_length: type: number @@ -2924,6 +3171,7 @@ paths: - day - month - year + type: string default: month description: Unit of time for the trial ('day', 'month', 'year'). card_required: @@ -3030,6 +3278,7 @@ paths: - quarter - semi_annual - year + type: string description: Billing interval (e.g. 'month', 'year'). interval_count: type: number @@ -3079,6 +3328,7 @@ paths: - single_use - continuous_use - credit_system + type: string description: The type of the feature display: anyOf: @@ -3143,6 +3393,7 @@ paths: - quarter - semi_annual - year + type: string description: The interval at which the feature balance resets (e.g. 'month', 'year'). For consumable features, usage resets to 0 and included units are restored. @@ -3176,6 +3427,7 @@ paths: enum: - graduated - volume + type: string interval: enum: - one_off @@ -3184,6 +3436,7 @@ paths: - quarter - semi_annual - year + type: string description: Billing interval for this price. For consumable features, should match reset.interval. interval_count: @@ -3199,6 +3452,7 @@ paths: enum: - prepaid - usage_based + type: string description: "'prepaid' for features like seats where customers pay upfront, 'usage_based' for pay-as-you-go after included usage." @@ -3242,6 +3496,7 @@ paths: enum: - month - forever + type: string description: When rolled over units expire. expiry_duration_length: type: number @@ -3270,6 +3525,7 @@ paths: - day - month - year + type: string description: Unit of time for the trial duration ('day', 'month', 'year'). card_required: type: boolean @@ -3288,6 +3544,7 @@ paths: enum: - sandbox - live + type: string description: Environment this plan belongs to ('sandbox' or 'live'). archived: type: boolean @@ -3310,6 +3567,7 @@ paths: enum: - active - scheduled + type: string description: The customer's current status with this plan. 'active' if attached, 'scheduled' if pending activation. canceling: @@ -3326,6 +3584,7 @@ paths: - downgrade - none - purchase + type: string description: The action that would occur if this plan were attached to the customer. required: @@ -3483,6 +3742,7 @@ paths: - quarter - semi_annual - year + type: string description: Billing interval (e.g. 'month', 'year'). interval_count: type: number @@ -3532,6 +3792,7 @@ paths: - single_use - continuous_use - credit_system + type: string description: The type of the feature display: anyOf: @@ -3596,6 +3857,7 @@ paths: - quarter - semi_annual - year + type: string description: The interval at which the feature balance resets (e.g. 'month', 'year'). For consumable features, usage resets to 0 and included units are restored. @@ -3629,6 +3891,7 @@ paths: enum: - graduated - volume + type: string interval: enum: - one_off @@ -3637,6 +3900,7 @@ paths: - quarter - semi_annual - year + type: string description: Billing interval for this price. For consumable features, should match reset.interval. interval_count: @@ -3652,6 +3916,7 @@ paths: enum: - prepaid - usage_based + type: string description: "'prepaid' for features like seats where customers pay upfront, 'usage_based' for pay-as-you-go after included usage." @@ -3695,6 +3960,7 @@ paths: enum: - month - forever + type: string description: When rolled over units expire. expiry_duration_length: type: number @@ -3723,6 +3989,7 @@ paths: - day - month - year + type: string description: Unit of time for the trial duration ('day', 'month', 'year'). card_required: type: boolean @@ -3741,6 +4008,7 @@ paths: enum: - sandbox - live + type: string description: Environment this plan belongs to ('sandbox' or 'live'). archived: type: boolean @@ -3763,6 +4031,7 @@ paths: enum: - active - scheduled + type: string description: The customer's current status with this plan. 'active' if attached, 'scheduled' if pending activation. canceling: @@ -3779,6 +4048,7 @@ paths: - downgrade - none - purchase + type: string description: The action that would occur if this plan were attached to the customer. required: @@ -3941,6 +4211,7 @@ paths: - quarter - semi_annual - year + type: string description: Billing interval (e.g. 'month', 'year'). interval_count: type: number @@ -3990,6 +4261,7 @@ paths: - single_use - continuous_use - credit_system + type: string description: The type of the feature display: anyOf: @@ -4054,6 +4326,7 @@ paths: - quarter - semi_annual - year + type: string description: The interval at which the feature balance resets (e.g. 'month', 'year'). For consumable features, usage resets to 0 and included units @@ -4088,6 +4361,7 @@ paths: enum: - graduated - volume + type: string interval: enum: - one_off @@ -4096,6 +4370,7 @@ paths: - quarter - semi_annual - year + type: string description: Billing interval for this price. For consumable features, should match reset.interval. interval_count: @@ -4111,6 +4386,7 @@ paths: enum: - prepaid - usage_based + type: string description: "'prepaid' for features like seats where customers pay upfront, 'usage_based' for pay-as-you-go after included usage." @@ -4155,6 +4431,7 @@ paths: enum: - month - forever + type: string description: When rolled over units expire. expiry_duration_length: type: number @@ -4184,6 +4461,7 @@ paths: - day - month - year + type: string description: Unit of time for the trial duration ('day', 'month', 'year'). card_required: type: boolean @@ -4202,6 +4480,7 @@ paths: enum: - sandbox - live + type: string description: Environment this plan belongs to ('sandbox' or 'live'). archived: type: boolean @@ -4224,6 +4503,7 @@ paths: enum: - active - scheduled + type: string description: The customer's current status with this plan. 'active' if attached, 'scheduled' if pending activation. canceling: @@ -4240,6 +4520,7 @@ paths: - downgrade - none - purchase + type: string description: The action that would occur if this plan were attached to the customer. required: @@ -4371,6 +4652,7 @@ paths: - quarter - semi_annual - year + type: string description: Billing interval (e.g. 'month', 'year'). interval_count: type: number @@ -4411,6 +4693,7 @@ paths: - quarter - semi_annual - year + type: string description: Interval at which balance resets (e.g. 'month', 'year'). For consumable features only. interval_count: @@ -4447,6 +4730,7 @@ paths: enum: - graduated - volume + type: string interval: enum: - one_off @@ -4455,6 +4739,7 @@ paths: - quarter - semi_annual - year + type: string description: Billing interval. For consumable features, should match reset.interval. interval_count: @@ -4470,6 +4755,7 @@ paths: enum: - prepaid - usage_based + type: string description: "'prepaid' for upfront payment (seats), 'usage_based' for pay-as-you-go." max_purchase: @@ -4489,6 +4775,7 @@ paths: - prorate_immediately - prorate_next_cycle - bill_next_cycle + type: string description: Billing behavior when quantity increases mid-cycle. on_decrease: enum: @@ -4497,6 +4784,7 @@ paths: - prorate_next_cycle - none - no_prorations + type: string description: Credit behavior when quantity decreases mid-cycle. required: - on_increase @@ -4513,6 +4801,7 @@ paths: enum: - month - forever + type: string description: When rolled over units expire. expiry_duration_length: type: number @@ -4540,6 +4829,7 @@ paths: - day - month - year + type: string default: month description: Unit of time for the trial ('day', 'month', 'year'). card_required: @@ -4631,6 +4921,7 @@ paths: - quarter - semi_annual - year + type: string description: Billing interval (e.g. 'month', 'year'). interval_count: type: number @@ -4680,6 +4971,7 @@ paths: - single_use - continuous_use - credit_system + type: string description: The type of the feature display: anyOf: @@ -4744,6 +5036,7 @@ paths: - quarter - semi_annual - year + type: string description: The interval at which the feature balance resets (e.g. 'month', 'year'). For consumable features, usage resets to 0 and included units are restored. @@ -4777,6 +5070,7 @@ paths: enum: - graduated - volume + type: string interval: enum: - one_off @@ -4785,6 +5079,7 @@ paths: - quarter - semi_annual - year + type: string description: Billing interval for this price. For consumable features, should match reset.interval. interval_count: @@ -4800,6 +5095,7 @@ paths: enum: - prepaid - usage_based + type: string description: "'prepaid' for features like seats where customers pay upfront, 'usage_based' for pay-as-you-go after included usage." @@ -4843,6 +5139,7 @@ paths: enum: - month - forever + type: string description: When rolled over units expire. expiry_duration_length: type: number @@ -4871,6 +5168,7 @@ paths: - day - month - year + type: string description: Unit of time for the trial duration ('day', 'month', 'year'). card_required: type: boolean @@ -4889,6 +5187,7 @@ paths: enum: - sandbox - live + type: string description: Environment this plan belongs to ('sandbox' or 'live'). archived: type: boolean @@ -4911,6 +5210,7 @@ paths: enum: - active - scheduled + type: string description: The customer's current status with this plan. 'active' if attached, 'scheduled' if pending activation. canceling: @@ -4927,6 +5227,7 @@ paths: - downgrade - none - purchase + type: string description: The action that would occur if this plan were attached to the customer. required: @@ -5075,6 +5376,7 @@ paths: - boolean - metered - credit_system + type: string description: The type of the feature. 'single_use' features are consumed, like API calls, tokens, or messages. 'continuous_use' features are allocated, like seats, workspaces, or projects. @@ -5160,6 +5462,7 @@ paths: - boolean - metered - credit_system + type: string description: "Feature type: 'boolean' for on/off access, 'metered' for usage-tracked features, 'credit_system' for unified credit pools." @@ -5274,6 +5577,7 @@ paths: - boolean - metered - credit_system + type: string description: "Feature type: 'boolean' for on/off access, 'metered' for usage-tracked features, 'credit_system' for unified credit pools." @@ -5378,6 +5682,7 @@ paths: - boolean - metered - credit_system + type: string description: "Feature type: 'boolean' for on/off access, 'metered' for usage-tracked features, 'credit_system' for unified credit pools." @@ -5489,6 +5794,7 @@ paths: - boolean - metered - credit_system + type: string description: The type of the feature. 'single_use' features are consumed, like API calls, tokens, or messages. 'continuous_use' features are allocated, like seats, workspaces, or projects. @@ -5574,6 +5880,7 @@ paths: - boolean - metered - credit_system + type: string description: "Feature type: 'boolean' for on/off access, 'metered' for usage-tracked features, 'credit_system' for unified credit pools." @@ -5761,6 +6068,7 @@ paths: - quarter - semi_annual - year + type: string description: Billing interval (e.g. 'month', 'year'). interval_count: type: number @@ -5802,6 +6110,7 @@ paths: - quarter - semi_annual - year + type: string description: Interval at which balance resets (e.g. 'month', 'year'). For consumable features only. interval_count: @@ -5838,6 +6147,7 @@ paths: enum: - graduated - volume + type: string interval: enum: - one_off @@ -5846,6 +6156,7 @@ paths: - quarter - semi_annual - year + type: string description: Billing interval. For consumable features, should match reset.interval. interval_count: @@ -5861,6 +6172,7 @@ paths: enum: - prepaid - usage_based + type: string description: "'prepaid' for upfront payment (seats), 'usage_based' for pay-as-you-go." max_purchase: @@ -5880,6 +6192,7 @@ paths: - prorate_immediately - prorate_next_cycle - bill_next_cycle + type: string description: Billing behavior when quantity increases mid-cycle. on_decrease: enum: @@ -5888,6 +6201,7 @@ paths: - prorate_next_cycle - none - no_prorations + type: string description: Credit behavior when quantity decreases mid-cycle. required: - on_increase @@ -5904,6 +6218,7 @@ paths: enum: - month - forever + type: string description: When rolled over units expire. expiry_duration_length: type: number @@ -5930,6 +6245,7 @@ paths: - day - month - year + type: string default: month description: Unit of time for the trial ('day', 'month', 'year'). card_required: @@ -5973,6 +6289,7 @@ paths: enum: - prorate_immediately - none + type: string description: How to handle proration when updating an existing subscription. 'prorate_immediately' charges/credits prorated amounts now, 'none' skips creating any charges. @@ -5981,6 +6298,7 @@ paths: - always - if_required - never + type: string description: Controls when to return a checkout URL. 'always' returns a URL even if payment succeeds, 'if_required' only when payment action is needed, 'never' disables redirects. @@ -6017,6 +6335,7 @@ paths: enum: - immediate - end_of_cycle + type: string description: When the plan change should take effect. 'immediate' applies now, 'end_of_cycle' schedules for the end of the current billing cycle. By default, upgrades are immediate and downgrades are @@ -6148,6 +6467,7 @@ paths: - 3ds_required - payment_method_required - payment_failed + type: string description: The type of action required to complete the payment. reason: type: string @@ -6221,6 +6541,7 @@ paths: - quarter - semi_annual - year + type: string description: Billing interval (e.g. 'month', 'year'). interval_count: type: number @@ -6262,6 +6583,7 @@ paths: - quarter - semi_annual - year + type: string description: Interval at which balance resets (e.g. 'month', 'year'). For consumable features only. interval_count: @@ -6298,6 +6620,7 @@ paths: enum: - graduated - volume + type: string interval: enum: - one_off @@ -6306,6 +6629,7 @@ paths: - quarter - semi_annual - year + type: string description: Billing interval. For consumable features, should match reset.interval. interval_count: @@ -6322,6 +6646,7 @@ paths: enum: - prepaid - usage_based + type: string description: "'prepaid' for upfront payment (seats), 'usage_based' for pay-as-you-go." max_purchase: @@ -6341,6 +6666,7 @@ paths: - prorate_immediately - prorate_next_cycle - bill_next_cycle + type: string description: Billing behavior when quantity increases mid-cycle. on_decrease: enum: @@ -6349,6 +6675,7 @@ paths: - prorate_next_cycle - none - no_prorations + type: string description: Credit behavior when quantity decreases mid-cycle. required: - on_increase @@ -6365,6 +6692,7 @@ paths: enum: - month - forever + type: string description: When rolled over units expire. expiry_duration_length: type: number @@ -6423,6 +6751,7 @@ paths: - day - month - year + type: string default: month description: Unit of time for the trial ('day', 'month', 'year'). card_required: @@ -6489,6 +6818,7 @@ paths: - always - if_required - never + type: string description: Controls when to return a checkout URL. 'always' returns a URL even if payment succeeds, 'if_required' only when payment action is needed, 'never' disables redirects. @@ -6529,6 +6859,40 @@ paths: minimum: 0 description: Maximum allowed overage spend for the target feature. description: List of overage spend limits per feature. + usage_alerts: + type: array + items: + type: object + properties: + feature_id: + type: string + description: The feature ID this alert applies to. If omitted, the alert applies + globally. + enabled: + type: boolean + default: true + description: Whether this usage alert is enabled. + threshold: + type: number + minimum: 0 + description: The threshold value that triggers the alert. For usage, this is an + absolute count. For usage_percentage, this is + a percentage (0-100). + threshold_type: + enum: + - usage + - usage_percentage + type: string + description: Whether the threshold is an absolute usage count or a percentage of + the usage allowance. + name: + type: string + description: Optional user-defined label to distinguish multiple alerts on the + same feature. + required: + - threshold + - threshold_type + description: List of usage alert configurations per feature. description: Billing controls for the entity. required: - feature_id @@ -6605,6 +6969,7 @@ paths: - 3ds_required - payment_method_required - payment_failed + type: string description: The type of action required to complete the payment. reason: type: string @@ -6703,6 +7068,7 @@ paths: - quarter - semi_annual - year + type: string description: Billing interval (e.g. 'month', 'year'). interval_count: type: number @@ -6744,6 +7110,7 @@ paths: - quarter - semi_annual - year + type: string description: Interval at which balance resets (e.g. 'month', 'year'). For consumable features only. interval_count: @@ -6780,6 +7147,7 @@ paths: enum: - graduated - volume + type: string interval: enum: - one_off @@ -6788,6 +7156,7 @@ paths: - quarter - semi_annual - year + type: string description: Billing interval. For consumable features, should match reset.interval. interval_count: @@ -6803,6 +7172,7 @@ paths: enum: - prepaid - usage_based + type: string description: "'prepaid' for upfront payment (seats), 'usage_based' for pay-as-you-go." max_purchase: @@ -6822,6 +7192,7 @@ paths: - prorate_immediately - prorate_next_cycle - bill_next_cycle + type: string description: Billing behavior when quantity increases mid-cycle. on_decrease: enum: @@ -6830,6 +7201,7 @@ paths: - prorate_next_cycle - none - no_prorations + type: string description: Credit behavior when quantity decreases mid-cycle. required: - on_increase @@ -6846,6 +7218,7 @@ paths: enum: - month - forever + type: string description: When rolled over units expire. expiry_duration_length: type: number @@ -6872,6 +7245,7 @@ paths: - day - month - year + type: string default: month description: Unit of time for the trial ('day', 'month', 'year'). card_required: @@ -6915,6 +7289,7 @@ paths: enum: - prorate_immediately - none + type: string description: How to handle proration when updating an existing subscription. 'prorate_immediately' charges/credits prorated amounts now, 'none' skips creating any charges. @@ -6923,6 +7298,7 @@ paths: - always - if_required - never + type: string description: Controls when to return a checkout URL. 'always' returns a URL even if payment succeeds, 'if_required' only when payment action is needed, 'never' disables redirects. @@ -6959,6 +7335,7 @@ paths: enum: - immediate - end_of_cycle + type: string description: When the plan change should take effect. 'immediate' applies now, 'end_of_cycle' schedules for the end of the current billing cycle. By default, upgrades are immediate and downgrades are @@ -7284,10 +7661,24 @@ paths: - type: "null" description: When this change takes effect, in milliseconds since the Unix epoch, or null if it applies immediately. + canceled_at: + anyOf: + - type: number + - type: "null" + description: When this plan was canceled, in milliseconds since the Unix epoch, + or null if it is not canceled. + expires_at: + anyOf: + - type: number + - type: "null" + description: When this plan expires, in milliseconds since the Unix epoch, or + null if it does not expire. required: - plan_id - feature_quantities - effective_at + - canceled_at + - expires_at description: Products or subscription changes being added or updated. outgoing: type: array @@ -7321,10 +7712,24 @@ paths: - type: "null" description: When this change takes effect, in milliseconds since the Unix epoch, or null if it applies immediately. + canceled_at: + anyOf: + - type: number + - type: "null" + description: When this plan was canceled, in milliseconds since the Unix epoch, + or null if it is not canceled. + expires_at: + anyOf: + - type: number + - type: "null" + description: When this plan expires, in milliseconds since the Unix epoch, or + null if it does not expire. required: - plan_id - feature_quantities - effective_at + - canceled_at + - expires_at description: Products or subscription changes being removed or ended. required: - customer_id @@ -7402,6 +7807,7 @@ paths: - quarter - semi_annual - year + type: string description: Billing interval (e.g. 'month', 'year'). interval_count: type: number @@ -7443,6 +7849,7 @@ paths: - quarter - semi_annual - year + type: string description: Interval at which balance resets (e.g. 'month', 'year'). For consumable features only. interval_count: @@ -7479,6 +7886,7 @@ paths: enum: - graduated - volume + type: string interval: enum: - one_off @@ -7487,6 +7895,7 @@ paths: - quarter - semi_annual - year + type: string description: Billing interval. For consumable features, should match reset.interval. interval_count: @@ -7503,6 +7912,7 @@ paths: enum: - prepaid - usage_based + type: string description: "'prepaid' for upfront payment (seats), 'usage_based' for pay-as-you-go." max_purchase: @@ -7522,6 +7932,7 @@ paths: - prorate_immediately - prorate_next_cycle - bill_next_cycle + type: string description: Billing behavior when quantity increases mid-cycle. on_decrease: enum: @@ -7530,6 +7941,7 @@ paths: - prorate_next_cycle - none - no_prorations + type: string description: Credit behavior when quantity decreases mid-cycle. required: - on_increase @@ -7546,6 +7958,7 @@ paths: enum: - month - forever + type: string description: When rolled over units expire. expiry_duration_length: type: number @@ -7604,6 +8017,7 @@ paths: - day - month - year + type: string default: month description: Unit of time for the trial ('day', 'month', 'year'). card_required: @@ -7670,6 +8084,7 @@ paths: - always - if_required - never + type: string description: Controls when to return a checkout URL. 'always' returns a URL even if payment succeeds, 'if_required' only when payment action is needed, 'never' disables redirects. @@ -7710,6 +8125,40 @@ paths: minimum: 0 description: Maximum allowed overage spend for the target feature. description: List of overage spend limits per feature. + usage_alerts: + type: array + items: + type: object + properties: + feature_id: + type: string + description: The feature ID this alert applies to. If omitted, the alert applies + globally. + enabled: + type: boolean + default: true + description: Whether this usage alert is enabled. + threshold: + type: number + minimum: 0 + description: The threshold value that triggers the alert. For usage, this is an + absolute count. For usage_percentage, this is + a percentage (0-100). + threshold_type: + enum: + - usage + - usage_percentage + type: string + description: Whether the threshold is an absolute usage count or a percentage of + the usage allowance. + name: + type: string + description: Optional user-defined label to distinguish multiple alerts on the + same feature. + required: + - threshold + - threshold_type + description: List of usage alert configurations per feature. description: Billing controls for the entity. required: - feature_id @@ -7980,10 +8429,24 @@ paths: - type: "null" description: When this change takes effect, in milliseconds since the Unix epoch, or null if it applies immediately. + canceled_at: + anyOf: + - type: number + - type: "null" + description: When this plan was canceled, in milliseconds since the Unix epoch, + or null if it is not canceled. + expires_at: + anyOf: + - type: number + - type: "null" + description: When this plan expires, in milliseconds since the Unix epoch, or + null if it does not expire. required: - plan_id - feature_quantities - effective_at + - canceled_at + - expires_at description: Products or subscription changes being added or updated. outgoing: type: array @@ -8017,10 +8480,24 @@ paths: - type: "null" description: When this change takes effect, in milliseconds since the Unix epoch, or null if it applies immediately. + canceled_at: + anyOf: + - type: number + - type: "null" + description: When this plan was canceled, in milliseconds since the Unix epoch, + or null if it is not canceled. + expires_at: + anyOf: + - type: number + - type: "null" + description: When this plan expires, in milliseconds since the Unix epoch, or + null if it does not expire. required: - plan_id - feature_quantities - effective_at + - canceled_at + - expires_at description: Products or subscription changes being removed or ended. required: - customer_id @@ -8119,6 +8596,7 @@ paths: - quarter - semi_annual - year + type: string description: Billing interval (e.g. 'month', 'year'). interval_count: type: number @@ -8160,6 +8638,7 @@ paths: - quarter - semi_annual - year + type: string description: Interval at which balance resets (e.g. 'month', 'year'). For consumable features only. interval_count: @@ -8196,6 +8675,7 @@ paths: enum: - graduated - volume + type: string interval: enum: - one_off @@ -8204,6 +8684,7 @@ paths: - quarter - semi_annual - year + type: string description: Billing interval. For consumable features, should match reset.interval. interval_count: @@ -8219,6 +8700,7 @@ paths: enum: - prepaid - usage_based + type: string description: "'prepaid' for upfront payment (seats), 'usage_based' for pay-as-you-go." max_purchase: @@ -8238,6 +8720,7 @@ paths: - prorate_immediately - prorate_next_cycle - bill_next_cycle + type: string description: Billing behavior when quantity increases mid-cycle. on_decrease: enum: @@ -8246,6 +8729,7 @@ paths: - prorate_next_cycle - none - no_prorations + type: string description: Credit behavior when quantity decreases mid-cycle. required: - on_increase @@ -8262,6 +8746,7 @@ paths: enum: - month - forever + type: string description: When rolled over units expire. expiry_duration_length: type: number @@ -8288,6 +8773,7 @@ paths: - day - month - year + type: string default: month description: Unit of time for the trial ('day', 'month', 'year'). card_required: @@ -8331,6 +8817,7 @@ paths: enum: - prorate_immediately - none + type: string description: How to handle proration when updating an existing subscription. 'prorate_immediately' charges/credits prorated amounts now, 'none' skips creating any charges. @@ -8339,6 +8826,7 @@ paths: - always - if_required - never + type: string description: Controls when to return a checkout URL. 'always' returns a URL even if payment succeeds, 'if_required' only when payment action is needed, 'never' disables redirects. @@ -8353,6 +8841,7 @@ paths: - cancel_immediately - cancel_end_of_cycle - uncancel + type: string description: Action to perform for cancellation. 'cancel_immediately' cancels now with prorated refund, 'cancel_end_of_cycle' cancels at period end, 'uncancel' reverses a pending cancellation. @@ -8360,6 +8849,17 @@ paths: type: boolean description: If true, the subscription is updated internally without applying billing changes in Stripe. + recalculate_balances: + type: object + properties: + enabled: + type: boolean + description: If true, recalculates balances during the subscription update. Only + applicable when updating feature quantities. + required: + - enabled + description: Controls whether balances should be recalculated during the + subscription update. required: - customer_id title: UpdateSubscriptionParams @@ -8430,6 +8930,7 @@ paths: - 3ds_required - payment_method_required - payment_failed + type: string description: The type of action required to complete the payment. reason: type: string @@ -8529,6 +9030,7 @@ paths: - quarter - semi_annual - year + type: string description: Billing interval (e.g. 'month', 'year'). interval_count: type: number @@ -8570,6 +9072,7 @@ paths: - quarter - semi_annual - year + type: string description: Interval at which balance resets (e.g. 'month', 'year'). For consumable features only. interval_count: @@ -8606,6 +9109,7 @@ paths: enum: - graduated - volume + type: string interval: enum: - one_off @@ -8614,6 +9118,7 @@ paths: - quarter - semi_annual - year + type: string description: Billing interval. For consumable features, should match reset.interval. interval_count: @@ -8629,6 +9134,7 @@ paths: enum: - prepaid - usage_based + type: string description: "'prepaid' for upfront payment (seats), 'usage_based' for pay-as-you-go." max_purchase: @@ -8648,6 +9154,7 @@ paths: - prorate_immediately - prorate_next_cycle - bill_next_cycle + type: string description: Billing behavior when quantity increases mid-cycle. on_decrease: enum: @@ -8656,6 +9163,7 @@ paths: - prorate_next_cycle - none - no_prorations + type: string description: Credit behavior when quantity decreases mid-cycle. required: - on_increase @@ -8672,6 +9180,7 @@ paths: enum: - month - forever + type: string description: When rolled over units expire. expiry_duration_length: type: number @@ -8698,6 +9207,7 @@ paths: - day - month - year + type: string default: month description: Unit of time for the trial ('day', 'month', 'year'). card_required: @@ -8741,6 +9251,7 @@ paths: enum: - prorate_immediately - none + type: string description: How to handle proration when updating an existing subscription. 'prorate_immediately' charges/credits prorated amounts now, 'none' skips creating any charges. @@ -8749,6 +9260,7 @@ paths: - always - if_required - never + type: string description: Controls when to return a checkout URL. 'always' returns a URL even if payment succeeds, 'if_required' only when payment action is needed, 'never' disables redirects. @@ -8763,6 +9275,7 @@ paths: - cancel_immediately - cancel_end_of_cycle - uncancel + type: string description: Action to perform for cancellation. 'cancel_immediately' cancels now with prorated refund, 'cancel_end_of_cycle' cancels at period end, 'uncancel' reverses a pending cancellation. @@ -8770,6 +9283,17 @@ paths: type: boolean description: If true, the subscription is updated internally without applying billing changes in Stripe. + recalculate_balances: + type: object + properties: + enabled: + type: boolean + description: If true, recalculates balances during the subscription update. Only + applicable when updating feature quantities. + required: + - enabled + description: Controls whether balances should be recalculated during the + subscription update. required: - customer_id title: PreviewUpdateParams @@ -9034,10 +9558,24 @@ paths: - type: "null" description: When this change takes effect, in milliseconds since the Unix epoch, or null if it applies immediately. + canceled_at: + anyOf: + - type: number + - type: "null" + description: When this plan was canceled, in milliseconds since the Unix epoch, + or null if it is not canceled. + expires_at: + anyOf: + - type: number + - type: "null" + description: When this plan expires, in milliseconds since the Unix epoch, or + null if it does not expire. required: - plan_id - feature_quantities - effective_at + - canceled_at + - expires_at description: Products or subscription changes being added or updated. outgoing: type: array @@ -9071,10 +9609,24 @@ paths: - type: "null" description: When this change takes effect, in milliseconds since the Unix epoch, or null if it applies immediately. + canceled_at: + anyOf: + - type: number + - type: "null" + description: When this plan was canceled, in milliseconds since the Unix epoch, + or null if it is not canceled. + expires_at: + anyOf: + - type: number + - type: "null" + description: When this plan expires, in milliseconds since the Unix epoch, or + null if it does not expire. required: - plan_id - feature_quantities - effective_at + - canceled_at + - expires_at description: Products or subscription changes being removed or ended. intent: enum: @@ -9084,6 +9636,7 @@ paths: - cancel_end_of_cycle - uncancel - none + type: string required: - customer_id - line_items @@ -9235,6 +9788,7 @@ paths: - quarter - semi_annual - year + type: string description: Billing interval (e.g. 'month', 'year'). interval_count: type: number @@ -9276,6 +9830,7 @@ paths: - quarter - semi_annual - year + type: string description: Interval at which balance resets (e.g. 'month', 'year'). For consumable features only. interval_count: @@ -9312,6 +9867,7 @@ paths: enum: - graduated - volume + type: string interval: enum: - one_off @@ -9320,6 +9876,7 @@ paths: - quarter - semi_annual - year + type: string description: Billing interval. For consumable features, should match reset.interval. interval_count: @@ -9335,6 +9892,7 @@ paths: enum: - prepaid - usage_based + type: string description: "'prepaid' for upfront payment (seats), 'usage_based' for pay-as-you-go." max_purchase: @@ -9354,6 +9912,7 @@ paths: - prorate_immediately - prorate_next_cycle - bill_next_cycle + type: string description: Billing behavior when quantity increases mid-cycle. on_decrease: enum: @@ -9362,6 +9921,7 @@ paths: - prorate_next_cycle - none - no_prorations + type: string description: Credit behavior when quantity decreases mid-cycle. required: - on_increase @@ -9378,6 +9938,7 @@ paths: enum: - month - forever + type: string description: When rolled over units expire. expiry_duration_length: type: number @@ -9404,6 +9965,7 @@ paths: - day - month - year + type: string default: month description: Unit of time for the trial ('day', 'month', 'year'). card_required: @@ -9424,6 +9986,7 @@ paths: enum: - prorate_immediately - none + type: string description: How to handle proration when updating an existing subscription. 'prorate_immediately' charges/credits prorated amounts now, 'none' skips creating any charges. @@ -9592,6 +10155,7 @@ paths: - quarter - semi_annual - year + type: string description: The interval at which the balance resets (e.g., 'month', 'day', 'year'). interval_count: @@ -9684,6 +10248,7 @@ paths: - quarter - semi_annual - year + type: string description: Target a specific balance by its reset interval. Use when the customer has multiple balances for the same feature with different reset intervals. @@ -9762,6 +10327,7 @@ paths: - quarter - semi_annual - year + type: string description: Target a specific balance by its reset interval. Use when the customer has multiple balances for the same feature with different reset intervals. @@ -9809,6 +10375,7 @@ paths: enum: - confirm - release + type: string description: Use 'confirm' to commit the deduction, or 'release' to return the held balance. override_value: @@ -9994,6 +10561,7 @@ paths: - boolean - metered - credit_system + type: string description: "Feature type: 'boolean' for on/off access, 'metered' for usage-tracked features, 'credit_system' for unified credit pools." @@ -10068,6 +10636,7 @@ paths: enum: - usage_limit - feature_flag + type: string description: The reason access was denied. 'usage_limit' means the customer exceeded their balance, 'feature_flag' means the feature is not included in their plan. @@ -10103,6 +10672,7 @@ paths: enum: - sandbox - live + type: string description: The environment of the product is_add_on: type: boolean @@ -10132,6 +10702,7 @@ paths: - feature - priced_feature - price + type: string - type: "null" description: The type of the product item feature_id: @@ -10147,6 +10718,7 @@ paths: - continuous_use - boolean - static + type: string - type: "null" description: Single use features are used once and then depleted, like API calls or credits. Continuous use features are @@ -10170,6 +10742,7 @@ paths: - quarter - semi_annual - year + type: string - type: "null" description: The reset or billing interval of the product item. If null, feature will have no reset date, and if there's a @@ -10200,6 +10773,7 @@ paths: - enum: - graduated - volume + type: string - type: "null" description: "How tiers are applied: graduated (split across bands) or volume (flat rate for the matched tier). Defaults @@ -10209,6 +10783,7 @@ paths: - enum: - prepaid - pay_per_use + type: string - type: "null" description: Whether the feature should be prepaid upfront or billed for how much they use end of billing period. @@ -10269,6 +10844,7 @@ paths: enum: - month - forever + type: string default: month length: type: number @@ -10283,6 +10859,7 @@ paths: - prorate_immediately - prorate_next_cycle - bill_next_cycle + type: string - type: "null" on_decrease: anyOf: @@ -10292,6 +10869,7 @@ paths: - prorate_next_cycle - none - no_prorations + type: string - type: "null" - type: "null" description: Configuration for rollover and proration behavior of the feature. @@ -10307,6 +10885,7 @@ paths: - day - month - year + type: string description: The duration type of the free trial length: type: number @@ -10351,6 +10930,7 @@ paths: - cancel - expired - past_due + type: string description: Scenario for when this product is used in attach flows properties: type: object @@ -10767,6 +11347,7 @@ paths: - last_cycle - 1bc - 3bc + type: string description: Time range to aggregate events for. Either range or custom_range must be provided bin_size: @@ -10774,6 +11355,7 @@ paths: - day - hour - month + type: string default: day description: Size of the time bins to aggregate events for. Defaults to hour if range is 24h, otherwise day @@ -10964,6 +11546,40 @@ paths: minimum: 0 description: Maximum allowed overage spend for the target feature. description: List of overage spend limits per feature. + usage_alerts: + type: array + items: + type: object + properties: + feature_id: + type: string + description: The feature ID this alert applies to. If omitted, the alert applies + globally. + enabled: + type: boolean + default: true + description: Whether this usage alert is enabled. + threshold: + type: number + minimum: 0 + description: The threshold value that triggers the alert. For usage, this is an + absolute count. For usage_percentage, this is a + percentage (0-100). + threshold_type: + enum: + - usage + - usage_percentage + type: string + description: Whether the threshold is an absolute usage count or a percentage of + the usage allowance. + name: + type: string + description: Optional user-defined label to distinguish multiple alerts on the + same feature. + required: + - threshold + - threshold_type + description: List of usage alert configurations per feature. description: Billing controls for the entity. customer_data: $ref: "#/components/schemas/CustomerData" @@ -11022,6 +11638,7 @@ paths: enum: - sandbox - live + type: string description: The environment (sandbox/live) subscriptions: type: array @@ -11049,6 +11666,7 @@ paths: enum: - active - scheduled + type: string description: Current status of the subscription. past_due: type: boolean @@ -11172,6 +11790,7 @@ paths: - boolean - metered - credit_system + type: string description: "Feature type: 'boolean' for on/off access, 'metered' for usage-tracked features, 'credit_system' for unified credit pools." @@ -11257,6 +11876,40 @@ paths: minimum: 0 description: Maximum allowed overage spend for the target feature. description: List of overage spend limits per feature. + usage_alerts: + type: array + items: + type: object + properties: + feature_id: + type: string + description: The feature ID this alert applies to. If omitted, the alert applies + globally. + enabled: + type: boolean + default: true + description: Whether this usage alert is enabled. + threshold: + type: number + minimum: 0 + description: The threshold value that triggers the alert. For usage, this is an + absolute count. For usage_percentage, this is a + percentage (0-100). + threshold_type: + enum: + - usage + - usage_percentage + type: string + description: Whether the threshold is an absolute usage count or a percentage of + the usage allowance. + name: + type: string + description: Optional user-defined label to distinguish multiple alerts on the + same feature. + required: + - threshold + - threshold_type + description: List of usage alert configurations per feature. description: Billing controls for the entity. invoices: type: array @@ -11423,6 +12076,7 @@ paths: enum: - sandbox - live + type: string description: The environment (sandbox/live) subscriptions: type: array @@ -11450,6 +12104,7 @@ paths: enum: - active - scheduled + type: string description: Current status of the subscription. past_due: type: boolean @@ -11573,6 +12228,7 @@ paths: - boolean - metered - credit_system + type: string description: "Feature type: 'boolean' for on/off access, 'metered' for usage-tracked features, 'credit_system' for unified credit pools." @@ -11658,6 +12314,40 @@ paths: minimum: 0 description: Maximum allowed overage spend for the target feature. description: List of overage spend limits per feature. + usage_alerts: + type: array + items: + type: object + properties: + feature_id: + type: string + description: The feature ID this alert applies to. If omitted, the alert applies + globally. + enabled: + type: boolean + default: true + description: Whether this usage alert is enabled. + threshold: + type: number + minimum: 0 + description: The threshold value that triggers the alert. For usage, this is an + absolute count. For usage_percentage, this is a + percentage (0-100). + threshold_type: + enum: + - usage + - usage_percentage + type: string + description: Whether the threshold is an absolute usage count or a percentage of + the usage allowance. + name: + type: string + description: Optional user-defined label to distinguish multiple alerts on the + same feature. + required: + - threshold + - threshold_type + description: List of usage alert configurations per feature. description: Billing controls for the entity. invoices: type: array @@ -11800,6 +12490,40 @@ paths: minimum: 0 description: Maximum allowed overage spend for the target feature. description: List of overage spend limits per feature. + usage_alerts: + type: array + items: + type: object + properties: + feature_id: + type: string + description: The feature ID this alert applies to. If omitted, the alert applies + globally. + enabled: + type: boolean + default: true + description: Whether this usage alert is enabled. + threshold: + type: number + minimum: 0 + description: The threshold value that triggers the alert. For usage, this is an + absolute count. For usage_percentage, this is a + percentage (0-100). + threshold_type: + enum: + - usage + - usage_percentage + type: string + description: Whether the threshold is an absolute usage count or a percentage of + the usage allowance. + name: + type: string + description: Optional user-defined label to distinguish multiple alerts on the + same feature. + required: + - threshold + - threshold_type + description: List of usage alert configurations per feature. description: Billing controls to replace on the entity. required: - entity_id @@ -11849,6 +12573,7 @@ paths: enum: - sandbox - live + type: string description: The environment (sandbox/live) subscriptions: type: array @@ -11876,6 +12601,7 @@ paths: enum: - active - scheduled + type: string description: Current status of the subscription. past_due: type: boolean @@ -11999,6 +12725,7 @@ paths: - boolean - metered - credit_system + type: string description: "Feature type: 'boolean' for on/off access, 'metered' for usage-tracked features, 'credit_system' for unified credit pools." @@ -12084,6 +12811,40 @@ paths: minimum: 0 description: Maximum allowed overage spend for the target feature. description: List of overage spend limits per feature. + usage_alerts: + type: array + items: + type: object + properties: + feature_id: + type: string + description: The feature ID this alert applies to. If omitted, the alert applies + globally. + enabled: + type: boolean + default: true + description: Whether this usage alert is enabled. + threshold: + type: number + minimum: 0 + description: The threshold value that triggers the alert. For usage, this is an + absolute count. For usage_percentage, this is a + percentage (0-100). + threshold_type: + enum: + - usage + - usage_percentage + type: string + description: Whether the threshold is an absolute usage count or a percentage of + the usage allowance. + name: + type: string + description: Optional user-defined label to distinguish multiple alerts on the + same feature. + required: + - threshold + - threshold_type + description: List of usage alert configurations per feature. description: Billing controls for the entity. invoices: type: array @@ -12360,3 +13121,317 @@ x-speakeasy-globals: type: string default: 2.2.0 x-speakeasy-globals-hidden: true +webhooks: + balances.usage_alert_triggered: + post: + operationId: balancesUsageAlertTriggered + summary: Usage Alert Triggered + description: Fired when a customer crosses a configured usage alert threshold. + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - type + - data + properties: + type: + type: string + const: balances.usage_alert_triggered + description: The webhook event type. + data: + examples: + - customer_id: org_123 + feature_id: api_calls + entity_id: workspace_abc + usage_alert: + name: 80% usage warning + threshold: 80 + threshold_type: usage_percentage_threshold + type: object + properties: + customer_id: + description: The ID of the customer whose usage alert was triggered. + type: string + feature_id: + description: The feature ID the alert applies to. + type: string + entity_id: + description: The entity ID the alert applies to, if the usage was entity-scoped. + type: string + usage_alert: + description: Details of the usage alert that was triggered. + type: object + properties: + name: + description: User-defined label for the alert, if provided. + type: string + threshold: + description: The threshold value that was crossed. + type: number + threshold_type: + description: Whether the threshold is an absolute usage count or a percentage. + type: string + enum: + - usage + - usage_percentage + required: + - threshold + - threshold_type + additionalProperties: false + required: + - customer_id + - feature_id + - usage_alert + additionalProperties: false + example: + type: balances.usage_alert_triggered + data: + customer_id: org_123 + feature_id: api_calls + entity_id: workspace_abc + usage_alert: + name: 80% usage warning + threshold: 80 + threshold_type: usage_percentage_threshold + responses: + "200": + description: Webhook received successfully. + balances.limit_reached: + post: + operationId: balancesLimitReached + summary: Limit Reached + description: Fired when a customer reaches the limit for a feature (included + allowance, max purchase, or spend limit). + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - type + - data + properties: + type: + type: string + const: balances.limit_reached + description: The webhook event type. + data: + examples: + - customer_id: org_123 + entity_id: workspace_abc + feature_id: api_calls + limit_type: included + type: object + properties: + customer_id: + description: The ID of the customer who hit the limit. + type: string + entity_id: + description: The entity ID, if the limit was reached on a specific entity. + type: string + feature_id: + description: The feature ID whose limit was reached. + type: string + limit_type: + description: "Which limit was hit: included allowance, max purchase cap, or + spend limit." + type: string + enum: + - included + - max_purchase + - spend_limit + required: + - customer_id + - feature_id + - limit_type + additionalProperties: false + example: + type: balances.limit_reached + data: + customer_id: org_123 + entity_id: workspace_abc + feature_id: api_calls + limit_type: included + responses: + "200": + description: Webhook received successfully. + vercel.resources.deleted: + post: + operationId: vercelResourcesDeleted + summary: Resource Deleted + description: When a Vercel resource is deleted, you'll need to handle + de-provisioning any API keys or other non-Autumn controlled data for + this user. + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - type + - data + properties: + type: + type: string + const: vercel.resources.deleted + description: The webhook event type. + data: + type: object + properties: + resource: + description: The resource that was deleted. + type: object + properties: + id: + description: The unique identifier of the deleted resource. + type: string + required: + - id + additionalProperties: false + installation_id: + description: The Vercel integration configuration ID. + type: string + required: + - resource + - installation_id + additionalProperties: false + responses: + "200": + description: Webhook received successfully. + vercel.resources.provisioned: + post: + operationId: vercelResourcesProvisioned + summary: Resource Provisioned + description: When a Vercel resource is created, you'll need to provision a + secret key for your service. Then you can use the provided access token + to patch the resource's secrets. + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - type + - data + properties: + type: + type: string + const: vercel.resources.provisioned + description: The webhook event type. + data: + type: object + properties: + resource: + description: The resource that was provisioned. + type: object + properties: + id: + description: The unique identifier of the provisioned resource. + type: string + name: + description: The display name of the provisioned resource. + type: string + required: + - id + - name + additionalProperties: false + installation_id: + description: The Vercel integration configuration ID. + type: string + access_token: + description: An access token that can be used to patch the resource's secrets. + type: string + required: + - resource + - installation_id + - access_token + additionalProperties: false + responses: + "200": + description: Webhook received successfully. + vercel.resources.rotate_secrets: + post: + operationId: vercelResourcesRotateSecrets + summary: Rotate Secrets + description: This event is sent when Vercel requires a resource's secrets to be + rotated. + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - type + - data + properties: + type: + type: string + const: vercel.resources.rotate_secrets + description: The webhook event type. + data: + type: object + properties: + resource: + description: The resource whose secrets should be rotated. + type: object + properties: + id: + description: The unique identifier of the resource. + type: string + required: + - id + additionalProperties: false + installation_id: + description: The Vercel integration configuration ID. + type: string + vercel_request_body: + description: The raw request body from Vercel's rotation request. + required: + - resource + - installation_id + - vercel_request_body + additionalProperties: false + responses: + "200": + description: Webhook received successfully. + vercel.webhooks.event: + post: + operationId: vercelWebhooksEvent + summary: Webhook Event + description: Passthrough webhook for Vercel events. + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - type + - data + properties: + type: + type: string + const: vercel.webhooks.event + description: The webhook event type. + data: + type: object + properties: + installation_id: + description: The Vercel integration configuration ID. + type: string + event: + description: The raw Vercel webhook event payload. + required: + - installation_id + - event + additionalProperties: false + responses: + "200": + description: Webhook received successfully. diff --git a/packages/openapi/openapi.yml b/packages/openapi/openapi.yml index a100860e5..3ffd44946 100644 --- a/packages/openapi/openapi.yml +++ b/packages/openapi/openapi.yml @@ -86,6 +86,7 @@ components: - day - week - month + type: string description: The time interval for the purchase limit window. interval_count: type: number @@ -122,6 +123,40 @@ components: minimum: 0 description: Maximum allowed overage spend for the target feature. description: List of overage spend limits per feature. + usage_alerts: + type: array + items: + type: object + properties: + feature_id: + type: string + description: The feature ID this alert applies to. If omitted, the alert applies + globally. + enabled: + type: boolean + default: true + description: Whether this usage alert is enabled. + threshold: + type: number + minimum: 0 + description: The threshold value that triggers the alert. For usage, this is an + absolute count. For usage_percentage, this is a percentage + (0-100). + threshold_type: + enum: + - usage + - usage_percentage + type: string + description: Whether the threshold is an absolute usage count or a percentage of + the usage allowance. + name: + type: string + description: Optional user-defined label to distinguish multiple alerts on the + same feature. + required: + - threshold + - threshold_type + description: List of usage alert configurations per feature. description: Billing controls for the customer (auto top-ups, etc.) title: CustomerData description: Customer details to set when creating a customer @@ -137,6 +172,7 @@ components: - purchases.plan - balances.feature - flags.feature + type: string title: CustomerExpand Customer: type: object @@ -174,6 +210,7 @@ components: enum: - sandbox - live + type: string description: The environment this customer was created in. metadata: type: object @@ -216,6 +253,7 @@ components: - day - week - month + type: string description: The time interval for the purchase limit window. interval_count: type: number @@ -252,6 +290,40 @@ components: minimum: 0 description: Maximum allowed overage spend for the target feature. description: List of overage spend limits per feature. + usage_alerts: + type: array + items: + type: object + properties: + feature_id: + type: string + description: The feature ID this alert applies to. If omitted, the alert applies + globally. + enabled: + type: boolean + default: true + description: Whether this usage alert is enabled. + threshold: + type: number + minimum: 0 + description: The threshold value that triggers the alert. For usage, this is an + absolute count. For usage_percentage, this is a percentage + (0-100). + threshold_type: + enum: + - usage + - usage_percentage + type: string + description: Whether the threshold is an absolute usage count or a percentage of + the usage allowance. + name: + type: string + description: Optional user-defined label to distinguish multiple alerts on the + same feature. + required: + - threshold + - threshold_type + description: List of usage alert configurations per feature. description: Billing controls for the customer (auto top-ups, etc.) subscriptions: type: array @@ -279,6 +351,7 @@ components: enum: - active - scheduled + type: string description: Current status of the subscription. past_due: type: boolean @@ -406,6 +479,7 @@ components: - boolean - metered - credit_system + type: string description: "Feature type: 'boolean' for on/off access, 'metered' for usage-tracked features, 'credit_system' for unified credit pools." @@ -543,6 +617,7 @@ components: enum: - sandbox - live + type: string description: The environment (sandbox/live) required: - id @@ -588,6 +663,7 @@ components: - fixed_discount - free_product - invoice_credits + type: string description: The type of reward discount_value: type: number @@ -597,6 +673,7 @@ components: - one_off - months - forever + type: string description: How long the discount lasts duration_value: anyOf: @@ -794,6 +871,7 @@ components: - quarter - semi_annual - year + type: string description: Billing interval (e.g. 'month', 'year'). interval_count: type: number @@ -843,6 +921,7 @@ components: - single_use - continuous_use - credit_system + type: string description: The type of the feature display: anyOf: @@ -907,6 +986,7 @@ components: - quarter - semi_annual - year + type: string description: The interval at which the feature balance resets (e.g. 'month', 'year'). For consumable features, usage resets to 0 and included units are restored. @@ -940,6 +1020,7 @@ components: enum: - graduated - volume + type: string interval: enum: - one_off @@ -948,6 +1029,7 @@ components: - quarter - semi_annual - year + type: string description: Billing interval for this price. For consumable features, should match reset.interval. interval_count: @@ -962,6 +1044,7 @@ components: enum: - prepaid - usage_based + type: string description: "'prepaid' for features like seats where customers pay upfront, 'usage_based' for pay-as-you-go after included usage." max_purchase: @@ -1004,6 +1087,7 @@ components: enum: - month - forever + type: string description: When rolled over units expire. expiry_duration_length: type: number @@ -1032,6 +1116,7 @@ components: - day - month - year + type: string description: Unit of time for the trial duration ('day', 'month', 'year'). card_required: type: boolean @@ -1050,6 +1135,7 @@ components: enum: - sandbox - live + type: string description: Environment this plan belongs to ('sandbox' or 'live'). archived: type: boolean @@ -1072,6 +1158,7 @@ components: enum: - active - scheduled + type: string description: The customer's current status with this plan. 'active' if attached, 'scheduled' if pending activation. canceling: @@ -1088,6 +1175,7 @@ components: - downgrade - none - purchase + type: string description: The action that would occur if this plan were attached to the customer. required: @@ -1127,6 +1215,7 @@ components: - boolean - metered - credit_system + type: string description: "Feature type: 'boolean' for on/off access, 'metered' for usage-tracked features, 'credit_system' for unified credit pools." @@ -1256,6 +1345,7 @@ components: - quarter - semi_annual - year + type: string - const: multiple description: The reset interval (hour, day, week, month, etc.) or 'multiple' if combined from different intervals. @@ -1290,6 +1380,7 @@ components: enum: - graduated - volume + type: string description: "How tiers are applied: graduated (split across bands) or volume (flat rate for the matched tier)." billing_units: @@ -1299,6 +1390,7 @@ components: enum: - prepaid - usage_based + type: string description: Whether usage is prepaid or billed pay-per-use. max_purchase: anyOf: @@ -1517,6 +1609,7 @@ paths: - day - week - month + type: string description: The time interval for the purchase limit window. interval_count: type: number @@ -1553,6 +1646,40 @@ paths: minimum: 0 description: Maximum allowed overage spend for the target feature. description: List of overage spend limits per feature. + usage_alerts: + type: array + items: + type: object + properties: + feature_id: + type: string + description: The feature ID this alert applies to. If omitted, the alert applies + globally. + enabled: + type: boolean + default: true + description: Whether this usage alert is enabled. + threshold: + type: number + minimum: 0 + description: The threshold value that triggers the alert. For usage, this is an + absolute count. For usage_percentage, this is a + percentage (0-100). + threshold_type: + enum: + - usage + - usage_percentage + type: string + description: Whether the threshold is an absolute usage count or a percentage of + the usage allowance. + name: + type: string + description: Optional user-defined label to distinguish multiple alerts on the + same feature. + required: + - threshold + - threshold_type + description: List of usage alert configurations per feature. description: Billing controls for the customer (auto top-ups, etc.) expand: type: array @@ -1629,6 +1756,7 @@ paths: enum: - active - scheduled + type: string description: Filter by customer product status. Defaults to active and scheduled search: type: string @@ -1684,6 +1812,7 @@ paths: enum: - sandbox - live + type: string description: The environment this customer was created in. metadata: type: object @@ -1726,6 +1855,7 @@ paths: - day - week - month + type: string description: The time interval for the purchase limit window. interval_count: type: number @@ -1762,6 +1892,40 @@ paths: minimum: 0 description: Maximum allowed overage spend for the target feature. description: List of overage spend limits per feature. + usage_alerts: + type: array + items: + type: object + properties: + feature_id: + type: string + description: The feature ID this alert applies to. If omitted, the alert applies + globally. + enabled: + type: boolean + default: true + description: Whether this usage alert is enabled. + threshold: + type: number + minimum: 0 + description: The threshold value that triggers the alert. For usage, this is an + absolute count. For usage_percentage, this + is a percentage (0-100). + threshold_type: + enum: + - usage + - usage_percentage + type: string + description: Whether the threshold is an absolute usage count or a percentage of + the usage allowance. + name: + type: string + description: Optional user-defined label to distinguish multiple alerts on the + same feature. + required: + - threshold + - threshold_type + description: List of usage alert configurations per feature. description: Billing controls for the customer (auto top-ups, etc.) subscriptions: type: array @@ -1789,6 +1953,7 @@ paths: enum: - active - scheduled + type: string description: Current status of the subscription. past_due: type: boolean @@ -1917,6 +2082,7 @@ paths: - boolean - metered - credit_system + type: string description: "Feature type: 'boolean' for on/off access, 'metered' for usage-tracked features, 'credit_system' for unified credit pools." @@ -2219,6 +2385,7 @@ paths: - day - week - month + type: string description: The time interval for the purchase limit window. interval_count: type: number @@ -2255,6 +2422,40 @@ paths: minimum: 0 description: Maximum allowed overage spend for the target feature. description: List of overage spend limits per feature. + usage_alerts: + type: array + items: + type: object + properties: + feature_id: + type: string + description: The feature ID this alert applies to. If omitted, the alert applies + globally. + enabled: + type: boolean + default: true + description: Whether this usage alert is enabled. + threshold: + type: number + minimum: 0 + description: The threshold value that triggers the alert. For usage, this is an + absolute count. For usage_percentage, this is a + percentage (0-100). + threshold_type: + enum: + - usage + - usage_percentage + type: string + description: Whether the threshold is an absolute usage count or a percentage of + the usage allowance. + name: + type: string + description: Optional user-defined label to distinguish multiple alerts on the + same feature. + required: + - threshold + - threshold_type + description: List of usage alert configurations per feature. description: Billing controls for the customer (auto top-ups, etc.) new_customer_id: $ref: "#/components/schemas/CustomerId" @@ -2307,6 +2508,7 @@ paths: enum: - sandbox - live + type: string description: The environment this customer was created in. metadata: type: object @@ -2349,6 +2551,7 @@ paths: - day - week - month + type: string description: The time interval for the purchase limit window. interval_count: type: number @@ -2385,6 +2588,40 @@ paths: minimum: 0 description: Maximum allowed overage spend for the target feature. description: List of overage spend limits per feature. + usage_alerts: + type: array + items: + type: object + properties: + feature_id: + type: string + description: The feature ID this alert applies to. If omitted, the alert applies + globally. + enabled: + type: boolean + default: true + description: Whether this usage alert is enabled. + threshold: + type: number + minimum: 0 + description: The threshold value that triggers the alert. For usage, this is an + absolute count. For usage_percentage, this is a + percentage (0-100). + threshold_type: + enum: + - usage + - usage_percentage + type: string + description: Whether the threshold is an absolute usage count or a percentage of + the usage allowance. + name: + type: string + description: Optional user-defined label to distinguish multiple alerts on the + same feature. + required: + - threshold + - threshold_type + description: List of usage alert configurations per feature. description: Billing controls for the customer (auto top-ups, etc.) subscriptions: type: array @@ -2412,6 +2649,7 @@ paths: enum: - active - scheduled + type: string description: Current status of the subscription. past_due: type: boolean @@ -2540,6 +2778,7 @@ paths: - boolean - metered - credit_system + type: string description: "Feature type: 'boolean' for on/off access, 'metered' for usage-tracked features, 'credit_system' for unified credit pools." @@ -2857,6 +3096,7 @@ paths: - quarter - semi_annual - year + type: string description: Billing interval (e.g. 'month', 'year'). interval_count: type: number @@ -2895,6 +3135,7 @@ paths: - quarter - semi_annual - year + type: string description: Interval at which balance resets (e.g. 'month', 'year'). For consumable features only. interval_count: @@ -2931,6 +3172,7 @@ paths: enum: - graduated - volume + type: string interval: enum: - one_off @@ -2939,6 +3181,7 @@ paths: - quarter - semi_annual - year + type: string description: Billing interval. For consumable features, should match reset.interval. interval_count: @@ -2954,6 +3197,7 @@ paths: enum: - prepaid - usage_based + type: string description: "'prepaid' for upfront payment (seats), 'usage_based' for pay-as-you-go." max_purchase: @@ -2973,6 +3217,7 @@ paths: - prorate_immediately - prorate_next_cycle - bill_next_cycle + type: string description: Billing behavior when quantity increases mid-cycle. on_decrease: enum: @@ -2981,6 +3226,7 @@ paths: - prorate_next_cycle - none - no_prorations + type: string description: Credit behavior when quantity decreases mid-cycle. required: - on_increase @@ -2997,6 +3243,7 @@ paths: enum: - month - forever + type: string description: When rolled over units expire. expiry_duration_length: type: number @@ -3023,6 +3270,7 @@ paths: - day - month - year + type: string default: month description: Unit of time for the trial ('day', 'month', 'year'). card_required: @@ -3127,6 +3375,7 @@ paths: - quarter - semi_annual - year + type: string description: Billing interval (e.g. 'month', 'year'). interval_count: type: number @@ -3176,6 +3425,7 @@ paths: - single_use - continuous_use - credit_system + type: string description: The type of the feature display: anyOf: @@ -3240,6 +3490,7 @@ paths: - quarter - semi_annual - year + type: string description: The interval at which the feature balance resets (e.g. 'month', 'year'). For consumable features, usage resets to 0 and included units are restored. @@ -3273,6 +3524,7 @@ paths: enum: - graduated - volume + type: string interval: enum: - one_off @@ -3281,6 +3533,7 @@ paths: - quarter - semi_annual - year + type: string description: Billing interval for this price. For consumable features, should match reset.interval. interval_count: @@ -3296,6 +3549,7 @@ paths: enum: - prepaid - usage_based + type: string description: "'prepaid' for features like seats where customers pay upfront, 'usage_based' for pay-as-you-go after included usage." @@ -3339,6 +3593,7 @@ paths: enum: - month - forever + type: string description: When rolled over units expire. expiry_duration_length: type: number @@ -3367,6 +3622,7 @@ paths: - day - month - year + type: string description: Unit of time for the trial duration ('day', 'month', 'year'). card_required: type: boolean @@ -3385,6 +3641,7 @@ paths: enum: - sandbox - live + type: string description: Environment this plan belongs to ('sandbox' or 'live'). archived: type: boolean @@ -3407,6 +3664,7 @@ paths: enum: - active - scheduled + type: string description: The customer's current status with this plan. 'active' if attached, 'scheduled' if pending activation. canceling: @@ -3423,6 +3681,7 @@ paths: - downgrade - none - purchase + type: string description: The action that would occur if this plan were attached to the customer. required: @@ -3608,6 +3867,7 @@ paths: - quarter - semi_annual - year + type: string description: Billing interval (e.g. 'month', 'year'). interval_count: type: number @@ -3657,6 +3917,7 @@ paths: - single_use - continuous_use - credit_system + type: string description: The type of the feature display: anyOf: @@ -3721,6 +3982,7 @@ paths: - quarter - semi_annual - year + type: string description: The interval at which the feature balance resets (e.g. 'month', 'year'). For consumable features, usage resets to 0 and included units are restored. @@ -3754,6 +4016,7 @@ paths: enum: - graduated - volume + type: string interval: enum: - one_off @@ -3762,6 +4025,7 @@ paths: - quarter - semi_annual - year + type: string description: Billing interval for this price. For consumable features, should match reset.interval. interval_count: @@ -3777,6 +4041,7 @@ paths: enum: - prepaid - usage_based + type: string description: "'prepaid' for features like seats where customers pay upfront, 'usage_based' for pay-as-you-go after included usage." @@ -3820,6 +4085,7 @@ paths: enum: - month - forever + type: string description: When rolled over units expire. expiry_duration_length: type: number @@ -3848,6 +4114,7 @@ paths: - day - month - year + type: string description: Unit of time for the trial duration ('day', 'month', 'year'). card_required: type: boolean @@ -3866,6 +4133,7 @@ paths: enum: - sandbox - live + type: string description: Environment this plan belongs to ('sandbox' or 'live'). archived: type: boolean @@ -3888,6 +4156,7 @@ paths: enum: - active - scheduled + type: string description: The customer's current status with this plan. 'active' if attached, 'scheduled' if pending activation. canceling: @@ -3904,6 +4173,7 @@ paths: - downgrade - none - purchase + type: string description: The action that would occur if this plan were attached to the customer. required: @@ -4067,6 +4337,7 @@ paths: - quarter - semi_annual - year + type: string description: Billing interval (e.g. 'month', 'year'). interval_count: type: number @@ -4116,6 +4387,7 @@ paths: - single_use - continuous_use - credit_system + type: string description: The type of the feature display: anyOf: @@ -4180,6 +4452,7 @@ paths: - quarter - semi_annual - year + type: string description: The interval at which the feature balance resets (e.g. 'month', 'year'). For consumable features, usage resets to 0 and included units @@ -4214,6 +4487,7 @@ paths: enum: - graduated - volume + type: string interval: enum: - one_off @@ -4222,6 +4496,7 @@ paths: - quarter - semi_annual - year + type: string description: Billing interval for this price. For consumable features, should match reset.interval. interval_count: @@ -4237,6 +4512,7 @@ paths: enum: - prepaid - usage_based + type: string description: "'prepaid' for features like seats where customers pay upfront, 'usage_based' for pay-as-you-go after included usage." @@ -4281,6 +4557,7 @@ paths: enum: - month - forever + type: string description: When rolled over units expire. expiry_duration_length: type: number @@ -4310,6 +4587,7 @@ paths: - day - month - year + type: string description: Unit of time for the trial duration ('day', 'month', 'year'). card_required: type: boolean @@ -4328,6 +4606,7 @@ paths: enum: - sandbox - live + type: string description: Environment this plan belongs to ('sandbox' or 'live'). archived: type: boolean @@ -4350,6 +4629,7 @@ paths: enum: - active - scheduled + type: string description: The customer's current status with this plan. 'active' if attached, 'scheduled' if pending activation. canceling: @@ -4366,6 +4646,7 @@ paths: - downgrade - none - purchase + type: string description: The action that would occur if this plan were attached to the customer. required: @@ -4533,6 +4814,7 @@ paths: - quarter - semi_annual - year + type: string description: Billing interval (e.g. 'month', 'year'). interval_count: type: number @@ -4573,6 +4855,7 @@ paths: - quarter - semi_annual - year + type: string description: Interval at which balance resets (e.g. 'month', 'year'). For consumable features only. interval_count: @@ -4609,6 +4892,7 @@ paths: enum: - graduated - volume + type: string interval: enum: - one_off @@ -4617,6 +4901,7 @@ paths: - quarter - semi_annual - year + type: string description: Billing interval. For consumable features, should match reset.interval. interval_count: @@ -4632,6 +4917,7 @@ paths: enum: - prepaid - usage_based + type: string description: "'prepaid' for upfront payment (seats), 'usage_based' for pay-as-you-go." max_purchase: @@ -4651,6 +4937,7 @@ paths: - prorate_immediately - prorate_next_cycle - bill_next_cycle + type: string description: Billing behavior when quantity increases mid-cycle. on_decrease: enum: @@ -4659,6 +4946,7 @@ paths: - prorate_next_cycle - none - no_prorations + type: string description: Credit behavior when quantity decreases mid-cycle. required: - on_increase @@ -4675,6 +4963,7 @@ paths: enum: - month - forever + type: string description: When rolled over units expire. expiry_duration_length: type: number @@ -4702,6 +4991,7 @@ paths: - day - month - year + type: string default: month description: Unit of time for the trial ('day', 'month', 'year'). card_required: @@ -4791,6 +5081,7 @@ paths: - quarter - semi_annual - year + type: string description: Billing interval (e.g. 'month', 'year'). interval_count: type: number @@ -4840,6 +5131,7 @@ paths: - single_use - continuous_use - credit_system + type: string description: The type of the feature display: anyOf: @@ -4904,6 +5196,7 @@ paths: - quarter - semi_annual - year + type: string description: The interval at which the feature balance resets (e.g. 'month', 'year'). For consumable features, usage resets to 0 and included units are restored. @@ -4937,6 +5230,7 @@ paths: enum: - graduated - volume + type: string interval: enum: - one_off @@ -4945,6 +5239,7 @@ paths: - quarter - semi_annual - year + type: string description: Billing interval for this price. For consumable features, should match reset.interval. interval_count: @@ -4960,6 +5255,7 @@ paths: enum: - prepaid - usage_based + type: string description: "'prepaid' for features like seats where customers pay upfront, 'usage_based' for pay-as-you-go after included usage." @@ -5003,6 +5299,7 @@ paths: enum: - month - forever + type: string description: When rolled over units expire. expiry_duration_length: type: number @@ -5031,6 +5328,7 @@ paths: - day - month - year + type: string description: Unit of time for the trial duration ('day', 'month', 'year'). card_required: type: boolean @@ -5049,6 +5347,7 @@ paths: enum: - sandbox - live + type: string description: Environment this plan belongs to ('sandbox' or 'live'). archived: type: boolean @@ -5071,6 +5370,7 @@ paths: enum: - active - scheduled + type: string description: The customer's current status with this plan. 'active' if attached, 'scheduled' if pending activation. canceling: @@ -5087,6 +5387,7 @@ paths: - downgrade - none - purchase + type: string description: The action that would occur if this plan were attached to the customer. required: @@ -5316,6 +5617,7 @@ paths: - boolean - metered - credit_system + type: string description: The type of the feature. 'single_use' features are consumed, like API calls, tokens, or messages. 'continuous_use' features are allocated, like seats, workspaces, or projects. @@ -5399,6 +5701,7 @@ paths: - boolean - metered - credit_system + type: string description: "Feature type: 'boolean' for on/off access, 'metered' for usage-tracked features, 'credit_system' for unified credit pools." @@ -5519,6 +5822,7 @@ paths: - boolean - metered - credit_system + type: string description: "Feature type: 'boolean' for on/off access, 'metered' for usage-tracked features, 'credit_system' for unified credit pools." @@ -5624,6 +5928,7 @@ paths: - boolean - metered - credit_system + type: string description: "Feature type: 'boolean' for on/off access, 'metered' for usage-tracked features, 'credit_system' for unified credit pools." @@ -5789,6 +6094,7 @@ paths: - boolean - metered - credit_system + type: string description: The type of the feature. 'single_use' features are consumed, like API calls, tokens, or messages. 'continuous_use' features are allocated, like seats, workspaces, or projects. @@ -5872,6 +6178,7 @@ paths: - boolean - metered - credit_system + type: string description: "Feature type: 'boolean' for on/off access, 'metered' for usage-tracked features, 'credit_system' for unified credit pools." @@ -6178,6 +6485,7 @@ paths: - quarter - semi_annual - year + type: string description: Billing interval (e.g. 'month', 'year'). interval_count: type: number @@ -6219,6 +6527,7 @@ paths: - quarter - semi_annual - year + type: string description: Interval at which balance resets (e.g. 'month', 'year'). For consumable features only. interval_count: @@ -6255,6 +6564,7 @@ paths: enum: - graduated - volume + type: string interval: enum: - one_off @@ -6263,6 +6573,7 @@ paths: - quarter - semi_annual - year + type: string description: Billing interval. For consumable features, should match reset.interval. interval_count: @@ -6278,6 +6589,7 @@ paths: enum: - prepaid - usage_based + type: string description: "'prepaid' for upfront payment (seats), 'usage_based' for pay-as-you-go." max_purchase: @@ -6297,6 +6609,7 @@ paths: - prorate_immediately - prorate_next_cycle - bill_next_cycle + type: string description: Billing behavior when quantity increases mid-cycle. on_decrease: enum: @@ -6305,6 +6618,7 @@ paths: - prorate_next_cycle - none - no_prorations + type: string description: Credit behavior when quantity decreases mid-cycle. required: - on_increase @@ -6321,6 +6635,7 @@ paths: enum: - month - forever + type: string description: When rolled over units expire. expiry_duration_length: type: number @@ -6347,6 +6662,7 @@ paths: - day - month - year + type: string default: month description: Unit of time for the trial ('day', 'month', 'year'). card_required: @@ -6390,6 +6706,7 @@ paths: enum: - prorate_immediately - none + type: string description: How to handle proration when updating an existing subscription. 'prorate_immediately' charges/credits prorated amounts now, 'none' skips creating any charges. @@ -6398,6 +6715,7 @@ paths: - always - if_required - never + type: string description: Controls when to return a checkout URL. 'always' returns a URL even if payment succeeds, 'if_required' only when payment action is needed, 'never' disables redirects. @@ -6434,6 +6752,7 @@ paths: enum: - immediate - end_of_cycle + type: string description: When the plan change should take effect. 'immediate' applies now, 'end_of_cycle' schedules for the end of the current billing cycle. By default, upgrades are immediate and downgrades are @@ -6563,6 +6882,7 @@ paths: - 3ds_required - payment_method_required - payment_failed + type: string description: The type of action required to complete the payment. reason: type: string @@ -6661,6 +6981,7 @@ paths: - quarter - semi_annual - year + type: string description: Billing interval (e.g. 'month', 'year'). interval_count: type: number @@ -6702,6 +7023,7 @@ paths: - quarter - semi_annual - year + type: string description: Interval at which balance resets (e.g. 'month', 'year'). For consumable features only. interval_count: @@ -6738,6 +7060,7 @@ paths: enum: - graduated - volume + type: string interval: enum: - one_off @@ -6746,6 +7069,7 @@ paths: - quarter - semi_annual - year + type: string description: Billing interval. For consumable features, should match reset.interval. interval_count: @@ -6762,6 +7086,7 @@ paths: enum: - prepaid - usage_based + type: string description: "'prepaid' for upfront payment (seats), 'usage_based' for pay-as-you-go." max_purchase: @@ -6781,6 +7106,7 @@ paths: - prorate_immediately - prorate_next_cycle - bill_next_cycle + type: string description: Billing behavior when quantity increases mid-cycle. on_decrease: enum: @@ -6789,6 +7115,7 @@ paths: - prorate_next_cycle - none - no_prorations + type: string description: Credit behavior when quantity decreases mid-cycle. required: - on_increase @@ -6805,6 +7132,7 @@ paths: enum: - month - forever + type: string description: When rolled over units expire. expiry_duration_length: type: number @@ -6863,6 +7191,7 @@ paths: - day - month - year + type: string default: month description: Unit of time for the trial ('day', 'month', 'year'). card_required: @@ -6929,6 +7258,7 @@ paths: - always - if_required - never + type: string description: Controls when to return a checkout URL. 'always' returns a URL even if payment succeeds, 'if_required' only when payment action is needed, 'never' disables redirects. @@ -6969,6 +7299,40 @@ paths: minimum: 0 description: Maximum allowed overage spend for the target feature. description: List of overage spend limits per feature. + usage_alerts: + type: array + items: + type: object + properties: + feature_id: + type: string + description: The feature ID this alert applies to. If omitted, the alert applies + globally. + enabled: + type: boolean + default: true + description: Whether this usage alert is enabled. + threshold: + type: number + minimum: 0 + description: The threshold value that triggers the alert. For usage, this is an + absolute count. For usage_percentage, this is + a percentage (0-100). + threshold_type: + enum: + - usage + - usage_percentage + type: string + description: Whether the threshold is an absolute usage count or a percentage of + the usage allowance. + name: + type: string + description: Optional user-defined label to distinguish multiple alerts on the + same feature. + required: + - threshold + - threshold_type + description: List of usage alert configurations per feature. description: Billing controls for the entity. required: - feature_id @@ -7043,6 +7407,7 @@ paths: - 3ds_required - payment_method_required - payment_failed + type: string description: The type of action required to complete the payment. reason: type: string @@ -7220,6 +7585,7 @@ paths: - quarter - semi_annual - year + type: string description: Billing interval (e.g. 'month', 'year'). interval_count: type: number @@ -7261,6 +7627,7 @@ paths: - quarter - semi_annual - year + type: string description: Interval at which balance resets (e.g. 'month', 'year'). For consumable features only. interval_count: @@ -7297,6 +7664,7 @@ paths: enum: - graduated - volume + type: string interval: enum: - one_off @@ -7305,6 +7673,7 @@ paths: - quarter - semi_annual - year + type: string description: Billing interval. For consumable features, should match reset.interval. interval_count: @@ -7320,6 +7689,7 @@ paths: enum: - prepaid - usage_based + type: string description: "'prepaid' for upfront payment (seats), 'usage_based' for pay-as-you-go." max_purchase: @@ -7339,6 +7709,7 @@ paths: - prorate_immediately - prorate_next_cycle - bill_next_cycle + type: string description: Billing behavior when quantity increases mid-cycle. on_decrease: enum: @@ -7347,6 +7718,7 @@ paths: - prorate_next_cycle - none - no_prorations + type: string description: Credit behavior when quantity decreases mid-cycle. required: - on_increase @@ -7363,6 +7735,7 @@ paths: enum: - month - forever + type: string description: When rolled over units expire. expiry_duration_length: type: number @@ -7389,6 +7762,7 @@ paths: - day - month - year + type: string default: month description: Unit of time for the trial ('day', 'month', 'year'). card_required: @@ -7432,6 +7806,7 @@ paths: enum: - prorate_immediately - none + type: string description: How to handle proration when updating an existing subscription. 'prorate_immediately' charges/credits prorated amounts now, 'none' skips creating any charges. @@ -7440,6 +7815,7 @@ paths: - always - if_required - never + type: string description: Controls when to return a checkout URL. 'always' returns a URL even if payment succeeds, 'if_required' only when payment action is needed, 'never' disables redirects. @@ -7476,6 +7852,7 @@ paths: enum: - immediate - end_of_cycle + type: string description: When the plan change should take effect. 'immediate' applies now, 'end_of_cycle' schedules for the end of the current billing cycle. By default, upgrades are immediate and downgrades are @@ -7799,10 +8176,24 @@ paths: - type: "null" description: When this change takes effect, in milliseconds since the Unix epoch, or null if it applies immediately. + canceled_at: + anyOf: + - type: number + - type: "null" + description: When this plan was canceled, in milliseconds since the Unix epoch, + or null if it is not canceled. + expires_at: + anyOf: + - type: number + - type: "null" + description: When this plan expires, in milliseconds since the Unix epoch, or + null if it does not expire. required: - plan_id - feature_quantities - effective_at + - canceled_at + - expires_at description: Products or subscription changes being added or updated. outgoing: type: array @@ -7836,10 +8227,24 @@ paths: - type: "null" description: When this change takes effect, in milliseconds since the Unix epoch, or null if it applies immediately. + canceled_at: + anyOf: + - type: number + - type: "null" + description: When this plan was canceled, in milliseconds since the Unix epoch, + or null if it is not canceled. + expires_at: + anyOf: + - type: number + - type: "null" + description: When this plan expires, in milliseconds since the Unix epoch, or + null if it does not expire. required: - plan_id - feature_quantities - effective_at + - canceled_at + - expires_at description: Products or subscription changes being removed or ended. required: - customer_id @@ -7931,6 +8336,7 @@ paths: - quarter - semi_annual - year + type: string description: Billing interval (e.g. 'month', 'year'). interval_count: type: number @@ -7972,6 +8378,7 @@ paths: - quarter - semi_annual - year + type: string description: Interval at which balance resets (e.g. 'month', 'year'). For consumable features only. interval_count: @@ -8008,6 +8415,7 @@ paths: enum: - graduated - volume + type: string interval: enum: - one_off @@ -8016,6 +8424,7 @@ paths: - quarter - semi_annual - year + type: string description: Billing interval. For consumable features, should match reset.interval. interval_count: @@ -8032,6 +8441,7 @@ paths: enum: - prepaid - usage_based + type: string description: "'prepaid' for upfront payment (seats), 'usage_based' for pay-as-you-go." max_purchase: @@ -8051,6 +8461,7 @@ paths: - prorate_immediately - prorate_next_cycle - bill_next_cycle + type: string description: Billing behavior when quantity increases mid-cycle. on_decrease: enum: @@ -8059,6 +8470,7 @@ paths: - prorate_next_cycle - none - no_prorations + type: string description: Credit behavior when quantity decreases mid-cycle. required: - on_increase @@ -8075,6 +8487,7 @@ paths: enum: - month - forever + type: string description: When rolled over units expire. expiry_duration_length: type: number @@ -8133,6 +8546,7 @@ paths: - day - month - year + type: string default: month description: Unit of time for the trial ('day', 'month', 'year'). card_required: @@ -8199,6 +8613,7 @@ paths: - always - if_required - never + type: string description: Controls when to return a checkout URL. 'always' returns a URL even if payment succeeds, 'if_required' only when payment action is needed, 'never' disables redirects. @@ -8239,6 +8654,40 @@ paths: minimum: 0 description: Maximum allowed overage spend for the target feature. description: List of overage spend limits per feature. + usage_alerts: + type: array + items: + type: object + properties: + feature_id: + type: string + description: The feature ID this alert applies to. If omitted, the alert applies + globally. + enabled: + type: boolean + default: true + description: Whether this usage alert is enabled. + threshold: + type: number + minimum: 0 + description: The threshold value that triggers the alert. For usage, this is an + absolute count. For usage_percentage, this is + a percentage (0-100). + threshold_type: + enum: + - usage + - usage_percentage + type: string + description: Whether the threshold is an absolute usage count or a percentage of + the usage allowance. + name: + type: string + description: Optional user-defined label to distinguish multiple alerts on the + same feature. + required: + - threshold + - threshold_type + description: List of usage alert configurations per feature. description: Billing controls for the entity. required: - feature_id @@ -8507,10 +8956,24 @@ paths: - type: "null" description: When this change takes effect, in milliseconds since the Unix epoch, or null if it applies immediately. + canceled_at: + anyOf: + - type: number + - type: "null" + description: When this plan was canceled, in milliseconds since the Unix epoch, + or null if it is not canceled. + expires_at: + anyOf: + - type: number + - type: "null" + description: When this plan expires, in milliseconds since the Unix epoch, or + null if it does not expire. required: - plan_id - feature_quantities - effective_at + - canceled_at + - expires_at description: Products or subscription changes being added or updated. outgoing: type: array @@ -8544,10 +9007,24 @@ paths: - type: "null" description: When this change takes effect, in milliseconds since the Unix epoch, or null if it applies immediately. + canceled_at: + anyOf: + - type: number + - type: "null" + description: When this plan was canceled, in milliseconds since the Unix epoch, + or null if it is not canceled. + expires_at: + anyOf: + - type: number + - type: "null" + description: When this plan expires, in milliseconds since the Unix epoch, or + null if it does not expire. required: - plan_id - feature_quantities - effective_at + - canceled_at + - expires_at description: Products or subscription changes being removed or ended. required: - customer_id @@ -8662,6 +9139,9 @@ paths: @param noBillingChanges - If true, the subscription is updated internally without applying billing changes in Stripe. (optional) + @param recalculateBalances - Controls whether balances should be + recalculated during the subscription update. (optional) + @returns A billing response with customer ID, invoice details, and payment URL (if next action is required). @@ -8728,6 +9208,7 @@ paths: - quarter - semi_annual - year + type: string description: Billing interval (e.g. 'month', 'year'). interval_count: type: number @@ -8769,6 +9250,7 @@ paths: - quarter - semi_annual - year + type: string description: Interval at which balance resets (e.g. 'month', 'year'). For consumable features only. interval_count: @@ -8805,6 +9287,7 @@ paths: enum: - graduated - volume + type: string interval: enum: - one_off @@ -8813,6 +9296,7 @@ paths: - quarter - semi_annual - year + type: string description: Billing interval. For consumable features, should match reset.interval. interval_count: @@ -8828,6 +9312,7 @@ paths: enum: - prepaid - usage_based + type: string description: "'prepaid' for upfront payment (seats), 'usage_based' for pay-as-you-go." max_purchase: @@ -8847,6 +9332,7 @@ paths: - prorate_immediately - prorate_next_cycle - bill_next_cycle + type: string description: Billing behavior when quantity increases mid-cycle. on_decrease: enum: @@ -8855,6 +9341,7 @@ paths: - prorate_next_cycle - none - no_prorations + type: string description: Credit behavior when quantity decreases mid-cycle. required: - on_increase @@ -8871,6 +9358,7 @@ paths: enum: - month - forever + type: string description: When rolled over units expire. expiry_duration_length: type: number @@ -8897,6 +9385,7 @@ paths: - day - month - year + type: string default: month description: Unit of time for the trial ('day', 'month', 'year'). card_required: @@ -8940,6 +9429,7 @@ paths: enum: - prorate_immediately - none + type: string description: How to handle proration when updating an existing subscription. 'prorate_immediately' charges/credits prorated amounts now, 'none' skips creating any charges. @@ -8948,6 +9438,7 @@ paths: - always - if_required - never + type: string description: Controls when to return a checkout URL. 'always' returns a URL even if payment succeeds, 'if_required' only when payment action is needed, 'never' disables redirects. @@ -8962,6 +9453,7 @@ paths: - cancel_immediately - cancel_end_of_cycle - uncancel + type: string description: Action to perform for cancellation. 'cancel_immediately' cancels now with prorated refund, 'cancel_end_of_cycle' cancels at period end, 'uncancel' reverses a pending cancellation. @@ -8969,6 +9461,17 @@ paths: type: boolean description: If true, the subscription is updated internally without applying billing changes in Stripe. + recalculate_balances: + type: object + properties: + enabled: + type: boolean + description: If true, recalculates balances during the subscription update. Only + applicable when updating feature quantities. + required: + - enabled + description: Controls whether balances should be recalculated during the + subscription update. required: - customer_id title: UpdateSubscriptionParams @@ -9037,6 +9540,7 @@ paths: - 3ds_required - payment_method_required - payment_failed + type: string description: The type of action required to complete the payment. reason: type: string @@ -9128,6 +9632,9 @@ paths: @param noBillingChanges - If true, the subscription is updated internally without applying billing changes in Stripe. (optional) + @param recalculateBalances - Controls whether balances should be + recalculated during the subscription update. (optional) + @returns A preview response with line items showing prorated charges or credits for the proposed changes. @@ -9194,6 +9701,7 @@ paths: - quarter - semi_annual - year + type: string description: Billing interval (e.g. 'month', 'year'). interval_count: type: number @@ -9235,6 +9743,7 @@ paths: - quarter - semi_annual - year + type: string description: Interval at which balance resets (e.g. 'month', 'year'). For consumable features only. interval_count: @@ -9271,6 +9780,7 @@ paths: enum: - graduated - volume + type: string interval: enum: - one_off @@ -9279,6 +9789,7 @@ paths: - quarter - semi_annual - year + type: string description: Billing interval. For consumable features, should match reset.interval. interval_count: @@ -9294,6 +9805,7 @@ paths: enum: - prepaid - usage_based + type: string description: "'prepaid' for upfront payment (seats), 'usage_based' for pay-as-you-go." max_purchase: @@ -9313,6 +9825,7 @@ paths: - prorate_immediately - prorate_next_cycle - bill_next_cycle + type: string description: Billing behavior when quantity increases mid-cycle. on_decrease: enum: @@ -9321,6 +9834,7 @@ paths: - prorate_next_cycle - none - no_prorations + type: string description: Credit behavior when quantity decreases mid-cycle. required: - on_increase @@ -9337,6 +9851,7 @@ paths: enum: - month - forever + type: string description: When rolled over units expire. expiry_duration_length: type: number @@ -9363,6 +9878,7 @@ paths: - day - month - year + type: string default: month description: Unit of time for the trial ('day', 'month', 'year'). card_required: @@ -9406,6 +9922,7 @@ paths: enum: - prorate_immediately - none + type: string description: How to handle proration when updating an existing subscription. 'prorate_immediately' charges/credits prorated amounts now, 'none' skips creating any charges. @@ -9414,6 +9931,7 @@ paths: - always - if_required - never + type: string description: Controls when to return a checkout URL. 'always' returns a URL even if payment succeeds, 'if_required' only when payment action is needed, 'never' disables redirects. @@ -9428,6 +9946,7 @@ paths: - cancel_immediately - cancel_end_of_cycle - uncancel + type: string description: Action to perform for cancellation. 'cancel_immediately' cancels now with prorated refund, 'cancel_end_of_cycle' cancels at period end, 'uncancel' reverses a pending cancellation. @@ -9435,6 +9954,17 @@ paths: type: boolean description: If true, the subscription is updated internally without applying billing changes in Stripe. + recalculate_balances: + type: object + properties: + enabled: + type: boolean + description: If true, recalculates balances during the subscription update. Only + applicable when updating feature quantities. + required: + - enabled + description: Controls whether balances should be recalculated during the + subscription update. required: - customer_id title: PreviewUpdateParams @@ -9697,10 +10227,24 @@ paths: - type: "null" description: When this change takes effect, in milliseconds since the Unix epoch, or null if it applies immediately. + canceled_at: + anyOf: + - type: number + - type: "null" + description: When this plan was canceled, in milliseconds since the Unix epoch, + or null if it is not canceled. + expires_at: + anyOf: + - type: number + - type: "null" + description: When this plan expires, in milliseconds since the Unix epoch, or + null if it does not expire. required: - plan_id - feature_quantities - effective_at + - canceled_at + - expires_at description: Products or subscription changes being added or updated. outgoing: type: array @@ -9734,10 +10278,24 @@ paths: - type: "null" description: When this change takes effect, in milliseconds since the Unix epoch, or null if it applies immediately. + canceled_at: + anyOf: + - type: number + - type: "null" + description: When this plan was canceled, in milliseconds since the Unix epoch, + or null if it is not canceled. + expires_at: + anyOf: + - type: number + - type: "null" + description: When this plan expires, in milliseconds since the Unix epoch, or + null if it does not expire. required: - plan_id - feature_quantities - effective_at + - canceled_at + - expires_at description: Products or subscription changes being removed or ended. intent: enum: @@ -9747,6 +10305,7 @@ paths: - cancel_end_of_cycle - uncancel - none + type: string required: - customer_id - line_items @@ -9892,6 +10451,7 @@ paths: - quarter - semi_annual - year + type: string description: Billing interval (e.g. 'month', 'year'). interval_count: type: number @@ -9933,6 +10493,7 @@ paths: - quarter - semi_annual - year + type: string description: Interval at which balance resets (e.g. 'month', 'year'). For consumable features only. interval_count: @@ -9969,6 +10530,7 @@ paths: enum: - graduated - volume + type: string interval: enum: - one_off @@ -9977,6 +10539,7 @@ paths: - quarter - semi_annual - year + type: string description: Billing interval. For consumable features, should match reset.interval. interval_count: @@ -9992,6 +10555,7 @@ paths: enum: - prepaid - usage_based + type: string description: "'prepaid' for upfront payment (seats), 'usage_based' for pay-as-you-go." max_purchase: @@ -10011,6 +10575,7 @@ paths: - prorate_immediately - prorate_next_cycle - bill_next_cycle + type: string description: Billing behavior when quantity increases mid-cycle. on_decrease: enum: @@ -10019,6 +10584,7 @@ paths: - prorate_next_cycle - none - no_prorations + type: string description: Credit behavior when quantity decreases mid-cycle. required: - on_increase @@ -10035,6 +10601,7 @@ paths: enum: - month - forever + type: string description: When rolled over units expire. expiry_duration_length: type: number @@ -10061,6 +10628,7 @@ paths: - day - month - year + type: string default: month description: Unit of time for the trial ('day', 'month', 'year'). card_required: @@ -10081,6 +10649,7 @@ paths: enum: - prorate_immediately - none + type: string description: How to handle proration when updating an existing subscription. 'prorate_immediately' charges/credits prorated amounts now, 'none' skips creating any charges. @@ -10245,6 +10814,7 @@ paths: - quarter - semi_annual - year + type: string description: The interval at which the balance resets (e.g., 'month', 'day', 'year'). interval_count: @@ -10335,6 +10905,7 @@ paths: - quarter - semi_annual - year + type: string description: Target a specific balance by its reset interval. Use when the customer has multiple balances for the same feature with different reset intervals. @@ -10411,6 +10982,7 @@ paths: - quarter - semi_annual - year + type: string description: Target a specific balance by its reset interval. Use when the customer has multiple balances for the same feature with different reset intervals. @@ -10456,6 +11028,7 @@ paths: enum: - confirm - release + type: string description: Use 'confirm' to commit the deduction, or 'release' to return the held balance. override_value: @@ -10695,6 +11268,7 @@ paths: - boolean - metered - credit_system + type: string description: "Feature type: 'boolean' for on/off access, 'metered' for usage-tracked features, 'credit_system' for unified credit pools." @@ -10769,6 +11343,7 @@ paths: enum: - usage_limit - feature_flag + type: string description: The reason access was denied. 'usage_limit' means the customer exceeded their balance, 'feature_flag' means the feature is not included in their plan. @@ -10804,6 +11379,7 @@ paths: enum: - sandbox - live + type: string description: The environment of the product is_add_on: type: boolean @@ -10833,6 +11409,7 @@ paths: - feature - priced_feature - price + type: string - type: "null" description: The type of the product item feature_id: @@ -10848,6 +11425,7 @@ paths: - continuous_use - boolean - static + type: string - type: "null" description: Single use features are used once and then depleted, like API calls or credits. Continuous use features are @@ -10871,6 +11449,7 @@ paths: - quarter - semi_annual - year + type: string - type: "null" description: The reset or billing interval of the product item. If null, feature will have no reset date, and if there's a @@ -10901,6 +11480,7 @@ paths: - enum: - graduated - volume + type: string - type: "null" description: "How tiers are applied: graduated (split across bands) or volume (flat rate for the matched tier). Defaults @@ -10910,6 +11490,7 @@ paths: - enum: - prepaid - pay_per_use + type: string - type: "null" description: Whether the feature should be prepaid upfront or billed for how much they use end of billing period. @@ -10970,6 +11551,7 @@ paths: enum: - month - forever + type: string default: month length: type: number @@ -10984,6 +11566,7 @@ paths: - prorate_immediately - prorate_next_cycle - bill_next_cycle + type: string - type: "null" on_decrease: anyOf: @@ -10993,6 +11576,7 @@ paths: - prorate_next_cycle - none - no_prorations + type: string - type: "null" - type: "null" description: Configuration for rollover and proration behavior of the feature. @@ -11008,6 +11592,7 @@ paths: - day - month - year + type: string description: The duration type of the free trial length: type: number @@ -11052,6 +11637,7 @@ paths: - cancel - expired - past_due + type: string description: Scenario for when this product is used in attach flows properties: type: object @@ -11506,6 +12092,7 @@ paths: - last_cycle - 1bc - 3bc + type: string description: Time range to aggregate events for. Either range or custom_range must be provided bin_size: @@ -11513,6 +12100,7 @@ paths: - day - hour - month + type: string default: day description: Size of the time bins to aggregate events for. Defaults to hour if range is 24h, otherwise day @@ -11733,6 +12321,40 @@ paths: minimum: 0 description: Maximum allowed overage spend for the target feature. description: List of overage spend limits per feature. + usage_alerts: + type: array + items: + type: object + properties: + feature_id: + type: string + description: The feature ID this alert applies to. If omitted, the alert applies + globally. + enabled: + type: boolean + default: true + description: Whether this usage alert is enabled. + threshold: + type: number + minimum: 0 + description: The threshold value that triggers the alert. For usage, this is an + absolute count. For usage_percentage, this is a + percentage (0-100). + threshold_type: + enum: + - usage + - usage_percentage + type: string + description: Whether the threshold is an absolute usage count or a percentage of + the usage allowance. + name: + type: string + description: Optional user-defined label to distinguish multiple alerts on the + same feature. + required: + - threshold + - threshold_type + description: List of usage alert configurations per feature. description: Billing controls for the entity. customer_data: $ref: "#/components/schemas/CustomerData" @@ -11789,6 +12411,7 @@ paths: enum: - sandbox - live + type: string description: The environment (sandbox/live) subscriptions: type: array @@ -11816,6 +12439,7 @@ paths: enum: - active - scheduled + type: string description: Current status of the subscription. past_due: type: boolean @@ -11939,6 +12563,7 @@ paths: - boolean - metered - credit_system + type: string description: "Feature type: 'boolean' for on/off access, 'metered' for usage-tracked features, 'credit_system' for unified credit pools." @@ -12024,6 +12649,40 @@ paths: minimum: 0 description: Maximum allowed overage spend for the target feature. description: List of overage spend limits per feature. + usage_alerts: + type: array + items: + type: object + properties: + feature_id: + type: string + description: The feature ID this alert applies to. If omitted, the alert applies + globally. + enabled: + type: boolean + default: true + description: Whether this usage alert is enabled. + threshold: + type: number + minimum: 0 + description: The threshold value that triggers the alert. For usage, this is an + absolute count. For usage_percentage, this is a + percentage (0-100). + threshold_type: + enum: + - usage + - usage_percentage + type: string + description: Whether the threshold is an absolute usage count or a percentage of + the usage allowance. + name: + type: string + description: Optional user-defined label to distinguish multiple alerts on the + same feature. + required: + - threshold + - threshold_type + description: List of usage alert configurations per feature. description: Billing controls for the entity. invoices: type: array @@ -12219,6 +12878,7 @@ paths: enum: - sandbox - live + type: string description: The environment (sandbox/live) subscriptions: type: array @@ -12246,6 +12906,7 @@ paths: enum: - active - scheduled + type: string description: Current status of the subscription. past_due: type: boolean @@ -12369,6 +13030,7 @@ paths: - boolean - metered - credit_system + type: string description: "Feature type: 'boolean' for on/off access, 'metered' for usage-tracked features, 'credit_system' for unified credit pools." @@ -12454,6 +13116,40 @@ paths: minimum: 0 description: Maximum allowed overage spend for the target feature. description: List of overage spend limits per feature. + usage_alerts: + type: array + items: + type: object + properties: + feature_id: + type: string + description: The feature ID this alert applies to. If omitted, the alert applies + globally. + enabled: + type: boolean + default: true + description: Whether this usage alert is enabled. + threshold: + type: number + minimum: 0 + description: The threshold value that triggers the alert. For usage, this is an + absolute count. For usage_percentage, this is a + percentage (0-100). + threshold_type: + enum: + - usage + - usage_percentage + type: string + description: Whether the threshold is an absolute usage count or a percentage of + the usage allowance. + name: + type: string + description: Optional user-defined label to distinguish multiple alerts on the + same feature. + required: + - threshold + - threshold_type + description: List of usage alert configurations per feature. description: Billing controls for the entity. invoices: type: array @@ -12604,6 +13300,40 @@ paths: minimum: 0 description: Maximum allowed overage spend for the target feature. description: List of overage spend limits per feature. + usage_alerts: + type: array + items: + type: object + properties: + feature_id: + type: string + description: The feature ID this alert applies to. If omitted, the alert applies + globally. + enabled: + type: boolean + default: true + description: Whether this usage alert is enabled. + threshold: + type: number + minimum: 0 + description: The threshold value that triggers the alert. For usage, this is an + absolute count. For usage_percentage, this is a + percentage (0-100). + threshold_type: + enum: + - usage + - usage_percentage + type: string + description: Whether the threshold is an absolute usage count or a percentage of + the usage allowance. + name: + type: string + description: Optional user-defined label to distinguish multiple alerts on the + same feature. + required: + - threshold + - threshold_type + description: List of usage alert configurations per feature. description: Billing controls to replace on the entity. required: - entity_id @@ -12651,6 +13381,7 @@ paths: enum: - sandbox - live + type: string description: The environment (sandbox/live) subscriptions: type: array @@ -12678,6 +13409,7 @@ paths: enum: - active - scheduled + type: string description: Current status of the subscription. past_due: type: boolean @@ -12801,6 +13533,7 @@ paths: - boolean - metered - credit_system + type: string description: "Feature type: 'boolean' for on/off access, 'metered' for usage-tracked features, 'credit_system' for unified credit pools." @@ -12886,6 +13619,40 @@ paths: minimum: 0 description: Maximum allowed overage spend for the target feature. description: List of overage spend limits per feature. + usage_alerts: + type: array + items: + type: object + properties: + feature_id: + type: string + description: The feature ID this alert applies to. If omitted, the alert applies + globally. + enabled: + type: boolean + default: true + description: Whether this usage alert is enabled. + threshold: + type: number + minimum: 0 + description: The threshold value that triggers the alert. For usage, this is an + absolute count. For usage_percentage, this is a + percentage (0-100). + threshold_type: + enum: + - usage + - usage_percentage + type: string + description: Whether the threshold is an absolute usage count or a percentage of + the usage allowance. + name: + type: string + description: Optional user-defined label to distinguish multiple alerts on the + same feature. + required: + - threshold + - threshold_type + description: List of usage alert configurations per feature. description: Billing controls for the entity. invoices: type: array @@ -13167,3 +13934,317 @@ x-speakeasy-globals: type: string default: 2.2.0 x-speakeasy-globals-hidden: true +webhooks: + balances.usage_alert_triggered: + post: + operationId: balancesUsageAlertTriggered + summary: Usage Alert Triggered + description: Fired when a customer crosses a configured usage alert threshold. + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - type + - data + properties: + type: + type: string + const: balances.usage_alert_triggered + description: The webhook event type. + data: + examples: + - customer_id: org_123 + feature_id: api_calls + entity_id: workspace_abc + usage_alert: + name: 80% usage warning + threshold: 80 + threshold_type: usage_percentage_threshold + type: object + properties: + customer_id: + description: The ID of the customer whose usage alert was triggered. + type: string + feature_id: + description: The feature ID the alert applies to. + type: string + entity_id: + description: The entity ID the alert applies to, if the usage was entity-scoped. + type: string + usage_alert: + description: Details of the usage alert that was triggered. + type: object + properties: + name: + description: User-defined label for the alert, if provided. + type: string + threshold: + description: The threshold value that was crossed. + type: number + threshold_type: + description: Whether the threshold is an absolute usage count or a percentage. + type: string + enum: + - usage + - usage_percentage + required: + - threshold + - threshold_type + additionalProperties: false + required: + - customer_id + - feature_id + - usage_alert + additionalProperties: false + example: + type: balances.usage_alert_triggered + data: + customer_id: org_123 + feature_id: api_calls + entity_id: workspace_abc + usage_alert: + name: 80% usage warning + threshold: 80 + threshold_type: usage_percentage_threshold + responses: + "200": + description: Webhook received successfully. + balances.limit_reached: + post: + operationId: balancesLimitReached + summary: Limit Reached + description: Fired when a customer reaches the limit for a feature (included + allowance, max purchase, or spend limit). + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - type + - data + properties: + type: + type: string + const: balances.limit_reached + description: The webhook event type. + data: + examples: + - customer_id: org_123 + entity_id: workspace_abc + feature_id: api_calls + limit_type: included + type: object + properties: + customer_id: + description: The ID of the customer who hit the limit. + type: string + entity_id: + description: The entity ID, if the limit was reached on a specific entity. + type: string + feature_id: + description: The feature ID whose limit was reached. + type: string + limit_type: + description: "Which limit was hit: included allowance, max purchase cap, or + spend limit." + type: string + enum: + - included + - max_purchase + - spend_limit + required: + - customer_id + - feature_id + - limit_type + additionalProperties: false + example: + type: balances.limit_reached + data: + customer_id: org_123 + entity_id: workspace_abc + feature_id: api_calls + limit_type: included + responses: + "200": + description: Webhook received successfully. + vercel.resources.deleted: + post: + operationId: vercelResourcesDeleted + summary: Resource Deleted + description: When a Vercel resource is deleted, you'll need to handle + de-provisioning any API keys or other non-Autumn controlled data for + this user. + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - type + - data + properties: + type: + type: string + const: vercel.resources.deleted + description: The webhook event type. + data: + type: object + properties: + resource: + description: The resource that was deleted. + type: object + properties: + id: + description: The unique identifier of the deleted resource. + type: string + required: + - id + additionalProperties: false + installation_id: + description: The Vercel integration configuration ID. + type: string + required: + - resource + - installation_id + additionalProperties: false + responses: + "200": + description: Webhook received successfully. + vercel.resources.provisioned: + post: + operationId: vercelResourcesProvisioned + summary: Resource Provisioned + description: When a Vercel resource is created, you'll need to provision a + secret key for your service. Then you can use the provided access token + to patch the resource's secrets. + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - type + - data + properties: + type: + type: string + const: vercel.resources.provisioned + description: The webhook event type. + data: + type: object + properties: + resource: + description: The resource that was provisioned. + type: object + properties: + id: + description: The unique identifier of the provisioned resource. + type: string + name: + description: The display name of the provisioned resource. + type: string + required: + - id + - name + additionalProperties: false + installation_id: + description: The Vercel integration configuration ID. + type: string + access_token: + description: An access token that can be used to patch the resource's secrets. + type: string + required: + - resource + - installation_id + - access_token + additionalProperties: false + responses: + "200": + description: Webhook received successfully. + vercel.resources.rotate_secrets: + post: + operationId: vercelResourcesRotateSecrets + summary: Rotate Secrets + description: This event is sent when Vercel requires a resource's secrets to be + rotated. + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - type + - data + properties: + type: + type: string + const: vercel.resources.rotate_secrets + description: The webhook event type. + data: + type: object + properties: + resource: + description: The resource whose secrets should be rotated. + type: object + properties: + id: + description: The unique identifier of the resource. + type: string + required: + - id + additionalProperties: false + installation_id: + description: The Vercel integration configuration ID. + type: string + vercel_request_body: + description: The raw request body from Vercel's rotation request. + required: + - resource + - installation_id + - vercel_request_body + additionalProperties: false + responses: + "200": + description: Webhook received successfully. + vercel.webhooks.event: + post: + operationId: vercelWebhooksEvent + summary: Webhook Event + description: Passthrough webhook for Vercel events. + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - type + - data + properties: + type: + type: string + const: vercel.webhooks.event + description: The webhook event type. + data: + type: object + properties: + installation_id: + description: The Vercel integration configuration ID. + type: string + event: + description: The raw Vercel webhook event payload. + required: + - installation_id + - event + additionalProperties: false + responses: + "200": + description: Webhook received successfully. diff --git a/packages/openapi/package.json b/packages/openapi/package.json index 3cbdfeba8..29aaf1b7f 100644 --- a/packages/openapi/package.json +++ b/packages/openapi/package.json @@ -12,6 +12,8 @@ "@orpc/contract": "catalog:", "@orpc/openapi": "^1.13.4", "@orpc/zod": "^1.13.4", + "dotenv": "^17.3.1", + "svix": "^1.89.0", "yaml": "^2.8.1", "zod-openapi": "^5.4.1" }, diff --git a/packages/openapi/scripts/svixPush.ts b/packages/openapi/scripts/svixPush.ts new file mode 100644 index 000000000..ffb9ab029 --- /dev/null +++ b/packages/openapi/scripts/svixPush.ts @@ -0,0 +1,102 @@ +import { webhookRegistry } from "@autumn/shared"; +import { config } from "dotenv"; +import { Svix } from "svix"; +import { createSchema } from "zod-openapi"; + +config({ path: "server/.env" }); + +const SVIX_API_KEY = process.env.SVIX_API_KEY; +if (!SVIX_API_KEY) { + console.error("SVIX_API_KEY is not set. Provide it via env or server/.env"); + process.exit(1); +} + +const svix = new Svix(SVIX_API_KEY); + +async function pushEventTypes() { + let created = 0; + let updated = 0; + let failed = 0; + + for (const definition of webhookRegistry) { + const schemas = definition.schema + ? buildJsonSchemas({ definition }) + : undefined; + + const payload = { + name: definition.eventType, + description: definition.description, + schemas, + deprecated: definition.deprecated, + archived: definition.archived, + featureFlags: definition.featureFlags, + }; + + try { + await svix.eventType.create(payload); + console.log(` [created] ${definition.eventType}`); + created++; + } catch (error: unknown) { + if (isConflictError(error)) { + try { + const { name: _name, ...updatePayload } = payload; + await svix.eventType.update(definition.eventType, updatePayload); + console.log(` [updated] ${definition.eventType}`); + updated++; + } catch (updateError) { + console.error( + ` [failed] ${definition.eventType} — update failed:`, + updateError, + ); + failed++; + } + } else { + console.error( + ` [failed] ${definition.eventType} — create failed:`, + error, + ); + failed++; + } + } + } + + console.log( + `\nDone: ${created} created, ${updated} updated, ${failed} failed (${webhookRegistry.length} total)`, + ); + + if (failed > 0) process.exit(1); +} + +function buildJsonSchemas({ + definition, +}: { + definition: (typeof webhookRegistry)[number]; +}) { + if (!definition.schema) return undefined; + + const { schema: jsonSchema } = createSchema(definition.schema); + return { + 1: { + type: "object", + required: ["type", "data"], + properties: { + type: { + type: "string", + const: definition.eventType, + }, + data: jsonSchema, + }, + }, + }; +} + +function isConflictError(error: unknown): boolean { + if (!error || typeof error !== "object") return false; + const statusCode = + (error as Record).code ?? + (error as Record).statusCode ?? + (error as Record).status; + return statusCode === 409; +} + +pushEventTypes(); diff --git a/packages/openapi/utils/apiReferenceGenerator/generateFields.ts b/packages/openapi/utils/apiReferenceGenerator/generateFields.ts index b18c0046f..0c9b216a7 100644 --- a/packages/openapi/utils/apiReferenceGenerator/generateFields.ts +++ b/packages/openapi/utils/apiReferenceGenerator/generateFields.ts @@ -1,4 +1,8 @@ -import type { ParsedOperation, SchemaField } from "./parseOpenApi.js"; +import type { + ParsedOperation, + ParsedWebhook, + SchemaField, +} from "./parseOpenApi.js"; /** * Generate the MDX content for request body and response fields. @@ -233,6 +237,79 @@ function formatType(type: string, enumValues?: string[]): string { return type; } +/** + * Generate MDX content for a webhook event. + * Uses plain `ParamField` with snake_case names since webhook payloads + * are raw JSON (not SDK-transformed). + */ +export function generateWebhookFields({ + webhook, +}: { + webhook: ParsedWebhook; +}): string { + const sections: string[] = []; + + if (webhook.dataFields && webhook.dataFields.length > 0) { + sections.push("### Payload Fields\n"); + sections.push( + generateStaticParamFields({ fields: webhook.dataFields, indent: 0 }), + ); + } + + return sections.join("\n"); +} + +/** + * Generate ParamField components with static snake_case names. + */ +function generateStaticParamFields({ + fields, + indent, +}: { + fields: SchemaField[]; + indent: number; +}): string { + const indentStr = " ".repeat(indent); + const lines: string[] = []; + + for (const field of fields) { + const typeStr = formatType(field.type, field.enumValues); + const requiredAttr = field.required ? " required" : ""; + const description = escapeDescription(field.description); + const hasChildren = field.children && field.children.length > 0; + + if (hasChildren) { + lines.push( + `${indentStr}`, + ); + if (description) { + lines.push(`${indentStr} ${description}`); + } + lines.push(`${indentStr} `); + lines.push( + generateStaticParamFields({ + fields: field.children!, + indent: indent + 2, + }), + ); + lines.push(`${indentStr} `); + lines.push(`${indentStr}\n`); + } else if (description) { + lines.push( + `${indentStr}`, + ); + lines.push(`${indentStr} ${description}`); + lines.push(`${indentStr}\n`); + } else { + lines.push( + `${indentStr}\n`, + ); + } + } + + return lines.join("\n"); +} + /** * Escape special characters in description for MDX. */ diff --git a/packages/openapi/utils/apiReferenceGenerator/index.ts b/packages/openapi/utils/apiReferenceGenerator/index.ts index 5fe46b4da..afc5d8d1f 100644 --- a/packages/openapi/utils/apiReferenceGenerator/index.ts +++ b/packages/openapi/utils/apiReferenceGenerator/index.ts @@ -1,8 +1,9 @@ -import { existsSync, mkdirSync, writeFileSync } from "node:fs"; +import { mkdirSync, writeFileSync } from "node:fs"; import path from "node:path"; -import { generateFields } from "./generateFields.js"; +import { webhookRegistry } from "@autumn/shared"; +import { generateFields, generateWebhookFields } from "./generateFields.js"; import { mergeMdx } from "./mergeMdx.js"; -import { parseOpenApi } from "./parseOpenApi.js"; +import { parseOpenApi, parseWebhooks } from "./parseOpenApi.js"; export interface GenerateApiReferenceOptions { openApiPath: string; @@ -10,6 +11,11 @@ export interface GenerateApiReferenceOptions { outputDir: string; } +export interface GeneratedWebhookPage { + group: string; + pagePath: string; +} + /** * Generate API reference MDX files from an OpenAPI spec. * @@ -18,51 +24,129 @@ export interface GenerateApiReferenceOptions { * 2. Generate DynamicParamField/DynamicResponseField components * 3. Merge with manual MDX content (if exists) * 4. Write to output directory: {outputDir}/{tag}/{operationId}.mdx + * + * Also generates webhook MDX files from the `webhooks` section + * and returns group metadata so callers can update navigation. */ export async function generateApiReference({ openApiPath, manualMdxDir, outputDir, -}: GenerateApiReferenceOptions): Promise { +}: GenerateApiReferenceOptions): Promise<{ + webhookPages: GeneratedWebhookPage[]; +}> { console.log(` Reading OpenAPI spec from: ${openApiPath}`); - // Parse OpenAPI spec const operations = parseOpenApi({ openApiPath }); console.log(` Found ${operations.length} operations`); let generated = 0; - const skipped = 0; for (const operation of operations) { const { tag, operationId } = operation; - // Determine file paths const manualMdxPath = path.join(manualMdxDir, tag, `${operationId}.mdx`); const outputPath = path.join(outputDir, tag, `${operationId}.mdx`); - // Generate fields MDX const generatedContent = generateFields({ operation }); - // Merge with manual MDX (if exists) const finalMdx = mergeMdx({ manualMdxPath, generatedContent, operation, }); - // Ensure output directory exists mkdirSync(path.dirname(outputPath), { recursive: true }); - - // Write output file writeFileSync(outputPath, finalMdx, "utf-8"); generated++; console.log(` Generated: ${tag}/${operationId}.mdx`); } - console.log( - ` API reference generation complete: ${generated} generated, ${skipped} skipped`, - ); + // Build operationId -> group mapping from the shared registry + const groupMap: Record = {}; + for (const definition of webhookRegistry) { + groupMap[definition.operationId] = definition.group; + } + + const webhooks = parseWebhooks({ openApiPath, groupMap }); + const webhookPages: GeneratedWebhookPage[] = []; + + if (webhooks.length > 0) { + console.log(` Found ${webhooks.length} webhooks`); + + for (const webhook of webhooks) { + const generatedContent = generateWebhookFields({ webhook }); + + const title = + webhook.summary ?? formatEventTypeAsTitle(webhook.eventType); + const frontmatter = `---\ntitle: "${title}"\nopenapi: "api/openapi.yml webhook ${webhook.eventType}"\n---`; + + const finalMdx = `${frontmatter}\n\n${generatedContent}`; + + const relativePage = `api-reference/webhooks/${webhook.operationId}`; + const outputPath = path.join( + outputDir, + "webhooks", + `${webhook.operationId}.mdx`, + ); + mkdirSync(path.dirname(outputPath), { recursive: true }); + writeFileSync(outputPath, finalMdx, "utf-8"); + generated++; + + webhookPages.push({ + group: webhook.group, + pagePath: relativePage, + }); + + console.log(` Generated webhook: webhooks/${webhook.operationId}.mdx`); + } + } + + // Also generate placeholder pages for registry entries without schemas + // (they won't be in the OpenAPI spec but we still want a docs page) + const generatedOperationIds = new Set(webhooks.map((w) => w.operationId)); + for (const definition of webhookRegistry) { + if (generatedOperationIds.has(definition.operationId)) continue; + + const title = definition.title; + const mdx = `---\ntitle: "${title}"\n---\n\n${definition.description}\n\nSchema documentation for this event type is coming soon.\n`; + + const relativePage = `api-reference/webhooks/${definition.operationId}`; + const outputPath = path.join( + outputDir, + "webhooks", + `${definition.operationId}.mdx`, + ); + mkdirSync(path.dirname(outputPath), { recursive: true }); + writeFileSync(outputPath, mdx, "utf-8"); + generated++; + + webhookPages.push({ + group: definition.group, + pagePath: relativePage, + }); + + console.log( + ` Generated webhook placeholder: webhooks/${definition.operationId}.mdx`, + ); + } + + console.log(` API reference generation complete: ${generated} generated`); + + return { webhookPages }; +} + +function formatEventTypeAsTitle(eventType: string): string { + return eventType + .split(".") + .map((segment) => + segment + .split("_") + .map((word) => word.charAt(0).toUpperCase() + word.slice(1)) + .join(" "), + ) + .join(" — "); } // Re-export types for consumers diff --git a/packages/openapi/utils/apiReferenceGenerator/parseOpenApi.ts b/packages/openapi/utils/apiReferenceGenerator/parseOpenApi.ts index f511b1913..fbf168b11 100644 --- a/packages/openapi/utils/apiReferenceGenerator/parseOpenApi.ts +++ b/packages/openapi/utils/apiReferenceGenerator/parseOpenApi.ts @@ -33,11 +33,22 @@ export interface ParsedOperation { allSchemas?: Record; } +export interface ParsedWebhook { + eventType: string; + operationId: string; + group: string; + summary?: string; + description?: string; + /** Fields inside the `data` envelope (excludes the outer `type` field) */ + dataFields?: SchemaField[]; +} + interface OpenApiDocument { components?: { schemas?: Record; }; paths?: Record>; + webhooks?: Record>; } /** @@ -151,6 +162,74 @@ export function parseOpenApi({ return operations; } +/** + * Parse webhook definitions from the OpenAPI `webhooks` section. + * Extracts the `data` sub-schema from the `{ type, data }` envelope + * so we can generate field docs for just the meaningful payload. + * + * @param groupMap - Maps operationId -> group name (from the webhook registry). + */ +export function parseWebhooks({ + openApiPath, + groupMap = {}, +}: { + openApiPath: string; + groupMap?: Record; +}): ParsedWebhook[] { + const content = readFileSync(openApiPath, "utf-8"); + const doc = yaml.parse(content) as OpenApiDocument; + + const schemas = doc.components?.schemas ?? {}; + const webhooks: ParsedWebhook[] = []; + + for (const [eventType, webhookItem] of Object.entries(doc.webhooks ?? {})) { + const postOp = webhookItem.post as Record | undefined; + if (!postOp) continue; + + const operationId = postOp.operationId as string | undefined; + if (!operationId) continue; + + const parsed: ParsedWebhook = { + eventType, + operationId, + group: groupMap[operationId] ?? "Webhooks", + summary: postOp.summary as string | undefined, + description: postOp.description as string | undefined, + }; + + const requestBody = postOp.requestBody as + | Record + | undefined; + const jsonContent = ( + requestBody?.content as Record | undefined + )?.["application/json"] as Record | undefined; + const bodySchema = jsonContent?.schema as + | Record + | undefined; + + if (bodySchema) { + const properties = bodySchema.properties as + | Record + | undefined; + const dataSchema = properties?.data as + | Record + | undefined; + + if (dataSchema) { + parsed.dataFields = parseSchema({ + schema: dataSchema, + schemas, + requiredFields: (dataSchema.required as string[]) ?? [], + }); + } + } + + webhooks.push(parsed); + } + + return webhooks; +} + /** * Resolves an example from a schema, following $ref if needed. */ diff --git a/packages/openapi/utils/mintlifyTransform/index.ts b/packages/openapi/utils/mintlifyTransform/index.ts index f74947dbb..3175c7c1f 100644 --- a/packages/openapi/utils/mintlifyTransform/index.ts +++ b/packages/openapi/utils/mintlifyTransform/index.ts @@ -1,7 +1,10 @@ import { readFileSync, writeFileSync } from "node:fs"; import path from "node:path"; import yaml from "yaml"; -import { generateApiReference } from "../apiReferenceGenerator/index.js"; +import { + type GeneratedWebhookPage, + generateApiReference, +} from "../apiReferenceGenerator/index.js"; import { removeInternalFields } from "../openapiTransform/removeInternalFields.js"; import { transformNode } from "./transformNode.js"; @@ -26,7 +29,6 @@ export function transformOpenApiForMintlify(yamlContent: string): string { | Record | undefined; - // Remove internal fields before other transformations removeInternalFields({ openApiDocument: doc }); transformNode(doc, schemas); @@ -38,6 +40,7 @@ export function transformOpenApiForMintlify(yamlContent: string): string { * * 1. Transforms OpenAPI (strips JSDoc tags, fixes code samples) * 2. Generates API reference MDX files with dynamic parameter fields + * 3. Updates docs.json navigation with webhook groups */ export async function generateMintlifyDocs({ openApiPath, @@ -46,21 +49,91 @@ export async function generateMintlifyDocs({ openApiPath: string; docsDir: string; }): Promise { - // Transform OpenAPI for Mintlify console.log("Transforming OpenAPI for Mintlify docs..."); const yamlContent = readFileSync(openApiPath, "utf-8"); const transformedYaml = transformOpenApiForMintlify(yamlContent); writeFileSync(openApiPath, transformedYaml); console.log("Mintlify transformation complete"); - // Generate API reference MDX files console.log("Generating API reference MDX files..."); const manualMdxDir = path.resolve(docsDir, "../api-reference-generator"); const outputMdxDir = path.resolve(docsDir, "api-reference"); - await generateApiReference({ + const { webhookPages } = await generateApiReference({ openApiPath, manualMdxDir, outputDir: outputMdxDir, }); console.log("API reference MDX generation complete"); + + if (webhookPages.length > 0) { + updateDocsJsonWebhooks({ docsDir, webhookPages }); + } +} + +/** + * Updates the docs.json navigation to include webhook groups in the + * API Reference tab, replacing any previously generated webhook groups. + */ +function updateDocsJsonWebhooks({ + docsDir, + webhookPages, +}: { + docsDir: string; + webhookPages: GeneratedWebhookPage[]; +}) { + const docsJsonPath = path.join(docsDir, "docs.json"); + const docsJson = JSON.parse(readFileSync(docsJsonPath, "utf-8")); + + const tabs = docsJson.navigation?.tabs; + if (!Array.isArray(tabs)) return; + + const apiTab = tabs.find( + (tab: Record) => tab.tab === "API Reference", + ); + if (!apiTab?.groups || !Array.isArray(apiTab.groups)) return; + + // Build nested subgroups under a single "Webhook Events" group + const groupedPages = new Map(); + for (const page of webhookPages) { + const existing = groupedPages.get(page.group) ?? []; + existing.push(page.pagePath); + groupedPages.set(page.group, existing); + } + + const subgroups = [...groupedPages.entries()].map( + ([groupName, pages]) => ({ + group: groupName, + pages, + }), + ); + + const webhookEventsGroup = { + group: "Webhook Events", + pages: subgroups, + }; + + // Remove any existing "Webhook Events" or old "Webhooks:" groups + const filteredGroups = apiTab.groups.filter( + (group: Record) => { + const name = group.group as string | undefined; + return name && !name.startsWith("Webhooks:") && name !== "Webhook Events"; + }, + ); + + // Insert before "Platform (Beta)" if it exists, otherwise at the end + const platformIdx = filteredGroups.findIndex( + (g: Record) => g.group === "Platform (Beta)", + ); + if (platformIdx >= 0) { + filteredGroups.splice(platformIdx, 0, webhookEventsGroup); + } else { + filteredGroups.push(webhookEventsGroup); + } + + apiTab.groups = filteredGroups; + + writeFileSync(docsJsonPath, `${JSON.stringify(docsJson, null, "\t")}\n`); + console.log( + ` Updated docs.json with ${subgroups.length} webhook subgroup(s)`, + ); } diff --git a/packages/openapi/v2.1/openapi2.1.ts b/packages/openapi/v2.1/openapi2.1.ts index c63ef850e..e4dd8229e 100644 --- a/packages/openapi/v2.1/openapi2.1.ts +++ b/packages/openapi/v2.1/openapi2.1.ts @@ -36,6 +36,7 @@ import { } from "../utils/openapiTransform/index.js"; import { registerInternalSchemas } from "../utils/registerInternalSchemas.js"; import { v2_1ContractRouter } from "./contracts/index.js"; +import { injectWebhooks } from "./webhooks/injectWebhooks.js"; const generator = new OpenAPIGenerator({ schemaConverters: [new ZodToJsonSchemaConverter()], @@ -120,6 +121,7 @@ async function generateOpenApiDocument(): Promise> { version: OPENAPI_DOC_VERSION, }); removeInternalFields({ openApiDocument }); + injectWebhooks({ openApiDocument }); return openApiDocument; } diff --git a/packages/openapi/v2.1/webhooks/injectWebhooks.ts b/packages/openapi/v2.1/webhooks/injectWebhooks.ts new file mode 100644 index 000000000..b15fbde63 --- /dev/null +++ b/packages/openapi/v2.1/webhooks/injectWebhooks.ts @@ -0,0 +1,81 @@ +import { createSchema } from "zod-openapi"; +import { z } from "zod/v4"; +import { webhookRegistry } from "./webhookDefinitions.js"; + +/** + * Injects OpenAPI `webhooks` entries and their component schemas into the + * generated OpenAPI document. Only definitions with a Zod schema are included; + * schema-less entries (description-only) are skipped. + */ +export function injectWebhooks({ + openApiDocument, +}: { + openApiDocument: Record; +}) { + const webhooks: Record = {}; + + const components = (openApiDocument.components ?? {}) as Record< + string, + unknown + >; + const existingSchemas = (components.schemas ?? {}) as Record; + + for (const definition of webhookRegistry) { + if (!definition.schema) continue; + + const { schema: jsonSchema, components: schemaComponents } = createSchema( + definition.schema, + ); + + for (const [name, schemaObj] of Object.entries(schemaComponents)) { + existingSchemas[name] = schemaObj; + } + + const meta = z.globalRegistry.get(definition.schema); + const schemaExample = meta?.examples?.[0] as + | Record + | undefined; + + webhooks[definition.eventType] = { + post: { + operationId: definition.operationId, + summary: definition.title, + description: definition.description, + requestBody: { + required: true, + content: { + "application/json": { + schema: { + type: "object", + required: ["type", "data"], + properties: { + type: { + type: "string", + const: definition.eventType, + description: "The webhook event type.", + }, + data: jsonSchema, + }, + }, + ...(schemaExample && { + example: { + type: definition.eventType, + data: schemaExample, + }, + }), + }, + }, + }, + responses: { + "200": { + description: "Webhook received successfully.", + }, + }, + }, + }; + } + + components.schemas = existingSchemas; + openApiDocument.components = components; + openApiDocument.webhooks = webhooks; +} diff --git a/packages/openapi/v2.1/webhooks/webhookDefinitions.ts b/packages/openapi/v2.1/webhooks/webhookDefinitions.ts new file mode 100644 index 000000000..37a66d094 --- /dev/null +++ b/packages/openapi/v2.1/webhooks/webhookDefinitions.ts @@ -0,0 +1 @@ +export { type WebhookDefinition, webhookRegistry } from "@autumn/shared"; diff --git a/packages/sdk/.npmignore b/packages/sdk/.npmignore index 670ac0a62..cf98a6bf0 100644 --- a/packages/sdk/.npmignore +++ b/packages/sdk/.npmignore @@ -5,14 +5,10 @@ !/**/*.ts !/**/*.js !/**/*.mjs -!/package.json -!/jsr.json -!/dist/**/*.json -!/esm/**/*.json +!/**/*.json !/**/*.map /eslint.config.mjs -/.oxlintrc.json /cjs /.tshy /.tshy-* diff --git a/packages/sdk/.speakeasy/gen.lock b/packages/sdk/.speakeasy/gen.lock index cfb8de934..dd20656ce 100644 --- a/packages/sdk/.speakeasy/gen.lock +++ b/packages/sdk/.speakeasy/gen.lock @@ -1,33 +1,33 @@ lockVersion: 2.0.0 id: 7b300647-cd76-49e9-bf77-7d1bf5446d66 management: - docChecksum: a9eda44de2ad5efffefc33432889b234 + docChecksum: a6df9b64f035c4af93b077b3174ecba8 docVersion: 2.2.0 - speakeasyVersion: 1.757.1 - generationVersion: 2.866.2 + speakeasyVersion: 1.719.0 + generationVersion: 2.824.1 releaseVersion: 0.10.17 configChecksum: c6b2bd1231da8dc3af5be7430f3cfbac persistentEdits: - generation_id: cf5f8e93-93fa-474e-8134-e9d24a4dee16 - pristine_commit_hash: d1602490f01343f2134e1de107c471bda19bc861 - pristine_tree_hash: 5d68f26e26ddbc41ea98a536ad5f711c9fa7dae5 + generation_id: f036c341-af7f-424d-b5c5-30b3e9b172a1 + pristine_commit_hash: 5127dc545cc26086977773862cd85d97ea348a80 + pristine_tree_hash: 6345cc3cfa59bf954c97f04795550fd94caa4e6d features: typescript: additionalDependencies: 0.1.0 - constsAndDefaults: 0.1.14 - core: 3.26.42 + constsAndDefaults: 0.1.13 + core: 3.26.27 defaultEnabledRetries: 0.1.0 devContainers: 2.90.1 enumUnions: 0.1.0 envVarSecurityUsage: 0.1.2 globalSecurity: 2.82.15 globalSecurityCallbacks: 0.1.0 - globalSecurityFlattening: 0.1.1 - globalServerURLs: 2.83.1 + globalSecurityFlattening: 0.1.0 + globalServerURLs: 2.83.0 globals: 2.82.2 hiddenGlobals: 0.1.0 methodArguments: 0.1.2 - nameOverrides: 2.81.4 + nameOverrides: 2.81.2 nullables: 0.1.1 responseFormat: 0.3.0 retries: 2.83.0 @@ -52,8 +52,8 @@ trackedFiles: pristine_git_object: 113eead5093c17d43a46159132885318f281a68a .npmignore: id: aa70c1f807c3 - last_write_checksum: sha1:6572da81f2e7a978ec29c22c2210bf461c5897b2 - pristine_git_object: 670ac0a62d7e568c9d44a14f5deafb8442a255d8 + last_write_checksum: sha1:3d5eb92f81539175db1ff0280e0aefbdd701f200 + pristine_git_object: cf98a6bf092538eb10ff0edc915102682ce9a6e6 FUNCTIONS.md: id: 21b9df02aaeb last_write_checksum: sha1:f8b9273977606e6c5bc3abae9354a5186af43ec0 @@ -96,8 +96,8 @@ trackedFiles: pristine_git_object: 39e2e27b82c7b641f0a498550c99017a00321785 docs/models/attach-action.md: id: 8de20a26b9b9 - last_write_checksum: sha1:44c1a79c9374746d732856aa68bf5844c148bdf8 - pristine_git_object: 44a90e2a8dba64514f85c88d7e9a287592fadf84 + last_write_checksum: sha1:45b557ec09fa5c493f57b8b9a6e8b563e9be95b5 + pristine_git_object: 9f0b94f97323321007e3fac6860afffe84f0b799 docs/models/attach-attach-discount.md: id: c10677064b44 last_write_checksum: sha1:f0095ac832df6fb4cc055b56d017207985a88adc @@ -120,8 +120,8 @@ trackedFiles: pristine_git_object: 376a0838c9e0cfdfe6ecfbfd2508353db485a627 docs/models/attach-code.md: id: 14b09292cbbc - last_write_checksum: sha1:3e916de85430e347c1a3594a8b68da273b5ad036 - pristine_git_object: fd60d9f2ea9203a756954cb671eb4931662820b8 + last_write_checksum: sha1:ee9ad35bc847c0b15c401e25610988b5f03db49b + pristine_git_object: a72bf7b95871aed0e16e742eed4be39b8cbdec8e docs/models/attach-custom-line-item.md: id: 0968ebbf76e1 last_write_checksum: sha1:4c493a8fba5e774a59206c47f63bef7ea4f9d613 @@ -236,8 +236,8 @@ trackedFiles: pristine_git_object: 1a31544c486bbdb05784f5f44d93dd8551f5a8d5 docs/models/balance-billing-method.md: id: 6ade18c9eaff - last_write_checksum: sha1:a53e1692058149acb627955e905176078f3efd97 - pristine_git_object: e895fa15164faf35ec3b60fcebe2a167c1aa1b2b + last_write_checksum: sha1:5a53ded38d42283a77c4a67af5e26fad8ccaf59e + pristine_git_object: 7b27f1d8239f0f01053f50f98da0c3709015444c docs/models/balance-credit-schema.md: id: 36fcc4d66629 last_write_checksum: sha1:b603a6d01cb2d65cfb542cae9880bebcd85d5928 @@ -252,8 +252,8 @@ trackedFiles: pristine_git_object: 7c450f9bfdabb817ca1bee6b9020453d6d9bcd17 docs/models/balance-interval-enum.md: id: dbc34d625754 - last_write_checksum: sha1:4238eeb6473efb2780568f1732a83087cd5c50ce - pristine_git_object: 7db0c2dd5c0b7ebb652b160074b92a53f85a29e7 + last_write_checksum: sha1:f90fb401c0c271e9473159272826a3f96905c0bf + pristine_git_object: 823d2ea29ce9abd3e1be7dba10667b7883e91b14 docs/models/balance-price.md: id: 0befed5ea384 last_write_checksum: sha1:fda6ad63bfebad099b4f9714d1b0ff4b8f064ffc @@ -268,12 +268,12 @@ trackedFiles: pristine_git_object: fe958e38daba860a25025cc1210cfc4327d8803f docs/models/balance-tier-behavior.md: id: 49fad040b38f - last_write_checksum: sha1:5c91cc7adf35dafa7e966d2d35937f92a46d3d25 - pristine_git_object: bac50dabd4fb38447fa593172f8ea3113a86fb4e + last_write_checksum: sha1:e0e8bf8c3965f936b559af3e25997bbbc18e4150 + pristine_git_object: 30c5de4a1922a1de4df750fb121e3f6857391f5c docs/models/balance-type.md: id: 193fed65f06f - last_write_checksum: sha1:da3f571fb4896b3d3caa20bf33c9c33c36f6faf7 - pristine_git_object: dfda3847ec0df4a8b917d5746722fe394b239258 + last_write_checksum: sha1:70e7a5881b94555a87d661714581bab07713702e + pristine_git_object: a7af331f1bddeb56774fc38e77fcb45959c0f558 docs/models/balance.md: id: 9de59403580f last_write_checksum: sha1:8d5433ac6435693a81086e91ba42d7ae173e2a45 @@ -292,8 +292,8 @@ trackedFiles: pristine_git_object: 68e5a3a00ee61c31522d695c2cdb26e2917f86be docs/models/billing-update-code.md: id: b84ac28f1591 - last_write_checksum: sha1:42971aa6160a71ae958639a336f749df58147eb2 - pristine_git_object: 7c5c0d332961e51e90e875930bc57fc5769f66dc + last_write_checksum: sha1:f884ec08c9f953fc2c2ccb85d0bdc24a71d1568c + pristine_git_object: 167a5a0db0d9f92c36f1f181e642a246753d0210 docs/models/billing-update-customize.md: id: 533e2ca5e4bd last_write_checksum: sha1:072993bc0384fd9debf9f72c717c659388dde340 @@ -358,6 +358,10 @@ trackedFiles: id: fcbf404063bc last_write_checksum: sha1:13335299452527b6e5accf8440600cc12bdcdc3d pristine_git_object: 36cdcc2b2d8a6a60d11ca36deac68d8f30b97d18 + docs/models/billing-update-recalculate-balances.md: + id: 8ead4615c410 + last_write_checksum: sha1:faeed44cbca8f10ff5e55213ce959bba7da80fa5 + pristine_git_object: 6c0732fded727c346294af65ef75e78a030f31ba docs/models/billing-update-redirect-mode.md: id: 6bd734fe582b last_write_checksum: sha1:bad9174a690d6c72dcbcf71e6f349c04ad4616d6 @@ -408,8 +412,8 @@ trackedFiles: pristine_git_object: c77bf103d178ca28a3192f153a676e80735904b2 docs/models/check-env.md: id: d46376d0c4e0 - last_write_checksum: sha1:79f6d930209b23c2bf5eb7ef468feeb2cf92f7b3 - pristine_git_object: c91506826d1df807c7e52fc71b93d43a08e64356 + last_write_checksum: sha1:fb17dcff1735e72d8f17c8a8ef3ddd6b7970d8bd + pristine_git_object: b232d2049d3acc05d189413f685362c377b0c4a4 docs/models/check-feature.md: id: 17698212d17f last_write_checksum: sha1:7da866b793c5b1dc17acbe43c867a0bfcf1d988f @@ -424,8 +428,8 @@ trackedFiles: pristine_git_object: e7a1e28ebd8cb19e0fd665f56754c4252ced391b docs/models/check-interval.md: id: 2b947e7da9da - last_write_checksum: sha1:a45ec5c1aa13d5d55190e3d5defb98dea5e56b28 - pristine_git_object: 7d90a519f2488653231e338d3d87749b6dd3a429 + last_write_checksum: sha1:f3760390659d8b08407d5dda25b3c45fabb33fa4 + pristine_git_object: c0f62b4515395a9594e22d8ee35a26953c53bf10 docs/models/check-item.md: id: 65ebecbc13ac last_write_checksum: sha1:faf9afc5dc6fc4d31ea5b4f4cfed35ffd538bd72 @@ -436,12 +440,12 @@ trackedFiles: pristine_git_object: b21ba54a0652e2c016fcb4434880c429fa4c41b3 docs/models/check-on-decrease.md: id: 361f05432960 - last_write_checksum: sha1:4aae28abd12eeccf2ee789c3684cb06052776115 - pristine_git_object: e08007c0ffd502919dd23fab540d0ce3ac92150f + last_write_checksum: sha1:218fe1ceed4ce70d3ab91ee5f86430670544df50 + pristine_git_object: 7401f77ec62b2981202cbaf4bbf2ffe3379f6bad docs/models/check-on-increase.md: id: 9f889141cf7b - last_write_checksum: sha1:539207de265a87ce63f2b37cd9a88d5dddc5ce8b - pristine_git_object: 985357bc0cc5110a25535a26fe123d923eccc52b + last_write_checksum: sha1:eb4f641b50be10d3316210c01a804d260373c3ab + pristine_git_object: 05a41c5e3b43f5b437df88e5c0b36e4a27efe8fd docs/models/check-params.md: id: 1f4a01957fbe last_write_checksum: sha1:c8c546b4aa4d1e459aef8131e522e6bf41ccc7c7 @@ -460,8 +464,8 @@ trackedFiles: pristine_git_object: c659c5a5a8df3ae58a7a467f513a905104e32cb6 docs/models/check-tier-behavior.md: id: 89be3843344e - last_write_checksum: sha1:942afb288468d96e6b14d3ae855b8dfbc2540083 - pristine_git_object: 77d39923ac11253f4bef2b2a581c9a1c6e634393 + last_write_checksum: sha1:5c5067037818a65556151b41c57cce608eac005e + pristine_git_object: 28423762d1e208e3464b8df9e0f10a28813c14f8 docs/models/config.md: id: bef254bf823c last_write_checksum: sha1:ee3a8a70d128bd4c6169a1ec01b9b53c2e075695 @@ -488,12 +492,12 @@ trackedFiles: pristine_git_object: 5a3f8c765ccd682f833dd305a9705770b8cae73c docs/models/create-entity-billing-controls-request.md: id: 1f94d07a9fe2 - last_write_checksum: sha1:b9caaeaddf6ccf964a62c8d7b6853029c7630b4c - pristine_git_object: a24bd89735a764c91bc40e2ea8226beed54c5667 + last_write_checksum: sha1:84b487ceb158e28c86bc02641f926865e38e3291 + pristine_git_object: 79879f470c36f6d35c54e142111c8c2197db7b3f docs/models/create-entity-billing-controls-response.md: id: 7048bbbdf39c - last_write_checksum: sha1:b42d259a20f81cc1d82bf0df57fdb5e6af7c333d - pristine_git_object: 658491c4ae8868549322e92e9a052702aece57b4 + last_write_checksum: sha1:be8e2bfe0482509cb860fa1dae192434ea4ca93f + pristine_git_object: 982f0f6c8d9bacfa0621641ab8179a1db7396702 docs/models/create-entity-credit-schema.md: id: 714d3a17c438 last_write_checksum: sha1:89c6f20f1230426553e153cdc3d0dddaccaa9725 @@ -504,8 +508,8 @@ trackedFiles: pristine_git_object: bd189cd3c9c870423540124e944760e44fc347e2 docs/models/create-entity-env.md: id: bdc2d4cbca15 - last_write_checksum: sha1:8c83dc475deaf8c560c582396a3d2278cbf228a2 - pristine_git_object: 8e59ea8fc2938ea30a6e9b582c44a4b5cab2a46d + last_write_checksum: sha1:7e8a20e31ba746e91bfadc5212e4178f3a3d5564 + pristine_git_object: 923094468b6a6435f41c1f9d831f345ac8a73012 docs/models/create-entity-feature.md: id: 53cedd277218 last_write_checksum: sha1:190a8d28cdead2c5bba81d15a0afb9a748825e9f @@ -544,16 +548,32 @@ trackedFiles: pristine_git_object: ae0a7e03eb4e2ca90cd529e911a8ef49b0ef4452 docs/models/create-entity-status.md: id: 658f1e6dd4d5 - last_write_checksum: sha1:0aa5d631d7d9ba0d9a0a42870153e7242b5b2ced - pristine_git_object: 788878d27119dc82e2877df317b425a1599a7f12 + last_write_checksum: sha1:72bf7235eccc3a1a1d871e28628e0a2ae6d689d3 + pristine_git_object: cf476e13ae64e821dc99420ba57aaf3b3a6d3262 docs/models/create-entity-subscription.md: id: d07f3f230823 last_write_checksum: sha1:52cca9d30e75b5a15325cde2003f67926dba0ab2 pristine_git_object: d3e9d13f1321d7af478fee7983ab2af4e4a647c4 + docs/models/create-entity-threshold-type-request-body.md: + id: e8502fdc1235 + last_write_checksum: sha1:fe909bd46f12501ccb64ae91d31355106e5d7933 + pristine_git_object: 37b9972da7d35cd2790acb7bf926a59e2855e49e + docs/models/create-entity-threshold-type-response.md: + id: 1248df87dfc4 + last_write_checksum: sha1:74e57a1ccb688b5c438b02c50ea45b67c9722a30 + pristine_git_object: 7614c3b6af77285fbc0c5f79b8d18b681a23c831 docs/models/create-entity-type.md: id: b7fd22bd7861 - last_write_checksum: sha1:a0f47b4b77657a52ac54e3ee07b553675bb9dd5c - pristine_git_object: 99caea31ac40ddd636425c0c559b31302d494cb3 + last_write_checksum: sha1:dcdeebd80668336b62034949f37c4f2465981337 + pristine_git_object: 8528c54987e315edbd01a6486b1e48e57e5a63ab + docs/models/create-entity-usage-alert-request-body.md: + id: a3441743c411 + last_write_checksum: sha1:e5b8794180d19bfd9bdf7df373c96d1f3be17990 + pristine_git_object: b248b2a832f5758f4d6bd099b8963be60002461b + docs/models/create-entity-usage-alert-response.md: + id: b4c50866191d + last_write_checksum: sha1:ea12949d17cbad703aae1039f64af4c36e07c4dc + pristine_git_object: 6366468abca89170abb2d5769ecb01ea3b205ba3 docs/models/create-feature-credit-schema-request.md: id: 12282f670bf0 last_write_checksum: sha1:68cb7e44ce4c8e0a8daacf13e2cb0e5afecdc172 @@ -588,20 +608,20 @@ trackedFiles: pristine_git_object: 59486a5f87ebfb477b8ac9c379cafe031fc1084b docs/models/create-feature-type-response.md: id: ec96747ac5a8 - last_write_checksum: sha1:a02cc9462eca35ec9d6d4149cb145a15be09679f - pristine_git_object: d45c54c26108de2eae9d7bcd881db79fac927fc5 + last_write_checksum: sha1:e8300fd82a995fb3db3c08fed4ee600222210174 + pristine_git_object: 13c8499a703b03b5aaf94deb471298fc8f4ccfe3 docs/models/create-plan-attach-action.md: id: 3a9b41faa0c8 - last_write_checksum: sha1:570d06010522edb4dabb3c27b26fa66aa2fcf909 - pristine_git_object: 11bf4a9d74e75a895e27489a55444fbe76d6488e + last_write_checksum: sha1:715383937d39ebf974fbe45bfa3f4fd75456c4a0 + pristine_git_object: a72358405d0c6c0b9815c09a60433b1a4e657006 docs/models/create-plan-billing-method-request.md: id: 5910c31fbd40 last_write_checksum: sha1:f760605fbcf453ca76282db0ceb6c56dc471198c pristine_git_object: 881afe6799b816389f7726b398c8703a5b43a1eb docs/models/create-plan-billing-method-response.md: id: 4b62f4430e70 - last_write_checksum: sha1:6f14cf6ec48162bc6154580375c55f699b9925a1 - pristine_git_object: 5a51ad5a3c5938a475f94789e10e56e93aa198f5 + last_write_checksum: sha1:760f8f63af3a0d880434489aff0ec69274205ac2 + pristine_git_object: c23b3e14cc3a3237db918db21e5a166f8948cd1b docs/models/create-plan-credit-schema.md: id: 213fe4cef877 last_write_checksum: sha1:9a9109b25682ec0ed4db881cf449e6ed823eb124 @@ -616,20 +636,20 @@ trackedFiles: pristine_git_object: 61eda90ca32639a989eab7ac744fa9aef0f827f6 docs/models/create-plan-duration-type-response.md: id: 7037528d7fd6 - last_write_checksum: sha1:dda35c0d789cca19ae6ec04493207f2931cfd2b0 - pristine_git_object: 7a02afe1f00c2a708d53363eff5668ebce86eade + last_write_checksum: sha1:b9ca0bae4d08cd78deb0a63ce58c057409101ef9 + pristine_git_object: 77c170b36f706ff57cdd83edd6fd9be065251695 docs/models/create-plan-env.md: id: 6cc4a7432037 - last_write_checksum: sha1:e4c71f4bf1bd9c341e40da5e7c1a5da14fbf7fad - pristine_git_object: ebe0cbac88d8f8430f6d870409e8e4e17f6ec7d2 + last_write_checksum: sha1:f5bfb3f0cface216095c8113fecfb6ed7b847698 + pristine_git_object: 54bc47b8d3d4e60a3f95f324a87aa2598da3ac62 docs/models/create-plan-expiry-duration-type-request.md: id: 64f50835e6bb last_write_checksum: sha1:5567b9305c2c0a0eb6a0507b62b5f1dc8569dfe9 pristine_git_object: e24e9550a7967f519354812a14490b5a2e6c3840 docs/models/create-plan-expiry-duration-type-response.md: id: c2e3d11324b4 - last_write_checksum: sha1:ac4d671900f88510bc21d82b4c4bc680d402836a - pristine_git_object: 4bfa66676478734a27953bcb09c4c09ad45e5ea9 + last_write_checksum: sha1:1163d8ba2d805ad45b966c6b463d3b0bb5ffa1c1 + pristine_git_object: 0e763d963d9478e1f59b696cef39340d701019ab docs/models/create-plan-feature-display.md: id: 77c8a90679b3 last_write_checksum: sha1:fbc637093c69e128250e5fc72e48dfc2ac319418 @@ -692,12 +712,12 @@ trackedFiles: pristine_git_object: 041e09cef3859854ecdf8997334bfdf94e732cf0 docs/models/create-plan-price-interval-response.md: id: 171e588628d3 - last_write_checksum: sha1:8684f1bae40c7b9b4dd50c234a014c69ffaf9c64 - pristine_git_object: 4681b6812d20c71b1e0f94d087127d375a047802 + last_write_checksum: sha1:a3687969c982d817d27534605aa63fdeed5c3a07 + pristine_git_object: c11dea424b2548d1935a0b217d098380e915e546 docs/models/create-plan-price-item-interval-response.md: id: f82a720e74cc - last_write_checksum: sha1:ab3d807d35c4d6a108593aec37e087c3efc54867 - pristine_git_object: b689fa821d998e5388d12f3fb7f8c1f21021f08d + last_write_checksum: sha1:8d3ea30be8b133d51a2524f169108e1bd2bac62d + pristine_git_object: 738eae0ccdfa30004d7a39b67b8a6cf290d1b138 docs/models/create-plan-price-request.md: id: ada0d70e716a last_write_checksum: sha1:1e5c54f88963da99a3cafa25d41bfd0a5b3fd8e6 @@ -716,8 +736,8 @@ trackedFiles: pristine_git_object: 3ab22b050c282b26f8e10b52d9cb96285e13f734 docs/models/create-plan-reset-interval-response.md: id: f48e94cb8d80 - last_write_checksum: sha1:4ac662e7e53d41d7d4082e38e6869391ca746e15 - pristine_git_object: 18e647441adf9d2f6bbde2a55c9b56748cd7ef6a + last_write_checksum: sha1:31ade0a5bec7f2706a11c61eaa7b00c01d4925a0 + pristine_git_object: 726d39c72f14a015954d6c7fa610dc56cdbc3df9 docs/models/create-plan-reset-request.md: id: d88e31eb9636 last_write_checksum: sha1:faa2ed1cdae4ae1ff4534b709c718e1a854c7ee8 @@ -740,16 +760,16 @@ trackedFiles: pristine_git_object: 5333fae7f3fb953439905529c246d31e90c0837b docs/models/create-plan-status.md: id: cb2e4b4b718d - last_write_checksum: sha1:5d4dcc420558a49ccdaf2931738ebbe09dfbb2f5 - pristine_git_object: 01165a04e3c5887958957a73150ea166229d86f7 + last_write_checksum: sha1:9d06e4c18d16af4e30f8599770874438206695a7 + pristine_git_object: 9176e8970812a64a9fa8f222cb804f98ad799e53 docs/models/create-plan-tier-behavior-request.md: id: a8b6b86a026a last_write_checksum: sha1:9ef8eb045da5b7fd0865603b7482d16f34dbe425 pristine_git_object: b3a2fb612213fe3ab0669c4c7e197ab83b3b2f36 docs/models/create-plan-tier-behavior-response.md: id: efafb363cb61 - last_write_checksum: sha1:98d171de5564d6e60e0844caf3ad8663285b70dd - pristine_git_object: 433e1c442a5f1c99bd755e45dc4b02e07afab7ac + last_write_checksum: sha1:8640c7a5a3d2d6d704b55c88e09481ce6da114ea + pristine_git_object: 8d87736b1e186c41aacc8e2f310a2ebf2fe6d817 docs/models/create-plan-tier.md: id: 9f8755fab2b3 last_write_checksum: sha1:9cef313a71dfe0ebcbfdfa3158e5a09cf380db2e @@ -760,8 +780,8 @@ trackedFiles: pristine_git_object: 86be2ef4df506af2e5f0886c0cb149453e6bfe8f docs/models/create-plan-type.md: id: b41ecee1f888 - last_write_checksum: sha1:f6b5067df1df12946d1d846d73d126ac5ebf2d73 - pristine_git_object: 0ed951484d4a3ca7527f3dd73320b24f3e4e3127 + last_write_checksum: sha1:d68e8655fd6692d7227e237051e746d4704f3055 + pristine_git_object: 6e9be0f142bba31c244a5c9e33b97bedb255f4a2 docs/models/create-referral-code-globals.md: id: 6e32bb0907b2 last_write_checksum: sha1:35e5d951bf5ff283f2c8325e02b597ec695cd0c4 @@ -780,8 +800,8 @@ trackedFiles: pristine_git_object: 675e2677bb14f3785175b8f0545c58f216d3fe0d docs/models/customer-billing-controls.md: id: 301a2b34ca74 - last_write_checksum: sha1:b99e2869f932eed0336a01f9a41448ed7c4d66e1 - pristine_git_object: 2cad5bcec72c06213ed5d70cbc833bb9b6056fe7 + last_write_checksum: sha1:93017e39c4ab759c8b149bc1924898914752e058 + pristine_git_object: c149dd4355a96397576326e7d9638ad58cf955b5 docs/models/customer-credit-schema.md: id: fa77c00fcafd last_write_checksum: sha1:ef98406b2bfd786c688c58331f8c60dd3768edc1 @@ -792,8 +812,8 @@ trackedFiles: pristine_git_object: 08690cfde833286110e149d4bc79a1dafa6d3010 docs/models/customer-data-billing-controls.md: id: ca09ea9a9d79 - last_write_checksum: sha1:96cd68586beeb120566f28fb0c93381b8fc0ce76 - pristine_git_object: d0e05395ded092f93d9a2829159704b688d7d357 + last_write_checksum: sha1:56444a8bd451fa1cd97d8cae818cb5f477d0da53 + pristine_git_object: 606866af27c288f4eec2cd2a6212de939543d575 docs/models/customer-data-interval.md: id: 3e52ae6b53d6 last_write_checksum: sha1:cc448a4ee6f5523b21d64f5e3c169626569d3161 @@ -806,6 +826,14 @@ trackedFiles: id: d6adb304f72d last_write_checksum: sha1:f510b4b0b5dcc6eb489318705078eb5683f348d9 pristine_git_object: 57c583eb651726cd311cbf33a1094773ff5bc1c0 + docs/models/customer-data-threshold-type.md: + id: 31ee69581c25 + last_write_checksum: sha1:54134d596ff7d386c5ac35300ab3c77376ebf118 + pristine_git_object: 89456db6d6ec404f7c652c332963de1a6517dba5 + docs/models/customer-data-usage-alert.md: + id: 4c36e645b4b3 + last_write_checksum: sha1:f531ce96ae322f2c8f4c8a615173199dd5238207 + pristine_git_object: c35e4aabef725a11d35c3ff126882cb94e7f908a docs/models/customer-data.md: id: 4561159f8324 last_write_checksum: sha1:a20bc91530f160598ed7556e1f44611e2a7ba49a @@ -816,28 +844,28 @@ trackedFiles: pristine_git_object: 72c256a9fe65486b7f0947ae7c4e1a08d307680a docs/models/customer-duration-type.md: id: cbfbb0769db5 - last_write_checksum: sha1:da368cd99ca260beb69f494102b503f0ef1fb131 - pristine_git_object: 3ec8623592871f2a2688f3c998d8edaa1fbd44e0 + last_write_checksum: sha1:5cc7fc548fc238c2c4db1517e1192dc036a74139 + pristine_git_object: 1e752c7056ae635cb6bd8aa5a72ee4a95db57ed2 docs/models/customer-eligibility.md: id: ca41bb82f9bb last_write_checksum: sha1:46c74c47a94a6c3272cc93f14c3e59513e73854c pristine_git_object: d116ce2acc6a2402cfbbfc03b68d6c83e655e689 docs/models/customer-env.md: id: f063b206890c - last_write_checksum: sha1:56f837d6ce27108c0ce1734d43119af75f9f6f76 - pristine_git_object: 654904fdd157bf55e25c3178991dd11d1317d485 + last_write_checksum: sha1:cc47133530e606c040759b3f18b48dad7b78cdae + pristine_git_object: d210083c532e8c527f089ea2abc2c227e2b7d8e2 docs/models/customer-feature.md: id: d90579a4e5c4 last_write_checksum: sha1:50870acf6a5fb9210beeed5c2c81e91a526d9c48 pristine_git_object: f38cdfd6ea5b5adec63eb912ca1339d50097614d docs/models/customer-flags-type.md: id: 42f5241c0bbc - last_write_checksum: sha1:eb1df3c4eafceb4af876a37ca91b6b0967abee2e - pristine_git_object: f5d8ac258d33cfd15ff581872aa4c0be9e9856a1 + last_write_checksum: sha1:aa84fa88f66cd8aae81a6e4d19c78a9910494f4e + pristine_git_object: 1484c10d794f0953afecf9ce7cc90ad3b2a9516c docs/models/customer-interval.md: id: df82a4aaf8e4 - last_write_checksum: sha1:d0b0e17f007ca5ac56800b6bb0906d6b5a39004b - pristine_git_object: 7f6886d54d124f6bef8f831bf084ded8da6ab8b1 + last_write_checksum: sha1:aaf308010396f889f64bbc0f1b6373a2b0be58df + pristine_git_object: 4be272a478676c247a14abd8118bf9c934916fb8 docs/models/customer-purchase-limit.md: id: 5bf7b9d4d318 last_write_checksum: sha1:6c6e6ad9afacda8aa5ea11f0866876dfcfa4b82c @@ -848,8 +876,16 @@ trackedFiles: pristine_git_object: 3658fb60429ebe70a39433584f8b991b2d04d9d5 docs/models/customer-status.md: id: e9ed998dbc6f - last_write_checksum: sha1:e2cbeeda5d8612ec18a98fd9e8a9c34af483753c - pristine_git_object: 30609b6ffb83a8ae805e29085c45246fefebb0f4 + last_write_checksum: sha1:11e549413866ee056d72b3c553da31b1d3391f07 + pristine_git_object: 20a2ee1d46ba4b86e4949d952e7dfc916177f056 + docs/models/customer-threshold-type.md: + id: 7b025bd502e0 + last_write_checksum: sha1:10900749d325726d95a259d942aa262aff2fcce4 + pristine_git_object: 90ab7fbeb380ccf210fd9b1fabca7a27703718ab + docs/models/customer-usage-alert.md: + id: 97223e162da0 + last_write_checksum: sha1:61314643433dbe105e3604247b17fc0659043ddd + pristine_git_object: 84f73f3108ecec7ee45c99c4fb9fa73863ee7c41 docs/models/customer.md: id: 42ac97d31359 last_write_checksum: sha1:da948098c6107d0f14bcf6f83f54868236d4e7bb @@ -924,8 +960,8 @@ trackedFiles: pristine_git_object: 1cd19465e5e2ccba85d1117383cbb3ee6cae7763 docs/models/entity-env.md: id: 817aa096ab27 - last_write_checksum: sha1:252538702571222f383aa430014bc61b99eb4a81 - pristine_git_object: 583f6eaf6f0c06982b6a1287fcbb81c17f0c6ced + last_write_checksum: sha1:e57c22c174cf8744c9fbc793a21c87eab86ba81a + pristine_git_object: ea4e92658978c0c7494a04f24e0f2e9276baaaac docs/models/entity.md: id: 903c73579a5c last_write_checksum: sha1:2fbd49394f3b36f26993a3d9b8a15da25f190727 @@ -940,12 +976,12 @@ trackedFiles: pristine_git_object: 032d2464b6ff1e4b2f1a35591a2014edf4ed21e6 docs/models/expiry-duration-type.md: id: 3a927f275515 - last_write_checksum: sha1:19a85259a30b26567db272e409038d45136a35c8 - pristine_git_object: cdf1d50ae086bd5778c6c266097c00619c0787df + last_write_checksum: sha1:c3248609945783ebe4b18bff68bec64bb1699694 + pristine_git_object: c622ff90557f1ff06fad783abed2c86415cfd372 docs/models/feature-type.md: id: c6368d6178e0 - last_write_checksum: sha1:6cfb774eadb97f33ce64f0e3a0d6a651f989b2c9 - pristine_git_object: 8d1c1037ac18f2073977feb666331ee662cd3ad3 + last_write_checksum: sha1:6505753d40a5ec1a42484e598418b79fe62b1495 + pristine_git_object: ddcb5323b6c9287ec6a5dd1d5ca65dee921c228e docs/models/finalize-balance-params.md: id: d27a9dc54b34 last_write_checksum: sha1:4a792e241eec2080f50ce35affdbe233f2452da5 @@ -964,8 +1000,8 @@ trackedFiles: pristine_git_object: 382a852fd69e97fa81176acdd66a374f5254399a docs/models/flag-type.md: id: bea64d93e37a - last_write_checksum: sha1:f347144e427f1c112728d1822c769c87fce21e6f - pristine_git_object: 7bb722b222e6bd30c8da293c4e3ab33005c0f14d + last_write_checksum: sha1:dbfa4f493bd520efaafd03628374cc19eb1efa17 + pristine_git_object: ad92646088cd31262986013299eb764f7711e832 docs/models/flag.md: id: f7a84826e2db last_write_checksum: sha1:68a6e6d129bcef481cfb50fc83955242d6c63edf @@ -976,8 +1012,8 @@ trackedFiles: pristine_git_object: 31ef9d606867dca40dea4bc8c751118acfb7077f docs/models/free-trial-duration.md: id: f12ff48f6deb - last_write_checksum: sha1:522ce4071e5cacf6aed1573e6b9c4ef8114de6f7 - pristine_git_object: be7e436b27f6c19e74687875395980c34840b330 + last_write_checksum: sha1:dbbd74a45263a761d7c0e14e8e743e34aca1f19a + pristine_git_object: 1d6b973f2eb7216a623c8ee0a41253abd993eacb docs/models/free-trial-request.md: id: 746a54d9b71f last_write_checksum: sha1:3e9f8119181b6d56ed4f0021f8f97766996ffb04 @@ -988,8 +1024,8 @@ trackedFiles: pristine_git_object: f9f3e74e3e6f989e12f5ae4ebbcaf98de2a2e6ff docs/models/get-entity-billing-controls.md: id: e5f62ec2d730 - last_write_checksum: sha1:6131fe9997d4772d5026f74a9bf7e142af77e9c9 - pristine_git_object: b2ce4bcef5cca2441f8d6aa94e1ed3a0dbb68ca7 + last_write_checksum: sha1:9fb89839a8eb58fd962052f326d1f91730166fbc + pristine_git_object: 90d9420da3a8ca814ab31c5737ec68c1f1ca96c6 docs/models/get-entity-credit-schema.md: id: 6f32eea7abc4 last_write_checksum: sha1:42a082402cccd20654f96e6af78f165d340b8324 @@ -1000,8 +1036,8 @@ trackedFiles: pristine_git_object: 9e676b05370fb3301b52b7edf3ac386eea2ecaf6 docs/models/get-entity-env.md: id: a0aec49ca920 - last_write_checksum: sha1:77edfad129919a116f78a82d247a81687cb93e2c - pristine_git_object: 8dcd9a68d2142e9d5fc73e97b0f6529641c45cf7 + last_write_checksum: sha1:dccda9677d4762959de028b0008965c35968f846 + pristine_git_object: 5490fe5912db6de66a4cfeb05914e41db0cdf110 docs/models/get-entity-feature.md: id: 61710e83f226 last_write_checksum: sha1:ae045ca5a705c07a4cf28d8e8794682ddcc53c24 @@ -1036,16 +1072,24 @@ trackedFiles: pristine_git_object: 065ca1896d65d047ef5b955ec5bcae1c424ed4e2 docs/models/get-entity-status.md: id: 06f4024e9973 - last_write_checksum: sha1:c8b7df3b5f53540a93ad059be38d7f7f8abea440 - pristine_git_object: 525aa382f4566aa0945589bb2f76bd30dc734080 + last_write_checksum: sha1:1b1e20ff2b6580f8db11b441174e9d9ec923d2f4 + pristine_git_object: 065cb9fd1c823066fcc5e8b1c353eaf607cc82a4 docs/models/get-entity-subscription.md: id: 3c768c24c069 last_write_checksum: sha1:7c4324295c741949236c978bc968ae51e8d8f570 pristine_git_object: 6dc404626b7beea1ba32c01269a9debd4533edee + docs/models/get-entity-threshold-type.md: + id: aeffe83b54ad + last_write_checksum: sha1:a6a6ae317ef4ee35c0d9c670dd61d6813b70232a + pristine_git_object: 9c79acd3f9b34c9283cc78b65b22b9f3bc5adbd3 docs/models/get-entity-type.md: id: a4327c9850bb - last_write_checksum: sha1:3b87a7bd5465a9fdd2019145225799140a136436 - pristine_git_object: c464e454b6a0e4a3ac2c1c2ffd949116622d6c70 + last_write_checksum: sha1:fecaad9042b8619a1603d30d58255f5177519781 + pristine_git_object: 94ba6334208e020988a681dad64accc7db48116e + docs/models/get-entity-usage-alert.md: + id: f9d9e7763fc7 + last_write_checksum: sha1:695ec9f5a6600a3b961171787fb65dea2630f1aa + pristine_git_object: f842aa7fc2de506852bfe5bbf200c579b9ad9fff docs/models/get-feature-credit-schema.md: id: 66fa50a914f7 last_write_checksum: sha1:1df7f3c8c99b23f0025f2ddf44923b64cd50fe8b @@ -1068,16 +1112,16 @@ trackedFiles: pristine_git_object: d16228318cf121178c15d0e0856e659c946c6e9c docs/models/get-feature-type.md: id: adf0af07d3cd - last_write_checksum: sha1:b372f582c4ae8bd51c95c8018aaf03142b47d35b - pristine_git_object: e0b36186fee578620f2b18bc58b518541b35b7ea + last_write_checksum: sha1:6f3f919b23692a2dd79903a0c5731f7b32308410 + pristine_git_object: b6f5d8682632257e68d9c66bb9cb4c6552d7f696 docs/models/get-or-create-customer-auto-topup.md: id: "673761036094" last_write_checksum: sha1:24beeb4b836370993abaed525ccf19fdb06ff9c7 pristine_git_object: 6df7e31ae12682659c51e3257d70078858179003 docs/models/get-or-create-customer-billing-controls.md: id: e7ee10d9a50b - last_write_checksum: sha1:e599f0c656c9d65877c0c00074665b539704a2b4 - pristine_git_object: e7e44bd53b080f1a0c27dfc15c909fd0e64f2a6b + last_write_checksum: sha1:6afb2e2879f8a0fba53be5820b123d106331c93e + pristine_git_object: 45f6c861de029ebecb414b6e0a02321400997675 docs/models/get-or-create-customer-globals.md: id: 4dd584e66362 last_write_checksum: sha1:2f39158f4225bc4e4fbc5507304a0654c7a2af79 @@ -1098,14 +1142,22 @@ trackedFiles: id: 6bc905d17111 last_write_checksum: sha1:a1c4a90b02fabc01b874185de0d3aa140aaca40d pristine_git_object: 232804422517c0aa5ed2ff5bb9b8ec77840d4a99 + docs/models/get-or-create-customer-threshold-type.md: + id: 766bad11b2d9 + last_write_checksum: sha1:99c0f5113d5aa2e794b9dd67e479bb268af6e692 + pristine_git_object: f41a96ea31c804d3c2dbc78959a3e2603cdf666e + docs/models/get-or-create-customer-usage-alert.md: + id: 283e702fbdc1 + last_write_checksum: sha1:b57c3b716aed0ceab82f9ebcba9374d056ed50c3 + pristine_git_object: 2fec2e0823cd0191f91e5c230c103ef04b0912e7 docs/models/get-plan-attach-action.md: id: 6a535e94ba23 - last_write_checksum: sha1:568f646609ada6451a989afa855bbb2ca40a628e - pristine_git_object: 67cd113927bb4350810e7301e0d0b33e61817154 + last_write_checksum: sha1:d29bf782658f15fa9a1cf4f2e461b580e6dfaf5b + pristine_git_object: a30a9edfccad50810206fafb99234bf1cfd5390e docs/models/get-plan-billing-method.md: id: 81d8a111a09a - last_write_checksum: sha1:25fc939c3c24f1e4fdee1ac9f9668dcaea817291 - pristine_git_object: d7318d7d8db471de2c14e9f80225da5437dc0aea + last_write_checksum: sha1:af53690dcbacd8d9de1b8d0fd3ffc8d84b9bffc6 + pristine_git_object: f5768604cf8923efd72ddd1d24c7bae63b4a01e2 docs/models/get-plan-credit-schema.md: id: fdfd3a232487 last_write_checksum: sha1:bda036d0335542dc4bea36444ead3b4d1fc31c6b @@ -1116,16 +1168,16 @@ trackedFiles: pristine_git_object: 768d96909fc8180ee25a600550a9db192980341a docs/models/get-plan-duration-type.md: id: b69c3a89ed38 - last_write_checksum: sha1:6283a7934599cc7dfe411b90b354e15da3534021 - pristine_git_object: 9ed1c3f531807594ac3d3dd21c59bea0e6496ca0 + last_write_checksum: sha1:4d302f73a60464b04f4e308e464d3011868b3a55 + pristine_git_object: 08738e384e682b3df3764eede7f159535456fd11 docs/models/get-plan-env.md: id: 9c45998ac325 - last_write_checksum: sha1:f87836e8d3cb3db588f76938d3914b4b6fddef79 - pristine_git_object: b8b049c88110c8c3adc3d80c85b33597d46c7684 + last_write_checksum: sha1:890b15667716ff79fff0baa98d50fec4f9a963e3 + pristine_git_object: 502bfcc4939437519274d07cd5fa6c5bbd0dd091 docs/models/get-plan-expiry-duration-type.md: id: 206c98bb07a5 - last_write_checksum: sha1:81c85b9a298b808eb1e07ac1d85440c7da18a553 - pristine_git_object: 00e529721f22a1cd26ce3f6fb6d77034c5904dc6 + last_write_checksum: sha1:c348f23836894aa52e0c31d388e30281efe2d4d9 + pristine_git_object: 0b633db6c9efd1cf814354322813f0082081f213 docs/models/get-plan-feature-display.md: id: 5cc0dba3045a last_write_checksum: sha1:6e2a60793ef7e7a29f48b393ccc01d72643ea9a9 @@ -1164,20 +1216,20 @@ trackedFiles: pristine_git_object: a385e4971e5561943d86db76c3bf11fb6f024a54 docs/models/get-plan-price-interval.md: id: 9c62d7ee142b - last_write_checksum: sha1:d3b369e876d47f4f9aabcbc36b113481e2ada71a - pristine_git_object: f1f0994945733efed1b848a27b297c008db0fe71 + last_write_checksum: sha1:6a0e5cdaeb26bb7886e0a60f2ba76b4420ab1669 + pristine_git_object: 63a258d288c8a45cf55600b5ebbd1c6c6d64f1cf docs/models/get-plan-price-item-interval.md: id: a6f9d83e7977 - last_write_checksum: sha1:010243e4bc3aa33bd04a0180ea32ed488fed365c - pristine_git_object: 3f99aee7fa7da9240724cc0f8937ae207163d267 + last_write_checksum: sha1:a4d16145daa8c651ecb1021f7676edf990a25c0b + pristine_git_object: af0c14090c03fda28711dadd99a1f54bba08141c docs/models/get-plan-price.md: id: c023219918c5 last_write_checksum: sha1:df9fad9b9570fbc20e35f04904f7cdc72bc471fb pristine_git_object: 8cfac5aa0600ecd1b8a5824bdfa278901ef66195 docs/models/get-plan-reset-interval.md: id: 1946366bc337 - last_write_checksum: sha1:9b8e321a6cfa15b9414b8a4abb7195e6b856512b - pristine_git_object: 7719fc58d5f440fbd2054f5aebbce3389f65b0b4 + last_write_checksum: sha1:d14fb798d8a7653d86ab2aea1172817e78260352 + pristine_git_object: 56d62f31decd85f39503c155e8d285add8b8918c docs/models/get-plan-reset.md: id: 271f23d3ba6c last_write_checksum: sha1:d80f52d6e012e26551f2fc6e49ad25dd2a22d423 @@ -1192,24 +1244,24 @@ trackedFiles: pristine_git_object: 2ed20d9be6b31bd70b2d30f0b517cd4470cf6273 docs/models/get-plan-status.md: id: b2b6fd3f7f36 - last_write_checksum: sha1:57e8addd1b9b62b57a14a4ffbb5e25d83f3d0dcd - pristine_git_object: 4d5fab597cb8830b619c94f124a30ac6fb6d3087 + last_write_checksum: sha1:677539b6b32bdb5d489ca1465017b3762e608740 + pristine_git_object: 6393a8749c562bf17a451dd2968f9d80ca1c5726 docs/models/get-plan-tier-behavior.md: id: f3718ee31687 - last_write_checksum: sha1:7fd442b40cca24b5b2058587b86b8343791549d1 - pristine_git_object: 4e14d9501022fe440e86ccb830a2caaf90352859 + last_write_checksum: sha1:1a2f2d68d35dd37f988476bc96bdffa2299d63eb + pristine_git_object: a03d5171735676a42527f85a76a9663d70890c4e docs/models/get-plan-type.md: id: 5300ef539ed8 - last_write_checksum: sha1:b334efb80b4e13e356c43248994d2f2640ffcf27 - pristine_git_object: b6ff1ca2773ceb3a33da7acc3bf2144f2823c16a + last_write_checksum: sha1:71adbae5b4d49f8e04676cf58a35318bae15ac48 + pristine_git_object: 75cd05fc9753020eeda5607a4cdefb0723b03482 docs/models/included-usage.md: id: f27abcdfdd7d last_write_checksum: sha1:ca0a41260fa62322a9525f4267ac0ec6d93ae6d8 pristine_git_object: 5fe6a61067cd319d6cd0d1e1e7f1d165c0d4579d docs/models/intent.md: id: a4a6fa8818f7 - last_write_checksum: sha1:39fa3a78bda572fa9b8a765966413b6d2b4436ea - pristine_git_object: e555a3ae8dede23c40e8f431e1b6101cf5e7f21a + last_write_checksum: sha1:eb7820865f56b87283859213490921e05cff1795 + pristine_git_object: 23c92340b59eda49f7ef7aa97bb9035a00bf6f20 docs/models/interval.md: id: 11a74d2c19c0 last_write_checksum: sha1:5f0ef8c55bb702634292f728b5abab0d9a0b9319 @@ -1228,8 +1280,8 @@ trackedFiles: pristine_git_object: f60f6ca4e299bdea107323dacb9349333bd62500 docs/models/list-customers-billing-controls.md: id: 28916a0d81f3 - last_write_checksum: sha1:402e141c7b2060d74716e16fd28f453a67abcf0e - pristine_git_object: 5b85d9e7e499c58d23d6179d35e4c1b74c0db9d1 + last_write_checksum: sha1:066331d3ade1c88fcc6c667650a2dcab3608b4d5 + pristine_git_object: de1786cf1660db01ad9db6d7887a4a670aaa5e55 docs/models/list-customers-credit-schema.md: id: bd8c18aa56d6 last_write_checksum: sha1:c5e78bcd3c4e7685e81788f23ab6251269f649c7 @@ -1240,8 +1292,8 @@ trackedFiles: pristine_git_object: cb09afda7dd728b185e62165bedab7c2ae878c54 docs/models/list-customers-env.md: id: aa422f2f068e - last_write_checksum: sha1:1eaa89b04ceb126d8854095fae4a375ad3b6690f - pristine_git_object: e8319e97653a42eb67a6e54d154471cde8182df8 + last_write_checksum: sha1:2813f4b038dd5a0145a4904890f8e87bc83ae53b + pristine_git_object: ae3dc7884d8884306e3df9310c093ec681637681 docs/models/list-customers-feature.md: id: e66feeb7ba38 last_write_checksum: sha1:6d64076d70976a5807411ec74edf56dddae486e8 @@ -1256,8 +1308,8 @@ trackedFiles: pristine_git_object: 8b5163cedee225b4b80be05037d7267d2f952b6c docs/models/list-customers-interval.md: id: 0cf67d0395ae - last_write_checksum: sha1:ca79dfd9771a32ba36f0c77c7fff79152a204e94 - pristine_git_object: 1f0bc2955b718a93046892f7bf5593afedd5a730 + last_write_checksum: sha1:bdbd0a010da0ab3d0c5a55c6d8b5d4c1f5e70897 + pristine_git_object: e92cca5d7a0d39aa5ac3245ae4197ab4db830cb1 docs/models/list-customers-list.md: id: d9cf28563990 last_write_checksum: sha1:22c3d4996dfd7b25f65919c4f634295b34567e37 @@ -1288,16 +1340,24 @@ trackedFiles: pristine_git_object: a0bcde52449c9b05ec2ffbaa3fd81ea911a1dbd1 docs/models/list-customers-status.md: id: a101fc59dad3 - last_write_checksum: sha1:d17ff581b24d4b6ae97ac01f672c6ccd2619e1e9 - pristine_git_object: ebb49c197b1cec0e7efbfbed9ff9d1429a5043e5 + last_write_checksum: sha1:7b6f527d630b8733488c3527c6097ab8ffdd1c88 + pristine_git_object: cac7cc97ab962419fca75b9d9d2982d25343f5e9 docs/models/list-customers-subscription.md: id: e5c39bdff7de last_write_checksum: sha1:2149bab9fbc402075c6e6fad9227da4d934f6354 pristine_git_object: eebfb64ba72352c3bdd046c5d524791b545c2c2c + docs/models/list-customers-threshold-type.md: + id: b31853748775 + last_write_checksum: sha1:f359dda63ff1705871ce3344f33ae07e3f4eeb5c + pristine_git_object: bb811c0e2545ab22359bc414fb108867599c8d32 docs/models/list-customers-type.md: id: 0800cbc8ca9e - last_write_checksum: sha1:ce2e02b77c93fceb4112a25522981cb9ad28da4c - pristine_git_object: a8572a253eaff23800e32b97966b27024a175d00 + last_write_checksum: sha1:2305f2fbfe8e5dacd1feba04a09abe8ecb6cd9c1 + pristine_git_object: 684d4be1ed4b78ef115955bbbf9b4650f2d7e93b + docs/models/list-customers-usage-alert.md: + id: b3eb5cb1a703 + last_write_checksum: sha1:1b748d9d32129465a66933c5dc33f1a0e0eef542 + pristine_git_object: 5c72a5e92a135e3759dbf9a0c04d327672e09693 docs/models/list-events-custom-range.md: id: 61ea802fb875 last_write_checksum: sha1:29739e8653c6bc2cb893b8c5fecd7503436f91ad @@ -1348,16 +1408,16 @@ trackedFiles: pristine_git_object: b4ab86d4b5ca500d8869996c31423005554d3bae docs/models/list-features-type.md: id: f90d587b8227 - last_write_checksum: sha1:92e406420f065240cc86249766dd22cfecdbcae1 - pristine_git_object: 2d4d45ea57e3eae7530b2907f918e7f021f70017 + last_write_checksum: sha1:a2a161ab7484bdc88a761c9f1317f3ec45c5fdc6 + pristine_git_object: 8561f5a4e0c0ba1a6a51af8a42713d89b9ba40e9 docs/models/list-plans-attach-action.md: id: d5b7f6e0bc00 - last_write_checksum: sha1:15a5241965f68db426a82537358beb64cad4cd2a - pristine_git_object: 51288bb87c4d1375aa9931b702b721e079b8b7b0 + last_write_checksum: sha1:06d3b009d198986ac24d7c78fc95fbf690a4f488 + pristine_git_object: 93e4587446540b93ffbe0098d3b3f13742c2c596 docs/models/list-plans-billing-method.md: id: 925f450419aa - last_write_checksum: sha1:6b7a4aa06733643802a7ca7e0f6fff763ca86eaa - pristine_git_object: 0466e6a0248bc7e481df111bed7f2db6e27c1e7e + last_write_checksum: sha1:f21829d201a1c91e6ca49463665829e541673d1d + pristine_git_object: faaec3e2653fb569cf621ced508c9b9d163f81a5 docs/models/list-plans-credit-schema.md: id: 3f2d4bd971cc last_write_checksum: sha1:11870331e68516a49daa39eab1dc751ee0a8674b @@ -1368,16 +1428,16 @@ trackedFiles: pristine_git_object: 1781568825934493fdaa174ef979367fd8ceb960 docs/models/list-plans-duration-type.md: id: bc63d2df769a - last_write_checksum: sha1:45a173ddde00f7fdd452a101cf08c6da37158df0 - pristine_git_object: 0bb25ebb30782b3165b8636755729ace8c852c09 + last_write_checksum: sha1:776412644be4783cd7fa9929c44f47cea49d2c03 + pristine_git_object: 24872dad4da39ca8c862e2629fece4bdfcf036b7 docs/models/list-plans-env.md: id: ef9fefbeb4f3 - last_write_checksum: sha1:f1c7dc0b446382318c24004d12f251764b6e0157 - pristine_git_object: bf77ecb66d9c8252e726d98fed90da940edefac6 + last_write_checksum: sha1:5ae97a1a4b7cd7b5c28393370fc70b0a3ad0f9a1 + pristine_git_object: b96f9cd95d8b53e7861771dd649b07607ba5f270 docs/models/list-plans-expiry-duration-type.md: id: 402de479f254 - last_write_checksum: sha1:6ce713141a2a8ad9f973f483239e5a2f1fff5446 - pristine_git_object: f46195e1be2d173f4f413cf5f297675dc5ba184c + last_write_checksum: sha1:44dd4a40c1454a441e2ab569f57dab51dd13f77a + pristine_git_object: 4844fa2eabe6067b1145b9f25cb1a9ba38eeb3d2 docs/models/list-plans-feature-display.md: id: d27baf90b440 last_write_checksum: sha1:883be8ae59b1164c14ff3f905365186ed4fdbc38 @@ -1420,20 +1480,20 @@ trackedFiles: pristine_git_object: 151bd7cef491657c4abca9d42008db6e3c7f0906 docs/models/list-plans-price-interval.md: id: 4fa8aef0b379 - last_write_checksum: sha1:c5feb012c9ec8e2e24914c8878f55b56c8dd0557 - pristine_git_object: 93cbd870f42f2b7f5b37d4d3d434b8d879bc51e5 + last_write_checksum: sha1:72d2e73954e84b0dd48e4a4af9a618d2cd81ab8f + pristine_git_object: 30ff6e6a966cd85f9754f0cccb2ccaba7b033208 docs/models/list-plans-price-item-interval.md: id: d61bea75abb4 - last_write_checksum: sha1:f8f5ef795a7a71897bff8d7e2fb39d280fbecb9e - pristine_git_object: dad8bb2a8ce0bc424ebe4417780bae3f2a0185d1 + last_write_checksum: sha1:c2fef21a913012ccdc85cda5c744f5118311af5b + pristine_git_object: b6fb74fa26de953985e49d79fd64d7400cf72aee docs/models/list-plans-price.md: id: 0ff7fddb4c5c last_write_checksum: sha1:ac808a57822330e7ae85f89c01baef6f8b71daba pristine_git_object: 221e8ac6b0ee5624f8a778162a56f0982458262a docs/models/list-plans-reset-interval.md: id: a8239738ef9c - last_write_checksum: sha1:d5a8b51e7b8b6a3792a21dd16cb36d3b3957ee04 - pristine_git_object: dcdaf47f0ca861b2b52f6458698b8bdf6488655d + last_write_checksum: sha1:6105403c713550f4d3d1c6a785e2fece51fc1454 + pristine_git_object: c6b71b112f78677e6051a95cb8da7b60007fc690 docs/models/list-plans-reset.md: id: 73e6ea5c00e7 last_write_checksum: sha1:21018da5956ea86b823cae081af9a99c1400a8ad @@ -1448,16 +1508,16 @@ trackedFiles: pristine_git_object: 760b01c5522a773685658074ba52e25bfbad02f9 docs/models/list-plans-status.md: id: b9f9a3b52ac5 - last_write_checksum: sha1:55cb11b9ddb0d3bb84effcefda0112a6fab859c3 - pristine_git_object: ca021a4fac21f62f99ca1fd50c7c284720e57caa + last_write_checksum: sha1:86b03c7db83295b5a6db46dca44d0b0bdfe55cb3 + pristine_git_object: 2be2e9d1ca17a61443aaf12ef416463668254df4 docs/models/list-plans-tier-behavior.md: id: 3e6b30e1aad3 - last_write_checksum: sha1:9f8478155d4f98a1156bc3364baf32b69d128e9a - pristine_git_object: 924fead782b1c352ecca3fe8980e36c0fd22ebd7 + last_write_checksum: sha1:d429823d060ba77f2ea07699a45bb00883b73c15 + pristine_git_object: 077a40dfdaac9037f7ecf4ed5a659165a709b8b8 docs/models/list-plans-type.md: id: 902fdb41bbb2 - last_write_checksum: sha1:d193eb535e717935365e99a4eac285d50cfd0288 - pristine_git_object: 8f2779e720e50be967f02698e4e5aa8b89b05e2e + last_write_checksum: sha1:8a14d90ad1601b2d21551520d37af9a93fe51db1 + pristine_git_object: 4ea81aa954edc194f40ee68038b0d4f578c04ef8 docs/models/multi-attach-attach-discount.md: id: 3536a21c4f47 last_write_checksum: sha1:2dfea27b10b93fd68105a4ca58a94f4d4bcf1c1b @@ -1468,16 +1528,16 @@ trackedFiles: pristine_git_object: 199a981d4f69a2401e27f70c412501d66e314cde docs/models/multi-attach-billing-controls.md: id: a2377cae5b76 - last_write_checksum: sha1:4b73860a51e4b96dc97914665f3ee55c2ed14866 - pristine_git_object: 5159b5792907d9ff6ddbbbab7624257c1c133d17 + last_write_checksum: sha1:b4ec8e7c64ab19e45b8d00ea47eec354a5d794dd + pristine_git_object: 31dd439bc05f5aa2f1a68de8d502630bd0a0103c docs/models/multi-attach-billing-method.md: id: 0a1702e9b84b last_write_checksum: sha1:9d863ab54bef7b8b74274b98275c70565f5473cd pristine_git_object: 9f2a0075d180395846c3983ea3d08951a26c1b1f docs/models/multi-attach-code.md: id: 09921b9ac8e1 - last_write_checksum: sha1:671b0456d6419384e67921a9f9a732ffc09a5b97 - pristine_git_object: 8a4eaa5b71c739b2f9ae755205fec9401fb1a70f + last_write_checksum: sha1:ae1135e9ef6470f2e322b2ecf00fcabec0462413 + pristine_git_object: f02c727931ffa9829ba35f4258b5d236c78ebd4c docs/models/multi-attach-customize.md: id: aedf94cc14eb last_write_checksum: sha1:e691f0270d87b69a45e6e7422bbf55802f798479 @@ -1578,6 +1638,10 @@ trackedFiles: id: 1ccfbf701bab last_write_checksum: sha1:77f6a60f64877d9c7ac5906bc43fb6b015fce7a3 pristine_git_object: be79c8fcbc9f81c5151e23308ebbca464ab73bf8 + docs/models/multi-attach-threshold-type.md: + id: f02f8c74ce7d + last_write_checksum: sha1:dd09c346315fab084199517d3fe0994e28bc9476 + pristine_git_object: 4c926b87db17071084edfdb0e08f2e3bb1b0a0c7 docs/models/multi-attach-tier-behavior.md: id: 6e6fb0c88a8f last_write_checksum: sha1:886a4f6a6e04c4caf254f6a0917a2eb46b3c552f @@ -1590,6 +1654,10 @@ trackedFiles: id: 9cc63135019b last_write_checksum: sha1:cb16b10293c7cd3917ccb6555fa95bc3c18ac65c pristine_git_object: 6c21843fd4846a9fb1ea645b25a94269f564008e + docs/models/multi-attach-usage-alert.md: + id: 7d49a7ca51a8 + last_write_checksum: sha1:ed3aedaa8fedcc7a80d8e5b2a57daadaf91fdf66 + pristine_git_object: 13296d7142996405188e7ce0dc78a01e51556e59 docs/models/open-customer-portal-globals.md: id: e0e501393359 last_write_checksum: sha1:eb5269be19a6426dfb429110bd750f61a9e2495d @@ -1604,20 +1672,20 @@ trackedFiles: pristine_git_object: 160d8340897a8bb4ddc8999bd05e49e2baf3c0ec docs/models/plan-billing-method.md: id: 4789ae90ae01 - last_write_checksum: sha1:7e999cb8f855e8f3d917a2024ed3fd88803b45cd - pristine_git_object: aa533c8b3c984f8773a81063ee748107b2eff98d + last_write_checksum: sha1:034ade6e914f7441adf1683c0a9a725bb3ed0234 + pristine_git_object: 6a3e64020748ca7ae31dde83e60228393c659da5 docs/models/plan-credit-schema.md: id: 4a323c1dbf0a last_write_checksum: sha1:167acec310caca3e8e3b1cd5461c5453994f09c9 pristine_git_object: 9dfd58042a96b6de19c6f5f3a21319e1806a35a0 docs/models/plan-duration-type.md: id: 522f79a4e1c8 - last_write_checksum: sha1:abc4c07df7482ae02965a688a956fbb8ec78f476 - pristine_git_object: 304fef3c1f5ee4d7dc24c98227f9e83b1ac6aa65 + last_write_checksum: sha1:1e4df37111b655c409a222f584889f794630e9df + pristine_git_object: 5ca43e03701cb24d900c6fd812a5a140be6a1039 docs/models/plan-env.md: id: 2684553fa0b2 - last_write_checksum: sha1:93e915bc71fe7ba3a8838bc659f1dee939f811e5 - pristine_git_object: 224f3c0569379464c201563e5e5046791ec50860 + last_write_checksum: sha1:8dabc92b19ee301cffbe36bd04e57f33fe05b078 + pristine_git_object: c373f26a00337e22d7530eb9dd99c78bd2970b11 docs/models/plan-feature-display.md: id: 4a23e75025f8 last_write_checksum: sha1:bf383e336435e84f0c51cbf12ad34db39fd5e8cd @@ -1640,20 +1708,20 @@ trackedFiles: pristine_git_object: 61d0d0140fdca02b6fb7b1767e44a57789ff970e docs/models/plan-price-interval.md: id: f4940ecda555 - last_write_checksum: sha1:86d2346e9f97589d88982142e5a8905cb490c68e - pristine_git_object: ee90166f582e2f298d9ae7fc6a7116d030d4c4bc + last_write_checksum: sha1:74cc6484180203f73664a7b151f5b49fb56b9072 + pristine_git_object: ce8ac898fd976c7e213cbfa7a95ec0e25b5cf761 docs/models/plan-price-item-interval.md: id: 2c196a6cec70 - last_write_checksum: sha1:e05edb29e63ef3326bd0c7508c50d59c5157c7dd - pristine_git_object: 09214f5b39fb6f6413144996b8e36afc4b332cf5 + last_write_checksum: sha1:6eb92ba0d4c53b5c2942552ad33c4c8a585a51eb + pristine_git_object: 630586b26f677b90d85d37ff688c8ac8d3b65775 docs/models/plan-price.md: id: f24c0778a8d1 last_write_checksum: sha1:0ae6e5e8e0293c24c92e93d0b98462627958bbbc pristine_git_object: 6a5f8089f942a4a783d148d7a1635970810bda73 docs/models/plan-reset-interval.md: id: 3ae21ed47961 - last_write_checksum: sha1:2647a361fd4c09e1d40acf1343d1c7254106d635 - pristine_git_object: b33f9090de57babc4885223099140d50825103cb + last_write_checksum: sha1:3707cc1f199c2c5138f1575d9d2d451648083761 + pristine_git_object: 5b8b97ba7166041db705ba0b92320fc2edafd78d docs/models/plan-reset.md: id: 1984f6727dbd last_write_checksum: sha1:20b04531084a0f459a1e1f32759dc647571cdb17 @@ -1664,16 +1732,16 @@ trackedFiles: pristine_git_object: ce6551a619ecf231881a602e7eff3f19a0df7d76 docs/models/plan-status.md: id: 3be17dca36b3 - last_write_checksum: sha1:fe2d18a5114bcc66f1f598d7930381a199e1488f - pristine_git_object: c201b3b3faa9c9f9e6ca5e6857d43ddad6b9fc00 + last_write_checksum: sha1:6df376b0847c418721c5ae272172228163302058 + pristine_git_object: 65984d328b576f9d05b489061c52cd7536f98a91 docs/models/plan-tier-behavior.md: id: 460cbe1aaa95 - last_write_checksum: sha1:632bab29fca02e35bbfc910cc2ca767e5245bb97 - pristine_git_object: 2b00459690aac0d23f912cc3408e1aea3784b8b4 + last_write_checksum: sha1:e2a361ce89641eda51df68d8b4149ec17d0c7354 + pristine_git_object: eccc4d94d4a1ac29ff970f7e706e9f8b94611cfb docs/models/plan-type.md: id: fcf04293a720 - last_write_checksum: sha1:ecc184cb1098804970168b1cc83516a04107f2ff - pristine_git_object: 7bc7590d5b2edd57dc26811f4a9ce9e60d4c02a3 + last_write_checksum: sha1:8a55b776c10325c521c94693c2301c3d35865204 + pristine_git_object: e573a1e61915a219fc68d1e31dd55c795dda4253 docs/models/plan.md: id: 900c4149ef4b last_write_checksum: sha1:62a2df64c93f1320fb1a1175222770ede624008b @@ -1736,8 +1804,8 @@ trackedFiles: pristine_git_object: f556d0824e0231f0b3f80a9a24e033cb7f32bcb7 docs/models/preview-attach-incoming.md: id: 562e0f8189a4 - last_write_checksum: sha1:fdd8b435c79ef32de421b73230c664e226c68036 - pristine_git_object: eb39be1e520b9fedda1639bbc2c5766970925dc3 + last_write_checksum: sha1:eb23a93c214d9ff39f5381c4dbaf3167132dc2d8 + pristine_git_object: af005b7366d908ba80f2f038ce0b5e834a4b40cd docs/models/preview-attach-invoice-mode.md: id: 52be741aaa35 last_write_checksum: sha1:aa2e16f83e6f12f781c200d6c0e39775d8c8184e @@ -1784,8 +1852,8 @@ trackedFiles: pristine_git_object: b6b9cab821c830095b2190d60b301f6798865718 docs/models/preview-attach-outgoing.md: id: fd5a276a9cd0 - last_write_checksum: sha1:aefbfe5be8ccd263cc036297d32f3af2477365c2 - pristine_git_object: ada9e4eea5f40d216c2ba31f87dc84d986af484c + last_write_checksum: sha1:9c77d7ae64f21914ac627b1a5e54c2abe26228fd + pristine_git_object: 5d210625047227aeae00e394f0bf104ae18de8d0 docs/models/preview-attach-params.md: id: 29fbf5be911d last_write_checksum: sha1:cb5be461a991a5258fc79f140a9c161214232f21 @@ -1828,8 +1896,8 @@ trackedFiles: pristine_git_object: 38738348cb8b3cb3f1466f4628e7c049ac8bc0a9 docs/models/preview-attach-response.md: id: f53481e3c4e9 - last_write_checksum: sha1:e693056e9671c707e57ba01a35601d8fa950be30 - pristine_git_object: 1c281ef2ecb3cb2b8832c9372569c79cc88f201c + last_write_checksum: sha1:f2597a87350bc64b10ef0b87ed88bfae05cbc107 + pristine_git_object: c6f5e8ee502064aa1152e9d66694021bc13aae49 docs/models/preview-attach-rollover.md: id: 45bd31144856 last_write_checksum: sha1:3a2f09b2565a522e050a728c885e822640ba0793 @@ -1864,8 +1932,8 @@ trackedFiles: pristine_git_object: 2c4b6c1f70e2eae9891821e6b5a1b34b1d9c64ad docs/models/preview-multi-attach-billing-controls.md: id: ce0ddedc67d0 - last_write_checksum: sha1:6c4ba82b4794253fa54d772f8a939d466a871461 - pristine_git_object: fc83158b3f5dc4b42a9069d2252ce823258fe138 + last_write_checksum: sha1:662c9d201162d19407d1f5d89011ba01602af7c8 + pristine_git_object: fc3ecbc9f8cb7a354eadf7c832f860d847ff4baa docs/models/preview-multi-attach-billing-method.md: id: 08a032b6436d last_write_checksum: sha1:8d37dcbdb16b45192fd041922ebd564c88e67b22 @@ -1904,8 +1972,8 @@ trackedFiles: pristine_git_object: bcc5d2e3c58e4cd2a2b7b07611e0653310d311dd docs/models/preview-multi-attach-incoming.md: id: 67ec83daecf9 - last_write_checksum: sha1:3781c843dac5d4b95b75f068a9773607e1ff8364 - pristine_git_object: 5dfcf9aff39f776d7d25560c47c99bc893cc0587 + last_write_checksum: sha1:ca66e7261025125291b058a837e464ab5928f9cb + pristine_git_object: 17dafbdca5489aff0889dca523fcb2cc94c43d6f docs/models/preview-multi-attach-invoice-mode.md: id: 3b06c211aa91 last_write_checksum: sha1:409db019762a74dba3c766d3b08e1a26f0914862 @@ -1952,8 +2020,8 @@ trackedFiles: pristine_git_object: b61c270542dd2b5d76397db487c3cdca174dc711 docs/models/preview-multi-attach-outgoing.md: id: 3291c58c5e86 - last_write_checksum: sha1:8a51956dc0c90db5a39ebe673281917303b439e6 - pristine_git_object: 6a8d7ab42440d8c85dd86ed913ec446b9615d058 + last_write_checksum: sha1:051fe779cbe6680d22b398c8c289ee95a8bdfaab + pristine_git_object: dc4a6ec8561e62c5f0808be788def7ee47efa814 docs/models/preview-multi-attach-params.md: id: 2d749929bd2d last_write_checksum: sha1:90f5ba02b2b4b815f8681f9fbc3fe980c63775b2 @@ -2006,6 +2074,10 @@ trackedFiles: id: ee69bccee8e0 last_write_checksum: sha1:740972361487a9ec8a73bc7b9553af4ffd6de9ea pristine_git_object: d8c311db6ef8f0def941b2f2384361dd4b48a191 + docs/models/preview-multi-attach-threshold-type.md: + id: 0319e15430f8 + last_write_checksum: sha1:c7d57f71acac72e95671508bd44b8c74e1d60ff2 + pristine_git_object: edf6d7291ba7c2a08148702f839f10b81ccff988 docs/models/preview-multi-attach-tier-behavior.md: id: 97ebd79496a2 last_write_checksum: sha1:f4d075f16924dc8196791acb7b2091702dbcd3d5 @@ -2018,6 +2090,10 @@ trackedFiles: id: aeaac9479091 last_write_checksum: sha1:ccfac3d8e2e623664f029fab1511d5d037676c6b pristine_git_object: 3e72823c679b396e06dd5a48d7f9e7d316a5c3bf + docs/models/preview-multi-attach-usage-alert.md: + id: d659a887aee8 + last_write_checksum: sha1:275161f8609f7587105f372e36d9779917f866d4 + pristine_git_object: 01d81b9f3e93ad897d5f12c8c879619fb7402aad docs/models/preview-multi-attach-usage-line-item-period.md: id: c38dc1d62a80 last_write_checksum: sha1:55002b0386a5d59a75e8dccbd201b96ca0618214 @@ -2072,8 +2148,8 @@ trackedFiles: pristine_git_object: 633fc298873b231e618d89bbeb2088ceb01a5a68 docs/models/preview-update-incoming.md: id: 991c5ea1f669 - last_write_checksum: sha1:4ea8e93296ed184a3d37b8f10e25ac8090392d7d - pristine_git_object: d6d34fd50361146c720bf19de335ee0d14a02a61 + last_write_checksum: sha1:920caaafd7129726e8e7bcaebcbd87e6a15f770a + pristine_git_object: f859f35f34578778e891fcd4ea8554bfd2e56aff docs/models/preview-update-invoice-mode.md: id: 50a22a368768 last_write_checksum: sha1:2753fa2eb31780aac9b3daff7744a571c290e59b @@ -2120,12 +2196,12 @@ trackedFiles: pristine_git_object: 0591d40c031e2efeb191782bc160aa17b6dc907f docs/models/preview-update-outgoing.md: id: 8bb066fbd6a3 - last_write_checksum: sha1:4d3ef1f7cbf2fb38be69112a7b89d0b2ae3f569a - pristine_git_object: f444eba07e8cdfaedf59304e3cf95e8e4d7fa9f2 + last_write_checksum: sha1:31ad3231ff396cc7b260cfa5de81c348e1786776 + pristine_git_object: 1d78c98b62d0a1101185567d854e18d93240442e docs/models/preview-update-params.md: id: 4f27fa514996 - last_write_checksum: sha1:15937d783cb2729b3f14cc5652e7f9a0e560f2e3 - pristine_git_object: 730780d43f4a4eb20189e54214bb4fea178cf07d + last_write_checksum: sha1:e32b8ca9b263070cee4028947265d72c9f6e3d44 + pristine_git_object: 96e1493a36a5bbc302f4275353f07fbaa7395bda docs/models/preview-update-plan-item.md: id: d9ec244374c8 last_write_checksum: sha1:4e0823c4d2cc23bbeffa8e42fbcb42a96deb4f30 @@ -2146,6 +2222,10 @@ trackedFiles: id: 096020425f5f last_write_checksum: sha1:2407ee797ec36dc229115a98eb9470cee8597854 pristine_git_object: 050ae04104ddf95dfa6d802d9caa132db36ed821 + docs/models/preview-update-recalculate-balances.md: + id: 8492e617571a + last_write_checksum: sha1:b42eaaf40821a806f22d0a5be11a543d1ef12ce2 + pristine_git_object: 5ca85a603e9526f6e3ec0f6100f85c164c611874 docs/models/preview-update-redirect-mode.md: id: fe04ef2c1f3c last_write_checksum: sha1:d13c5367cd6b1855e85e7387f02004fb776ad153 @@ -2160,8 +2240,8 @@ trackedFiles: pristine_git_object: 0765a516dacc6291b302c98a17bd62753c075619 docs/models/preview-update-response.md: id: 8106134ab3a8 - last_write_checksum: sha1:f73bce7805f9b8ffba02d77795afed780d69e0bd - pristine_git_object: d8648dc94f571a8469c916e9336c1c638552a50e + last_write_checksum: sha1:bd5cf16e816920435e2ab4b0865abf04dbcaf164 + pristine_git_object: a5409878ae000c600310db7b05dcdaf12feb013f docs/models/preview-update-rollover.md: id: fd27620d33af last_write_checksum: sha1:c02354fc996937d2d71acbf4c6938a20089ce1f1 @@ -2196,12 +2276,12 @@ trackedFiles: pristine_git_object: 71aafeb419a55dced06ff025e7aa4ed9af46b812 docs/models/product-scenario.md: id: 53b34e452304 - last_write_checksum: sha1:38c04a7b7c9721934c6b5ad8b0e4f6a286b5e3b1 - pristine_git_object: 2bab4761cb499c25cd0d8edbf482160df0c42c58 + last_write_checksum: sha1:1b89a6c5aca71e11bc1c602eb29f5d7a5d62cdd8 + pristine_git_object: d7854faec6b4d21eab3873c1bfedc4c321695195 docs/models/product-type.md: id: 739b492c48c8 - last_write_checksum: sha1:b16bb5e2b258d3eabb0213f6dd24c5b36a5fc581 - pristine_git_object: 42b3d7af1ce89e608a6c6c41c65098305b5ac826 + last_write_checksum: sha1:deb88681ef554ce1be6e025796ed1b69fdac692b + pristine_git_object: 3545a7deb0f2c9974c512988e31f2b5e6e2d038c docs/models/product.md: id: c91436bbe13a last_write_checksum: sha1:4f32659bdbdd6cc02f2e3664709c4ff969def976 @@ -2236,20 +2316,20 @@ trackedFiles: pristine_git_object: 6133ec7c2af5271b41ce09dddfb0eb8cbeb14418 docs/models/rewards-type.md: id: c48adeacd4fc - last_write_checksum: sha1:27496e9a4a8de62630ebfc6ed7f0a39dd2e3845b - pristine_git_object: 316e1ae6d5e72783cd07bfbdea163f2f7db54806 + last_write_checksum: sha1:fc8c460d22c515495d54385f2b0ea1f045605e26 + pristine_git_object: ca2e4f7e35d62a3bfc3658e8c3e20dbdc6e0ed70 docs/models/rewards.md: id: 4551c882db3e last_write_checksum: sha1:400f48d09c30265fc4650ca42db90109dfdda599 pristine_git_object: 08b89a9cc150d2d174408e0ccb7d2eea9b8e4014 docs/models/rollover-duration.md: id: 2d83c1287827 - last_write_checksum: sha1:b280c07fab2d26e111a692faf91a391869e92f11 - pristine_git_object: c23b8dcea93beed758447fb48b614298922aadf0 + last_write_checksum: sha1:6e5d3704ee11b7ed69c26f2ac40524dba5f3817f + pristine_git_object: 4f9293c3e3617e496703fb7dc28a6947b8b03ff0 docs/models/scenario.md: id: e3aad8ab5efa - last_write_checksum: sha1:092442eb1ef3d6258528e50ee796c1f2dc6ccdeb - pristine_git_object: d237cbd24dcea87d28d5fe57feeeda9244676f66 + last_write_checksum: sha1:dea955e2e6537c03af820669075ace61a6d283be + pristine_git_object: 9d59212541bcf67d5332b474aaa48085a4be19a5 docs/models/security.md: id: 452e4d4eb67a last_write_checksum: sha1:d2af82412a97b139d12d416d11a235638001243b @@ -2424,12 +2504,12 @@ trackedFiles: pristine_git_object: e90fd7ed6b459e1a9cad0d55b8adacc0caf28633 docs/models/update-customer-billing-controls-request.md: id: c32b379ebbc0 - last_write_checksum: sha1:0a140aa486a66a84b04bb77702b3c0b4a3be3fec - pristine_git_object: 1d4ac04e095f14f853adb7335a5eee1d6574af5e + last_write_checksum: sha1:dd80c67321ab61038e8488ad4d84273b30826ddb + pristine_git_object: 53c53146a39333eb96825a6e7a96540d088839e5 docs/models/update-customer-billing-controls-response.md: id: 8f1c813a9ca8 - last_write_checksum: sha1:b24638d3ddd1c532a2a38d0ddf070967bf5ef384 - pristine_git_object: 7699dc8d73683b45f383e3b7333681dfbec5301f + last_write_checksum: sha1:531b246b24c390487d12171d7ccca188f991352c + pristine_git_object: 3e7ba07698b275c053690ed4e6cf7d8fd7e45bc3 docs/models/update-customer-credit-schema.md: id: 3cf3ff338501 last_write_checksum: sha1:f9961157a387d1c5befbbb9efa9169d0912eee4f @@ -2440,8 +2520,8 @@ trackedFiles: pristine_git_object: 5844674b03a3affec2c2537f244e462ffe9437cd docs/models/update-customer-env.md: id: d418dfa14402 - last_write_checksum: sha1:bad1f5982c944a85cc03a4f42cd4c133926e9ac5 - pristine_git_object: 49b1e0d4fa22077061818565a4c51e8516e63087 + last_write_checksum: sha1:d325228f92f006cadbaa962906f743d8ba5e0a1e + pristine_git_object: 43114cf33fd88602a5997e6575e4a30af88001e8 docs/models/update-customer-feature.md: id: 168e1b65d4aa last_write_checksum: sha1:138fd6e774ad7c62ea6f214715b6f723ff26860b @@ -2460,8 +2540,8 @@ trackedFiles: pristine_git_object: e44fe97352c3cda9c0b20cddbca6c5b6139d6a1b docs/models/update-customer-interval-response.md: id: a9d0d34e312f - last_write_checksum: sha1:28df18fdbce1e098643e8ab5ef8be5ab1a0a6911 - pristine_git_object: 45a09bc6f17d2c578073316310a1634ec289bbb7 + last_write_checksum: sha1:c47d9f13238533be2d23995e16b03cd01d6f9a3c + pristine_git_object: fe6c9a746987de0bf0fb25e908e562865e99ed3b docs/models/update-customer-params.md: id: b0eaa77673a7 last_write_checksum: sha1:819c5567450b6fe64775b29b0af21e41626c1852 @@ -2492,24 +2572,40 @@ trackedFiles: pristine_git_object: 7fec85c333456100c9d53f880df4d93bf74ce9a0 docs/models/update-customer-status.md: id: 37adfd15b5dc - last_write_checksum: sha1:c1d49cd41fc2323c5e7b22807963efa958f9a4f9 - pristine_git_object: 3effcadf96576c9a9918ff1ec7329d28cede6dcc + last_write_checksum: sha1:ccf057de69e42a6f304fae96cce81b4829a5c931 + pristine_git_object: 666616765c3b7e7b81855d3d055c6c497b157973 docs/models/update-customer-subscription.md: id: "412049526229" last_write_checksum: sha1:14b670d3f09bd42b9288c24e8ddc440b5e2692ae pristine_git_object: 61190d55755f7d4d25d433defd47bc3ed6a0b3a4 + docs/models/update-customer-threshold-type-request-body.md: + id: c38d53770bd0 + last_write_checksum: sha1:cf290b4b827ef73b9ebb30c9450c9e09fa237e37 + pristine_git_object: c49227627cc71886b1cdfc42753ba5950f0d3792 + docs/models/update-customer-threshold-type-response.md: + id: 140d164cb745 + last_write_checksum: sha1:8125ee728d535329fef313b9786cd3c5dd35b31d + pristine_git_object: bed4e9087c3e5352f2fa9d7c146daebad05621fd docs/models/update-customer-type.md: id: 875a45ee72f2 - last_write_checksum: sha1:044907040da1e827528a5a25f99df920f9ffcfbc - pristine_git_object: 83d707b139180304ae75f646872142d39330a358 + last_write_checksum: sha1:fdca10efc943fd7b923fef01c574d191771c2fa0 + pristine_git_object: 62ccf1f0cd28011a65cd6018fc2ff36321e84329 + docs/models/update-customer-usage-alert-request-body.md: + id: c4f5132a2774 + last_write_checksum: sha1:a5f472194a56dedf903b4db196cf02d9accdb2a7 + pristine_git_object: 37e958f7a497670ca6bf45ee5be4aa6c6a7aa8fa + docs/models/update-customer-usage-alert-response.md: + id: 0c424e14021b + last_write_checksum: sha1:a4b3c268d269b40e744ed8b47585cff1bfa8795f + pristine_git_object: 1d8bb52999352d17fba0f1dd014a5508f813e369 docs/models/update-entity-billing-controls-request.md: id: 9b1761390078 - last_write_checksum: sha1:e5f4ac7cd42c1701b8c2da536dcf2555f7a7acdf - pristine_git_object: 1218a68accf2a2b433d3878b214543809d77fce3 + last_write_checksum: sha1:8440aecb90ce47726eea9c1b4ebf5d052f73ccca + pristine_git_object: 808191209a3d0eeda7820f3452eb0c9e9270768e docs/models/update-entity-billing-controls-response.md: id: 293e6deae7f0 - last_write_checksum: sha1:d9df4288b6089edf6c8817292590574152613fb0 - pristine_git_object: 153262087f4bed3c8b7895c4cf276c7aa4076167 + last_write_checksum: sha1:1c659a6b41f6fa0015309788c9f2882d1ade7515 + pristine_git_object: 193d6273870de4ced9438cd6cb62c53a166bd1f8 docs/models/update-entity-credit-schema.md: id: cb9d6a715c8f last_write_checksum: sha1:8c0ce2f7b224153309c9253e02a846d9a456f232 @@ -2520,8 +2616,8 @@ trackedFiles: pristine_git_object: b7c9ab7b072af08f005d6bbd73f93b256f6b4ff3 docs/models/update-entity-env.md: id: ba8bb70ec367 - last_write_checksum: sha1:dfa25fd93c754b0f1b90869007dab9b3e4280d9b - pristine_git_object: f8515ff3068a6db2e14fdf925285e6cd588bd3f5 + last_write_checksum: sha1:ebabe20304aaf868147c89ec93b0fdf8c7410504 + pristine_git_object: 97702406e52bc0e63281c142d436d385a10f6399 docs/models/update-entity-feature.md: id: cdf0e1868d89 last_write_checksum: sha1:4ac2661631f51e41dc56ead085ba1c4f3c18a416 @@ -2560,16 +2656,32 @@ trackedFiles: pristine_git_object: bb4652db59eda761cb9de9c7c753c2d84e20a02d docs/models/update-entity-status.md: id: a123286977c4 - last_write_checksum: sha1:3b260455837c095923e54a862f811e23fc09e75e - pristine_git_object: 0a022e6eb0c5caf8ec0020f2b8778c0ac5f41cbf + last_write_checksum: sha1:2f194c547bd8c6fbb6dc0330bd195f9b3e47f753 + pristine_git_object: 1403f0344b32c4c2b3883a742d6e56444ad63420 docs/models/update-entity-subscription.md: id: 730dc25c840f last_write_checksum: sha1:137d384d2d4751c301eb6c0c09a50f4dee9a4fc9 pristine_git_object: cd975f24e8e7d76b803aeff4d46fc0c22ea780ee + docs/models/update-entity-threshold-type-request-body.md: + id: 87b1d9fc5d5d + last_write_checksum: sha1:2425222f4e2a9ff441ef3ef7b9021ad6bed46066 + pristine_git_object: 579429d97deafbc24575385a1b05ea1b52240ef3 + docs/models/update-entity-threshold-type-response.md: + id: d6e1ad6934ce + last_write_checksum: sha1:bbd117bc25653a26b4b5d4be1e673c225ae554e6 + pristine_git_object: 86a4a04ad98f7da4354b599f0e06b8879e180459 docs/models/update-entity-type.md: id: 394dfb877cb7 - last_write_checksum: sha1:6a66ba39192c4124f1d88a4002968a1375057eff - pristine_git_object: d978e0a8bc80c75a43521c2d1ce78d0a11132270 + last_write_checksum: sha1:da5bfb334d71880215ba0eb97bbc1423017568a7 + pristine_git_object: ab98d85bab5f617228a12b1cb88bc7abe4bff902 + docs/models/update-entity-usage-alert-request-body.md: + id: 327b3aeb824e + last_write_checksum: sha1:d6701450fc5e8be33295725bc01b79a1af1577c2 + pristine_git_object: c1d0410988665ee5b445548cf904f36f29d2ff31 + docs/models/update-entity-usage-alert-response.md: + id: f176e3c4b1f2 + last_write_checksum: sha1:9b82bb47d5f5283a9e04a545c24718158e4790ba + pristine_git_object: 02c8d82fdd25dfcd57462f0ec958617109fa8795 docs/models/update-feature-credit-schema-request.md: id: a82e108a3756 last_write_checksum: sha1:9aeca0b0271a2657e571cda1a2182ba633d8efff @@ -2604,12 +2716,12 @@ trackedFiles: pristine_git_object: 011cd5876e919cdf84167f388a8e576b2ff96e50 docs/models/update-feature-type-response.md: id: 55ef8f61ed28 - last_write_checksum: sha1:36bc60e36ec75ab72b26645751fe8e4a02437053 - pristine_git_object: 8feb59b6f2386611f2db04d66bf8d95202e1d9ec + last_write_checksum: sha1:8edc60f47c6feaabb96b01479306ce762c3b863c + pristine_git_object: e537c89a174c185a0833eb63be1e07d8a0558325 docs/models/update-plan-attach-action.md: id: 3f596f5740b1 - last_write_checksum: sha1:02f0e4cb31d8b2cd6ba5d6a38b16d10dcada44fb - pristine_git_object: e67655ce96d6c0b48a0a6930027a0394b816136d + last_write_checksum: sha1:e58f8b39293307e6bb75b35e03d6cf3a459d7c2c + pristine_git_object: 073fd9c8dd01dbda27bef5f28da8ec408764c889 docs/models/update-plan-base-price.md: id: 7f764af15f7d last_write_checksum: sha1:342436cc671fbfa0fa02779f5635f2ae28804626 @@ -2620,8 +2732,8 @@ trackedFiles: pristine_git_object: 3fcfc1ffd0e051ca7d6267202af8ac6756a48f0e docs/models/update-plan-billing-method-response.md: id: ddca1b594754 - last_write_checksum: sha1:684b8ac067ff95bd19c8252fed27767389012afc - pristine_git_object: 2f38389e4cc43531f126c82a08713edf787e877f + last_write_checksum: sha1:045532224fb1a560ae04aa85cfbc175a5208ca9e + pristine_git_object: 1c3d7ae7c5e8f54333c14c3e480eefdd7b4b1ebf docs/models/update-plan-credit-schema.md: id: acaf39d42386 last_write_checksum: sha1:af3af2720a587f377efbf14df3e586cc376ead26 @@ -2636,20 +2748,20 @@ trackedFiles: pristine_git_object: 823ca3a08fbfe410bcc170abba6a9fb1a26aa848 docs/models/update-plan-duration-type-response.md: id: 7e8e1a2d27c1 - last_write_checksum: sha1:45fa868e2ea230807bb93b96cf1d1d4d091db40a - pristine_git_object: e2aad42fd702d3b0a19fb4b3766dd26f60f20891 + last_write_checksum: sha1:ed21c15df2b5c41affc78e28440b4e3051f7e0a2 + pristine_git_object: 1a60b6ee9910560a58e9dc1ee2413465b6f0b724 docs/models/update-plan-env.md: id: 1ec7258b0baa - last_write_checksum: sha1:d4594b9ca68ab42976728a90051e63158147be0b - pristine_git_object: 1a9287acd4e08b4512cfbcdb04682ba80b280089 + last_write_checksum: sha1:5c914a9bfde14e77725e1f7fd80b55c4435ba9b9 + pristine_git_object: 3027bd5dd67aadcabafbd0ebcb694f654fa9a143 docs/models/update-plan-expiry-duration-type-request.md: id: 9deda139c872 last_write_checksum: sha1:ed51270204f6b3b01d4d4f4fc2069debfdddec88 pristine_git_object: 89747b93d89370fa39a0b3a802c255401ab17567 docs/models/update-plan-expiry-duration-type-response.md: id: 4f1456745f6b - last_write_checksum: sha1:804c08642b3c40af78c8f534239f6ec353381ad0 - pristine_git_object: 0d2036c1b49a9dfd90cdc7c10c4770eada3581a3 + last_write_checksum: sha1:037ea11512c88eab6c9db6733344a4a99edbb3ff + pristine_git_object: d886a3142cb7db7666f94de89ad811a3be1a66fa docs/models/update-plan-feature-display.md: id: 60e529fe4eec last_write_checksum: sha1:bcb11546dcfc1e87c3b7e2c99e158441a6da6ac7 @@ -2712,12 +2824,12 @@ trackedFiles: pristine_git_object: 308fdd7c25468a6dd81b07ed46391d1a9bdc0113 docs/models/update-plan-price-interval-response.md: id: 895a33399c7b - last_write_checksum: sha1:cc3a352b3f4c6a155eab5c20297a4d9f423d0d43 - pristine_git_object: e2b7b2f28422ed55186e1d38418b1054e8362b19 + last_write_checksum: sha1:bc84d3d69ff743ef119f7752e6256f3aa01c5cb4 + pristine_git_object: 1bbe591e12e17abd1e6d439f725515c2ad30d4b9 docs/models/update-plan-price-item-interval-response.md: id: e909a35141c8 - last_write_checksum: sha1:ef54f93e6dd1c247b2fd91615e01655f5d090c8d - pristine_git_object: 82e7a008247cf0745ee12616656dc0fc885b482c + last_write_checksum: sha1:cb7187b76af4aaebc38bef1bddef721ca8ec85f8 + pristine_git_object: e3ffa074588d8dc4cc5ce76cbb57b0adcb537228 docs/models/update-plan-price-request.md: id: 4602b3ebb686 last_write_checksum: sha1:4a7faf35e7d8382ee50e8cde87cf15cfc034fe5c @@ -2736,8 +2848,8 @@ trackedFiles: pristine_git_object: d30dc71cbb6362b2817893a7b9d85f600b3fe704 docs/models/update-plan-reset-interval-response.md: id: e04031025a69 - last_write_checksum: sha1:7cf89cfb935aa10335fd3e731b1510b0cb7b124a - pristine_git_object: 39bb94ebcc183905b3d84961f59a6ffe16ef8221 + last_write_checksum: sha1:39f5bdcb899e1855e84edef3ce03c619a7ef8b40 + pristine_git_object: d89b60eb37801f8fa2a3f4653e65c0ef3d356d13 docs/models/update-plan-reset-request.md: id: cc5ffaf44e69 last_write_checksum: sha1:7b5494303638691323b06a24345154f1922c09ae @@ -2760,16 +2872,16 @@ trackedFiles: pristine_git_object: 8bad9b30e3d3445904a7deab4bd769f28a412f44 docs/models/update-plan-status.md: id: f2d8e8969aac - last_write_checksum: sha1:0c7f9b87be7ec7992c7a7cfae8889af100c4b5b2 - pristine_git_object: d8f5473b55509af4d6b3ca9a5100516c32944f61 + last_write_checksum: sha1:1282e2a189f6086805af184a94e387a7daa61dcc + pristine_git_object: f03621514664842542256ec0b1d280a238d72cbd docs/models/update-plan-tier-behavior-request.md: id: 8ce61fb8637e last_write_checksum: sha1:b9e837d1016b53e5ba973bdb3aec0f63a3cd7bc0 pristine_git_object: b027e08b063fed9b87885cae46a9fa282124596c docs/models/update-plan-tier-behavior-response.md: id: 4da31d438a94 - last_write_checksum: sha1:319738e80d8e1648e746fd5b41fde23412eb6a1e - pristine_git_object: 1c7755baaca987e11d366427182be05949c8fbc7 + last_write_checksum: sha1:1db3f4e8189db73c50db0299bb5dca95165f57c7 + pristine_git_object: cd0aa9bf04621edd356628caa97a8c3bcad8395a docs/models/update-plan-tier.md: id: 0cac01f522a2 last_write_checksum: sha1:65a9e826becab3da5c24fef7fbf915992df4dd01 @@ -2780,16 +2892,16 @@ trackedFiles: pristine_git_object: af6af1c81c983d8a50d21b44329a3aa0bd24ebed docs/models/update-plan-type.md: id: 5cfd33c31fa4 - last_write_checksum: sha1:e6925622d28aadf7dda81743c075f806a1889b3e - pristine_git_object: ef8461bb5f5b6dde98c8f325bb176effbe346b88 + last_write_checksum: sha1:dbe46f3341404b4f4da84312247a83a410f26129 + pristine_git_object: 286ef6a9dc6cf9cb52cedb2b6ffb75be463d1d81 docs/models/update-subscription-params.md: id: 2f1abbd42a8a - last_write_checksum: sha1:a9dd736840a5111ffe367a5ffeaee8495e074ad8 - pristine_git_object: bcc2607ea2c7c6d50c1ff2283767fd44af9cebf0 + last_write_checksum: sha1:8d3dec0da8e950d8b884e0c003c48c3bcd104978 + pristine_git_object: 96e2b759e232fb9fa2c603098e6bbc6a72272f91 docs/models/usage-model.md: id: 32a269601e79 - last_write_checksum: sha1:faa6fbdacaf3e836fef0c74a2430790ed5181d55 - pristine_git_object: 14952a4ee67b77ab09f4697e1767649ea412d2d5 + last_write_checksum: sha1:c8bfcbed266005cbcc6114bfb969c2d90d028d1c + pristine_git_object: 56e566eba7aeffa9422da7c6b4bcb80a123e5f14 docs/sdks/autumn/README.md: id: d27c9292a1a3 last_write_checksum: sha1:8b3c26a9a0202d01d704f782172e06caef3a9b64 @@ -2800,8 +2912,8 @@ trackedFiles: pristine_git_object: a366694c3e2f4df91e7ae37aa212d8f07cb83c40 docs/sdks/billing/README.md: id: dc915331dd9d - last_write_checksum: sha1:53dfd365ec6177a94b1406953b4632ad45e556ff - pristine_git_object: 5620ab958f6bd99e45cc350d99bf7c53b461a27f + last_write_checksum: sha1:e7ceda34964ab16d3b58cdcdad503eac1d549a60 + pristine_git_object: d94ecd720f2708a966fb68b01f36fb4cac4a2617 docs/sdks/customers/README.md: id: 9332759cffc2 last_write_checksum: sha1:1eb602635426550359b47163b6f402b6c7b959df @@ -2852,8 +2964,8 @@ trackedFiles: pristine_git_object: 397d986f1533891eddd2b39bf57e502c5d71613a package.json: id: 7030d0b2f71b - last_write_checksum: sha1:c0059fecd0464a94b545d4e9ce4ce57acfd5b151 - pristine_git_object: 0762dd7e393759664d238185cfa34215f13933ef + last_write_checksum: sha1:ccce7e66c9bb241f74bee50fac536d72da80c2f9 + pristine_git_object: cea8a792bbaf1e6c7e05c026273b04c6576f2441 src/core.ts: id: f431fdbcd144 last_write_checksum: sha1:f8f24a3ca09c1efb285d7a75ad3697d0128f47e2 @@ -2896,16 +3008,16 @@ trackedFiles: pristine_git_object: 104a2ea5718c4d0cca3ff3e50f762a2225208b05 src/funcs/billing-preview-update.ts: id: cd3a375787c5 - last_write_checksum: sha1:4f523857caf820f20b7abcc091ce321f55cd0da9 - pristine_git_object: bcbdaddd77b806a1169bf489ef1ed6b77fcea92f + last_write_checksum: sha1:2a22d8b6fe3f2ccd268546dfc6cca878c1e2c1d1 + pristine_git_object: 69d04d5f49f6199719abbd207cccb9a24a27f37a src/funcs/billing-setup-payment.ts: id: 4d2d8096862d last_write_checksum: sha1:8104b79ac9e2922b97ae923454d0e41a24dd9d8f pristine_git_object: e30ea0c1e60bcfce426ff277ce40ed8ef3e77adb src/funcs/billing-update.ts: id: 5c14ddfe1de0 - last_write_checksum: sha1:839ea39066913d0f4134876046d33fe10db2ce27 - pristine_git_object: c7c08f719274c305f96206868b9101704b285b51 + last_write_checksum: sha1:32facdab8b2196ba0ab1a4fe17ae58d4149b43f1 + pristine_git_object: 43bceea02eca1fd4b70b344177986d427e87089e src/funcs/check.ts: id: e962b1e3321b last_write_checksum: sha1:88705e19bfe4ef3397cc66b815ec842590111be0 @@ -3024,8 +3136,8 @@ trackedFiles: pristine_git_object: 44be0eae8246521b230e8e711a88eff738fc015d src/lib/config.ts: id: 320761608fb3 - last_write_checksum: sha1:eb7590ff72d3784a45a7bdc106f510ea9d55fd83 - pristine_git_object: ef0ca20614889d20c6e6b15c538847eb1f768792 + last_write_checksum: sha1:ddc74e2d374d3fe2ee1e8a47b0c762259c05c96f + pristine_git_object: 468ec0db08775aac0b972b73beb5edce16b9a6f5 src/lib/dlv.ts: id: b1988214835a last_write_checksum: sha1:1dd3e3fbb4550c4bf31f5ef997faff355d6f3250 @@ -3040,8 +3152,8 @@ trackedFiles: pristine_git_object: 6439826c5dcc6f5b21cad742cb1b24951d912a6a src/lib/files.ts: id: e5efa54fcb95 - last_write_checksum: sha1:795c14026405d547bfc47012f7ad9666e530fa7f - pristine_git_object: 6ca6b37d35a12448da176ee2517cc036db12c81c + last_write_checksum: sha1:d0f325f445b8d22e7d73baf052c585ec2dd24841 + pristine_git_object: 0344cd046d033f9e8a55de02f7935c5cec5dc30b src/lib/http.ts: id: 63a80782d37e last_write_checksum: sha1:797cbf16d3c7c4d62d3ba0eedb08617524938457 @@ -3056,8 +3168,8 @@ trackedFiles: pristine_git_object: d181f2937d4128afbe9b0327e0f81d1fa9c877b7 src/lib/matchers.ts: id: d54b2253b719 - last_write_checksum: sha1:5338bf281b49894fea64a93d18c207afec547959 - pristine_git_object: 9a72b3fe2b6b7f39be7c7283f85c36b9c874021e + last_write_checksum: sha1:fd1a4f9ab108d1fbc597b60e529ce5144c0982f5 + pristine_git_object: 2f22acee9666d9c16532376b0897cd00608a608b src/lib/primitives.ts: id: 74859f750b28 last_write_checksum: sha1:987869fc54790b9c22e9182099103d6aa7c67016 @@ -3076,8 +3188,8 @@ trackedFiles: pristine_git_object: a39f7e35308f9b6aa4bd787c9cd5dbfd0630064e src/lib/security.ts: id: 0502afa7922e - last_write_checksum: sha1:292e4f6785c5d8ac82a00a5ab7cca593162b70d1 - pristine_git_object: ee8dd58612b10b6e2b5cd17266af7496e611cdaa + last_write_checksum: sha1:2a17865cac9bf5b9703c4dcb294e6e1dcc2c018f + pristine_git_object: 659b39acbbbaa57b369984bf6cd97e1867573501 src/lib/url.ts: id: b0057e24ed76 last_write_checksum: sha1:d124050c7e755c0cce233b9e029afb584ff65201 @@ -3104,8 +3216,8 @@ trackedFiles: pristine_git_object: 0a1fa37762bc3d687bf5305bff7ec1e429e09a94 src/models/billing-update-op.ts: id: e7371769c7ca - last_write_checksum: sha1:4a65baa7b9d0e495c629a320813d59a9a9a928ce - pristine_git_object: 055c273ee0653391ad0e5905e2642bc4a4b17e9a + last_write_checksum: sha1:c290454f78154046bb4805327762a572a61eac13 + pristine_git_object: 32ffe830bae55e19f004738fbf46c94c545ce519 src/models/check-op.ts: id: 42085bda016a last_write_checksum: sha1:29c31308dde34633123443a1c0b206bc2af7cb38 @@ -3116,8 +3228,8 @@ trackedFiles: pristine_git_object: e29ec4d1c6b55865e72c8a2d415bdf19a9b2a8ed src/models/create-entity-op.ts: id: 9ad8367048a1 - last_write_checksum: sha1:fa1a4d327132c3407269e1b0d7c812f5ca77f965 - pristine_git_object: 3e065c21a00783dafd92227d253ef6075af5cbb3 + last_write_checksum: sha1:9fed6cb8c773a6d29dd7e906fb75c7b9d73ce065 + pristine_git_object: 44f5f23e693ed618765cfb59ca83dbbd978b09ef src/models/create-feature-op.ts: id: 06f0161d677b last_write_checksum: sha1:2343ab517f362b3eaaa65e9039cec647ac497111 @@ -3132,12 +3244,12 @@ trackedFiles: pristine_git_object: d979198ac227f8e5731e5ca5e2e34b55d88da348 src/models/customer-data.ts: id: 04dac7ee392e - last_write_checksum: sha1:55cdeb7dbfa50ff55b2394c24c0fc381fcb3483a - pristine_git_object: d519831f23c59f39560262cfd7fddafc297f6d62 + last_write_checksum: sha1:a2b386eb741d2913ac5cc222cf59e7887e1ecb7f + pristine_git_object: 06b6401180e19e3a95b59719948b00ae24bb65ea src/models/customer.ts: id: 20be78c552a4 - last_write_checksum: sha1:438af099cd020e8ca54e91bf11291f0b2ed5ac90 - pristine_git_object: 4d0e407238a5b0c23602450456d7157caf32142f + last_write_checksum: sha1:5add38a9938c0570d84972ab059c6157da1740ff + pristine_git_object: 0196844d6cca018f17d138035e2935beb4e5066a src/models/delete-balance-op.ts: id: ea84d6bda9c3 last_write_checksum: sha1:e592136c1840f2dff9a17d7ed4dc1b6e6bd38f0a @@ -3164,16 +3276,16 @@ trackedFiles: pristine_git_object: e32f582176649899148ca6afba2175c75dc7abdf src/models/get-entity-op.ts: id: 7932a3cea5c1 - last_write_checksum: sha1:420b4e34b466d99847b368614323ce09803e265b - pristine_git_object: 5eba1e01d9a4aabc1ab842ebec97d9fe3d7881d3 + last_write_checksum: sha1:7acc5336f1e1186d55c7967d3c4c995127658d49 + pristine_git_object: ce36a7c97239a9091d3cf4c6b8b718f77d3bdd78 src/models/get-feature-op.ts: id: a820efa3e08d last_write_checksum: sha1:e42d99dba37a2380e1e9ed4afe9b69460598f578 pristine_git_object: 2dab76561c71950e9622b079172e1d0dc339b081 src/models/get-or-create-customer-op.ts: id: 46f8f65a57f2 - last_write_checksum: sha1:35772dd4e5d6f979cfafce29961835483fe904b4 - pristine_git_object: 0d7c5de1ab2264df40705413807685f918367411 + last_write_checksum: sha1:fa54d8e17df6eabe05199184af93ad454c10b55d + pristine_git_object: 67fd8b56b02d968c71df3ad700096be69a25a660 src/models/get-plan-op.ts: id: 91c8f8dda7c8 last_write_checksum: sha1:4ce23c219fc779e598370b220970c90ade2b12f9 @@ -3188,8 +3300,8 @@ trackedFiles: pristine_git_object: 4a4d15fbe91ea4e8d6b053f6b2874f2bb272ee08 src/models/list-customers-op.ts: id: b391692c8429 - last_write_checksum: sha1:257bc3828af7ab5186e9a936ddf7c986ea24b295 - pristine_git_object: ffe79c5317c42623b35792a1466c59fbdc82c2e3 + last_write_checksum: sha1:6e1bcb810bdaf31f92f8dfdb595bd1d349da788e + pristine_git_object: 7c17614447ca43360529b04bf94d6afaa401a1ea src/models/list-events-op.ts: id: 82a9f364bb21 last_write_checksum: sha1:2d409806ca68c98d4a9a5a1031d591f831065c75 @@ -3204,8 +3316,8 @@ trackedFiles: pristine_git_object: 14e70100aa956ccbb2cf296781e15d67dd1a9b6e src/models/multi-attach-op.ts: id: 99a2b77c1afc - last_write_checksum: sha1:1aeeda38d2ef8b43ac2f10f4891690dacc26ac1b - pristine_git_object: 637e66fa77050607a8775dbecd168952835f9819 + last_write_checksum: sha1:7a766c1c932de94611cc82560cecc9e4d0a376c8 + pristine_git_object: e7b0525505667e0d599f5cf08e3154e895b5a550 src/models/open-customer-portal-op.ts: id: a003eb4172a9 last_write_checksum: sha1:5e672fc975a0336c963181042a770c2a43cbc0e3 @@ -3216,16 +3328,16 @@ trackedFiles: pristine_git_object: 57c2119234cc30673a067a26c8ccca1244b2295f src/models/preview-attach-op.ts: id: 3efc6e3443a7 - last_write_checksum: sha1:9d0abed14a2ba8a527da4bce44a3b5edd3f20170 - pristine_git_object: f0a16ec5a87e519b5a56688a9b7d6239a3f683ba + last_write_checksum: sha1:593828c02419a43568b504304fd85ef55c2a5843 + pristine_git_object: 69b603db9c6b7dcafcc1431820c3cc09bd104313 src/models/preview-multi-attach-op.ts: id: e4847dc281a6 - last_write_checksum: sha1:e2b710a11a6963850e08dc85d9aa42a3f2fc2490 - pristine_git_object: 84255104a8b9452190671556d90d1e2cf7278b60 + last_write_checksum: sha1:b81fa93c90e11a02ee71acda6542c262cca0d5c2 + pristine_git_object: 16920a58e0f56d9b268851b14404aade061dfcf3 src/models/preview-update-op.ts: id: fcbbbf3b22ac - last_write_checksum: sha1:a9c0fc7fd86a990a86ca061cc547693d29b3da51 - pristine_git_object: bc3526adf2fa788b7b4030b6f2d7ceed238e115d + last_write_checksum: sha1:76069c26da18000a06ea93d18c265637ed2c87a9 + pristine_git_object: c6884ba5fbac5c488e525042acf0b5285eddd16b src/models/redeem-referral-code-op.ts: id: 511bf73dc4c6 last_write_checksum: sha1:9ab6622018c82175ea98d2b26eadb4abf08f441a @@ -3256,12 +3368,12 @@ trackedFiles: pristine_git_object: bfa2a0d29be530ccbf883a563399b35712623642 src/models/update-customer-op.ts: id: 5d226d30d8e4 - last_write_checksum: sha1:b5b6a0cd4a88537dba83fcd16b27700cafa25c83 - pristine_git_object: bcd66af95d7eb16e9445ea8d2dc9840a61eed206 + last_write_checksum: sha1:4cd61e0c3a7dd54edeba51950baac22544ee1ae9 + pristine_git_object: 64d04d0eea23580ec5efa63c961ea60396017788 src/models/update-entity-op.ts: id: c3fdb6479f02 - last_write_checksum: sha1:4d32ffe520a8bd2395e75ab26387b940b16c8ceb - pristine_git_object: 1761c6366d436d2ea58db62a41bb1f12d5285346 + last_write_checksum: sha1:c2721d95e8f452174a3b8e029eca28613d6070a0 + pristine_git_object: a3974d0fbcfc23bb2df016b3ade6941a0a4b4565 src/models/update-feature-op.ts: id: 7c27d245784e last_write_checksum: sha1:fca4d29e843ff678c6f85258ef40668a46da5e42 @@ -3276,8 +3388,8 @@ trackedFiles: pristine_git_object: 571de419ea3321d79acec4bddbb46b1580007115 src/sdk/billing.ts: id: 10905058c4ad - last_write_checksum: sha1:8bc56dcf1da206ef7e88fb5316e02f71cb37247c - pristine_git_object: 28e980d78d03b1e3eb5943baea72517a1ced0855 + last_write_checksum: sha1:6de4f6f49f746b15fde5f6f0ef89f5442e24487e + pristine_git_object: 7891ff9bce4d17d0fa8675226b696670ab50f39e src/sdk/customers.ts: id: d33e193e0c00 last_write_checksum: sha1:d7bd2dbe3435c37f2abad38c59c64b725a2dac4b @@ -3364,8 +3476,8 @@ trackedFiles: pristine_git_object: b7a2a13f3dff50663429df24ae2f55b647ff1084 tsconfig.json: id: 61ebb9fd6e8c - last_write_checksum: sha1:79dc1550d921fefec69f8632ed3b24dad41ca2f6 - pristine_git_object: 76110f883cac40bb04fb2f376cd69ea8c8d6d215 + last_write_checksum: sha1:c3ec7996536cdb9a54319e7d1eb3b199b733d34c + pristine_git_object: 0ccdbe286a8780e06a469a9eb7e2fb95322fd507 examples: get_/plans: speakeasy-default-get-/plans: @@ -4115,7 +4227,7 @@ examples: application/json: {"customer_id": "cus_123", "plans": [{"plan_id": "pro_plan"}, {"plan_id": "addon_seats", "feature_quantities": [{"feature_id": "seats", "quantity": 5}]}], "redirect_mode": "if_required"} responses: "200": - application/json: {"customer_id": "", "line_items": [{"display_name": "Percival_Towne81", "description": "as unfortunately wherever crest", "subtotal": 1273.44, "total": 7630.04, "plan_id": "", "feature_id": null, "quantity": 1062.24}], "subtotal": 20, "total": 20, "currency": "usd", "incoming": [{"plan_id": "", "feature_quantities": [], "effective_at": 1983.1}], "outgoing": []} + application/json: {"customer_id": "", "line_items": [{"display_name": "Percival_Towne81", "description": "as unfortunately wherever crest", "subtotal": 1273.44, "total": 7630.04, "plan_id": "", "feature_id": null, "quantity": 1062.24}], "subtotal": 20, "total": 20, "currency": "usd", "incoming": [{"plan_id": "", "feature_quantities": [], "effective_at": 1983.1, "canceled_at": 2257.08, "expires_at": 7910.67}], "outgoing": []} multiAttach: speakeasy-default-multi-attach: parameters: diff --git a/packages/sdk/.speakeasy/out.openapi.yaml b/packages/sdk/.speakeasy/out.openapi.yaml index a9be56129..3c55826f5 100644 --- a/packages/sdk/.speakeasy/out.openapi.yaml +++ b/packages/sdk/.speakeasy/out.openapi.yaml @@ -84,6 +84,7 @@ components: - day - week - month + type: string description: The time interval for the purchase limit window. interval_count: type: number @@ -120,6 +121,35 @@ components: minimum: 0 description: Maximum allowed overage spend for the target feature. description: List of overage spend limits per feature. + usage_alerts: + type: array + items: + type: object + properties: + feature_id: + type: string + description: The feature ID this alert applies to. If omitted, the alert applies globally. + enabled: + type: boolean + default: true + description: Whether this usage alert is enabled. + threshold: + type: number + minimum: 0 + description: The threshold value that triggers the alert. For usage, this is an absolute count. For usage_percentage, this is a percentage (0-100). + threshold_type: + enum: + - usage + - usage_percentage + type: string + description: Whether the threshold is an absolute usage count or a percentage of the usage allowance. + name: + type: string + description: Optional user-defined label to distinguish multiple alerts on the same feature. + required: + - threshold + - threshold_type + description: List of usage alert configurations per feature. description: Billing controls for the customer (auto top-ups, etc.) title: CustomerData description: Customer details to set when creating a customer @@ -158,6 +188,7 @@ components: enum: - sandbox - live + type: string description: The environment this customer was created in. metadata: type: object @@ -199,6 +230,7 @@ components: - day - week - month + type: string description: The time interval for the purchase limit window. interval_count: type: number @@ -235,6 +267,35 @@ components: minimum: 0 description: Maximum allowed overage spend for the target feature. description: List of overage spend limits per feature. + usage_alerts: + type: array + items: + type: object + properties: + feature_id: + type: string + description: The feature ID this alert applies to. If omitted, the alert applies globally. + enabled: + type: boolean + default: true + description: Whether this usage alert is enabled. + threshold: + type: number + minimum: 0 + description: The threshold value that triggers the alert. For usage, this is an absolute count. For usage_percentage, this is a percentage (0-100). + threshold_type: + enum: + - usage + - usage_percentage + type: string + description: Whether the threshold is an absolute usage count or a percentage of the usage allowance. + name: + type: string + description: Optional user-defined label to distinguish multiple alerts on the same feature. + required: + - threshold + - threshold_type + description: List of usage alert configurations per feature. description: Billing controls for the customer (auto top-ups, etc.) subscriptions: type: array @@ -260,6 +321,7 @@ components: enum: - active - scheduled + type: string description: Current status of the subscription. past_due: type: boolean @@ -382,6 +444,7 @@ components: - boolean - metered - credit_system + type: string description: "Feature type: 'boolean' for on/off access, 'metered' for usage-tracked features, 'credit_system' for unified credit pools." consumable: type: boolean @@ -511,6 +574,7 @@ components: enum: - sandbox - live + type: string description: The environment (sandbox/live) required: - id @@ -556,6 +620,7 @@ components: - fixed_discount - free_product - invoice_credits + type: string description: The type of reward discount_value: type: number @@ -565,6 +630,7 @@ components: - one_off - months - forever + type: string description: How long the discount lasts duration_value: anyOf: @@ -757,6 +823,7 @@ components: - quarter - semi_annual - year + type: string description: Billing interval (e.g. 'month', 'year'). interval_count: type: number @@ -804,6 +871,7 @@ components: - single_use - continuous_use - credit_system + type: string description: The type of the feature display: anyOf: @@ -867,6 +935,7 @@ components: - quarter - semi_annual - year + type: string description: The interval at which the feature balance resets (e.g. 'month', 'year'). For consumable features, usage resets to 0 and included units are restored. interval_count: type: number @@ -893,6 +962,7 @@ components: enum: - graduated - volume + type: string interval: enum: - one_off @@ -901,6 +971,7 @@ components: - quarter - semi_annual - year + type: string description: Billing interval for this price. For consumable features, should match reset.interval. interval_count: type: number @@ -912,6 +983,7 @@ components: enum: - prepaid - usage_based + type: string description: "'prepaid' for features like seats where customers pay upfront, 'usage_based' for pay-as-you-go after included usage." max_purchase: anyOf: @@ -949,6 +1021,7 @@ components: enum: - month - forever + type: string description: When rolled over units expire. expiry_duration_length: type: number @@ -975,6 +1048,7 @@ components: - day - month - year + type: string description: Unit of time for the trial duration ('day', 'month', 'year'). card_required: type: boolean @@ -991,6 +1065,7 @@ components: enum: - sandbox - live + type: string description: Environment this plan belongs to ('sandbox' or 'live'). archived: type: boolean @@ -1010,6 +1085,7 @@ components: enum: - active - scheduled + type: string description: The customer's current status with this plan. 'active' if attached, 'scheduled' if pending activation. canceling: type: boolean @@ -1024,6 +1100,7 @@ components: - downgrade - none - purchase + type: string description: The action that would occur if this plan were attached to the customer. required: - attach_action @@ -1061,6 +1138,7 @@ components: - boolean - metered - credit_system + type: string description: "Feature type: 'boolean' for on/off access, 'metered' for usage-tracked features, 'credit_system' for unified credit pools." consumable: type: boolean @@ -1180,6 +1258,7 @@ components: - quarter - semi_annual - year + type: string - const: multiple description: The reset interval (hour, day, week, month, etc.) or 'multiple' if combined from different intervals. interval_count: @@ -1213,6 +1292,7 @@ components: enum: - graduated - volume + type: string description: "How tiers are applied: graduated (split across bands) or volume (flat rate for the matched tier)." billing_units: type: number @@ -1221,6 +1301,7 @@ components: enum: - prepaid - usage_based + type: string description: Whether usage is prepaid or billed pay-per-use. max_purchase: anyOf: @@ -1426,6 +1507,7 @@ paths: - day - week - month + type: string description: The time interval for the purchase limit window. interval_count: type: number @@ -1462,6 +1544,35 @@ paths: minimum: 0 description: Maximum allowed overage spend for the target feature. description: List of overage spend limits per feature. + usage_alerts: + type: array + items: + type: object + properties: + feature_id: + type: string + description: The feature ID this alert applies to. If omitted, the alert applies globally. + enabled: + type: boolean + default: true + description: Whether this usage alert is enabled. + threshold: + type: number + minimum: 0 + description: The threshold value that triggers the alert. For usage, this is an absolute count. For usage_percentage, this is a percentage (0-100). + threshold_type: + enum: + - usage + - usage_percentage + type: string + description: Whether the threshold is an absolute usage count or a percentage of the usage allowance. + name: + type: string + description: Optional user-defined label to distinguish multiple alerts on the same feature. + required: + - threshold + - threshold_type + description: List of usage alert configurations per feature. description: Billing controls for the customer (auto top-ups, etc.) expand: type: array @@ -1535,6 +1646,7 @@ paths: enum: - active - scheduled + type: string description: Filter by customer product status. Defaults to active and scheduled search: type: string @@ -1588,6 +1700,7 @@ paths: enum: - sandbox - live + type: string description: The environment this customer was created in. metadata: type: object @@ -1629,6 +1742,7 @@ paths: - day - week - month + type: string description: The time interval for the purchase limit window. interval_count: type: number @@ -1665,6 +1779,35 @@ paths: minimum: 0 description: Maximum allowed overage spend for the target feature. description: List of overage spend limits per feature. + usage_alerts: + type: array + items: + type: object + properties: + feature_id: + type: string + description: The feature ID this alert applies to. If omitted, the alert applies globally. + enabled: + type: boolean + default: true + description: Whether this usage alert is enabled. + threshold: + type: number + minimum: 0 + description: The threshold value that triggers the alert. For usage, this is an absolute count. For usage_percentage, this is a percentage (0-100). + threshold_type: + enum: + - usage + - usage_percentage + type: string + description: Whether the threshold is an absolute usage count or a percentage of the usage allowance. + name: + type: string + description: Optional user-defined label to distinguish multiple alerts on the same feature. + required: + - threshold + - threshold_type + description: List of usage alert configurations per feature. description: Billing controls for the customer (auto top-ups, etc.) subscriptions: type: array @@ -1690,6 +1833,7 @@ paths: enum: - active - scheduled + type: string description: Current status of the subscription. past_due: type: boolean @@ -1812,6 +1956,7 @@ paths: - boolean - metered - credit_system + type: string description: "Feature type: 'boolean' for on/off access, 'metered' for usage-tracked features, 'credit_system' for unified credit pools." consumable: type: boolean @@ -2104,6 +2249,7 @@ paths: - day - week - month + type: string description: The time interval for the purchase limit window. interval_count: type: number @@ -2140,6 +2286,35 @@ paths: minimum: 0 description: Maximum allowed overage spend for the target feature. description: List of overage spend limits per feature. + usage_alerts: + type: array + items: + type: object + properties: + feature_id: + type: string + description: The feature ID this alert applies to. If omitted, the alert applies globally. + enabled: + type: boolean + default: true + description: Whether this usage alert is enabled. + threshold: + type: number + minimum: 0 + description: The threshold value that triggers the alert. For usage, this is an absolute count. For usage_percentage, this is a percentage (0-100). + threshold_type: + enum: + - usage + - usage_percentage + type: string + description: Whether the threshold is an absolute usage count or a percentage of the usage allowance. + name: + type: string + description: Optional user-defined label to distinguish multiple alerts on the same feature. + required: + - threshold + - threshold_type + description: List of usage alert configurations per feature. description: Billing controls for the customer (auto top-ups, etc.) new_customer_id: $ref: "#/components/schemas/CustomerId" @@ -2191,6 +2366,7 @@ paths: enum: - sandbox - live + type: string description: The environment this customer was created in. metadata: type: object @@ -2232,6 +2408,7 @@ paths: - day - week - month + type: string description: The time interval for the purchase limit window. interval_count: type: number @@ -2268,6 +2445,35 @@ paths: minimum: 0 description: Maximum allowed overage spend for the target feature. description: List of overage spend limits per feature. + usage_alerts: + type: array + items: + type: object + properties: + feature_id: + type: string + description: The feature ID this alert applies to. If omitted, the alert applies globally. + enabled: + type: boolean + default: true + description: Whether this usage alert is enabled. + threshold: + type: number + minimum: 0 + description: The threshold value that triggers the alert. For usage, this is an absolute count. For usage_percentage, this is a percentage (0-100). + threshold_type: + enum: + - usage + - usage_percentage + type: string + description: Whether the threshold is an absolute usage count or a percentage of the usage allowance. + name: + type: string + description: Optional user-defined label to distinguish multiple alerts on the same feature. + required: + - threshold + - threshold_type + description: List of usage alert configurations per feature. description: Billing controls for the customer (auto top-ups, etc.) subscriptions: type: array @@ -2293,6 +2499,7 @@ paths: enum: - active - scheduled + type: string description: Current status of the subscription. past_due: type: boolean @@ -2415,6 +2622,7 @@ paths: - boolean - metered - credit_system + type: string description: "Feature type: 'boolean' for on/off access, 'metered' for usage-tracked features, 'credit_system' for unified credit pools." consumable: type: boolean @@ -2720,6 +2928,7 @@ paths: - quarter - semi_annual - year + type: string description: Billing interval (e.g. 'month', 'year'). interval_count: type: number @@ -2756,6 +2965,7 @@ paths: - quarter - semi_annual - year + type: string description: Interval at which balance resets (e.g. 'month', 'year'). For consumable features only. interval_count: type: number @@ -2789,6 +2999,7 @@ paths: enum: - graduated - volume + type: string interval: enum: - one_off @@ -2797,6 +3008,7 @@ paths: - quarter - semi_annual - year + type: string description: Billing interval. For consumable features, should match reset.interval. interval_count: type: number @@ -2810,6 +3022,7 @@ paths: enum: - prepaid - usage_based + type: string description: "'prepaid' for upfront payment (seats), 'usage_based' for pay-as-you-go." max_purchase: type: number @@ -2827,6 +3040,7 @@ paths: - prorate_immediately - prorate_next_cycle - bill_next_cycle + type: string description: Billing behavior when quantity increases mid-cycle. on_decrease: enum: @@ -2835,6 +3049,7 @@ paths: - prorate_next_cycle - none - no_prorations + type: string description: Credit behavior when quantity decreases mid-cycle. required: - on_increase @@ -2850,6 +3065,7 @@ paths: enum: - month - forever + type: string description: When rolled over units expire. expiry_duration_length: type: number @@ -2873,6 +3089,7 @@ paths: - day - month - year + type: string default: month description: Unit of time for the trial ('day', 'month', 'year'). card_required: @@ -2971,6 +3188,7 @@ paths: - quarter - semi_annual - year + type: string description: Billing interval (e.g. 'month', 'year'). interval_count: type: number @@ -3018,6 +3236,7 @@ paths: - single_use - continuous_use - credit_system + type: string description: The type of the feature display: anyOf: @@ -3081,6 +3300,7 @@ paths: - quarter - semi_annual - year + type: string description: The interval at which the feature balance resets (e.g. 'month', 'year'). For consumable features, usage resets to 0 and included units are restored. interval_count: type: number @@ -3107,6 +3327,7 @@ paths: enum: - graduated - volume + type: string interval: enum: - one_off @@ -3115,6 +3336,7 @@ paths: - quarter - semi_annual - year + type: string description: Billing interval for this price. For consumable features, should match reset.interval. interval_count: type: number @@ -3126,6 +3348,7 @@ paths: enum: - prepaid - usage_based + type: string description: "'prepaid' for features like seats where customers pay upfront, 'usage_based' for pay-as-you-go after included usage." max_purchase: anyOf: @@ -3163,6 +3386,7 @@ paths: enum: - month - forever + type: string description: When rolled over units expire. expiry_duration_length: type: number @@ -3189,6 +3413,7 @@ paths: - day - month - year + type: string description: Unit of time for the trial duration ('day', 'month', 'year'). card_required: type: boolean @@ -3205,6 +3430,7 @@ paths: enum: - sandbox - live + type: string description: Environment this plan belongs to ('sandbox' or 'live'). archived: type: boolean @@ -3224,6 +3450,7 @@ paths: enum: - active - scheduled + type: string description: The customer's current status with this plan. 'active' if attached, 'scheduled' if pending activation. canceling: type: boolean @@ -3238,6 +3465,7 @@ paths: - downgrade - none - purchase + type: string description: The action that would occur if this plan were attached to the customer. required: - attach_action @@ -3414,6 +3642,7 @@ paths: - quarter - semi_annual - year + type: string description: Billing interval (e.g. 'month', 'year'). interval_count: type: number @@ -3461,6 +3690,7 @@ paths: - single_use - continuous_use - credit_system + type: string description: The type of the feature display: anyOf: @@ -3524,6 +3754,7 @@ paths: - quarter - semi_annual - year + type: string description: The interval at which the feature balance resets (e.g. 'month', 'year'). For consumable features, usage resets to 0 and included units are restored. interval_count: type: number @@ -3550,6 +3781,7 @@ paths: enum: - graduated - volume + type: string interval: enum: - one_off @@ -3558,6 +3790,7 @@ paths: - quarter - semi_annual - year + type: string description: Billing interval for this price. For consumable features, should match reset.interval. interval_count: type: number @@ -3569,6 +3802,7 @@ paths: enum: - prepaid - usage_based + type: string description: "'prepaid' for features like seats where customers pay upfront, 'usage_based' for pay-as-you-go after included usage." max_purchase: anyOf: @@ -3606,6 +3840,7 @@ paths: enum: - month - forever + type: string description: When rolled over units expire. expiry_duration_length: type: number @@ -3632,6 +3867,7 @@ paths: - day - month - year + type: string description: Unit of time for the trial duration ('day', 'month', 'year'). card_required: type: boolean @@ -3648,6 +3884,7 @@ paths: enum: - sandbox - live + type: string description: Environment this plan belongs to ('sandbox' or 'live'). archived: type: boolean @@ -3667,6 +3904,7 @@ paths: enum: - active - scheduled + type: string description: The customer's current status with this plan. 'active' if attached, 'scheduled' if pending activation. canceling: type: boolean @@ -3681,6 +3919,7 @@ paths: - downgrade - none - purchase + type: string description: The action that would occur if this plan were attached to the customer. required: - attach_action @@ -3835,6 +4074,7 @@ paths: - quarter - semi_annual - year + type: string description: Billing interval (e.g. 'month', 'year'). interval_count: type: number @@ -3882,6 +4122,7 @@ paths: - single_use - continuous_use - credit_system + type: string description: The type of the feature display: anyOf: @@ -3945,6 +4186,7 @@ paths: - quarter - semi_annual - year + type: string description: The interval at which the feature balance resets (e.g. 'month', 'year'). For consumable features, usage resets to 0 and included units are restored. interval_count: type: number @@ -3971,6 +4213,7 @@ paths: enum: - graduated - volume + type: string interval: enum: - one_off @@ -3979,6 +4222,7 @@ paths: - quarter - semi_annual - year + type: string description: Billing interval for this price. For consumable features, should match reset.interval. interval_count: type: number @@ -3990,6 +4234,7 @@ paths: enum: - prepaid - usage_based + type: string description: "'prepaid' for features like seats where customers pay upfront, 'usage_based' for pay-as-you-go after included usage." max_purchase: anyOf: @@ -4027,6 +4272,7 @@ paths: enum: - month - forever + type: string description: When rolled over units expire. expiry_duration_length: type: number @@ -4053,6 +4299,7 @@ paths: - day - month - year + type: string description: Unit of time for the trial duration ('day', 'month', 'year'). card_required: type: boolean @@ -4069,6 +4316,7 @@ paths: enum: - sandbox - live + type: string description: Environment this plan belongs to ('sandbox' or 'live'). archived: type: boolean @@ -4088,6 +4336,7 @@ paths: enum: - active - scheduled + type: string description: The customer's current status with this plan. 'active' if attached, 'scheduled' if pending activation. canceling: type: boolean @@ -4102,6 +4351,7 @@ paths: - downgrade - none - purchase + type: string description: The action that would occur if this plan were attached to the customer. required: - attach_action @@ -4266,6 +4516,7 @@ paths: - quarter - semi_annual - year + type: string description: Billing interval (e.g. 'month', 'year'). interval_count: type: number @@ -4305,6 +4556,7 @@ paths: - quarter - semi_annual - year + type: string description: Interval at which balance resets (e.g. 'month', 'year'). For consumable features only. interval_count: type: number @@ -4338,6 +4590,7 @@ paths: enum: - graduated - volume + type: string interval: enum: - one_off @@ -4346,6 +4599,7 @@ paths: - quarter - semi_annual - year + type: string description: Billing interval. For consumable features, should match reset.interval. interval_count: type: number @@ -4359,6 +4613,7 @@ paths: enum: - prepaid - usage_based + type: string description: "'prepaid' for upfront payment (seats), 'usage_based' for pay-as-you-go." max_purchase: type: number @@ -4376,6 +4631,7 @@ paths: - prorate_immediately - prorate_next_cycle - bill_next_cycle + type: string description: Billing behavior when quantity increases mid-cycle. on_decrease: enum: @@ -4384,6 +4640,7 @@ paths: - prorate_next_cycle - none - no_prorations + type: string description: Credit behavior when quantity decreases mid-cycle. required: - on_increase @@ -4399,6 +4656,7 @@ paths: enum: - month - forever + type: string description: When rolled over units expire. expiry_duration_length: type: number @@ -4423,6 +4681,7 @@ paths: - day - month - year + type: string default: month description: Unit of time for the trial ('day', 'month', 'year'). card_required: @@ -4506,6 +4765,7 @@ paths: - quarter - semi_annual - year + type: string description: Billing interval (e.g. 'month', 'year'). interval_count: type: number @@ -4553,6 +4813,7 @@ paths: - single_use - continuous_use - credit_system + type: string description: The type of the feature display: anyOf: @@ -4616,6 +4877,7 @@ paths: - quarter - semi_annual - year + type: string description: The interval at which the feature balance resets (e.g. 'month', 'year'). For consumable features, usage resets to 0 and included units are restored. interval_count: type: number @@ -4642,6 +4904,7 @@ paths: enum: - graduated - volume + type: string interval: enum: - one_off @@ -4650,6 +4913,7 @@ paths: - quarter - semi_annual - year + type: string description: Billing interval for this price. For consumable features, should match reset.interval. interval_count: type: number @@ -4661,6 +4925,7 @@ paths: enum: - prepaid - usage_based + type: string description: "'prepaid' for features like seats where customers pay upfront, 'usage_based' for pay-as-you-go after included usage." max_purchase: anyOf: @@ -4698,6 +4963,7 @@ paths: enum: - month - forever + type: string description: When rolled over units expire. expiry_duration_length: type: number @@ -4724,6 +4990,7 @@ paths: - day - month - year + type: string description: Unit of time for the trial duration ('day', 'month', 'year'). card_required: type: boolean @@ -4740,6 +5007,7 @@ paths: enum: - sandbox - live + type: string description: Environment this plan belongs to ('sandbox' or 'live'). archived: type: boolean @@ -4759,6 +5027,7 @@ paths: enum: - active - scheduled + type: string description: The customer's current status with this plan. 'active' if attached, 'scheduled' if pending activation. canceling: type: boolean @@ -4773,6 +5042,7 @@ paths: - downgrade - none - purchase + type: string description: The action that would occur if this plan were attached to the customer. required: - attach_action @@ -4987,6 +5257,7 @@ paths: - boolean - metered - credit_system + type: string description: The type of the feature. 'single_use' features are consumed, like API calls, tokens, or messages. 'continuous_use' features are allocated, like seats, workspaces, or projects. 'credit_system' features are schemas that unify multiple 'single_use' features into a single credit system. consumable: type: boolean @@ -5060,6 +5331,7 @@ paths: - boolean - metered - credit_system + type: string description: "Feature type: 'boolean' for on/off access, 'metered' for usage-tracked features, 'credit_system' for unified credit pools." consumable: type: boolean @@ -5172,6 +5444,7 @@ paths: - boolean - metered - credit_system + type: string description: "Feature type: 'boolean' for on/off access, 'metered' for usage-tracked features, 'credit_system' for unified credit pools." consumable: type: boolean @@ -5268,6 +5541,7 @@ paths: - boolean - metered - credit_system + type: string description: "Feature type: 'boolean' for on/off access, 'metered' for usage-tracked features, 'credit_system' for unified credit pools." consumable: type: boolean @@ -5411,6 +5685,7 @@ paths: - boolean - metered - credit_system + type: string description: The type of the feature. 'single_use' features are consumed, like API calls, tokens, or messages. 'continuous_use' features are allocated, like seats, workspaces, or projects. 'credit_system' features are schemas that unify multiple 'single_use' features into a single credit system. consumable: type: boolean @@ -5482,6 +5757,7 @@ paths: - boolean - metered - credit_system + type: string description: "Feature type: 'boolean' for on/off access, 'metered' for usage-tracked features, 'credit_system' for unified credit pools." consumable: type: boolean @@ -5742,6 +6018,7 @@ paths: - quarter - semi_annual - year + type: string description: Billing interval (e.g. 'month', 'year'). interval_count: type: number @@ -5781,6 +6058,7 @@ paths: - quarter - semi_annual - year + type: string description: Interval at which balance resets (e.g. 'month', 'year'). For consumable features only. interval_count: type: number @@ -5814,6 +6092,7 @@ paths: enum: - graduated - volume + type: string interval: enum: - one_off @@ -5822,6 +6101,7 @@ paths: - quarter - semi_annual - year + type: string description: Billing interval. For consumable features, should match reset.interval. interval_count: type: number @@ -5835,6 +6115,7 @@ paths: enum: - prepaid - usage_based + type: string description: "'prepaid' for upfront payment (seats), 'usage_based' for pay-as-you-go." max_purchase: type: number @@ -5852,6 +6133,7 @@ paths: - prorate_immediately - prorate_next_cycle - bill_next_cycle + type: string description: Billing behavior when quantity increases mid-cycle. on_decrease: enum: @@ -5860,6 +6142,7 @@ paths: - prorate_next_cycle - none - no_prorations + type: string description: Credit behavior when quantity decreases mid-cycle. required: - on_increase @@ -5875,6 +6158,7 @@ paths: enum: - month - forever + type: string description: When rolled over units expire. expiry_duration_length: type: number @@ -5899,6 +6183,7 @@ paths: - day - month - year + type: string default: month description: Unit of time for the trial ('day', 'month', 'year'). card_required: @@ -5933,12 +6218,14 @@ paths: enum: - prorate_immediately - none + type: string description: How to handle proration when updating an existing subscription. 'prorate_immediately' charges/credits prorated amounts now, 'none' skips creating any charges. redirect_mode: enum: - always - if_required - never + type: string description: Controls when to return a checkout URL. 'always' returns a URL even if payment succeeds, 'if_required' only when payment action is needed, 'never' disables redirects. default: if_required subscription_id: @@ -5968,6 +6255,7 @@ paths: enum: - immediate - end_of_cycle + type: string description: When the plan change should take effect. 'immediate' applies now, 'end_of_cycle' schedules for the end of the current billing cycle. By default, upgrades are immediate and downgrades are scheduled. checkout_session_params: type: object @@ -6084,6 +6372,7 @@ paths: - 3ds_required - payment_method_required - payment_failed + type: string description: The type of action required to complete the payment. reason: type: string @@ -6181,6 +6470,7 @@ paths: - quarter - semi_annual - year + type: string description: Billing interval (e.g. 'month', 'year'). interval_count: type: number @@ -6220,6 +6510,7 @@ paths: - quarter - semi_annual - year + type: string description: Interval at which balance resets (e.g. 'month', 'year'). For consumable features only. interval_count: type: number @@ -6253,6 +6544,7 @@ paths: enum: - graduated - volume + type: string interval: enum: - one_off @@ -6261,6 +6553,7 @@ paths: - quarter - semi_annual - year + type: string description: Billing interval. For consumable features, should match reset.interval. interval_count: type: number @@ -6274,6 +6567,7 @@ paths: enum: - prepaid - usage_based + type: string description: "'prepaid' for upfront payment (seats), 'usage_based' for pay-as-you-go." max_purchase: type: number @@ -6291,6 +6585,7 @@ paths: - prorate_immediately - prorate_next_cycle - bill_next_cycle + type: string description: Billing behavior when quantity increases mid-cycle. on_decrease: enum: @@ -6299,6 +6594,7 @@ paths: - prorate_next_cycle - none - no_prorations + type: string description: Credit behavior when quantity decreases mid-cycle. required: - on_increase @@ -6314,6 +6610,7 @@ paths: enum: - month - forever + type: string description: When rolled over units expire. expiry_duration_length: type: number @@ -6368,6 +6665,7 @@ paths: - day - month - year + type: string default: month description: Unit of time for the trial ('day', 'month', 'year'). card_required: @@ -6425,6 +6723,7 @@ paths: - always - if_required - never + type: string description: Controls when to return a checkout URL. 'always' returns a URL even if payment succeeds, 'if_required' only when payment action is needed, 'never' disables redirects. default: if_required new_billing_subscription: @@ -6461,6 +6760,35 @@ paths: minimum: 0 description: Maximum allowed overage spend for the target feature. description: List of overage spend limits per feature. + usage_alerts: + type: array + items: + type: object + properties: + feature_id: + type: string + description: The feature ID this alert applies to. If omitted, the alert applies globally. + enabled: + type: boolean + default: true + description: Whether this usage alert is enabled. + threshold: + type: number + minimum: 0 + description: The threshold value that triggers the alert. For usage, this is an absolute count. For usage_percentage, this is a percentage (0-100). + threshold_type: + enum: + - usage + - usage_percentage + type: string + description: Whether the threshold is an absolute usage count or a percentage of the usage allowance. + name: + type: string + description: Optional user-defined label to distinguish multiple alerts on the same feature. + required: + - threshold + - threshold_type + description: List of usage alert configurations per feature. description: Billing controls for the entity. required: - feature_id @@ -6532,6 +6860,7 @@ paths: - 3ds_required - payment_method_required - payment_failed + type: string description: The type of action required to complete the payment. reason: type: string @@ -6675,6 +7004,7 @@ paths: - quarter - semi_annual - year + type: string description: Billing interval (e.g. 'month', 'year'). interval_count: type: number @@ -6714,6 +7044,7 @@ paths: - quarter - semi_annual - year + type: string description: Interval at which balance resets (e.g. 'month', 'year'). For consumable features only. interval_count: type: number @@ -6747,6 +7078,7 @@ paths: enum: - graduated - volume + type: string interval: enum: - one_off @@ -6755,6 +7087,7 @@ paths: - quarter - semi_annual - year + type: string description: Billing interval. For consumable features, should match reset.interval. interval_count: type: number @@ -6768,6 +7101,7 @@ paths: enum: - prepaid - usage_based + type: string description: "'prepaid' for upfront payment (seats), 'usage_based' for pay-as-you-go." max_purchase: type: number @@ -6785,6 +7119,7 @@ paths: - prorate_immediately - prorate_next_cycle - bill_next_cycle + type: string description: Billing behavior when quantity increases mid-cycle. on_decrease: enum: @@ -6793,6 +7128,7 @@ paths: - prorate_next_cycle - none - no_prorations + type: string description: Credit behavior when quantity decreases mid-cycle. required: - on_increase @@ -6808,6 +7144,7 @@ paths: enum: - month - forever + type: string description: When rolled over units expire. expiry_duration_length: type: number @@ -6832,6 +7169,7 @@ paths: - day - month - year + type: string default: month description: Unit of time for the trial ('day', 'month', 'year'). card_required: @@ -6866,12 +7204,14 @@ paths: enum: - prorate_immediately - none + type: string description: How to handle proration when updating an existing subscription. 'prorate_immediately' charges/credits prorated amounts now, 'none' skips creating any charges. redirect_mode: enum: - always - if_required - never + type: string description: Controls when to return a checkout URL. 'always' returns a URL even if payment succeeds, 'if_required' only when payment action is needed, 'never' disables redirects. default: if_required subscription_id: @@ -6901,6 +7241,7 @@ paths: enum: - immediate - end_of_cycle + type: string description: When the plan change should take effect. 'immediate' applies now, 'end_of_cycle' schedules for the end of the current billing cycle. By default, upgrades are immediate and downgrades are scheduled. checkout_session_params: type: object @@ -7204,10 +7545,22 @@ paths: - type: number - type: "null" description: When this change takes effect, in milliseconds since the Unix epoch, or null if it applies immediately. + canceled_at: + anyOf: + - type: number + - type: "null" + description: When this plan was canceled, in milliseconds since the Unix epoch, or null if it is not canceled. + expires_at: + anyOf: + - type: number + - type: "null" + description: When this plan expires, in milliseconds since the Unix epoch, or null if it does not expire. required: - plan_id - feature_quantities - effective_at + - canceled_at + - expires_at description: Products or subscription changes being added or updated. outgoing: type: array @@ -7240,10 +7593,22 @@ paths: - type: number - type: "null" description: When this change takes effect, in milliseconds since the Unix epoch, or null if it applies immediately. + canceled_at: + anyOf: + - type: number + - type: "null" + description: When this plan was canceled, in milliseconds since the Unix epoch, or null if it is not canceled. + expires_at: + anyOf: + - type: number + - type: "null" + description: When this plan expires, in milliseconds since the Unix epoch, or null if it does not expire. required: - plan_id - feature_quantities - effective_at + - canceled_at + - expires_at description: Products or subscription changes being removed or ended. required: - customer_id @@ -7335,6 +7700,7 @@ paths: - quarter - semi_annual - year + type: string description: Billing interval (e.g. 'month', 'year'). interval_count: type: number @@ -7374,6 +7740,7 @@ paths: - quarter - semi_annual - year + type: string description: Interval at which balance resets (e.g. 'month', 'year'). For consumable features only. interval_count: type: number @@ -7407,6 +7774,7 @@ paths: enum: - graduated - volume + type: string interval: enum: - one_off @@ -7415,6 +7783,7 @@ paths: - quarter - semi_annual - year + type: string description: Billing interval. For consumable features, should match reset.interval. interval_count: type: number @@ -7428,6 +7797,7 @@ paths: enum: - prepaid - usage_based + type: string description: "'prepaid' for upfront payment (seats), 'usage_based' for pay-as-you-go." max_purchase: type: number @@ -7445,6 +7815,7 @@ paths: - prorate_immediately - prorate_next_cycle - bill_next_cycle + type: string description: Billing behavior when quantity increases mid-cycle. on_decrease: enum: @@ -7453,6 +7824,7 @@ paths: - prorate_next_cycle - none - no_prorations + type: string description: Credit behavior when quantity decreases mid-cycle. required: - on_increase @@ -7468,6 +7840,7 @@ paths: enum: - month - forever + type: string description: When rolled over units expire. expiry_duration_length: type: number @@ -7522,6 +7895,7 @@ paths: - day - month - year + type: string default: month description: Unit of time for the trial ('day', 'month', 'year'). card_required: @@ -7579,6 +7953,7 @@ paths: - always - if_required - never + type: string description: Controls when to return a checkout URL. 'always' returns a URL even if payment succeeds, 'if_required' only when payment action is needed, 'never' disables redirects. default: if_required new_billing_subscription: @@ -7615,6 +7990,35 @@ paths: minimum: 0 description: Maximum allowed overage spend for the target feature. description: List of overage spend limits per feature. + usage_alerts: + type: array + items: + type: object + properties: + feature_id: + type: string + description: The feature ID this alert applies to. If omitted, the alert applies globally. + enabled: + type: boolean + default: true + description: Whether this usage alert is enabled. + threshold: + type: number + minimum: 0 + description: The threshold value that triggers the alert. For usage, this is an absolute count. For usage_percentage, this is a percentage (0-100). + threshold_type: + enum: + - usage + - usage_percentage + type: string + description: Whether the threshold is an absolute usage count or a percentage of the usage allowance. + name: + type: string + description: Optional user-defined label to distinguish multiple alerts on the same feature. + required: + - threshold + - threshold_type + description: List of usage alert configurations per feature. description: Billing controls for the entity. required: - feature_id @@ -7873,10 +8277,22 @@ paths: - type: number - type: "null" description: When this change takes effect, in milliseconds since the Unix epoch, or null if it applies immediately. + canceled_at: + anyOf: + - type: number + - type: "null" + description: When this plan was canceled, in milliseconds since the Unix epoch, or null if it is not canceled. + expires_at: + anyOf: + - type: number + - type: "null" + description: When this plan expires, in milliseconds since the Unix epoch, or null if it does not expire. required: - plan_id - feature_quantities - effective_at + - canceled_at + - expires_at description: Products or subscription changes being added or updated. outgoing: type: array @@ -7909,10 +8325,22 @@ paths: - type: number - type: "null" description: When this change takes effect, in milliseconds since the Unix epoch, or null if it applies immediately. + canceled_at: + anyOf: + - type: number + - type: "null" + description: When this plan was canceled, in milliseconds since the Unix epoch, or null if it is not canceled. + expires_at: + anyOf: + - type: number + - type: "null" + description: When this plan expires, in milliseconds since the Unix epoch, or null if it does not expire. required: - plan_id - feature_quantities - effective_at + - canceled_at + - expires_at description: Products or subscription changes being removed or ended. required: - customer_id @@ -8003,6 +8431,8 @@ paths: @param noBillingChanges - If true, the subscription is updated internally without applying billing changes in Stripe. (optional) + @param recalculateBalances - Controls whether balances should be recalculated during the subscription update. (optional) + @returns A billing response with customer ID, invoice details, and payment URL (if next action is required). tags: @@ -8064,6 +8494,7 @@ paths: - quarter - semi_annual - year + type: string description: Billing interval (e.g. 'month', 'year'). interval_count: type: number @@ -8103,6 +8534,7 @@ paths: - quarter - semi_annual - year + type: string description: Interval at which balance resets (e.g. 'month', 'year'). For consumable features only. interval_count: type: number @@ -8136,6 +8568,7 @@ paths: enum: - graduated - volume + type: string interval: enum: - one_off @@ -8144,6 +8577,7 @@ paths: - quarter - semi_annual - year + type: string description: Billing interval. For consumable features, should match reset.interval. interval_count: type: number @@ -8157,6 +8591,7 @@ paths: enum: - prepaid - usage_based + type: string description: "'prepaid' for upfront payment (seats), 'usage_based' for pay-as-you-go." max_purchase: type: number @@ -8174,6 +8609,7 @@ paths: - prorate_immediately - prorate_next_cycle - bill_next_cycle + type: string description: Billing behavior when quantity increases mid-cycle. on_decrease: enum: @@ -8182,6 +8618,7 @@ paths: - prorate_next_cycle - none - no_prorations + type: string description: Credit behavior when quantity decreases mid-cycle. required: - on_increase @@ -8197,6 +8634,7 @@ paths: enum: - month - forever + type: string description: When rolled over units expire. expiry_duration_length: type: number @@ -8221,6 +8659,7 @@ paths: - day - month - year + type: string default: month description: Unit of time for the trial ('day', 'month', 'year'). card_required: @@ -8255,12 +8694,14 @@ paths: enum: - prorate_immediately - none + type: string description: How to handle proration when updating an existing subscription. 'prorate_immediately' charges/credits prorated amounts now, 'none' skips creating any charges. redirect_mode: enum: - always - if_required - never + type: string description: Controls when to return a checkout URL. 'always' returns a URL even if payment succeeds, 'if_required' only when payment action is needed, 'never' disables redirects. default: if_required subscription_id: @@ -8271,10 +8712,20 @@ paths: - cancel_immediately - cancel_end_of_cycle - uncancel + type: string description: Action to perform for cancellation. 'cancel_immediately' cancels now with prorated refund, 'cancel_end_of_cycle' cancels at period end, 'uncancel' reverses a pending cancellation. no_billing_changes: type: boolean description: If true, the subscription is updated internally without applying billing changes in Stripe. + recalculate_balances: + type: object + properties: + enabled: + type: boolean + description: If true, recalculates balances during the subscription update. Only applicable when updating feature quantities. + required: + - enabled + description: Controls whether balances should be recalculated during the subscription update. required: - customer_id title: UpdateSubscriptionParams @@ -8340,6 +8791,7 @@ paths: - 3ds_required - payment_method_required - payment_failed + type: string description: The type of action required to complete the payment. reason: type: string @@ -8408,6 +8860,8 @@ paths: @param noBillingChanges - If true, the subscription is updated internally without applying billing changes in Stripe. (optional) + @param recalculateBalances - Controls whether balances should be recalculated during the subscription update. (optional) + @returns A preview response with line items showing prorated charges or credits for the proposed changes. tags: @@ -8469,6 +8923,7 @@ paths: - quarter - semi_annual - year + type: string description: Billing interval (e.g. 'month', 'year'). interval_count: type: number @@ -8508,6 +8963,7 @@ paths: - quarter - semi_annual - year + type: string description: Interval at which balance resets (e.g. 'month', 'year'). For consumable features only. interval_count: type: number @@ -8541,6 +8997,7 @@ paths: enum: - graduated - volume + type: string interval: enum: - one_off @@ -8549,6 +9006,7 @@ paths: - quarter - semi_annual - year + type: string description: Billing interval. For consumable features, should match reset.interval. interval_count: type: number @@ -8562,6 +9020,7 @@ paths: enum: - prepaid - usage_based + type: string description: "'prepaid' for upfront payment (seats), 'usage_based' for pay-as-you-go." max_purchase: type: number @@ -8579,6 +9038,7 @@ paths: - prorate_immediately - prorate_next_cycle - bill_next_cycle + type: string description: Billing behavior when quantity increases mid-cycle. on_decrease: enum: @@ -8587,6 +9047,7 @@ paths: - prorate_next_cycle - none - no_prorations + type: string description: Credit behavior when quantity decreases mid-cycle. required: - on_increase @@ -8602,6 +9063,7 @@ paths: enum: - month - forever + type: string description: When rolled over units expire. expiry_duration_length: type: number @@ -8626,6 +9088,7 @@ paths: - day - month - year + type: string default: month description: Unit of time for the trial ('day', 'month', 'year'). card_required: @@ -8660,12 +9123,14 @@ paths: enum: - prorate_immediately - none + type: string description: How to handle proration when updating an existing subscription. 'prorate_immediately' charges/credits prorated amounts now, 'none' skips creating any charges. redirect_mode: enum: - always - if_required - never + type: string description: Controls when to return a checkout URL. 'always' returns a URL even if payment succeeds, 'if_required' only when payment action is needed, 'never' disables redirects. default: if_required subscription_id: @@ -8676,10 +9141,20 @@ paths: - cancel_immediately - cancel_end_of_cycle - uncancel + type: string description: Action to perform for cancellation. 'cancel_immediately' cancels now with prorated refund, 'cancel_end_of_cycle' cancels at period end, 'uncancel' reverses a pending cancellation. no_billing_changes: type: boolean description: If true, the subscription is updated internally without applying billing changes in Stripe. + recalculate_balances: + type: object + properties: + enabled: + type: boolean + description: If true, recalculates balances during the subscription update. Only applicable when updating feature quantities. + required: + - enabled + description: Controls whether balances should be recalculated during the subscription update. required: - customer_id title: PreviewUpdateParams @@ -8932,10 +9407,22 @@ paths: - type: number - type: "null" description: When this change takes effect, in milliseconds since the Unix epoch, or null if it applies immediately. + canceled_at: + anyOf: + - type: number + - type: "null" + description: When this plan was canceled, in milliseconds since the Unix epoch, or null if it is not canceled. + expires_at: + anyOf: + - type: number + - type: "null" + description: When this plan expires, in milliseconds since the Unix epoch, or null if it does not expire. required: - plan_id - feature_quantities - effective_at + - canceled_at + - expires_at description: Products or subscription changes being added or updated. outgoing: type: array @@ -8968,10 +9455,22 @@ paths: - type: number - type: "null" description: When this change takes effect, in milliseconds since the Unix epoch, or null if it applies immediately. + canceled_at: + anyOf: + - type: number + - type: "null" + description: When this plan was canceled, in milliseconds since the Unix epoch, or null if it is not canceled. + expires_at: + anyOf: + - type: number + - type: "null" + description: When this plan expires, in milliseconds since the Unix epoch, or null if it does not expire. required: - plan_id - feature_quantities - effective_at + - canceled_at + - expires_at description: Products or subscription changes being removed or ended. intent: enum: @@ -8981,6 +9480,7 @@ paths: - cancel_end_of_cycle - uncancel - none + type: string required: - customer_id - line_items @@ -9118,6 +9618,7 @@ paths: - quarter - semi_annual - year + type: string description: Billing interval (e.g. 'month', 'year'). interval_count: type: number @@ -9157,6 +9658,7 @@ paths: - quarter - semi_annual - year + type: string description: Interval at which balance resets (e.g. 'month', 'year'). For consumable features only. interval_count: type: number @@ -9190,6 +9692,7 @@ paths: enum: - graduated - volume + type: string interval: enum: - one_off @@ -9198,6 +9701,7 @@ paths: - quarter - semi_annual - year + type: string description: Billing interval. For consumable features, should match reset.interval. interval_count: type: number @@ -9211,6 +9715,7 @@ paths: enum: - prepaid - usage_based + type: string description: "'prepaid' for upfront payment (seats), 'usage_based' for pay-as-you-go." max_purchase: type: number @@ -9228,6 +9733,7 @@ paths: - prorate_immediately - prorate_next_cycle - bill_next_cycle + type: string description: Billing behavior when quantity increases mid-cycle. on_decrease: enum: @@ -9236,6 +9742,7 @@ paths: - prorate_next_cycle - none - no_prorations + type: string description: Credit behavior when quantity decreases mid-cycle. required: - on_increase @@ -9251,6 +9758,7 @@ paths: enum: - month - forever + type: string description: When rolled over units expire. expiry_duration_length: type: number @@ -9275,6 +9783,7 @@ paths: - day - month - year + type: string default: month description: Unit of time for the trial ('day', 'month', 'year'). card_required: @@ -9292,6 +9801,7 @@ paths: enum: - prorate_immediately - none + type: string description: How to handle proration when updating an existing subscription. 'prorate_immediately' charges/credits prorated amounts now, 'none' skips creating any charges. subscription_id: type: string @@ -9440,6 +9950,7 @@ paths: - quarter - semi_annual - year + type: string description: The interval at which the balance resets (e.g., 'month', 'day', 'year'). interval_count: type: number @@ -9520,6 +10031,7 @@ paths: - quarter - semi_annual - year + type: string description: Target a specific balance by its reset interval. Use when the customer has multiple balances for the same feature with different reset intervals. included_grant: type: number @@ -9589,6 +10101,7 @@ paths: - quarter - semi_annual - year + type: string description: Target a specific balance by its reset interval. Use when the customer has multiple balances for the same feature with different reset intervals. required: - customer_id @@ -9631,6 +10144,7 @@ paths: enum: - confirm - release + type: string description: Use 'confirm' to commit the deduction, or 'release' to return the held balance. override_value: type: number @@ -9845,6 +10359,7 @@ paths: - boolean - metered - credit_system + type: string description: "Feature type: 'boolean' for on/off access, 'metered' for usage-tracked features, 'credit_system' for unified credit pools." consumable: type: boolean @@ -9912,6 +10427,7 @@ paths: enum: - usage_limit - feature_flag + type: string description: The reason access was denied. 'usage_limit' means the customer exceeded their balance, 'feature_flag' means the feature is not included in their plan. title: type: string @@ -9945,6 +10461,7 @@ paths: enum: - sandbox - live + type: string description: The environment of the product is_add_on: type: boolean @@ -9972,6 +10489,7 @@ paths: - feature - priced_feature - price + type: string - type: "null" description: The type of the product item feature_id: @@ -9986,6 +10504,7 @@ paths: - continuous_use - boolean - static + type: string - type: "null" description: Single use features are used once and then depleted, like API calls or credits. Continuous use features are those being used on an ongoing-basis, like storage or seats. included_usage: @@ -10006,6 +10525,7 @@ paths: - quarter - semi_annual - year + type: string - type: "null" description: The reset or billing interval of the product item. If null, feature will have no reset date, and if there's a price, it will be billed one-off. interval_count: @@ -10032,6 +10552,7 @@ paths: - enum: - graduated - volume + type: string - type: "null" description: "How tiers are applied: graduated (split across bands) or volume (flat rate for the matched tier). Defaults to graduated." usage_model: @@ -10039,6 +10560,7 @@ paths: - enum: - prepaid - pay_per_use + type: string - type: "null" description: Whether the feature should be prepaid upfront or billed for how much they use end of billing period. billing_units: @@ -10096,6 +10618,7 @@ paths: enum: - month - forever + type: string default: month length: type: number @@ -10110,6 +10633,7 @@ paths: - prorate_immediately - prorate_next_cycle - bill_next_cycle + type: string - type: "null" on_decrease: anyOf: @@ -10119,6 +10643,7 @@ paths: - prorate_next_cycle - none - no_prorations + type: string - type: "null" - type: "null" description: Configuration for rollover and proration behavior of the feature. @@ -10133,6 +10658,7 @@ paths: - day - month - year + type: string description: The duration type of the free trial length: type: number @@ -10172,6 +10698,7 @@ paths: - cancel - expired - past_due + type: string description: Scenario for when this product is used in attach flows properties: type: object @@ -10598,12 +11125,14 @@ paths: - last_cycle - 1bc - 3bc + type: string description: Time range to aggregate events for. Either range or custom_range must be provided bin_size: enum: - day - hour - month + type: string default: day description: Size of the time bins to aggregate events for. Defaults to hour if range is 24h, otherwise day custom_range: @@ -10818,6 +11347,35 @@ paths: minimum: 0 description: Maximum allowed overage spend for the target feature. description: List of overage spend limits per feature. + usage_alerts: + type: array + items: + type: object + properties: + feature_id: + type: string + description: The feature ID this alert applies to. If omitted, the alert applies globally. + enabled: + type: boolean + default: true + description: Whether this usage alert is enabled. + threshold: + type: number + minimum: 0 + description: The threshold value that triggers the alert. For usage, this is an absolute count. For usage_percentage, this is a percentage (0-100). + threshold_type: + enum: + - usage + - usage_percentage + type: string + description: Whether the threshold is an absolute usage count or a percentage of the usage allowance. + name: + type: string + description: Optional user-defined label to distinguish multiple alerts on the same feature. + required: + - threshold + - threshold_type + description: List of usage alert configurations per feature. description: Billing controls for the entity. customer_data: $ref: "#/components/schemas/CustomerData" @@ -10873,6 +11431,7 @@ paths: enum: - sandbox - live + type: string description: The environment (sandbox/live) subscriptions: type: array @@ -10898,6 +11457,7 @@ paths: enum: - active - scheduled + type: string description: Current status of the subscription. past_due: type: boolean @@ -11017,6 +11577,7 @@ paths: - boolean - metered - credit_system + type: string description: "Feature type: 'boolean' for on/off access, 'metered' for usage-tracked features, 'credit_system' for unified credit pools." consumable: type: boolean @@ -11095,6 +11656,35 @@ paths: minimum: 0 description: Maximum allowed overage spend for the target feature. description: List of overage spend limits per feature. + usage_alerts: + type: array + items: + type: object + properties: + feature_id: + type: string + description: The feature ID this alert applies to. If omitted, the alert applies globally. + enabled: + type: boolean + default: true + description: Whether this usage alert is enabled. + threshold: + type: number + minimum: 0 + description: The threshold value that triggers the alert. For usage, this is an absolute count. For usage_percentage, this is a percentage (0-100). + threshold_type: + enum: + - usage + - usage_percentage + type: string + description: Whether the threshold is an absolute usage count or a percentage of the usage allowance. + name: + type: string + description: Optional user-defined label to distinguish multiple alerts on the same feature. + required: + - threshold + - threshold_type + description: List of usage alert configurations per feature. description: Billing controls for the entity. invoices: type: array @@ -11286,6 +11876,7 @@ paths: enum: - sandbox - live + type: string description: The environment (sandbox/live) subscriptions: type: array @@ -11311,6 +11902,7 @@ paths: enum: - active - scheduled + type: string description: Current status of the subscription. past_due: type: boolean @@ -11430,6 +12022,7 @@ paths: - boolean - metered - credit_system + type: string description: "Feature type: 'boolean' for on/off access, 'metered' for usage-tracked features, 'credit_system' for unified credit pools." consumable: type: boolean @@ -11508,6 +12101,35 @@ paths: minimum: 0 description: Maximum allowed overage spend for the target feature. description: List of overage spend limits per feature. + usage_alerts: + type: array + items: + type: object + properties: + feature_id: + type: string + description: The feature ID this alert applies to. If omitted, the alert applies globally. + enabled: + type: boolean + default: true + description: Whether this usage alert is enabled. + threshold: + type: number + minimum: 0 + description: The threshold value that triggers the alert. For usage, this is an absolute count. For usage_percentage, this is a percentage (0-100). + threshold_type: + enum: + - usage + - usage_percentage + type: string + description: Whether the threshold is an absolute usage count or a percentage of the usage allowance. + name: + type: string + description: Optional user-defined label to distinguish multiple alerts on the same feature. + required: + - threshold + - threshold_type + description: List of usage alert configurations per feature. description: Billing controls for the entity. invoices: type: array @@ -11658,6 +12280,35 @@ paths: minimum: 0 description: Maximum allowed overage spend for the target feature. description: List of overage spend limits per feature. + usage_alerts: + type: array + items: + type: object + properties: + feature_id: + type: string + description: The feature ID this alert applies to. If omitted, the alert applies globally. + enabled: + type: boolean + default: true + description: Whether this usage alert is enabled. + threshold: + type: number + minimum: 0 + description: The threshold value that triggers the alert. For usage, this is an absolute count. For usage_percentage, this is a percentage (0-100). + threshold_type: + enum: + - usage + - usage_percentage + type: string + description: Whether the threshold is an absolute usage count or a percentage of the usage allowance. + name: + type: string + description: Optional user-defined label to distinguish multiple alerts on the same feature. + required: + - threshold + - threshold_type + description: List of usage alert configurations per feature. description: Billing controls to replace on the entity. required: - entity_id @@ -11705,6 +12356,7 @@ paths: enum: - sandbox - live + type: string description: The environment (sandbox/live) subscriptions: type: array @@ -11730,6 +12382,7 @@ paths: enum: - active - scheduled + type: string description: Current status of the subscription. past_due: type: boolean @@ -11849,6 +12502,7 @@ paths: - boolean - metered - credit_system + type: string description: "Feature type: 'boolean' for on/off access, 'metered' for usage-tracked features, 'credit_system' for unified credit pools." consumable: type: boolean @@ -11927,6 +12581,35 @@ paths: minimum: 0 description: Maximum allowed overage spend for the target feature. description: List of overage spend limits per feature. + usage_alerts: + type: array + items: + type: object + properties: + feature_id: + type: string + description: The feature ID this alert applies to. If omitted, the alert applies globally. + enabled: + type: boolean + default: true + description: Whether this usage alert is enabled. + threshold: + type: number + minimum: 0 + description: The threshold value that triggers the alert. For usage, this is an absolute count. For usage_percentage, this is a percentage (0-100). + threshold_type: + enum: + - usage + - usage_percentage + type: string + description: Whether the threshold is an absolute usage count or a percentage of the usage allowance. + name: + type: string + description: Optional user-defined label to distinguish multiple alerts on the same feature. + required: + - threshold + - threshold_type + description: List of usage alert configurations per feature. description: Billing controls for the entity. invoices: type: array @@ -12207,3 +12890,310 @@ x-speakeasy-globals: type: string default: 2.2.0 x-speakeasy-globals-hidden: true +webhooks: + balances.usage_alert_triggered: + post: + operationId: balancesUsageAlertTriggered + summary: Usage Alert Triggered + description: Fired when a customer crosses a configured usage alert threshold. + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - type + - data + properties: + type: + type: string + const: balances.usage_alert_triggered + description: The webhook event type. + data: + examples: + - customer_id: org_123 + feature_id: api_calls + entity_id: workspace_abc + usage_alert: + name: 80% usage warning + threshold: 80 + threshold_type: usage_percentage_threshold + type: object + properties: + customer_id: + description: The ID of the customer whose usage alert was triggered. + type: string + feature_id: + description: The feature ID the alert applies to. + type: string + entity_id: + description: The entity ID the alert applies to, if the usage was entity-scoped. + type: string + usage_alert: + description: Details of the usage alert that was triggered. + type: object + properties: + name: + description: User-defined label for the alert, if provided. + type: string + threshold: + description: The threshold value that was crossed. + type: number + threshold_type: + description: Whether the threshold is an absolute usage count or a percentage. + type: string + enum: + - usage + - usage_percentage + required: + - threshold + - threshold_type + additionalProperties: false + required: + - customer_id + - feature_id + - usage_alert + additionalProperties: false + example: + type: balances.usage_alert_triggered + data: + customer_id: org_123 + feature_id: api_calls + entity_id: workspace_abc + usage_alert: + name: 80% usage warning + threshold: 80 + threshold_type: usage_percentage_threshold + responses: + "200": + description: Webhook received successfully. + balances.limit_reached: + post: + operationId: balancesLimitReached + summary: Limit Reached + description: Fired when a customer reaches the limit for a feature (included allowance, max purchase, or spend limit). + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - type + - data + properties: + type: + type: string + const: balances.limit_reached + description: The webhook event type. + data: + examples: + - customer_id: org_123 + entity_id: workspace_abc + feature_id: api_calls + limit_type: included + type: object + properties: + customer_id: + description: The ID of the customer who hit the limit. + type: string + entity_id: + description: The entity ID, if the limit was reached on a specific entity. + type: string + feature_id: + description: The feature ID whose limit was reached. + type: string + limit_type: + description: "Which limit was hit: included allowance, max purchase cap, or spend limit." + type: string + enum: + - included + - max_purchase + - spend_limit + required: + - customer_id + - feature_id + - limit_type + additionalProperties: false + example: + type: balances.limit_reached + data: + customer_id: org_123 + entity_id: workspace_abc + feature_id: api_calls + limit_type: included + responses: + "200": + description: Webhook received successfully. + vercel.resources.deleted: + post: + operationId: vercelResourcesDeleted + summary: Resource Deleted + description: When a Vercel resource is deleted, you'll need to handle de-provisioning any API keys or other non-Autumn controlled data for this user. + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - type + - data + properties: + type: + type: string + const: vercel.resources.deleted + description: The webhook event type. + data: + type: object + properties: + resource: + description: The resource that was deleted. + type: object + properties: + id: + description: The unique identifier of the deleted resource. + type: string + required: + - id + additionalProperties: false + installation_id: + description: The Vercel integration configuration ID. + type: string + required: + - resource + - installation_id + additionalProperties: false + responses: + "200": + description: Webhook received successfully. + vercel.resources.provisioned: + post: + operationId: vercelResourcesProvisioned + summary: Resource Provisioned + description: When a Vercel resource is created, you'll need to provision a secret key for your service. Then you can use the provided access token to patch the resource's secrets. + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - type + - data + properties: + type: + type: string + const: vercel.resources.provisioned + description: The webhook event type. + data: + type: object + properties: + resource: + description: The resource that was provisioned. + type: object + properties: + id: + description: The unique identifier of the provisioned resource. + type: string + name: + description: The display name of the provisioned resource. + type: string + required: + - id + - name + additionalProperties: false + installation_id: + description: The Vercel integration configuration ID. + type: string + access_token: + description: An access token that can be used to patch the resource's secrets. + type: string + required: + - resource + - installation_id + - access_token + additionalProperties: false + responses: + "200": + description: Webhook received successfully. + vercel.resources.rotate_secrets: + post: + operationId: vercelResourcesRotateSecrets + summary: Rotate Secrets + description: This event is sent when Vercel requires a resource's secrets to be rotated. + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - type + - data + properties: + type: + type: string + const: vercel.resources.rotate_secrets + description: The webhook event type. + data: + type: object + properties: + resource: + description: The resource whose secrets should be rotated. + type: object + properties: + id: + description: The unique identifier of the resource. + type: string + required: + - id + additionalProperties: false + installation_id: + description: The Vercel integration configuration ID. + type: string + vercel_request_body: + description: The raw request body from Vercel's rotation request. + required: + - resource + - installation_id + - vercel_request_body + additionalProperties: false + responses: + "200": + description: Webhook received successfully. + vercel.webhooks.event: + post: + operationId: vercelWebhooksEvent + summary: Webhook Event + description: Passthrough webhook for Vercel events. + requestBody: + required: true + content: + application/json: + schema: + type: object + required: + - type + - data + properties: + type: + type: string + const: vercel.webhooks.event + description: The webhook event type. + data: + type: object + properties: + installation_id: + description: The Vercel integration configuration ID. + type: string + event: + description: The raw Vercel webhook event payload. + required: + - installation_id + - event + additionalProperties: false + responses: + "200": + description: Webhook received successfully. diff --git a/packages/sdk/.speakeasy/workflow.lock b/packages/sdk/.speakeasy/workflow.lock index 40c79d6e3..d19d9afe2 100644 --- a/packages/sdk/.speakeasy/workflow.lock +++ b/packages/sdk/.speakeasy/workflow.lock @@ -1,16 +1,16 @@ -speakeasyVersion: 1.757.1 +speakeasyVersion: 1.719.0 sources: Autumn API: sourceNamespace: autumn-api - sourceRevisionDigest: sha256:5eb5071d5420195da5f83032ba1123effe8934181288e8b08695a1d0fa5d8734 - sourceBlobDigest: sha256:163c4ad9005ca92206e93dc4233f6e3932b1927e9e3a797638dfeae905d4450d + sourceRevisionDigest: sha256:2bcc989537f4586adcc8402828479bcd9c4b42ac9345534d31f2c3a345fa00ed + sourceBlobDigest: sha256:2260cf8c08d26c02fffa4368afe9735bb6f202e52f95105bd3705f0953ae6f78 tags: - latest - - 2.1.0 + - 2.2.0 Autumn API Stripped: sourceNamespace: autumn-api-stripped - sourceRevisionDigest: sha256:4d9487e22543b3e51d08789572c3d90ac3d02564991610bc11541e34b20bc60b - sourceBlobDigest: sha256:26275a1f91ac6dd56e87f72778c860fce556d2a433dee3a8e634b7dfecf842d8 + sourceRevisionDigest: sha256:73b97e1e3131f4a268daddbc9107f4e77beaf628f9308078516cb84848a94480 + sourceBlobDigest: sha256:125b8a9f6111ceb84655b9f7eae781f5a566c8946bee87632a501e382f0a06db tags: - latest - 2.2.0 @@ -18,17 +18,17 @@ targets: autumn: source: Autumn API sourceNamespace: autumn-api - sourceRevisionDigest: sha256:5eb5071d5420195da5f83032ba1123effe8934181288e8b08695a1d0fa5d8734 - sourceBlobDigest: sha256:163c4ad9005ca92206e93dc4233f6e3932b1927e9e3a797638dfeae905d4450d + sourceRevisionDigest: sha256:2bcc989537f4586adcc8402828479bcd9c4b42ac9345534d31f2c3a345fa00ed + sourceBlobDigest: sha256:2260cf8c08d26c02fffa4368afe9735bb6f202e52f95105bd3705f0953ae6f78 codeSamplesNamespace: autumn-api-typescript-code-samples - codeSamplesRevisionDigest: sha256:24d7a293e42a7de5b564b2a1cb011cbbaa81592fe71b7906c64090b1bdb33d4e + codeSamplesRevisionDigest: sha256:ed725e6d550745811ba55b8f9abcfd47782d47cfe73d09757a4bbf56b240b6a4 autumn-python: source: Autumn API Stripped sourceNamespace: autumn-api-stripped - sourceRevisionDigest: sha256:4d9487e22543b3e51d08789572c3d90ac3d02564991610bc11541e34b20bc60b - sourceBlobDigest: sha256:26275a1f91ac6dd56e87f72778c860fce556d2a433dee3a8e634b7dfecf842d8 + sourceRevisionDigest: sha256:73b97e1e3131f4a268daddbc9107f4e77beaf628f9308078516cb84848a94480 + sourceBlobDigest: sha256:125b8a9f6111ceb84655b9f7eae781f5a566c8946bee87632a501e382f0a06db codeSamplesNamespace: autumn-api-python-code-samples - codeSamplesRevisionDigest: sha256:6f5e1b71a197e371ec518024628dbcf0f5f6189bdbd3ffae55f80c7efb43bff8 + codeSamplesRevisionDigest: sha256:9804d178e8ccbe6f452890582dfdd15bdcd88c54ad12ffaec9e7b887b5792082 workflow: workflowVersion: 1.0.0 speakeasyVersion: pinned diff --git a/packages/sdk/README.md b/packages/sdk/README.md index 683ea3b43..016bcc73d 100644 --- a/packages/sdk/README.md +++ b/packages/sdk/README.md @@ -380,6 +380,7 @@ const response = await client.billing.update({ customerId: "cus_123", planId: "p @param subscriptionId - A unique ID to identify this subscription. Can be used to target specific subscriptions in update operations when a customer has multiple products with the same plan. (optional) @param cancelAction - Action to perform for cancellation. 'cancel_immediately' cancels now with prorated refund, 'cancel_end_of_cycle' cancels at period end, 'uncancel' reverses a pending cancellation. (optional) @param noBillingChanges - If true, the subscription is updated internally without applying billing changes in Stripe. (optional) +@param recalculateBalances - Controls whether balances should be recalculated during the subscription update. (optional) @returns A billing response with customer ID, invoice details, and payment URL (if next action is required). * [previewUpdate](docs/sdks/billing/README.md#previewupdate) - Previews the billing changes that would occur when updating a subscription, without actually making any changes. @@ -404,6 +405,7 @@ const response = await client.billing.previewUpdate({ customerId: "cus_123", pla @param subscriptionId - A unique ID to identify this subscription. Can be used to target specific subscriptions in update operations when a customer has multiple products with the same plan. (optional) @param cancelAction - Action to perform for cancellation. 'cancel_immediately' cancels now with prorated refund, 'cancel_end_of_cycle' cancels at period end, 'uncancel' reverses a pending cancellation. (optional) @param noBillingChanges - If true, the subscription is updated internally without applying billing changes in Stripe. (optional) +@param recalculateBalances - Controls whether balances should be recalculated during the subscription update. (optional) @returns A preview response with line items showing prorated charges or credits for the proposed changes. * [openCustomerPortal](docs/sdks/billing/README.md#opencustomerportal) - Create a billing portal session for a customer to manage their subscription. @@ -797,6 +799,7 @@ const response = await client.billing.previewUpdate({ customerId: "cus_123", pla @param subscriptionId - A unique ID to identify this subscription. Can be used to target specific subscriptions in update operations when a customer has multiple products with the same plan. (optional) @param cancelAction - Action to perform for cancellation. 'cancel_immediately' cancels now with prorated refund, 'cancel_end_of_cycle' cancels at period end, 'uncancel' reverses a pending cancellation. (optional) @param noBillingChanges - If true, the subscription is updated internally without applying billing changes in Stripe. (optional) +@param recalculateBalances - Controls whether balances should be recalculated during the subscription update. (optional) @returns A preview response with line items showing prorated charges or credits for the proposed changes. - [`billingSetupPayment`](docs/sdks/billing/README.md#setuppayment) - Create a payment setup session for a customer to add or update their payment method. @@ -834,6 +837,7 @@ const response = await client.billing.update({ customerId: "cus_123", planId: "p @param subscriptionId - A unique ID to identify this subscription. Can be used to target specific subscriptions in update operations when a customer has multiple products with the same plan. (optional) @param cancelAction - Action to perform for cancellation. 'cancel_immediately' cancels now with prorated refund, 'cancel_end_of_cycle' cancels at period end, 'uncancel' reverses a pending cancellation. (optional) @param noBillingChanges - If true, the subscription is updated internally without applying billing changes in Stripe. (optional) +@param recalculateBalances - Controls whether balances should be recalculated during the subscription update. (optional) @returns A billing response with customer ID, invoice details, and payment URL (if next action is required). - [`check`](docs/sdks/autumn/README.md#check) - Checks whether a customer currently has enough balance to use a feature. diff --git a/packages/sdk/package.json b/packages/sdk/package.json index 84d7ead7a..fe58d7845 100644 --- a/packages/sdk/package.json +++ b/packages/sdk/package.json @@ -30,7 +30,7 @@ "@eslint/js": "^9.26.0", "eslint": "^9.26.0", "globals": "^15.14.0", - "tshy": "^3.3.2", + "tshy": "^2.0.0", "typescript": "~5.8.3", "typescript-eslint": "^8.26.0" }, diff --git a/packages/sdk/src/funcs/billing-preview-update.ts b/packages/sdk/src/funcs/billing-preview-update.ts index bcbdaddd7..69d04d5f4 100644 --- a/packages/sdk/src/funcs/billing-preview-update.ts +++ b/packages/sdk/src/funcs/billing-preview-update.ts @@ -48,6 +48,7 @@ import { Result } from "../types/fp.js"; * @param subscriptionId - A unique ID to identify this subscription. Can be used to target specific subscriptions in update operations when a customer has multiple products with the same plan. (optional) * @param cancelAction - Action to perform for cancellation. 'cancel_immediately' cancels now with prorated refund, 'cancel_end_of_cycle' cancels at period end, 'uncancel' reverses a pending cancellation. (optional) * @param noBillingChanges - If true, the subscription is updated internally without applying billing changes in Stripe. (optional) + * @param recalculateBalances - Controls whether balances should be recalculated during the subscription update. (optional) * * @returns A preview response with line items showing prorated charges or credits for the proposed changes. */ diff --git a/packages/sdk/src/funcs/billing-update.ts b/packages/sdk/src/funcs/billing-update.ts index c7c08f719..43bceea02 100644 --- a/packages/sdk/src/funcs/billing-update.ts +++ b/packages/sdk/src/funcs/billing-update.ts @@ -60,6 +60,7 @@ import { Result } from "../types/fp.js"; * @param subscriptionId - A unique ID to identify this subscription. Can be used to target specific subscriptions in update operations when a customer has multiple products with the same plan. (optional) * @param cancelAction - Action to perform for cancellation. 'cancel_immediately' cancels now with prorated refund, 'cancel_end_of_cycle' cancels at period end, 'uncancel' reverses a pending cancellation. (optional) * @param noBillingChanges - If true, the subscription is updated internally without applying billing changes in Stripe. (optional) + * @param recalculateBalances - Controls whether balances should be recalculated during the subscription update. (optional) * * @returns A billing response with customer ID, invoice details, and payment URL (if next action is required). */ diff --git a/packages/sdk/src/lib/config.ts b/packages/sdk/src/lib/config.ts index ef0ca2061..468ec0db0 100644 --- a/packages/sdk/src/lib/config.ts +++ b/packages/sdk/src/lib/config.ts @@ -67,6 +67,6 @@ export const SDK_METADATA = { language: "typescript", openapiDocVersion: "2.2.0", sdkVersion: "0.10.17", - genVersion: "2.866.2", - userAgent: "speakeasy-sdk/typescript 0.10.17 2.866.2 2.2.0 @useautumn/sdk", + genVersion: "2.824.1", + userAgent: "speakeasy-sdk/typescript 0.10.17 2.824.1 2.2.0 @useautumn/sdk", } as const; diff --git a/packages/sdk/src/lib/files.ts b/packages/sdk/src/lib/files.ts index 6ca6b37d3..0344cd046 100644 --- a/packages/sdk/src/lib/files.ts +++ b/packages/sdk/src/lib/files.ts @@ -80,25 +80,3 @@ export function getContentTypeFromFileName(fileName: string): string | null { return mimeTypes[ext] || null; } - -/** - * Creates a Blob from file content with the given MIME type. - * - * Node.js Buffers are Uint8Array subclasses that may share a pooled - * ArrayBuffer (byteOffset > 0, byteLength < buffer.byteLength). Passing - * such a Buffer directly to `new Blob([buf])` can include the entire - * underlying pool on some runtimes, producing a Blob with extra bytes - * that corrupts multipart uploads. - * - * Copying into a standalone Uint8Array ensures the Blob receives only the - * intended bytes regardless of runtime behaviour. - */ -export function bytesToBlob( - content: Uint8Array | ArrayBuffer | Blob | string, - contentType: string, -): Blob { - if (content instanceof Uint8Array) { - return new Blob([new Uint8Array(content)], { type: contentType }); - } - return new Blob([content as BlobPart], { type: contentType }); -} diff --git a/packages/sdk/src/lib/matchers.ts b/packages/sdk/src/lib/matchers.ts index 9a72b3fe2..2f22acee9 100644 --- a/packages/sdk/src/lib/matchers.ts +++ b/packages/sdk/src/lib/matchers.ts @@ -251,9 +251,8 @@ export function match( raw = body; break; default: - throw new Error( - `Unsupported response type: ${encoding satisfies never}`, - ); + encoding satisfies never; + throw new Error(`Unsupported response type: ${encoding}`); } if (matcher.enc === "fail") { diff --git a/packages/sdk/src/lib/security.ts b/packages/sdk/src/lib/security.ts index ee8dd5861..659b39acb 100644 --- a/packages/sdk/src/lib/security.ts +++ b/packages/sdk/src/lib/security.ts @@ -198,7 +198,8 @@ export function resolveSecurity( applyBearer(state, spec); break; default: - throw SecurityError.unrecognizedType((spec satisfies never, type)); + spec satisfies never; + throw SecurityError.unrecognizedType(type); } }); diff --git a/packages/sdk/src/models/billing-update-op.ts b/packages/sdk/src/models/billing-update-op.ts index 055c273ee..32ffe830b 100644 --- a/packages/sdk/src/models/billing-update-op.ts +++ b/packages/sdk/src/models/billing-update-op.ts @@ -414,6 +414,16 @@ export type BillingUpdateCancelAction = ClosedEnum< typeof BillingUpdateCancelAction >; +/** + * Controls whether balances should be recalculated during the subscription update. + */ +export type BillingUpdateRecalculateBalances = { + /** + * If true, recalculates balances during the subscription update. Only applicable when updating feature quantities. + */ + enabled: boolean; +}; + export type UpdateSubscriptionParams = { /** * The ID of the customer to attach the plan to. @@ -463,6 +473,10 @@ export type UpdateSubscriptionParams = { * If true, the subscription is updated internally without applying billing changes in Stripe. */ noBillingChanges?: boolean | undefined; + /** + * Controls whether balances should be recalculated during the subscription update. + */ + recalculateBalances?: BillingUpdateRecalculateBalances | undefined; }; /** @@ -1003,6 +1017,29 @@ export const BillingUpdateCancelAction$outboundSchema: z.ZodMiniEnum< typeof BillingUpdateCancelAction > = z.enum(BillingUpdateCancelAction); +/** @internal */ +export type BillingUpdateRecalculateBalances$Outbound = { + enabled: boolean; +}; + +/** @internal */ +export const BillingUpdateRecalculateBalances$outboundSchema: z.ZodMiniType< + BillingUpdateRecalculateBalances$Outbound, + BillingUpdateRecalculateBalances +> = z.object({ + enabled: z.boolean(), +}); + +export function billingUpdateRecalculateBalancesToJSON( + billingUpdateRecalculateBalances: BillingUpdateRecalculateBalances, +): string { + return JSON.stringify( + BillingUpdateRecalculateBalances$outboundSchema.parse( + billingUpdateRecalculateBalances, + ), + ); +} + /** @internal */ export type UpdateSubscriptionParams$Outbound = { customer_id: string; @@ -1017,6 +1054,7 @@ export type UpdateSubscriptionParams$Outbound = { subscription_id?: string | undefined; cancel_action?: string | undefined; no_billing_changes?: boolean | undefined; + recalculate_balances?: BillingUpdateRecalculateBalances$Outbound | undefined; }; /** @internal */ @@ -1046,6 +1084,9 @@ export const UpdateSubscriptionParams$outboundSchema: z.ZodMiniType< subscriptionId: z.optional(z.string()), cancelAction: z.optional(BillingUpdateCancelAction$outboundSchema), noBillingChanges: z.optional(z.boolean()), + recalculateBalances: z.optional( + z.lazy(() => BillingUpdateRecalculateBalances$outboundSchema), + ), }), z.transform((v) => { return remap$(v, { @@ -1059,6 +1100,7 @@ export const UpdateSubscriptionParams$outboundSchema: z.ZodMiniType< subscriptionId: "subscription_id", cancelAction: "cancel_action", noBillingChanges: "no_billing_changes", + recalculateBalances: "recalculate_balances", }); }), ); diff --git a/packages/sdk/src/models/create-entity-op.ts b/packages/sdk/src/models/create-entity-op.ts index 3e065c21a..44f5f23e6 100644 --- a/packages/sdk/src/models/create-entity-op.ts +++ b/packages/sdk/src/models/create-entity-op.ts @@ -6,7 +6,7 @@ import * as z from "zod/v4-mini"; import { remap as remap$ } from "../lib/primitives.js"; import { safeParse } from "../lib/schemas.js"; import * as openEnums from "../types/enums.js"; -import { OpenEnum } from "../types/enums.js"; +import { ClosedEnum, OpenEnum } from "../types/enums.js"; import { Result as SafeParseResult } from "../types/fp.js"; import * as types from "../types/primitives.js"; import { Balance, Balance$inboundSchema } from "./balance.js"; @@ -37,6 +37,43 @@ export type CreateEntitySpendLimitRequest = { overageLimit?: number | undefined; }; +/** + * Whether the threshold is an absolute usage count or a percentage of the usage allowance. + */ +export const CreateEntityThresholdTypeRequestBody = { + Usage: "usage", + UsagePercentage: "usage_percentage", +} as const; +/** + * Whether the threshold is an absolute usage count or a percentage of the usage allowance. + */ +export type CreateEntityThresholdTypeRequestBody = ClosedEnum< + typeof CreateEntityThresholdTypeRequestBody +>; + +export type CreateEntityUsageAlertRequestBody = { + /** + * The feature ID this alert applies to. If omitted, the alert applies globally. + */ + featureId?: string | undefined; + /** + * Whether this usage alert is enabled. + */ + enabled?: boolean | undefined; + /** + * The threshold value that triggers the alert. For usage, this is an absolute count. For usage_percentage, this is a percentage (0-100). + */ + threshold: number; + /** + * Whether the threshold is an absolute usage count or a percentage of the usage allowance. + */ + thresholdType: CreateEntityThresholdTypeRequestBody; + /** + * Optional user-defined label to distinguish multiple alerts on the same feature. + */ + name?: string | undefined; +}; + /** * Billing controls for the entity. */ @@ -45,6 +82,10 @@ export type CreateEntityBillingControlsRequest = { * List of overage spend limits per feature. */ spendLimits?: Array | undefined; + /** + * List of usage alert configurations per feature. + */ + usageAlerts?: Array | undefined; }; export type CreateEntityParams = { @@ -288,6 +329,43 @@ export type CreateEntitySpendLimitResponse = { overageLimit?: number | undefined; }; +/** + * Whether the threshold is an absolute usage count or a percentage of the usage allowance. + */ +export const CreateEntityThresholdTypeResponse = { + Usage: "usage", + UsagePercentage: "usage_percentage", +} as const; +/** + * Whether the threshold is an absolute usage count or a percentage of the usage allowance. + */ +export type CreateEntityThresholdTypeResponse = OpenEnum< + typeof CreateEntityThresholdTypeResponse +>; + +export type CreateEntityUsageAlertResponse = { + /** + * The feature ID this alert applies to. If omitted, the alert applies globally. + */ + featureId?: string | undefined; + /** + * Whether this usage alert is enabled. + */ + enabled: boolean; + /** + * The threshold value that triggers the alert. For usage, this is an absolute count. For usage_percentage, this is a percentage (0-100). + */ + threshold: number; + /** + * Whether the threshold is an absolute usage count or a percentage of the usage allowance. + */ + thresholdType: CreateEntityThresholdTypeResponse; + /** + * Optional user-defined label to distinguish multiple alerts on the same feature. + */ + name?: string | undefined; +}; + /** * Billing controls for the entity. */ @@ -296,6 +374,10 @@ export type CreateEntityBillingControlsResponse = { * List of overage spend limits per feature. */ spendLimits?: Array | undefined; + /** + * List of usage alert configurations per feature. + */ + usageAlerts?: Array | undefined; }; export type CreateEntityInvoice = { @@ -406,9 +488,54 @@ export function createEntitySpendLimitRequestToJSON( ); } +/** @internal */ +export const CreateEntityThresholdTypeRequestBody$outboundSchema: z.ZodMiniEnum< + typeof CreateEntityThresholdTypeRequestBody +> = z.enum(CreateEntityThresholdTypeRequestBody); + +/** @internal */ +export type CreateEntityUsageAlertRequestBody$Outbound = { + feature_id?: string | undefined; + enabled: boolean; + threshold: number; + threshold_type: string; + name?: string | undefined; +}; + +/** @internal */ +export const CreateEntityUsageAlertRequestBody$outboundSchema: z.ZodMiniType< + CreateEntityUsageAlertRequestBody$Outbound, + CreateEntityUsageAlertRequestBody +> = z.pipe( + z.object({ + featureId: z.optional(z.string()), + enabled: z._default(z.boolean(), true), + threshold: z.number(), + thresholdType: CreateEntityThresholdTypeRequestBody$outboundSchema, + name: z.optional(z.string()), + }), + z.transform((v) => { + return remap$(v, { + featureId: "feature_id", + thresholdType: "threshold_type", + }); + }), +); + +export function createEntityUsageAlertRequestBodyToJSON( + createEntityUsageAlertRequestBody: CreateEntityUsageAlertRequestBody, +): string { + return JSON.stringify( + CreateEntityUsageAlertRequestBody$outboundSchema.parse( + createEntityUsageAlertRequestBody, + ), + ); +} + /** @internal */ export type CreateEntityBillingControlsRequest$Outbound = { spend_limits?: Array | undefined; + usage_alerts?: Array | undefined; }; /** @internal */ @@ -420,10 +547,14 @@ export const CreateEntityBillingControlsRequest$outboundSchema: z.ZodMiniType< spendLimits: z.optional( z.array(z.lazy(() => CreateEntitySpendLimitRequest$outboundSchema)), ), + usageAlerts: z.optional( + z.array(z.lazy(() => CreateEntityUsageAlertRequestBody$outboundSchema)), + ), }), z.transform((v) => { return remap$(v, { spendLimits: "spend_limits", + usageAlerts: "usage_alerts", }); }), ); @@ -718,6 +849,42 @@ export function createEntitySpendLimitResponseFromJSON( ); } +/** @internal */ +export const CreateEntityThresholdTypeResponse$inboundSchema: z.ZodMiniType< + CreateEntityThresholdTypeResponse, + unknown +> = openEnums.inboundSchema(CreateEntityThresholdTypeResponse); + +/** @internal */ +export const CreateEntityUsageAlertResponse$inboundSchema: z.ZodMiniType< + CreateEntityUsageAlertResponse, + unknown +> = z.pipe( + z.object({ + feature_id: types.optional(types.string()), + enabled: z._default(types.boolean(), true), + threshold: types.number(), + threshold_type: CreateEntityThresholdTypeResponse$inboundSchema, + name: types.optional(types.string()), + }), + z.transform((v) => { + return remap$(v, { + "feature_id": "featureId", + "threshold_type": "thresholdType", + }); + }), +); + +export function createEntityUsageAlertResponseFromJSON( + jsonString: string, +): SafeParseResult { + return safeParse( + jsonString, + (x) => CreateEntityUsageAlertResponse$inboundSchema.parse(JSON.parse(x)), + `Failed to parse 'CreateEntityUsageAlertResponse' from JSON`, + ); +} + /** @internal */ export const CreateEntityBillingControlsResponse$inboundSchema: z.ZodMiniType< CreateEntityBillingControlsResponse, @@ -727,10 +894,14 @@ export const CreateEntityBillingControlsResponse$inboundSchema: z.ZodMiniType< spend_limits: types.optional( z.array(z.lazy(() => CreateEntitySpendLimitResponse$inboundSchema)), ), + usage_alerts: types.optional( + z.array(z.lazy(() => CreateEntityUsageAlertResponse$inboundSchema)), + ), }), z.transform((v) => { return remap$(v, { "spend_limits": "spendLimits", + "usage_alerts": "usageAlerts", }); }), ); diff --git a/packages/sdk/src/models/customer-data.ts b/packages/sdk/src/models/customer-data.ts index d519831f2..06b640118 100644 --- a/packages/sdk/src/models/customer-data.ts +++ b/packages/sdk/src/models/customer-data.ts @@ -76,6 +76,43 @@ export type CustomerDataSpendLimit = { overageLimit?: number | undefined; }; +/** + * Whether the threshold is an absolute usage count or a percentage of the usage allowance. + */ +export const CustomerDataThresholdType = { + Usage: "usage", + UsagePercentage: "usage_percentage", +} as const; +/** + * Whether the threshold is an absolute usage count or a percentage of the usage allowance. + */ +export type CustomerDataThresholdType = ClosedEnum< + typeof CustomerDataThresholdType +>; + +export type CustomerDataUsageAlert = { + /** + * The feature ID this alert applies to. If omitted, the alert applies globally. + */ + featureId?: string | undefined; + /** + * Whether this usage alert is enabled. + */ + enabled?: boolean | undefined; + /** + * The threshold value that triggers the alert. For usage, this is an absolute count. For usage_percentage, this is a percentage (0-100). + */ + threshold: number; + /** + * Whether the threshold is an absolute usage count or a percentage of the usage allowance. + */ + thresholdType: CustomerDataThresholdType; + /** + * Optional user-defined label to distinguish multiple alerts on the same feature. + */ + name?: string | undefined; +}; + /** * Billing controls for the customer (auto top-ups, etc.) */ @@ -88,6 +125,10 @@ export type CustomerDataBillingControls = { * List of overage spend limits per feature. */ spendLimits?: Array | undefined; + /** + * List of usage alert configurations per feature. + */ + usageAlerts?: Array | undefined; }; /** @@ -241,10 +282,53 @@ export function customerDataSpendLimitToJSON( ); } +/** @internal */ +export const CustomerDataThresholdType$outboundSchema: z.ZodMiniEnum< + typeof CustomerDataThresholdType +> = z.enum(CustomerDataThresholdType); + +/** @internal */ +export type CustomerDataUsageAlert$Outbound = { + feature_id?: string | undefined; + enabled: boolean; + threshold: number; + threshold_type: string; + name?: string | undefined; +}; + +/** @internal */ +export const CustomerDataUsageAlert$outboundSchema: z.ZodMiniType< + CustomerDataUsageAlert$Outbound, + CustomerDataUsageAlert +> = z.pipe( + z.object({ + featureId: z.optional(z.string()), + enabled: z._default(z.boolean(), true), + threshold: z.number(), + thresholdType: CustomerDataThresholdType$outboundSchema, + name: z.optional(z.string()), + }), + z.transform((v) => { + return remap$(v, { + featureId: "feature_id", + thresholdType: "threshold_type", + }); + }), +); + +export function customerDataUsageAlertToJSON( + customerDataUsageAlert: CustomerDataUsageAlert, +): string { + return JSON.stringify( + CustomerDataUsageAlert$outboundSchema.parse(customerDataUsageAlert), + ); +} + /** @internal */ export type CustomerDataBillingControls$Outbound = { auto_topups?: Array | undefined; spend_limits?: Array | undefined; + usage_alerts?: Array | undefined; }; /** @internal */ @@ -259,11 +343,15 @@ export const CustomerDataBillingControls$outboundSchema: z.ZodMiniType< spendLimits: z.optional( z.array(z.lazy(() => CustomerDataSpendLimit$outboundSchema)), ), + usageAlerts: z.optional( + z.array(z.lazy(() => CustomerDataUsageAlert$outboundSchema)), + ), }), z.transform((v) => { return remap$(v, { autoTopups: "auto_topups", spendLimits: "spend_limits", + usageAlerts: "usage_alerts", }); }), ); diff --git a/packages/sdk/src/models/customer.ts b/packages/sdk/src/models/customer.ts index 4d0e40723..0196844d6 100644 --- a/packages/sdk/src/models/customer.ts +++ b/packages/sdk/src/models/customer.ts @@ -95,6 +95,41 @@ export type CustomerSpendLimit = { overageLimit?: number | undefined; }; +/** + * Whether the threshold is an absolute usage count or a percentage of the usage allowance. + */ +export const CustomerThresholdType = { + Usage: "usage", + UsagePercentage: "usage_percentage", +} as const; +/** + * Whether the threshold is an absolute usage count or a percentage of the usage allowance. + */ +export type CustomerThresholdType = OpenEnum; + +export type CustomerUsageAlert = { + /** + * The feature ID this alert applies to. If omitted, the alert applies globally. + */ + featureId?: string | undefined; + /** + * Whether this usage alert is enabled. + */ + enabled: boolean; + /** + * The threshold value that triggers the alert. For usage, this is an absolute count. For usage_percentage, this is a percentage (0-100). + */ + threshold: number; + /** + * Whether the threshold is an absolute usage count or a percentage of the usage allowance. + */ + thresholdType: CustomerThresholdType; + /** + * Optional user-defined label to distinguish multiple alerts on the same feature. + */ + name?: string | undefined; +}; + /** * Billing controls for the customer (auto top-ups, etc.) */ @@ -107,6 +142,10 @@ export type CustomerBillingControls = { * List of overage spend limits per feature. */ spendLimits?: Array | undefined; + /** + * List of usage alert configurations per feature. + */ + usageAlerts?: Array | undefined; }; /** @@ -646,6 +685,42 @@ export function customerSpendLimitFromJSON( ); } +/** @internal */ +export const CustomerThresholdType$inboundSchema: z.ZodMiniType< + CustomerThresholdType, + unknown +> = openEnums.inboundSchema(CustomerThresholdType); + +/** @internal */ +export const CustomerUsageAlert$inboundSchema: z.ZodMiniType< + CustomerUsageAlert, + unknown +> = z.pipe( + z.object({ + feature_id: types.optional(types.string()), + enabled: z._default(types.boolean(), true), + threshold: types.number(), + threshold_type: CustomerThresholdType$inboundSchema, + name: types.optional(types.string()), + }), + z.transform((v) => { + return remap$(v, { + "feature_id": "featureId", + "threshold_type": "thresholdType", + }); + }), +); + +export function customerUsageAlertFromJSON( + jsonString: string, +): SafeParseResult { + return safeParse( + jsonString, + (x) => CustomerUsageAlert$inboundSchema.parse(JSON.parse(x)), + `Failed to parse 'CustomerUsageAlert' from JSON`, + ); +} + /** @internal */ export const CustomerBillingControls$inboundSchema: z.ZodMiniType< CustomerBillingControls, @@ -658,11 +733,15 @@ export const CustomerBillingControls$inboundSchema: z.ZodMiniType< spend_limits: types.optional( z.array(z.lazy(() => CustomerSpendLimit$inboundSchema)), ), + usage_alerts: types.optional( + z.array(z.lazy(() => CustomerUsageAlert$inboundSchema)), + ), }), z.transform((v) => { return remap$(v, { "auto_topups": "autoTopups", "spend_limits": "spendLimits", + "usage_alerts": "usageAlerts", }); }), ); diff --git a/packages/sdk/src/models/get-entity-op.ts b/packages/sdk/src/models/get-entity-op.ts index 5eba1e01d..ce36a7c97 100644 --- a/packages/sdk/src/models/get-entity-op.ts +++ b/packages/sdk/src/models/get-entity-op.ts @@ -242,6 +242,41 @@ export type GetEntitySpendLimit = { overageLimit?: number | undefined; }; +/** + * Whether the threshold is an absolute usage count or a percentage of the usage allowance. + */ +export const GetEntityThresholdType = { + Usage: "usage", + UsagePercentage: "usage_percentage", +} as const; +/** + * Whether the threshold is an absolute usage count or a percentage of the usage allowance. + */ +export type GetEntityThresholdType = OpenEnum; + +export type GetEntityUsageAlert = { + /** + * The feature ID this alert applies to. If omitted, the alert applies globally. + */ + featureId?: string | undefined; + /** + * Whether this usage alert is enabled. + */ + enabled: boolean; + /** + * The threshold value that triggers the alert. For usage, this is an absolute count. For usage_percentage, this is a percentage (0-100). + */ + threshold: number; + /** + * Whether the threshold is an absolute usage count or a percentage of the usage allowance. + */ + thresholdType: GetEntityThresholdType; + /** + * Optional user-defined label to distinguish multiple alerts on the same feature. + */ + name?: string | undefined; +}; + /** * Billing controls for the entity. */ @@ -250,6 +285,10 @@ export type GetEntityBillingControls = { * List of overage spend limits per feature. */ spendLimits?: Array | undefined; + /** + * List of usage alert configurations per feature. + */ + usageAlerts?: Array | undefined; }; export type GetEntityInvoice = { @@ -588,6 +627,42 @@ export function getEntitySpendLimitFromJSON( ); } +/** @internal */ +export const GetEntityThresholdType$inboundSchema: z.ZodMiniType< + GetEntityThresholdType, + unknown +> = openEnums.inboundSchema(GetEntityThresholdType); + +/** @internal */ +export const GetEntityUsageAlert$inboundSchema: z.ZodMiniType< + GetEntityUsageAlert, + unknown +> = z.pipe( + z.object({ + feature_id: types.optional(types.string()), + enabled: z._default(types.boolean(), true), + threshold: types.number(), + threshold_type: GetEntityThresholdType$inboundSchema, + name: types.optional(types.string()), + }), + z.transform((v) => { + return remap$(v, { + "feature_id": "featureId", + "threshold_type": "thresholdType", + }); + }), +); + +export function getEntityUsageAlertFromJSON( + jsonString: string, +): SafeParseResult { + return safeParse( + jsonString, + (x) => GetEntityUsageAlert$inboundSchema.parse(JSON.parse(x)), + `Failed to parse 'GetEntityUsageAlert' from JSON`, + ); +} + /** @internal */ export const GetEntityBillingControls$inboundSchema: z.ZodMiniType< GetEntityBillingControls, @@ -597,10 +672,14 @@ export const GetEntityBillingControls$inboundSchema: z.ZodMiniType< spend_limits: types.optional( z.array(z.lazy(() => GetEntitySpendLimit$inboundSchema)), ), + usage_alerts: types.optional( + z.array(z.lazy(() => GetEntityUsageAlert$inboundSchema)), + ), }), z.transform((v) => { return remap$(v, { "spend_limits": "spendLimits", + "usage_alerts": "usageAlerts", }); }), ); diff --git a/packages/sdk/src/models/get-or-create-customer-op.ts b/packages/sdk/src/models/get-or-create-customer-op.ts index 0d7c5de1a..67fd8b56b 100644 --- a/packages/sdk/src/models/get-or-create-customer-op.ts +++ b/packages/sdk/src/models/get-or-create-customer-op.ts @@ -82,6 +82,43 @@ export type GetOrCreateCustomerSpendLimit = { overageLimit?: number | undefined; }; +/** + * Whether the threshold is an absolute usage count or a percentage of the usage allowance. + */ +export const GetOrCreateCustomerThresholdType = { + Usage: "usage", + UsagePercentage: "usage_percentage", +} as const; +/** + * Whether the threshold is an absolute usage count or a percentage of the usage allowance. + */ +export type GetOrCreateCustomerThresholdType = ClosedEnum< + typeof GetOrCreateCustomerThresholdType +>; + +export type GetOrCreateCustomerUsageAlert = { + /** + * The feature ID this alert applies to. If omitted, the alert applies globally. + */ + featureId?: string | undefined; + /** + * Whether this usage alert is enabled. + */ + enabled?: boolean | undefined; + /** + * The threshold value that triggers the alert. For usage, this is an absolute count. For usage_percentage, this is a percentage (0-100). + */ + threshold: number; + /** + * Whether the threshold is an absolute usage count or a percentage of the usage allowance. + */ + thresholdType: GetOrCreateCustomerThresholdType; + /** + * Optional user-defined label to distinguish multiple alerts on the same feature. + */ + name?: string | undefined; +}; + /** * Billing controls for the customer (auto top-ups, etc.) */ @@ -94,6 +131,10 @@ export type GetOrCreateCustomerBillingControls = { * List of overage spend limits per feature. */ spendLimits?: Array | undefined; + /** + * List of usage alert configurations per feature. + */ + usageAlerts?: Array | undefined; }; export type GetOrCreateCustomerParams = { @@ -255,10 +296,55 @@ export function getOrCreateCustomerSpendLimitToJSON( ); } +/** @internal */ +export const GetOrCreateCustomerThresholdType$outboundSchema: z.ZodMiniEnum< + typeof GetOrCreateCustomerThresholdType +> = z.enum(GetOrCreateCustomerThresholdType); + +/** @internal */ +export type GetOrCreateCustomerUsageAlert$Outbound = { + feature_id?: string | undefined; + enabled: boolean; + threshold: number; + threshold_type: string; + name?: string | undefined; +}; + +/** @internal */ +export const GetOrCreateCustomerUsageAlert$outboundSchema: z.ZodMiniType< + GetOrCreateCustomerUsageAlert$Outbound, + GetOrCreateCustomerUsageAlert +> = z.pipe( + z.object({ + featureId: z.optional(z.string()), + enabled: z._default(z.boolean(), true), + threshold: z.number(), + thresholdType: GetOrCreateCustomerThresholdType$outboundSchema, + name: z.optional(z.string()), + }), + z.transform((v) => { + return remap$(v, { + featureId: "feature_id", + thresholdType: "threshold_type", + }); + }), +); + +export function getOrCreateCustomerUsageAlertToJSON( + getOrCreateCustomerUsageAlert: GetOrCreateCustomerUsageAlert, +): string { + return JSON.stringify( + GetOrCreateCustomerUsageAlert$outboundSchema.parse( + getOrCreateCustomerUsageAlert, + ), + ); +} + /** @internal */ export type GetOrCreateCustomerBillingControls$Outbound = { auto_topups?: Array | undefined; spend_limits?: Array | undefined; + usage_alerts?: Array | undefined; }; /** @internal */ @@ -273,11 +359,15 @@ export const GetOrCreateCustomerBillingControls$outboundSchema: z.ZodMiniType< spendLimits: z.optional( z.array(z.lazy(() => GetOrCreateCustomerSpendLimit$outboundSchema)), ), + usageAlerts: z.optional( + z.array(z.lazy(() => GetOrCreateCustomerUsageAlert$outboundSchema)), + ), }), z.transform((v) => { return remap$(v, { autoTopups: "auto_topups", spendLimits: "spend_limits", + usageAlerts: "usage_alerts", }); }), ); diff --git a/packages/sdk/src/models/list-customers-op.ts b/packages/sdk/src/models/list-customers-op.ts index ffe79c531..7c1761444 100644 --- a/packages/sdk/src/models/list-customers-op.ts +++ b/packages/sdk/src/models/list-customers-op.ts @@ -139,6 +139,43 @@ export type ListCustomersSpendLimit = { overageLimit?: number | undefined; }; +/** + * Whether the threshold is an absolute usage count or a percentage of the usage allowance. + */ +export const ListCustomersThresholdType = { + Usage: "usage", + UsagePercentage: "usage_percentage", +} as const; +/** + * Whether the threshold is an absolute usage count or a percentage of the usage allowance. + */ +export type ListCustomersThresholdType = OpenEnum< + typeof ListCustomersThresholdType +>; + +export type ListCustomersUsageAlert = { + /** + * The feature ID this alert applies to. If omitted, the alert applies globally. + */ + featureId?: string | undefined; + /** + * Whether this usage alert is enabled. + */ + enabled: boolean; + /** + * The threshold value that triggers the alert. For usage, this is an absolute count. For usage_percentage, this is a percentage (0-100). + */ + threshold: number; + /** + * Whether the threshold is an absolute usage count or a percentage of the usage allowance. + */ + thresholdType: ListCustomersThresholdType; + /** + * Optional user-defined label to distinguish multiple alerts on the same feature. + */ + name?: string | undefined; +}; + /** * Billing controls for the customer (auto top-ups, etc.) */ @@ -151,6 +188,10 @@ export type ListCustomersBillingControls = { * List of overage spend limits per feature. */ spendLimits?: Array | undefined; + /** + * List of usage alert configurations per feature. + */ + usageAlerts?: Array | undefined; }; /** @@ -588,6 +629,42 @@ export function listCustomersSpendLimitFromJSON( ); } +/** @internal */ +export const ListCustomersThresholdType$inboundSchema: z.ZodMiniType< + ListCustomersThresholdType, + unknown +> = openEnums.inboundSchema(ListCustomersThresholdType); + +/** @internal */ +export const ListCustomersUsageAlert$inboundSchema: z.ZodMiniType< + ListCustomersUsageAlert, + unknown +> = z.pipe( + z.object({ + feature_id: types.optional(types.string()), + enabled: z._default(types.boolean(), true), + threshold: types.number(), + threshold_type: ListCustomersThresholdType$inboundSchema, + name: types.optional(types.string()), + }), + z.transform((v) => { + return remap$(v, { + "feature_id": "featureId", + "threshold_type": "thresholdType", + }); + }), +); + +export function listCustomersUsageAlertFromJSON( + jsonString: string, +): SafeParseResult { + return safeParse( + jsonString, + (x) => ListCustomersUsageAlert$inboundSchema.parse(JSON.parse(x)), + `Failed to parse 'ListCustomersUsageAlert' from JSON`, + ); +} + /** @internal */ export const ListCustomersBillingControls$inboundSchema: z.ZodMiniType< ListCustomersBillingControls, @@ -600,11 +677,15 @@ export const ListCustomersBillingControls$inboundSchema: z.ZodMiniType< spend_limits: types.optional( z.array(z.lazy(() => ListCustomersSpendLimit$inboundSchema)), ), + usage_alerts: types.optional( + z.array(z.lazy(() => ListCustomersUsageAlert$inboundSchema)), + ), }), z.transform((v) => { return remap$(v, { "auto_topups": "autoTopups", "spend_limits": "spendLimits", + "usage_alerts": "usageAlerts", }); }), ); diff --git a/packages/sdk/src/models/multi-attach-op.ts b/packages/sdk/src/models/multi-attach-op.ts index 637e66fa7..e7b052550 100644 --- a/packages/sdk/src/models/multi-attach-op.ts +++ b/packages/sdk/src/models/multi-attach-op.ts @@ -434,6 +434,43 @@ export type MultiAttachSpendLimit = { overageLimit?: number | undefined; }; +/** + * Whether the threshold is an absolute usage count or a percentage of the usage allowance. + */ +export const MultiAttachThresholdType = { + Usage: "usage", + UsagePercentage: "usage_percentage", +} as const; +/** + * Whether the threshold is an absolute usage count or a percentage of the usage allowance. + */ +export type MultiAttachThresholdType = ClosedEnum< + typeof MultiAttachThresholdType +>; + +export type MultiAttachUsageAlert = { + /** + * The feature ID this alert applies to. If omitted, the alert applies globally. + */ + featureId?: string | undefined; + /** + * Whether this usage alert is enabled. + */ + enabled?: boolean | undefined; + /** + * The threshold value that triggers the alert. For usage, this is an absolute count. For usage_percentage, this is a percentage (0-100). + */ + threshold: number; + /** + * Whether the threshold is an absolute usage count or a percentage of the usage allowance. + */ + thresholdType: MultiAttachThresholdType; + /** + * Optional user-defined label to distinguish multiple alerts on the same feature. + */ + name?: string | undefined; +}; + /** * Billing controls for the entity. */ @@ -442,6 +479,10 @@ export type MultiAttachBillingControls = { * List of overage spend limits per feature. */ spendLimits?: Array | undefined; + /** + * List of usage alert configurations per feature. + */ + usageAlerts?: Array | undefined; }; export type MultiAttachEntityData = { @@ -1116,9 +1157,52 @@ export function multiAttachSpendLimitToJSON( ); } +/** @internal */ +export const MultiAttachThresholdType$outboundSchema: z.ZodMiniEnum< + typeof MultiAttachThresholdType +> = z.enum(MultiAttachThresholdType); + +/** @internal */ +export type MultiAttachUsageAlert$Outbound = { + feature_id?: string | undefined; + enabled: boolean; + threshold: number; + threshold_type: string; + name?: string | undefined; +}; + +/** @internal */ +export const MultiAttachUsageAlert$outboundSchema: z.ZodMiniType< + MultiAttachUsageAlert$Outbound, + MultiAttachUsageAlert +> = z.pipe( + z.object({ + featureId: z.optional(z.string()), + enabled: z._default(z.boolean(), true), + threshold: z.number(), + thresholdType: MultiAttachThresholdType$outboundSchema, + name: z.optional(z.string()), + }), + z.transform((v) => { + return remap$(v, { + featureId: "feature_id", + thresholdType: "threshold_type", + }); + }), +); + +export function multiAttachUsageAlertToJSON( + multiAttachUsageAlert: MultiAttachUsageAlert, +): string { + return JSON.stringify( + MultiAttachUsageAlert$outboundSchema.parse(multiAttachUsageAlert), + ); +} + /** @internal */ export type MultiAttachBillingControls$Outbound = { spend_limits?: Array | undefined; + usage_alerts?: Array | undefined; }; /** @internal */ @@ -1130,10 +1214,14 @@ export const MultiAttachBillingControls$outboundSchema: z.ZodMiniType< spendLimits: z.optional( z.array(z.lazy(() => MultiAttachSpendLimit$outboundSchema)), ), + usageAlerts: z.optional( + z.array(z.lazy(() => MultiAttachUsageAlert$outboundSchema)), + ), }), z.transform((v) => { return remap$(v, { spendLimits: "spend_limits", + usageAlerts: "usage_alerts", }); }), ); diff --git a/packages/sdk/src/models/preview-attach-op.ts b/packages/sdk/src/models/preview-attach-op.ts index f0a16ec5a..69b603db9 100644 --- a/packages/sdk/src/models/preview-attach-op.ts +++ b/packages/sdk/src/models/preview-attach-op.ts @@ -749,6 +749,14 @@ export type PreviewAttachIncoming = { * When this change takes effect, in milliseconds since the Unix epoch, or null if it applies immediately. */ effectiveAt: number | null; + /** + * When this plan was canceled, in milliseconds since the Unix epoch, or null if it is not canceled. + */ + canceledAt: number | null; + /** + * When this plan expires, in milliseconds since the Unix epoch, or null if it does not expire. + */ + expiresAt: number | null; }; export type PreviewAttachOutgoingFeatureQuantity = { @@ -776,6 +784,14 @@ export type PreviewAttachOutgoing = { * When this change takes effect, in milliseconds since the Unix epoch, or null if it applies immediately. */ effectiveAt: number | null; + /** + * When this plan was canceled, in milliseconds since the Unix epoch, or null if it is not canceled. + */ + canceledAt: number | null; + /** + * When this plan expires, in milliseconds since the Unix epoch, or null if it does not expire. + */ + expiresAt: number | null; }; /** @@ -1803,12 +1819,16 @@ export const PreviewAttachIncoming$inboundSchema: z.ZodMiniType< z.lazy(() => PreviewAttachIncomingFeatureQuantity$inboundSchema), ), effective_at: types.nullable(types.number()), + canceled_at: types.nullable(types.number()), + expires_at: types.nullable(types.number()), }), z.transform((v) => { return remap$(v, { "plan_id": "planId", "feature_quantities": "featureQuantities", "effective_at": "effectiveAt", + "canceled_at": "canceledAt", + "expires_at": "expiresAt", }); }), ); @@ -1862,12 +1882,16 @@ export const PreviewAttachOutgoing$inboundSchema: z.ZodMiniType< z.lazy(() => PreviewAttachOutgoingFeatureQuantity$inboundSchema), ), effective_at: types.nullable(types.number()), + canceled_at: types.nullable(types.number()), + expires_at: types.nullable(types.number()), }), z.transform((v) => { return remap$(v, { "plan_id": "planId", "feature_quantities": "featureQuantities", "effective_at": "effectiveAt", + "canceled_at": "canceledAt", + "expires_at": "expiresAt", }); }), ); diff --git a/packages/sdk/src/models/preview-multi-attach-op.ts b/packages/sdk/src/models/preview-multi-attach-op.ts index 84255104a..16920a58e 100644 --- a/packages/sdk/src/models/preview-multi-attach-op.ts +++ b/packages/sdk/src/models/preview-multi-attach-op.ts @@ -438,6 +438,43 @@ export type PreviewMultiAttachSpendLimit = { overageLimit?: number | undefined; }; +/** + * Whether the threshold is an absolute usage count or a percentage of the usage allowance. + */ +export const PreviewMultiAttachThresholdType = { + Usage: "usage", + UsagePercentage: "usage_percentage", +} as const; +/** + * Whether the threshold is an absolute usage count or a percentage of the usage allowance. + */ +export type PreviewMultiAttachThresholdType = ClosedEnum< + typeof PreviewMultiAttachThresholdType +>; + +export type PreviewMultiAttachUsageAlert = { + /** + * The feature ID this alert applies to. If omitted, the alert applies globally. + */ + featureId?: string | undefined; + /** + * Whether this usage alert is enabled. + */ + enabled?: boolean | undefined; + /** + * The threshold value that triggers the alert. For usage, this is an absolute count. For usage_percentage, this is a percentage (0-100). + */ + threshold: number; + /** + * Whether the threshold is an absolute usage count or a percentage of the usage allowance. + */ + thresholdType: PreviewMultiAttachThresholdType; + /** + * Optional user-defined label to distinguish multiple alerts on the same feature. + */ + name?: string | undefined; +}; + /** * Billing controls for the entity. */ @@ -446,6 +483,10 @@ export type PreviewMultiAttachBillingControls = { * List of overage spend limits per feature. */ spendLimits?: Array | undefined; + /** + * List of usage alert configurations per feature. + */ + usageAlerts?: Array | undefined; }; export type PreviewMultiAttachEntityData = { @@ -715,6 +756,14 @@ export type PreviewMultiAttachIncoming = { * When this change takes effect, in milliseconds since the Unix epoch, or null if it applies immediately. */ effectiveAt: number | null; + /** + * When this plan was canceled, in milliseconds since the Unix epoch, or null if it is not canceled. + */ + canceledAt: number | null; + /** + * When this plan expires, in milliseconds since the Unix epoch, or null if it does not expire. + */ + expiresAt: number | null; }; export type PreviewMultiAttachOutgoingFeatureQuantity = { @@ -742,6 +791,14 @@ export type PreviewMultiAttachOutgoing = { * When this change takes effect, in milliseconds since the Unix epoch, or null if it applies immediately. */ effectiveAt: number | null; + /** + * When this plan was canceled, in milliseconds since the Unix epoch, or null if it is not canceled. + */ + canceledAt: number | null; + /** + * When this plan expires, in milliseconds since the Unix epoch, or null if it does not expire. + */ + expiresAt: number | null; }; /** @@ -1358,9 +1415,54 @@ export function previewMultiAttachSpendLimitToJSON( ); } +/** @internal */ +export const PreviewMultiAttachThresholdType$outboundSchema: z.ZodMiniEnum< + typeof PreviewMultiAttachThresholdType +> = z.enum(PreviewMultiAttachThresholdType); + +/** @internal */ +export type PreviewMultiAttachUsageAlert$Outbound = { + feature_id?: string | undefined; + enabled: boolean; + threshold: number; + threshold_type: string; + name?: string | undefined; +}; + +/** @internal */ +export const PreviewMultiAttachUsageAlert$outboundSchema: z.ZodMiniType< + PreviewMultiAttachUsageAlert$Outbound, + PreviewMultiAttachUsageAlert +> = z.pipe( + z.object({ + featureId: z.optional(z.string()), + enabled: z._default(z.boolean(), true), + threshold: z.number(), + thresholdType: PreviewMultiAttachThresholdType$outboundSchema, + name: z.optional(z.string()), + }), + z.transform((v) => { + return remap$(v, { + featureId: "feature_id", + thresholdType: "threshold_type", + }); + }), +); + +export function previewMultiAttachUsageAlertToJSON( + previewMultiAttachUsageAlert: PreviewMultiAttachUsageAlert, +): string { + return JSON.stringify( + PreviewMultiAttachUsageAlert$outboundSchema.parse( + previewMultiAttachUsageAlert, + ), + ); +} + /** @internal */ export type PreviewMultiAttachBillingControls$Outbound = { spend_limits?: Array | undefined; + usage_alerts?: Array | undefined; }; /** @internal */ @@ -1372,10 +1474,14 @@ export const PreviewMultiAttachBillingControls$outboundSchema: z.ZodMiniType< spendLimits: z.optional( z.array(z.lazy(() => PreviewMultiAttachSpendLimit$outboundSchema)), ), + usageAlerts: z.optional( + z.array(z.lazy(() => PreviewMultiAttachUsageAlert$outboundSchema)), + ), }), z.transform((v) => { return remap$(v, { spendLimits: "spend_limits", + usageAlerts: "usage_alerts", }); }), ); @@ -1812,12 +1918,16 @@ export const PreviewMultiAttachIncoming$inboundSchema: z.ZodMiniType< z.lazy(() => PreviewMultiAttachIncomingFeatureQuantity$inboundSchema), ), effective_at: types.nullable(types.number()), + canceled_at: types.nullable(types.number()), + expires_at: types.nullable(types.number()), }), z.transform((v) => { return remap$(v, { "plan_id": "planId", "feature_quantities": "featureQuantities", "effective_at": "effectiveAt", + "canceled_at": "canceledAt", + "expires_at": "expiresAt", }); }), ); @@ -1874,12 +1984,16 @@ export const PreviewMultiAttachOutgoing$inboundSchema: z.ZodMiniType< z.lazy(() => PreviewMultiAttachOutgoingFeatureQuantity$inboundSchema), ), effective_at: types.nullable(types.number()), + canceled_at: types.nullable(types.number()), + expires_at: types.nullable(types.number()), }), z.transform((v) => { return remap$(v, { "plan_id": "planId", "feature_quantities": "featureQuantities", "effective_at": "effectiveAt", + "canceled_at": "canceledAt", + "expires_at": "expiresAt", }); }), ); diff --git a/packages/sdk/src/models/preview-update-op.ts b/packages/sdk/src/models/preview-update-op.ts index bc3526adf..c6884ba5f 100644 --- a/packages/sdk/src/models/preview-update-op.ts +++ b/packages/sdk/src/models/preview-update-op.ts @@ -415,6 +415,16 @@ export type PreviewUpdateCancelAction = ClosedEnum< typeof PreviewUpdateCancelAction >; +/** + * Controls whether balances should be recalculated during the subscription update. + */ +export type PreviewUpdateRecalculateBalances = { + /** + * If true, recalculates balances during the subscription update. Only applicable when updating feature quantities. + */ + enabled: boolean; +}; + export type PreviewUpdateParams = { /** * The ID of the customer to attach the plan to. @@ -464,6 +474,10 @@ export type PreviewUpdateParams = { * If true, the subscription is updated internally without applying billing changes in Stripe. */ noBillingChanges?: boolean | undefined; + /** + * Controls whether balances should be recalculated during the subscription update. + */ + recalculateBalances?: PreviewUpdateRecalculateBalances | undefined; }; export type PreviewUpdateDiscount = { @@ -670,6 +684,14 @@ export type PreviewUpdateIncoming = { * When this change takes effect, in milliseconds since the Unix epoch, or null if it applies immediately. */ effectiveAt: number | null; + /** + * When this plan was canceled, in milliseconds since the Unix epoch, or null if it is not canceled. + */ + canceledAt: number | null; + /** + * When this plan expires, in milliseconds since the Unix epoch, or null if it does not expire. + */ + expiresAt: number | null; }; export type PreviewUpdateOutgoingFeatureQuantity = { @@ -697,6 +719,14 @@ export type PreviewUpdateOutgoing = { * When this change takes effect, in milliseconds since the Unix epoch, or null if it applies immediately. */ effectiveAt: number | null; + /** + * When this plan was canceled, in milliseconds since the Unix epoch, or null if it is not canceled. + */ + canceledAt: number | null; + /** + * When this plan expires, in milliseconds since the Unix epoch, or null if it does not expire. + */ + expiresAt: number | null; }; export const Intent = { @@ -1211,6 +1241,29 @@ export const PreviewUpdateCancelAction$outboundSchema: z.ZodMiniEnum< typeof PreviewUpdateCancelAction > = z.enum(PreviewUpdateCancelAction); +/** @internal */ +export type PreviewUpdateRecalculateBalances$Outbound = { + enabled: boolean; +}; + +/** @internal */ +export const PreviewUpdateRecalculateBalances$outboundSchema: z.ZodMiniType< + PreviewUpdateRecalculateBalances$Outbound, + PreviewUpdateRecalculateBalances +> = z.object({ + enabled: z.boolean(), +}); + +export function previewUpdateRecalculateBalancesToJSON( + previewUpdateRecalculateBalances: PreviewUpdateRecalculateBalances, +): string { + return JSON.stringify( + PreviewUpdateRecalculateBalances$outboundSchema.parse( + previewUpdateRecalculateBalances, + ), + ); +} + /** @internal */ export type PreviewUpdateParams$Outbound = { customer_id: string; @@ -1227,6 +1280,7 @@ export type PreviewUpdateParams$Outbound = { subscription_id?: string | undefined; cancel_action?: string | undefined; no_billing_changes?: boolean | undefined; + recalculate_balances?: PreviewUpdateRecalculateBalances$Outbound | undefined; }; /** @internal */ @@ -1256,6 +1310,9 @@ export const PreviewUpdateParams$outboundSchema: z.ZodMiniType< subscriptionId: z.optional(z.string()), cancelAction: z.optional(PreviewUpdateCancelAction$outboundSchema), noBillingChanges: z.optional(z.boolean()), + recalculateBalances: z.optional( + z.lazy(() => PreviewUpdateRecalculateBalances$outboundSchema), + ), }), z.transform((v) => { return remap$(v, { @@ -1269,6 +1326,7 @@ export const PreviewUpdateParams$outboundSchema: z.ZodMiniType< subscriptionId: "subscription_id", cancelAction: "cancel_action", noBillingChanges: "no_billing_changes", + recalculateBalances: "recalculate_balances", }); }), ); @@ -1585,12 +1643,16 @@ export const PreviewUpdateIncoming$inboundSchema: z.ZodMiniType< z.lazy(() => PreviewUpdateIncomingFeatureQuantity$inboundSchema), ), effective_at: types.nullable(types.number()), + canceled_at: types.nullable(types.number()), + expires_at: types.nullable(types.number()), }), z.transform((v) => { return remap$(v, { "plan_id": "planId", "feature_quantities": "featureQuantities", "effective_at": "effectiveAt", + "canceled_at": "canceledAt", + "expires_at": "expiresAt", }); }), ); @@ -1644,12 +1706,16 @@ export const PreviewUpdateOutgoing$inboundSchema: z.ZodMiniType< z.lazy(() => PreviewUpdateOutgoingFeatureQuantity$inboundSchema), ), effective_at: types.nullable(types.number()), + canceled_at: types.nullable(types.number()), + expires_at: types.nullable(types.number()), }), z.transform((v) => { return remap$(v, { "plan_id": "planId", "feature_quantities": "featureQuantities", "effective_at": "effectiveAt", + "canceled_at": "canceledAt", + "expires_at": "expiresAt", }); }), ); diff --git a/packages/sdk/src/models/update-customer-op.ts b/packages/sdk/src/models/update-customer-op.ts index bcd66af95..64d04d0ee 100644 --- a/packages/sdk/src/models/update-customer-op.ts +++ b/packages/sdk/src/models/update-customer-op.ts @@ -89,6 +89,43 @@ export type UpdateCustomerSpendLimitRequest = { overageLimit?: number | undefined; }; +/** + * Whether the threshold is an absolute usage count or a percentage of the usage allowance. + */ +export const UpdateCustomerThresholdTypeRequestBody = { + Usage: "usage", + UsagePercentage: "usage_percentage", +} as const; +/** + * Whether the threshold is an absolute usage count or a percentage of the usage allowance. + */ +export type UpdateCustomerThresholdTypeRequestBody = ClosedEnum< + typeof UpdateCustomerThresholdTypeRequestBody +>; + +export type UpdateCustomerUsageAlertRequestBody = { + /** + * The feature ID this alert applies to. If omitted, the alert applies globally. + */ + featureId?: string | undefined; + /** + * Whether this usage alert is enabled. + */ + enabled?: boolean | undefined; + /** + * The threshold value that triggers the alert. For usage, this is an absolute count. For usage_percentage, this is a percentage (0-100). + */ + threshold: number; + /** + * Whether the threshold is an absolute usage count or a percentage of the usage allowance. + */ + thresholdType: UpdateCustomerThresholdTypeRequestBody; + /** + * Optional user-defined label to distinguish multiple alerts on the same feature. + */ + name?: string | undefined; +}; + /** * Billing controls for the customer (auto top-ups, etc.) */ @@ -101,6 +138,10 @@ export type UpdateCustomerBillingControlsRequest = { * List of overage spend limits per feature. */ spendLimits?: Array | undefined; + /** + * List of usage alert configurations per feature. + */ + usageAlerts?: Array | undefined; }; export type UpdateCustomerParams = { @@ -226,6 +267,43 @@ export type UpdateCustomerSpendLimitResponse = { overageLimit?: number | undefined; }; +/** + * Whether the threshold is an absolute usage count or a percentage of the usage allowance. + */ +export const UpdateCustomerThresholdTypeResponse = { + Usage: "usage", + UsagePercentage: "usage_percentage", +} as const; +/** + * Whether the threshold is an absolute usage count or a percentage of the usage allowance. + */ +export type UpdateCustomerThresholdTypeResponse = OpenEnum< + typeof UpdateCustomerThresholdTypeResponse +>; + +export type UpdateCustomerUsageAlertResponse = { + /** + * The feature ID this alert applies to. If omitted, the alert applies globally. + */ + featureId?: string | undefined; + /** + * Whether this usage alert is enabled. + */ + enabled: boolean; + /** + * The threshold value that triggers the alert. For usage, this is an absolute count. For usage_percentage, this is a percentage (0-100). + */ + threshold: number; + /** + * Whether the threshold is an absolute usage count or a percentage of the usage allowance. + */ + thresholdType: UpdateCustomerThresholdTypeResponse; + /** + * Optional user-defined label to distinguish multiple alerts on the same feature. + */ + name?: string | undefined; +}; + /** * Billing controls for the customer (auto top-ups, etc.) */ @@ -238,6 +316,10 @@ export type UpdateCustomerBillingControlsResponse = { * List of overage spend limits per feature. */ spendLimits?: Array | undefined; + /** + * List of usage alert configurations per feature. + */ + usageAlerts?: Array | undefined; }; /** @@ -604,10 +686,58 @@ export function updateCustomerSpendLimitRequestToJSON( ); } +/** @internal */ +export const UpdateCustomerThresholdTypeRequestBody$outboundSchema: + z.ZodMiniEnum = z.enum( + UpdateCustomerThresholdTypeRequestBody, + ); + +/** @internal */ +export type UpdateCustomerUsageAlertRequestBody$Outbound = { + feature_id?: string | undefined; + enabled: boolean; + threshold: number; + threshold_type: string; + name?: string | undefined; +}; + +/** @internal */ +export const UpdateCustomerUsageAlertRequestBody$outboundSchema: z.ZodMiniType< + UpdateCustomerUsageAlertRequestBody$Outbound, + UpdateCustomerUsageAlertRequestBody +> = z.pipe( + z.object({ + featureId: z.optional(z.string()), + enabled: z._default(z.boolean(), true), + threshold: z.number(), + thresholdType: UpdateCustomerThresholdTypeRequestBody$outboundSchema, + name: z.optional(z.string()), + }), + z.transform((v) => { + return remap$(v, { + featureId: "feature_id", + thresholdType: "threshold_type", + }); + }), +); + +export function updateCustomerUsageAlertRequestBodyToJSON( + updateCustomerUsageAlertRequestBody: UpdateCustomerUsageAlertRequestBody, +): string { + return JSON.stringify( + UpdateCustomerUsageAlertRequestBody$outboundSchema.parse( + updateCustomerUsageAlertRequestBody, + ), + ); +} + /** @internal */ export type UpdateCustomerBillingControlsRequest$Outbound = { auto_topups?: Array | undefined; spend_limits?: Array | undefined; + usage_alerts?: + | Array + | undefined; }; /** @internal */ @@ -622,11 +752,15 @@ export const UpdateCustomerBillingControlsRequest$outboundSchema: z.ZodMiniType< spendLimits: z.optional( z.array(z.lazy(() => UpdateCustomerSpendLimitRequest$outboundSchema)), ), + usageAlerts: z.optional( + z.array(z.lazy(() => UpdateCustomerUsageAlertRequestBody$outboundSchema)), + ), }), z.transform((v) => { return remap$(v, { autoTopups: "auto_topups", spendLimits: "spend_limits", + usageAlerts: "usage_alerts", }); }), ); @@ -791,6 +925,42 @@ export function updateCustomerSpendLimitResponseFromJSON( ); } +/** @internal */ +export const UpdateCustomerThresholdTypeResponse$inboundSchema: z.ZodMiniType< + UpdateCustomerThresholdTypeResponse, + unknown +> = openEnums.inboundSchema(UpdateCustomerThresholdTypeResponse); + +/** @internal */ +export const UpdateCustomerUsageAlertResponse$inboundSchema: z.ZodMiniType< + UpdateCustomerUsageAlertResponse, + unknown +> = z.pipe( + z.object({ + feature_id: types.optional(types.string()), + enabled: z._default(types.boolean(), true), + threshold: types.number(), + threshold_type: UpdateCustomerThresholdTypeResponse$inboundSchema, + name: types.optional(types.string()), + }), + z.transform((v) => { + return remap$(v, { + "feature_id": "featureId", + "threshold_type": "thresholdType", + }); + }), +); + +export function updateCustomerUsageAlertResponseFromJSON( + jsonString: string, +): SafeParseResult { + return safeParse( + jsonString, + (x) => UpdateCustomerUsageAlertResponse$inboundSchema.parse(JSON.parse(x)), + `Failed to parse 'UpdateCustomerUsageAlertResponse' from JSON`, + ); +} + /** @internal */ export const UpdateCustomerBillingControlsResponse$inboundSchema: z.ZodMiniType< UpdateCustomerBillingControlsResponse, @@ -803,11 +973,15 @@ export const UpdateCustomerBillingControlsResponse$inboundSchema: z.ZodMiniType< spend_limits: types.optional( z.array(z.lazy(() => UpdateCustomerSpendLimitResponse$inboundSchema)), ), + usage_alerts: types.optional( + z.array(z.lazy(() => UpdateCustomerUsageAlertResponse$inboundSchema)), + ), }), z.transform((v) => { return remap$(v, { "auto_topups": "autoTopups", "spend_limits": "spendLimits", + "usage_alerts": "usageAlerts", }); }), ); diff --git a/packages/sdk/src/models/update-entity-op.ts b/packages/sdk/src/models/update-entity-op.ts index 1761c6366..a3974d0fb 100644 --- a/packages/sdk/src/models/update-entity-op.ts +++ b/packages/sdk/src/models/update-entity-op.ts @@ -6,7 +6,7 @@ import * as z from "zod/v4-mini"; import { remap as remap$ } from "../lib/primitives.js"; import { safeParse } from "../lib/schemas.js"; import * as openEnums from "../types/enums.js"; -import { OpenEnum } from "../types/enums.js"; +import { ClosedEnum, OpenEnum } from "../types/enums.js"; import { Result as SafeParseResult } from "../types/fp.js"; import * as types from "../types/primitives.js"; import { Balance, Balance$inboundSchema } from "./balance.js"; @@ -32,6 +32,43 @@ export type UpdateEntitySpendLimitRequest = { overageLimit?: number | undefined; }; +/** + * Whether the threshold is an absolute usage count or a percentage of the usage allowance. + */ +export const UpdateEntityThresholdTypeRequestBody = { + Usage: "usage", + UsagePercentage: "usage_percentage", +} as const; +/** + * Whether the threshold is an absolute usage count or a percentage of the usage allowance. + */ +export type UpdateEntityThresholdTypeRequestBody = ClosedEnum< + typeof UpdateEntityThresholdTypeRequestBody +>; + +export type UpdateEntityUsageAlertRequestBody = { + /** + * The feature ID this alert applies to. If omitted, the alert applies globally. + */ + featureId?: string | undefined; + /** + * Whether this usage alert is enabled. + */ + enabled?: boolean | undefined; + /** + * The threshold value that triggers the alert. For usage, this is an absolute count. For usage_percentage, this is a percentage (0-100). + */ + threshold: number; + /** + * Whether the threshold is an absolute usage count or a percentage of the usage allowance. + */ + thresholdType: UpdateEntityThresholdTypeRequestBody; + /** + * Optional user-defined label to distinguish multiple alerts on the same feature. + */ + name?: string | undefined; +}; + /** * Billing controls to replace on the entity. */ @@ -40,6 +77,10 @@ export type UpdateEntityBillingControlsRequest = { * List of overage spend limits per feature. */ spendLimits?: Array | undefined; + /** + * List of usage alert configurations per feature. + */ + usageAlerts?: Array | undefined; }; export type UpdateEntityParams = { @@ -271,6 +312,43 @@ export type UpdateEntitySpendLimitResponse = { overageLimit?: number | undefined; }; +/** + * Whether the threshold is an absolute usage count or a percentage of the usage allowance. + */ +export const UpdateEntityThresholdTypeResponse = { + Usage: "usage", + UsagePercentage: "usage_percentage", +} as const; +/** + * Whether the threshold is an absolute usage count or a percentage of the usage allowance. + */ +export type UpdateEntityThresholdTypeResponse = OpenEnum< + typeof UpdateEntityThresholdTypeResponse +>; + +export type UpdateEntityUsageAlertResponse = { + /** + * The feature ID this alert applies to. If omitted, the alert applies globally. + */ + featureId?: string | undefined; + /** + * Whether this usage alert is enabled. + */ + enabled: boolean; + /** + * The threshold value that triggers the alert. For usage, this is an absolute count. For usage_percentage, this is a percentage (0-100). + */ + threshold: number; + /** + * Whether the threshold is an absolute usage count or a percentage of the usage allowance. + */ + thresholdType: UpdateEntityThresholdTypeResponse; + /** + * Optional user-defined label to distinguish multiple alerts on the same feature. + */ + name?: string | undefined; +}; + /** * Billing controls for the entity. */ @@ -279,6 +357,10 @@ export type UpdateEntityBillingControlsResponse = { * List of overage spend limits per feature. */ spendLimits?: Array | undefined; + /** + * List of usage alert configurations per feature. + */ + usageAlerts?: Array | undefined; }; export type UpdateEntityInvoice = { @@ -389,9 +471,54 @@ export function updateEntitySpendLimitRequestToJSON( ); } +/** @internal */ +export const UpdateEntityThresholdTypeRequestBody$outboundSchema: z.ZodMiniEnum< + typeof UpdateEntityThresholdTypeRequestBody +> = z.enum(UpdateEntityThresholdTypeRequestBody); + +/** @internal */ +export type UpdateEntityUsageAlertRequestBody$Outbound = { + feature_id?: string | undefined; + enabled: boolean; + threshold: number; + threshold_type: string; + name?: string | undefined; +}; + +/** @internal */ +export const UpdateEntityUsageAlertRequestBody$outboundSchema: z.ZodMiniType< + UpdateEntityUsageAlertRequestBody$Outbound, + UpdateEntityUsageAlertRequestBody +> = z.pipe( + z.object({ + featureId: z.optional(z.string()), + enabled: z._default(z.boolean(), true), + threshold: z.number(), + thresholdType: UpdateEntityThresholdTypeRequestBody$outboundSchema, + name: z.optional(z.string()), + }), + z.transform((v) => { + return remap$(v, { + featureId: "feature_id", + thresholdType: "threshold_type", + }); + }), +); + +export function updateEntityUsageAlertRequestBodyToJSON( + updateEntityUsageAlertRequestBody: UpdateEntityUsageAlertRequestBody, +): string { + return JSON.stringify( + UpdateEntityUsageAlertRequestBody$outboundSchema.parse( + updateEntityUsageAlertRequestBody, + ), + ); +} + /** @internal */ export type UpdateEntityBillingControlsRequest$Outbound = { spend_limits?: Array | undefined; + usage_alerts?: Array | undefined; }; /** @internal */ @@ -403,10 +530,14 @@ export const UpdateEntityBillingControlsRequest$outboundSchema: z.ZodMiniType< spendLimits: z.optional( z.array(z.lazy(() => UpdateEntitySpendLimitRequest$outboundSchema)), ), + usageAlerts: z.optional( + z.array(z.lazy(() => UpdateEntityUsageAlertRequestBody$outboundSchema)), + ), }), z.transform((v) => { return remap$(v, { spendLimits: "spend_limits", + usageAlerts: "usage_alerts", }); }), ); @@ -693,6 +824,42 @@ export function updateEntitySpendLimitResponseFromJSON( ); } +/** @internal */ +export const UpdateEntityThresholdTypeResponse$inboundSchema: z.ZodMiniType< + UpdateEntityThresholdTypeResponse, + unknown +> = openEnums.inboundSchema(UpdateEntityThresholdTypeResponse); + +/** @internal */ +export const UpdateEntityUsageAlertResponse$inboundSchema: z.ZodMiniType< + UpdateEntityUsageAlertResponse, + unknown +> = z.pipe( + z.object({ + feature_id: types.optional(types.string()), + enabled: z._default(types.boolean(), true), + threshold: types.number(), + threshold_type: UpdateEntityThresholdTypeResponse$inboundSchema, + name: types.optional(types.string()), + }), + z.transform((v) => { + return remap$(v, { + "feature_id": "featureId", + "threshold_type": "thresholdType", + }); + }), +); + +export function updateEntityUsageAlertResponseFromJSON( + jsonString: string, +): SafeParseResult { + return safeParse( + jsonString, + (x) => UpdateEntityUsageAlertResponse$inboundSchema.parse(JSON.parse(x)), + `Failed to parse 'UpdateEntityUsageAlertResponse' from JSON`, + ); +} + /** @internal */ export const UpdateEntityBillingControlsResponse$inboundSchema: z.ZodMiniType< UpdateEntityBillingControlsResponse, @@ -702,10 +869,14 @@ export const UpdateEntityBillingControlsResponse$inboundSchema: z.ZodMiniType< spend_limits: types.optional( z.array(z.lazy(() => UpdateEntitySpendLimitResponse$inboundSchema)), ), + usage_alerts: types.optional( + z.array(z.lazy(() => UpdateEntityUsageAlertResponse$inboundSchema)), + ), }), z.transform((v) => { return remap$(v, { "spend_limits": "spendLimits", + "usage_alerts": "usageAlerts", }); }), ); diff --git a/packages/sdk/src/sdk/billing.ts b/packages/sdk/src/sdk/billing.ts index 28e980d78..7891ff9bc 100644 --- a/packages/sdk/src/sdk/billing.ts +++ b/packages/sdk/src/sdk/billing.ts @@ -232,6 +232,7 @@ export class Billing extends ClientSDK { * @param subscriptionId - A unique ID to identify this subscription. Can be used to target specific subscriptions in update operations when a customer has multiple products with the same plan. (optional) * @param cancelAction - Action to perform for cancellation. 'cancel_immediately' cancels now with prorated refund, 'cancel_end_of_cycle' cancels at period end, 'uncancel' reverses a pending cancellation. (optional) * @param noBillingChanges - If true, the subscription is updated internally without applying billing changes in Stripe. (optional) + * @param recalculateBalances - Controls whether balances should be recalculated during the subscription update. (optional) * * @returns A billing response with customer ID, invoice details, and payment URL (if next action is required). */ @@ -269,6 +270,7 @@ export class Billing extends ClientSDK { * @param subscriptionId - A unique ID to identify this subscription. Can be used to target specific subscriptions in update operations when a customer has multiple products with the same plan. (optional) * @param cancelAction - Action to perform for cancellation. 'cancel_immediately' cancels now with prorated refund, 'cancel_end_of_cycle' cancels at period end, 'uncancel' reverses a pending cancellation. (optional) * @param noBillingChanges - If true, the subscription is updated internally without applying billing changes in Stripe. (optional) + * @param recalculateBalances - Controls whether balances should be recalculated during the subscription update. (optional) * * @returns A preview response with line items showing prorated charges or credits for the proposed changes. */ diff --git a/packages/sdk/tsconfig.json b/packages/sdk/tsconfig.json index 76110f883..0ccdbe286 100644 --- a/packages/sdk/tsconfig.json +++ b/packages/sdk/tsconfig.json @@ -13,7 +13,6 @@ "declaration": true, "declarationMap": true, "sourceMap": true, - "rootDir": "src", "outDir": ".", @@ -37,5 +36,5 @@ "forceConsistentCasingInFileNames": true }, "include": ["src"], - "exclude": ["node_modules", "src/__tests__"] + "exclude": ["node_modules"] } diff --git a/server/src/_luaScriptsV2/customers/updateCustomerData.lua b/server/src/_luaScriptsV2/customers/updateCustomerData.lua index 570acb58d..9b4762908 100644 --- a/server/src/_luaScriptsV2/customers/updateCustomerData.lua +++ b/server/src/_luaScriptsV2/customers/updateCustomerData.lua @@ -17,7 +17,8 @@ processor?: object | null, processors?: object | null, auto_topups?: array | null, - spend_limits?: array | null + spend_limits?: array | null, + usage_alerts?: array | null } } @@ -111,4 +112,13 @@ if updates.spend_limits ~= nil then table.insert(updated_fields, 'spend_limits') end +if updates.usage_alerts ~= nil then + if is_nil(updates.usage_alerts) then + redis.call('JSON.SET', cache_key, '$.usage_alerts', 'null') + else + redis.call('JSON.SET', cache_key, '$.usage_alerts', cjson.encode(updates.usage_alerts)) + end + table.insert(updated_fields, 'usage_alerts') +end + return cjson.encode({ success = true, updated_fields = updated_fields }) diff --git a/server/src/external/autumn/autumnWebhookRouter.ts b/server/src/external/autumn/autumnWebhookRouter.ts index 185a21004..a5f111081 100644 --- a/server/src/external/autumn/autumnWebhookRouter.ts +++ b/server/src/external/autumn/autumnWebhookRouter.ts @@ -1,4 +1,4 @@ -import { ErrCode, WebhookEventType } from "@autumn/shared"; +import { ErrCode } from "@autumn/shared"; import { Hono } from "hono"; import { Webhook } from "svix"; import type { HonoEnv } from "@/honoUtils/HonoEnv.js"; @@ -58,17 +58,19 @@ autumnWebhookRouter.post("", async (c) => { console.log("Received webhook from autumn"); const { type, data } = evt; - switch (type) { - case WebhookEventType.CustomerProductsUpdated: - console.log( - `Type: ${type}, Scenario: ${data?.scenario}, Product: ${(data?.updated_product as { id?: string })?.id}`, - ); - break; - case WebhookEventType.CustomerThresholdReached: - console.log(`Type: ${type}`); - console.log(`Feature: `, data?.feature); - break; - } + console.log("EVENT:", JSON.stringify(evt, null, 2)); + + // switch (type) { + // case WebhookEventType.CustomerProductsUpdated: + // console.log( + // `Type: ${type}, Scenario: ${data?.scenario}, Product: ${(data?.updated_product as { id?: string })?.id}`, + // ); + // break; + // case WebhookEventType.CustomerThresholdReached: + // console.log(`Type: ${type}`); + // console.log(`Feature: `, data?.feature); + // break; + // } return c.json({ success: true, message: "Webhook received" }, 200); } catch (_error) { diff --git a/server/src/external/svix/svixHelpers.ts b/server/src/external/svix/svixHelpers.ts index c2724bf10..83302847e 100644 --- a/server/src/external/svix/svixHelpers.ts +++ b/server/src/external/svix/svixHelpers.ts @@ -1,4 +1,7 @@ import type { AppEnv, Organization } from "@autumn/shared"; +import * as Sentry from "@sentry/bun"; +import type { AutumnContext } from "@/honoUtils/HonoEnv.js"; +import { getSentryTags } from "@/external/sentry/sentryUtils.js"; import { createSvixCli, getSvixAppId, safeSvix } from "./svixUtils.js"; export const createSvixApp = safeSvix({ @@ -11,7 +14,7 @@ export const createSvixApp = safeSvix({ name: string; orgId: string; env: AppEnv; - meta?: Record; + meta?: Record; }) => { const svix = createSvixCli(); const app = await svix.application.create({ @@ -35,23 +38,26 @@ export const deleteSvixApp = safeSvix({ action: "deleteSvixApp", }); -export const sendSvixEvent = safeSvix({ - fn: async ({ - org, - env, - eventType, - data, - }: { - org: Organization; - env: AppEnv; - eventType: string; - data: any; - }) => { +export const sendSvixEvent = async ({ + ctx, + eventType, + data, +}: { + ctx: AutumnContext; + eventType: string; + data: unknown; +}) => { + if (!process.env.SVIX_API_KEY) return; + + const { org, env } = ctx; + + try { + ctx.logger.info(`[svix] Firing webhook: ${eventType}`); + const svix = createSvixCli(); const appId = getSvixAppId({ org, env }); - if (!appId) { - return null; - } + if (!appId) return null; + return await svix.message.create(appId, { eventType, payload: { @@ -59,9 +65,13 @@ export const sendSvixEvent = safeSvix({ data, }, }); - }, - action: "sendSvixEvent", -}); + } catch (error) { + ctx.logger.error(`[svix] Failed to send ${eventType}: ${error}`); + Sentry.captureException(error, { + tags: getSentryTags({ ctx }), + }); + } +}; export const sendCustomSvixEvent = safeSvix({ fn: async ({ @@ -76,7 +86,7 @@ export const sendCustomSvixEvent = safeSvix({ org: Organization; env: AppEnv; eventType: string; - data: any; + data: unknown; appId: string; }) => { const svix = createSvixCli(); diff --git a/server/src/internal/analytics/handlers/handleProductsUpdated.ts b/server/src/internal/analytics/handlers/handleProductsUpdated.ts index 6e4205762..77ca1cecd 100644 --- a/server/src/internal/analytics/handlers/handleProductsUpdated.ts +++ b/server/src/internal/analytics/handlers/handleProductsUpdated.ts @@ -195,8 +195,7 @@ export const handleProductsUpdated = async ({ `sending customer.products.updated webhook, customer ID: ${data.customerId}, entity ID: ${fullCus.entity?.id || "none"}`, ); await sendSvixEvent({ - org, - env, + ctx, eventType: "customer.products.updated", data: { scenario, diff --git a/server/src/internal/api/check/checkUtils/getV2CheckResponse.ts b/server/src/internal/api/check/checkUtils/getV2CheckResponse.ts index 1538ee9a9..92c168fcd 100644 --- a/server/src/internal/api/check/checkUtils/getV2CheckResponse.ts +++ b/server/src/internal/api/check/checkUtils/getV2CheckResponse.ts @@ -54,7 +54,7 @@ export const getV2CheckResponse = async ({ apiSubject, feature: featureToUse, requiredBalance, - }) + }).allowed : false; return CheckResponseV3Schema.parse({ diff --git a/server/src/internal/balances/trackWebhooks/checkLimitReached.ts b/server/src/internal/balances/trackWebhooks/checkLimitReached.ts new file mode 100644 index 000000000..d04f0d35c --- /dev/null +++ b/server/src/internal/balances/trackWebhooks/checkLimitReached.ts @@ -0,0 +1,123 @@ +import { + type ApiCustomerV5, + type ApiEntityV2, + apiBalanceToAllowed, + type Feature, + type FullCustomer, + WebhookEventType, +} from "@autumn/shared"; +import { sendSvixEvent } from "@/external/svix/svixHelpers.js"; +import type { AutumnContext } from "@/honoUtils/HonoEnv.js"; +import { getApiCustomerBase } from "@/internal/customers/cusUtils/apiCusUtils/getApiCustomerBase.js"; +import { getApiEntityBase } from "@/internal/entities/entityUtils/apiEntityUtils/getApiEntityBase.js"; + +const checkLimitForSubject = async ({ + ctx, + oldFullCus, + newFullCus, + feature, + entityId, +}: { + ctx: AutumnContext; + oldFullCus: FullCustomer; + newFullCus: FullCustomer; + feature: Feature; + entityId?: string; +}) => { + const entity = entityId + ? newFullCus.entities?.find((e) => e.id === entityId) + : undefined; + + let oldSubject: ApiCustomerV5 | ApiEntityV2 | undefined; + let newSubject: ApiCustomerV5 | ApiEntityV2 | undefined; + + if (entity) { + const { apiEntity: oldApiEntity } = await getApiEntityBase({ + ctx, + entity, + fullCus: oldFullCus, + }); + const { apiEntity: newApiEntity } = await getApiEntityBase({ + ctx, + entity, + fullCus: newFullCus, + }); + oldSubject = oldApiEntity; + newSubject = newApiEntity; + } else { + const { apiCustomer: oldApiCustomer } = await getApiCustomerBase({ + ctx, + fullCus: oldFullCus, + }); + const { apiCustomer: newApiCustomer } = await getApiCustomerBase({ + ctx, + fullCus: newFullCus, + }); + oldSubject = oldApiCustomer; + newSubject = newApiCustomer; + } + + const oldBalance = oldSubject.balances?.[feature.id]; + const newBalance = newSubject.balances?.[feature.id]; + + if (!oldBalance || !newBalance) return; + + const oldResult = apiBalanceToAllowed({ + apiBalance: oldBalance, + apiSubject: oldSubject, + feature, + requiredBalance: 0.0000001, + }); + + const newResult = apiBalanceToAllowed({ + apiBalance: newBalance, + apiSubject: newSubject, + feature, + requiredBalance: 0.0000001, + }); + + if (!oldResult.allowed || newResult.allowed) return; + + const customerId = newFullCus.id || newFullCus.internal_id; + + await sendSvixEvent({ + ctx, + eventType: WebhookEventType.BalancesLimitReached, + data: { + customer_id: customerId, + feature_id: feature.id, + limit_type: newResult.limitType ?? "included", + ...(entityId && { entity_id: entityId }), + }, + }); + + ctx.logger.info( + `Limit reached for customer ${customerId}, feature ${feature.id}, type ${newResult.limitType ?? "included"}${entityId ? `, entity ${entityId}` : ""}`, + ); +}; + +export const checkLimitReached = async ({ + ctx, + oldFullCus, + newFullCus, + feature, + entityId, +}: { + ctx: AutumnContext; + oldFullCus: FullCustomer; + newFullCus: FullCustomer; + feature: Feature; + entityId?: string; +}) => { + try { + await checkLimitForSubject({ + ctx, + oldFullCus, + newFullCus, + feature, + entityId, + }); + } catch (error) { + ctx.logger.error(`[checkLimitReached] error: ${error}`, { error }); + } +}; diff --git a/server/src/internal/balances/thresholdReached/checkUsageAlerts.ts b/server/src/internal/balances/trackWebhooks/checkUsageAlerts.ts similarity index 70% rename from server/src/internal/balances/thresholdReached/checkUsageAlerts.ts rename to server/src/internal/balances/trackWebhooks/checkUsageAlerts.ts index 933f253c1..7002f7059 100644 --- a/server/src/internal/balances/thresholdReached/checkUsageAlerts.ts +++ b/server/src/internal/balances/trackWebhooks/checkUsageAlerts.ts @@ -25,11 +25,13 @@ const wasThresholdCrossed = ({ oldGrantedBalance: number; newGrantedBalance: number; }) => { - if (alert.threshold_type === "usage_threshold") { - return oldUsage < alert.threshold && newUsage >= alert.threshold; + if (alert.threshold_type === "usage") { + const shldAlert = oldUsage < alert.threshold && newUsage >= alert.threshold; + + return shldAlert; } - // usage_percentage_threshold + // usage_percentage if (oldGrantedBalance <= 0 || newGrantedBalance <= 0) return false; const oldPercentage = new Decimal(oldUsage) @@ -44,21 +46,27 @@ const wasThresholdCrossed = ({ return oldPercentage < alert.threshold && newPercentage >= alert.threshold; }; -export const checkUsageAlerts = async ({ +const processAlerts = async ({ ctx, oldFullCus, newFullCus, feature, + entityId, }: { ctx: AutumnContext; oldFullCus: FullCustomer; newFullCus: FullCustomer; feature: Feature; + entityId?: string; }) => { - const usageAlerts = newFullCus.usage_alerts; - if (!usageAlerts || usageAlerts.length === 0) return; + const entity = entityId + ? newFullCus.entities?.find((e) => e.id === entityId) + : undefined; - const matchingAlerts = usageAlerts.filter( + const alerts = entity ? entity.usage_alerts : newFullCus.usage_alerts; + if (!alerts || alerts.length === 0) return; + + const matchingAlerts = alerts.filter( (alert) => alert.enabled && (alert.feature_id === feature.id || !alert.feature_id), ); @@ -68,11 +76,13 @@ export const checkUsageAlerts = async ({ const oldCustomerEntitlements = fullCustomerToCustomerEntitlements({ fullCustomer: oldFullCus, featureId: feature.id, + entity, }); const newCustomerEntitlements = fullCustomerToCustomerEntitlements({ fullCustomer: newFullCus, featureId: feature.id, + entity, }); const oldUsage = cusEntsToUsage({ cusEnts: oldCustomerEntitlements }); @@ -105,13 +115,12 @@ export const checkUsageAlerts = async ({ const customerId = newFullCus.id || newFullCus.internal_id; await sendSvixEvent({ - org: ctx.org, - env: ctx.env, - eventType: WebhookEventType.BalancesThresholdReached, + ctx, + eventType: WebhookEventType.BalancesUsageAlertTriggered, data: { customer_id: customerId, feature_id: feature.id, - threshold_type: "usage_alert", + ...(entityId && { entity_id: entityId }), usage_alert: { name: alert.name, threshold: alert.threshold, @@ -121,7 +130,28 @@ export const checkUsageAlerts = async ({ }); ctx.logger.info( - `Usage alert triggered for customer ${customerId}, feature ${feature.id}, threshold ${alert.threshold} (${alert.threshold_type})`, + `Usage alert triggered for customer ${customerId}, feature ${feature.id}, threshold ${alert.threshold} (${alert.threshold_type})${entityId ? `, entity ${entityId}` : ""}`, ); } }; + +export const checkUsageAlerts = async ({ + ctx, + oldFullCus, + newFullCus, + feature, + entityId, +}: { + ctx: AutumnContext; + oldFullCus: FullCustomer; + newFullCus: FullCustomer; + feature: Feature; + entityId?: string; +}) => { + // 1. Customer-level alerts (always checked, no entity scoping) + await processAlerts({ ctx, oldFullCus, newFullCus, feature }); + + // 2. Entity-level alerts (only when entityId is provided) + if (!entityId) return; + await processAlerts({ ctx, oldFullCus, newFullCus, feature, entityId }); +}; diff --git a/server/src/internal/balances/trackWebhooks/fireTrackWebhooks.ts b/server/src/internal/balances/trackWebhooks/fireTrackWebhooks.ts new file mode 100644 index 000000000..cd91245a9 --- /dev/null +++ b/server/src/internal/balances/trackWebhooks/fireTrackWebhooks.ts @@ -0,0 +1,48 @@ +import type { Feature, FullCustomer } from "@autumn/shared"; +import type { AutumnContext } from "@/honoUtils/HonoEnv.js"; +import { checkUsageAlerts } from "./checkUsageAlerts.js"; +import { handleThresholdReached } from "./handleThresholdReached.js"; +import { checkLimitReached } from "./checkLimitReached.js"; + +export const fireTrackWebhooks = ({ + ctx, + oldFullCus, + newFullCus, + feature, + entityId, +}: { + ctx: AutumnContext; + oldFullCus: FullCustomer; + newFullCus: FullCustomer; + feature: Feature; + entityId?: string; +}) => { + handleThresholdReached({ + ctx, + oldFullCus, + newFullCus, + feature, + }).catch((error) => { + ctx.logger.error(`[fireTrackWebhooks] handleThresholdReached: ${error}`); + }); + + checkUsageAlerts({ + ctx, + oldFullCus, + newFullCus, + feature, + entityId, + }).catch((error) => { + ctx.logger.error(`[fireTrackWebhooks] checkUsageAlerts: ${error}`); + }); + + checkLimitReached({ + ctx, + oldFullCus, + newFullCus, + feature, + entityId, + }).catch((error) => { + ctx.logger.error(`[fireTrackWebhooks] checkLimitReached: ${error}`); + }); +}; diff --git a/server/src/internal/balances/thresholdReached/handleThresholdReached.ts b/server/src/internal/balances/trackWebhooks/handleThresholdReached.ts similarity index 68% rename from server/src/internal/balances/thresholdReached/handleThresholdReached.ts rename to server/src/internal/balances/trackWebhooks/handleThresholdReached.ts index 87e628148..2be74591b 100644 --- a/server/src/internal/balances/thresholdReached/handleThresholdReached.ts +++ b/server/src/internal/balances/trackWebhooks/handleThresholdReached.ts @@ -68,56 +68,42 @@ const handleAllowanceUsed = async ({ const prevCusFeature = prevApiCustomer.balances[feature.id]; const newCusFeature = newApiCustomer.balances[feature.id]; - const oldAllowed = apiBalanceToAllowed({ + const { allowed: oldAllowed } = apiBalanceToAllowed({ apiBalance: prevCusFeature, apiSubject: prevApiCustomer, feature, requiredBalance: 1, }); - const newAllowed = apiBalanceToAllowed({ + const { allowed: newAllowed } = apiBalanceToAllowed({ apiBalance: newCusFeature, apiSubject: newApiCustomer, feature, requiredBalance: 1, }); - if (oldAllowed === true && newAllowed === false) { - const customerId = newFullCus.id || newFullCus.internal_id; - - await Promise.all([ - sendSvixEvent({ - org: ctx.org, - env: ctx.env, - eventType: WebhookEventType.CustomerThresholdReached, - data: { - threshold_type: "allowance_used", - customer: cleanApiCustomer({ - ctx, - apiCustomer: newApiCustomer, - legacyData: newLegacyData, - }), - feature: dbToApiFeatureV1({ - ctx, - dbFeature: feature, - targetVersion: ctx.apiVersion, - }), - }, - }), - sendSvixEvent({ - org: ctx.org, - env: ctx.env, - eventType: WebhookEventType.BalancesThresholdReached, - data: { - customer_id: customerId, - feature_id: feature.id, - threshold_type: "allowance_used", - }, - }), - ]); + if (oldAllowed && !newAllowed) { + await sendSvixEvent({ + ctx, + eventType: WebhookEventType.CustomerThresholdReached, + data: { + threshold_type: "allowance_used", + customer: cleanApiCustomer({ + ctx, + apiCustomer: newApiCustomer, + legacyData: newLegacyData, + }), + feature: dbToApiFeatureV1({ + ctx, + dbFeature: feature, + targetVersion: ctx.apiVersion, + }), + }, + }); } }; +/** @deprecated Use checkUsageAlerts / checkLimitReached instead */ export const handleThresholdReached = async ({ ctx, oldFullCus, @@ -153,54 +139,38 @@ export const handleThresholdReached = async ({ fullCus: newFullCus, }); - const oldAllowed = apiBalanceToAllowed({ + const { allowed: oldAllowed } = apiBalanceToAllowed({ apiBalance: prevApiCustomer.balances[feature.id], apiSubject: prevApiCustomer, feature, requiredBalance: 1, }); - const newAllowed = apiBalanceToAllowed({ + const { allowed: newAllowed } = apiBalanceToAllowed({ apiBalance: newApiCustomer.balances[feature.id], apiSubject: newApiCustomer, feature, requiredBalance: 1, }); - if (oldAllowed === true && newAllowed === false) { - const customerId = newFullCus.id || newFullCus.internal_id; - - await Promise.all([ - sendSvixEvent({ - org: ctx.org, - env: ctx.env, - eventType: WebhookEventType.CustomerThresholdReached, - data: { - threshold_type: "limit_reached", - customer: cleanApiCustomer({ - ctx, - apiCustomer: newApiCustomer, - legacyData: newLegacyData, - }), - feature: dbToApiFeatureV1({ - ctx, - dbFeature: feature, - targetVersion: ctx.apiVersion, - }), - }, - }), - sendSvixEvent({ - org: ctx.org, - env: ctx.env, - eventType: WebhookEventType.BalancesThresholdReached, - data: { - customer_id: customerId, - feature_id: feature.id, - threshold_type: "limit_reached", - }, - }), - ]); - + if (oldAllowed && !newAllowed) { + await sendSvixEvent({ + ctx, + eventType: WebhookEventType.CustomerThresholdReached, + data: { + threshold_type: "limit_reached", + customer: cleanApiCustomer({ + ctx, + apiCustomer: newApiCustomer, + legacyData: newLegacyData, + }), + feature: dbToApiFeatureV1({ + ctx, + dbFeature: feature, + targetVersion: ctx.apiVersion, + }), + }, + }); ctx.logger.info( "Sent Svix event for threshold reached (type: limit_reached)", ); @@ -212,10 +182,9 @@ export const handleThresholdReached = async ({ oldFullCus, newFullCus, }); - } catch (error: any) { - ctx.logger.error("Failed to handle threshold reached", { + } catch (error) { + ctx.logger.error(`Failed to handle threshold reached, error: ${error}`, { error, - message: error?.message, }); } }; diff --git a/server/src/internal/balances/utils/deduction/executePostgresDeduction.ts b/server/src/internal/balances/utils/deduction/executePostgresDeduction.ts index 23d29e3f8..d688995d4 100644 --- a/server/src/internal/balances/utils/deduction/executePostgresDeduction.ts +++ b/server/src/internal/balances/utils/deduction/executePostgresDeduction.ts @@ -16,8 +16,7 @@ import type { DeductionUpdate } from "../../utils/types/deductionUpdate.js"; import type { FeatureDeduction } from "../../utils/types/featureDeduction.js"; import type { MutationLogItem } from "../../utils/types/mutationLogItem.js"; import { createAllocatedInvoice } from "../allocatedInvoice/createAllocatedInvoice.js"; -import { checkUsageAlerts } from "../../thresholdReached/checkUsageAlerts.js"; -import { handleThresholdReached } from "../../thresholdReached/handleThresholdReached.js"; +import { fireTrackWebhooks } from "../../trackWebhooks/fireTrackWebhooks.js"; import type { DeductionOptions } from "../types/deductionTypes.js"; import { applyRolloverUpdatesToFullCustomer } from "./applyRolloverUpdatesToFullCustomer.js"; import { @@ -229,26 +228,12 @@ export const executePostgresDeduction = async ({ throw error; } - handleThresholdReached({ + fireTrackWebhooks({ ctx, oldFullCus, newFullCus: fullCustomer, feature: deduction.feature, - }).catch((error) => { - ctx.logger.error( - `[executePostgresDeduction] Failed to handle threshold reached: ${error}`, - ); - }); - - checkUsageAlerts({ - ctx, - oldFullCus, - newFullCus: fullCustomer, - feature: deduction.feature, - }).catch((error) => { - ctx.logger.error( - `[executePostgresDeduction] Failed to check usage alerts: ${error}`, - ); + entityId, }); if (resolvedOptions.triggerAutoTopUp) { diff --git a/server/src/internal/balances/utils/deduction/executeRedisDeduction.ts b/server/src/internal/balances/utils/deduction/executeRedisDeduction.ts index c37f6fc10..9279ee35f 100644 --- a/server/src/internal/balances/utils/deduction/executeRedisDeduction.ts +++ b/server/src/internal/balances/utils/deduction/executeRedisDeduction.ts @@ -10,8 +10,7 @@ import { handlePaidAllocatedCusEnt } from "@/internal/balances/utils/paidAllocat import { rollbackDeduction } from "@/internal/balances/utils/paidAllocatedFeature/rollbackDeduction.js"; import { buildFullCustomerCacheKey } from "@/internal/customers/cusUtils/fullCustomerCacheUtils/fullCustomerCacheConfig.js"; import { tryRedisWrite } from "@/utils/cacheUtils/cacheUtils.js"; -import { checkUsageAlerts } from "../../thresholdReached/checkUsageAlerts.js"; -import { handleThresholdReached } from "../../thresholdReached/handleThresholdReached.js"; +import { fireTrackWebhooks } from "../../trackWebhooks/fireTrackWebhooks.js"; import type { DeductionOptions } from "../types/deductionTypes.js"; import type { DeductionUpdate } from "../types/deductionUpdate.js"; import type { FeatureDeduction } from "../types/featureDeduction.js"; @@ -236,26 +235,12 @@ export const executeRedisDeduction = async ({ throw error; } - handleThresholdReached({ + fireTrackWebhooks({ ctx, oldFullCus, newFullCus: fullCustomer, feature: deduction.feature, - }).catch((error) => { - ctx.logger.error( - `[executeRedisDeduction] Failed to handle threshold reached: ${error}`, - ); - }); - - checkUsageAlerts({ - ctx, - oldFullCus, - newFullCus: fullCustomer, - feature: deduction.feature, - }).catch((error) => { - ctx.logger.error( - `[executeRedisDeduction] Failed to check usage alerts: ${error}`, - ); + entityId, }); if (options.triggerAutoTopUp) { diff --git a/server/src/internal/billing/v2/workflows/sendProductsUpdated/sendProductsUpdated.ts b/server/src/internal/billing/v2/workflows/sendProductsUpdated/sendProductsUpdated.ts index 6f4d78c01..12a743974 100644 --- a/server/src/internal/billing/v2/workflows/sendProductsUpdated/sendProductsUpdated.ts +++ b/server/src/internal/billing/v2/workflows/sendProductsUpdated/sendProductsUpdated.ts @@ -37,7 +37,7 @@ export const sendProductsUpdated = async ({ ctx: AutumnContext; payload: SendProductsUpdatedPayload; }) => { - const { db, org, env, features, logger } = ctx; + const { features, logger } = ctx; const { customerProductId, scenario, customerId } = payload; // Fetch FullCustomer @@ -139,8 +139,7 @@ export const sendProductsUpdated = async ({ ); await sendSvixEvent({ - org, - env, + ctx, eventType: "customer.products.updated", data: { scenario, diff --git a/server/src/internal/customers/cusUtils/fullCustomerCacheUtils/updateCachedCustomerData.ts b/server/src/internal/customers/cusUtils/fullCustomerCacheUtils/updateCachedCustomerData.ts index 3047724e1..20f620d09 100644 --- a/server/src/internal/customers/cusUtils/fullCustomerCacheUtils/updateCachedCustomerData.ts +++ b/server/src/internal/customers/cusUtils/fullCustomerCacheUtils/updateCachedCustomerData.ts @@ -22,6 +22,7 @@ type CustomerDataUpdates = Pick< | "processors" | "auto_topups" | "spend_limits" + | "usage_alerts" >; /** diff --git a/server/src/internal/customers/cusUtils/fullCustomerCacheUtils/updateEntityInCache.ts b/server/src/internal/customers/cusUtils/fullCustomerCacheUtils/updateEntityInCache.ts index 635d45c9e..88be31a22 100644 --- a/server/src/internal/customers/cusUtils/fullCustomerCacheUtils/updateEntityInCache.ts +++ b/server/src/internal/customers/cusUtils/fullCustomerCacheUtils/updateEntityInCache.ts @@ -36,7 +36,7 @@ export const updateEntityInCache = async ({ ctx: AutumnContext; customerId: string; idOrInternalId: string; - updates: Partial>; + updates: Partial>; }): Promise => { try { if (Object.keys(updates).length === 0) { diff --git a/server/src/internal/customers/cusUtils/initCustomer.ts b/server/src/internal/customers/cusUtils/initCustomer.ts index ae809f37e..8ab40b74b 100644 --- a/server/src/internal/customers/cusUtils/initCustomer.ts +++ b/server/src/internal/customers/cusUtils/initCustomer.ts @@ -36,6 +36,7 @@ const initCustomer = ({ send_email_receipts: customerData?.send_email_receipts ?? false, auto_topups: customerData?.billing_controls?.auto_topups, spend_limits: customerData?.billing_controls?.spend_limits, + usage_alerts: customerData?.billing_controls?.usage_alerts, }; }; diff --git a/server/src/internal/entities/actions/batchCreateEntities.ts b/server/src/internal/entities/actions/batchCreateEntities.ts index 36564e9ce..f0ee6fae6 100644 --- a/server/src/internal/entities/actions/batchCreateEntities.ts +++ b/server/src/internal/entities/actions/batchCreateEntities.ts @@ -75,6 +75,7 @@ export const batchCreateEntities = async ({ name: inputEntities[0].name, ...(inputEntities[0].billing_controls && { spend_limits: inputEntities[0].billing_controls.spend_limits, + usage_alerts: inputEntities[0].billing_controls.usage_alerts, }), }, }); diff --git a/server/src/internal/entities/actions/updateEntity.ts b/server/src/internal/entities/actions/updateEntity.ts index 7563e8c93..34606cd3c 100644 --- a/server/src/internal/entities/actions/updateEntity.ts +++ b/server/src/internal/entities/actions/updateEntity.ts @@ -44,6 +44,7 @@ export const updateEntity = async ({ entity, updates: { spend_limits: billing_controls?.spend_limits, + usage_alerts: billing_controls?.usage_alerts, }, }); diff --git a/server/src/internal/entities/actions/updateEntityDbAndCache.ts b/server/src/internal/entities/actions/updateEntityDbAndCache.ts index 6bc0e05a5..e5483f7a9 100644 --- a/server/src/internal/entities/actions/updateEntityDbAndCache.ts +++ b/server/src/internal/entities/actions/updateEntityDbAndCache.ts @@ -12,11 +12,11 @@ export const updateEntityDbAndCache = async ({ ctx: AutumnContext; customerId: string; entity: Entity; - updates: Partial>; + updates: Partial>; }) => { const filteredUpdates = Object.fromEntries( Object.entries(updates).filter(([, value]) => value !== undefined), - ) as Partial>; + ) as Partial>; if (Object.keys(filteredUpdates).length === 0) { return entity; diff --git a/server/src/internal/entities/entityUtils/apiEntityUtils/getApiEntityBase.ts b/server/src/internal/entities/entityUtils/apiEntityUtils/getApiEntityBase.ts index 37a93b9c1..555e6a0de 100644 --- a/server/src/internal/entities/entityUtils/apiEntityUtils/getApiEntityBase.ts +++ b/server/src/internal/entities/entityUtils/apiEntityUtils/getApiEntityBase.ts @@ -72,7 +72,10 @@ export const getApiEntityBase = async ({ purchases: apiPurchases, balances: apiBalances, flags: apiFlags, - billing_controls: { spend_limits: entity.spend_limits ?? undefined }, + billing_controls: { + spend_limits: entity.spend_limits ?? undefined, + usage_alerts: entity.usage_alerts ?? undefined, + }, } satisfies ApiEntityV2); return { diff --git a/server/src/internal/entities/entityUtils/entityUtils.ts b/server/src/internal/entities/entityUtils/entityUtils.ts index f18ebb7af..eda4bbde6 100644 --- a/server/src/internal/entities/entityUtils/entityUtils.ts +++ b/server/src/internal/entities/entityUtils/entityUtils.ts @@ -33,6 +33,7 @@ export const constructEntity = ({ deleted, created_at: Date.now(), spend_limits: inputEntity.billing_controls?.spend_limits, + usage_alerts: inputEntity.billing_controls?.usage_alerts, }; return entity; diff --git a/server/src/internal/entities/handlers/handleListEntities.ts b/server/src/internal/entities/handlers/handleListEntities.ts index f3d0018fd..cfd6895b5 100644 --- a/server/src/internal/entities/handlers/handleListEntities.ts +++ b/server/src/internal/entities/handlers/handleListEntities.ts @@ -13,10 +13,15 @@ export const handleListEntities = createRoute({ }); return c.json({ - list: fullCus.entities.map(({ spend_limits, ...entity }) => ({ - ...entity, - billing_controls: { spend_limits: spend_limits ?? undefined }, - })), + list: fullCus.entities.map( + ({ spend_limits, usage_alerts, ...entity }) => ({ + ...entity, + billing_controls: { + spend_limits: spend_limits ?? undefined, + usage_alerts: usage_alerts ?? undefined, + }, + }), + ), }); }, }); diff --git a/server/tests/integration/balances/track/limit-reached/limit-reached-customer.test.ts b/server/tests/integration/balances/track/limit-reached/limit-reached-customer.test.ts new file mode 100644 index 000000000..718cf2252 --- /dev/null +++ b/server/tests/integration/balances/track/limit-reached/limit-reached-customer.test.ts @@ -0,0 +1,353 @@ +/** + * Integration tests for the `balances.limit_reached` webhook at the customer level. + * + * Verifies that the webhook fires when a customer's balance transitions from + * allowed → not allowed, with the correct `limit_type` for each scenario: + * - included: free allowance exhausted + * - max_purchase: consumable overage cap reached + * - spend_limit: customer-level spend limit reached + * + * Also verifies no-fire / no-refire behavior. + */ + +import { afterAll, beforeAll, expect, test } from "bun:test"; +import { + getPlayHistory, + getTestSvixAppId, + parseEventBody, + setupWebhookTest, + type WebhookTestSetup, + waitForWebhook, +} from "@tests/integration/utils/svixWebhookTestUtils.js"; +import { TestFeature } from "@tests/setup/v2Features.js"; +import { items } from "@tests/utils/fixtures/items.js"; +import { products } from "@tests/utils/fixtures/products.js"; +import ctx from "@tests/utils/testInitUtils/createTestContext.js"; +import { initScenario, s } from "@tests/utils/testInitUtils/initScenario.js"; +import chalk from "chalk"; +import { setCustomerSpendLimit } from "../../utils/spend-limit-utils/customerSpendLimitUtils.js"; + +type BalancesLimitReachedPayload = { + type: string; + data: { + customer_id: string; + feature_id: string; + limit_type: string; + entity_id?: string; + }; +}; + +// ═══════════════════════════════════════════════════════════════════════════════ +// SVIX PLAY SETUP +// ═══════════════════════════════════════════════════════════════════════════════ + +let webhook: WebhookTestSetup; +let playToken: string; + +beforeAll(async () => { + const appId = getTestSvixAppId({ svixConfig: ctx.org.svix_config }); + webhook = await setupWebhookTest({ + appId, + filterTypes: ["balances.limit_reached"], + }); + playToken = webhook.playToken; +}); + +afterAll(async () => { + await webhook?.cleanup(); +}); + +// ═══════════════════════════════════════════════════════════════════════════════ +// TEST 1: included — free allowance exhausted triggers webhook +// ═══════════════════════════════════════════════════════════════════════════════ + +test.concurrent(`${chalk.yellowBright("limit-reached-cus1: included allowance exhausted fires webhook")}`, async () => { + const messagesItem = items.monthlyMessages({ includedUsage: 100 }); + const freeProd = products.base({ + id: "lr-included-1", + items: [messagesItem], + }); + + const { customerId, autumnV2_1 } = await initScenario({ + customerId: "lr-included-cus-1", + setup: [s.customer({ testClock: false }), s.products({ list: [freeProd] })], + actions: [s.attach({ productId: freeProd.id })], + }); + + await autumnV2_1.track({ + customer_id: customerId, + feature_id: TestFeature.Messages, + value: 100, + }); + + const result = await waitForWebhook({ + token: playToken, + predicate: (payload) => + payload.type === "balances.limit_reached" && + payload.data?.customer_id === customerId && + payload.data?.limit_type === "included", + timeoutMs: 15000, + }); + + expect(result).not.toBeNull(); + expect(result?.payload.type).toBe("balances.limit_reached"); + + const { data } = result!.payload; + expect(data.customer_id).toBe(customerId); + expect(data.feature_id).toBe(TestFeature.Messages); + expect(data.limit_type).toBe("included"); + expect(data.entity_id).toBeUndefined(); +}); + +// ═══════════════════════════════════════════════════════════════════════════════ +// TEST 2: max_purchase — consumable overage cap reached triggers webhook +// ═══════════════════════════════════════════════════════════════════════════════ + +test.concurrent(`${chalk.yellowBright("limit-reached-cus2: max_purchase cap reached fires webhook")}`, async () => { + const consumableMsg = items.consumableMessages({ + includedUsage: 50, + maxPurchase: 50, + }); + const proProd = products.pro({ + id: "lr-max-purchase-1", + items: [consumableMsg], + }); + + const { customerId, autumnV2_1 } = await initScenario({ + customerId: "lr-maxpurchase-cus-1", + setup: [ + s.customer({ testClock: false, paymentMethod: "success" }), + s.products({ list: [proProd] }), + ], + actions: [s.attach({ productId: proProd.id })], + }); + + await autumnV2_1.track({ + customer_id: customerId, + feature_id: TestFeature.Messages, + value: 100, + }); + + const result = await waitForWebhook({ + token: playToken, + predicate: (payload) => + payload.type === "balances.limit_reached" && + payload.data?.customer_id === customerId && + payload.data?.limit_type === "max_purchase", + timeoutMs: 15000, + }); + + expect(result).not.toBeNull(); + const { data } = result!.payload; + expect(data.customer_id).toBe(customerId); + expect(data.feature_id).toBe(TestFeature.Messages); + expect(data.limit_type).toBe("max_purchase"); +}); + +// ═══════════════════════════════════════════════════════════════════════════════ +// TEST 3: spend_limit — customer-level spend limit reached triggers webhook +// ═══════════════════════════════════════════════════════════════════════════════ + +test.concurrent(`${chalk.yellowBright("limit-reached-cus3: spend_limit reached fires webhook")}`, async () => { + const consumableMsg = items.consumableMessages({ + includedUsage: 50, + price: 1, + }); + const proProd = products.pro({ + id: "lr-spend-limit-1", + items: [consumableMsg], + }); + + const { customerId, autumnV2_1 } = await initScenario({ + customerId: "lr-spendlimit-cus-1", + setup: [ + s.customer({ testClock: false, paymentMethod: "success" }), + s.products({ list: [proProd] }), + ], + actions: [s.attach({ productId: proProd.id })], + }); + + await setCustomerSpendLimit({ + autumn: autumnV2_1, + customerId, + featureId: TestFeature.Messages, + overageLimit: 10, + }); + + await autumnV2_1.track({ + customer_id: customerId, + feature_id: TestFeature.Messages, + value: 60, + }); + + const result = await waitForWebhook({ + token: playToken, + predicate: (payload) => + payload.type === "balances.limit_reached" && + payload.data?.customer_id === customerId && + payload.data?.limit_type === "spend_limit", + timeoutMs: 15000, + }); + + expect(result).not.toBeNull(); + const { data } = result!.payload; + expect(data.customer_id).toBe(customerId); + expect(data.feature_id).toBe(TestFeature.Messages); + expect(data.limit_type).toBe("spend_limit"); +}); + +// ═══════════════════════════════════════════════════════════════════════════════ +// TEST 4: no-fire — usage below limit does not trigger webhook +// ═══════════════════════════════════════════════════════════════════════════════ + +test.concurrent(`${chalk.yellowBright("limit-reached-cus4: usage below limit does not fire webhook")}`, async () => { + const messagesItem = items.monthlyMessages({ includedUsage: 1000 }); + const freeProd = products.base({ + id: "lr-no-fire-1", + items: [messagesItem], + }); + + const { customerId, autumnV2_1 } = await initScenario({ + customerId: "lr-nofire-cus-1", + setup: [s.customer({ testClock: false }), s.products({ list: [freeProd] })], + actions: [s.attach({ productId: freeProd.id })], + }); + + await autumnV2_1.track({ + customer_id: customerId, + feature_id: TestFeature.Messages, + value: 500, + }); + + const result = await waitForWebhook({ + token: playToken, + predicate: (payload) => + payload.type === "balances.limit_reached" && + payload.data?.customer_id === customerId, + timeoutMs: 8000, + }); + + expect(result).toBeNull(); +}); + +// ═══════════════════════════════════════════════════════════════════════════════ +// TEST 5: no-refire — second track after limit already reached does not refire +// ═══════════════════════════════════════════════════════════════════════════════ + +test.concurrent(`${chalk.yellowBright("limit-reached-cus5: does not refire after limit already reached")}`, async () => { + const messagesItem = items.monthlyMessages({ includedUsage: 100 }); + const freeProd = products.base({ + id: "lr-no-refire-1", + items: [messagesItem], + }); + + const { customerId, autumnV2_1 } = await initScenario({ + customerId: "lr-norefire-cus-1", + setup: [s.customer({ testClock: false }), s.products({ list: [freeProd] })], + actions: [s.attach({ productId: freeProd.id })], + }); + + await autumnV2_1.track({ + customer_id: customerId, + feature_id: TestFeature.Messages, + value: 100, + }); + + const firstResult = await waitForWebhook({ + token: playToken, + predicate: (payload) => + payload.type === "balances.limit_reached" && + payload.data?.customer_id === customerId, + timeoutMs: 15000, + }); + + expect(firstResult).not.toBeNull(); + + await autumnV2_1.track({ + customer_id: customerId, + feature_id: TestFeature.Messages, + value: 50, + }); + + await waitForWebhook({ + token: playToken, + predicate: (payload) => + payload.type === "balances.limit_reached" && + payload.data?.customer_id === customerId, + timeoutMs: 8000, + }); + + let matchCount = 0; + const history = await getPlayHistory({ token: playToken }); + for (const event of history.data) { + try { + const payload = parseEventBody(event); + if ( + payload.type === "balances.limit_reached" && + payload.data?.customer_id === customerId + ) { + matchCount++; + } + } catch { + // Skip unparseable events + } + } + + expect(matchCount).toBe(1); +}); + +// ═══════════════════════════════════════════════════════════════════════════════ +// TEST 6: precision — fractional usage doesn't false-trigger limit reached +// ═══════════════════════════════════════════════════════════════════════════════ + +test.concurrent(`${chalk.yellowBright("limit-reached-cus6: precision — 0.001 remaining does not trigger, 0 remaining does")}`, async () => { + const messagesItem = items.monthlyMessages({ includedUsage: 1 }); + const freeProd = products.base({ + id: "lr-precision-1", + items: [messagesItem], + }); + + const { customerId, autumnV2_1 } = await initScenario({ + customerId: "lr-precision-cus-1", + setup: [s.customer({ testClock: false }), s.products({ list: [freeProd] })], + actions: [s.attach({ productId: freeProd.id })], + }); + + // Track 0.999 — leaves 0.001 remaining, should NOT trigger + await autumnV2_1.track({ + customer_id: customerId, + feature_id: TestFeature.Messages, + value: 0.999, + }); + + const noFireResult = await waitForWebhook({ + token: playToken, + predicate: (payload) => + payload.type === "balances.limit_reached" && + payload.data?.customer_id === customerId, + timeoutMs: 8000, + }); + + expect(noFireResult).toBeNull(); + + // Track 0.001 more — now exactly 0 remaining, SHOULD trigger + await autumnV2_1.track({ + customer_id: customerId, + feature_id: TestFeature.Messages, + value: 0.001, + }); + + const result = await waitForWebhook({ + token: playToken, + predicate: (payload) => + payload.type === "balances.limit_reached" && + payload.data?.customer_id === customerId, + timeoutMs: 15000, + }); + + expect(result).not.toBeNull(); + const { data } = result!.payload; + expect(data.customer_id).toBe(customerId); + expect(data.feature_id).toBe(TestFeature.Messages); + expect(data.limit_type).toBe("included"); +}); diff --git a/server/tests/integration/balances/track/limit-reached/limit-reached-entities.test.ts b/server/tests/integration/balances/track/limit-reached/limit-reached-entities.test.ts new file mode 100644 index 000000000..b700f5142 --- /dev/null +++ b/server/tests/integration/balances/track/limit-reached/limit-reached-entities.test.ts @@ -0,0 +1,298 @@ +/** + * Integration tests for the `balances.limit_reached` webhook at the entity level. + * + * `checkLimitReached` fires exactly once: entity-level when `entityId` is + * provided, customer-level otherwise. These tests verify that entity-scoped + * tracking only produces an entity-scoped webhook (no extra customer-level fire). + */ + +import { afterAll, beforeAll, expect, test } from "bun:test"; +import type { EntityBillingControls } from "@autumn/shared"; +import { + getPlayHistory, + getTestSvixAppId, + parseEventBody, + setupWebhookTest, + type WebhookTestSetup, + waitForWebhook, +} from "@tests/integration/utils/svixWebhookTestUtils.js"; +import { TestFeature } from "@tests/setup/v2Features.js"; +import { items } from "@tests/utils/fixtures/items.js"; +import { products } from "@tests/utils/fixtures/products.js"; +import { timeout } from "@tests/utils/genUtils.js"; +import ctx from "@tests/utils/testInitUtils/createTestContext.js"; +import { initScenario, s } from "@tests/utils/testInitUtils/initScenario.js"; +import chalk from "chalk"; + +type BalancesLimitReachedPayload = { + type: string; + data: { + customer_id: string; + feature_id: string; + limit_type: string; + entity_id?: string; + }; +}; + +// ═══════════════════════════════════════════════════════════════════════════════ +// SVIX PLAY SETUP +// ═══════════════════════════════════════════════════════════════════════════════ + +let webhook: WebhookTestSetup; +let playToken: string; + +beforeAll(async () => { + const appId = getTestSvixAppId({ svixConfig: ctx.org.svix_config }); + webhook = await setupWebhookTest({ + appId, + filterTypes: ["balances.limit_reached"], + }); + playToken = webhook.playToken; +}); + +afterAll(async () => { + await webhook?.cleanup(); +}); + +// ═══════════════════════════════════════════════════════════════════════════════ +// TEST 1: entity included — per-entity allowance exhausted +// ═══════════════════════════════════════════════════════════════════════════════ + +test.concurrent(`${chalk.yellowBright("limit-reached-ent1: per-entity included allowance exhausted fires webhook")}`, async () => { + const perEntityMessages = items.monthlyMessages({ + includedUsage: 100, + entityFeatureId: TestFeature.Users, + }); + const prod = products.base({ + id: "lr-ent-included-1", + items: [perEntityMessages], + }); + + const { customerId, autumnV2_1, entities } = await initScenario({ + customerId: "lr-ent-included-cus-1", + setup: [ + s.customer({ testClock: false }), + s.products({ list: [prod] }), + s.entities({ count: 1, featureId: TestFeature.Users }), + ], + actions: [s.attach({ productId: prod.id })], + }); + + await autumnV2_1.track({ + customer_id: customerId, + entity_id: entities[0].id, + feature_id: TestFeature.Messages, + value: 100, + }); + + const result = await waitForWebhook({ + token: playToken, + predicate: (payload) => + payload.type === "balances.limit_reached" && + payload.data?.customer_id === customerId && + payload.data?.entity_id === entities[0].id && + payload.data?.limit_type === "included", + timeoutMs: 15000, + }); + + expect(result).not.toBeNull(); + const { data } = result!.payload; + expect(data.customer_id).toBe(customerId); + expect(data.entity_id).toBe(entities[0].id); + expect(data.feature_id).toBe(TestFeature.Messages); + expect(data.limit_type).toBe("included"); + + // Single-fire: no customer-level webhook (without entity_id) should exist + await timeout(3000); + let customerLevelFired = false; + const history = await getPlayHistory({ token: playToken }); + for (const event of history.data) { + try { + const payload = parseEventBody(event); + if ( + payload.type === "balances.limit_reached" && + payload.data?.customer_id === customerId && + !payload.data?.entity_id + ) { + customerLevelFired = true; + } + } catch { + // Skip + } + } + expect(customerLevelFired).toBe(false); +}); + +// ═══════════════════════════════════════════════════════════════════════════════ +// TEST 2: entity max_purchase — per-entity consumable cap reached +// ═══════════════════════════════════════════════════════════════════════════════ + +test.concurrent(`${chalk.yellowBright("limit-reached-ent2: per-entity max_purchase cap reached fires webhook")}`, async () => { + const consumableMsg = items.consumableMessages({ + includedUsage: 50, + maxPurchase: 50, + entityFeatureId: TestFeature.Users, + }); + const proProd = products.pro({ + id: "lr-ent-maxpurchase-1", + items: [consumableMsg], + }); + + const { customerId, autumnV2_1, entities } = await initScenario({ + customerId: "lr-ent-maxpurchase-cus-1", + setup: [ + s.customer({ testClock: false, paymentMethod: "success" }), + s.products({ list: [proProd] }), + s.entities({ count: 1, featureId: TestFeature.Users }), + ], + actions: [s.attach({ productId: proProd.id })], + }); + + await autumnV2_1.track({ + customer_id: customerId, + entity_id: entities[0].id, + feature_id: TestFeature.Messages, + value: 100, + }); + + const result = await waitForWebhook({ + token: playToken, + predicate: (payload) => + payload.type === "balances.limit_reached" && + payload.data?.customer_id === customerId && + payload.data?.entity_id === entities[0].id && + payload.data?.limit_type === "max_purchase", + timeoutMs: 15000, + }); + + expect(result).not.toBeNull(); + const { data } = result!.payload; + expect(data.entity_id).toBe(entities[0].id); + expect(data.limit_type).toBe("max_purchase"); +}); + +// ═══════════════════════════════════════════════════════════════════════════════ +// TEST 3: entity spend_limit — per-entity spend limit reached +// ═══════════════════════════════════════════════════════════════════════════════ + +test.concurrent(`${chalk.yellowBright("limit-reached-ent3: per-entity spend_limit reached fires webhook")}`, async () => { + const consumableMsg = items.consumableMessages({ + includedUsage: 50, + price: 1, + entityFeatureId: TestFeature.Users, + }); + const proProd = products.pro({ + id: "lr-ent-spendlimit-1", + items: [consumableMsg], + }); + + const { customerId, autumnV2_1, entities } = await initScenario({ + customerId: "lr-ent-spendlimit-cus-1", + setup: [ + s.customer({ testClock: false, paymentMethod: "success" }), + s.products({ list: [proProd] }), + s.entities({ count: 1, featureId: TestFeature.Users }), + ], + actions: [s.attach({ productId: proProd.id })], + }); + + await autumnV2_1.entities.update(customerId, entities[0].id, { + billing_controls: { + spend_limits: [ + { + feature_id: TestFeature.Messages, + enabled: true, + overage_limit: 10, + }, + ], + } as EntityBillingControls, + }); + + await autumnV2_1.track({ + customer_id: customerId, + entity_id: entities[0].id, + feature_id: TestFeature.Messages, + value: 60, + }); + + const result = await waitForWebhook({ + token: playToken, + predicate: (payload) => + payload.type === "balances.limit_reached" && + payload.data?.customer_id === customerId && + payload.data?.entity_id === entities[0].id && + payload.data?.limit_type === "spend_limit", + timeoutMs: 15000, + }); + + expect(result).not.toBeNull(); + const { data } = result!.payload; + expect(data.entity_id).toBe(entities[0].id); + expect(data.limit_type).toBe("spend_limit"); +}); + +// ═══════════════════════════════════════════════════════════════════════════════ +// TEST 4: two entities — only the entity that hits limit fires webhook +// ═══════════════════════════════════════════════════════════════════════════════ + +test.concurrent(`${chalk.yellowBright("limit-reached-ent4: two entities, only entity hitting limit fires webhook")}`, async () => { + const perEntityMessages = items.monthlyMessages({ + includedUsage: 100, + entityFeatureId: TestFeature.Users, + }); + const prod = products.base({ + id: "lr-ent-twoents-1", + items: [perEntityMessages], + }); + + const { customerId, autumnV2_1, entities } = await initScenario({ + customerId: "lr-ent-twoents-cus-1", + setup: [ + s.customer({ testClock: false }), + s.products({ list: [prod] }), + s.entities({ count: 2, featureId: TestFeature.Users }), + ], + actions: [s.attach({ productId: prod.id })], + }); + + await autumnV2_1.track({ + customer_id: customerId, + entity_id: entities[0].id, + feature_id: TestFeature.Messages, + value: 100, + }); + + const entity1Result = await waitForWebhook({ + token: playToken, + predicate: (payload) => + payload.type === "balances.limit_reached" && + payload.data?.customer_id === customerId && + payload.data?.entity_id === entities[0].id, + timeoutMs: 15000, + }); + + expect(entity1Result).not.toBeNull(); + expect(entity1Result!.payload.data.entity_id).toBe(entities[0].id); + + await timeout(5000); + + let entity2Fired = false; + let customerLevelFired = false; + const history = await getPlayHistory({ token: playToken }); + for (const event of history.data) { + try { + const payload = parseEventBody(event); + if ( + payload.type === "balances.limit_reached" && + payload.data?.customer_id === customerId + ) { + if (payload.data?.entity_id === entities[1].id) entity2Fired = true; + if (!payload.data?.entity_id) customerLevelFired = true; + } + } catch { + // Skip + } + } + expect(entity2Fired).toBe(false); + expect(customerLevelFired).toBe(false); +}); diff --git a/server/tests/integration/balances/track/usage-alerts/usage-alert-basic.test.ts b/server/tests/integration/balances/track/usage-alerts/usage-alert-basic.test.ts index 72a72f76f..98fc9adf1 100644 --- a/server/tests/integration/balances/track/usage-alerts/usage-alert-basic.test.ts +++ b/server/tests/integration/balances/track/usage-alerts/usage-alert-basic.test.ts @@ -1,7 +1,7 @@ /** * Integration tests for usage alert webhooks. * - * Verifies that `balances.threshold_reached` webhooks fire correctly when + * Verifies that `balances.usage_alert_triggered` webhooks fire correctly when * customer usage crosses configured thresholds (both absolute and percentage). * * Uses Svix Play to receive and verify webhooks. @@ -9,12 +9,13 @@ import { afterAll, beforeAll, expect, test } from "bun:test"; import { - generatePlayToken, getPlayHistory, - getPlayWebhookUrl, + getTestSvixAppId, parseEventBody, + setupWebhookTest, + type WebhookTestSetup, waitForWebhook, -} from "@tests/integration/billing/autumn-webhooks/utils/svixPlayClient.js"; +} from "@tests/integration/utils/svixWebhookTestUtils.js"; import { TestFeature } from "@tests/setup/v2Features.js"; import { items } from "@tests/utils/fixtures/items.js"; import { products } from "@tests/utils/fixtures/products.js"; @@ -23,18 +24,13 @@ import ctx from "@tests/utils/testInitUtils/createTestContext.js"; import { initScenario, s } from "@tests/utils/testInitUtils/initScenario.js"; import chalk from "chalk"; import { setCustomerUsageAlerts } from "../../utils/usage-alert-utils/customerUsageAlertUtils.js"; -import { - createUsageAlertTestEndpoint, - deleteUsageAlertTestEndpoint, -} from "../../utils/usage-alert-utils/svixUsageAlertEndpoint.js"; -type BalancesThresholdReachedPayload = { +type BalancesUsageAlertTriggeredPayload = { type: string; data: { customer_id: string; feature_id: string; - threshold_type: string; - usage_alert?: { + usage_alert: { name?: string; threshold: number; threshold_type: string; @@ -46,36 +42,20 @@ type BalancesThresholdReachedPayload = { // SVIX PLAY SETUP // ═══════════════════════════════════════════════════════════════════════════════ +let webhook: WebhookTestSetup; let playToken: string; -let endpointId: string; beforeAll(async () => { - playToken = await generatePlayToken(); - console.log(`Generated Svix Play token: ${playToken}`); - - const svixAppId = ctx.org.svix_config?.sandbox_app_id; - if (!svixAppId) { - throw new Error( - "Test org does not have svix_config.sandbox_app_id configured. " + - "Cannot run webhook integration tests without Svix app.", - ); - } - - const playUrl = getPlayWebhookUrl(playToken); - console.log(`Creating Svix endpoint: ${playUrl}`); - endpointId = await createUsageAlertTestEndpoint({ - appId: svixAppId, - playUrl, + const appId = getTestSvixAppId({ svixConfig: ctx.org.svix_config }); + webhook = await setupWebhookTest({ + appId, + filterTypes: ["balances.usage_alert_triggered"], }); - console.log(`Created Svix endpoint: ${endpointId}`); + playToken = webhook.playToken; }); afterAll(async () => { - const svixAppId = ctx.org.svix_config?.sandbox_app_id; - if (svixAppId && endpointId) { - await deleteUsageAlertTestEndpoint({ appId: svixAppId, endpointId }); - console.log(`Deleted Svix endpoint: ${endpointId}`); - } + await webhook?.cleanup(); }); // ═══════════════════════════════════════════════════════════════════════════════ @@ -102,7 +82,7 @@ test(`${chalk.yellowBright("usage-alert1: usage threshold crossing triggers webh { feature_id: TestFeature.Messages, threshold: 800, - threshold_type: "usage_threshold", + threshold_type: "usage", enabled: true, }, ], @@ -115,26 +95,23 @@ test(`${chalk.yellowBright("usage-alert1: usage threshold crossing triggers webh value: 850, }); - const result = await waitForWebhook({ + const result = await waitForWebhook({ token: playToken, predicate: (payload) => - payload.type === "balances.threshold_reached" && + payload.type === "balances.usage_alert_triggered" && payload.data?.customer_id === customerId && - payload.data?.threshold_type === "usage_alert" && payload.data?.usage_alert?.threshold === 800, timeoutMs: 15000, }); expect(result).not.toBeNull(); - expect(result?.payload.type).toBe("balances.threshold_reached"); + expect(result?.payload.type).toBe("balances.usage_alert_triggered"); const { data } = result!.payload; expect(data.customer_id).toBe(customerId); expect(data.feature_id).toBe(TestFeature.Messages); - expect(data.threshold_type).toBe("usage_alert"); - expect(data.usage_alert).toBeDefined(); - expect(data.usage_alert!.threshold).toBe(800); - expect(data.usage_alert!.threshold_type).toBe("usage_threshold"); + expect(data.usage_alert.threshold).toBe(800); + expect(data.usage_alert.threshold_type).toBe("usage"); }); // ═══════════════════════════════════════════════════════════════════════════════ @@ -161,7 +138,7 @@ test(`${chalk.yellowBright("usage-alert2: percentage threshold crossing triggers { feature_id: TestFeature.Messages, threshold: 90, - threshold_type: "usage_percentage_threshold", + threshold_type: "usage_percentage", enabled: true, }, ], @@ -174,26 +151,23 @@ test(`${chalk.yellowBright("usage-alert2: percentage threshold crossing triggers value: 950, }); - const result = await waitForWebhook({ + const result = await waitForWebhook({ token: playToken, predicate: (payload) => - payload.type === "balances.threshold_reached" && + payload.type === "balances.usage_alert_triggered" && payload.data?.customer_id === customerId && - payload.data?.threshold_type === "usage_alert" && payload.data?.usage_alert?.threshold === 90, timeoutMs: 15000, }); expect(result).not.toBeNull(); - expect(result?.payload.type).toBe("balances.threshold_reached"); + expect(result?.payload.type).toBe("balances.usage_alert_triggered"); const { data } = result!.payload; expect(data.customer_id).toBe(customerId); expect(data.feature_id).toBe(TestFeature.Messages); - expect(data.threshold_type).toBe("usage_alert"); - expect(data.usage_alert).toBeDefined(); - expect(data.usage_alert!.threshold).toBe(90); - expect(data.usage_alert!.threshold_type).toBe("usage_percentage_threshold"); + expect(data.usage_alert.threshold).toBe(90); + expect(data.usage_alert.threshold_type).toBe("usage_percentage"); }); // ═══════════════════════════════════════════════════════════════════════════════ @@ -220,7 +194,7 @@ test(`${chalk.yellowBright("usage-alert3: alert does not re-fire after already c { feature_id: TestFeature.Messages, threshold: 500, - threshold_type: "usage_threshold", + threshold_type: "usage", enabled: true, }, ], @@ -233,10 +207,10 @@ test(`${chalk.yellowBright("usage-alert3: alert does not re-fire after already c value: 600, }); - const firstResult = await waitForWebhook({ + const firstResult = await waitForWebhook({ token: playToken, predicate: (payload) => - payload.type === "balances.threshold_reached" && + payload.type === "balances.usage_alert_triggered" && payload.data?.customer_id === customerId && payload.data?.usage_alert?.threshold === 500, timeoutMs: 15000, @@ -252,10 +226,10 @@ test(`${chalk.yellowBright("usage-alert3: alert does not re-fire after already c }); // Wait briefly, then assert no second webhook arrived - await waitForWebhook({ + await waitForWebhook({ token: playToken, predicate: (payload) => - payload.type === "balances.threshold_reached" && + payload.type === "balances.usage_alert_triggered" && payload.data?.customer_id === customerId && payload.data?.usage_alert?.threshold === 500, timeoutMs: 8000, @@ -267,9 +241,9 @@ test(`${chalk.yellowBright("usage-alert3: alert does not re-fire after already c const history = await getPlayHistory({ token: playToken }); for (const event of history.data) { try { - const payload = parseEventBody(event); + const payload = parseEventBody(event); if ( - payload.type === "balances.threshold_reached" && + payload.type === "balances.usage_alert_triggered" && payload.data?.customer_id === customerId && payload.data?.usage_alert?.threshold === 500 ) { @@ -308,7 +282,7 @@ test(`${chalk.yellowBright("usage-alert4: disabled alert does not fire")}`, asyn { feature_id: TestFeature.Messages, threshold: 500, - threshold_type: "usage_threshold", + threshold_type: "usage", enabled: false, }, ], @@ -322,10 +296,10 @@ test(`${chalk.yellowBright("usage-alert4: disabled alert does not fire")}`, asyn }); // Wait and verify no webhook - const result = await waitForWebhook({ + const result = await waitForWebhook({ token: playToken, predicate: (payload) => - payload.type === "balances.threshold_reached" && + payload.type === "balances.usage_alert_triggered" && payload.data?.customer_id === customerId && payload.data?.usage_alert?.threshold === 500, timeoutMs: 8000, @@ -358,13 +332,13 @@ test(`${chalk.yellowBright("usage-alert5: multiple alerts fire independently")}` { feature_id: TestFeature.Messages, threshold: 500, - threshold_type: "usage_threshold", + threshold_type: "usage", enabled: true, }, { feature_id: TestFeature.Messages, threshold: 800, - threshold_type: "usage_threshold", + threshold_type: "usage", enabled: true, }, ], @@ -377,17 +351,17 @@ test(`${chalk.yellowBright("usage-alert5: multiple alerts fire independently")}` value: 600, }); - const firstResult = await waitForWebhook({ + const firstResult = await waitForWebhook({ token: playToken, predicate: (payload) => - payload.type === "balances.threshold_reached" && + payload.type === "balances.usage_alert_triggered" && payload.data?.customer_id === customerId && payload.data?.usage_alert?.threshold === 500, timeoutMs: 15000, }); expect(firstResult).not.toBeNull(); - expect(firstResult!.payload.data.usage_alert!.threshold).toBe(500); + expect(firstResult!.payload.data.usage_alert.threshold).toBe(500); // Verify 800 threshold has NOT fired yet await timeout(3000); @@ -396,9 +370,9 @@ test(`${chalk.yellowBright("usage-alert5: multiple alerts fire independently")}` const historyMid = await getPlayHistory({ token: playToken }); for (const event of historyMid.data) { try { - const payload = parseEventBody(event); + const payload = parseEventBody(event); if ( - payload.type === "balances.threshold_reached" && + payload.type === "balances.usage_alert_triggered" && payload.data?.customer_id === customerId && payload.data?.usage_alert?.threshold === 800 ) { @@ -417,15 +391,15 @@ test(`${chalk.yellowBright("usage-alert5: multiple alerts fire independently")}` value: 300, }); - const secondResult = await waitForWebhook({ + const secondResult = await waitForWebhook({ token: playToken, predicate: (payload) => - payload.type === "balances.threshold_reached" && + payload.type === "balances.usage_alert_triggered" && payload.data?.customer_id === customerId && payload.data?.usage_alert?.threshold === 800, timeoutMs: 15000, }); expect(secondResult).not.toBeNull(); - expect(secondResult!.payload.data.usage_alert!.threshold).toBe(800); + expect(secondResult!.payload.data.usage_alert.threshold).toBe(800); }); diff --git a/server/tests/integration/balances/track/usage-alerts/usage-alert-entities.test.ts b/server/tests/integration/balances/track/usage-alerts/usage-alert-entities.test.ts new file mode 100644 index 000000000..0ca6e1fa2 --- /dev/null +++ b/server/tests/integration/balances/track/usage-alerts/usage-alert-entities.test.ts @@ -0,0 +1,464 @@ +/** + * Integration tests for entity-scoped usage alert webhooks. + * + * Verifies that `balances.usage_alert_triggered` webhooks fire correctly + * when entity-level usage alerts are configured, including: + * - Per-entity items (entityFeatureId scoping) + * - Entity-level alerts on individual entities + * - Multiple entities with different alert thresholds + * - Customer-level alerts still fire alongside entity-level alerts + */ + +import { afterAll, beforeAll, expect, test } from "bun:test"; +import type { EntityBillingControls } from "@autumn/shared"; +import { + getPlayHistory, + getTestSvixAppId, + parseEventBody, + setupWebhookTest, + type WebhookTestSetup, + waitForWebhook, +} from "@tests/integration/utils/svixWebhookTestUtils.js"; +import { TestFeature } from "@tests/setup/v2Features.js"; +import { items } from "@tests/utils/fixtures/items.js"; +import { products } from "@tests/utils/fixtures/products.js"; +import { timeout } from "@tests/utils/genUtils.js"; +import ctx from "@tests/utils/testInitUtils/createTestContext.js"; +import { initScenario, s } from "@tests/utils/testInitUtils/initScenario.js"; +import chalk from "chalk"; + +type BalancesUsageAlertTriggeredPayload = { + type: string; + data: { + customer_id: string; + feature_id: string; + entity_id?: string; + usage_alert: { + name?: string; + threshold: number; + threshold_type: string; + }; + }; +}; + +// ═══════════════════════════════════════════════════════════════════════════════ +// SVIX PLAY SETUP +// ═══════════════════════════════════════════════════════════════════════════════ + +let webhook: WebhookTestSetup; +let playToken: string; + +beforeAll(async () => { + const appId = getTestSvixAppId({ svixConfig: ctx.org.svix_config }); + webhook = await setupWebhookTest({ + appId, + filterTypes: ["balances.usage_alert_triggered"], + }); + playToken = webhook.playToken; +}); + +afterAll(async () => { + await webhook?.cleanup(); +}); + +// ═══════════════════════════════════════════════════════════════════════════════ +// TEST 1: Per-entity item — entity-level usage alert triggers with entity_id +// ═══════════════════════════════════════════════════════════════════════════════ + +test(`${chalk.yellowBright("entity-alert1: per-entity item triggers entity-scoped alert with entity_id")}`, async () => { + const perEntityMessages = items.monthlyMessages({ + includedUsage: 500, + entityFeatureId: TestFeature.Users, + }); + const prod = products.base({ + id: "ea-per-entity-1", + items: [perEntityMessages], + }); + + const { customerId, autumnV2_1, entities } = await initScenario({ + customerId: "entity-alert-per-entity-1", + setup: [ + s.customer({ testClock: false }), + s.products({ list: [prod] }), + s.entities({ count: 1, featureId: TestFeature.Users }), + ], + actions: [s.attach({ productId: prod.id })], + }); + + // Set entity-level usage alert + await autumnV2_1.entities.update(customerId, entities[0].id, { + billing_controls: { + usage_alerts: [ + { + feature_id: TestFeature.Messages, + threshold: 400, + threshold_type: "usage", + enabled: true, + }, + ], + } as EntityBillingControls, + }); + + // Track 450 usage on entity — crosses threshold of 400 + await autumnV2_1.track({ + customer_id: customerId, + entity_id: entities[0].id, + feature_id: TestFeature.Messages, + value: 450, + }); + + const result = await waitForWebhook({ + token: playToken, + predicate: (payload) => + payload.type === "balances.usage_alert_triggered" && + payload.data?.customer_id === customerId && + payload.data?.entity_id === entities[0].id && + payload.data?.usage_alert?.threshold === 400, + timeoutMs: 15000, + }); + + expect(result).not.toBeNull(); + expect(result?.payload.type).toBe("balances.usage_alert_triggered"); + + const { data } = result!.payload; + expect(data.customer_id).toBe(customerId); + expect(data.feature_id).toBe(TestFeature.Messages); + expect(data.entity_id).toBe(entities[0].id); + expect(data.usage_alert.threshold).toBe(400); + expect(data.usage_alert.threshold_type).toBe("usage"); +}); + +// ═══════════════════════════════════════════════════════════════════════════════ +// TEST 2: Two entities with different thresholds — only the crossed one fires +// ═══════════════════════════════════════════════════════════════════════════════ + +test(`${chalk.yellowBright("entity-alert2: two entities, only entity crossing threshold fires alert")}`, async () => { + const perEntityMessages = items.monthlyMessages({ + includedUsage: 1000, + entityFeatureId: TestFeature.Users, + }); + const prod = products.base({ + id: "ea-two-ents-1", + items: [perEntityMessages], + }); + + const { customerId, autumnV2_1, entities } = await initScenario({ + customerId: "entity-alert-two-ents-1", + setup: [ + s.customer({ testClock: false }), + s.products({ list: [prod] }), + s.entities({ count: 2, featureId: TestFeature.Users }), + ], + actions: [s.attach({ productId: prod.id })], + }); + + // Entity 1: alert at 300 + await autumnV2_1.entities.update(customerId, entities[0].id, { + billing_controls: { + usage_alerts: [ + { + feature_id: TestFeature.Messages, + threshold: 300, + threshold_type: "usage", + enabled: true, + }, + ], + } as EntityBillingControls, + }); + + // Entity 2: alert at 700 + await autumnV2_1.entities.update(customerId, entities[1].id, { + billing_controls: { + usage_alerts: [ + { + feature_id: TestFeature.Messages, + threshold: 700, + threshold_type: "usage", + enabled: true, + }, + ], + } as EntityBillingControls, + }); + + // Track 400 on entity 1 — crosses its 300 threshold + await autumnV2_1.track({ + customer_id: customerId, + entity_id: entities[0].id, + feature_id: TestFeature.Messages, + value: 400, + }); + + const entity1Result = + await waitForWebhook({ + token: playToken, + predicate: (payload) => + payload.type === "balances.usage_alert_triggered" && + payload.data?.customer_id === customerId && + payload.data?.entity_id === entities[0].id && + payload.data?.usage_alert?.threshold === 300, + timeoutMs: 15000, + }); + + expect(entity1Result).not.toBeNull(); + expect(entity1Result!.payload.data.entity_id).toBe(entities[0].id); + + // Wait and verify entity 2's alert (700) has NOT fired + await timeout(5000); + + let entity2Fired = false; + const history = await getPlayHistory({ token: playToken }); + for (const event of history.data) { + try { + const payload = parseEventBody(event); + if ( + payload.type === "balances.usage_alert_triggered" && + payload.data?.customer_id === customerId && + payload.data?.entity_id === entities[1].id && + payload.data?.usage_alert?.threshold === 700 + ) { + entity2Fired = true; + } + } catch { + // Skip + } + } + expect(entity2Fired).toBe(false); + + // Now track 800 on entity 2 — crosses its 700 threshold + await autumnV2_1.track({ + customer_id: customerId, + entity_id: entities[1].id, + feature_id: TestFeature.Messages, + value: 800, + }); + + const entity2Result = + await waitForWebhook({ + token: playToken, + predicate: (payload) => + payload.type === "balances.usage_alert_triggered" && + payload.data?.customer_id === customerId && + payload.data?.entity_id === entities[1].id && + payload.data?.usage_alert?.threshold === 700, + timeoutMs: 15000, + }); + + expect(entity2Result).not.toBeNull(); + expect(entity2Result!.payload.data.entity_id).toBe(entities[1].id); +}); + +// ═══════════════════════════════════════════════════════════════════════════════ +// TEST 3: Customer-level alert still fires alongside entity-level alert +// ═══════════════════════════════════════════════════════════════════════════════ + +test(`${chalk.yellowBright("entity-alert3: customer-level and entity-level alerts both fire")}`, async () => { + const perEntityMessages = items.monthlyMessages({ + includedUsage: 500, + entityFeatureId: TestFeature.Users, + }); + const prod = products.base({ + id: "ea-both-levels-1", + items: [perEntityMessages], + }); + + const { customerId, autumnV2_1, entities } = await initScenario({ + customerId: "entity-alert-both-levels-1", + setup: [ + s.customer({ testClock: false }), + s.products({ list: [prod] }), + s.entities({ count: 1, featureId: TestFeature.Users }), + ], + actions: [s.attach({ productId: prod.id })], + }); + + // Set customer-level alert at 200 + await autumnV2_1.customers.update(customerId, { + billing_controls: { + usage_alerts: [ + { + feature_id: TestFeature.Messages, + threshold: 200, + threshold_type: "usage", + enabled: true, + }, + ], + }, + }); + + // Set entity-level alert at 300 + await autumnV2_1.entities.update(customerId, entities[0].id, { + billing_controls: { + usage_alerts: [ + { + feature_id: TestFeature.Messages, + threshold: 300, + threshold_type: "usage", + enabled: true, + }, + ], + } as EntityBillingControls, + }); + + // Track 350 on entity — crosses both 200 (customer) and 300 (entity) + await autumnV2_1.track({ + customer_id: customerId, + entity_id: entities[0].id, + feature_id: TestFeature.Messages, + value: 350, + }); + + // Customer-level alert (no entity_id in payload) + const customerResult = + await waitForWebhook({ + token: playToken, + predicate: (payload) => + payload.type === "balances.usage_alert_triggered" && + payload.data?.customer_id === customerId && + !payload.data?.entity_id && + payload.data?.usage_alert?.threshold === 200, + timeoutMs: 15000, + }); + + expect(customerResult).not.toBeNull(); + expect(customerResult!.payload.data.entity_id).toBeUndefined(); + expect(customerResult!.payload.data.usage_alert.threshold).toBe(200); + + // Entity-level alert (has entity_id in payload) + const entityResult = await waitForWebhook( + { + token: playToken, + predicate: (payload) => + payload.type === "balances.usage_alert_triggered" && + payload.data?.customer_id === customerId && + payload.data?.entity_id === entities[0].id && + payload.data?.usage_alert?.threshold === 300, + timeoutMs: 15000, + }, + ); + + expect(entityResult).not.toBeNull(); + expect(entityResult!.payload.data.entity_id).toBe(entities[0].id); + expect(entityResult!.payload.data.usage_alert.threshold).toBe(300); +}); + +// ═══════════════════════════════════════════════════════════════════════════════ +// TEST 4: Entity percentage threshold alert +// ═══════════════════════════════════════════════════════════════════════════════ + +test(`${chalk.yellowBright("entity-alert4: entity percentage threshold fires correctly")}`, async () => { + const perEntityMessages = items.monthlyMessages({ + includedUsage: 200, + entityFeatureId: TestFeature.Users, + }); + const prod = products.base({ + id: "ea-pct-1", + items: [perEntityMessages], + }); + + const { customerId, autumnV2_1, entities } = await initScenario({ + customerId: "entity-alert-pct-1", + setup: [ + s.customer({ testClock: false }), + s.products({ list: [prod] }), + s.entities({ count: 1, featureId: TestFeature.Users }), + ], + actions: [s.attach({ productId: prod.id })], + }); + + // Set entity-level percentage alert at 80% + await autumnV2_1.entities.update(customerId, entities[0].id, { + billing_controls: { + usage_alerts: [ + { + feature_id: TestFeature.Messages, + threshold: 80, + threshold_type: "usage_percentage", + enabled: true, + }, + ], + } as EntityBillingControls, + }); + + // Track 170 usage on entity — 85% of 200, crosses 80% threshold + await autumnV2_1.track({ + customer_id: customerId, + entity_id: entities[0].id, + feature_id: TestFeature.Messages, + value: 170, + }); + + const result = await waitForWebhook({ + token: playToken, + predicate: (payload) => + payload.type === "balances.usage_alert_triggered" && + payload.data?.customer_id === customerId && + payload.data?.entity_id === entities[0].id && + payload.data?.usage_alert?.threshold === 80, + timeoutMs: 15000, + }); + + expect(result).not.toBeNull(); + const { data } = result!.payload; + expect(data.entity_id).toBe(entities[0].id); + expect(data.usage_alert.threshold).toBe(80); + expect(data.usage_alert.threshold_type).toBe("usage_percentage"); +}); + +// ═══════════════════════════════════════════════════════════════════════════════ +// TEST 5: Entity alert does not fire when below threshold +// ═══════════════════════════════════════════════════════════════════════════════ + +test(`${chalk.yellowBright("entity-alert5: entity alert does not fire when below threshold")}`, async () => { + const perEntityMessages = items.monthlyMessages({ + includedUsage: 1000, + entityFeatureId: TestFeature.Users, + }); + const prod = products.base({ + id: "ea-no-fire-1", + items: [perEntityMessages], + }); + + const { customerId, autumnV2_1, entities } = await initScenario({ + customerId: "entity-alert-no-fire-1", + setup: [ + s.customer({ testClock: false }), + s.products({ list: [prod] }), + s.entities({ count: 1, featureId: TestFeature.Users }), + ], + actions: [s.attach({ productId: prod.id })], + }); + + // Set entity-level alert at 800 + await autumnV2_1.entities.update(customerId, entities[0].id, { + billing_controls: { + usage_alerts: [ + { + feature_id: TestFeature.Messages, + threshold: 800, + threshold_type: "usage", + enabled: true, + }, + ], + } as EntityBillingControls, + }); + + // Track only 500 — below threshold + await autumnV2_1.track({ + customer_id: customerId, + entity_id: entities[0].id, + feature_id: TestFeature.Messages, + value: 500, + }); + + const result = await waitForWebhook({ + token: playToken, + predicate: (payload) => + payload.type === "balances.usage_alert_triggered" && + payload.data?.customer_id === customerId && + payload.data?.entity_id === entities[0].id && + payload.data?.usage_alert?.threshold === 800, + timeoutMs: 8000, + }); + + expect(result).toBeNull(); +}); diff --git a/server/tests/integration/balances/utils/usage-alert-utils/svixUsageAlertEndpoint.ts b/server/tests/integration/balances/utils/usage-alert-utils/svixUsageAlertEndpoint.ts deleted file mode 100644 index 911a4e031..000000000 --- a/server/tests/integration/balances/utils/usage-alert-utils/svixUsageAlertEndpoint.ts +++ /dev/null @@ -1,55 +0,0 @@ -/** - * Svix endpoint utilities for usage alert webhook tests. - * Creates temporary endpoints filtered to `balances.threshold_reached` events. - */ - -import { Svix } from "svix"; - -let svixClient: Svix | null = null; - -const getSvixClient = (): Svix => { - if (!svixClient) { - const apiKey = process.env.SVIX_API_KEY; - if (!apiKey) { - throw new Error( - "SVIX_API_KEY environment variable is required for webhook tests", - ); - } - svixClient = new Svix(apiKey); - } - return svixClient; -}; - -export const createUsageAlertTestEndpoint = async ({ - appId, - playUrl, -}: { - appId: string; - playUrl: string; -}): Promise => { - const svix = getSvixClient(); - - const endpoint = await svix.endpoint.create(appId, { - url: playUrl, - description: "Test endpoint for usage alert webhook tests", - filterTypes: ["balances.threshold_reached"], - }); - - return endpoint.id; -}; - -export const deleteUsageAlertTestEndpoint = async ({ - appId, - endpointId, -}: { - appId: string; - endpointId: string; -}): Promise => { - const svix = getSvixClient(); - - try { - await svix.endpoint.delete(appId, endpointId); - } catch (error) { - console.warn(`Failed to delete test endpoint ${endpointId}:`, error); - } -}; diff --git a/server/tests/integration/billing/autumn-webhooks/attach-v1-webhooks.test.ts b/server/tests/integration/billing/autumn-webhooks/attach-v1-webhooks.test.ts index 5caf7d35f..5d417eb3e 100644 --- a/server/tests/integration/billing/autumn-webhooks/attach-v1-webhooks.test.ts +++ b/server/tests/integration/billing/autumn-webhooks/attach-v1-webhooks.test.ts @@ -18,21 +18,18 @@ import { expectProductCanceling, expectProductScheduled, } from "@tests/integration/billing/utils/expectCustomerProductCorrect"; +import { + getTestSvixAppId, + setupWebhookTest, + type WebhookTestSetup, + waitForWebhook, +} from "@tests/integration/utils/svixWebhookTestUtils.js"; import { TestFeature } from "@tests/setup/v2Features.js"; import { items } from "@tests/utils/fixtures/items.js"; import { products } from "@tests/utils/fixtures/products.js"; import ctx from "@tests/utils/testInitUtils/createTestContext.js"; import { initScenario, s } from "@tests/utils/testInitUtils/initScenario.js"; import chalk from "chalk"; -import { - generatePlayToken, - getPlayWebhookUrl, - waitForWebhook, -} from "./utils/svixPlayClient.js"; -import { - createTestEndpoint, - deleteTestEndpoint, -} from "./utils/svixTestEndpoint.js"; type CustomerProductsUpdatedPayload = { type: string; @@ -48,37 +45,20 @@ type CustomerProductsUpdatedPayload = { // SVIX PLAY SETUP (shared across all tests) // ═══════════════════════════════════════════════════════════════════════════════ +let webhook: WebhookTestSetup; let playToken: string; -let endpointId: string; beforeAll(async () => { - // 1. Generate Svix Play token - playToken = await generatePlayToken(); - console.log(`Generated Svix Play token: ${playToken}`); - - // 2. Get org's Svix app ID - const svixAppId = ctx.org.svix_config?.sandbox_app_id; - if (!svixAppId) { - throw new Error( - "Test org does not have svix_config.sandbox_app_id configured. " + - "Cannot run webhook integration tests without Svix app.", - ); - } - - // 3. Create Svix endpoint pointing to Svix Play - const playUrl = getPlayWebhookUrl(playToken); - console.log(`Creating Svix endpoint: ${playUrl}`); - endpointId = await createTestEndpoint({ appId: svixAppId, playUrl }); - console.log(`Created Svix endpoint: ${endpointId}`); + const appId = getTestSvixAppId({ svixConfig: ctx.org.svix_config }); + webhook = await setupWebhookTest({ + appId, + filterTypes: ["customer.products.updated"], + }); + playToken = webhook.playToken; }); afterAll(async () => { - // Cleanup: delete Svix endpoint - const svixAppId = ctx.org.svix_config?.sandbox_app_id; - if (svixAppId && endpointId) { - await deleteTestEndpoint({ appId: svixAppId, endpointId }); - console.log(`Deleted Svix endpoint: ${endpointId}`); - } + await webhook?.cleanup(); }); // ═══════════════════════════════════════════════════════════════════════════════ diff --git a/server/tests/integration/billing/autumn-webhooks/attach-v2-webhooks.test.ts b/server/tests/integration/billing/autumn-webhooks/attach-v2-webhooks.test.ts index f064134b1..c3a3d641f 100644 --- a/server/tests/integration/billing/autumn-webhooks/attach-v2-webhooks.test.ts +++ b/server/tests/integration/billing/autumn-webhooks/attach-v2-webhooks.test.ts @@ -19,21 +19,18 @@ import { expectProductCanceling, expectProductScheduled, } from "@tests/integration/billing/utils/expectCustomerProductCorrect"; +import { + getTestSvixAppId, + setupWebhookTest, + type WebhookTestSetup, + waitForWebhook, +} from "@tests/integration/utils/svixWebhookTestUtils.js"; import { TestFeature } from "@tests/setup/v2Features.js"; import { items } from "@tests/utils/fixtures/items.js"; import { products } from "@tests/utils/fixtures/products.js"; import ctx from "@tests/utils/testInitUtils/createTestContext.js"; import { initScenario, s } from "@tests/utils/testInitUtils/initScenario.js"; import chalk from "chalk"; -import { - generatePlayToken, - getPlayWebhookUrl, - waitForWebhook, -} from "./utils/svixPlayClient.js"; -import { - createTestEndpoint, - deleteTestEndpoint, -} from "./utils/svixTestEndpoint.js"; type CustomerProductsUpdatedPayload = { type: string; @@ -49,37 +46,20 @@ type CustomerProductsUpdatedPayload = { // SVIX PLAY SETUP (shared across all tests) // ═══════════════════════════════════════════════════════════════════════════════ +let webhook: WebhookTestSetup; let playToken: string; -let endpointId: string; beforeAll(async () => { - // 1. Generate Svix Play token - playToken = await generatePlayToken(); - console.log(`Generated Svix Play token: ${playToken}`); - - // 2. Get org's Svix app ID - const svixAppId = ctx.org.svix_config?.sandbox_app_id; - if (!svixAppId) { - throw new Error( - "Test org does not have svix_config.sandbox_app_id configured. " + - "Cannot run webhook integration tests without Svix app.", - ); - } - - // 3. Create Svix endpoint pointing to Svix Play - const playUrl = getPlayWebhookUrl(playToken); - console.log(`Creating Svix endpoint: ${playUrl}`); - endpointId = await createTestEndpoint({ appId: svixAppId, playUrl }); - console.log(`Created Svix endpoint: ${endpointId}`); + const appId = getTestSvixAppId({ svixConfig: ctx.org.svix_config }); + webhook = await setupWebhookTest({ + appId, + filterTypes: ["customer.products.updated"], + }); + playToken = webhook.playToken; }); afterAll(async () => { - // Cleanup: delete Svix endpoint - const svixAppId = ctx.org.svix_config?.sandbox_app_id; - if (svixAppId && endpointId) { - await deleteTestEndpoint({ appId: svixAppId, endpointId }); - console.log(`Deleted Svix endpoint: ${endpointId}`); - } + await webhook?.cleanup(); }); // ═══════════════════════════════════════════════════════════════════════════════ diff --git a/server/tests/integration/billing/autumn-webhooks/customer-products-updated.test.ts b/server/tests/integration/billing/autumn-webhooks/customer-products-updated.test.ts index acc788b1c..d8b2bfd0e 100644 --- a/server/tests/integration/billing/autumn-webhooks/customer-products-updated.test.ts +++ b/server/tests/integration/billing/autumn-webhooks/customer-products-updated.test.ts @@ -17,21 +17,18 @@ import { expectProductActive, expectProductCanceling, } from "@tests/integration/billing/utils/expectCustomerProductCorrect"; +import { + getTestSvixAppId, + setupWebhookTest, + type WebhookTestSetup, + waitForWebhook, +} from "@tests/integration/utils/svixWebhookTestUtils.js"; import { TestFeature } from "@tests/setup/v2Features.js"; import { items } from "@tests/utils/fixtures/items.js"; import { products } from "@tests/utils/fixtures/products.js"; import ctx from "@tests/utils/testInitUtils/createTestContext.js"; import { initScenario, s } from "@tests/utils/testInitUtils/initScenario.js"; import chalk from "chalk"; -import { - generatePlayToken, - getPlayWebhookUrl, - waitForWebhook, -} from "./utils/svixPlayClient.js"; -import { - createTestEndpoint, - deleteTestEndpoint, -} from "./utils/svixTestEndpoint.js"; type CustomerProductsUpdatedPayload = { type: string; @@ -47,37 +44,20 @@ type CustomerProductsUpdatedPayload = { // SVIX PLAY SETUP (shared across all tests) // ═══════════════════════════════════════════════════════════════════════════════ +let webhook: WebhookTestSetup; let playToken: string; -let endpointId: string; beforeAll(async () => { - // 1. Generate Svix Play token - playToken = await generatePlayToken(); - console.log(`Generated Svix Play token: ${playToken}`); - - // 2. Get org's Svix app ID - const svixAppId = ctx.org.svix_config?.sandbox_app_id; - if (!svixAppId) { - throw new Error( - "Test org does not have svix_config.sandbox_app_id configured. " + - "Cannot run webhook integration tests without Svix app.", - ); - } - - // 3. Create Svix endpoint pointing to Svix Play - const playUrl = getPlayWebhookUrl(playToken); - console.log(`Creating Svix endpoint: ${playUrl}`); - endpointId = await createTestEndpoint({ appId: svixAppId, playUrl }); - console.log(`Created Svix endpoint: ${endpointId}`); + const appId = getTestSvixAppId({ svixConfig: ctx.org.svix_config }); + webhook = await setupWebhookTest({ + appId, + filterTypes: ["customer.products.updated"], + }); + playToken = webhook.playToken; }); afterAll(async () => { - // Cleanup: delete Svix endpoint - const svixAppId = ctx.org.svix_config?.sandbox_app_id; - if (svixAppId && endpointId) { - await deleteTestEndpoint({ appId: svixAppId, endpointId }); - console.log(`Deleted Svix endpoint: ${endpointId}`); - } + await webhook?.cleanup(); }); // ═══════════════════════════════════════════════════════════════════════════════ diff --git a/server/tests/integration/billing/autumn-webhooks/free-to-pro-upgrade-v1-webhook.test.ts b/server/tests/integration/billing/autumn-webhooks/free-to-pro-upgrade-v1-webhook.test.ts index 318ee2570..b826207ed 100644 --- a/server/tests/integration/billing/autumn-webhooks/free-to-pro-upgrade-v1-webhook.test.ts +++ b/server/tests/integration/billing/autumn-webhooks/free-to-pro-upgrade-v1-webhook.test.ts @@ -10,6 +10,12 @@ import { afterAll, beforeAll, expect, test } from "bun:test"; import type { ApiCustomerV3, ApiProduct } from "@autumn/shared"; import { expectProductActive } from "@tests/integration/billing/utils/expectCustomerProductCorrect"; +import { + getTestSvixAppId, + setupWebhookTest, + type WebhookTestSetup, + waitForWebhook, +} from "@tests/integration/utils/svixWebhookTestUtils.js"; import { completeStripeCheckoutFormV2 } from "@tests/utils/browserPool/completeStripeCheckoutFormV2.js"; import { items } from "@tests/utils/fixtures/items.js"; import { products } from "@tests/utils/fixtures/products.js"; @@ -17,15 +23,6 @@ import { timeout } from "@tests/utils/genUtils.js"; import ctx from "@tests/utils/testInitUtils/createTestContext.js"; import { initScenario, s } from "@tests/utils/testInitUtils/initScenario.js"; import chalk from "chalk"; -import { - generatePlayToken, - getPlayWebhookUrl, - waitForWebhook, -} from "./utils/svixPlayClient.js"; -import { - createTestEndpoint, - deleteTestEndpoint, -} from "./utils/svixTestEndpoint.js"; type CustomerProductsUpdatedPayload = { type: string; @@ -40,33 +37,20 @@ type CustomerProductsUpdatedPayload = { // SVIX PLAY SETUP // ═══════════════════════════════════════════════════════════════════════════════ +let webhook: WebhookTestSetup; let playToken: string; -let endpointId: string; beforeAll(async () => { - playToken = await generatePlayToken(); - console.log(`Generated Svix Play token: ${playToken}`); - - const svixAppId = ctx.org.svix_config?.sandbox_app_id; - if (!svixAppId) { - throw new Error( - "Test org does not have svix_config.sandbox_app_id configured. " + - "Cannot run webhook integration tests without Svix app.", - ); - } - - const playUrl = getPlayWebhookUrl(playToken); - console.log(`Creating Svix endpoint: ${playUrl}`); - endpointId = await createTestEndpoint({ appId: svixAppId, playUrl }); - console.log(`Created Svix endpoint: ${endpointId}`); + const appId = getTestSvixAppId({ svixConfig: ctx.org.svix_config }); + webhook = await setupWebhookTest({ + appId, + filterTypes: ["customer.products.updated"], + }); + playToken = webhook.playToken; }); afterAll(async () => { - const svixAppId = ctx.org.svix_config?.sandbox_app_id; - if (svixAppId && endpointId) { - await deleteTestEndpoint({ appId: svixAppId, endpointId }); - console.log(`Deleted Svix endpoint: ${endpointId}`); - } + await webhook?.cleanup(); }); // ═══════════════════════════════════════════════════════════════════════════════ diff --git a/server/tests/integration/billing/autumn-webhooks/free-to-pro-upgrade-v2-webhook.test.ts b/server/tests/integration/billing/autumn-webhooks/free-to-pro-upgrade-v2-webhook.test.ts index 620d28deb..62ff26d33 100644 --- a/server/tests/integration/billing/autumn-webhooks/free-to-pro-upgrade-v2-webhook.test.ts +++ b/server/tests/integration/billing/autumn-webhooks/free-to-pro-upgrade-v2-webhook.test.ts @@ -10,6 +10,12 @@ import { afterAll, beforeAll, expect, test } from "bun:test"; import type { ApiCustomerV3, ApiProduct } from "@autumn/shared"; import { expectProductActive } from "@tests/integration/billing/utils/expectCustomerProductCorrect"; +import { + getTestSvixAppId, + setupWebhookTest, + type WebhookTestSetup, + waitForWebhook, +} from "@tests/integration/utils/svixWebhookTestUtils.js"; import { completeStripeCheckoutFormV2 } from "@tests/utils/browserPool/completeStripeCheckoutFormV2.js"; import { items } from "@tests/utils/fixtures/items.js"; import { products } from "@tests/utils/fixtures/products.js"; @@ -17,15 +23,6 @@ import { timeout } from "@tests/utils/genUtils.js"; import ctx from "@tests/utils/testInitUtils/createTestContext.js"; import { initScenario, s } from "@tests/utils/testInitUtils/initScenario.js"; import chalk from "chalk"; -import { - generatePlayToken, - getPlayWebhookUrl, - waitForWebhook, -} from "./utils/svixPlayClient.js"; -import { - createTestEndpoint, - deleteTestEndpoint, -} from "./utils/svixTestEndpoint.js"; type CustomerProductsUpdatedPayload = { type: string; @@ -40,33 +37,20 @@ type CustomerProductsUpdatedPayload = { // SVIX PLAY SETUP // ═══════════════════════════════════════════════════════════════════════════════ +let webhook: WebhookTestSetup; let playToken: string; -let endpointId: string; beforeAll(async () => { - playToken = await generatePlayToken(); - console.log(`Generated Svix Play token: ${playToken}`); - - const svixAppId = ctx.org.svix_config?.sandbox_app_id; - if (!svixAppId) { - throw new Error( - "Test org does not have svix_config.sandbox_app_id configured. " + - "Cannot run webhook integration tests without Svix app.", - ); - } - - const playUrl = getPlayWebhookUrl(playToken); - console.log(`Creating Svix endpoint: ${playUrl}`); - endpointId = await createTestEndpoint({ appId: svixAppId, playUrl }); - console.log(`Created Svix endpoint: ${endpointId}`); + const appId = getTestSvixAppId({ svixConfig: ctx.org.svix_config }); + webhook = await setupWebhookTest({ + appId, + filterTypes: ["customer.products.updated"], + }); + playToken = webhook.playToken; }); afterAll(async () => { - const svixAppId = ctx.org.svix_config?.sandbox_app_id; - if (svixAppId && endpointId) { - await deleteTestEndpoint({ appId: svixAppId, endpointId }); - console.log(`Deleted Svix endpoint: ${endpointId}`); - } + await webhook?.cleanup(); }); // ═══════════════════════════════════════════════════════════════════════════════ diff --git a/server/tests/integration/billing/autumn-webhooks/update-subscription-webhooks.test.ts b/server/tests/integration/billing/autumn-webhooks/update-subscription-webhooks.test.ts index 448aeaa5e..e39f08c90 100644 --- a/server/tests/integration/billing/autumn-webhooks/update-subscription-webhooks.test.ts +++ b/server/tests/integration/billing/autumn-webhooks/update-subscription-webhooks.test.ts @@ -14,21 +14,18 @@ import { afterAll, beforeAll, expect, test } from "bun:test"; import type { ApiCustomerV3, ApiProduct } from "@autumn/shared"; import { expectCustomerFeatureCorrect } from "@tests/integration/billing/utils/expectCustomerFeatureCorrect"; import { expectProductActive } from "@tests/integration/billing/utils/expectCustomerProductCorrect"; +import { + getTestSvixAppId, + setupWebhookTest, + type WebhookTestSetup, + waitForWebhook, +} from "@tests/integration/utils/svixWebhookTestUtils.js"; import { TestFeature } from "@tests/setup/v2Features.js"; import { items } from "@tests/utils/fixtures/items.js"; import { products } from "@tests/utils/fixtures/products.js"; import ctx from "@tests/utils/testInitUtils/createTestContext.js"; import { initScenario, s } from "@tests/utils/testInitUtils/initScenario.js"; import chalk from "chalk"; -import { - generatePlayToken, - getPlayWebhookUrl, - waitForWebhook, -} from "./utils/svixPlayClient.js"; -import { - createTestEndpoint, - deleteTestEndpoint, -} from "./utils/svixTestEndpoint.js"; type CustomerProductsUpdatedPayload = { type: string; @@ -43,37 +40,20 @@ type CustomerProductsUpdatedPayload = { // SVIX PLAY SETUP (shared across all tests) // ═══════════════════════════════════════════════════════════════════════════════ +let webhook: WebhookTestSetup; let playToken: string; -let endpointId: string; beforeAll(async () => { - // 1. Generate Svix Play token - playToken = await generatePlayToken(); - console.log(`Generated Svix Play token: ${playToken}`); - - // 2. Get org's Svix app ID - const svixAppId = ctx.org.svix_config?.sandbox_app_id; - if (!svixAppId) { - throw new Error( - "Test org does not have svix_config.sandbox_app_id configured. " + - "Cannot run webhook integration tests without Svix app.", - ); - } - - // 3. Create Svix endpoint pointing to Svix Play - const playUrl = getPlayWebhookUrl(playToken); - console.log(`Creating Svix endpoint: ${playUrl}`); - endpointId = await createTestEndpoint({ appId: svixAppId, playUrl }); - console.log(`Created Svix endpoint: ${endpointId}`); + const appId = getTestSvixAppId({ svixConfig: ctx.org.svix_config }); + webhook = await setupWebhookTest({ + appId, + filterTypes: ["customer.products.updated"], + }); + playToken = webhook.playToken; }); afterAll(async () => { - // Cleanup: delete Svix endpoint - const svixAppId = ctx.org.svix_config?.sandbox_app_id; - if (svixAppId && endpointId) { - await deleteTestEndpoint({ appId: svixAppId, endpointId }); - console.log(`Deleted Svix endpoint: ${endpointId}`); - } + await webhook?.cleanup(); }); // ═══════════════════════════════════════════════════════════════════════════════ diff --git a/server/tests/integration/billing/autumn-webhooks/utils/svixPlayClient.ts b/server/tests/integration/billing/autumn-webhooks/utils/svixPlayClient.ts deleted file mode 100644 index 14a665608..000000000 --- a/server/tests/integration/billing/autumn-webhooks/utils/svixPlayClient.ts +++ /dev/null @@ -1,121 +0,0 @@ -/** - * Svix Play API client for webhook testing. - * Uses the free Svix Play API - no signup required. - * - * API Docs: https://docs.svix.com/play#programmatic-use-of-the-public-api - */ - -const SVIX_PLAY_API_BASE = "https://api.play.svix.com/api/v1"; - -export type SvixPlayEvent = { - id: string; - url: string; - method: string; - created_at: string; - body: string; // base64 encoded - headers: Record; - response: { - status_code: number; - headers: Record; - body: string; - }; - ip: string | null; -}; - -export type SvixPlayHistory = { - iterator: string; - data: SvixPlayEvent[]; -}; - -/** - * Generate a new Svix Play token for webhook testing. - * Tokens are freely generated and don't require authentication. - */ -export const generatePlayToken = async (): Promise => { - const response = await fetch(`${SVIX_PLAY_API_BASE}/token/generate/`, { - method: "POST", - }); - - if (!response.ok) { - throw new Error(`Failed to generate Svix Play token: ${response.status}`); - } - - const data = (await response.json()) as { token: string }; - return data.token; -}; - -/** - * Get the webhook URL for a given Svix Play token. - * This URL receives webhooks and stores them for later inspection. - */ -export const getPlayWebhookUrl = (token: string): string => { - return `${SVIX_PLAY_API_BASE}/in/${token}/`; -}; - -/** - * Query the webhook history for a Svix Play token. - * Returns all webhooks received by this token. - */ -export const getPlayHistory = async ({ - token, - iterator, -}: { - token: string; - iterator?: string; -}): Promise => { - const url = new URL(`${SVIX_PLAY_API_BASE}/history/${token}/`); - if (iterator) { - url.searchParams.set("iterator", iterator); - } - - const response = await fetch(url.toString()); - - if (!response.ok) { - throw new Error(`Failed to get Svix Play history: ${response.status}`); - } - - return response.json() as Promise; -}; - -/** - * Parse a Svix Play event body (base64 → JSON). - */ -export const parseEventBody = (event: SvixPlayEvent): T => { - const decoded = Buffer.from(event.body, "base64").toString("utf-8"); - return JSON.parse(decoded) as T; -}; - -/** - * Wait for a webhook matching a predicate to appear in Svix Play. - * Polls every 500ms until timeout. - */ -export const waitForWebhook = async ({ - token, - predicate, - timeoutMs = 10000, -}: { - token: string; - predicate: (payload: T) => boolean; - timeoutMs?: number; -}): Promise<{ event: SvixPlayEvent; payload: T } | null> => { - const startTime = Date.now(); - - while (Date.now() - startTime < timeoutMs) { - const history = await getPlayHistory({ token }); - - for (const event of history.data) { - try { - const payload = parseEventBody(event); - if (predicate(payload)) { - return { event, payload }; - } - } catch { - // Skip events that can't be parsed - } - } - - await new Promise((resolve) => setTimeout(resolve, 500)); - } - - return null; -}; diff --git a/server/tests/integration/billing/autumn-webhooks/utils/svixTestEndpoint.ts b/server/tests/integration/billing/autumn-webhooks/utils/svixTestEndpoint.ts deleted file mode 100644 index 85a713d16..000000000 --- a/server/tests/integration/billing/autumn-webhooks/utils/svixTestEndpoint.ts +++ /dev/null @@ -1,63 +0,0 @@ -/** - * Utilities for managing Svix endpoints during webhook tests. - * Creates temporary endpoints pointing to Svix Play for test verification. - */ - -import { Svix } from "svix"; - -let svixClient: Svix | null = null; - -const getSvixClient = (): Svix => { - if (!svixClient) { - const apiKey = process.env.SVIX_API_KEY; - if (!apiKey) { - throw new Error( - "SVIX_API_KEY environment variable is required for webhook tests", - ); - } - svixClient = new Svix(apiKey); - } - return svixClient; -}; - -/** - * Create a test endpoint pointing to Svix Play. - * The endpoint will receive all webhook events from the org's Svix app. - */ -export const createTestEndpoint = async ({ - appId, - playUrl, -}: { - appId: string; - playUrl: string; -}): Promise => { - const svix = getSvixClient(); - - const endpoint = await svix.endpoint.create(appId, { - url: playUrl, - description: "Test endpoint for webhook integration tests", - filterTypes: ["customer.products.updated"], - }); - - return endpoint.id; -}; - -/** - * Delete a test endpoint after tests complete. - */ -export const deleteTestEndpoint = async ({ - appId, - endpointId, -}: { - appId: string; - endpointId: string; -}): Promise => { - const svix = getSvixClient(); - - try { - await svix.endpoint.delete(appId, endpointId); - } catch (error) { - // Log but don't fail if cleanup fails - console.warn(`Failed to delete test endpoint ${endpointId}:`, error); - } -}; diff --git a/server/tests/integration/crud/customers/customer-billing-controls.test.ts b/server/tests/integration/crud/customers/customer-billing-controls.test.ts index 5e97aa80d..2c4c22044 100644 --- a/server/tests/integration/crud/customers/customer-billing-controls.test.ts +++ b/server/tests/integration/crud/customers/customer-billing-controls.test.ts @@ -27,6 +27,17 @@ const autoTopupControls: CustomerBillingControls = { ], }; +const usageAlertControls: CustomerBillingControls = { + usage_alerts: [ + { + feature_id: TestFeature.Messages, + threshold: 90, + threshold_type: "usage_percentage", + enabled: true, + }, + ], +}; + test.concurrent(`${chalk.yellowBright("customer billing controls: create customer with spend limits")}`, async () => { const customerId = "customer-billing-controls-1"; const { autumnV2_1, ctx } = await initScenario({ @@ -170,3 +181,157 @@ test.concurrent(`${chalk.yellowBright("customer billing controls: reject duplica }), }); }); + +test.concurrent(`${chalk.yellowBright("customer billing controls: create customer with usage alerts")}`, async () => { + const customerId = "customer-billing-controls-4"; + const { autumnV2_1, ctx } = await initScenario({ + setup: [s.deleteCustomer({ customerId })], + actions: [], + }); + + await autumnV2_1.customers.create({ + id: customerId, + name: "Usage Alert Customer", + email: `${customerId}@example.com`, + billing_controls: usageAlertControls, + }); + + const cachedCustomer = + await autumnV2_1.customers.get(customerId); + expect(cachedCustomer.billing_controls?.usage_alerts).toEqual( + usageAlertControls.usage_alerts, + ); + + const uncachedCustomer = await autumnV2_1.customers.get( + customerId, + { skip_cache: "true" }, + ); + expect(uncachedCustomer.billing_controls?.usage_alerts).toEqual( + usageAlertControls.usage_alerts, + ); + + const fromDb = await CusService.getFull({ + ctx, + idOrInternalId: customerId, + }); + expect(fromDb.usage_alerts).toEqual(usageAlertControls.usage_alerts); +}); + +test.concurrent(`${chalk.yellowBright("customer billing controls: updating usage alerts does not unset spend limits or auto topups")}`, async () => { + const customerId = "customer-billing-controls-5"; + const { autumnV2_1 } = await initScenario({ + customerId, + setup: [s.customer({})], + actions: [], + }); + + // Set spend limits and auto topups first + await autumnV2_1.customers.update(customerId, { + billing_controls: spendLimitControls, + }); + await autumnV2_1.customers.update(customerId, { + billing_controls: autoTopupControls, + }); + + // Now update only usage_alerts + await autumnV2_1.customers.update(customerId, { + billing_controls: usageAlertControls, + }); + + const cached = await autumnV2_1.customers.get(customerId); + expect(cached.billing_controls?.spend_limits).toEqual( + spendLimitControls.spend_limits, + ); + expect(cached.billing_controls?.auto_topups).toEqual( + autoTopupControls.auto_topups, + ); + expect(cached.billing_controls?.usage_alerts).toEqual( + usageAlertControls.usage_alerts, + ); + + const uncached = await autumnV2_1.customers.get(customerId, { + skip_cache: "true", + }); + expect(uncached.billing_controls?.spend_limits).toEqual( + spendLimitControls.spend_limits, + ); + expect(uncached.billing_controls?.auto_topups).toEqual( + autoTopupControls.auto_topups, + ); + expect(uncached.billing_controls?.usage_alerts).toEqual( + usageAlertControls.usage_alerts, + ); +}); + +test.concurrent(`${chalk.yellowBright("customer billing controls: updating spend limits does not unset usage alerts")}`, async () => { + const customerId = "customer-billing-controls-6"; + const { autumnV2_1 } = await initScenario({ + customerId, + setup: [s.customer({})], + actions: [], + }); + + // Set usage alerts first + await autumnV2_1.customers.update(customerId, { + billing_controls: usageAlertControls, + }); + + // Now update only spend_limits + await autumnV2_1.customers.update(customerId, { + billing_controls: spendLimitControls, + }); + + const cached = await autumnV2_1.customers.get(customerId); + expect(cached.billing_controls?.usage_alerts).toEqual( + usageAlertControls.usage_alerts, + ); + expect(cached.billing_controls?.spend_limits).toEqual( + spendLimitControls.spend_limits, + ); + + const uncached = await autumnV2_1.customers.get(customerId, { + skip_cache: "true", + }); + expect(uncached.billing_controls?.usage_alerts).toEqual( + usageAlertControls.usage_alerts, + ); + expect(uncached.billing_controls?.spend_limits).toEqual( + spendLimitControls.spend_limits, + ); +}); + +test.concurrent(`${chalk.yellowBright("customer billing controls: clearing usage alerts with empty array")}`, async () => { + const customerId = "customer-billing-controls-7"; + const { autumnV2_1 } = await initScenario({ + customerId, + setup: [s.customer({})], + actions: [], + }); + + // Set both spend limits and usage alerts + await autumnV2_1.customers.update(customerId, { + billing_controls: { + ...spendLimitControls, + ...usageAlertControls, + }, + }); + + // Clear only usage_alerts + await autumnV2_1.customers.update(customerId, { + billing_controls: { usage_alerts: [] }, + }); + + const cached = await autumnV2_1.customers.get(customerId); + expect(cached.billing_controls?.usage_alerts).toEqual([]); + expect(cached.billing_controls?.spend_limits).toEqual( + spendLimitControls.spend_limits, + ); + + const uncached = await autumnV2_1.customers.get(customerId, { + skip_cache: "true", + }); + expect(uncached.billing_controls?.usage_alerts).toEqual([]); + expect(uncached.billing_controls?.spend_limits).toEqual( + spendLimitControls.spend_limits, + ); +}); diff --git a/server/tests/integration/crud/entities/update-entity-billing-controls.test.ts b/server/tests/integration/crud/entities/update-entity-billing-controls.test.ts index adc6727de..f3ecd781e 100644 --- a/server/tests/integration/crud/entities/update-entity-billing-controls.test.ts +++ b/server/tests/integration/crud/entities/update-entity-billing-controls.test.ts @@ -17,6 +17,17 @@ const initialBillingControls: EntityBillingControls = { ], }; +const usageAlertControls: EntityBillingControls = { + usage_alerts: [ + { + feature_id: TestFeature.Messages, + threshold: 80, + threshold_type: "usage_percentage", + enabled: true, + }, + ], +}; + test.concurrent(`${chalk.yellowBright("entity billing controls: create and update entity spend limits")}`, async () => { const { customerId, autumnV2_1 } = await initScenario({ customerId: "entity-billing-controls-1", @@ -171,3 +182,172 @@ test.concurrent(`${chalk.yellowBright("entity billing controls: reject duplicate }), }); }); + +test.concurrent(`${chalk.yellowBright("entity billing controls: create entity with usage alerts")}`, async () => { + const { customerId, autumnV2_1 } = await initScenario({ + customerId: "entity-billing-controls-4", + setup: [s.customer({})], + actions: [], + }); + + const created = await autumnV2_1.entities.create(customerId, { + id: "entity-ua-1", + name: "Entity UA 1", + feature_id: TestFeature.Users, + billing_controls: usageAlertControls, + }); + + expect((created as ApiEntityV2).billing_controls?.usage_alerts).toEqual( + usageAlertControls.usage_alerts, + ); + + const fetched = await autumnV2_1.entities.get( + customerId, + "entity-ua-1", + ); + + expect(fetched.billing_controls?.usage_alerts).toEqual( + usageAlertControls.usage_alerts, + ); +}); + +test.concurrent(`${chalk.yellowBright("entity billing controls: create entity with both spend limits and usage alerts")}`, async () => { + const { customerId, autumnV2_1 } = await initScenario({ + customerId: "entity-billing-controls-5", + setup: [s.customer({})], + actions: [], + }); + + const bothControls: EntityBillingControls = { + ...initialBillingControls, + ...usageAlertControls, + }; + + const created = await autumnV2_1.entities.create(customerId, { + id: "entity-both-1", + name: "Entity Both 1", + feature_id: TestFeature.Users, + billing_controls: bothControls, + }); + + expect((created as ApiEntityV2).billing_controls?.spend_limits).toEqual( + initialBillingControls.spend_limits, + ); + expect((created as ApiEntityV2).billing_controls?.usage_alerts).toEqual( + usageAlertControls.usage_alerts, + ); +}); + +test.concurrent(`${chalk.yellowBright("entity billing controls: updating usage alerts does not unset spend limits")}`, async () => { + const { customerId, autumnV2_1 } = await initScenario({ + customerId: "entity-billing-controls-6", + setup: [s.customer({})], + actions: [], + }); + + await autumnV2_1.entities.create(customerId, { + id: "entity-preserve-1", + name: "Entity Preserve 1", + feature_id: TestFeature.Users, + billing_controls: initialBillingControls, + }); + + // Update only usage_alerts + await autumnV2_1.entities.update(customerId, "entity-preserve-1", { + billing_controls: usageAlertControls, + }); + + const fetched = await autumnV2_1.entities.get( + customerId, + "entity-preserve-1", + ); + + // spend_limits should be preserved + expect(fetched.billing_controls?.spend_limits).toEqual( + initialBillingControls.spend_limits, + ); + // usage_alerts should be set + expect(fetched.billing_controls?.usage_alerts).toEqual( + usageAlertControls.usage_alerts, + ); + + // Verify in DB too + const fromDb = await CusService.getFull({ + ctx, + idOrInternalId: customerId, + withEntities: true, + }); + const entity = fromDb.entities.find( + (candidate) => candidate.id === "entity-preserve-1", + ); + expect(entity?.spend_limits).toEqual(initialBillingControls.spend_limits); + expect(entity?.usage_alerts).toEqual(usageAlertControls.usage_alerts); +}); + +test.concurrent(`${chalk.yellowBright("entity billing controls: updating spend limits does not unset usage alerts")}`, async () => { + const { customerId, autumnV2_1 } = await initScenario({ + customerId: "entity-billing-controls-7", + setup: [s.customer({})], + actions: [], + }); + + await autumnV2_1.entities.create(customerId, { + id: "entity-preserve-2", + name: "Entity Preserve 2", + feature_id: TestFeature.Users, + billing_controls: usageAlertControls, + }); + + // Update only spend_limits + await autumnV2_1.entities.update(customerId, "entity-preserve-2", { + billing_controls: initialBillingControls, + }); + + const fetched = await autumnV2_1.entities.get( + customerId, + "entity-preserve-2", + ); + + // usage_alerts should be preserved + expect(fetched.billing_controls?.usage_alerts).toEqual( + usageAlertControls.usage_alerts, + ); + // spend_limits should be set + expect(fetched.billing_controls?.spend_limits).toEqual( + initialBillingControls.spend_limits, + ); +}); + +test.concurrent(`${chalk.yellowBright("entity billing controls: clearing usage alerts with empty array")}`, async () => { + const { customerId, autumnV2_1 } = await initScenario({ + customerId: "entity-billing-controls-8", + setup: [s.customer({})], + actions: [], + }); + + await autumnV2_1.entities.create(customerId, { + id: "entity-clear-ua-1", + name: "Entity Clear UA 1", + feature_id: TestFeature.Users, + billing_controls: { + ...initialBillingControls, + ...usageAlertControls, + }, + }); + + // Clear usage_alerts + await autumnV2_1.entities.update(customerId, "entity-clear-ua-1", { + billing_controls: { usage_alerts: [] }, + }); + + const fetched = await autumnV2_1.entities.get( + customerId, + "entity-clear-ua-1", + ); + + expect(fetched.billing_controls?.usage_alerts).toEqual([]); + // spend_limits should still be intact + expect(fetched.billing_controls?.spend_limits).toEqual( + initialBillingControls.spend_limits, + ); +}); diff --git a/server/tests/integration/utils/svixWebhookTestUtils.ts b/server/tests/integration/utils/svixWebhookTestUtils.ts new file mode 100644 index 000000000..d77a64006 --- /dev/null +++ b/server/tests/integration/utils/svixWebhookTestUtils.ts @@ -0,0 +1,214 @@ +/** + * Shared Svix webhook test utilities. + * + * Consolidates Svix Play client + endpoint management into one module + * so every webhook test file doesn't have to duplicate boilerplate. + */ + +import { Svix } from "svix"; + +// ─── Svix Admin Client ─────────────────────────────────────────────────────── + +let svixClient: Svix | null = null; + +const getSvixClient = (): Svix => { + if (!svixClient) { + const apiKey = process.env.SVIX_API_KEY; + if (!apiKey) + throw new Error( + "SVIX_API_KEY environment variable is required for webhook tests", + ); + svixClient = new Svix(apiKey); + } + return svixClient; +}; + +// ─── Svix Play Client ─────────────────────────────────────────────────────── + +const SVIX_PLAY_API_BASE = "https://api.play.svix.com/api/v1"; + +export type SvixPlayEvent = { + id: string; + url: string; + method: string; + created_at: string; + body: string; // base64 encoded + headers: Record; + response: { + status_code: number; + headers: Record; + body: string; + }; + ip: string | null; +}; + +export type SvixPlayHistory = { + iterator: string; + data: SvixPlayEvent[]; +}; + +export const generatePlayToken = async (): Promise => { + const response = await fetch(`${SVIX_PLAY_API_BASE}/token/generate/`, { + method: "POST", + }); + + if (!response.ok) + throw new Error(`Failed to generate Svix Play token: ${response.status}`); + + const data = (await response.json()) as { token: string }; + return data.token; +}; + +export const getPlayWebhookUrl = (token: string): string => { + return `${SVIX_PLAY_API_BASE}/in/${token}/`; +}; + +export const getPlayHistory = async ({ + token, + iterator, +}: { + token: string; + iterator?: string; +}): Promise => { + const url = new URL(`${SVIX_PLAY_API_BASE}/history/${token}/`); + if (iterator) url.searchParams.set("iterator", iterator); + + const response = await fetch(url.toString()); + + if (!response.ok) + throw new Error(`Failed to get Svix Play history: ${response.status}`); + + return response.json() as Promise; +}; + +export const parseEventBody = (event: SvixPlayEvent): T => { + const decoded = Buffer.from(event.body, "base64").toString("utf-8"); + return JSON.parse(decoded) as T; +}; + +/** Poll Svix Play until a webhook matching `predicate` appears, or timeout. */ +export const waitForWebhook = async ({ + token, + predicate, + timeoutMs = 10000, +}: { + token: string; + predicate: (payload: T) => boolean; + timeoutMs?: number; +}): Promise<{ event: SvixPlayEvent; payload: T } | null> => { + const startTime = Date.now(); + + while (Date.now() - startTime < timeoutMs) { + const history = await getPlayHistory({ token }); + + for (const event of history.data) { + try { + const payload = parseEventBody(event); + if (predicate(payload)) return { event, payload }; + } catch { + // Skip events that can't be parsed + } + } + + await new Promise((resolve) => setTimeout(resolve, 500)); + } + + return null; +}; + +// ─── Endpoint Lifecycle ───────────────────────────────────────────────────── + +export const createWebhookTestEndpoint = async ({ + appId, + playUrl, + filterTypes, +}: { + appId: string; + playUrl: string; + filterTypes: string[]; +}): Promise => { + const svix = getSvixClient(); + + const endpoint = await svix.endpoint.create(appId, { + url: playUrl, + description: "Test endpoint for webhook integration tests", + filterTypes, + }); + + return endpoint.id; +}; + +export const deleteWebhookTestEndpoint = async ({ + appId, + endpointId, +}: { + appId: string; + endpointId: string; +}): Promise => { + const svix = getSvixClient(); + + try { + await svix.endpoint.delete(appId, endpointId); + } catch (error) { + console.warn(`Failed to delete test endpoint ${endpointId}:`, error); + } +}; + +// ─── High-Level Setup Helper ──────────────────────────────────────────────── + +export type WebhookTestSetup = { + playToken: string; + endpointId: string; + cleanup: () => Promise; +}; + +/** + * Full lifecycle helper: generates a Svix Play token, creates a filtered + * endpoint in the given app, and returns everything needed for tests + + * a `cleanup` function for `afterAll`. + */ +export const setupWebhookTest = async ({ + appId, + filterTypes, +}: { + appId: string; + filterTypes: string[]; +}): Promise => { + const playToken = await generatePlayToken(); + console.log(`Generated Svix Play token: ${playToken}`); + + const playUrl = getPlayWebhookUrl(playToken); + console.log(`Creating Svix endpoint: ${playUrl}`); + + const endpointId = await createWebhookTestEndpoint({ + appId, + playUrl, + filterTypes, + }); + console.log(`Created Svix endpoint: ${endpointId}`); + + const cleanup = async () => { + await deleteWebhookTestEndpoint({ appId, endpointId }); + console.log(`Deleted Svix endpoint: ${endpointId}`); + }; + + return { playToken, endpointId, cleanup }; +}; + +/** + * Resolves the org's Svix sandbox app ID or throws a clear error. + * Keeps the guard-clause out of every test file. + */ +export const getTestSvixAppId = ({ + svixConfig, +}: { + svixConfig?: { sandbox_app_id?: string } | null; +}): string => { + const appId = svixConfig?.sandbox_app_id; + if (!appId) + throw new Error( + "Test org does not have svix_config.sandbox_app_id configured. " + + "Cannot run webhook integration tests without Svix app.", + ); + return appId; +}; diff --git a/shared/api/billingControls/entityBillingControls.ts b/shared/api/billingControls/entityBillingControls.ts index 693f5b15a..179d63638 100644 --- a/shared/api/billingControls/entityBillingControls.ts +++ b/shared/api/billingControls/entityBillingControls.ts @@ -1,10 +1,14 @@ import { z } from "zod/v4"; import { ApiSpendLimitSchema } from "./spendLimit.js"; +import { ApiUsageAlertSchema } from "./usageAlert.js"; export const ApiEntityBillingControlsSchema = z.object({ spend_limits: z.array(ApiSpendLimitSchema).optional().meta({ description: "List of overage spend limits per feature.", }), + usage_alerts: z.array(ApiUsageAlertSchema).optional().meta({ + description: "List of usage alert configurations per feature.", + }), }); export const ApiEntityBillingControlsParamsSchema = diff --git a/shared/api/customers/cusFeatures/utils/check/getFeatureToUseForCheck.ts b/shared/api/customers/cusFeatures/utils/check/getFeatureToUseForCheck.ts index 1fbba4000..378015d2e 100644 --- a/shared/api/customers/cusFeatures/utils/check/getFeatureToUseForCheck.ts +++ b/shared/api/customers/cusFeatures/utils/check/getFeatureToUseForCheck.ts @@ -30,7 +30,7 @@ export const getFeatureToUseForCheck = ({ apiSubject, feature, requiredBalance, - }) + }).allowed ) { return feature; } @@ -45,7 +45,7 @@ export const getFeatureToUseForCheck = ({ apiSubject, feature: creditSystem, requiredBalance, - }) + }).allowed ) { return creditSystem; } diff --git a/shared/api/customers/cusFeatures/utils/convert/apiBalanceToAllowed.ts b/shared/api/customers/cusFeatures/utils/convert/apiBalanceToAllowed.ts index 449d83dc7..f5880d406 100644 --- a/shared/api/customers/cusFeatures/utils/convert/apiBalanceToAllowed.ts +++ b/shared/api/customers/cusFeatures/utils/convert/apiBalanceToAllowed.ts @@ -5,58 +5,53 @@ import type { Feature } from "@models/featureModels/featureModels"; import { isBooleanFeature, notNullish } from "@utils/index"; import { Decimal } from "decimal.js"; +export type AllowedResult = { + allowed: boolean; + limitType?: "included" | "max_purchase" | "spend_limit"; +}; + +export type ApiBalanceInput = { + apiBalance: ApiBalanceV1; + apiSubject: ApiSubjectV0; + feature: Feature; + requiredBalance: number; +}; + export const apiBalanceToAllowed = ({ apiBalance, apiSubject, feature, requiredBalance, -}: { - apiBalance: ApiBalanceV1; - apiSubject: ApiSubjectV0; - feature: Feature; - requiredBalance: number; -}) => { - if (!apiBalance) { - return false; - } +}: ApiBalanceInput): AllowedResult => { + if (!apiBalance) return { allowed: false }; - // 1. Boolean - if (isBooleanFeature({ feature })) { - return true; - } + if (isBooleanFeature({ feature })) return { allowed: true }; - // 2. Unlimited - if (apiBalance.unlimited) { - return true; - } + if (apiBalance.unlimited) return { allowed: true }; - // 2. Required balance is negative - if (requiredBalance < 0) { - return true; - } + if (requiredBalance < 0) return { allowed: true }; - // 3. Overage allowed if (apiBalance.overage_allowed) { - // 1. Available overage - const availableOverage = apiBalanceV1ToAvailableOverage({ + const { availableOverage, reason } = apiBalanceV1ToAvailableOverage({ apiBalance, apiSubject, feature, }); if (notNullish(availableOverage)) { - return new Decimal(availableOverage) + const allowed = new Decimal(availableOverage) .add(apiBalance.remaining) .gte(requiredBalance); + + if (!allowed) return { allowed: false, limitType: reason }; + return { allowed: true }; } - return true; + return { allowed: true }; } - // 4. Balance >= required balance (V1 uses 'remaining' instead of 'current_balance') - if (new Decimal(apiBalance.remaining).gte(requiredBalance)) { - return true; - } + if (new Decimal(apiBalance.remaining).gte(requiredBalance)) + return { allowed: true }; - return false; + return { allowed: false, limitType: "included" }; }; diff --git a/shared/api/customers/cusFeatures/utils/convert/apiBalanceV1ToAvailableOverage.ts b/shared/api/customers/cusFeatures/utils/convert/apiBalanceV1ToAvailableOverage.ts index ced0cbd19..586ee9d0b 100644 --- a/shared/api/customers/cusFeatures/utils/convert/apiBalanceV1ToAvailableOverage.ts +++ b/shared/api/customers/cusFeatures/utils/convert/apiBalanceV1ToAvailableOverage.ts @@ -39,6 +39,11 @@ export const apiBalanceV1ToMaxOverage = ({ ); }; +export type AvailableOverageResult = { + availableOverage: number | undefined; + reason?: "spend_limit" | "max_purchase"; +}; + export const apiBalanceV1ToAvailableOverage = ({ apiBalance, apiSubject, @@ -47,7 +52,7 @@ export const apiBalanceV1ToAvailableOverage = ({ apiBalance: ApiBalanceV1; apiSubject: ApiSubjectV0; feature: Feature; -}): number | undefined => { +}): AvailableOverageResult => { const overage = apiBalanceV1ToOverage({ apiBalance }); const spendLimit: ApiSpendLimit | undefined = apiSubject ? apiSubjectToSpendLimit({ @@ -57,17 +62,26 @@ export const apiBalanceV1ToAvailableOverage = ({ : undefined; if (spendLimit?.overage_limit !== undefined) { - return Math.max( - 0, - new Decimal(spendLimit.overage_limit).sub(overage).toNumber(), - ); + return { + availableOverage: Math.max( + 0, + new Decimal(spendLimit.overage_limit).sub(overage).toNumber(), + ), + reason: "spend_limit", + }; } const maxOverage = apiBalanceV1ToMaxOverage({ apiBalance }); if (maxOverage === undefined) { - return undefined; + return { availableOverage: undefined }; } - return Math.max(0, new Decimal(maxOverage).sub(overage).toNumber()); + return { + availableOverage: Math.max( + 0, + new Decimal(maxOverage).sub(overage).toNumber(), + ), + reason: "max_purchase", + }; }; diff --git a/shared/api/webhooks/balances/balancesLimitReached.ts b/shared/api/webhooks/balances/balancesLimitReached.ts new file mode 100644 index 000000000..489fb1cc3 --- /dev/null +++ b/shared/api/webhooks/balances/balancesLimitReached.ts @@ -0,0 +1,33 @@ +import { z } from "zod/v4"; + +export const LimitType = z.enum(["included", "max_purchase", "spend_limit"]); + +export const BALANCES_LIMIT_REACHED_EXAMPLE = { + customer_id: "org_123", + entity_id: "workspace_abc", + feature_id: "api_calls", + limit_type: "included", +}; + +export const BalancesLimitReachedSchema = z + .object({ + customer_id: z.string().meta({ + description: "The ID of the customer who hit the limit.", + }), + entity_id: z.string().optional().meta({ + description: + "The entity ID, if the limit was reached on a specific entity.", + }), + feature_id: z.string().meta({ + description: "The feature ID whose limit was reached.", + }), + limit_type: LimitType.meta({ + description: + "Which limit was hit: included allowance, max purchase cap, or spend limit.", + }), + }) + .meta({ + examples: [BALANCES_LIMIT_REACHED_EXAMPLE], + }); + +export type BalancesLimitReached = z.infer; diff --git a/shared/api/webhooks/balances/balancesUsageAlertTriggered.ts b/shared/api/webhooks/balances/balancesUsageAlertTriggered.ts new file mode 100644 index 000000000..1f9a65c00 --- /dev/null +++ b/shared/api/webhooks/balances/balancesUsageAlertTriggered.ts @@ -0,0 +1,53 @@ +import { z } from "zod/v4"; +import { UsageAlertThresholdType } from "../../billingControls/usageAlert.js"; + +export const BalancesUsageAlertTriggeredAlertSchema = z.object({ + name: z.string().optional().meta({ + description: "User-defined label for the alert, if provided.", + }), + threshold: z.number().meta({ + description: "The threshold value that was crossed.", + }), + threshold_type: UsageAlertThresholdType.meta({ + description: + "Whether the threshold is an absolute usage count or a percentage.", + }), +}); + +export const BALANCES_USAGE_ALERT_TRIGGERED_EXAMPLE = { + customer_id: "org_123", + feature_id: "api_calls", + entity_id: "workspace_abc", + usage_alert: { + name: "80% usage warning", + threshold: 80, + threshold_type: "usage_percentage_threshold", + }, +}; + +export const BalancesUsageAlertTriggeredSchema = z + .object({ + customer_id: z.string().meta({ + description: "The ID of the customer whose usage alert was triggered.", + }), + feature_id: z.string().meta({ + description: "The feature ID the alert applies to.", + }), + entity_id: z.string().optional().meta({ + description: + "The entity ID the alert applies to, if the usage was entity-scoped.", + }), + usage_alert: BalancesUsageAlertTriggeredAlertSchema.meta({ + description: "Details of the usage alert that was triggered.", + }), + }) + .meta({ + examples: [BALANCES_USAGE_ALERT_TRIGGERED_EXAMPLE], + }); + +export type BalancesUsageAlertTriggered = z.infer< + typeof BalancesUsageAlertTriggeredSchema +>; +export type BalancesUsageAlertTriggeredAlert = z.infer< + typeof BalancesUsageAlertTriggeredAlertSchema +>; diff --git a/shared/api/webhooks/balancesThresholdReached.ts b/shared/api/webhooks/balancesThresholdReached.ts deleted file mode 100644 index 9e32d48cd..000000000 --- a/shared/api/webhooks/balancesThresholdReached.ts +++ /dev/null @@ -1,69 +0,0 @@ -import { z } from "zod/v4"; -import { UsageAlertThresholdType } from "../billingControls/usageAlert.js"; - -export const BalancesThresholdType = z.enum([ - "usage_alert", - "allowance_used", - "limit_reached", -]); - -export const BalancesThresholdReachedUsageAlertSchema = z.object({ - name: z.string().optional().meta({ - description: "User-defined label for the alert, if provided.", - }), - threshold: z.number().meta({ - description: "The threshold value that was crossed.", - }), - threshold_type: UsageAlertThresholdType.meta({ - description: - "Whether the threshold is an absolute usage count or a percentage.", - }), -}); - -export const BalancesThresholdReachedSchema = z - .object({ - customer_id: z.string().meta({ - description: "The ID of the customer whose threshold was reached.", - }), - feature_id: z.string().meta({ - description: "The feature ID the threshold applies to.", - }), - threshold_type: BalancesThresholdType.meta({ - description: "The type of threshold that was reached.", - }), - usage_alert: BalancesThresholdReachedUsageAlertSchema.optional().meta({ - description: - "Details of the usage alert that was triggered. Required when threshold_type is usage_alert.", - }), - }) - .check((ctx) => { - const { threshold_type, usage_alert } = ctx.value; - - if (threshold_type === "usage_alert" && !usage_alert) { - ctx.issues.push({ - code: "custom", - input: ctx.value, - message: - "usage_alert is required when threshold_type is usage_alert", - path: ["usage_alert"], - }); - return; - } - - if (threshold_type !== "usage_alert" && usage_alert) { - ctx.issues.push({ - code: "custom", - input: ctx.value, - message: - "usage_alert must not be provided when threshold_type is not usage_alert", - path: ["usage_alert"], - }); - } - }); - -export type BalancesThresholdReached = z.infer< - typeof BalancesThresholdReachedSchema ->; -export type BalancesThresholdReachedUsageAlert = z.infer< - typeof BalancesThresholdReachedUsageAlertSchema ->; diff --git a/shared/api/webhooks/index.ts b/shared/api/webhooks/index.ts index 402494dda..d44177ee6 100644 --- a/shared/api/webhooks/index.ts +++ b/shared/api/webhooks/index.ts @@ -1 +1,5 @@ -export * from "./balancesThresholdReached.js"; +export * from "./balances/balancesLimitReached.js"; +export * from "./balances/balancesUsageAlertTriggered.js"; +export * from "./vercel/index.js"; +export * from "./webhookEventType.js"; +export * from "./webhookRegistry.js"; diff --git a/shared/api/webhooks/vercel/index.ts b/shared/api/webhooks/vercel/index.ts new file mode 100644 index 000000000..7bd43c800 --- /dev/null +++ b/shared/api/webhooks/vercel/index.ts @@ -0,0 +1,4 @@ +export * from "./vercelResourceDeleted.js"; +export * from "./vercelResourceProvisioned.js"; +export * from "./vercelResourceRotateSecrets.js"; +export * from "./vercelWebhookEvent.js"; diff --git a/shared/api/webhooks/vercel/vercelResourceDeleted.ts b/shared/api/webhooks/vercel/vercelResourceDeleted.ts new file mode 100644 index 000000000..33dfc1074 --- /dev/null +++ b/shared/api/webhooks/vercel/vercelResourceDeleted.ts @@ -0,0 +1,14 @@ +import { z } from "zod/v4"; + +export const VercelResourceDeletedSchema = z.object({ + resource: z + .object({ + id: z.string().meta({ + description: "The unique identifier of the deleted resource.", + }), + }) + .meta({ description: "The resource that was deleted." }), + installation_id: z.string().meta({ + description: "The Vercel integration configuration ID.", + }), +}); diff --git a/shared/api/webhooks/vercel/vercelResourceProvisioned.ts b/shared/api/webhooks/vercel/vercelResourceProvisioned.ts new file mode 100644 index 000000000..8a4ce4679 --- /dev/null +++ b/shared/api/webhooks/vercel/vercelResourceProvisioned.ts @@ -0,0 +1,21 @@ +import { z } from "zod/v4"; + +export const VercelResourceProvisionedSchema = z.object({ + resource: z + .object({ + id: z.string().meta({ + description: "The unique identifier of the provisioned resource.", + }), + name: z.string().meta({ + description: "The display name of the provisioned resource.", + }), + }) + .meta({ description: "The resource that was provisioned." }), + installation_id: z.string().meta({ + description: "The Vercel integration configuration ID.", + }), + access_token: z.string().meta({ + description: + "An access token that can be used to patch the resource's secrets.", + }), +}); diff --git a/shared/api/webhooks/vercel/vercelResourceRotateSecrets.ts b/shared/api/webhooks/vercel/vercelResourceRotateSecrets.ts new file mode 100644 index 000000000..003847618 --- /dev/null +++ b/shared/api/webhooks/vercel/vercelResourceRotateSecrets.ts @@ -0,0 +1,17 @@ +import { z } from "zod/v4"; + +export const VercelResourceRotateSecretsSchema = z.object({ + resource: z + .object({ + id: z.string().meta({ + description: "The unique identifier of the resource.", + }), + }) + .meta({ description: "The resource whose secrets should be rotated." }), + installation_id: z.string().meta({ + description: "The Vercel integration configuration ID.", + }), + vercel_request_body: z.any().meta({ + description: "The raw request body from Vercel's rotation request.", + }), +}); diff --git a/shared/api/webhooks/vercel/vercelWebhookEvent.ts b/shared/api/webhooks/vercel/vercelWebhookEvent.ts new file mode 100644 index 000000000..4f846c3d8 --- /dev/null +++ b/shared/api/webhooks/vercel/vercelWebhookEvent.ts @@ -0,0 +1,10 @@ +import { z } from "zod/v4"; + +export const VercelWebhookEventSchema = z.object({ + installation_id: z.string().meta({ + description: "The Vercel integration configuration ID.", + }), + event: z.any().meta({ + description: "The raw Vercel webhook event payload.", + }), +}); diff --git a/shared/api/webhooks/webhookEventType.ts b/shared/api/webhooks/webhookEventType.ts new file mode 100644 index 000000000..377c78986 --- /dev/null +++ b/shared/api/webhooks/webhookEventType.ts @@ -0,0 +1,12 @@ +export enum WebhookEventType { + CustomerProductsUpdated = "customer.products.updated", + CustomerThresholdReached = "customer.threshold_reached", + + BalancesUsageAlertTriggered = "balances.usage_alert_triggered", + BalancesLimitReached = "balances.limit_reached", + + VercelResourcesDeleted = "vercel.resources.deleted", + VercelResourcesProvisioned = "vercel.resources.provisioned", + VercelResourcesRotateSecrets = "vercel.resources.rotate_secrets", + VercelWebhooksEvent = "vercel.webhooks.event", +} diff --git a/shared/api/webhooks/webhookRegistry.ts b/shared/api/webhooks/webhookRegistry.ts new file mode 100644 index 000000000..bee687f7a --- /dev/null +++ b/shared/api/webhooks/webhookRegistry.ts @@ -0,0 +1,83 @@ +import type { z } from "zod/v4"; +import { BalancesLimitReachedSchema } from "./balances/balancesLimitReached.js"; +import { BalancesUsageAlertTriggeredSchema } from "./balances/balancesUsageAlertTriggered.js"; +import { VercelResourceDeletedSchema } from "./vercel/vercelResourceDeleted.js"; +import { VercelResourceProvisionedSchema } from "./vercel/vercelResourceProvisioned.js"; +import { VercelResourceRotateSecretsSchema } from "./vercel/vercelResourceRotateSecrets.js"; +import { VercelWebhookEventSchema } from "./vercel/vercelWebhookEvent.js"; +import { WebhookEventType } from "./webhookEventType.js"; + +export interface WebhookDefinition { + eventType: string; + operationId: string; + title: string; + schema?: z.ZodType; + description: string; + group: string; + deprecated?: boolean; + archived?: boolean; + featureFlags?: string[]; +} + +export const webhookRegistry: WebhookDefinition[] = [ + // ── Balances ────────────────────────────────────────────────────────── + { + eventType: WebhookEventType.BalancesUsageAlertTriggered, + operationId: "balancesUsageAlertTriggered", + title: "Usage Alert Triggered", + schema: BalancesUsageAlertTriggeredSchema, + group: "Balances", + description: + "Fired when a customer crosses a configured usage alert threshold.", + }, + { + eventType: WebhookEventType.BalancesLimitReached, + operationId: "balancesLimitReached", + title: "Limit Reached", + schema: BalancesLimitReachedSchema, + group: "Balances", + description: + "Fired when a customer reaches the limit for a feature (included allowance, max purchase, or spend limit).", + }, + + // ── Vercel ──────────────────────────────────────────────────────────── + { + eventType: WebhookEventType.VercelResourcesDeleted, + operationId: "vercelResourcesDeleted", + title: "Resource Deleted", + schema: VercelResourceDeletedSchema, + group: "Vercel", + description: + "When a Vercel resource is deleted, you'll need to handle de-provisioning any API keys or other non-Autumn controlled data for this user.", + featureFlags: ["vercel"], + }, + { + eventType: WebhookEventType.VercelResourcesProvisioned, + operationId: "vercelResourcesProvisioned", + title: "Resource Provisioned", + schema: VercelResourceProvisionedSchema, + group: "Vercel", + description: + "When a Vercel resource is created, you'll need to provision a secret key for your service. Then you can use the provided access token to patch the resource's secrets.", + featureFlags: ["vercel"], + }, + { + eventType: WebhookEventType.VercelResourcesRotateSecrets, + operationId: "vercelResourcesRotateSecrets", + title: "Rotate Secrets", + schema: VercelResourceRotateSecretsSchema, + group: "Vercel", + description: + "This event is sent when Vercel requires a resource's secrets to be rotated.", + featureFlags: ["vercel"], + }, + { + eventType: WebhookEventType.VercelWebhooksEvent, + operationId: "vercelWebhooksEvent", + title: "Webhook Event", + schema: VercelWebhookEventSchema, + group: "Vercel", + description: "Passthrough webhook for Vercel events.", + featureFlags: ["vercel"], + }, +]; diff --git a/shared/enums/WebhookEventType.ts b/shared/enums/WebhookEventType.ts deleted file mode 100644 index 10b1f149c..000000000 --- a/shared/enums/WebhookEventType.ts +++ /dev/null @@ -1,5 +0,0 @@ -export enum WebhookEventType { - CustomerProductsUpdated = "customer.products.updated", - CustomerThresholdReached = "customer.threshold_reached", - BalancesThresholdReached = "balances.threshold_reached", -} diff --git a/shared/index.ts b/shared/index.ts index 5b8cd450f..8beded914 100644 --- a/shared/index.ts +++ b/shared/index.ts @@ -30,8 +30,7 @@ export * from "./enums/ErrCode"; export * from "./enums/LoggerAction"; // ENUMS export * from "./enums/SuccessCode"; -export * from "./enums/WebhookEventType"; -// Webhook Schemas +// Webhook Schemas + WebhookEventType enum export * from "./api/webhooks/index"; // Internal API (checkout app, dashboard) export * from "./internal/index"; diff --git a/shared/models/cusModels/billingControls/entityBillingControls.ts b/shared/models/cusModels/billingControls/entityBillingControls.ts index afde88943..d815fcd2a 100644 --- a/shared/models/cusModels/billingControls/entityBillingControls.ts +++ b/shared/models/cusModels/billingControls/entityBillingControls.ts @@ -1,10 +1,14 @@ import { z } from "zod/v4"; import { DbSpendLimitSchema } from "./spendLimit.js"; +import { DbUsageAlertSchema } from "./usageAlert.js"; export const EntityBillingControlsSchema = z.object({ spend_limits: z.array(DbSpendLimitSchema).optional().meta({ description: "List of overage spend limits per feature.", }), + usage_alerts: z.array(DbUsageAlertSchema).optional().meta({ + description: "List of usage alert configurations per feature.", + }), }); export type EntityBillingControls = z.infer; diff --git a/shared/models/cusModels/billingControls/usageAlert.ts b/shared/models/cusModels/billingControls/usageAlert.ts index f47fe5c29..e838e5dd3 100644 --- a/shared/models/cusModels/billingControls/usageAlert.ts +++ b/shared/models/cusModels/billingControls/usageAlert.ts @@ -1,8 +1,8 @@ import { z } from "zod/v4"; export const UsageAlertThresholdType = z.enum([ - "usage_threshold", - "usage_percentage_threshold", + "usage", + "usage_percentage", ]); export const DbUsageAlertSchema = z @@ -16,7 +16,7 @@ export const DbUsageAlertSchema = z }), threshold: z.number().min(0).meta({ description: - "The threshold value that triggers the alert. For usage_threshold, this is an absolute count. For usage_percentage_threshold, this is a percentage (0-100).", + "The threshold value that triggers the alert. For usage, this is an absolute count. For usage_percentage, this is a percentage (0-100).", }), threshold_type: UsageAlertThresholdType.meta({ description: @@ -30,13 +30,13 @@ export const DbUsageAlertSchema = z .check((ctx) => { const { threshold_type, threshold } = ctx.value; - if (threshold_type === "usage_percentage_threshold" && threshold > 100) { + if (threshold_type === "usage_percentage" && threshold > 100) { ctx.issues.push({ code: "custom", input: threshold, path: ["threshold"], message: - "Threshold must be between 0 and 100 for usage_percentage_threshold", + "Threshold must be between 0 and 100 for usage_percentage", }); } }); diff --git a/shared/models/cusModels/entityModels/entityModels.ts b/shared/models/cusModels/entityModels/entityModels.ts index f63ffbace..25c8413f0 100644 --- a/shared/models/cusModels/entityModels/entityModels.ts +++ b/shared/models/cusModels/entityModels/entityModels.ts @@ -1,6 +1,9 @@ import { z } from "zod/v4"; import type { Feature } from "../../featureModels/featureModels.js"; -import { DbSpendLimitSchema } from "../billingControls/customerBillingControls.js"; +import { + DbSpendLimitSchema, + DbUsageAlertSchema, +} from "../billingControls/customerBillingControls.js"; export const EntitySchema = z.object({ id: z.string().nullable(), @@ -14,6 +17,7 @@ export const EntitySchema = z.object({ feature_id: z.string(), internal_feature_id: z.string(), spend_limits: z.array(DbSpendLimitSchema).nullish(), + usage_alerts: z.array(DbUsageAlertSchema).nullish(), }); // export const CreateEntitySchema = z.object({ diff --git a/shared/models/cusModels/entityModels/entityTable.ts b/shared/models/cusModels/entityModels/entityTable.ts index 9715bef54..5cfe847b6 100644 --- a/shared/models/cusModels/entityModels/entityTable.ts +++ b/shared/models/cusModels/entityModels/entityTable.ts @@ -11,7 +11,10 @@ import { } from "drizzle-orm/pg-core"; import { features } from "../../featureModels/featureTable.js"; import { organizations } from "../../orgModels/orgTable.js"; -import type { DbSpendLimit } from "../billingControls/customerBillingControls.js"; +import type { + DbSpendLimit, + DbUsageAlert, +} from "../billingControls/customerBillingControls.js"; import { customers } from "../cusTable.js"; export const entities = pgTable( @@ -27,6 +30,7 @@ export const entities = pgTable( deleted: boolean().default(false).notNull(), internal_feature_id: text("internal_feature_id"), spend_limits: jsonb().$type(), + usage_alerts: jsonb().$type(), // Optional... feature_id: text("feature_id"),