{
"error": {
"code": "ERR_BAD_REQUEST",
"message": "Bad request — the input payload is malformed, missing required fields, or contains invalid data."
}
}
{
"error": {
"code": "ERR_NOT_FOUND",
"message": "Not found — the resource you are looking for does not exist."
}
}
Subscription Upgrades
Create a subscription upgrade
Creates a subscription upgrade that can be used to add or remove add-ons from an existing contract term.
Use /subscriptions/{subscription_id}/upgrade/{order_id}/estimate to preview pricing before confirming
Use /subscriptions/{subscription_id}/upgrade/{order_id}/start to begin the upgrade
The upgrade keeps the subscription’s CRM account. Pass crm_opportunity_id to link it to its own opportunity in your connected CRM; without one, no opportunity is linked or created.
How plan_id affects pricing:
plan_id omitted — the upgrade keeps the subscription’s current plan version and contracted pricing (customers stay grandfathered). If bricks includes a brick that doesn’t exist on the current plan version, it is pulled in from that plan’s latest published version, producing a merged plan version.
plan_id provided — the upgrade switches to the latest published version of the referenced plan. If bricks references a brick that only exists on the subscription’s prior plan version, it is carried over into a merged plan version.
plan_id may reference a different plan than the subscription’s current plan; that is how cross-plan upgrades are expressed.
plan_id is only honoured when bricks is also provided. Sending plan_id without bricks returns 400.
How bricks affects existing discounts:
Per-brick discounts are replaced, not merged. The discount sent on a brick becomes that brick’s complete set of discounts for this order, and a brick sent without a discount ends up with none — any discount it previously carried is dropped.
This applies to every brick in the payload, not only the ones being changed. A brick included solely to keep it on the order still needs its discount resent, or it loses it.
Read the current values from the subscription’s line items — discount is returned there in the same shape this endpoint accepts — and send them back for every brick whose discount should carry over.
Subscription upgrade input serializer for upgrading a subscription order.
This payload has two forms — see anyOf:
Single-phase — omit phases; the order-level starts_at, contract_length, billing_frequency and bricks define the one phase and are required.
Multi-phase — send phases; the phases own the timeline, billing frequency and bricks, and the order-level equivalents become optional (omitted, they are derived from the phases).
The fields are declared optional because OpenAPI 3.0 cannot make one field's required depend on another. Sending neither form is a 400.
The effective date of the subscription upgrade. Required only when phases is omitted: when phases is provided the phases own the timeline, so the effective date is taken from the first phase's starts_at and this order-level value is ignored.
The bricks included in subscription upgrade. Quantity is used to upgrade the add-on quantity (ie. adding 2 more units should be quantity 2 -> quantity 4). For usage, quantity is used to set the pre-commitment (ie. previously having 5 pre-commitment quantity and updating it to 10 would update the pre-commitment quantity to 10.)
Optional ID of the opportunity (deal in HubSpot) in your connected CRM to link the subscription to. Requires a linked CRM account, and must not be linked to another subscription. Omit for no change; pass an empty string to unlink it.
Optional plan ID for the upgrade. When provided, the upgrade switches to the latest published version of that plan; when omitted, it keeps the subscription's existing plan version and contracted pricing. Must be sent together with bricks — plan_id alone is rejected with 400. See the endpoint description for full semantics including cross-plan upgrades and merged plan versions.
Discount coupon codes to apply to the subscription upgrade. Currently only supports one discount coupon - only the first one in the list will be applied.
Optional list of phases for a multi-phase upgrade. Each phase's phase_position must match a phase on the base order; only the phases being changed need to be sent, and omitted positions are inherited from the base order unchanged. Order-level bricks and starts_at are ignored when phases are provided — the phases own the timeline and the first phase's starts_at is the upgrade's effective date.
{"docsConfig":{"theme":"mint","$schema":"https://mintlify.com/docs.json","name":"Salesbricks","colors":{"primary":"#197F78","light":"#26BFB4","dark":"#197F78"},"logo":{"light":"https://mintcdn.com/salesbricks/3GVA0K12Q7dXW89y/logo/light.svg?fit=max\u0026auto=format\u0026n=3GVA0K12Q7dXW89y\u0026q=85\u0026s=ead3e65ff72970d53a9cd22de50bd8fc","dark":"https://mintcdn.com/salesbricks/3GVA0K12Q7dXW89y/logo/dark.svg?fit=max\u0026auto=format\u0026n=3GVA0K12Q7dXW89y\u0026q=85\u0026s=786876a66955115a9896bb4ce9e0f779","href":"https://www.salesbricks.com"},"favicon":"https://mintcdn.com/salesbricks/3GVA0K12Q7dXW89y/favicon.svg?fit=max\u0026auto=format\u0026n=3GVA0K12Q7dXW89y\u0026q=85\u0026s=149c42d5e530bbd556361118b756ccb8","api":{"playground":{"display":"interactive"},"mdx":{"auth":{"method":"key"},"server":["https://api.salesbricks.com"]}},"background":{"color":{"light":"#FFFFFF","dark":"#0A0A0A"}},"navbar":{"primary":{"type":"button","label":"Log in","href":"https://app.salesbricks.com/login"}},"footer":{"socials":{"linkedin":"https://www.linkedin.com/company/salesbricks","x":"https://twitter.com/getsalesbricks","instagram":"https://www.instagram.com/salesbricks"}},"search":{"prompt":"Search Salesbricks docs..."},"seo":{"indexing":"navigable"},"styling":{"latex":true},"navigation":{"pages":[]}},"deployment":{"deploymentMetadataValue":{"subdomain":"salesbricks","hasAudioNarration":false,"actualSubdomain":"salesbricks","customDomains":["docs.salesbricks.com"],"gitSource":{"type":"github","owner":"goderecho","repo":"docs","deployBranch":"main","contentDirectory":"","isPrivate":true,"mountPath":"","label":""},"chroma":{"liveDeploymentHistoryId":"6ae4d297f0f0e506e23495aa","collectionId":"e22ee52d-f716-4e2e-b522-09bd305a1646","schemaVersion":"v3","latestBuiltDeploymentHistoryId":"6ae4d297f0f0e506e23495aa"},"feedback":{"thumbs":false},"entitlements":{"AI_CHAT":{"status":"ENABLED"},"WEB_MCP":{"status":"ENABLED"},"NARRATION":{"status":"ENABLED"}},"buildId":"6aed16ea8eec1bf8be06828a","clientVersion":"0.0.4076","searchFilterCounts":[{"language":"default","tag":"APIs \u0026 Webhooks","count":127},{"language":"default","tag":"REST API Endpoints","count":83},{"language":"default","tag":"Documentation","count":40},{"language":"default","tag":"Webhooks","count":34},{"language":"default","tag":"Integrations","count":19},{"language":"default","tag":"Invoices","count":13},{"language":"default","tag":"Subscriptions","count":12},{"language":"default","tag":"Usage","count":11},{"language":"default","tag":"Payment Methods","count":11},{"language":"default","tag":"Order Webhooks","count":10}]},"assistantConfig":{},"basePath":"","hasChatPermissions":true,"hasWebMcpPermissions":true,"toggles":[{"name":"kill-isr","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"agent-mintlify-slack","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"agent-integrations-settings","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"rbac-expansion","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automations-pr-grouping","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"custom-prefix","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"analytics-v7","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"user-flows-analytics","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"no-publish-flow","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-onboarding","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"llms-txt-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"snapshot-serving-live","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"stripTemperatureMiddleware","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"support-platform-pylon-zendesk","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"snapshot-serving","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"instant-rollback","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"granular-notifications-server","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"granular-notifications","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automations-fable","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"fixed-ai-action-pricing","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automation-resolve-merge-conflict","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"scoped-publishing","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"mintql","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"page-level-analytics","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"editor-version-history-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"billing-page-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"full-page-search","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workspace-projects","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"assistant-v5","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"fork-pr-previews","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"revalidation-jwt","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-sso-scim","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"hobby-abuse-scan","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"dashboard-inbox","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-signup","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"turbopuffer-dual-write","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-enabled","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"approve-review-flow","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"sso-setup-deadline-banner","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"turbopuffer-serve","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"live-agents","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"comment-mode","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false}],"googleFontsInlined":false},"customCss":[{"filePath":"style.css","content":"table.two-column td,table.two-column th{width:50%}"}],"page":{"pagePath":"api-reference/subscription-upgrades/create-a-subscription-upgrade","slug":"/api-reference/subscription-upgrades/create-a-subscription-upgrade","pageMetadata":{"title":"Create a subscription upgrade","description":"Creates a subscription upgrade that can be used to add or remove add-ons from an existing contract term.\n\n- Use `/subscriptions/{subscription_id}/upgrade/{order_id}/estimate` to preview pricing before confirming\n- Use `/subscriptions/{subscription_id}/upgrade/{order_id}/start` to begin the upgrade\n\nThe upgrade keeps the subscription's CRM account. Pass `crm_opportunity_id` to link it to its own opportunity in your connected CRM; without one, no opportunity is linked or created.\n\n**How `plan_id` affects pricing:**\n\n- **`plan_id` omitted** — the upgrade keeps the subscription's current plan version and contracted pricing (customers stay grandfathered). If `bricks` includes a brick that doesn't exist on the current plan version, it is pulled in from that plan's latest published version, producing a merged plan version.\n- **`plan_id` provided** — the upgrade switches to the latest published version of the referenced plan. If `bricks` references a brick that only exists on the subscription's prior plan version, it is carried over into a merged plan version.\n- `plan_id` may reference a different plan than the subscription's current plan; that is how cross-plan upgrades are expressed.\n- **`plan_id` is only honoured when `bricks` is also provided.** Sending `plan_id` without `bricks` returns 400.\n\n**How `bricks` affects existing discounts:**\n\nPer-brick discounts are **replaced, not merged**. The `discount` sent on a brick becomes that brick's complete set of discounts for this order, and a brick sent without a `discount` ends up with none — any discount it previously carried is dropped.\n\nThis applies to every brick in the payload, not only the ones being changed. A brick included solely to keep it on the order still needs its `discount` resent, or it loses it.\n\nRead the current values from the subscription's line items — `discount` is returned there in the same shape this endpoint accepts — and send them back for every brick whose discount should carry over.","deprecated":null,"version":null,"openapi":"https://api.salesbricks.com/api/v2/openapi.yaml post /subscriptions/{subscription_id}/upgrade","href":"/api-reference/subscription-upgrades/create-a-subscription-upgrade","autogeneratedByOpenApi":true},"description":{"compiledSource":"\"use strict\";\nconst {Fragment: _Fragment, jsx: _jsx, jsxs: _jsxs} = arguments[0];\nconst {useMDXComponents: _provideComponents} = arguments[0];\nfunction _createMdxContent(props) {\n const _components = {\n code: \"code\",\n li: \"li\",\n p: \"p\",\n strong: \"strong\",\n ul: \"ul\",\n ..._provideComponents(),\n ...props.components\n };\n return _jsxs(_Fragment, {\n children: [_jsx(_components.p, {\n children: \"Creates a subscription upgrade that can be used to add or remove add-ons from an existing contract term.\"\n }), \"\\n\", _jsxs(_components.ul, {\n children: [\"\\n\", _jsxs(_components.li, {\n children: [\"Use \", _jsx(_components.code, {\n children: \"/subscriptions/{subscription_id}/upgrade/{order_id}/estimate\"\n }), \" to preview pricing before confirming\"]\n }), \"\\n\", _jsxs(_components.li, {\n children: [\"Use \", _jsx(_components.code, {\n children: \"/subscriptions/{subscription_id}/upgrade/{order_id}/start\"\n }), \" to begin the upgrade\"]\n }), \"\\n\"]\n }), \"\\n\", _jsxs(_components.p, {\n children: [\"The upgrade keeps the subscription’s CRM account. Pass \", _jsx(_components.code, {\n children: \"crm_opportunity_id\"\n }), \" to link it to its own opportunity in your connected CRM; without one, no opportunity is linked or created.\"]\n }), \"\\n\", _jsx(_components.p, {\n children: _jsxs(_components.strong, {\n children: [\"How \", _jsx(_components.code, {\n children: \"plan_id\"\n }), \" affects pricing:\"]\n })\n }), \"\\n\", _jsxs(_components.ul, {\n children: [\"\\n\", _jsxs(_components.li, {\n children: [_jsxs(_components.strong, {\n children: [_jsx(_components.code, {\n children: \"plan_id\"\n }), \" omitted\"]\n }), \" — the upgrade keeps the subscription’s current plan version and contracted pricing (customers stay grandfathered). If \", _jsx(_components.code, {\n children: \"bricks\"\n }), \" includes a brick that doesn’t exist on the current plan version, it is pulled in from that plan’s latest published version, producing a merged plan version.\"]\n }), \"\\n\", _jsxs(_components.li, {\n children: [_jsxs(_components.strong, {\n children: [_jsx(_components.code, {\n children: \"plan_id\"\n }), \" provided\"]\n }), \" — the upgrade switches to the latest published version of the referenced plan. If \", _jsx(_components.code, {\n children: \"bricks\"\n }), \" references a brick that only exists on the subscription’s prior plan version, it is carried over into a merged plan version.\"]\n }), \"\\n\", _jsxs(_components.li, {\n children: [_jsx(_components.code, {\n children: \"plan_id\"\n }), \" may reference a different plan than the subscription’s current plan; that is how cross-plan upgrades are expressed.\"]\n }), \"\\n\", _jsxs(_components.li, {\n children: [_jsxs(_components.strong, {\n children: [_jsx(_components.code, {\n children: \"plan_id\"\n }), \" is only honoured when \", _jsx(_components.code, {\n children: \"bricks\"\n }), \" is also provided.\"]\n }), \" Sending \", _jsx(_components.code, {\n children: \"plan_id\"\n }), \" without \", _jsx(_components.code, {\n children: \"bricks\"\n }), \" returns 400.\"]\n }), \"\\n\"]\n }), \"\\n\", _jsx(_components.p, {\n children: _jsxs(_components.strong, {\n children: [\"How \", _jsx(_components.code, {\n children: \"bricks\"\n }), \" affects existing discounts:\"]\n })\n }), \"\\n\", _jsxs(_components.p, {\n children: [\"Per-brick discounts are \", _jsx(_components.strong, {\n children: \"replaced, not merged\"\n }), \". The \", _jsx(_components.code, {\n children: \"discount\"\n }), \" sent on a brick becomes that brick’s complete set of discounts for this order, and a brick sent without a \", _jsx(_components.code, {\n children: \"discount\"\n }), \" ends up with none — any discount it previously carried is dropped.\"]\n }), \"\\n\", _jsxs(_components.p, {\n children: [\"This applies to every brick in the payload, not only the ones being changed. A brick included solely to keep it on the order still needs its \", _jsx(_components.code, {\n children: \"discount\"\n }), \" resent, or it loses it.\"]\n }), \"\\n\", _jsxs(_components.p, {\n children: [\"Read the current values from the subscription’s line items — \", _jsx(_components.code, {\n children: \"discount\"\n }), \" is returned there in the same shape this endpoint accepts — and send them back for every brick whose discount should carry over.\"]\n })]\n });\n}\nfunction MDXContent(props = {}) {\n const {wrapper: MDXLayout} = {\n ..._provideComponents(),\n ...props.components\n };\n return MDXLayout ? _jsx(MDXLayout, {\n ...props,\n children: _jsx(_createMdxContent, {\n ...props\n })\n }) : _createMdxContent(props);\n}\nreturn {\n default: MDXContent\n};\n","frontmatter":{},"scope":{}},"pageType":"default","mdx":{"mdxSource":{"compiledSource":"\"use strict\";const{Fragment:_Fragment,jsx:_jsx}=arguments[0];const{useMDXComponents:_provideComponents}=arguments[0];function _createMdxContent(props){return _jsx(_Fragment,{})}function MDXContent(props={}){const{wrapper:MDXLayout}={..._provideComponents(),...props.components};return MDXLayout?_jsx(MDXLayout,{...props,children:_jsx(_createMdxContent,{...props})}):_createMdxContent(props)}return{default:MDXContent}","frontmatter":{},"scope":{"config":{},"pageMetadata":{"title":"Create a subscription upgrade","description":"Creates a subscription upgrade that can be used to add or remove add-ons from an existing contract term.\n\n- Use `/subscriptions/{subscription_id}/upgrade/{order_id}/estimate` to preview pricing before confirming\n- Use `/subscriptions/{subscription_id}/upgrade/{order_id}/start` to begin the upgrade\n\nThe upgrade keeps the subscription's CRM account. Pass `crm_opportunity_id` to link it to its own opportunity in your connected CRM; without one, no opportunity is linked or created.\n\n**How `plan_id` affects pricing:**\n\n- **`plan_id` omitted** — the upgrade keeps the subscription's current plan version and contracted pricing (customers stay grandfathered). If `bricks` includes a brick that doesn't exist on the current plan version, it is pulled in from that plan's latest published version, producing a merged plan version.\n- **`plan_id` provided** — the upgrade switches to the latest published version of the referenced plan. If `bricks` references a brick that only exists on the subscription's prior plan version, it is carried over into a merged plan version.\n- `plan_id` may reference a different plan than the subscription's current plan; that is how cross-plan upgrades are expressed.\n- **`plan_id` is only honoured when `bricks` is also provided.** Sending `plan_id` without `bricks` returns 400.\n\n**How `bricks` affects existing discounts:**\n\nPer-brick discounts are **replaced, not merged**. The `discount` sent on a brick becomes that brick's complete set of discounts for this order, and a brick sent without a `discount` ends up with none — any discount it previously carried is dropped.\n\nThis applies to every brick in the payload, not only the ones being changed. A brick included solely to keep it on the order still needs its `discount` resent, or it loses it.\n\nRead the current values from the subscription's line items — `discount` is returned there in the same shape this endpoint accepts — and send them back for every brick whose discount should carry over.","deprecated":null,"version":null,"openapi":"https://api.salesbricks.com/api/v2/openapi.yaml post /subscriptions/{subscription_id}/upgrade","href":"/api-reference/subscription-upgrades/create-a-subscription-upgrade","autogeneratedByOpenApi":true}}},"mdxSourceWithNoJs":null},"mdxExtracts":{"tableOfContents":[],"codeExamples":{}},"jsLinks":[],"openApiReferenceData":{"operation":{"operationId":"createSubscriptionUpgrade","description":"Creates a subscription upgrade that can be used to add or remove add-ons from an existing contract term.\n\n- Use `/subscriptions/{subscription_id}/upgrade/{order_id}/estimate` to preview pricing before confirming\n- Use `/subscriptions/{subscription_id}/upgrade/{order_id}/start` to begin the upgrade\n\nThe upgrade keeps the subscription's CRM account. Pass `crm_opportunity_id` to link it to its own opportunity in your connected CRM; without one, no opportunity is linked or created.\n\n**How `plan_id` affects pricing:**\n\n- **`plan_id` omitted** — the upgrade keeps the subscription's current plan version and contracted pricing (customers stay grandfathered). If `bricks` includes a brick that doesn't exist on the current plan version, it is pulled in from that plan's latest published version, producing a merged plan version.\n- **`plan_id` provided** — the upgrade switches to the latest published version of the referenced plan. If `bricks` references a brick that only exists on the subscription's prior plan version, it is carried over into a merged plan version.\n- `plan_id` may reference a different plan than the subscription's current plan; that is how cross-plan upgrades are expressed.\n- **`plan_id` is only honoured when `bricks` is also provided.** Sending `plan_id` without `bricks` returns 400.\n\n**How `bricks` affects existing discounts:**\n\nPer-brick discounts are **replaced, not merged**. The `discount` sent on a brick becomes that brick's complete set of discounts for this order, and a brick sent without a `discount` ends up with none — any discount it previously carried is dropped.\n\nThis applies to every brick in the payload, not only the ones being changed. A brick included solely to keep it on the order still needs its `discount` resent, or it loses it.\n\nRead the current values from the subscription's line items — `discount` is returned there in the same shape this endpoint accepts — and send them back for every brick whose discount should carry over.","summary":"Create a subscription upgrade","parameters":["90df5c2c-b191-4d50-8829-df6799ec88fc"],"tags":["Subscription Upgrades"],"requestBody":"8386b025-bea6-40a1-b1dd-7953888d3fea","responses":{"200":"7dce3e4d-23a5-44e5-a5da-afd8dbcac0ed","400":"3efce312-9c07-4e6e-9501-be0b3527fe59","404":"c56f7520-4241-4382-8e58-76bca55c2a2e"},"method":"post","type":"path","servers":["473a595f-0b07-4538-b033-faf5582d0b46"],"security":["96e2b814-4b2f-4ec1-a062-fb177ecfca77"],"path":"/subscriptions/{subscription_id}/upgrade","baseUrlOptions":["https://api.salesbricks.com/api/v2"],"title":"Create a subscription upgrade","codeSamples":[],"requiredOnlyExamples":false,"requestExampleType":"generated","responseExampleType":"generated"},"dependencies":{"parameters":{"90df5c2c-b191-4d50-8829-df6799ec88fc":{"in":"path","name":"subscription_id","schema":{"type":"string","pattern":"^([a-zA-Z\\d\\-]+)$","isRequired":true,"uniqueKey":"","typeLabel":"string"},"required":true}},"requestBody":{"content":{"application/json":{"schema":{"oneOf":[{"type":"object","title":"SubscriptionInputUpgradeSinglePhase","description":"Subscription upgrade input serializer for upgrading a subscription order.\n\nThis payload has two forms — see `anyOf`:\n\n* **Single-phase** — omit `phases`; the order-level `starts_at`, `contract_length`, `billing_frequency` and `bricks` define the one phase and are required.\n* **Multi-phase** — send `phases`; the phases own the timeline, billing frequency and bricks, and the order-level equivalents become optional (omitted, they are derived from the phases).\n\nThe fields are declared optional because OpenAPI 3.0 cannot make one field's `required` depend on another. Sending neither form is a 400.","required":["starts_at","bricks"],"properties":{"starts_at":{"type":"string","description":"The effective date of the subscription upgrade. Required only when `phases` is omitted: when `phases` is provided the phases own the timeline, so the effective date is taken from the first phase's `starts_at` and this order-level value is ignored.","format":"date","isRequired":true,"uniqueKey":"oneOf.0.starts_at","typeLabel":"string\u003cdate>"},"bricks":{"type":"array","items":{"type":"object","description":"Line item input serializer for creating a new estimate","properties":{"brick_id":{"type":"string","format":"uuid","description":"The ID of the brick to add to the subscription","isRequired":true,"uniqueKey":"oneOf.0.bricks.items.[INDEX].brick_id","typeLabel":"string\u003cuuid>"},"quantity":{"type":"integer","description":"The quantity of the brick, used as the basis for its price","uniqueKey":"oneOf.0.bricks.items.[INDEX].quantity","typeLabel":"integer"},"is_unlimited":{"type":"boolean","description":"Sell this line with an uncapped entitlement, keeping `quantity` as the pricing basis its price is calculated from. Optional: omitting it on create leaves the line limited, and omitting it on update leaves the line's current value alone — send it explicitly as false to clear it. Subscription bricks only.","uniqueKey":"oneOf.0.bricks.items.[INDEX].is_unlimited","typeLabel":"boolean"},"discount":{"oneOf":[{"type":"array","items":{"type":"object","description":"Discount serializer for a subscription estimate line item","properties":{"rate":{"type":"string","format":"decimal","pattern":"^-?\\d{0,14}(?:\\.\\d{0,6})?$","description":"The discount rate as a percentage with up to six decimal places (e.g. 10 = 10%, 62.6758 = 62.6758%). Mutually exclusive with `amount`.","uniqueKey":"oneOf.0.bricks.items.[INDEX].discount.oneOf.0.items.[INDEX].rate","typeLabel":"string\u003cdecimal>"},"amount":{"type":"integer","description":"A fixed discount amount in cents (e.g. 1000 = $10.00). One-time only — `renews` must be false when `amount` is set. Mutually exclusive with `rate`. The amount is applied as-is and is not clamped to the line item total, so it should not exceed the brick's price.","uniqueKey":"oneOf.0.bricks.items.[INDEX].discount.oneOf.0.items.[INDEX].amount","typeLabel":"integer"},"renews":{"type":"boolean","default":false,"description":"If the discount is carried over at renewal. Must be false when `amount` is set, as fixed discounts are one-time only.","uniqueKey":"oneOf.0.bricks.items.[INDEX].discount.oneOf.0.items.[INDEX].renews","typeLabel":"boolean"}},"uniqueKey":"oneOf.0.bricks.items.[INDEX].discount.oneOf.0.items.[INDEX]","typeLabel":"object"},"description":"A list of discounts to apply to the line item — at most one renewing rate, one one-time rate, and one fixed amount. Discounts are replaced, not merged: what is sent here becomes the line item's complete set of discounts. Omitting this field for a brick that currently has a discount drops that discount. Read the current values from the subscription's line items, which return `discount` in this same shape, and send them back for every brick whose discount should carry over.","uniqueKey":"oneOf.0.bricks.items.[INDEX].discount.oneOf.0","typeLabel":"object[]"},{"type":"null","items":{"type":"object","description":"Discount serializer for a subscription estimate line item","properties":{"rate":{"type":"string","format":"decimal","pattern":"^-?\\d{0,14}(?:\\.\\d{0,6})?$","description":"The discount rate as a percentage with up to six decimal places (e.g. 10 = 10%, 62.6758 = 62.6758%). Mutually exclusive with `amount`."},"amount":{"type":"integer","description":"A fixed discount amount in cents (e.g. 1000 = $10.00). One-time only — `renews` must be false when `amount` is set. Mutually exclusive with `rate`. The amount is applied as-is and is not clamped to the line item total, so it should not exceed the brick's price."},"renews":{"type":"boolean","default":false,"description":"If the discount is carried over at renewal. Must be false when `amount` is set, as fixed discounts are one-time only."}}},"description":"A list of discounts to apply to the line item — at most one renewing rate, one one-time rate, and one fixed amount. Discounts are replaced, not merged: what is sent here becomes the line item's complete set of discounts. Omitting this field for a brick that currently has a discount drops that discount. Read the current values from the subscription's line items, which return `discount` in this same shape, and send them back for every brick whose discount should carry over.","uniqueKey":"oneOf.0.bricks.items.[INDEX].discount.oneOf.1","typeLabel":"null"}],"uniqueKey":"oneOf.0.bricks.items.[INDEX].discount","typeLabel":"object[] | null"}},"required":["brick_id"],"uniqueKey":"oneOf.0.bricks.items.[INDEX]","typeLabel":"object"},"description":"The bricks included in subscription upgrade. Quantity is used to upgrade the add-on quantity (ie. adding 2 more units should be quantity 2 -> quantity 4). For usage, quantity is used to set the pre-commitment (ie. previously having 5 pre-commitment quantity and updating it to 10 would update the pre-commitment quantity to 10.)","isRequired":true,"uniqueKey":"oneOf.0.bricks","typeLabel":"object[]"},"crm_opportunity_id":{"type":"string","description":"Optional ID of the opportunity (deal in HubSpot) in your connected CRM to link the subscription to. Requires a linked CRM account, and must not be linked to another subscription. Omit for no change; pass an empty string to unlink it.","maxLength":255,"uniqueKey":"oneOf.0.crm_opportunity_id","typeLabel":"string"},"plan_id":{"type":"string","format":"uuid","description":"Optional plan ID for the upgrade. When provided, the upgrade switches to the latest published version of that plan; when omitted, it keeps the subscription's existing plan version and contracted pricing. Must be sent together with `bricks` — `plan_id` alone is rejected with 400. See the endpoint description for full semantics including cross-plan upgrades and merged plan versions.","uniqueKey":"oneOf.0.plan_id","typeLabel":"string\u003cuuid>"},"discount_coupons":{"type":"array","items":{"type":"string","uniqueKey":"oneOf.0.discount_coupons.items.[INDEX]","typeLabel":"string"},"description":"Discount coupon codes to apply to the subscription upgrade. Currently only supports one discount coupon - only the first one in the list will be applied.","uniqueKey":"oneOf.0.discount_coupons","typeLabel":"string[]"},"phases":{"oneOf":[{"type":"array","items":{"type":"object","description":"Input serializer for a single order phase in multi-phase operations.\n\n``phase_position`` is required on every phase. For creation, recast and\nestimate the array is the complete phase set, so positions must be the full\n0-based sequence (position N at index N). For upgrades only the phases being\nchanged are sent, so positions are a subset of the base order's phase\npositions.\n\n``starts_at`` is optional — phase 0 defaults to the order-level starts_at,\nand subsequent phases are derived from the previous phase's end date.\n\n``contract_length`` replaces the old ``ends_at`` field. Required for\ncreate/estimate/recast; not needed for upgrades (end date inherited from\nthe base order). The phase *output* reports ``ends_at`` rather than\n``contract_length``, so a read-modify-write of a phase has to convert:\n``contract_length`` is the number of whole months from ``starts_at`` to the\nday after ``ends_at``. Phases are contiguous and whole-month, so the\nconversion is exact.\n\n``billing_frequency`` follows the same rule: required for\ncreate/estimate/recast, where phases own the billing frequency outright,\nand inherited from the base order's phase on upgrades.\n\n``plan_id`` is optional and lets a phase sell a different plan from the\norder's, matching what the order builder already supports (SAL-6327).\nOmitted, the phase uses the order-level ``plan_id``.","properties":{"phase_position":{"type":"integer","minimum":0,"description":"Phase position (0-based). Must be unique across phases.","isRequired":true,"uniqueKey":"oneOf.0.phases.oneOf.0.items.[INDEX].phase_position","typeLabel":"integer"},"bricks":{"type":"array","items":{"type":"object","description":"Line item input serializer for creating a new estimate","properties":{"brick_id":{"type":"string","format":"uuid","description":"The ID of the brick to add to the subscription","isRequired":true,"uniqueKey":"oneOf.0.phases.oneOf.0.items.[INDEX].bricks.items.[INDEX].brick_id","typeLabel":"string\u003cuuid>"},"quantity":{"type":"integer","description":"The quantity of the brick, used as the basis for its price","uniqueKey":"oneOf.0.phases.oneOf.0.items.[INDEX].bricks.items.[INDEX].quantity","typeLabel":"integer"},"is_unlimited":{"type":"boolean","description":"Sell this line with an uncapped entitlement, keeping `quantity` as the pricing basis its price is calculated from. Optional: omitting it on create leaves the line limited, and omitting it on update leaves the line's current value alone — send it explicitly as false to clear it. Subscription bricks only.","uniqueKey":"oneOf.0.phases.oneOf.0.items.[INDEX].bricks.items.[INDEX].is_unlimited","typeLabel":"boolean"},"discount":{"oneOf":[{"type":"array","items":{"type":"object","description":"Discount serializer for a subscription estimate line item","properties":{"rate":{"type":"string","format":"decimal","pattern":"^-?\\d{0,14}(?:\\.\\d{0,6})?$","description":"The discount rate as a percentage with up to six decimal places (e.g. 10 = 10%, 62.6758 = 62.6758%). Mutually exclusive with `amount`.","uniqueKey":"oneOf.0.phases.oneOf.0.items.[INDEX].bricks.items.[INDEX].discount.oneOf.0.items.[INDEX].rate","typeLabel":"string\u003cdecimal>"},"amount":{"type":"integer","description":"A fixed discount amount in cents (e.g. 1000 = $10.00). One-time only — `renews` must be false when `amount` is set. Mutually exclusive with `rate`. The amount is applied as-is and is not clamped to the line item total, so it should not exceed the brick's price.","uniqueKey":"oneOf.0.phases.oneOf.0.items.[INDEX].bricks.items.[INDEX].discount.oneOf.0.items.[INDEX].amount","typeLabel":"integer"},"renews":{"type":"boolean","default":false,"description":"If the discount is carried over at renewal. Must be false when `amount` is set, as fixed discounts are one-time only.","uniqueKey":"oneOf.0.phases.oneOf.0.items.[INDEX].bricks.items.[INDEX].discount.oneOf.0.items.[INDEX].renews","typeLabel":"boolean"}},"uniqueKey":"oneOf.0.phases.oneOf.0.items.[INDEX].bricks.items.[INDEX].discount.oneOf.0.items.[INDEX]","typeLabel":"object"},"description":"A list of discounts to apply to the line item — at most one renewing rate, one one-time rate, and one fixed amount. Discounts are replaced, not merged: what is sent here becomes the line item's complete set of discounts. Omitting this field for a brick that currently has a discount drops that discount. Read the current values from the subscription's line items, which return `discount` in this same shape, and send them back for every brick whose discount should carry over.","uniqueKey":"oneOf.0.phases.oneOf.0.items.[INDEX].bricks.items.[INDEX].discount.oneOf.0","typeLabel":"object[]"},{"type":"null","items":{"type":"object","description":"Discount serializer for a subscription estimate line item","properties":{"rate":{"type":"string","format":"decimal","pattern":"^-?\\d{0,14}(?:\\.\\d{0,6})?$","description":"The discount rate as a percentage with up to six decimal places (e.g. 10 = 10%, 62.6758 = 62.6758%). Mutually exclusive with `amount`."},"amount":{"type":"integer","description":"A fixed discount amount in cents (e.g. 1000 = $10.00). One-time only — `renews` must be false when `amount` is set. Mutually exclusive with `rate`. The amount is applied as-is and is not clamped to the line item total, so it should not exceed the brick's price."},"renews":{"type":"boolean","default":false,"description":"If the discount is carried over at renewal. Must be false when `amount` is set, as fixed discounts are one-time only."}}},"description":"A list of discounts to apply to the line item — at most one renewing rate, one one-time rate, and one fixed amount. Discounts are replaced, not merged: what is sent here becomes the line item's complete set of discounts. Omitting this field for a brick that currently has a discount drops that discount. Read the current values from the subscription's line items, which return `discount` in this same shape, and send them back for every brick whose discount should carry over.","uniqueKey":"oneOf.0.phases.oneOf.0.items.[INDEX].bricks.items.[INDEX].discount.oneOf.1","typeLabel":"null"}],"uniqueKey":"oneOf.0.phases.oneOf.0.items.[INDEX].bricks.items.[INDEX].discount","typeLabel":"object[] | null"}},"required":["brick_id"],"uniqueKey":"oneOf.0.phases.oneOf.0.items.[INDEX].bricks.items.[INDEX]","typeLabel":"object"},"description":"The bricks included in this phase.","isRequired":true,"uniqueKey":"oneOf.0.phases.oneOf.0.items.[INDEX].bricks","typeLabel":"object[]"},"starts_at":{"oneOf":[{"type":"string","format":"date","description":"Start date of this phase. Optional — phase 0 defaults to order-level starts_at; subsequent phases are derived from the previous phase's end date + 1 day.","uniqueKey":"oneOf.0.phases.oneOf.0.items.[INDEX].starts_at.oneOf.0","typeLabel":"string\u003cdate>"},{"type":"null","format":"date","description":"Start date of this phase. Optional — phase 0 defaults to order-level starts_at; subsequent phases are derived from the previous phase's end date + 1 day.","uniqueKey":"oneOf.0.phases.oneOf.0.items.[INDEX].starts_at.oneOf.1","typeLabel":"null"}],"uniqueKey":"oneOf.0.phases.oneOf.0.items.[INDEX].starts_at","typeLabel":"string\u003cdate> | null"},"contract_length":{"oneOf":[{"type":"integer","minimum":1,"description":"Duration of this phase in months. Required for create, estimate, and recast. Not required for upgrades (end date inherited from the base order).","uniqueKey":"oneOf.0.phases.oneOf.0.items.[INDEX].contract_length.oneOf.0","typeLabel":"integer"},{"type":"null","minimum":1,"description":"Duration of this phase in months. Required for create, estimate, and recast. Not required for upgrades (end date inherited from the base order).","uniqueKey":"oneOf.0.phases.oneOf.0.items.[INDEX].contract_length.oneOf.1","typeLabel":"null"}],"uniqueKey":"oneOf.0.phases.oneOf.0.items.[INDEX].contract_length","typeLabel":"integer | null"},"billing_frequency":{"enum":["MONTHLY","QUARTERLY","SEMI_ANNUALLY","ANNUALLY","ALL_UPFRONT","CUSTOM"],"type":"string","x-spec-enum-id":"5f29351b16a5547f","description":"Billing frequency for this phase. Required for create, estimate and recast — when phases are provided they own the billing frequency outright, so the order-level billing_frequency is not consulted. Not required for upgrades (inherited from the base order's phase). The legacy name `billing_schedule` is still accepted.\n\n* `MONTHLY` - Monthly\n* `QUARTERLY` - Quarterly\n* `SEMI_ANNUALLY` - Semi-annually\n* `ANNUALLY` - Annually\n* `ALL_UPFRONT` - All upfront\n* `CUSTOM` - Custom","uniqueKey":"oneOf.0.phases.oneOf.0.items.[INDEX].billing_frequency","typeLabel":"enum\u003cstring>"},"plan_id":{"oneOf":[{"type":"string","format":"uuid","description":"Optional plan for this phase. Each phase may sell a different plan; the phase's bricks are then validated and priced against it. Defaults to the order-level `plan_id`.","uniqueKey":"oneOf.0.phases.oneOf.0.items.[INDEX].plan_id.oneOf.0","typeLabel":"string\u003cuuid>"},{"type":"null","format":"uuid","description":"Optional plan for this phase. Each phase may sell a different plan; the phase's bricks are then validated and priced against it. Defaults to the order-level `plan_id`.","uniqueKey":"oneOf.0.phases.oneOf.0.items.[INDEX].plan_id.oneOf.1","typeLabel":"null"}],"uniqueKey":"oneOf.0.phases.oneOf.0.items.[INDEX].plan_id","typeLabel":"string\u003cuuid> | null"},"payment_terms":{"type":"integer","maximum":999,"minimum":0,"description":"Payment terms in days for this phase. Named to match the order-level `payment_terms` input and the phase output — the model field it lands on is `payment_due_upon_receipt`, which is still accepted as a legacy name. Omitted, the phase inherits the order-level value.","uniqueKey":"oneOf.0.phases.oneOf.0.items.[INDEX].payment_terms","typeLabel":"integer"},"discount_coupons":{"type":"array","items":{"type":"string","uniqueKey":"oneOf.0.phases.oneOf.0.items.[INDEX].discount_coupons.items.[INDEX]","typeLabel":"string"},"description":"Discount coupon codes to apply to this phase. Currently only supports one discount coupon - only the first one in the list will be applied.","uniqueKey":"oneOf.0.phases.oneOf.0.items.[INDEX].discount_coupons","typeLabel":"string[]"}},"required":["bricks","phase_position"],"uniqueKey":"oneOf.0.phases.oneOf.0.items.[INDEX]","typeLabel":"object"},"description":"Optional list of phases for a multi-phase upgrade. Each phase's ``phase_position`` must match a phase on the base order; only the phases being changed need to be sent, and omitted positions are inherited from the base order unchanged. Order-level bricks and `starts_at` are ignored when phases are provided — the phases own the timeline and the first phase's `starts_at` is the upgrade's effective date.","uniqueKey":"oneOf.0.phases.oneOf.0","typeLabel":"object[]"},{"type":"null","items":{"type":"object","description":"Input serializer for a single order phase in multi-phase operations.\n\n``phase_position`` is required on every phase. For creation, recast and\nestimate the array is the complete phase set, so positions must be the full\n0-based sequence (position N at index N). For upgrades only the phases being\nchanged are sent, so positions are a subset of the base order's phase\npositions.\n\n``starts_at`` is optional — phase 0 defaults to the order-level starts_at,\nand subsequent phases are derived from the previous phase's end date.\n\n``contract_length`` replaces the old ``ends_at`` field. Required for\ncreate/estimate/recast; not needed for upgrades (end date inherited from\nthe base order). The phase *output* reports ``ends_at`` rather than\n``contract_length``, so a read-modify-write of a phase has to convert:\n``contract_length`` is the number of whole months from ``starts_at`` to the\nday after ``ends_at``. Phases are contiguous and whole-month, so the\nconversion is exact.\n\n``billing_frequency`` follows the same rule: required for\ncreate/estimate/recast, where phases own the billing frequency outright,\nand inherited from the base order's phase on upgrades.\n\n``plan_id`` is optional and lets a phase sell a different plan from the\norder's, matching what the order builder already supports (SAL-6327).\nOmitted, the phase uses the order-level ``plan_id``.","properties":{"phase_position":{"type":"integer","minimum":0,"description":"Phase position (0-based). Must be unique across phases."},"starts_at":{"oneOf":[{"type":"string","format":"date","description":"Start date of this phase. Optional — phase 0 defaults to order-level starts_at; subsequent phases are derived from the previous phase's end date + 1 day."},{"type":"null","format":"date","description":"Start date of this phase. Optional — phase 0 defaults to order-level starts_at; subsequent phases are derived from the previous phase's end date + 1 day."}]},"contract_length":{"oneOf":[{"type":"integer","minimum":1,"description":"Duration of this phase in months. Required for create, estimate, and recast. Not required for upgrades (end date inherited from the base order)."},{"type":"null","minimum":1,"description":"Duration of this phase in months. Required for create, estimate, and recast. Not required for upgrades (end date inherited from the base order)."}]},"billing_frequency":{"enum":["MONTHLY","QUARTERLY","SEMI_ANNUALLY","ANNUALLY","ALL_UPFRONT","CUSTOM"],"type":"string","x-spec-enum-id":"5f29351b16a5547f","description":"Billing frequency for this phase. Required for create, estimate and recast — when phases are provided they own the billing frequency outright, so the order-level billing_frequency is not consulted. Not required for upgrades (inherited from the base order's phase). The legacy name `billing_schedule` is still accepted.\n\n* `MONTHLY` - Monthly\n* `QUARTERLY` - Quarterly\n* `SEMI_ANNUALLY` - Semi-annually\n* `ANNUALLY` - Annually\n* `ALL_UPFRONT` - All upfront\n* `CUSTOM` - Custom"},"plan_id":{"oneOf":[{"type":"string","format":"uuid","description":"Optional plan for this phase. Each phase may sell a different plan; the phase's bricks are then validated and priced against it. Defaults to the order-level `plan_id`."},{"type":"null","format":"uuid","description":"Optional plan for this phase. Each phase may sell a different plan; the phase's bricks are then validated and priced against it. Defaults to the order-level `plan_id`."}]},"payment_terms":{"type":"integer","maximum":999,"minimum":0,"description":"Payment terms in days for this phase. Named to match the order-level `payment_terms` input and the phase output — the model field it lands on is `payment_due_upon_receipt`, which is still accepted as a legacy name. Omitted, the phase inherits the order-level value."},"bricks":{"type":"array","items":{"type":"object","description":"Line item input serializer for creating a new estimate","properties":{"brick_id":{"type":"string","format":"uuid","description":"The ID of the brick to add to the subscription"},"quantity":{"type":"integer","description":"The quantity of the brick, used as the basis for its price"},"is_unlimited":{"type":"boolean","description":"Sell this line with an uncapped entitlement, keeping `quantity` as the pricing basis its price is calculated from. Optional: omitting it on create leaves the line limited, and omitting it on update leaves the line's current value alone — send it explicitly as false to clear it. Subscription bricks only."},"discount":{"oneOf":[{"type":"array","items":{"type":"object","description":"Discount serializer for a subscription estimate line item","properties":{"rate":{"type":"string","format":"decimal","pattern":"^-?\\d{0,14}(?:\\.\\d{0,6})?$","description":"The discount rate as a percentage with up to six decimal places (e.g. 10 = 10%, 62.6758 = 62.6758%). Mutually exclusive with `amount`."},"amount":{"type":"integer","description":"A fixed discount amount in cents (e.g. 1000 = $10.00). One-time only — `renews` must be false when `amount` is set. Mutually exclusive with `rate`. The amount is applied as-is and is not clamped to the line item total, so it should not exceed the brick's price."},"renews":{"type":"boolean","default":false,"description":"If the discount is carried over at renewal. Must be false when `amount` is set, as fixed discounts are one-time only."}}},"description":"A list of discounts to apply to the line item — at most one renewing rate, one one-time rate, and one fixed amount. Discounts are replaced, not merged: what is sent here becomes the line item's complete set of discounts. Omitting this field for a brick that currently has a discount drops that discount. Read the current values from the subscription's line items, which return `discount` in this same shape, and send them back for every brick whose discount should carry over."},{"type":"null","items":{"type":"object","description":"Discount serializer for a subscription estimate line item","properties":{"rate":{"type":"string","format":"decimal","pattern":"^-?\\d{0,14}(?:\\.\\d{0,6})?$","description":"The discount rate as a percentage with up to six decimal places (e.g. 10 = 10%, 62.6758 = 62.6758%). Mutually exclusive with `amount`."},"amount":{"type":"integer","description":"A fixed discount amount in cents (e.g. 1000 = $10.00). One-time only — `renews` must be false when `amount` is set. Mutually exclusive with `rate`. The amount is applied as-is and is not clamped to the line item total, so it should not exceed the brick's price."},"renews":{"type":"boolean","default":false,"description":"If the discount is carried over at renewal. Must be false when `amount` is set, as fixed discounts are one-time only."}}},"description":"A list of discounts to apply to the line item — at most one renewing rate, one one-time rate, and one fixed amount. Discounts are replaced, not merged: what is sent here becomes the line item's complete set of discounts. Omitting this field for a brick that currently has a discount drops that discount. Read the current values from the subscription's line items, which return `discount` in this same shape, and send them back for every brick whose discount should carry over."}]}},"required":["brick_id"]},"description":"The bricks included in this phase."},"discount_coupons":{"type":"array","items":{"type":"string"},"description":"Discount coupon codes to apply to this phase. Currently only supports one discount coupon - only the first one in the list will be applied."}},"required":["bricks","phase_position"]},"description":"Optional list of phases for a multi-phase upgrade. Each phase's ``phase_position`` must match a phase on the base order; only the phases being changed need to be sent, and omitted positions are inherited from the base order unchanged. Order-level bricks and `starts_at` are ignored when phases are provided — the phases own the timeline and the first phase's `starts_at` is the upgrade's effective date.","uniqueKey":"oneOf.0.phases.oneOf.1","typeLabel":"null"}],"uniqueKey":"oneOf.0.phases","typeLabel":"object[] | null"},"custom_order_form_html":{"type":"string","description":"The custom order form html to use with `\u003chtml>\u003cbody>...\u003c/body>\u003c/html>` formatting","uniqueKey":"oneOf.0.custom_order_form_html","typeLabel":"string"},"metadata":{"oneOf":[{"description":"Optional metadata to add to the subscription. Sending an empty map will delete all keys. Keys prefixed with _ are private and will be ignored.","uniqueKey":"oneOf.0.metadata.oneOf.0","typeLabel":"any"},{"description":"Optional metadata to add to the subscription. Sending an empty map will delete all keys. Keys prefixed with _ are private and will be ignored.","type":"null","uniqueKey":"oneOf.0.metadata.oneOf.1","typeLabel":"null"}],"uniqueKey":"oneOf.0.metadata","typeLabel":"any | null"},"downgrade_method":{"oneOf":[{"enum":["CREDIT","REFUND"],"type":"string","x-spec-enum-id":"b3bcc767e244c89a","description":"Method to apply for the downgrade. CREDIT - apply as credit, REFUND - refund the money back. Omitted is treated as CREDIT.\n\n* `CREDIT` - Credit\n* `REFUND` - Refund","uniqueKey":"oneOf.0.downgrade_method.oneOf.0","typeLabel":"enum\u003cstring>"},{"enum":["CREDIT","REFUND"],"type":"null","x-spec-enum-id":"b3bcc767e244c89a","description":"Method to apply for the downgrade. CREDIT - apply as credit, REFUND - refund the money back. Omitted is treated as CREDIT.\n\n* `CREDIT` - Credit\n* `REFUND` - Refund","uniqueKey":"oneOf.0.downgrade_method.oneOf.1","typeLabel":"null"}],"uniqueKey":"oneOf.0.downgrade_method","typeLabel":"enum\u003cstring> | null"}},"uniqueKey":"oneOf.0","typeLabel":"SubscriptionInputUpgradeSinglePhase · object"},{"type":"object","title":"SubscriptionInputUpgradeMultiPhase","description":"Subscription upgrade input serializer for upgrading a subscription order.\n\nThis payload has two forms — see `anyOf`:\n\n* **Single-phase** — omit `phases`; the order-level `starts_at`, `contract_length`, `billing_frequency` and `bricks` define the one phase and are required.\n* **Multi-phase** — send `phases`; the phases own the timeline, billing frequency and bricks, and the order-level equivalents become optional (omitted, they are derived from the phases).\n\nThe fields are declared optional because OpenAPI 3.0 cannot make one field's `required` depend on another. Sending neither form is a 400.","required":["phases","bricks"],"properties":{"bricks":{"type":"array","items":{"type":"object","description":"Line item input serializer for creating a new estimate","properties":{"brick_id":{"type":"string","format":"uuid","description":"The ID of the brick to add to the subscription","isRequired":true,"uniqueKey":"oneOf.1.bricks.items.[INDEX].brick_id","typeLabel":"string\u003cuuid>"},"quantity":{"type":"integer","description":"The quantity of the brick, used as the basis for its price","uniqueKey":"oneOf.1.bricks.items.[INDEX].quantity","typeLabel":"integer"},"is_unlimited":{"type":"boolean","description":"Sell this line with an uncapped entitlement, keeping `quantity` as the pricing basis its price is calculated from. Optional: omitting it on create leaves the line limited, and omitting it on update leaves the line's current value alone — send it explicitly as false to clear it. Subscription bricks only.","uniqueKey":"oneOf.1.bricks.items.[INDEX].is_unlimited","typeLabel":"boolean"},"discount":{"oneOf":[{"type":"array","items":{"type":"object","description":"Discount serializer for a subscription estimate line item","properties":{"rate":{"type":"string","format":"decimal","pattern":"^-?\\d{0,14}(?:\\.\\d{0,6})?$","description":"The discount rate as a percentage with up to six decimal places (e.g. 10 = 10%, 62.6758 = 62.6758%). Mutually exclusive with `amount`.","uniqueKey":"oneOf.1.bricks.items.[INDEX].discount.oneOf.0.items.[INDEX].rate","typeLabel":"string\u003cdecimal>"},"amount":{"type":"integer","description":"A fixed discount amount in cents (e.g. 1000 = $10.00). One-time only — `renews` must be false when `amount` is set. Mutually exclusive with `rate`. The amount is applied as-is and is not clamped to the line item total, so it should not exceed the brick's price.","uniqueKey":"oneOf.1.bricks.items.[INDEX].discount.oneOf.0.items.[INDEX].amount","typeLabel":"integer"},"renews":{"type":"boolean","default":false,"description":"If the discount is carried over at renewal. Must be false when `amount` is set, as fixed discounts are one-time only.","uniqueKey":"oneOf.1.bricks.items.[INDEX].discount.oneOf.0.items.[INDEX].renews","typeLabel":"boolean"}},"uniqueKey":"oneOf.1.bricks.items.[INDEX].discount.oneOf.0.items.[INDEX]","typeLabel":"object"},"description":"A list of discounts to apply to the line item — at most one renewing rate, one one-time rate, and one fixed amount. Discounts are replaced, not merged: what is sent here becomes the line item's complete set of discounts. Omitting this field for a brick that currently has a discount drops that discount. Read the current values from the subscription's line items, which return `discount` in this same shape, and send them back for every brick whose discount should carry over.","uniqueKey":"oneOf.1.bricks.items.[INDEX].discount.oneOf.0","typeLabel":"object[]"},{"type":"null","items":{"type":"object","description":"Discount serializer for a subscription estimate line item","properties":{"rate":{"type":"string","format":"decimal","pattern":"^-?\\d{0,14}(?:\\.\\d{0,6})?$","description":"The discount rate as a percentage with up to six decimal places (e.g. 10 = 10%, 62.6758 = 62.6758%). Mutually exclusive with `amount`."},"amount":{"type":"integer","description":"A fixed discount amount in cents (e.g. 1000 = $10.00). One-time only — `renews` must be false when `amount` is set. Mutually exclusive with `rate`. The amount is applied as-is and is not clamped to the line item total, so it should not exceed the brick's price."},"renews":{"type":"boolean","default":false,"description":"If the discount is carried over at renewal. Must be false when `amount` is set, as fixed discounts are one-time only."}}},"description":"A list of discounts to apply to the line item — at most one renewing rate, one one-time rate, and one fixed amount. Discounts are replaced, not merged: what is sent here becomes the line item's complete set of discounts. Omitting this field for a brick that currently has a discount drops that discount. Read the current values from the subscription's line items, which return `discount` in this same shape, and send them back for every brick whose discount should carry over.","uniqueKey":"oneOf.1.bricks.items.[INDEX].discount.oneOf.1","typeLabel":"null"}],"uniqueKey":"oneOf.1.bricks.items.[INDEX].discount","typeLabel":"object[] | null"}},"required":["brick_id"],"uniqueKey":"oneOf.1.bricks.items.[INDEX]","typeLabel":"object"},"description":"The bricks included in subscription upgrade. Quantity is used to upgrade the add-on quantity (ie. adding 2 more units should be quantity 2 -> quantity 4). For usage, quantity is used to set the pre-commitment (ie. previously having 5 pre-commitment quantity and updating it to 10 would update the pre-commitment quantity to 10.)","isRequired":true,"uniqueKey":"oneOf.1.bricks","typeLabel":"object[]"},"phases":{"type":"array","items":{"type":"object","description":"Input serializer for a single order phase in multi-phase operations.\n\n``phase_position`` is required on every phase. For creation, recast and\nestimate the array is the complete phase set, so positions must be the full\n0-based sequence (position N at index N). For upgrades only the phases being\nchanged are sent, so positions are a subset of the base order's phase\npositions.\n\n``starts_at`` is optional — phase 0 defaults to the order-level starts_at,\nand subsequent phases are derived from the previous phase's end date.\n\n``contract_length`` replaces the old ``ends_at`` field. Required for\ncreate/estimate/recast; not needed for upgrades (end date inherited from\nthe base order). The phase *output* reports ``ends_at`` rather than\n``contract_length``, so a read-modify-write of a phase has to convert:\n``contract_length`` is the number of whole months from ``starts_at`` to the\nday after ``ends_at``. Phases are contiguous and whole-month, so the\nconversion is exact.\n\n``billing_frequency`` follows the same rule: required for\ncreate/estimate/recast, where phases own the billing frequency outright,\nand inherited from the base order's phase on upgrades.\n\n``plan_id`` is optional and lets a phase sell a different plan from the\norder's, matching what the order builder already supports (SAL-6327).\nOmitted, the phase uses the order-level ``plan_id``.","required":["bricks","phase_position"],"properties":{"phase_position":{"type":"integer","description":"Phase position (0-based). Must be unique across phases.","minimum":0,"isRequired":true,"uniqueKey":"oneOf.1.phases.items.[INDEX].phase_position","typeLabel":"integer"},"bricks":{"type":"array","items":{"type":"object","description":"Line item input serializer for creating a new estimate","required":["brick_id"],"properties":{"brick_id":{"type":"string","description":"The ID of the brick to add to the subscription","format":"uuid","isRequired":true,"uniqueKey":"oneOf.1.phases.items.[INDEX].bricks.items.[INDEX].brick_id","typeLabel":"string\u003cuuid>"},"quantity":{"type":"integer","description":"The quantity of the brick, used as the basis for its price","uniqueKey":"oneOf.1.phases.items.[INDEX].bricks.items.[INDEX].quantity","typeLabel":"integer"},"is_unlimited":{"type":"boolean","description":"Sell this line with an uncapped entitlement, keeping `quantity` as the pricing basis its price is calculated from. Optional: omitting it on create leaves the line limited, and omitting it on update leaves the line's current value alone — send it explicitly as false to clear it. Subscription bricks only.","uniqueKey":"oneOf.1.phases.items.[INDEX].bricks.items.[INDEX].is_unlimited","typeLabel":"boolean"},"discount":{"oneOf":[{"type":"array","items":{"type":"object","description":"Discount serializer for a subscription estimate line item","properties":{"rate":{"type":"string","description":"The discount rate as a percentage with up to six decimal places (e.g. 10 = 10%, 62.6758 = 62.6758%). Mutually exclusive with `amount`.","format":"decimal","pattern":"^-?\\d{0,14}(?:\\.\\d{0,6})?$","uniqueKey":"oneOf.1.phases.items.[INDEX].bricks.items.[INDEX].discount.oneOf.0.items.[INDEX].rate","typeLabel":"string\u003cdecimal>"},"amount":{"type":"integer","description":"A fixed discount amount in cents (e.g. 1000 = $10.00). One-time only — `renews` must be false when `amount` is set. Mutually exclusive with `rate`. The amount is applied as-is and is not clamped to the line item total, so it should not exceed the brick's price.","uniqueKey":"oneOf.1.phases.items.[INDEX].bricks.items.[INDEX].discount.oneOf.0.items.[INDEX].amount","typeLabel":"integer"},"renews":{"type":"boolean","description":"If the discount is carried over at renewal. Must be false when `amount` is set, as fixed discounts are one-time only.","default":false,"uniqueKey":"oneOf.1.phases.items.[INDEX].bricks.items.[INDEX].discount.oneOf.0.items.[INDEX].renews","typeLabel":"boolean"}},"uniqueKey":"oneOf.1.phases.items.[INDEX].bricks.items.[INDEX].discount.oneOf.0.items.[INDEX]","typeLabel":"object"},"description":"A list of discounts to apply to the line item — at most one renewing rate, one one-time rate, and one fixed amount. Discounts are replaced, not merged: what is sent here becomes the line item's complete set of discounts. Omitting this field for a brick that currently has a discount drops that discount. Read the current values from the subscription's line items, which return `discount` in this same shape, and send them back for every brick whose discount should carry over.","uniqueKey":"oneOf.1.phases.items.[INDEX].bricks.items.[INDEX].discount.oneOf.0","typeLabel":"object[]"},{"type":"null","description":"A list of discounts to apply to the line item — at most one renewing rate, one one-time rate, and one fixed amount. Discounts are replaced, not merged: what is sent here becomes the line item's complete set of discounts. Omitting this field for a brick that currently has a discount drops that discount. Read the current values from the subscription's line items, which return `discount` in this same shape, and send them back for every brick whose discount should carry over.","uniqueKey":"oneOf.1.phases.items.[INDEX].bricks.items.[INDEX].discount.oneOf.1","typeLabel":"null"}],"uniqueKey":"oneOf.1.phases.items.[INDEX].bricks.items.[INDEX].discount","typeLabel":"object[] | null"}},"uniqueKey":"oneOf.1.phases.items.[INDEX].bricks.items.[INDEX]","typeLabel":"object"},"description":"The bricks included in this phase.","isRequired":true,"uniqueKey":"oneOf.1.phases.items.[INDEX].bricks","typeLabel":"object[]"},"starts_at":{"oneOf":[{"type":"string","description":"Start date of this phase. Optional — phase 0 defaults to order-level starts_at; subsequent phases are derived from the previous phase's end date + 1 day.","format":"date","uniqueKey":"oneOf.1.phases.items.[INDEX].starts_at.oneOf.0","typeLabel":"string\u003cdate>"},{"type":"null","description":"Start date of this phase. Optional — phase 0 defaults to order-level starts_at; subsequent phases are derived from the previous phase's end date + 1 day.","format":"date","uniqueKey":"oneOf.1.phases.items.[INDEX].starts_at.oneOf.1","typeLabel":"null"}],"uniqueKey":"oneOf.1.phases.items.[INDEX].starts_at","typeLabel":"string\u003cdate> | null"},"contract_length":{"oneOf":[{"type":"integer","description":"Duration of this phase in months. Required for create, estimate, and recast. Not required for upgrades (end date inherited from the base order).","minimum":1,"uniqueKey":"oneOf.1.phases.items.[INDEX].contract_length.oneOf.0","typeLabel":"integer"},{"type":"null","description":"Duration of this phase in months. Required for create, estimate, and recast. Not required for upgrades (end date inherited from the base order).","minimum":1,"uniqueKey":"oneOf.1.phases.items.[INDEX].contract_length.oneOf.1","typeLabel":"null"}],"uniqueKey":"oneOf.1.phases.items.[INDEX].contract_length","typeLabel":"integer | null"},"billing_frequency":{"type":"string","description":"Billing frequency for this phase. Required for create, estimate and recast — when phases are provided they own the billing frequency outright, so the order-level billing_frequency is not consulted. Not required for upgrades (inherited from the base order's phase). The legacy name `billing_schedule` is still accepted.\n\n* `MONTHLY` - Monthly\n* `QUARTERLY` - Quarterly\n* `SEMI_ANNUALLY` - Semi-annually\n* `ANNUALLY` - Annually\n* `ALL_UPFRONT` - All upfront\n* `CUSTOM` - Custom","enum":["MONTHLY","QUARTERLY","SEMI_ANNUALLY","ANNUALLY","ALL_UPFRONT","CUSTOM"],"x-spec-enum-id":"5f29351b16a5547f","uniqueKey":"oneOf.1.phases.items.[INDEX].billing_frequency","typeLabel":"enum\u003cstring>"},"plan_id":{"oneOf":[{"type":"string","description":"Optional plan for this phase. Each phase may sell a different plan; the phase's bricks are then validated and priced against it. Defaults to the order-level `plan_id`.","format":"uuid","uniqueKey":"oneOf.1.phases.items.[INDEX].plan_id.oneOf.0","typeLabel":"string\u003cuuid>"},{"type":"null","description":"Optional plan for this phase. Each phase may sell a different plan; the phase's bricks are then validated and priced against it. Defaults to the order-level `plan_id`.","format":"uuid","uniqueKey":"oneOf.1.phases.items.[INDEX].plan_id.oneOf.1","typeLabel":"null"}],"uniqueKey":"oneOf.1.phases.items.[INDEX].plan_id","typeLabel":"string\u003cuuid> | null"},"payment_terms":{"type":"integer","description":"Payment terms in days for this phase. Named to match the order-level `payment_terms` input and the phase output — the model field it lands on is `payment_due_upon_receipt`, which is still accepted as a legacy name. Omitted, the phase inherits the order-level value.","maximum":999,"minimum":0,"uniqueKey":"oneOf.1.phases.items.[INDEX].payment_terms","typeLabel":"integer"},"discount_coupons":{"type":"array","items":{"type":"string","uniqueKey":"oneOf.1.phases.items.[INDEX].discount_coupons.items.[INDEX]","typeLabel":"string"},"description":"Discount coupon codes to apply to this phase. Currently only supports one discount coupon - only the first one in the list will be applied.","uniqueKey":"oneOf.1.phases.items.[INDEX].discount_coupons","typeLabel":"string[]"}},"uniqueKey":"oneOf.1.phases.items.[INDEX]","typeLabel":"object"},"description":"Optional list of phases for a multi-phase upgrade. Each phase's ``phase_position`` must match a phase on the base order; only the phases being changed need to be sent, and omitted positions are inherited from the base order unchanged. Order-level bricks and `starts_at` are ignored when phases are provided — the phases own the timeline and the first phase's `starts_at` is the upgrade's effective date.","minItems":1,"isRequired":true,"uniqueKey":"oneOf.1.phases","typeLabel":"object[]"},"crm_opportunity_id":{"type":"string","description":"Optional ID of the opportunity (deal in HubSpot) in your connected CRM to link the subscription to. Requires a linked CRM account, and must not be linked to another subscription. Omit for no change; pass an empty string to unlink it.","maxLength":255,"uniqueKey":"oneOf.1.crm_opportunity_id","typeLabel":"string"},"plan_id":{"type":"string","format":"uuid","description":"Optional plan ID for the upgrade. When provided, the upgrade switches to the latest published version of that plan; when omitted, it keeps the subscription's existing plan version and contracted pricing. Must be sent together with `bricks` — `plan_id` alone is rejected with 400. See the endpoint description for full semantics including cross-plan upgrades and merged plan versions.","uniqueKey":"oneOf.1.plan_id","typeLabel":"string\u003cuuid>"},"starts_at":{"oneOf":[{"type":"string","format":"date","description":"The effective date of the subscription upgrade. Required only when `phases` is omitted: when `phases` is provided the phases own the timeline, so the effective date is taken from the first phase's `starts_at` and this order-level value is ignored.","uniqueKey":"oneOf.1.starts_at.oneOf.0","typeLabel":"string\u003cdate>"},{"type":"null","format":"date","description":"The effective date of the subscription upgrade. Required only when `phases` is omitted: when `phases` is provided the phases own the timeline, so the effective date is taken from the first phase's `starts_at` and this order-level value is ignored.","uniqueKey":"oneOf.1.starts_at.oneOf.1","typeLabel":"null"}],"uniqueKey":"oneOf.1.starts_at","typeLabel":"string\u003cdate> | null"},"discount_coupons":{"type":"array","items":{"type":"string","uniqueKey":"oneOf.1.discount_coupons.items.[INDEX]","typeLabel":"string"},"description":"Discount coupon codes to apply to the subscription upgrade. Currently only supports one discount coupon - only the first one in the list will be applied.","uniqueKey":"oneOf.1.discount_coupons","typeLabel":"string[]"},"custom_order_form_html":{"type":"string","description":"The custom order form html to use with `\u003chtml>\u003cbody>...\u003c/body>\u003c/html>` formatting","uniqueKey":"oneOf.1.custom_order_form_html","typeLabel":"string"},"metadata":{"oneOf":[{"description":"Optional metadata to add to the subscription. Sending an empty map will delete all keys. Keys prefixed with _ are private and will be ignored.","uniqueKey":"oneOf.1.metadata.oneOf.0","typeLabel":"any"},{"description":"Optional metadata to add to the subscription. Sending an empty map will delete all keys. Keys prefixed with _ are private and will be ignored.","type":"null","uniqueKey":"oneOf.1.metadata.oneOf.1","typeLabel":"null"}],"uniqueKey":"oneOf.1.metadata","typeLabel":"any | null"},"downgrade_method":{"oneOf":[{"enum":["CREDIT","REFUND"],"type":"string","x-spec-enum-id":"b3bcc767e244c89a","description":"Method to apply for the downgrade. CREDIT - apply as credit, REFUND - refund the money back. Omitted is treated as CREDIT.\n\n* `CREDIT` - Credit\n* `REFUND` - Refund","uniqueKey":"oneOf.1.downgrade_method.oneOf.0","typeLabel":"enum\u003cstring>"},{"enum":["CREDIT","REFUND"],"type":"null","x-spec-enum-id":"b3bcc767e244c89a","description":"Method to apply for the downgrade. CREDIT - apply as credit, REFUND - refund the money back. Omitted is treated as CREDIT.\n\n* `CREDIT` - Credit\n* `REFUND` - Refund","uniqueKey":"oneOf.1.downgrade_method.oneOf.1","typeLabel":"null"}],"uniqueKey":"oneOf.1.downgrade_method","typeLabel":"enum\u003cstring> | null"}},"uniqueKey":"oneOf.1","typeLabel":"SubscriptionInputUpgradeMultiPhase · object"}],"uniqueKey":"","typeLabel":"SubscriptionInputUpgradeSinglePhase · object | SubscriptionInputUpgradeMultiPhase · object"},"examples":{"Example":{"title":"Example","value":{"starts_at":"2023-12-25","bricks":[{"brick_id":"3c90c3cc-0d44-4b50-8888-8dd25736052a","quantity":123,"is_unlimited":true,"discount":[{"rate":"\u003cstring>","amount":123,"renews":false}]}],"crm_opportunity_id":"\u003cstring>","plan_id":"3c90c3cc-0d44-4b50-8888-8dd25736052a","discount_coupons":["\u003cstring>"],"phases":[{"phase_position":1,"bricks":[{"brick_id":"3c90c3cc-0d44-4b50-8888-8dd25736052a","quantity":123,"is_unlimited":true,"discount":[{"rate":"\u003cstring>","amount":123,"renews":false}]}],"starts_at":"2023-12-25","contract_length":2,"plan_id":"3c90c3cc-0d44-4b50-8888-8dd25736052a","payment_terms":499,"discount_coupons":["\u003cstring>"]}],"custom_order_form_html":"\u003cstring>","metadata":"\u003cunknown>"}}},"exampleType":"generated"},"application/x-www-form-urlencoded":{"schema":{"oneOf":[{"type":"object","title":"SubscriptionInputUpgradeSinglePhase","description":"Subscription upgrade input serializer for upgrading a subscription order.\n\nThis payload has two forms — see `anyOf`:\n\n* **Single-phase** — omit `phases`; the order-level `starts_at`, `contract_length`, `billing_frequency` and `bricks` define the one phase and are required.\n* **Multi-phase** — send `phases`; the phases own the timeline, billing frequency and bricks, and the order-level equivalents become optional (omitted, they are derived from the phases).\n\nThe fields are declared optional because OpenAPI 3.0 cannot make one field's `required` depend on another. Sending neither form is a 400.","required":["starts_at","bricks"],"properties":{"starts_at":{"type":"string","description":"The effective date of the subscription upgrade. Required only when `phases` is omitted: when `phases` is provided the phases own the timeline, so the effective date is taken from the first phase's `starts_at` and this order-level value is ignored.","format":"date","isRequired":true,"uniqueKey":"oneOf.0.starts_at","typeLabel":"string\u003cdate>"},"bricks":{"type":"array","items":{"type":"object","description":"Line item input serializer for creating a new estimate","properties":{"brick_id":{"type":"string","format":"uuid","description":"The ID of the brick to add to the subscription","isRequired":true,"uniqueKey":"oneOf.0.bricks.items.[INDEX].brick_id","typeLabel":"string\u003cuuid>"},"quantity":{"type":"integer","description":"The quantity of the brick, used as the basis for its price","uniqueKey":"oneOf.0.bricks.items.[INDEX].quantity","typeLabel":"integer"},"is_unlimited":{"type":"boolean","description":"Sell this line with an uncapped entitlement, keeping `quantity` as the pricing basis its price is calculated from. Optional: omitting it on create leaves the line limited, and omitting it on update leaves the line's current value alone — send it explicitly as false to clear it. Subscription bricks only.","uniqueKey":"oneOf.0.bricks.items.[INDEX].is_unlimited","typeLabel":"boolean"},"discount":{"oneOf":[{"type":"array","items":{"type":"object","description":"Discount serializer for a subscription estimate line item","properties":{"rate":{"type":"string","format":"decimal","pattern":"^-?\\d{0,14}(?:\\.\\d{0,6})?$","description":"The discount rate as a percentage with up to six decimal places (e.g. 10 = 10%, 62.6758 = 62.6758%). Mutually exclusive with `amount`.","uniqueKey":"oneOf.0.bricks.items.[INDEX].discount.oneOf.0.items.[INDEX].rate","typeLabel":"string\u003cdecimal>"},"amount":{"type":"integer","description":"A fixed discount amount in cents (e.g. 1000 = $10.00). One-time only — `renews` must be false when `amount` is set. Mutually exclusive with `rate`. The amount is applied as-is and is not clamped to the line item total, so it should not exceed the brick's price.","uniqueKey":"oneOf.0.bricks.items.[INDEX].discount.oneOf.0.items.[INDEX].amount","typeLabel":"integer"},"renews":{"type":"boolean","default":false,"description":"If the discount is carried over at renewal. Must be false when `amount` is set, as fixed discounts are one-time only.","uniqueKey":"oneOf.0.bricks.items.[INDEX].discount.oneOf.0.items.[INDEX].renews","typeLabel":"boolean"}},"uniqueKey":"oneOf.0.bricks.items.[INDEX].discount.oneOf.0.items.[INDEX]","typeLabel":"object"},"description":"A list of discounts to apply to the line item — at most one renewing rate, one one-time rate, and one fixed amount. Discounts are replaced, not merged: what is sent here becomes the line item's complete set of discounts. Omitting this field for a brick that currently has a discount drops that discount. Read the current values from the subscription's line items, which return `discount` in this same shape, and send them back for every brick whose discount should carry over.","uniqueKey":"oneOf.0.bricks.items.[INDEX].discount.oneOf.0","typeLabel":"object[]"},{"type":"null","items":{"type":"object","description":"Discount serializer for a subscription estimate line item","properties":{"rate":{"type":"string","format":"decimal","pattern":"^-?\\d{0,14}(?:\\.\\d{0,6})?$","description":"The discount rate as a percentage with up to six decimal places (e.g. 10 = 10%, 62.6758 = 62.6758%). Mutually exclusive with `amount`."},"amount":{"type":"integer","description":"A fixed discount amount in cents (e.g. 1000 = $10.00). One-time only — `renews` must be false when `amount` is set. Mutually exclusive with `rate`. The amount is applied as-is and is not clamped to the line item total, so it should not exceed the brick's price."},"renews":{"type":"boolean","default":false,"description":"If the discount is carried over at renewal. Must be false when `amount` is set, as fixed discounts are one-time only."}}},"description":"A list of discounts to apply to the line item — at most one renewing rate, one one-time rate, and one fixed amount. Discounts are replaced, not merged: what is sent here becomes the line item's complete set of discounts. Omitting this field for a brick that currently has a discount drops that discount. Read the current values from the subscription's line items, which return `discount` in this same shape, and send them back for every brick whose discount should carry over.","uniqueKey":"oneOf.0.bricks.items.[INDEX].discount.oneOf.1","typeLabel":"null"}],"uniqueKey":"oneOf.0.bricks.items.[INDEX].discount","typeLabel":"object[] | null"}},"required":["brick_id"],"uniqueKey":"oneOf.0.bricks.items.[INDEX]","typeLabel":"object"},"description":"The bricks included in subscription upgrade. Quantity is used to upgrade the add-on quantity (ie. adding 2 more units should be quantity 2 -> quantity 4). For usage, quantity is used to set the pre-commitment (ie. previously having 5 pre-commitment quantity and updating it to 10 would update the pre-commitment quantity to 10.)","isRequired":true,"uniqueKey":"oneOf.0.bricks","typeLabel":"object[]"},"crm_opportunity_id":{"type":"string","description":"Optional ID of the opportunity (deal in HubSpot) in your connected CRM to link the subscription to. Requires a linked CRM account, and must not be linked to another subscription. Omit for no change; pass an empty string to unlink it.","maxLength":255,"uniqueKey":"oneOf.0.crm_opportunity_id","typeLabel":"string"},"plan_id":{"type":"string","format":"uuid","description":"Optional plan ID for the upgrade. When provided, the upgrade switches to the latest published version of that plan; when omitted, it keeps the subscription's existing plan version and contracted pricing. Must be sent together with `bricks` — `plan_id` alone is rejected with 400. See the endpoint description for full semantics including cross-plan upgrades and merged plan versions.","uniqueKey":"oneOf.0.plan_id","typeLabel":"string\u003cuuid>"},"discount_coupons":{"type":"array","items":{"type":"string","uniqueKey":"oneOf.0.discount_coupons.items.[INDEX]","typeLabel":"string"},"description":"Discount coupon codes to apply to the subscription upgrade. Currently only supports one discount coupon - only the first one in the list will be applied.","uniqueKey":"oneOf.0.discount_coupons","typeLabel":"string[]"},"phases":{"oneOf":[{"type":"array","items":{"type":"object","description":"Input serializer for a single order phase in multi-phase operations.\n\n``phase_position`` is required on every phase. For creation, recast and\nestimate the array is the complete phase set, so positions must be the full\n0-based sequence (position N at index N). For upgrades only the phases being\nchanged are sent, so positions are a subset of the base order's phase\npositions.\n\n``starts_at`` is optional — phase 0 defaults to the order-level starts_at,\nand subsequent phases are derived from the previous phase's end date.\n\n``contract_length`` replaces the old ``ends_at`` field. Required for\ncreate/estimate/recast; not needed for upgrades (end date inherited from\nthe base order). The phase *output* reports ``ends_at`` rather than\n``contract_length``, so a read-modify-write of a phase has to convert:\n``contract_length`` is the number of whole months from ``starts_at`` to the\nday after ``ends_at``. Phases are contiguous and whole-month, so the\nconversion is exact.\n\n``billing_frequency`` follows the same rule: required for\ncreate/estimate/recast, where phases own the billing frequency outright,\nand inherited from the base order's phase on upgrades.\n\n``plan_id`` is optional and lets a phase sell a different plan from the\norder's, matching what the order builder already supports (SAL-6327).\nOmitted, the phase uses the order-level ``plan_id``.","properties":{"phase_position":{"type":"integer","minimum":0,"description":"Phase position (0-based). Must be unique across phases.","isRequired":true,"uniqueKey":"oneOf.0.phases.oneOf.0.items.[INDEX].phase_position","typeLabel":"integer"},"bricks":{"type":"array","items":{"type":"object","description":"Line item input serializer for creating a new estimate","properties":{"brick_id":{"type":"string","format":"uuid","description":"The ID of the brick to add to the subscription","isRequired":true,"uniqueKey":"oneOf.0.phases.oneOf.0.items.[INDEX].bricks.items.[INDEX].brick_id","typeLabel":"string\u003cuuid>"},"quantity":{"type":"integer","description":"The quantity of the brick, used as the basis for its price","uniqueKey":"oneOf.0.phases.oneOf.0.items.[INDEX].bricks.items.[INDEX].quantity","typeLabel":"integer"},"is_unlimited":{"type":"boolean","description":"Sell this line with an uncapped entitlement, keeping `quantity` as the pricing basis its price is calculated from. Optional: omitting it on create leaves the line limited, and omitting it on update leaves the line's current value alone — send it explicitly as false to clear it. Subscription bricks only.","uniqueKey":"oneOf.0.phases.oneOf.0.items.[INDEX].bricks.items.[INDEX].is_unlimited","typeLabel":"boolean"},"discount":{"oneOf":[{"type":"array","items":{"type":"object","description":"Discount serializer for a subscription estimate line item","properties":{"rate":{"type":"string","format":"decimal","pattern":"^-?\\d{0,14}(?:\\.\\d{0,6})?$","description":"The discount rate as a percentage with up to six decimal places (e.g. 10 = 10%, 62.6758 = 62.6758%). Mutually exclusive with `amount`.","uniqueKey":"oneOf.0.phases.oneOf.0.items.[INDEX].bricks.items.[INDEX].discount.oneOf.0.items.[INDEX].rate","typeLabel":"string\u003cdecimal>"},"amount":{"type":"integer","description":"A fixed discount amount in cents (e.g. 1000 = $10.00). One-time only — `renews` must be false when `amount` is set. Mutually exclusive with `rate`. The amount is applied as-is and is not clamped to the line item total, so it should not exceed the brick's price.","uniqueKey":"oneOf.0.phases.oneOf.0.items.[INDEX].bricks.items.[INDEX].discount.oneOf.0.items.[INDEX].amount","typeLabel":"integer"},"renews":{"type":"boolean","default":false,"description":"If the discount is carried over at renewal. Must be false when `amount` is set, as fixed discounts are one-time only.","uniqueKey":"oneOf.0.phases.oneOf.0.items.[INDEX].bricks.items.[INDEX].discount.oneOf.0.items.[INDEX].renews","typeLabel":"boolean"}},"uniqueKey":"oneOf.0.phases.oneOf.0.items.[INDEX].bricks.items.[INDEX].discount.oneOf.0.items.[INDEX]","typeLabel":"object"},"description":"A list of discounts to apply to the line item — at most one renewing rate, one one-time rate, and one fixed amount. Discounts are replaced, not merged: what is sent here becomes the line item's complete set of discounts. Omitting this field for a brick that currently has a discount drops that discount. Read the current values from the subscription's line items, which return `discount` in this same shape, and send them back for every brick whose discount should carry over.","uniqueKey":"oneOf.0.phases.oneOf.0.items.[INDEX].bricks.items.[INDEX].discount.oneOf.0","typeLabel":"object[]"},{"type":"null","items":{"type":"object","description":"Discount serializer for a subscription estimate line item","properties":{"rate":{"type":"string","format":"decimal","pattern":"^-?\\d{0,14}(?:\\.\\d{0,6})?$","description":"The discount rate as a percentage with up to six decimal places (e.g. 10 = 10%, 62.6758 = 62.6758%). Mutually exclusive with `amount`."},"amount":{"type":"integer","description":"A fixed discount amount in cents (e.g. 1000 = $10.00). One-time only — `renews` must be false when `amount` is set. Mutually exclusive with `rate`. The amount is applied as-is and is not clamped to the line item total, so it should not exceed the brick's price."},"renews":{"type":"boolean","default":false,"description":"If the discount is carried over at renewal. Must be false when `amount` is set, as fixed discounts are one-time only."}}},"description":"A list of discounts to apply to the line item — at most one renewing rate, one one-time rate, and one fixed amount. Discounts are replaced, not merged: what is sent here becomes the line item's complete set of discounts. Omitting this field for a brick that currently has a discount drops that discount. Read the current values from the subscription's line items, which return `discount` in this same shape, and send them back for every brick whose discount should carry over.","uniqueKey":"oneOf.0.phases.oneOf.0.items.[INDEX].bricks.items.[INDEX].discount.oneOf.1","typeLabel":"null"}],"uniqueKey":"oneOf.0.phases.oneOf.0.items.[INDEX].bricks.items.[INDEX].discount","typeLabel":"object[] | null"}},"required":["brick_id"],"uniqueKey":"oneOf.0.phases.oneOf.0.items.[INDEX].bricks.items.[INDEX]","typeLabel":"object"},"description":"The bricks included in this phase.","isRequired":true,"uniqueKey":"oneOf.0.phases.oneOf.0.items.[INDEX].bricks","typeLabel":"object[]"},"starts_at":{"oneOf":[{"type":"string","format":"date","description":"Start date of this phase. Optional — phase 0 defaults to order-level starts_at; subsequent phases are derived from the previous phase's end date + 1 day.","uniqueKey":"oneOf.0.phases.oneOf.0.items.[INDEX].starts_at.oneOf.0","typeLabel":"string\u003cdate>"},{"type":"null","format":"date","description":"Start date of this phase. Optional — phase 0 defaults to order-level starts_at; subsequent phases are derived from the previous phase's end date + 1 day.","uniqueKey":"oneOf.0.phases.oneOf.0.items.[INDEX].starts_at.oneOf.1","typeLabel":"null"}],"uniqueKey":"oneOf.0.phases.oneOf.0.items.[INDEX].starts_at","typeLabel":"string\u003cdate> | null"},"contract_length":{"oneOf":[{"type":"integer","minimum":1,"description":"Duration of this phase in months. Required for create, estimate, and recast. Not required for upgrades (end date inherited from the base order).","uniqueKey":"oneOf.0.phases.oneOf.0.items.[INDEX].contract_length.oneOf.0","typeLabel":"integer"},{"type":"null","minimum":1,"description":"Duration of this phase in months. Required for create, estimate, and recast. Not required for upgrades (end date inherited from the base order).","uniqueKey":"oneOf.0.phases.oneOf.0.items.[INDEX].contract_length.oneOf.1","typeLabel":"null"}],"uniqueKey":"oneOf.0.phases.oneOf.0.items.[INDEX].contract_length","typeLabel":"integer | null"},"billing_frequency":{"enum":["MONTHLY","QUARTERLY","SEMI_ANNUALLY","ANNUALLY","ALL_UPFRONT","CUSTOM"],"type":"string","x-spec-enum-id":"5f29351b16a5547f","description":"Billing frequency for this phase. Required for create, estimate and recast — when phases are provided they own the billing frequency outright, so the order-level billing_frequency is not consulted. Not required for upgrades (inherited from the base order's phase). The legacy name `billing_schedule` is still accepted.\n\n* `MONTHLY` - Monthly\n* `QUARTERLY` - Quarterly\n* `SEMI_ANNUALLY` - Semi-annually\n* `ANNUALLY` - Annually\n* `ALL_UPFRONT` - All upfront\n* `CUSTOM` - Custom","uniqueKey":"oneOf.0.phases.oneOf.0.items.[INDEX].billing_frequency","typeLabel":"enum\u003cstring>"},"plan_id":{"oneOf":[{"type":"string","format":"uuid","description":"Optional plan for this phase. Each phase may sell a different plan; the phase's bricks are then validated and priced against it. Defaults to the order-level `plan_id`.","uniqueKey":"oneOf.0.phases.oneOf.0.items.[INDEX].plan_id.oneOf.0","typeLabel":"string\u003cuuid>"},{"type":"null","format":"uuid","description":"Optional plan for this phase. Each phase may sell a different plan; the phase's bricks are then validated and priced against it. Defaults to the order-level `plan_id`.","uniqueKey":"oneOf.0.phases.oneOf.0.items.[INDEX].plan_id.oneOf.1","typeLabel":"null"}],"uniqueKey":"oneOf.0.phases.oneOf.0.items.[INDEX].plan_id","typeLabel":"string\u003cuuid> | null"},"payment_terms":{"type":"integer","maximum":999,"minimum":0,"description":"Payment terms in days for this phase. Named to match the order-level `payment_terms` input and the phase output — the model field it lands on is `payment_due_upon_receipt`, which is still accepted as a legacy name. Omitted, the phase inherits the order-level value.","uniqueKey":"oneOf.0.phases.oneOf.0.items.[INDEX].payment_terms","typeLabel":"integer"},"discount_coupons":{"type":"array","items":{"type":"string","uniqueKey":"oneOf.0.phases.oneOf.0.items.[INDEX].discount_coupons.items.[INDEX]","typeLabel":"string"},"description":"Discount coupon codes to apply to this phase. Currently only supports one discount coupon - only the first one in the list will be applied.","uniqueKey":"oneOf.0.phases.oneOf.0.items.[INDEX].discount_coupons","typeLabel":"string[]"}},"required":["bricks","phase_position"],"uniqueKey":"oneOf.0.phases.oneOf.0.items.[INDEX]","typeLabel":"object"},"description":"Optional list of phases for a multi-phase upgrade. Each phase's ``phase_position`` must match a phase on the base order; only the phases being changed need to be sent, and omitted positions are inherited from the base order unchanged. Order-level bricks and `starts_at` are ignored when phases are provided — the phases own the timeline and the first phase's `starts_at` is the upgrade's effective date.","uniqueKey":"oneOf.0.phases.oneOf.0","typeLabel":"object[]"},{"type":"null","items":{"type":"object","description":"Input serializer for a single order phase in multi-phase operations.\n\n``phase_position`` is required on every phase. For creation, recast and\nestimate the array is the complete phase set, so positions must be the full\n0-based sequence (position N at index N). For upgrades only the phases being\nchanged are sent, so positions are a subset of the base order's phase\npositions.\n\n``starts_at`` is optional — phase 0 defaults to the order-level starts_at,\nand subsequent phases are derived from the previous phase's end date.\n\n``contract_length`` replaces the old ``ends_at`` field. Required for\ncreate/estimate/recast; not needed for upgrades (end date inherited from\nthe base order). The phase *output* reports ``ends_at`` rather than\n``contract_length``, so a read-modify-write of a phase has to convert:\n``contract_length`` is the number of whole months from ``starts_at`` to the\nday after ``ends_at``. Phases are contiguous and whole-month, so the\nconversion is exact.\n\n``billing_frequency`` follows the same rule: required for\ncreate/estimate/recast, where phases own the billing frequency outright,\nand inherited from the base order's phase on upgrades.\n\n``plan_id`` is optional and lets a phase sell a different plan from the\norder's, matching what the order builder already supports (SAL-6327).\nOmitted, the phase uses the order-level ``plan_id``.","properties":{"phase_position":{"type":"integer","minimum":0,"description":"Phase position (0-based). Must be unique across phases."},"starts_at":{"oneOf":[{"type":"string","format":"date","description":"Start date of this phase. Optional — phase 0 defaults to order-level starts_at; subsequent phases are derived from the previous phase's end date + 1 day."},{"type":"null","format":"date","description":"Start date of this phase. Optional — phase 0 defaults to order-level starts_at; subsequent phases are derived from the previous phase's end date + 1 day."}]},"contract_length":{"oneOf":[{"type":"integer","minimum":1,"description":"Duration of this phase in months. Required for create, estimate, and recast. Not required for upgrades (end date inherited from the base order)."},{"type":"null","minimum":1,"description":"Duration of this phase in months. Required for create, estimate, and recast. Not required for upgrades (end date inherited from the base order)."}]},"billing_frequency":{"enum":["MONTHLY","QUARTERLY","SEMI_ANNUALLY","ANNUALLY","ALL_UPFRONT","CUSTOM"],"type":"string","x-spec-enum-id":"5f29351b16a5547f","description":"Billing frequency for this phase. Required for create, estimate and recast — when phases are provided they own the billing frequency outright, so the order-level billing_frequency is not consulted. Not required for upgrades (inherited from the base order's phase). The legacy name `billing_schedule` is still accepted.\n\n* `MONTHLY` - Monthly\n* `QUARTERLY` - Quarterly\n* `SEMI_ANNUALLY` - Semi-annually\n* `ANNUALLY` - Annually\n* `ALL_UPFRONT` - All upfront\n* `CUSTOM` - Custom"},"plan_id":{"oneOf":[{"type":"string","format":"uuid","description":"Optional plan for this phase. Each phase may sell a different plan; the phase's bricks are then validated and priced against it. Defaults to the order-level `plan_id`."},{"type":"null","format":"uuid","description":"Optional plan for this phase. Each phase may sell a different plan; the phase's bricks are then validated and priced against it. Defaults to the order-level `plan_id`."}]},"payment_terms":{"type":"integer","maximum":999,"minimum":0,"description":"Payment terms in days for this phase. Named to match the order-level `payment_terms` input and the phase output — the model field it lands on is `payment_due_upon_receipt`, which is still accepted as a legacy name. Omitted, the phase inherits the order-level value."},"bricks":{"type":"array","items":{"type":"object","description":"Line item input serializer for creating a new estimate","properties":{"brick_id":{"type":"string","format":"uuid","description":"The ID of the brick to add to the subscription"},"quantity":{"type":"integer","description":"The quantity of the brick, used as the basis for its price"},"is_unlimited":{"type":"boolean","description":"Sell this line with an uncapped entitlement, keeping `quantity` as the pricing basis its price is calculated from. Optional: omitting it on create leaves the line limited, and omitting it on update leaves the line's current value alone — send it explicitly as false to clear it. Subscription bricks only."},"discount":{"oneOf":[{"type":"array","items":{"type":"object","description":"Discount serializer for a subscription estimate line item","properties":{"rate":{"type":"string","format":"decimal","pattern":"^-?\\d{0,14}(?:\\.\\d{0,6})?$","description":"The discount rate as a percentage with up to six decimal places (e.g. 10 = 10%, 62.6758 = 62.6758%). Mutually exclusive with `amount`."},"amount":{"type":"integer","description":"A fixed discount amount in cents (e.g. 1000 = $10.00). One-time only — `renews` must be false when `amount` is set. Mutually exclusive with `rate`. The amount is applied as-is and is not clamped to the line item total, so it should not exceed the brick's price."},"renews":{"type":"boolean","default":false,"description":"If the discount is carried over at renewal. Must be false when `amount` is set, as fixed discounts are one-time only."}}},"description":"A list of discounts to apply to the line item — at most one renewing rate, one one-time rate, and one fixed amount. Discounts are replaced, not merged: what is sent here becomes the line item's complete set of discounts. Omitting this field for a brick that currently has a discount drops that discount. Read the current values from the subscription's line items, which return `discount` in this same shape, and send them back for every brick whose discount should carry over."},{"type":"null","items":{"type":"object","description":"Discount serializer for a subscription estimate line item","properties":{"rate":{"type":"string","format":"decimal","pattern":"^-?\\d{0,14}(?:\\.\\d{0,6})?$","description":"The discount rate as a percentage with up to six decimal places (e.g. 10 = 10%, 62.6758 = 62.6758%). Mutually exclusive with `amount`."},"amount":{"type":"integer","description":"A fixed discount amount in cents (e.g. 1000 = $10.00). One-time only — `renews` must be false when `amount` is set. Mutually exclusive with `rate`. The amount is applied as-is and is not clamped to the line item total, so it should not exceed the brick's price."},"renews":{"type":"boolean","default":false,"description":"If the discount is carried over at renewal. Must be false when `amount` is set, as fixed discounts are one-time only."}}},"description":"A list of discounts to apply to the line item — at most one renewing rate, one one-time rate, and one fixed amount. Discounts are replaced, not merged: what is sent here becomes the line item's complete set of discounts. Omitting this field for a brick that currently has a discount drops that discount. Read the current values from the subscription's line items, which return `discount` in this same shape, and send them back for every brick whose discount should carry over."}]}},"required":["brick_id"]},"description":"The bricks included in this phase."},"discount_coupons":{"type":"array","items":{"type":"string"},"description":"Discount coupon codes to apply to this phase. Currently only supports one discount coupon - only the first one in the list will be applied."}},"required":["bricks","phase_position"]},"description":"Optional list of phases for a multi-phase upgrade. Each phase's ``phase_position`` must match a phase on the base order; only the phases being changed need to be sent, and omitted positions are inherited from the base order unchanged. Order-level bricks and `starts_at` are ignored when phases are provided — the phases own the timeline and the first phase's `starts_at` is the upgrade's effective date.","uniqueKey":"oneOf.0.phases.oneOf.1","typeLabel":"null"}],"uniqueKey":"oneOf.0.phases","typeLabel":"object[] | null"},"custom_order_form_html":{"type":"string","description":"The custom order form html to use with `\u003chtml>\u003cbody>...\u003c/body>\u003c/html>` formatting","uniqueKey":"oneOf.0.custom_order_form_html","typeLabel":"string"},"metadata":{"oneOf":[{"description":"Optional metadata to add to the subscription. Sending an empty map will delete all keys. Keys prefixed with _ are private and will be ignored.","uniqueKey":"oneOf.0.metadata.oneOf.0","typeLabel":"any"},{"description":"Optional metadata to add to the subscription. Sending an empty map will delete all keys. Keys prefixed with _ are private and will be ignored.","type":"null","uniqueKey":"oneOf.0.metadata.oneOf.1","typeLabel":"null"}],"uniqueKey":"oneOf.0.metadata","typeLabel":"any | null"},"downgrade_method":{"oneOf":[{"enum":["CREDIT","REFUND"],"type":"string","x-spec-enum-id":"b3bcc767e244c89a","description":"Method to apply for the downgrade. CREDIT - apply as credit, REFUND - refund the money back. Omitted is treated as CREDIT.\n\n* `CREDIT` - Credit\n* `REFUND` - Refund","uniqueKey":"oneOf.0.downgrade_method.oneOf.0","typeLabel":"enum\u003cstring>"},{"enum":["CREDIT","REFUND"],"type":"null","x-spec-enum-id":"b3bcc767e244c89a","description":"Method to apply for the downgrade. CREDIT - apply as credit, REFUND - refund the money back. Omitted is treated as CREDIT.\n\n* `CREDIT` - Credit\n* `REFUND` - Refund","uniqueKey":"oneOf.0.downgrade_method.oneOf.1","typeLabel":"null"}],"uniqueKey":"oneOf.0.downgrade_method","typeLabel":"enum\u003cstring> | null"}},"uniqueKey":"oneOf.0","typeLabel":"SubscriptionInputUpgradeSinglePhase · object"},{"type":"object","title":"SubscriptionInputUpgradeMultiPhase","description":"Subscription upgrade input serializer for upgrading a subscription order.\n\nThis payload has two forms — see `anyOf`:\n\n* **Single-phase** — omit `phases`; the order-level `starts_at`, `contract_length`, `billing_frequency` and `bricks` define the one phase and are required.\n* **Multi-phase** — send `phases`; the phases own the timeline, billing frequency and bricks, and the order-level equivalents become optional (omitted, they are derived from the phases).\n\nThe fields are declared optional because OpenAPI 3.0 cannot make one field's `required` depend on another. Sending neither form is a 400.","required":["phases","bricks"],"properties":{"bricks":{"type":"array","items":{"type":"object","description":"Line item input serializer for creating a new estimate","properties":{"brick_id":{"type":"string","format":"uuid","description":"The ID of the brick to add to the subscription","isRequired":true,"uniqueKey":"oneOf.1.bricks.items.[INDEX].brick_id","typeLabel":"string\u003cuuid>"},"quantity":{"type":"integer","description":"The quantity of the brick, used as the basis for its price","uniqueKey":"oneOf.1.bricks.items.[INDEX].quantity","typeLabel":"integer"},"is_unlimited":{"type":"boolean","description":"Sell this line with an uncapped entitlement, keeping `quantity` as the pricing basis its price is calculated from. Optional: omitting it on create leaves the line limited, and omitting it on update leaves the line's current value alone — send it explicitly as false to clear it. Subscription bricks only.","uniqueKey":"oneOf.1.bricks.items.[INDEX].is_unlimited","typeLabel":"boolean"},"discount":{"oneOf":[{"type":"array","items":{"type":"object","description":"Discount serializer for a subscription estimate line item","properties":{"rate":{"type":"string","format":"decimal","pattern":"^-?\\d{0,14}(?:\\.\\d{0,6})?$","description":"The discount rate as a percentage with up to six decimal places (e.g. 10 = 10%, 62.6758 = 62.6758%). Mutually exclusive with `amount`.","uniqueKey":"oneOf.1.bricks.items.[INDEX].discount.oneOf.0.items.[INDEX].rate","typeLabel":"string\u003cdecimal>"},"amount":{"type":"integer","description":"A fixed discount amount in cents (e.g. 1000 = $10.00). One-time only — `renews` must be false when `amount` is set. Mutually exclusive with `rate`. The amount is applied as-is and is not clamped to the line item total, so it should not exceed the brick's price.","uniqueKey":"oneOf.1.bricks.items.[INDEX].discount.oneOf.0.items.[INDEX].amount","typeLabel":"integer"},"renews":{"type":"boolean","default":false,"description":"If the discount is carried over at renewal. Must be false when `amount` is set, as fixed discounts are one-time only.","uniqueKey":"oneOf.1.bricks.items.[INDEX].discount.oneOf.0.items.[INDEX].renews","typeLabel":"boolean"}},"uniqueKey":"oneOf.1.bricks.items.[INDEX].discount.oneOf.0.items.[INDEX]","typeLabel":"object"},"description":"A list of discounts to apply to the line item — at most one renewing rate, one one-time rate, and one fixed amount. Discounts are replaced, not merged: what is sent here becomes the line item's complete set of discounts. Omitting this field for a brick that currently has a discount drops that discount. Read the current values from the subscription's line items, which return `discount` in this same shape, and send them back for every brick whose discount should carry over.","uniqueKey":"oneOf.1.bricks.items.[INDEX].discount.oneOf.0","typeLabel":"object[]"},{"type":"null","items":{"type":"object","description":"Discount serializer for a subscription estimate line item","properties":{"rate":{"type":"string","format":"decimal","pattern":"^-?\\d{0,14}(?:\\.\\d{0,6})?$","description":"The discount rate as a percentage with up to six decimal places (e.g. 10 = 10%, 62.6758 = 62.6758%). Mutually exclusive with `amount`."},"amount":{"type":"integer","description":"A fixed discount amount in cents (e.g. 1000 = $10.00). One-time only — `renews` must be false when `amount` is set. Mutually exclusive with `rate`. The amount is applied as-is and is not clamped to the line item total, so it should not exceed the brick's price."},"renews":{"type":"boolean","default":false,"description":"If the discount is carried over at renewal. Must be false when `amount` is set, as fixed discounts are one-time only."}}},"description":"A list of discounts to apply to the line item — at most one renewing rate, one one-time rate, and one fixed amount. Discounts are replaced, not merged: what is sent here becomes the line item's complete set of discounts. Omitting this field for a brick that currently has a discount drops that discount. Read the current values from the subscription's line items, which return `discount` in this same shape, and send them back for every brick whose discount should carry over.","uniqueKey":"oneOf.1.bricks.items.[INDEX].discount.oneOf.1","typeLabel":"null"}],"uniqueKey":"oneOf.1.bricks.items.[INDEX].discount","typeLabel":"object[] | null"}},"required":["brick_id"],"uniqueKey":"oneOf.1.bricks.items.[INDEX]","typeLabel":"object"},"description":"The bricks included in subscription upgrade. Quantity is used to upgrade the add-on quantity (ie. adding 2 more units should be quantity 2 -> quantity 4). For usage, quantity is used to set the pre-commitment (ie. previously having 5 pre-commitment quantity and updating it to 10 would update the pre-commitment quantity to 10.)","isRequired":true,"uniqueKey":"oneOf.1.bricks","typeLabel":"object[]"},"phases":{"type":"array","items":{"type":"object","description":"Input serializer for a single order phase in multi-phase operations.\n\n``phase_position`` is required on every phase. For creation, recast and\nestimate the array is the complete phase set, so positions must be the full\n0-based sequence (position N at index N). For upgrades only the phases being\nchanged are sent, so positions are a subset of the base order's phase\npositions.\n\n``starts_at`` is optional — phase 0 defaults to the order-level starts_at,\nand subsequent phases are derived from the previous phase's end date.\n\n``contract_length`` replaces the old ``ends_at`` field. Required for\ncreate/estimate/recast; not needed for upgrades (end date inherited from\nthe base order). The phase *output* reports ``ends_at`` rather than\n``contract_length``, so a read-modify-write of a phase has to convert:\n``contract_length`` is the number of whole months from ``starts_at`` to the\nday after ``ends_at``. Phases are contiguous and whole-month, so the\nconversion is exact.\n\n``billing_frequency`` follows the same rule: required for\ncreate/estimate/recast, where phases own the billing frequency outright,\nand inherited from the base order's phase on upgrades.\n\n``plan_id`` is optional and lets a phase sell a different plan from the\norder's, matching what the order builder already supports (SAL-6327).\nOmitted, the phase uses the order-level ``plan_id``.","required":["bricks","phase_position"],"properties":{"phase_position":{"type":"integer","description":"Phase position (0-based). Must be unique across phases.","minimum":0,"isRequired":true,"uniqueKey":"oneOf.1.phases.items.[INDEX].phase_position","typeLabel":"integer"},"bricks":{"type":"array","items":{"type":"object","description":"Line item input serializer for creating a new estimate","required":["brick_id"],"properties":{"brick_id":{"type":"string","description":"The ID of the brick to add to the subscription","format":"uuid","isRequired":true,"uniqueKey":"oneOf.1.phases.items.[INDEX].bricks.items.[INDEX].brick_id","typeLabel":"string\u003cuuid>"},"quantity":{"type":"integer","description":"The quantity of the brick, used as the basis for its price","uniqueKey":"oneOf.1.phases.items.[INDEX].bricks.items.[INDEX].quantity","typeLabel":"integer"},"is_unlimited":{"type":"boolean","description":"Sell this line with an uncapped entitlement, keeping `quantity` as the pricing basis its price is calculated from. Optional: omitting it on create leaves the line limited, and omitting it on update leaves the line's current value alone — send it explicitly as false to clear it. Subscription bricks only.","uniqueKey":"oneOf.1.phases.items.[INDEX].bricks.items.[INDEX].is_unlimited","typeLabel":"boolean"},"discount":{"oneOf":[{"type":"array","items":{"type":"object","description":"Discount serializer for a subscription estimate line item","properties":{"rate":{"type":"string","description":"The discount rate as a percentage with up to six decimal places (e.g. 10 = 10%, 62.6758 = 62.6758%). Mutually exclusive with `amount`.","format":"decimal","pattern":"^-?\\d{0,14}(?:\\.\\d{0,6})?$","uniqueKey":"oneOf.1.phases.items.[INDEX].bricks.items.[INDEX].discount.oneOf.0.items.[INDEX].rate","typeLabel":"string\u003cdecimal>"},"amount":{"type":"integer","description":"A fixed discount amount in cents (e.g. 1000 = $10.00). One-time only — `renews` must be false when `amount` is set. Mutually exclusive with `rate`. The amount is applied as-is and is not clamped to the line item total, so it should not exceed the brick's price.","uniqueKey":"oneOf.1.phases.items.[INDEX].bricks.items.[INDEX].discount.oneOf.0.items.[INDEX].amount","typeLabel":"integer"},"renews":{"type":"boolean","description":"If the discount is carried over at renewal. Must be false when `amount` is set, as fixed discounts are one-time only.","default":false,"uniqueKey":"oneOf.1.phases.items.[INDEX].bricks.items.[INDEX].discount.oneOf.0.items.[INDEX].renews","typeLabel":"boolean"}},"uniqueKey":"oneOf.1.phases.items.[INDEX].bricks.items.[INDEX].discount.oneOf.0.items.[INDEX]","typeLabel":"object"},"description":"A list of discounts to apply to the line item — at most one renewing rate, one one-time rate, and one fixed amount. Discounts are replaced, not merged: what is sent here becomes the line item's complete set of discounts. Omitting this field for a brick that currently has a discount drops that discount. Read the current values from the subscription's line items, which return `discount` in this same shape, and send them back for every brick whose discount should carry over.","uniqueKey":"oneOf.1.phases.items.[INDEX].bricks.items.[INDEX].discount.oneOf.0","typeLabel":"object[]"},{"type":"null","description":"A list of discounts to apply to the line item — at most one renewing rate, one one-time rate, and one fixed amount. Discounts are replaced, not merged: what is sent here becomes the line item's complete set of discounts. Omitting this field for a brick that currently has a discount drops that discount. Read the current values from the subscription's line items, which return `discount` in this same shape, and send them back for every brick whose discount should carry over.","uniqueKey":"oneOf.1.phases.items.[INDEX].bricks.items.[INDEX].discount.oneOf.1","typeLabel":"null"}],"uniqueKey":"oneOf.1.phases.items.[INDEX].bricks.items.[INDEX].discount","typeLabel":"object[] | null"}},"uniqueKey":"oneOf.1.phases.items.[INDEX].bricks.items.[INDEX]","typeLabel":"object"},"description":"The bricks included in this phase.","isRequired":true,"uniqueKey":"oneOf.1.phases.items.[INDEX].bricks","typeLabel":"object[]"},"starts_at":{"oneOf":[{"type":"string","description":"Start date of this phase. Optional — phase 0 defaults to order-level starts_at; subsequent phases are derived from the previous phase's end date + 1 day.","format":"date","uniqueKey":"oneOf.1.phases.items.[INDEX].starts_at.oneOf.0","typeLabel":"string\u003cdate>"},{"type":"null","description":"Start date of this phase. Optional — phase 0 defaults to order-level starts_at; subsequent phases are derived from the previous phase's end date + 1 day.","format":"date","uniqueKey":"oneOf.1.phases.items.[INDEX].starts_at.oneOf.1","typeLabel":"null"}],"uniqueKey":"oneOf.1.phases.items.[INDEX].starts_at","typeLabel":"string\u003cdate> | null"},"contract_length":{"oneOf":[{"type":"integer","description":"Duration of this phase in months. Required for create, estimate, and recast. Not required for upgrades (end date inherited from the base order).","minimum":1,"uniqueKey":"oneOf.1.phases.items.[INDEX].contract_length.oneOf.0","typeLabel":"integer"},{"type":"null","description":"Duration of this phase in months. Required for create, estimate, and recast. Not required for upgrades (end date inherited from the base order).","minimum":1,"uniqueKey":"oneOf.1.phases.items.[INDEX].contract_length.oneOf.1","typeLabel":"null"}],"uniqueKey":"oneOf.1.phases.items.[INDEX].contract_length","typeLabel":"integer | null"},"billing_frequency":{"type":"string","description":"Billing frequency for this phase. Required for create, estimate and recast — when phases are provided they own the billing frequency outright, so the order-level billing_frequency is not consulted. Not required for upgrades (inherited from the base order's phase). The legacy name `billing_schedule` is still accepted.\n\n* `MONTHLY` - Monthly\n* `QUARTERLY` - Quarterly\n* `SEMI_ANNUALLY` - Semi-annually\n* `ANNUALLY` - Annually\n* `ALL_UPFRONT` - All upfront\n* `CUSTOM` - Custom","enum":["MONTHLY","QUARTERLY","SEMI_ANNUALLY","ANNUALLY","ALL_UPFRONT","CUSTOM"],"x-spec-enum-id":"5f29351b16a5547f","uniqueKey":"oneOf.1.phases.items.[INDEX].billing_frequency","typeLabel":"enum\u003cstring>"},"plan_id":{"oneOf":[{"type":"string","description":"Optional plan for this phase. Each phase may sell a different plan; the phase's bricks are then validated and priced against it. Defaults to the order-level `plan_id`.","format":"uuid","uniqueKey":"oneOf.1.phases.items.[INDEX].plan_id.oneOf.0","typeLabel":"string\u003cuuid>"},{"type":"null","description":"Optional plan for this phase. Each phase may sell a different plan; the phase's bricks are then validated and priced against it. Defaults to the order-level `plan_id`.","format":"uuid","uniqueKey":"oneOf.1.phases.items.[INDEX].plan_id.oneOf.1","typeLabel":"null"}],"uniqueKey":"oneOf.1.phases.items.[INDEX].plan_id","typeLabel":"string\u003cuuid> | null"},"payment_terms":{"type":"integer","description":"Payment terms in days for this phase. Named to match the order-level `payment_terms` input and the phase output — the model field it lands on is `payment_due_upon_receipt`, which is still accepted as a legacy name. Omitted, the phase inherits the order-level value.","maximum":999,"minimum":0,"uniqueKey":"oneOf.1.phases.items.[INDEX].payment_terms","typeLabel":"integer"},"discount_coupons":{"type":"array","items":{"type":"string","uniqueKey":"oneOf.1.phases.items.[INDEX].discount_coupons.items.[INDEX]","typeLabel":"string"},"description":"Discount coupon codes to apply to this phase. Currently only supports one discount coupon - only the first one in the list will be applied.","uniqueKey":"oneOf.1.phases.items.[INDEX].discount_coupons","typeLabel":"string[]"}},"uniqueKey":"oneOf.1.phases.items.[INDEX]","typeLabel":"object"},"description":"Optional list of phases for a multi-phase upgrade. Each phase's ``phase_position`` must match a phase on the base order; only the phases being changed need to be sent, and omitted positions are inherited from the base order unchanged. Order-level bricks and `starts_at` are ignored when phases are provided — the phases own the timeline and the first phase's `starts_at` is the upgrade's effective date.","minItems":1,"isRequired":true,"uniqueKey":"oneOf.1.phases","typeLabel":"object[]"},"crm_opportunity_id":{"type":"string","description":"Optional ID of the opportunity (deal in HubSpot) in your connected CRM to link the subscription to. Requires a linked CRM account, and must not be linked to another subscription. Omit for no change; pass an empty string to unlink it.","maxLength":255,"uniqueKey":"oneOf.1.crm_opportunity_id","typeLabel":"string"},"plan_id":{"type":"string","format":"uuid","description":"Optional plan ID for the upgrade. When provided, the upgrade switches to the latest published version of that plan; when omitted, it keeps the subscription's existing plan version and contracted pricing. Must be sent together with `bricks` — `plan_id` alone is rejected with 400. See the endpoint description for full semantics including cross-plan upgrades and merged plan versions.","uniqueKey":"oneOf.1.plan_id","typeLabel":"string\u003cuuid>"},"starts_at":{"oneOf":[{"type":"string","format":"date","description":"The effective date of the subscription upgrade. Required only when `phases` is omitted: when `phases` is provided the phases own the timeline, so the effective date is taken from the first phase's `starts_at` and this order-level value is ignored.","uniqueKey":"oneOf.1.starts_at.oneOf.0","typeLabel":"string\u003cdate>"},{"type":"null","format":"date","description":"The effective date of the subscription upgrade. Required only when `phases` is omitted: when `phases` is provided the phases own the timeline, so the effective date is taken from the first phase's `starts_at` and this order-level value is ignored.","uniqueKey":"oneOf.1.starts_at.oneOf.1","typeLabel":"null"}],"uniqueKey":"oneOf.1.starts_at","typeLabel":"string\u003cdate> | null"},"discount_coupons":{"type":"array","items":{"type":"string","uniqueKey":"oneOf.1.discount_coupons.items.[INDEX]","typeLabel":"string"},"description":"Discount coupon codes to apply to the subscription upgrade. Currently only supports one discount coupon - only the first one in the list will be applied.","uniqueKey":"oneOf.1.discount_coupons","typeLabel":"string[]"},"custom_order_form_html":{"type":"string","description":"The custom order form html to use with `\u003chtml>\u003cbody>...\u003c/body>\u003c/html>` formatting","uniqueKey":"oneOf.1.custom_order_form_html","typeLabel":"string"},"metadata":{"oneOf":[{"description":"Optional metadata to add to the subscription. Sending an empty map will delete all keys. Keys prefixed with _ are private and will be ignored.","uniqueKey":"oneOf.1.metadata.oneOf.0","typeLabel":"any"},{"description":"Optional metadata to add to the subscription. Sending an empty map will delete all keys. Keys prefixed with _ are private and will be ignored.","type":"null","uniqueKey":"oneOf.1.metadata.oneOf.1","typeLabel":"null"}],"uniqueKey":"oneOf.1.metadata","typeLabel":"any | null"},"downgrade_method":{"oneOf":[{"enum":["CREDIT","REFUND"],"type":"string","x-spec-enum-id":"b3bcc767e244c89a","description":"Method to apply for the downgrade. CREDIT - apply as credit, REFUND - refund the money back. Omitted is treated as CREDIT.\n\n* `CREDIT` - Credit\n* `REFUND` - Refund","uniqueKey":"oneOf.1.downgrade_method.oneOf.0","typeLabel":"enum\u003cstring>"},{"enum":["CREDIT","REFUND"],"type":"null","x-spec-enum-id":"b3bcc767e244c89a","description":"Method to apply for the downgrade. CREDIT - apply as credit, REFUND - refund the money back. Omitted is treated as CREDIT.\n\n* `CREDIT` - Credit\n* `REFUND` - Refund","uniqueKey":"oneOf.1.downgrade_method.oneOf.1","typeLabel":"null"}],"uniqueKey":"oneOf.1.downgrade_method","typeLabel":"enum\u003cstring> | null"}},"uniqueKey":"oneOf.1","typeLabel":"SubscriptionInputUpgradeMultiPhase · object"}],"uniqueKey":"","typeLabel":"SubscriptionInputUpgradeSinglePhase · object | SubscriptionInputUpgradeMultiPhase · object"},"examples":{"Example":{"title":"Example","value":{"starts_at":"2023-12-25","bricks":[{"brick_id":"3c90c3cc-0d44-4b50-8888-8dd25736052a","quantity":123,"is_unlimited":true,"discount":[{"rate":"\u003cstring>","amount":123,"renews":false}]}],"crm_opportunity_id":"\u003cstring>","plan_id":"3c90c3cc-0d44-4b50-8888-8dd25736052a","discount_coupons":["\u003cstring>"],"phases":[{"phase_position":1,"bricks":[{"brick_id":"3c90c3cc-0d44-4b50-8888-8dd25736052a","quantity":123,"is_unlimited":true,"discount":[{"rate":"\u003cstring>","amount":123,"renews":false}]}],"starts_at":"2023-12-25","contract_length":2,"plan_id":"3c90c3cc-0d44-4b50-8888-8dd25736052a","payment_terms":499,"discount_coupons":["\u003cstring>"]}],"custom_order_form_html":"\u003cstring>","metadata":"\u003cunknown>"}}},"exampleType":"generated"},"multipart/form-data":{"schema":{"oneOf":[{"type":"object","title":"SubscriptionInputUpgradeSinglePhase","description":"Subscription upgrade input serializer for upgrading a subscription order.\n\nThis payload has two forms — see `anyOf`:\n\n* **Single-phase** — omit `phases`; the order-level `starts_at`, `contract_length`, `billing_frequency` and `bricks` define the one phase and are required.\n* **Multi-phase** — send `phases`; the phases own the timeline, billing frequency and bricks, and the order-level equivalents become optional (omitted, they are derived from the phases).\n\nThe fields are declared optional because OpenAPI 3.0 cannot make one field's `required` depend on another. Sending neither form is a 400.","required":["starts_at","bricks"],"properties":{"starts_at":{"type":"string","description":"The effective date of the subscription upgrade. Required only when `phases` is omitted: when `phases` is provided the phases own the timeline, so the effective date is taken from the first phase's `starts_at` and this order-level value is ignored.","format":"date","isRequired":true,"uniqueKey":"oneOf.0.starts_at","typeLabel":"string\u003cdate>"},"bricks":{"type":"array","items":{"type":"object","description":"Line item input serializer for creating a new estimate","properties":{"brick_id":{"type":"string","format":"uuid","description":"The ID of the brick to add to the subscription","isRequired":true,"uniqueKey":"oneOf.0.bricks.items.[INDEX].brick_id","typeLabel":"string\u003cuuid>"},"quantity":{"type":"integer","description":"The quantity of the brick, used as the basis for its price","uniqueKey":"oneOf.0.bricks.items.[INDEX].quantity","typeLabel":"integer"},"is_unlimited":{"type":"boolean","description":"Sell this line with an uncapped entitlement, keeping `quantity` as the pricing basis its price is calculated from. Optional: omitting it on create leaves the line limited, and omitting it on update leaves the line's current value alone — send it explicitly as false to clear it. Subscription bricks only.","uniqueKey":"oneOf.0.bricks.items.[INDEX].is_unlimited","typeLabel":"boolean"},"discount":{"oneOf":[{"type":"array","items":{"type":"object","description":"Discount serializer for a subscription estimate line item","properties":{"rate":{"type":"string","format":"decimal","pattern":"^-?\\d{0,14}(?:\\.\\d{0,6})?$","description":"The discount rate as a percentage with up to six decimal places (e.g. 10 = 10%, 62.6758 = 62.6758%). Mutually exclusive with `amount`.","uniqueKey":"oneOf.0.bricks.items.[INDEX].discount.oneOf.0.items.[INDEX].rate","typeLabel":"string\u003cdecimal>"},"amount":{"type":"integer","description":"A fixed discount amount in cents (e.g. 1000 = $10.00). One-time only — `renews` must be false when `amount` is set. Mutually exclusive with `rate`. The amount is applied as-is and is not clamped to the line item total, so it should not exceed the brick's price.","uniqueKey":"oneOf.0.bricks.items.[INDEX].discount.oneOf.0.items.[INDEX].amount","typeLabel":"integer"},"renews":{"type":"boolean","default":false,"description":"If the discount is carried over at renewal. Must be false when `amount` is set, as fixed discounts are one-time only.","uniqueKey":"oneOf.0.bricks.items.[INDEX].discount.oneOf.0.items.[INDEX].renews","typeLabel":"boolean"}},"uniqueKey":"oneOf.0.bricks.items.[INDEX].discount.oneOf.0.items.[INDEX]","typeLabel":"object"},"description":"A list of discounts to apply to the line item — at most one renewing rate, one one-time rate, and one fixed amount. Discounts are replaced, not merged: what is sent here becomes the line item's complete set of discounts. Omitting this field for a brick that currently has a discount drops that discount. Read the current values from the subscription's line items, which return `discount` in this same shape, and send them back for every brick whose discount should carry over.","uniqueKey":"oneOf.0.bricks.items.[INDEX].discount.oneOf.0","typeLabel":"object[]"},{"type":"null","items":{"type":"object","description":"Discount serializer for a subscription estimate line item","properties":{"rate":{"type":"string","format":"decimal","pattern":"^-?\\d{0,14}(?:\\.\\d{0,6})?$","description":"The discount rate as a percentage with up to six decimal places (e.g. 10 = 10%, 62.6758 = 62.6758%). Mutually exclusive with `amount`."},"amount":{"type":"integer","description":"A fixed discount amount in cents (e.g. 1000 = $10.00). One-time only — `renews` must be false when `amount` is set. Mutually exclusive with `rate`. The amount is applied as-is and is not clamped to the line item total, so it should not exceed the brick's price."},"renews":{"type":"boolean","default":false,"description":"If the discount is carried over at renewal. Must be false when `amount` is set, as fixed discounts are one-time only."}}},"description":"A list of discounts to apply to the line item — at most one renewing rate, one one-time rate, and one fixed amount. Discounts are replaced, not merged: what is sent here becomes the line item's complete set of discounts. Omitting this field for a brick that currently has a discount drops that discount. Read the current values from the subscription's line items, which return `discount` in this same shape, and send them back for every brick whose discount should carry over.","uniqueKey":"oneOf.0.bricks.items.[INDEX].discount.oneOf.1","typeLabel":"null"}],"uniqueKey":"oneOf.0.bricks.items.[INDEX].discount","typeLabel":"object[] | null"}},"required":["brick_id"],"uniqueKey":"oneOf.0.bricks.items.[INDEX]","typeLabel":"object"},"description":"The bricks included in subscription upgrade. Quantity is used to upgrade the add-on quantity (ie. adding 2 more units should be quantity 2 -> quantity 4). For usage, quantity is used to set the pre-commitment (ie. previously having 5 pre-commitment quantity and updating it to 10 would update the pre-commitment quantity to 10.)","isRequired":true,"uniqueKey":"oneOf.0.bricks","typeLabel":"object[]"},"crm_opportunity_id":{"type":"string","description":"Optional ID of the opportunity (deal in HubSpot) in your connected CRM to link the subscription to. Requires a linked CRM account, and must not be linked to another subscription. Omit for no change; pass an empty string to unlink it.","maxLength":255,"uniqueKey":"oneOf.0.crm_opportunity_id","typeLabel":"string"},"plan_id":{"type":"string","format":"uuid","description":"Optional plan ID for the upgrade. When provided, the upgrade switches to the latest published version of that plan; when omitted, it keeps the subscription's existing plan version and contracted pricing. Must be sent together with `bricks` — `plan_id` alone is rejected with 400. See the endpoint description for full semantics including cross-plan upgrades and merged plan versions.","uniqueKey":"oneOf.0.plan_id","typeLabel":"string\u003cuuid>"},"discount_coupons":{"type":"array","items":{"type":"string","uniqueKey":"oneOf.0.discount_coupons.items.[INDEX]","typeLabel":"string"},"description":"Discount coupon codes to apply to the subscription upgrade. Currently only supports one discount coupon - only the first one in the list will be applied.","uniqueKey":"oneOf.0.discount_coupons","typeLabel":"string[]"},"phases":{"oneOf":[{"type":"array","items":{"type":"object","description":"Input serializer for a single order phase in multi-phase operations.\n\n``phase_position`` is required on every phase. For creation, recast and\nestimate the array is the complete phase set, so positions must be the full\n0-based sequence (position N at index N). For upgrades only the phases being\nchanged are sent, so positions are a subset of the base order's phase\npositions.\n\n``starts_at`` is optional — phase 0 defaults to the order-level starts_at,\nand subsequent phases are derived from the previous phase's end date.\n\n``contract_length`` replaces the old ``ends_at`` field. Required for\ncreate/estimate/recast; not needed for upgrades (end date inherited from\nthe base order). The phase *output* reports ``ends_at`` rather than\n``contract_length``, so a read-modify-write of a phase has to convert:\n``contract_length`` is the number of whole months from ``starts_at`` to the\nday after ``ends_at``. Phases are contiguous and whole-month, so the\nconversion is exact.\n\n``billing_frequency`` follows the same rule: required for\ncreate/estimate/recast, where phases own the billing frequency outright,\nand inherited from the base order's phase on upgrades.\n\n``plan_id`` is optional and lets a phase sell a different plan from the\norder's, matching what the order builder already supports (SAL-6327).\nOmitted, the phase uses the order-level ``plan_id``.","properties":{"phase_position":{"type":"integer","minimum":0,"description":"Phase position (0-based). Must be unique across phases.","isRequired":true,"uniqueKey":"oneOf.0.phases.oneOf.0.items.[INDEX].phase_position","typeLabel":"integer"},"bricks":{"type":"array","items":{"type":"object","description":"Line item input serializer for creating a new estimate","properties":{"brick_id":{"type":"string","format":"uuid","description":"The ID of the brick to add to the subscription","isRequired":true,"uniqueKey":"oneOf.0.phases.oneOf.0.items.[INDEX].bricks.items.[INDEX].brick_id","typeLabel":"string\u003cuuid>"},"quantity":{"type":"integer","description":"The quantity of the brick, used as the basis for its price","uniqueKey":"oneOf.0.phases.oneOf.0.items.[INDEX].bricks.items.[INDEX].quantity","typeLabel":"integer"},"is_unlimited":{"type":"boolean","description":"Sell this line with an uncapped entitlement, keeping `quantity` as the pricing basis its price is calculated from. Optional: omitting it on create leaves the line limited, and omitting it on update leaves the line's current value alone — send it explicitly as false to clear it. Subscription bricks only.","uniqueKey":"oneOf.0.phases.oneOf.0.items.[INDEX].bricks.items.[INDEX].is_unlimited","typeLabel":"boolean"},"discount":{"oneOf":[{"type":"array","items":{"type":"object","description":"Discount serializer for a subscription estimate line item","properties":{"rate":{"type":"string","format":"decimal","pattern":"^-?\\d{0,14}(?:\\.\\d{0,6})?$","description":"The discount rate as a percentage with up to six decimal places (e.g. 10 = 10%, 62.6758 = 62.6758%). Mutually exclusive with `amount`.","uniqueKey":"oneOf.0.phases.oneOf.0.items.[INDEX].bricks.items.[INDEX].discount.oneOf.0.items.[INDEX].rate","typeLabel":"string\u003cdecimal>"},"amount":{"type":"integer","description":"A fixed discount amount in cents (e.g. 1000 = $10.00). One-time only — `renews` must be false when `amount` is set. Mutually exclusive with `rate`. The amount is applied as-is and is not clamped to the line item total, so it should not exceed the brick's price.","uniqueKey":"oneOf.0.phases.oneOf.0.items.[INDEX].bricks.items.[INDEX].discount.oneOf.0.items.[INDEX].amount","typeLabel":"integer"},"renews":{"type":"boolean","default":false,"description":"If the discount is carried over at renewal. Must be false when `amount` is set, as fixed discounts are one-time only.","uniqueKey":"oneOf.0.phases.oneOf.0.items.[INDEX].bricks.items.[INDEX].discount.oneOf.0.items.[INDEX].renews","typeLabel":"boolean"}},"uniqueKey":"oneOf.0.phases.oneOf.0.items.[INDEX].bricks.items.[INDEX].discount.oneOf.0.items.[INDEX]","typeLabel":"object"},"description":"A list of discounts to apply to the line item — at most one renewing rate, one one-time rate, and one fixed amount. Discounts are replaced, not merged: what is sent here becomes the line item's complete set of discounts. Omitting this field for a brick that currently has a discount drops that discount. Read the current values from the subscription's line items, which return `discount` in this same shape, and send them back for every brick whose discount should carry over.","uniqueKey":"oneOf.0.phases.oneOf.0.items.[INDEX].bricks.items.[INDEX].discount.oneOf.0","typeLabel":"object[]"},{"type":"null","items":{"type":"object","description":"Discount serializer for a subscription estimate line item","properties":{"rate":{"type":"string","format":"decimal","pattern":"^-?\\d{0,14}(?:\\.\\d{0,6})?$","description":"The discount rate as a percentage with up to six decimal places (e.g. 10 = 10%, 62.6758 = 62.6758%). Mutually exclusive with `amount`."},"amount":{"type":"integer","description":"A fixed discount amount in cents (e.g. 1000 = $10.00). One-time only — `renews` must be false when `amount` is set. Mutually exclusive with `rate`. The amount is applied as-is and is not clamped to the line item total, so it should not exceed the brick's price."},"renews":{"type":"boolean","default":false,"description":"If the discount is carried over at renewal. Must be false when `amount` is set, as fixed discounts are one-time only."}}},"description":"A list of discounts to apply to the line item — at most one renewing rate, one one-time rate, and one fixed amount. Discounts are replaced, not merged: what is sent here becomes the line item's complete set of discounts. Omitting this field for a brick that currently has a discount drops that discount. Read the current values from the subscription's line items, which return `discount` in this same shape, and send them back for every brick whose discount should carry over.","uniqueKey":"oneOf.0.phases.oneOf.0.items.[INDEX].bricks.items.[INDEX].discount.oneOf.1","typeLabel":"null"}],"uniqueKey":"oneOf.0.phases.oneOf.0.items.[INDEX].bricks.items.[INDEX].discount","typeLabel":"object[] | null"}},"required":["brick_id"],"uniqueKey":"oneOf.0.phases.oneOf.0.items.[INDEX].bricks.items.[INDEX]","typeLabel":"object"},"description":"The bricks included in this phase.","isRequired":true,"uniqueKey":"oneOf.0.phases.oneOf.0.items.[INDEX].bricks","typeLabel":"object[]"},"starts_at":{"oneOf":[{"type":"string","format":"date","description":"Start date of this phase. Optional — phase 0 defaults to order-level starts_at; subsequent phases are derived from the previous phase's end date + 1 day.","uniqueKey":"oneOf.0.phases.oneOf.0.items.[INDEX].starts_at.oneOf.0","typeLabel":"string\u003cdate>"},{"type":"null","format":"date","description":"Start date of this phase. Optional — phase 0 defaults to order-level starts_at; subsequent phases are derived from the previous phase's end date + 1 day.","uniqueKey":"oneOf.0.phases.oneOf.0.items.[INDEX].starts_at.oneOf.1","typeLabel":"null"}],"uniqueKey":"oneOf.0.phases.oneOf.0.items.[INDEX].starts_at","typeLabel":"string\u003cdate> | null"},"contract_length":{"oneOf":[{"type":"integer","minimum":1,"description":"Duration of this phase in months. Required for create, estimate, and recast. Not required for upgrades (end date inherited from the base order).","uniqueKey":"oneOf.0.phases.oneOf.0.items.[INDEX].contract_length.oneOf.0","typeLabel":"integer"},{"type":"null","minimum":1,"description":"Duration of this phase in months. Required for create, estimate, and recast. Not required for upgrades (end date inherited from the base order).","uniqueKey":"oneOf.0.phases.oneOf.0.items.[INDEX].contract_length.oneOf.1","typeLabel":"null"}],"uniqueKey":"oneOf.0.phases.oneOf.0.items.[INDEX].contract_length","typeLabel":"integer | null"},"billing_frequency":{"enum":["MONTHLY","QUARTERLY","SEMI_ANNUALLY","ANNUALLY","ALL_UPFRONT","CUSTOM"],"type":"string","x-spec-enum-id":"5f29351b16a5547f","description":"Billing frequency for this phase. Required for create, estimate and recast — when phases are provided they own the billing frequency outright, so the order-level billing_frequency is not consulted. Not required for upgrades (inherited from the base order's phase). The legacy name `billing_schedule` is still accepted.\n\n* `MONTHLY` - Monthly\n* `QUARTERLY` - Quarterly\n* `SEMI_ANNUALLY` - Semi-annually\n* `ANNUALLY` - Annually\n* `ALL_UPFRONT` - All upfront\n* `CUSTOM` - Custom","uniqueKey":"oneOf.0.phases.oneOf.0.items.[INDEX].billing_frequency","typeLabel":"enum\u003cstring>"},"plan_id":{"oneOf":[{"type":"string","format":"uuid","description":"Optional plan for this phase. Each phase may sell a different plan; the phase's bricks are then validated and priced against it. Defaults to the order-level `plan_id`.","uniqueKey":"oneOf.0.phases.oneOf.0.items.[INDEX].plan_id.oneOf.0","typeLabel":"string\u003cuuid>"},{"type":"null","format":"uuid","description":"Optional plan for this phase. Each phase may sell a different plan; the phase's bricks are then validated and priced against it. Defaults to the order-level `plan_id`.","uniqueKey":"oneOf.0.phases.oneOf.0.items.[INDEX].plan_id.oneOf.1","typeLabel":"null"}],"uniqueKey":"oneOf.0.phases.oneOf.0.items.[INDEX].plan_id","typeLabel":"string\u003cuuid> | null"},"payment_terms":{"type":"integer","maximum":999,"minimum":0,"description":"Payment terms in days for this phase. Named to match the order-level `payment_terms` input and the phase output — the model field it lands on is `payment_due_upon_receipt`, which is still accepted as a legacy name. Omitted, the phase inherits the order-level value.","uniqueKey":"oneOf.0.phases.oneOf.0.items.[INDEX].payment_terms","typeLabel":"integer"},"discount_coupons":{"type":"array","items":{"type":"string","uniqueKey":"oneOf.0.phases.oneOf.0.items.[INDEX].discount_coupons.items.[INDEX]","typeLabel":"string"},"description":"Discount coupon codes to apply to this phase. Currently only supports one discount coupon - only the first one in the list will be applied.","uniqueKey":"oneOf.0.phases.oneOf.0.items.[INDEX].discount_coupons","typeLabel":"string[]"}},"required":["bricks","phase_position"],"uniqueKey":"oneOf.0.phases.oneOf.0.items.[INDEX]","typeLabel":"object"},"description":"Optional list of phases for a multi-phase upgrade. Each phase's ``phase_position`` must match a phase on the base order; only the phases being changed need to be sent, and omitted positions are inherited from the base order unchanged. Order-level bricks and `starts_at` are ignored when phases are provided — the phases own the timeline and the first phase's `starts_at` is the upgrade's effective date.","uniqueKey":"oneOf.0.phases.oneOf.0","typeLabel":"object[]"},{"type":"null","items":{"type":"object","description":"Input serializer for a single order phase in multi-phase operations.\n\n``phase_position`` is required on every phase. For creation, recast and\nestimate the array is the complete phase set, so positions must be the full\n0-based sequence (position N at index N). For upgrades only the phases being\nchanged are sent, so positions are a subset of the base order's phase\npositions.\n\n``starts_at`` is optional — phase 0 defaults to the order-level starts_at,\nand subsequent phases are derived from the previous phase's end date.\n\n``contract_length`` replaces the old ``ends_at`` field. Required for\ncreate/estimate/recast; not needed for upgrades (end date inherited from\nthe base order). The phase *output* reports ``ends_at`` rather than\n``contract_length``, so a read-modify-write of a phase has to convert:\n``contract_length`` is the number of whole months from ``starts_at`` to the\nday after ``ends_at``. Phases are contiguous and whole-month, so the\nconversion is exact.\n\n``billing_frequency`` follows the same rule: required for\ncreate/estimate/recast, where phases own the billing frequency outright,\nand inherited from the base order's phase on upgrades.\n\n``plan_id`` is optional and lets a phase sell a different plan from the\norder's, matching what the order builder already supports (SAL-6327).\nOmitted, the phase uses the order-level ``plan_id``.","properties":{"phase_position":{"type":"integer","minimum":0,"description":"Phase position (0-based). Must be unique across phases."},"starts_at":{"oneOf":[{"type":"string","format":"date","description":"Start date of this phase. Optional — phase 0 defaults to order-level starts_at; subsequent phases are derived from the previous phase's end date + 1 day."},{"type":"null","format":"date","description":"Start date of this phase. Optional — phase 0 defaults to order-level starts_at; subsequent phases are derived from the previous phase's end date + 1 day."}]},"contract_length":{"oneOf":[{"type":"integer","minimum":1,"description":"Duration of this phase in months. Required for create, estimate, and recast. Not required for upgrades (end date inherited from the base order)."},{"type":"null","minimum":1,"description":"Duration of this phase in months. Required for create, estimate, and recast. Not required for upgrades (end date inherited from the base order)."}]},"billing_frequency":{"enum":["MONTHLY","QUARTERLY","SEMI_ANNUALLY","ANNUALLY","ALL_UPFRONT","CUSTOM"],"type":"string","x-spec-enum-id":"5f29351b16a5547f","description":"Billing frequency for this phase. Required for create, estimate and recast — when phases are provided they own the billing frequency outright, so the order-level billing_frequency is not consulted. Not required for upgrades (inherited from the base order's phase). The legacy name `billing_schedule` is still accepted.\n\n* `MONTHLY` - Monthly\n* `QUARTERLY` - Quarterly\n* `SEMI_ANNUALLY` - Semi-annually\n* `ANNUALLY` - Annually\n* `ALL_UPFRONT` - All upfront\n* `CUSTOM` - Custom"},"plan_id":{"oneOf":[{"type":"string","format":"uuid","description":"Optional plan for this phase. Each phase may sell a different plan; the phase's bricks are then validated and priced against it. Defaults to the order-level `plan_id`."},{"type":"null","format":"uuid","description":"Optional plan for this phase. Each phase may sell a different plan; the phase's bricks are then validated and priced against it. Defaults to the order-level `plan_id`."}]},"payment_terms":{"type":"integer","maximum":999,"minimum":0,"description":"Payment terms in days for this phase. Named to match the order-level `payment_terms` input and the phase output — the model field it lands on is `payment_due_upon_receipt`, which is still accepted as a legacy name. Omitted, the phase inherits the order-level value."},"bricks":{"type":"array","items":{"type":"object","description":"Line item input serializer for creating a new estimate","properties":{"brick_id":{"type":"string","format":"uuid","description":"The ID of the brick to add to the subscription"},"quantity":{"type":"integer","description":"The quantity of the brick, used as the basis for its price"},"is_unlimited":{"type":"boolean","description":"Sell this line with an uncapped entitlement, keeping `quantity` as the pricing basis its price is calculated from. Optional: omitting it on create leaves the line limited, and omitting it on update leaves the line's current value alone — send it explicitly as false to clear it. Subscription bricks only."},"discount":{"oneOf":[{"type":"array","items":{"type":"object","description":"Discount serializer for a subscription estimate line item","properties":{"rate":{"type":"string","format":"decimal","pattern":"^-?\\d{0,14}(?:\\.\\d{0,6})?$","description":"The discount rate as a percentage with up to six decimal places (e.g. 10 = 10%, 62.6758 = 62.6758%). Mutually exclusive with `amount`."},"amount":{"type":"integer","description":"A fixed discount amount in cents (e.g. 1000 = $10.00). One-time only — `renews` must be false when `amount` is set. Mutually exclusive with `rate`. The amount is applied as-is and is not clamped to the line item total, so it should not exceed the brick's price."},"renews":{"type":"boolean","default":false,"description":"If the discount is carried over at renewal. Must be false when `amount` is set, as fixed discounts are one-time only."}}},"description":"A list of discounts to apply to the line item — at most one renewing rate, one one-time rate, and one fixed amount. Discounts are replaced, not merged: what is sent here becomes the line item's complete set of discounts. Omitting this field for a brick that currently has a discount drops that discount. Read the current values from the subscription's line items, which return `discount` in this same shape, and send them back for every brick whose discount should carry over."},{"type":"null","items":{"type":"object","description":"Discount serializer for a subscription estimate line item","properties":{"rate":{"type":"string","format":"decimal","pattern":"^-?\\d{0,14}(?:\\.\\d{0,6})?$","description":"The discount rate as a percentage with up to six decimal places (e.g. 10 = 10%, 62.6758 = 62.6758%). Mutually exclusive with `amount`."},"amount":{"type":"integer","description":"A fixed discount amount in cents (e.g. 1000 = $10.00). One-time only — `renews` must be false when `amount` is set. Mutually exclusive with `rate`. The amount is applied as-is and is not clamped to the line item total, so it should not exceed the brick's price."},"renews":{"type":"boolean","default":false,"description":"If the discount is carried over at renewal. Must be false when `amount` is set, as fixed discounts are one-time only."}}},"description":"A list of discounts to apply to the line item — at most one renewing rate, one one-time rate, and one fixed amount. Discounts are replaced, not merged: what is sent here becomes the line item's complete set of discounts. Omitting this field for a brick that currently has a discount drops that discount. Read the current values from the subscription's line items, which return `discount` in this same shape, and send them back for every brick whose discount should carry over."}]}},"required":["brick_id"]},"description":"The bricks included in this phase."},"discount_coupons":{"type":"array","items":{"type":"string"},"description":"Discount coupon codes to apply to this phase. Currently only supports one discount coupon - only the first one in the list will be applied."}},"required":["bricks","phase_position"]},"description":"Optional list of phases for a multi-phase upgrade. Each phase's ``phase_position`` must match a phase on the base order; only the phases being changed need to be sent, and omitted positions are inherited from the base order unchanged. Order-level bricks and `starts_at` are ignored when phases are provided — the phases own the timeline and the first phase's `starts_at` is the upgrade's effective date.","uniqueKey":"oneOf.0.phases.oneOf.1","typeLabel":"null"}],"uniqueKey":"oneOf.0.phases","typeLabel":"object[] | null"},"custom_order_form_html":{"type":"string","description":"The custom order form html to use with `\u003chtml>\u003cbody>...\u003c/body>\u003c/html>` formatting","uniqueKey":"oneOf.0.custom_order_form_html","typeLabel":"string"},"metadata":{"oneOf":[{"description":"Optional metadata to add to the subscription. Sending an empty map will delete all keys. Keys prefixed with _ are private and will be ignored.","uniqueKey":"oneOf.0.metadata.oneOf.0","typeLabel":"any"},{"description":"Optional metadata to add to the subscription. Sending an empty map will delete all keys. Keys prefixed with _ are private and will be ignored.","type":"null","uniqueKey":"oneOf.0.metadata.oneOf.1","typeLabel":"null"}],"uniqueKey":"oneOf.0.metadata","typeLabel":"any | null"},"downgrade_method":{"oneOf":[{"enum":["CREDIT","REFUND"],"type":"string","x-spec-enum-id":"b3bcc767e244c89a","description":"Method to apply for the downgrade. CREDIT - apply as credit, REFUND - refund the money back. Omitted is treated as CREDIT.\n\n* `CREDIT` - Credit\n* `REFUND` - Refund","uniqueKey":"oneOf.0.downgrade_method.oneOf.0","typeLabel":"enum\u003cstring>"},{"enum":["CREDIT","REFUND"],"type":"null","x-spec-enum-id":"b3bcc767e244c89a","description":"Method to apply for the downgrade. CREDIT - apply as credit, REFUND - refund the money back. Omitted is treated as CREDIT.\n\n* `CREDIT` - Credit\n* `REFUND` - Refund","uniqueKey":"oneOf.0.downgrade_method.oneOf.1","typeLabel":"null"}],"uniqueKey":"oneOf.0.downgrade_method","typeLabel":"enum\u003cstring> | null"}},"uniqueKey":"oneOf.0","typeLabel":"SubscriptionInputUpgradeSinglePhase · object"},{"type":"object","title":"SubscriptionInputUpgradeMultiPhase","description":"Subscription upgrade input serializer for upgrading a subscription order.\n\nThis payload has two forms — see `anyOf`:\n\n* **Single-phase** — omit `phases`; the order-level `starts_at`, `contract_length`, `billing_frequency` and `bricks` define the one phase and are required.\n* **Multi-phase** — send `phases`; the phases own the timeline, billing frequency and bricks, and the order-level equivalents become optional (omitted, they are derived from the phases).\n\nThe fields are declared optional because OpenAPI 3.0 cannot make one field's `required` depend on another. Sending neither form is a 400.","required":["phases","bricks"],"properties":{"bricks":{"type":"array","items":{"type":"object","description":"Line item input serializer for creating a new estimate","properties":{"brick_id":{"type":"string","format":"uuid","description":"The ID of the brick to add to the subscription","isRequired":true,"uniqueKey":"oneOf.1.bricks.items.[INDEX].brick_id","typeLabel":"string\u003cuuid>"},"quantity":{"type":"integer","description":"The quantity of the brick, used as the basis for its price","uniqueKey":"oneOf.1.bricks.items.[INDEX].quantity","typeLabel":"integer"},"is_unlimited":{"type":"boolean","description":"Sell this line with an uncapped entitlement, keeping `quantity` as the pricing basis its price is calculated from. Optional: omitting it on create leaves the line limited, and omitting it on update leaves the line's current value alone — send it explicitly as false to clear it. Subscription bricks only.","uniqueKey":"oneOf.1.bricks.items.[INDEX].is_unlimited","typeLabel":"boolean"},"discount":{"oneOf":[{"type":"array","items":{"type":"object","description":"Discount serializer for a subscription estimate line item","properties":{"rate":{"type":"string","format":"decimal","pattern":"^-?\\d{0,14}(?:\\.\\d{0,6})?$","description":"The discount rate as a percentage with up to six decimal places (e.g. 10 = 10%, 62.6758 = 62.6758%). Mutually exclusive with `amount`.","uniqueKey":"oneOf.1.bricks.items.[INDEX].discount.oneOf.0.items.[INDEX].rate","typeLabel":"string\u003cdecimal>"},"amount":{"type":"integer","description":"A fixed discount amount in cents (e.g. 1000 = $10.00). One-time only — `renews` must be false when `amount` is set. Mutually exclusive with `rate`. The amount is applied as-is and is not clamped to the line item total, so it should not exceed the brick's price.","uniqueKey":"oneOf.1.bricks.items.[INDEX].discount.oneOf.0.items.[INDEX].amount","typeLabel":"integer"},"renews":{"type":"boolean","default":false,"description":"If the discount is carried over at renewal. Must be false when `amount` is set, as fixed discounts are one-time only.","uniqueKey":"oneOf.1.bricks.items.[INDEX].discount.oneOf.0.items.[INDEX].renews","typeLabel":"boolean"}},"uniqueKey":"oneOf.1.bricks.items.[INDEX].discount.oneOf.0.items.[INDEX]","typeLabel":"object"},"description":"A list of discounts to apply to the line item — at most one renewing rate, one one-time rate, and one fixed amount. Discounts are replaced, not merged: what is sent here becomes the line item's complete set of discounts. Omitting this field for a brick that currently has a discount drops that discount. Read the current values from the subscription's line items, which return `discount` in this same shape, and send them back for every brick whose discount should carry over.","uniqueKey":"oneOf.1.bricks.items.[INDEX].discount.oneOf.0","typeLabel":"object[]"},{"type":"null","items":{"type":"object","description":"Discount serializer for a subscription estimate line item","properties":{"rate":{"type":"string","format":"decimal","pattern":"^-?\\d{0,14}(?:\\.\\d{0,6})?$","description":"The discount rate as a percentage with up to six decimal places (e.g. 10 = 10%, 62.6758 = 62.6758%). Mutually exclusive with `amount`."},"amount":{"type":"integer","description":"A fixed discount amount in cents (e.g. 1000 = $10.00). One-time only — `renews` must be false when `amount` is set. Mutually exclusive with `rate`. The amount is applied as-is and is not clamped to the line item total, so it should not exceed the brick's price."},"renews":{"type":"boolean","default":false,"description":"If the discount is carried over at renewal. Must be false when `amount` is set, as fixed discounts are one-time only."}}},"description":"A list of discounts to apply to the line item — at most one renewing rate, one one-time rate, and one fixed amount. Discounts are replaced, not merged: what is sent here becomes the line item's complete set of discounts. Omitting this field for a brick that currently has a discount drops that discount. Read the current values from the subscription's line items, which return `discount` in this same shape, and send them back for every brick whose discount should carry over.","uniqueKey":"oneOf.1.bricks.items.[INDEX].discount.oneOf.1","typeLabel":"null"}],"uniqueKey":"oneOf.1.bricks.items.[INDEX].discount","typeLabel":"object[] | null"}},"required":["brick_id"],"uniqueKey":"oneOf.1.bricks.items.[INDEX]","typeLabel":"object"},"description":"The bricks included in subscription upgrade. Quantity is used to upgrade the add-on quantity (ie. adding 2 more units should be quantity 2 -> quantity 4). For usage, quantity is used to set the pre-commitment (ie. previously having 5 pre-commitment quantity and updating it to 10 would update the pre-commitment quantity to 10.)","isRequired":true,"uniqueKey":"oneOf.1.bricks","typeLabel":"object[]"},"phases":{"type":"array","items":{"type":"object","description":"Input serializer for a single order phase in multi-phase operations.\n\n``phase_position`` is required on every phase. For creation, recast and\nestimate the array is the complete phase set, so positions must be the full\n0-based sequence (position N at index N). For upgrades only the phases being\nchanged are sent, so positions are a subset of the base order's phase\npositions.\n\n``starts_at`` is optional — phase 0 defaults to the order-level starts_at,\nand subsequent phases are derived from the previous phase's end date.\n\n``contract_length`` replaces the old ``ends_at`` field. Required for\ncreate/estimate/recast; not needed for upgrades (end date inherited from\nthe base order). The phase *output* reports ``ends_at`` rather than\n``contract_length``, so a read-modify-write of a phase has to convert:\n``contract_length`` is the number of whole months from ``starts_at`` to the\nday after ``ends_at``. Phases are contiguous and whole-month, so the\nconversion is exact.\n\n``billing_frequency`` follows the same rule: required for\ncreate/estimate/recast, where phases own the billing frequency outright,\nand inherited from the base order's phase on upgrades.\n\n``plan_id`` is optional and lets a phase sell a different plan from the\norder's, matching what the order builder already supports (SAL-6327).\nOmitted, the phase uses the order-level ``plan_id``.","required":["bricks","phase_position"],"properties":{"phase_position":{"type":"integer","description":"Phase position (0-based). Must be unique across phases.","minimum":0,"isRequired":true,"uniqueKey":"oneOf.1.phases.items.[INDEX].phase_position","typeLabel":"integer"},"bricks":{"type":"array","items":{"type":"object","description":"Line item input serializer for creating a new estimate","required":["brick_id"],"properties":{"brick_id":{"type":"string","description":"The ID of the brick to add to the subscription","format":"uuid","isRequired":true,"uniqueKey":"oneOf.1.phases.items.[INDEX].bricks.items.[INDEX].brick_id","typeLabel":"string\u003cuuid>"},"quantity":{"type":"integer","description":"The quantity of the brick, used as the basis for its price","uniqueKey":"oneOf.1.phases.items.[INDEX].bricks.items.[INDEX].quantity","typeLabel":"integer"},"is_unlimited":{"type":"boolean","description":"Sell this line with an uncapped entitlement, keeping `quantity` as the pricing basis its price is calculated from. Optional: omitting it on create leaves the line limited, and omitting it on update leaves the line's current value alone — send it explicitly as false to clear it. Subscription bricks only.","uniqueKey":"oneOf.1.phases.items.[INDEX].bricks.items.[INDEX].is_unlimited","typeLabel":"boolean"},"discount":{"oneOf":[{"type":"array","items":{"type":"object","description":"Discount serializer for a subscription estimate line item","properties":{"rate":{"type":"string","description":"The discount rate as a percentage with up to six decimal places (e.g. 10 = 10%, 62.6758 = 62.6758%). Mutually exclusive with `amount`.","format":"decimal","pattern":"^-?\\d{0,14}(?:\\.\\d{0,6})?$","uniqueKey":"oneOf.1.phases.items.[INDEX].bricks.items.[INDEX].discount.oneOf.0.items.[INDEX].rate","typeLabel":"string\u003cdecimal>"},"amount":{"type":"integer","description":"A fixed discount amount in cents (e.g. 1000 = $10.00). One-time only — `renews` must be false when `amount` is set. Mutually exclusive with `rate`. The amount is applied as-is and is not clamped to the line item total, so it should not exceed the brick's price.","uniqueKey":"oneOf.1.phases.items.[INDEX].bricks.items.[INDEX].discount.oneOf.0.items.[INDEX].amount","typeLabel":"integer"},"renews":{"type":"boolean","description":"If the discount is carried over at renewal. Must be false when `amount` is set, as fixed discounts are one-time only.","default":false,"uniqueKey":"oneOf.1.phases.items.[INDEX].bricks.items.[INDEX].discount.oneOf.0.items.[INDEX].renews","typeLabel":"boolean"}},"uniqueKey":"oneOf.1.phases.items.[INDEX].bricks.items.[INDEX].discount.oneOf.0.items.[INDEX]","typeLabel":"object"},"description":"A list of discounts to apply to the line item — at most one renewing rate, one one-time rate, and one fixed amount. Discounts are replaced, not merged: what is sent here becomes the line item's complete set of discounts. Omitting this field for a brick that currently has a discount drops that discount. Read the current values from the subscription's line items, which return `discount` in this same shape, and send them back for every brick whose discount should carry over.","uniqueKey":"oneOf.1.phases.items.[INDEX].bricks.items.[INDEX].discount.oneOf.0","typeLabel":"object[]"},{"type":"null","description":"A list of discounts to apply to the line item — at most one renewing rate, one one-time rate, and one fixed amount. Discounts are replaced, not merged: what is sent here becomes the line item's complete set of discounts. Omitting this field for a brick that currently has a discount drops that discount. Read the current values from the subscription's line items, which return `discount` in this same shape, and send them back for every brick whose discount should carry over.","uniqueKey":"oneOf.1.phases.items.[INDEX].bricks.items.[INDEX].discount.oneOf.1","typeLabel":"null"}],"uniqueKey":"oneOf.1.phases.items.[INDEX].bricks.items.[INDEX].discount","typeLabel":"object[] | null"}},"uniqueKey":"oneOf.1.phases.items.[INDEX].bricks.items.[INDEX]","typeLabel":"object"},"description":"The bricks included in this phase.","isRequired":true,"uniqueKey":"oneOf.1.phases.items.[INDEX].bricks","typeLabel":"object[]"},"starts_at":{"oneOf":[{"type":"string","description":"Start date of this phase. Optional — phase 0 defaults to order-level starts_at; subsequent phases are derived from the previous phase's end date + 1 day.","format":"date","uniqueKey":"oneOf.1.phases.items.[INDEX].starts_at.oneOf.0","typeLabel":"string\u003cdate>"},{"type":"null","description":"Start date of this phase. Optional — phase 0 defaults to order-level starts_at; subsequent phases are derived from the previous phase's end date + 1 day.","format":"date","uniqueKey":"oneOf.1.phases.items.[INDEX].starts_at.oneOf.1","typeLabel":"null"}],"uniqueKey":"oneOf.1.phases.items.[INDEX].starts_at","typeLabel":"string\u003cdate> | null"},"contract_length":{"oneOf":[{"type":"integer","description":"Duration of this phase in months. Required for create, estimate, and recast. Not required for upgrades (end date inherited from the base order).","minimum":1,"uniqueKey":"oneOf.1.phases.items.[INDEX].contract_length.oneOf.0","typeLabel":"integer"},{"type":"null","description":"Duration of this phase in months. Required for create, estimate, and recast. Not required for upgrades (end date inherited from the base order).","minimum":1,"uniqueKey":"oneOf.1.phases.items.[INDEX].contract_length.oneOf.1","typeLabel":"null"}],"uniqueKey":"oneOf.1.phases.items.[INDEX].contract_length","typeLabel":"integer | null"},"billing_frequency":{"type":"string","description":"Billing frequency for this phase. Required for create, estimate and recast — when phases are provided they own the billing frequency outright, so the order-level billing_frequency is not consulted. Not required for upgrades (inherited from the base order's phase). The legacy name `billing_schedule` is still accepted.\n\n* `MONTHLY` - Monthly\n* `QUARTERLY` - Quarterly\n* `SEMI_ANNUALLY` - Semi-annually\n* `ANNUALLY` - Annually\n* `ALL_UPFRONT` - All upfront\n* `CUSTOM` - Custom","enum":["MONTHLY","QUARTERLY","SEMI_ANNUALLY","ANNUALLY","ALL_UPFRONT","CUSTOM"],"x-spec-enum-id":"5f29351b16a5547f","uniqueKey":"oneOf.1.phases.items.[INDEX].billing_frequency","typeLabel":"enum\u003cstring>"},"plan_id":{"oneOf":[{"type":"string","description":"Optional plan for this phase. Each phase may sell a different plan; the phase's bricks are then validated and priced against it. Defaults to the order-level `plan_id`.","format":"uuid","uniqueKey":"oneOf.1.phases.items.[INDEX].plan_id.oneOf.0","typeLabel":"string\u003cuuid>"},{"type":"null","description":"Optional plan for this phase. Each phase may sell a different plan; the phase's bricks are then validated and priced against it. Defaults to the order-level `plan_id`.","format":"uuid","uniqueKey":"oneOf.1.phases.items.[INDEX].plan_id.oneOf.1","typeLabel":"null"}],"uniqueKey":"oneOf.1.phases.items.[INDEX].plan_id","typeLabel":"string\u003cuuid> | null"},"payment_terms":{"type":"integer","description":"Payment terms in days for this phase. Named to match the order-level `payment_terms` input and the phase output — the model field it lands on is `payment_due_upon_receipt`, which is still accepted as a legacy name. Omitted, the phase inherits the order-level value.","maximum":999,"minimum":0,"uniqueKey":"oneOf.1.phases.items.[INDEX].payment_terms","typeLabel":"integer"},"discount_coupons":{"type":"array","items":{"type":"string","uniqueKey":"oneOf.1.phases.items.[INDEX].discount_coupons.items.[INDEX]","typeLabel":"string"},"description":"Discount coupon codes to apply to this phase. Currently only supports one discount coupon - only the first one in the list will be applied.","uniqueKey":"oneOf.1.phases.items.[INDEX].discount_coupons","typeLabel":"string[]"}},"uniqueKey":"oneOf.1.phases.items.[INDEX]","typeLabel":"object"},"description":"Optional list of phases for a multi-phase upgrade. Each phase's ``phase_position`` must match a phase on the base order; only the phases being changed need to be sent, and omitted positions are inherited from the base order unchanged. Order-level bricks and `starts_at` are ignored when phases are provided — the phases own the timeline and the first phase's `starts_at` is the upgrade's effective date.","minItems":1,"isRequired":true,"uniqueKey":"oneOf.1.phases","typeLabel":"object[]"},"crm_opportunity_id":{"type":"string","description":"Optional ID of the opportunity (deal in HubSpot) in your connected CRM to link the subscription to. Requires a linked CRM account, and must not be linked to another subscription. Omit for no change; pass an empty string to unlink it.","maxLength":255,"uniqueKey":"oneOf.1.crm_opportunity_id","typeLabel":"string"},"plan_id":{"type":"string","format":"uuid","description":"Optional plan ID for the upgrade. When provided, the upgrade switches to the latest published version of that plan; when omitted, it keeps the subscription's existing plan version and contracted pricing. Must be sent together with `bricks` — `plan_id` alone is rejected with 400. See the endpoint description for full semantics including cross-plan upgrades and merged plan versions.","uniqueKey":"oneOf.1.plan_id","typeLabel":"string\u003cuuid>"},"starts_at":{"oneOf":[{"type":"string","format":"date","description":"The effective date of the subscription upgrade. Required only when `phases` is omitted: when `phases` is provided the phases own the timeline, so the effective date is taken from the first phase's `starts_at` and this order-level value is ignored.","uniqueKey":"oneOf.1.starts_at.oneOf.0","typeLabel":"string\u003cdate>"},{"type":"null","format":"date","description":"The effective date of the subscription upgrade. Required only when `phases` is omitted: when `phases` is provided the phases own the timeline, so the effective date is taken from the first phase's `starts_at` and this order-level value is ignored.","uniqueKey":"oneOf.1.starts_at.oneOf.1","typeLabel":"null"}],"uniqueKey":"oneOf.1.starts_at","typeLabel":"string\u003cdate> | null"},"discount_coupons":{"type":"array","items":{"type":"string","uniqueKey":"oneOf.1.discount_coupons.items.[INDEX]","typeLabel":"string"},"description":"Discount coupon codes to apply to the subscription upgrade. Currently only supports one discount coupon - only the first one in the list will be applied.","uniqueKey":"oneOf.1.discount_coupons","typeLabel":"string[]"},"custom_order_form_html":{"type":"string","description":"The custom order form html to use with `\u003chtml>\u003cbody>...\u003c/body>\u003c/html>` formatting","uniqueKey":"oneOf.1.custom_order_form_html","typeLabel":"string"},"metadata":{"oneOf":[{"description":"Optional metadata to add to the subscription. Sending an empty map will delete all keys. Keys prefixed with _ are private and will be ignored.","uniqueKey":"oneOf.1.metadata.oneOf.0","typeLabel":"any"},{"description":"Optional metadata to add to the subscription. Sending an empty map will delete all keys. Keys prefixed with _ are private and will be ignored.","type":"null","uniqueKey":"oneOf.1.metadata.oneOf.1","typeLabel":"null"}],"uniqueKey":"oneOf.1.metadata","typeLabel":"any | null"},"downgrade_method":{"oneOf":[{"enum":["CREDIT","REFUND"],"type":"string","x-spec-enum-id":"b3bcc767e244c89a","description":"Method to apply for the downgrade. CREDIT - apply as credit, REFUND - refund the money back. Omitted is treated as CREDIT.\n\n* `CREDIT` - Credit\n* `REFUND` - Refund","uniqueKey":"oneOf.1.downgrade_method.oneOf.0","typeLabel":"enum\u003cstring>"},{"enum":["CREDIT","REFUND"],"type":"null","x-spec-enum-id":"b3bcc767e244c89a","description":"Method to apply for the downgrade. CREDIT - apply as credit, REFUND - refund the money back. Omitted is treated as CREDIT.\n\n* `CREDIT` - Credit\n* `REFUND` - Refund","uniqueKey":"oneOf.1.downgrade_method.oneOf.1","typeLabel":"null"}],"uniqueKey":"oneOf.1.downgrade_method","typeLabel":"enum\u003cstring> | null"}},"uniqueKey":"oneOf.1","typeLabel":"SubscriptionInputUpgradeMultiPhase · object"}],"uniqueKey":"","typeLabel":"SubscriptionInputUpgradeSinglePhase · object | SubscriptionInputUpgradeMultiPhase · object"},"examples":{"Example":{"title":"Example","value":{"starts_at":"2023-12-25","bricks":[{"brick_id":"3c90c3cc-0d44-4b50-8888-8dd25736052a","quantity":123,"is_unlimited":true,"discount":[{"rate":"\u003cstring>","amount":123,"renews":false}]}],"crm_opportunity_id":"\u003cstring>","plan_id":"3c90c3cc-0d44-4b50-8888-8dd25736052a","discount_coupons":["\u003cstring>"],"phases":[{"phase_position":1,"bricks":[{"brick_id":"3c90c3cc-0d44-4b50-8888-8dd25736052a","quantity":123,"is_unlimited":true,"discount":[{"rate":"\u003cstring>","amount":123,"renews":false}]}],"starts_at":"2023-12-25","contract_length":2,"plan_id":"3c90c3cc-0d44-4b50-8888-8dd25736052a","payment_terms":499,"discount_coupons":["\u003cstring>"]}],"custom_order_form_html":"\u003cstring>","metadata":"\u003cunknown>"}}},"exampleType":"generated"}},"required":true,"exampleType":"generated"},"responses":{"7dce3e4d-23a5-44e5-a5da-afd8dbcac0ed":{"content":{"application/json":{"schema":{"type":"object","description":"Serializer for individual subscription order","properties":{"order_id":{"type":"string","format":"uuid","description":"Unique identifier for the order","isRequired":true,"uniqueKey":"order_id","typeLabel":"string\u003cuuid>"},"contract_value":{"type":"string","readOnly":true,"description":"Total contract value with currency","isRequired":true,"uniqueKey":"contract_value","typeLabel":"string"},"pdf_url":{"type":"string","readOnly":true,"description":"URL to download signed order form PDF","isRequired":true,"uniqueKey":"pdf_url","typeLabel":"string"},"crm_account_id":{"oneOf":[{"type":"string","readOnly":true,"description":"ID of the account linked in your connected CRM, if any.","isRequired":true,"uniqueKey":"crm_account_id.oneOf.0","typeLabel":"string"},{"type":"null","readOnly":true,"description":"ID of the account linked in your connected CRM, if any.","isRequired":true,"uniqueKey":"crm_account_id.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"crm_account_id","typeLabel":"string | null"},"crm_opportunity_id":{"oneOf":[{"type":"string","readOnly":true,"description":"ID of the opportunity linked in your connected CRM, if any.","isRequired":true,"uniqueKey":"crm_opportunity_id.oneOf.0","typeLabel":"string"},{"type":"null","readOnly":true,"description":"ID of the opportunity linked in your connected CRM, if any.","isRequired":true,"uniqueKey":"crm_opportunity_id.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"crm_opportunity_id","typeLabel":"string | null"},"starts_at":{"type":"string","format":"date","description":"Start date of the order","uniqueKey":"starts_at","typeLabel":"string\u003cdate>"},"ends_at":{"type":"string","format":"date","description":"End date of the order","uniqueKey":"ends_at","typeLabel":"string\u003cdate>"},"order_type":{"enum":["TRIAL","STANDARD","RENEWAL","UPGRADE","RECAST"],"type":"string","description":"* `TRIAL` - Trial\n* `STANDARD` - New Business\n* `RENEWAL` - Renewal\n* `UPGRADE` - Upgrade\n* `RECAST` - Recast","x-spec-enum-id":"f190c93bb8b6757b","uniqueKey":"order_type","typeLabel":"enum\u003cstring>"}},"required":["contract_value","crm_account_id","crm_opportunity_id","order_id","pdf_url"],"uniqueKey":"","typeLabel":"object"},"examples":{"Example":{"title":"Example","value":{"order_id":"3c90c3cc-0d44-4b50-8888-8dd25736052a","contract_value":"\u003cstring>","pdf_url":"\u003cstring>","crm_account_id":"\u003cstring>","crm_opportunity_id":"\u003cstring>","starts_at":"2023-12-25","ends_at":"2023-12-25","order_type":"TRIAL"}}},"exampleType":"generated"}},"description":"","exampleType":"generated"},"3efce312-9c07-4e6e-9501-be0b3527fe59":{"content":{"application/json":{"schema":{"type":"object","description":"Standardizes API error responses with a consistent structure containing error code and message.","properties":{"error":{"type":"object","description":"The error that caused the request to fail","required":["code","message"],"properties":{"code":{"enum":["ERR_NOT_FOUND","ERR_BAD_REQUEST","ERR_SERVER_ERROR"],"type":"string","x-spec-enum-id":"dc5a5d6feae1b697","description":"Error code indicating the type of error: NOT_FOUND for missing resources, BAD_REQUEST for invalid input, SERVER_ERROR for internal server issues\n\n* `ERR_NOT_FOUND` - ERR_NOT_FOUND\n* `ERR_BAD_REQUEST` - ERR_BAD_REQUEST\n* `ERR_SERVER_ERROR` - ERR_SERVER_ERROR","isRequired":true,"uniqueKey":"error.code","typeLabel":"enum\u003cstring>"},"message":{"type":"string","description":"Human-readable explanation of the error","isRequired":true,"uniqueKey":"error.message","typeLabel":"string"},"error_id":{"type":"string","format":"uuid","description":"Correlation handle for SERVER_ERROR responses — quote this when contacting support; it joins to the structured server log line for the failure. Not present on 4xx responses.","uniqueKey":"error.error_id","typeLabel":"string\u003cuuid>"}},"isRequired":true,"uniqueKey":"error","typeLabel":"object"}},"required":["error"],"uniqueKey":"","typeLabel":"object"},"examples":{"BadRequestResponse":{"title":"BadRequestResponse","value":{"error":{"code":"ERR_BAD_REQUEST","message":"Bad request — the input payload is malformed, missing required fields, or contains invalid data."}}}},"exampleType":"examples"}},"description":"","exampleType":"examples"},"c56f7520-4241-4382-8e58-76bca55c2a2e":{"content":{"application/json":{"schema":{"type":"object","description":"Standardizes API error responses with a consistent structure containing error code and message.","properties":{"error":{"type":"object","description":"The error that caused the request to fail","required":["code","message"],"properties":{"code":{"enum":["ERR_NOT_FOUND","ERR_BAD_REQUEST","ERR_SERVER_ERROR"],"type":"string","x-spec-enum-id":"dc5a5d6feae1b697","description":"Error code indicating the type of error: NOT_FOUND for missing resources, BAD_REQUEST for invalid input, SERVER_ERROR for internal server issues\n\n* `ERR_NOT_FOUND` - ERR_NOT_FOUND\n* `ERR_BAD_REQUEST` - ERR_BAD_REQUEST\n* `ERR_SERVER_ERROR` - ERR_SERVER_ERROR","isRequired":true,"uniqueKey":"error.code","typeLabel":"enum\u003cstring>"},"message":{"type":"string","description":"Human-readable explanation of the error","isRequired":true,"uniqueKey":"error.message","typeLabel":"string"},"error_id":{"type":"string","format":"uuid","description":"Correlation handle for SERVER_ERROR responses — quote this when contacting support; it joins to the structured server log line for the failure. Not present on 4xx responses.","uniqueKey":"error.error_id","typeLabel":"string\u003cuuid>"}},"isRequired":true,"uniqueKey":"error","typeLabel":"object"}},"required":["error"],"uniqueKey":"","typeLabel":"object"},"examples":{"NotFoundResponse":{"title":"NotFoundResponse","value":{"error":{"code":"ERR_NOT_FOUND","message":"Not found — the resource you are looking for does not exist."}}}},"exampleType":"examples"}},"description":"","exampleType":"examples"}},"security":{"96e2b814-4b2f-4ec1-a062-fb177ecfca77":{"ApiKeyAuth":{"type":"apiKey","in":"header","name":"X-SALESBRICKS-KEY","description":"API key for authentication","scopes":[],"schemeName":"ApiKeyAuth"}}},"servers":{"473a595f-0b07-4538-b033-faf5582d0b46":{"url":"https://api.salesbricks.com/api/v2","description":"Production"}},"processedSecurityOptions":[{"schemes":[{"scheme":{"type":"apiKey","in":"header","name":"X-SALESBRICKS-KEY","description":"API key for authentication","scopes":[],"schemeName":"ApiKeyAuth"},"schema":{"title":"X-SALESBRICKS-KEY","type":"string","description":"API key for authentication","isRequired":true,"typeLabel":"string","deprecated":false},"schemeName":"ApiKeyAuth","name":"X-SALESBRICKS-KEY"}],"title":"ApiKeyAuth"}]},"originalFileLocation":"https://api.salesbricks.com/api/v2/openapi.yaml"},"subdomain":"salesbricks","siteName":"Salesbricks","title":"Create a subscription upgrade - Salesbricks","relatedPagesConfig":{"enabled":true,"limit":3,"mode":"automatic"},"navMaps":{"firstHrefInVersion":{},"firstHrefInLanguage":{}},"lastModified":"2026-11-05T23:31:30.944Z","originalFileLocation":"api-reference/subscription-upgrades/create-a-subscription-upgrade.mdx"},"headHtml":"\u003cscript data-mint-head>(function(){var d=document.documentElement,p=null;if(!p){try{p=localStorage.getItem(\"isDarkMode\")}catch(e){}if(p==='true')p='dark';else if(p==='false')p='light';if(p!=='light'\u0026\u0026p!=='dark'\u0026\u0026p!=='system')p=\"system\"}var r=p==='system'?(matchMedia(\"(prefers-color-scheme: dark)\").matches?'dark':'light'):p;d.classList.remove(r==='dark'?'light':'dark');d.classList.add(r);d.setAttribute(\"data-theme-preference\",p)})();\u003c/script>\u003cmeta data-mint-head name=\"description\" content=\"Creates a subscription upgrade that can be used to add or remove add-ons from an existing contract term. - Use /subscriptions/{subscription_id}/upgrade/{order_id}/estimate to preview pricing before confirming - Use /subscriptions/{subscription_id}/upgrade/{order_id}/start to begin the upgrade The upgrade keeps the subscription\u0026#x27;s CRM account. Pass crm_opportunity_id to link it to its own opportunity in your connected CRM; without one, no opportunity is linked or created. How plan_id affects pricing: - plan_id omitted — the upgrade keeps the subscription\u0026#x27;s current plan version and contracted pricing (customers stay grandfathered). If bricks includes a brick that doesn\u0026#x27;t exist on the current plan version, it is pulled in from that plan\u0026#x27;s latest published version, producing a merged plan version. - plan_id provided — the upgrade switches to the latest published version of the referenced plan. If bricks references a brick that only exists on the subscription\u0026#x27;s prior plan version, it is carried over into a merged plan version. - plan_id may reference a different plan than the subscription\u0026#x27;s current plan; that is how cross-plan upgrades are expressed. - plan_id is only honoured when bricks is also provided. Sending plan_id without bricks returns 400. How bricks affects existing discounts: Per-brick discounts are replaced, not merged. The discount sent on a brick becomes that brick\u0026#x27;s complete set of discounts for this order, and a brick sent without a discount ends up with none — any discount it previously carried is dropped. This applies to every brick in the payload, not only the ones being changed. A brick included solely to keep it on the order still needs its discount resent, or it loses it. Read the current values from the subscription\u0026#x27;s line items — discount is returned there in the same shape this endpoint accepts — and send them back for every brick whose discount should carry over.\">\u003cmeta data-mint-head name=\"application-name\" content=\"Salesbricks\">\u003cmeta data-mint-head name=\"generator\" content=\"Mintlify\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"192x192\" href=\"/mintlify-assets/_mintlify/favicons/salesbricks/Q_HZP6fZfruEcDCT/_generated/favicon/android-chrome-192x192.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"apple-touch-icon\" type=\"image/png\" sizes=\"180x180\" href=\"/mintlify-assets/_mintlify/favicons/salesbricks/Q_HZP6fZfruEcDCT/_generated/favicon/apple-touch-icon.png\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"/mintlify-assets/_mintlify/favicons/salesbricks/Q_HZP6fZfruEcDCT/_generated/favicon/favicon-16x16.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"/mintlify-assets/_mintlify/favicons/salesbricks/Q_HZP6fZfruEcDCT/_generated/favicon/favicon-32x32.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"shortcut icon\" type=\"image/x-icon\" href=\"/mintlify-assets/_mintlify/favicons/salesbricks/Q_HZP6fZfruEcDCT/_generated/favicon/favicon.ico\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"192x192\" href=\"/mintlify-assets/_mintlify/favicons/salesbricks/Q_HZP6fZfruEcDCT/_generated/favicon-dark/android-chrome-192x192.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"/mintlify-assets/_mintlify/favicons/salesbricks/Q_HZP6fZfruEcDCT/_generated/favicon-dark/favicon-16x16.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"/mintlify-assets/_mintlify/favicons/salesbricks/Q_HZP6fZfruEcDCT/_generated/favicon-dark/favicon-32x32.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"shortcut icon\" type=\"image/x-icon\" href=\"/mintlify-assets/_mintlify/favicons/salesbricks/Q_HZP6fZfruEcDCT/_generated/favicon-dark/favicon.ico\" media=\"(prefers-color-scheme: dark)\">\u003cmeta data-mint-head property=\"og:title\" content=\"Create a subscription upgrade - Salesbricks\">\u003cmeta data-mint-head property=\"og:description\" content=\"Creates a subscription upgrade that can be used to add or remove add-ons from an existing contract term. - Use /subscriptions/{subscription_id}/upgrade/{order_id}/estimate to preview pricing before confirming - Use /subscriptions/{subscription_id}/upgrade/{order_id}/start to begin the upgrade The upgrade keeps the subscription\u0026#x27;s CRM account. Pass crm_opportunity_id to link it to its own opportunity in your connected CRM; without one, no opportunity is linked or created. How plan_id affects pricing: - plan_id omitted — the upgrade keeps the subscription\u0026#x27;s current plan version and contracted pricing (customers stay grandfathered). If bricks includes a brick that doesn\u0026#x27;t exist on the current plan version, it is pulled in from that plan\u0026#x27;s latest published version, producing a merged plan version. - plan_id provided — the upgrade switches to the latest published version of the referenced plan. If bricks references a brick that only exists on the subscription\u0026#x27;s prior plan version, it is carried over into a merged plan version. - plan_id may reference a different plan than the subscription\u0026#x27;s current plan; that is how cross-plan upgrades are expressed. - plan_id is only honoured when bricks is also provided. Sending plan_id without bricks returns 400. How bricks affects existing discounts: Per-brick discounts are replaced, not merged. The discount sent on a brick becomes that brick\u0026#x27;s complete set of discounts for this order, and a brick sent without a discount ends up with none — any discount it previously carried is dropped. This applies to every brick in the payload, not only the ones being changed. A brick included solely to keep it on the order still needs its discount resent, or it loses it. Read the current values from the subscription\u0026#x27;s line items — discount is returned there in the same shape this endpoint accepts — and send them back for every brick whose discount should carry over.\">\u003cmeta data-mint-head property=\"og:site_name\" content=\"Salesbricks\">\u003cmeta data-mint-head property=\"og:url\" content=\"https://docs.salesbricks.com/api-reference/subscription-upgrades/create-a-subscription-upgrade\">\u003cmeta data-mint-head property=\"og:type\" content=\"website\">\u003cmeta data-mint-head property=\"og:image\" content=\"https://salesbricks.mintlify.site/_mintlify/api/og/v2?division=Subscription+Upgrades\u0026amp;title=Create+a+subscription+upgrade\u0026amp;description=Creates+a+subscription+upgrade+that+can+be+used+to+add+or+remove+add-ons+from+an+existing+contract+term.%0A%0A-+Use+%60%2Fsubscriptions%2F%7Bsubscription_id%7D%2Fupgrade%2F%7Border\u0026amp;theme=c38cf69ba54d28d8add3f8a9\u0026amp;signature=14730e6674f623c094c0f7c71036413d38203f215fc931dc62516b4b2d5fbddf\">\u003cmeta data-mint-head property=\"og:image:width\" content=\"1200\">\u003cmeta data-mint-head property=\"og:image:height\" content=\"630\">\u003cmeta data-mint-head name=\"twitter:card\" content=\"summary_large_image\">\u003cmeta data-mint-head name=\"twitter:title\" content=\"Create a subscription upgrade - Salesbricks\">\u003cmeta data-mint-head name=\"twitter:description\" content=\"Creates a subscription upgrade that can be used to add or remove add-ons from an existing contract term. - Use /subscriptions/{subscription_id}/upgrade/{order_id}/estimate to preview pricing before confirming - Use /subscriptions/{subscription_id}/upgrade/{order_id}/start to begin the upgrade The upgrade keeps the subscription\u0026#x27;s CRM account. Pass crm_opportunity_id to link it to its own opportunity in your connected CRM; without one, no opportunity is linked or created. How plan_id affects pricing: - plan_id omitted — the upgrade keeps the subscription\u0026#x27;s current plan version and contracted pricing (customers stay grandfathered). If bricks includes a brick that doesn\u0026#x27;t exist on the current plan version, it is pulled in from that plan\u0026#x27;s latest published version, producing a merged plan version. - plan_id provided — the upgrade switches to the latest published version of the referenced plan. If bricks references a brick that only exists on the subscription\u0026#x27;s prior plan version, it is carried over into a merged plan version. - plan_id may reference a different plan than the subscription\u0026#x27;s current plan; that is how cross-plan upgrades are expressed. - plan_id is only honoured when bricks is also provided. Sending plan_id without bricks returns 400. How bricks affects existing discounts: Per-brick discounts are replaced, not merged. The discount sent on a brick becomes that brick\u0026#x27;s complete set of discounts for this order, and a brick sent without a discount ends up with none — any discount it previously carried is dropped. This applies to every brick in the payload, not only the ones being changed. A brick included solely to keep it on the order still needs its discount resent, or it loses it. Read the current values from the subscription\u0026#x27;s line items — discount is returned there in the same shape this endpoint accepts — and send them back for every brick whose discount should carry over.\">\u003cmeta data-mint-head name=\"twitter:image\" content=\"https://salesbricks.mintlify.site/_mintlify/api/og/v2?division=Subscription+Upgrades\u0026amp;title=Create+a+subscription+upgrade\u0026amp;description=Creates+a+subscription+upgrade+that+can+be+used+to+add+or+remove+add-ons+from+an+existing+contract+term.%0A%0A-+Use+%60%2Fsubscriptions%2F%7Bsubscription_id%7D%2Fupgrade%2F%7Border\u0026amp;theme=c38cf69ba54d28d8add3f8a9\u0026amp;signature=14730e6674f623c094c0f7c71036413d38203f215fc931dc62516b4b2d5fbddf\">\u003cmeta data-mint-head name=\"twitter:image:width\" content=\"1200\">\u003cmeta data-mint-head name=\"twitter:image:height\" content=\"630\">\u003cmeta data-mint-head name=\"msapplication-config\" content=\"/mintlify-assets/_mintlify/favicons/salesbricks/Q_HZP6fZfruEcDCT/_generated/favicon/browserconfig.xml\">\u003cmeta data-mint-head name=\"apple-mobile-web-app-title\" content=\"Salesbricks\">\u003cmeta data-mint-head name=\"msapplication-TileColor\" content=\"#197F78\">\u003clink data-mint-head rel=\"canonical\" href=\"https://docs.salesbricks.com/api-reference/subscription-upgrades/create-a-subscription-upgrade\">\u003clink data-mint-head rel=\"alternate\" type=\"application/xml\" href=\"/sitemap.xml\">\u003clink data-mint-head rel=\"alternate\" type=\"text/markdown\" href=\"/api-reference/subscription-upgrades/create-a-subscription-upgrade.md\">\u003cscript data-mint-head type=\"application/ld+json\">{\"@context\":\"https://schema.org\",\"@graph\":[{\"@type\":\"Organization\",\"@id\":\"https://docs.salesbricks.com/#organization\",\"name\":\"Salesbricks\",\"url\":\"https://docs.salesbricks.com\",\"logo\":{\"@type\":\"ImageObject\",\"url\":\"https://mintcdn.com/salesbricks/3GVA0K12Q7dXW89y/logo/light.svg?fit=max\u0026auto=format\u0026n=3GVA0K12Q7dXW89y\u0026q=85\u0026s=ead3e65ff72970d53a9cd22de50bd8fc\"}},{\"@type\":\"WebSite\",\"@id\":\"https://docs.salesbricks.com#website\",\"name\":\"Salesbricks\",\"url\":\"https://docs.salesbricks.com\",\"publisher\":{\"@id\":\"https://docs.salesbricks.com/#organization\"}},{\"@type\":\"WebPage\",\"@id\":\"https://docs.salesbricks.com/api-reference/subscription-upgrades/create-a-subscription-upgrade#webpage\",\"url\":\"https://docs.salesbricks.com/api-reference/subscription-upgrades/create-a-subscription-upgrade\",\"name\":\"Create a subscription upgrade\",\"description\":\"Creates a subscription upgrade that can be used to add or remove add-ons from an existing contract term. - Use /subscriptions/{subscription_id}/upgrade/{order_id}/estimate to preview pricing before confirming - Use /subscriptions/{subscription_id}/upgrade/{order_id}/start to begin the upgrade The upgrade keeps the subscription's CRM account. Pass crm_opportunity_id to link it to its own opportunity in your connected CRM; without one, no opportunity is linked or created. How plan_id affects pricing: - plan_id omitted — the upgrade keeps the subscription's current plan version and contracted pricing (customers stay grandfathered). If bricks includes a brick that doesn't exist on the current plan version, it is pulled in from that plan's latest published version, producing a merged plan version. - plan_id provided — the upgrade switches to the latest published version of the referenced plan. If bricks references a brick that only exists on the subscription's prior plan version, it is carried over into a merged plan version. - plan_id may reference a different plan than the subscription's current plan; that is how cross-plan upgrades are expressed. - plan_id is only honoured when bricks is also provided. Sending plan_id without bricks returns 400. How bricks affects existing discounts: Per-brick discounts are replaced, not merged. The discount sent on a brick becomes that brick's complete set of discounts for this order, and a brick sent without a discount ends up with none — any discount it previously carried is dropped. This applies to every brick in the payload, not only the ones being changed. A brick included solely to keep it on the order still needs its discount resent, or it loses it. Read the current values from the subscription's line items — discount is returned there in the same shape this endpoint accepts — and send them back for every brick whose discount should carry over.\",\"dateModified\":\"2026-11-05T23:31:30.944Z\",\"isPartOf\":{\"@id\":\"https://docs.salesbricks.com#website\"},\"breadcrumb\":{\"@id\":\"https://docs.salesbricks.com/api-reference/subscription-upgrades/create-a-subscription-upgrade#breadcrumb\"}},{\"@type\":\"BreadcrumbList\",\"@id\":\"https://docs.salesbricks.com/api-reference/subscription-upgrades/create-a-subscription-upgrade#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"REST API Endpoints\",\"item\":\"https://docs.salesbricks.com/api-reference/customers/list-all-customers\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Subscription Upgrades\",\"item\":\"https://docs.salesbricks.com/api-reference/subscription-upgrades/list-all-subscription-upgrade-open-orders\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"Create a subscription upgrade\",\"item\":\"https://docs.salesbricks.com/api-reference/subscription-upgrades/create-a-subscription-upgrade\"}]},{\"@type\":[\"TechArticle\",\"APIReference\"],\"@id\":\"https://docs.salesbricks.com/api-reference/subscription-upgrades/create-a-subscription-upgrade#apireference\",\"headline\":\"Create a subscription upgrade\",\"name\":\"Create a subscription upgrade\",\"description\":\"Creates a subscription upgrade that can be used to add or remove add-ons from an existing contract term. - Use /subscriptions/{subscription_id}/upgrade/{order_id}/estimate to preview pricing before confirming - Use /subscriptions/{subscription_id}/upgrade/{order_id}/start to begin the upgrade The upgrade keeps the subscription's CRM account. Pass crm_opportunity_id to link it to its own opportunity in your connected CRM; without one, no opportunity is linked or created. How plan_id affects pricing: - plan_id omitted — the upgrade keeps the subscription's current plan version and contracted pricing (customers stay grandfathered). If bricks includes a brick that doesn't exist on the current plan version, it is pulled in from that plan's latest published version, producing a merged plan version. - plan_id provided — the upgrade switches to the latest published version of the referenced plan. If bricks references a brick that only exists on the subscription's prior plan version, it is carried over into a merged plan version. - plan_id may reference a different plan than the subscription's current plan; that is how cross-plan upgrades are expressed. - plan_id is only honoured when bricks is also provided. Sending plan_id without bricks returns 400. How bricks affects existing discounts: Per-brick discounts are replaced, not merged. The discount sent on a brick becomes that brick's complete set of discounts for this order, and a brick sent without a discount ends up with none — any discount it previously carried is dropped. This applies to every brick in the payload, not only the ones being changed. A brick included solely to keep it on the order still needs its discount resent, or it loses it. Read the current values from the subscription's line items — discount is returned there in the same shape this endpoint accepts — and send them back for every brick whose discount should carry over.\",\"url\":\"https://docs.salesbricks.com/api-reference/subscription-upgrades/create-a-subscription-upgrade\",\"mainEntityOfPage\":{\"@id\":\"https://docs.salesbricks.com/api-reference/subscription-upgrades/create-a-subscription-upgrade#webpage\"},\"dateModified\":\"2026-11-05T23:31:30.944Z\",\"publisher\":{\"@id\":\"https://docs.salesbricks.com/#organization\"},\"isPartOf\":{\"@id\":\"https://docs.salesbricks.com#website\"}}]}\u003c/script>\u003cscript data-mint-head type=\"application/ld+json\">{\"@context\":\"https://schema.org\",\"@type\":\"WebSite\",\"name\":\"Salesbricks\",\"creator\":{\"@type\":\"Organization\",\"name\":\"Mintlify\",\"url\":\"https://mintlify.com\"}}\u003c/script>","siteName":"Salesbricks","nav":{"global":null,"tabs":[{"tab":"Documentation","pages":[{"title":"Documentation","href":"/quickstart-guide/introduction"}]},{"tab":"Integrations","pages":[{"title":"Integrations","href":"/integrations/salesforce/overview"}]},{"tab":"APIs \u0026 Webhooks","groups":[{"group":"APIs","icon":"code","pages":[{"title":"REST API Overview","href":"/api-reference/getting-started/overview"},{"title":"Authentication","href":"/api-reference/getting-started/authentication"},{"title":"Starting a Subscription","href":"/api-reference/getting-started/starting-a-subscription"},{"title":"Idempotent Requests","href":"/api-reference/getting-started/idempotent-requests"},{"title":"GraphQL API (Legacy)","href":"/api-reference/getting-started/graphql"},{"title":"Manage My Subscription","href":"/api-reference/manage-my-subscription"}]},{"group":"REST API Endpoints","icon":"server","pages":[{"group":"Customers","pages":[{"title":"List all customers","deprecated":null,"version":null,"openapi":"https://api.salesbricks.com/api/v2/openapi.yaml get /customers","href":"/api-reference/customers/list-all-customers"},{"title":"Create a customer","deprecated":null,"version":null,"openapi":"https://api.salesbricks.com/api/v2/openapi.yaml post /customers","href":"/api-reference/customers/create-a-customer"},{"title":"Retrieve a customer","deprecated":null,"version":null,"openapi":"https://api.salesbricks.com/api/v2/openapi.yaml get /customers/{customer_id}","href":"/api-reference/customers/retrieve-a-customer"},{"title":"Update a customer","deprecated":null,"version":null,"openapi":"https://api.salesbricks.com/api/v2/openapi.yaml patch /customers/{customer_id}","href":"/api-reference/customers/update-a-customer"},{"title":"Search customers","deprecated":null,"version":null,"openapi":"https://api.salesbricks.com/api/v2/openapi.yaml post /customers/search","href":"/api-reference/customers/search-customers"}]},{"group":"Invoices","pages":[{"title":"List all customer invoices","deprecated":null,"version":null,"openapi":"https://api.salesbricks.com/api/v2/openapi.yaml get /customers/{customer_id}/invoices","href":"/api-reference/invoices/list-all-customer-invoices"},{"title":"Create standalone invoice","deprecated":null,"version":null,"openapi":"https://api.salesbricks.com/api/v2/openapi.yaml post /invoices","href":"/api-reference/invoices/create-standalone-invoice"},{"title":"Retrieve an invoice","deprecated":null,"version":null,"openapi":"https://api.salesbricks.com/api/v2/openapi.yaml get /invoices/{invoice_id}","href":"/api-reference/invoices/retrieve-an-invoice"},{"title":"Update an invoice","deprecated":null,"version":null,"openapi":"https://api.salesbricks.com/api/v2/openapi.yaml patch /invoices/{invoice_id}","href":"/api-reference/invoices/update-an-invoice"},{"title":"Finalize an invoice","deprecated":null,"version":null,"openapi":"https://api.salesbricks.com/api/v2/openapi.yaml post /invoices/{invoice_id}/finalize","href":"/api-reference/invoices/finalize-an-invoice"},{"title":"Pay an invoice","deprecated":null,"version":null,"openapi":"https://api.salesbricks.com/api/v2/openapi.yaml post /invoices/{invoice_id}/pay","href":"/api-reference/invoices/pay-an-invoice"},{"title":"Create a payment","deprecated":null,"version":null,"openapi":"https://api.salesbricks.com/api/v2/openapi.yaml post /invoices/{invoice_id}/payments","href":"/api-reference/invoices/create-a-payment"},{"title":"Retrieve an invoice PDF","deprecated":null,"version":null,"openapi":"https://api.salesbricks.com/api/v2/openapi.yaml get /invoices/{invoice_id}/pdf","href":"/api-reference/invoices/retrieve-an-invoice-pdf"},{"title":"Regenerate an invoice","deprecated":null,"version":null,"openapi":"https://api.salesbricks.com/api/v2/openapi.yaml post /invoices/{invoice_id}/regenerate","href":"/api-reference/invoices/regenerate-an-invoice"},{"title":"Void an invoice","deprecated":null,"version":null,"openapi":"https://api.salesbricks.com/api/v2/openapi.yaml post /invoices/{invoice_id}/void","href":"/api-reference/invoices/void-an-invoice"},{"title":"Search invoices","deprecated":null,"version":null,"openapi":"https://api.salesbricks.com/api/v2/openapi.yaml post /invoices/search","href":"/api-reference/invoices/search-invoices"},{"title":"List all subscription invoices","deprecated":null,"version":null,"openapi":"https://api.salesbricks.com/api/v2/openapi.yaml get /subscriptions/{subscription_id}/invoices","href":"/api-reference/invoices/list-all-subscription-invoices"},{"title":"Retrieve next subscription invoice","deprecated":null,"version":null,"openapi":"https://api.salesbricks.com/api/v2/openapi.yaml get /subscriptions/{subscription_id}/invoices/next","href":"/api-reference/invoices/retrieve-next-subscription-invoice"}]},{"group":"Payment Methods","pages":[{"title":"List all payment methods","deprecated":null,"version":null,"openapi":"https://api.salesbricks.com/api/v2/openapi.yaml get /customers/{customer_id}/payment-methods","href":"/api-reference/payment-methods/list-all-payment-methods"},{"title":"Setup a payment method","deprecated":null,"version":null,"openapi":"https://api.salesbricks.com/api/v2/openapi.yaml post /customers/{customer_id}/payment-methods","href":"/api-reference/payment-methods/setup-a-payment-method"},{"title":"Retrieve default payment method","deprecated":null,"version":null,"openapi":"https://api.salesbricks.com/api/v2/openapi.yaml get /customers/{customer_id}/payment-methods/default","href":"/api-reference/payment-methods/retrieve-default-payment-method"},{"title":"Set default payment method","deprecated":null,"version":null,"openapi":"https://api.salesbricks.com/api/v2/openapi.yaml put /customers/{customer_id}/payment-methods/default","href":"/api-reference/payment-methods/set-default-payment-method"},{"title":"Delete a payment method","deprecated":null,"version":null,"openapi":"https://api.salesbricks.com/api/v2/openapi.yaml delete /customers/{customer_id}/payment-methods/detail","href":"/api-reference/payment-methods/delete-a-payment-method"},{"title":"List the payment methods for an invoice","deprecated":null,"version":null,"openapi":"https://api.salesbricks.com/api/v2/openapi.yaml get /invoices/{invoice_id}/payment-methods","href":"/api-reference/payment-methods/list-the-payment-methods-for-an-invoice"},{"title":"List all payment methods","deprecated":null,"version":null,"openapi":"https://api.salesbricks.com/api/v2/openapi.yaml get /subscriptions/{subscription_id}/payment-methods","href":"/api-reference/payment-methods/list-all-payment-methods-1"},{"title":"Setup a payment method","deprecated":null,"version":null,"openapi":"https://api.salesbricks.com/api/v2/openapi.yaml post /subscriptions/{subscription_id}/payment-methods","href":"/api-reference/payment-methods/setup-a-payment-method-1"},{"title":"Retrieve default payment method","deprecated":null,"version":null,"openapi":"https://api.salesbricks.com/api/v2/openapi.yaml get /subscriptions/{subscription_id}/payment-methods/default","href":"/api-reference/payment-methods/retrieve-default-payment-method-1"},{"title":"Set default payment method","deprecated":null,"version":null,"openapi":"https://api.salesbricks.com/api/v2/openapi.yaml put /subscriptions/{subscription_id}/payment-methods/default","href":"/api-reference/payment-methods/set-default-payment-method-1"},{"title":"Delete a payment method","deprecated":null,"version":null,"openapi":"https://api.salesbricks.com/api/v2/openapi.yaml delete /subscriptions/{subscription_id}/payment-methods/detail","href":"/api-reference/payment-methods/delete-a-payment-method-1"}]},{"group":"Customer Contacts","pages":[{"title":"Create a customer contact","deprecated":null,"version":null,"openapi":"https://api.salesbricks.com/api/v2/openapi.yaml post /customers/{customer_id}/persons","href":"/api-reference/customer-contacts/create-a-customer-contact"},{"title":"Update a customer contact","deprecated":null,"version":null,"openapi":"https://api.salesbricks.com/api/v2/openapi.yaml patch /customers/{customer_id}/persons/{person_id}","href":"/api-reference/customer-contacts/update-a-customer-contact"},{"title":"Search customer contacts","deprecated":null,"version":null,"openapi":"https://api.salesbricks.com/api/v2/openapi.yaml post /persons/search","href":"/api-reference/customer-contacts/search-customer-contacts"}]},{"group":"Discount Coupons","pages":[{"title":"List all discount coupons","deprecated":null,"version":null,"openapi":"https://api.salesbricks.com/api/v2/openapi.yaml get /discount-coupons","href":"/api-reference/discount-coupons/list-all-discount-coupons"},{"title":"Retrieve a discount coupon","deprecated":null,"version":null,"openapi":"https://api.salesbricks.com/api/v2/openapi.yaml get /discount-coupons/{code}","href":"/api-reference/discount-coupons/retrieve-a-discount-coupon"}]},{"group":"Invoice Versions","pages":[{"title":"List all invoice versions","deprecated":null,"version":null,"openapi":"https://api.salesbricks.com/api/v2/openapi.yaml get /invoices/{invoice_id}/versions","href":"/api-reference/invoice-versions/list-all-invoice-versions"}]},{"group":"Legal Entities","pages":[{"title":"List all legal entities","deprecated":null,"version":null,"openapi":"https://api.salesbricks.com/api/v2/openapi.yaml get /legal-entities","href":"/api-reference/legal-entities/list-all-legal-entities"}]},{"group":"Plans","pages":[{"title":"List all plans","deprecated":null,"version":null,"openapi":"https://api.salesbricks.com/api/v2/openapi.yaml get /plans","href":"/api-reference/plans/list-all-plans"},{"title":"Retrieve a plan","deprecated":null,"version":null,"openapi":"https://api.salesbricks.com/api/v2/openapi.yaml get /plans/{plan_id}","href":"/api-reference/plans/retrieve-a-plan"}]},{"group":"Revenue","pages":[{"title":"Get per-subscription revenue by month","deprecated":null,"version":null,"openapi":"https://api.salesbricks.com/api/v2/openapi.yaml get /revenue/subscriptions","href":"/api-reference/revenue/get-per-subscription-revenue-by-month"}]},{"group":"Subscriptions","pages":[{"title":"Create a subscription","deprecated":null,"version":null,"openapi":"https://api.salesbricks.com/api/v2/openapi.yaml post /subscriptions","href":"/api-reference/subscriptions/create-a-subscription"},{"title":"Retrieve a subscription","deprecated":null,"version":null,"openapi":"https://api.salesbricks.com/api/v2/openapi.yaml get /subscriptions/{subscription_id}","href":"/api-reference/subscriptions/retrieve-a-subscription"},{"title":"Update a subscription","deprecated":null,"version":null,"openapi":"https://api.salesbricks.com/api/v2/openapi.yaml patch /subscriptions/{subscription_id}","href":"/api-reference/subscriptions/update-a-subscription"},{"title":"Retrieve subscription checkout URL","deprecated":null,"version":null,"openapi":"https://api.salesbricks.com/api/v2/openapi.yaml get /subscriptions/{subscription_id}/checkout","href":"/api-reference/subscriptions/retrieve-subscription-checkout-url"},{"title":"Update a subscription pause","deprecated":null,"version":null,"openapi":"https://api.salesbricks.com/api/v2/openapi.yaml put /subscriptions/{subscription_id}/pause","href":"/api-reference/subscriptions/update-a-subscription-pause"},{"title":"Pause a subscription","deprecated":null,"version":null,"openapi":"https://api.salesbricks.com/api/v2/openapi.yaml post /subscriptions/{subscription_id}/pause","href":"/api-reference/subscriptions/pause-a-subscription"},{"title":"Cancel an upcoming subscription pause","deprecated":null,"version":null,"openapi":"https://api.salesbricks.com/api/v2/openapi.yaml delete /subscriptions/{subscription_id}/pause","href":"/api-reference/subscriptions/cancel-an-upcoming-subscription-pause"},{"title":"Resume a paused subscription","deprecated":null,"version":null,"openapi":"https://api.salesbricks.com/api/v2/openapi.yaml post /subscriptions/{subscription_id}/resume","href":"/api-reference/subscriptions/resume-a-paused-subscription"},{"title":"Retrieve subscription sign URL","deprecated":null,"version":null,"openapi":"https://api.salesbricks.com/api/v2/openapi.yaml post /subscriptions/{subscription_id}/sign","href":"/api-reference/subscriptions/retrieve-subscription-sign-url"},{"title":"Start a subscription","deprecated":null,"version":null,"openapi":"https://api.salesbricks.com/api/v2/openapi.yaml post /subscriptions/{subscription_id}/start","href":"/api-reference/subscriptions/start-a-subscription"},{"title":"Terminate a subscription","deprecated":null,"version":null,"openapi":"https://api.salesbricks.com/api/v2/openapi.yaml post /subscriptions/{subscription_id}/terminate","href":"/api-reference/subscriptions/terminate-a-subscription"},{"title":"Estimate a subscription","deprecated":null,"version":null,"openapi":"https://api.salesbricks.com/api/v2/openapi.yaml post /subscriptions/estimate","href":"/api-reference/subscriptions/estimate-a-subscription"}]},{"group":"Subscription Management","pages":[{"title":"Retrieve subscription management URL","deprecated":null,"version":null,"openapi":"https://api.salesbricks.com/api/v2/openapi.yaml get /subscriptions/{subscription_id}/billing-portal","href":"/api-reference/subscription-management/retrieve-subscription-management-url"}]},{"group":"Subscription State","pages":[{"title":"List all subscription bricks","deprecated":null,"version":null,"openapi":"https://api.salesbricks.com/api/v2/openapi.yaml get /subscriptions/{subscription_id}/bricks","href":"/api-reference/subscription-state/list-all-subscription-bricks"},{"title":"Retrieve current subscription state","deprecated":null,"version":null,"openapi":"https://api.salesbricks.com/api/v2/openapi.yaml get /subscriptions/{subscription_id}/current","href":"/api-reference/subscription-state/retrieve-current-subscription-state"},{"title":"Update details for a closed subscription","deprecated":null,"version":null,"openapi":"https://api.salesbricks.com/api/v2/openapi.yaml patch /subscriptions/{subscription_id}/current","href":"/api-reference/subscription-state/update-details-for-a-closed-subscription"},{"title":"Retrieve current subscription order form PDF","deprecated":null,"version":null,"openapi":"https://api.salesbricks.com/api/v2/openapi.yaml get /subscriptions/{subscription_id}/current/pdf","href":"/api-reference/subscription-state/retrieve-current-subscription-order-form-pdf"},{"title":"Retrieve a subscription order form PDF","deprecated":null,"version":null,"openapi":"https://api.salesbricks.com/api/v2/openapi.yaml get /subscriptions/{subscription_id}/pdf","href":"/api-reference/subscription-state/retrieve-a-subscription-order-form-pdf"}]},{"group":"Usage","pages":[{"title":"Retrieve brick usage","deprecated":null,"version":null,"openapi":"https://api.salesbricks.com/api/v2/openapi.yaml get /subscriptions/{subscription_id}/bricks/{brick_id}/usage","href":"/api-reference/usage/retrieve-brick-usage"},{"title":"List individual usage entries","deprecated":null,"version":null,"openapi":"https://api.salesbricks.com/api/v2/openapi.yaml get /subscriptions/{subscription_id}/bricks/{brick_id}/usage/entries","href":"/api-reference/usage/list-individual-usage-entries"},{"title":"Retrieve brick usage time series","deprecated":null,"version":null,"openapi":"https://api.salesbricks.com/api/v2/openapi.yaml get /subscriptions/{subscription_id}/bricks/{brick_id}/usage/series","href":"/api-reference/usage/retrieve-brick-usage-time-series"},{"title":"Create a usage entry","deprecated":null,"version":null,"openapi":"https://api.salesbricks.com/api/v2/openapi.yaml post /usage/","href":"/api-reference/usage/create-a-usage-entry"},{"title":"Delete a usage entry","deprecated":null,"version":null,"openapi":"https://api.salesbricks.com/api/v2/openapi.yaml delete /usage/","href":"/api-reference/usage/delete-a-usage-entry"},{"title":"Update a usage entry","deprecated":null,"version":null,"openapi":"https://api.salesbricks.com/api/v2/openapi.yaml patch /usage/","href":"/api-reference/usage/update-a-usage-entry"},{"title":"Get usage transaction details","deprecated":null,"version":null,"openapi":"https://api.salesbricks.com/api/v2/openapi.yaml get /usage/transactions/{transaction_id}/","href":"/api-reference/usage/get-usage-transaction-details"}]},{"group":"Subscription Milestones","pages":[{"title":"List all subscription milestones","deprecated":null,"version":null,"openapi":"https://api.salesbricks.com/api/v2/openapi.yaml get /subscriptions/{subscription_id}/milestones","href":"/api-reference/subscription-milestones/list-all-subscription-milestones"},{"title":"Complete a subscription milestone","deprecated":null,"version":null,"openapi":"https://api.salesbricks.com/api/v2/openapi.yaml post /subscriptions/{subscription_id}/milestones/{milestone_id}/complete","href":"/api-reference/subscription-milestones/complete-a-subscription-milestone"}]},{"group":"Subscription History","pages":[{"title":"List all subscription orders","deprecated":null,"version":null,"openapi":"https://api.salesbricks.com/api/v2/openapi.yaml get /subscriptions/{subscription_id}/orders","href":"/api-reference/subscription-history/list-all-subscription-orders"}]},{"group":"Subscription Recasts","pages":[{"title":"List all subscription recast open orders","deprecated":null,"version":null,"openapi":"https://api.salesbricks.com/api/v2/openapi.yaml get /subscriptions/{subscription_id}/recast","href":"/api-reference/subscription-recasts/list-all-subscription-recast-open-orders"},{"title":"Create a subscription recast","deprecated":null,"version":null,"openapi":"https://api.salesbricks.com/api/v2/openapi.yaml post /subscriptions/{subscription_id}/recast","href":"/api-reference/subscription-recasts/create-a-subscription-recast"},{"title":"Delete a subscription recast","deprecated":null,"version":null,"openapi":"https://api.salesbricks.com/api/v2/openapi.yaml delete /subscriptions/{subscription_id}/recast/{order_id}","href":"/api-reference/subscription-recasts/delete-a-subscription-recast"},{"title":"Update a subscription recast","deprecated":null,"version":null,"openapi":"https://api.salesbricks.com/api/v2/openapi.yaml patch /subscriptions/{subscription_id}/recast/{order_id}","href":"/api-reference/subscription-recasts/update-a-subscription-recast"},{"title":"Retrieve subscription recast checkout URL","deprecated":null,"version":null,"openapi":"https://api.salesbricks.com/api/v2/openapi.yaml get /subscriptions/{subscription_id}/recast/{order_id}/checkout","href":"/api-reference/subscription-recasts/retrieve-subscription-recast-checkout-url"},{"title":"Retrieve subscription recast sign URL","deprecated":null,"version":null,"openapi":"https://api.salesbricks.com/api/v2/openapi.yaml post /subscriptions/{subscription_id}/recast/{order_id}/sign","href":"/api-reference/subscription-recasts/retrieve-subscription-recast-sign-url"},{"title":"Start a subscription recast","deprecated":null,"version":null,"openapi":"https://api.salesbricks.com/api/v2/openapi.yaml post /subscriptions/{subscription_id}/recast/{order_id}/start","href":"/api-reference/subscription-recasts/start-a-subscription-recast"},{"title":"Estimate a subscription recast","deprecated":null,"version":null,"openapi":"https://api.salesbricks.com/api/v2/openapi.yaml post /subscriptions/{subscription_id}/recast/estimate","href":"/api-reference/subscription-recasts/estimate-a-subscription-recast"}]},{"group":"Subscription Upgrades","pages":[{"title":"List all subscription upgrade open orders","description":"Returns a list of all open orders for subscription upgrade. These are upgrade orders that haven't started yet.","deprecated":null,"version":null,"openapi":"https://api.salesbricks.com/api/v2/openapi.yaml get /subscriptions/{subscription_id}/upgrade","href":"/api-reference/subscription-upgrades/list-all-subscription-upgrade-open-orders"},{"title":"Create a subscription upgrade","deprecated":null,"version":null,"openapi":"https://api.salesbricks.com/api/v2/openapi.yaml post /subscriptions/{subscription_id}/upgrade","href":"/api-reference/subscription-upgrades/create-a-subscription-upgrade"},{"title":"Delete a subscription upgrade","description":null,"deprecated":null,"version":null,"openapi":"https://api.salesbricks.com/api/v2/openapi.yaml delete /subscriptions/{subscription_id}/upgrade/{order_id}","href":"/api-reference/subscription-upgrades/delete-a-subscription-upgrade"},{"title":"Update a subscription upgrade","deprecated":null,"version":null,"openapi":"https://api.salesbricks.com/api/v2/openapi.yaml patch /subscriptions/{subscription_id}/upgrade/{order_id}","href":"/api-reference/subscription-upgrades/update-a-subscription-upgrade"},{"title":"Retrieve subscription upgrade checkout URL","deprecated":null,"version":null,"openapi":"https://api.salesbricks.com/api/v2/openapi.yaml get /subscriptions/{subscription_id}/upgrade/{order_id}/checkout","href":"/api-reference/subscription-upgrades/retrieve-subscription-upgrade-checkout-url"},{"title":"Retrieve subscription upgrade sign URL","deprecated":null,"version":null,"openapi":"https://api.salesbricks.com/api/v2/openapi.yaml post /subscriptions/{subscription_id}/upgrade/{order_id}/sign","href":"/api-reference/subscription-upgrades/retrieve-subscription-upgrade-sign-url"},{"title":"Start a subscription upgrade","deprecated":null,"version":null,"openapi":"https://api.salesbricks.com/api/v2/openapi.yaml post /subscriptions/{subscription_id}/upgrade/{order_id}/start","href":"/api-reference/subscription-upgrades/start-a-subscription-upgrade"},{"title":"Estimate a subscription upgrade","deprecated":null,"version":null,"openapi":"https://api.salesbricks.com/api/v2/openapi.yaml post /subscriptions/{subscription_id}/upgrade/estimate","href":"/api-reference/subscription-upgrades/estimate-a-subscription-upgrade"}]}]},{"group":"Usage","icon":"gauge-high","pages":[{"title":"Overview","href":"/api-reference/usage/overview"},{"title":"Submit a usage entry","openapi":"POST /usage","href":"/api-reference/usage/post"},{"title":"Update a usage entry","openapi":"PATCH /usage","href":"/api-reference/usage/patch"},{"title":"Delete a usage entry","openapi":"DELETE /usage","href":"/api-reference/usage/delete"}]},{"group":"Webhooks","icon":"webhook","pages":[{"title":"Overview","href":"/api-reference/webhooks/overview"},{"title":"Schemas","href":"/api-reference/webhooks/schemas"},{"group":"Order Webhooks","pages":[{"title":"Order Webhook Payload","mode":"wide","href":"/api-reference/webhooks/order/payload"},{"title":"order.stage.change","href":"/api-reference/webhooks/order/stage-change"},{"title":"order.approval.status.changed","href":"/api-reference/webhooks/order/approval-status-changed"},{"title":"order.complete","href":"/api-reference/webhooks/order/complete"},{"title":"order.closed.lost","href":"/api-reference/webhooks/order/closed-lost"},{"title":"order.closed.delete","href":"/api-reference/webhooks/order/closed-delete"},{"title":"order.end","href":"/api-reference/webhooks/order/end"},{"title":"order.new-ramping-period","href":"/api-reference/webhooks/order/new-ramping-period"},{"title":"order.terminated","href":"/api-reference/webhooks/order/terminated"},{"title":"order.reinstated","href":"/api-reference/webhooks/order/reinstated"}]},{"group":"Subscription Webhooks","pages":[{"title":"Subscription Inactive Payload","mode":"wide","href":"/api-reference/webhooks/subscription/payload"},{"title":"subscription.inactive","href":"/api-reference/webhooks/subscription/inactive"}]},{"group":"Invoice Webhooks","pages":[{"title":"Invoice Webhook Payload","mode":"wide","href":"/api-reference/webhooks/invoice/payload"},{"title":"invoice.start","href":"/api-reference/webhooks/invoice/start"},{"title":"invoice.upcoming.due","href":"/api-reference/webhooks/invoice/upcoming-due"},{"title":"invoice.past.due","href":"/api-reference/webhooks/invoice/past-due"},{"title":"invoice.payment.succeeded","href":"/api-reference/webhooks/invoice/payment/succeeded"},{"title":"invoice.payment.failed","href":"/api-reference/webhooks/invoice/payment/failed"},{"title":"invoice.refunded","href":"/api-reference/webhooks/invoice/refunded"},{"title":"invoice.voided","href":"/api-reference/webhooks/invoice/voided"}]},{"group":"Payment Webhooks","pages":[{"title":"Payment Webhook Payload","mode":"wide","href":"/api-reference/webhooks/payment/payload"}]},{"group":"Usage Webhooks","pages":[{"title":"Usage Threshold Payload","mode":"wide","href":"/api-reference/webhooks/usage/payload"},{"title":"usage.threshold.exceeded.precommitment","href":"/api-reference/webhooks/usage/threshold-exceeded-precommitment"},{"title":"usage.threshold.exceeded.units","href":"/api-reference/webhooks/usage/threshold-exceeded-units"},{"title":"usage.threshold.exceeded.money","href":"/api-reference/webhooks/usage/threshold-exceeded-money"}]},{"group":"Plan Webhooks","pages":[{"title":"plan.published","href":"/api-reference/webhooks/plan/published"}]},{"group":"Company Webhooks","pages":[{"title":"Company Webhook Payload","mode":"wide","href":"/api-reference/webhooks/company/payload"},{"title":"company.created","href":"/api-reference/webhooks/company/created"},{"title":"company.updated","href":"/api-reference/webhooks/company/updated"}]},{"group":"Person Webhooks","pages":[{"title":"Person Webhook Payload","mode":"wide","href":"/api-reference/webhooks/person/payload"},{"title":"person.created","href":"/api-reference/webhooks/person/created"},{"title":"person.updated","href":"/api-reference/webhooks/person/updated"}]}]}]},{"tab":"What's new","pages":[{"title":"What's new","href":"/whats-new"}]},{"tab":"Knowledge Base","href":"https://support.salesbricks.com"}]},"basePath":"","title":"Create a subscription upgrade - Salesbricks","buildId":"dpl_8LJbrAiZvr1K98WQNZXCyY5AvT34","deploymentId":"dpl_8LJbrAiZvr1K98WQNZXCyY5AvT34","dynamics":["c2aa737661","2b790eda92","b0f84f53ff","a9bb46feb3"],"chunks":["OpenApiReferenceProvider-i2a3QZ8E.js","utils-ChLwp8m0.js","cloneDeep-izs3Hzxb.js","_Uint8Array-BVIqJ90l.js","isObjectLike-C8vmzPEN.js","isArray-Dcu1dQ5t.js","utils-DRktVTDc.js","toString-BX-iyh8G.js","isSymbol-CSH9U2Gm.js","addUniqueKeysToSchema-CA2pEs4T.js","snippetPresets-ClQ6XrKD.js","style-to-object-BY3JEAdk.js","v4-DIgz8zy6.js","ApiExamples-Ct_Lv36y.js","isEqual-BfaiBbcl.js","usePlaygroundInputsStore-Cn2PYw9e.js","shallow-rkyymjXQ.js","getApiPlaygroundDisplay-BB9vkXtE.js","CodeSnippet-Bm5RU7m1.js","CodeSnippets-BgU9Deuz.js","Page-BUDYNlhG.js","getPastedJson-BD-6NNum.js","icon-8Z6tud2e.js","MethodPill-Tuzr4g3V.js","DuplicateIcon-0ceWFYhN.js","createIcon-FBXow_ST.js","DynamicMarkdown-CD8713Yy.js","SectionHeading-7zgzQbH-.js","axios-vUo_bRtp.js","Markdown-D7Ofw1oz.js","clsx-eKJ4rcii.js","lib-DuNMoZ05.js","lib-B8HbPgcC.js","html-void-elements-mCSPHezU.js","dist-CwjSCXIK.js","katex-YMM-FMeD.js","marked.esm-CZWythHk.js","AssistantPageLink-9EK5IAXV.js"]}