Subscription estimate input serializer for generating a pricing estimate.
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.
Every phase needs a plan, so the multi-phase form splits in two: send an order-level plan_id (the plan for any phase that names none), or give every phase its own plan_id. A multi-phase payload naming no plan at all is a 400.
Optional list of phases for multi-phase orders. When provided, ALL phases come from this array (first element = phase 0, second = phase 1, etc.) and starts_at, contract_length, billing_frequency and bricks become optional — omit them and they are derived from the phases. plan_id is still required, and every brick in every phase must belong to it. When absent, the order-level fields define a single phase.
Show child attributes
Response
Subscription /estimate output serializer from OrderPricing
SAL-6964: the commercial payload lives at exactly one altitude. A
multi-phase order carries it per phase and omits the order-level copies —
the same brick appears once per phase and may differ in each, so a single
flattened set can only misrepresent it. A single-phase order keeps the
order-level fields and omits phases entirely, since a lone phase
restates the order. See PHASE_OWNED_FIELDS.
Per-phase breakdown. Only present for multi-phase estimates.
Show child attributes
{"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.4074","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":[],"googleFontsInlined":false},"customCss":[{"filePath":"style.css","content":"table.two-column td,table.two-column th{width:50%}"}],"page":{"pagePath":"api-reference/subscriptions/estimate-a-subscription","slug":"/api-reference/subscriptions/estimate-a-subscription","pageMetadata":{"title":"Estimate a subscription","description":"Gets a pricing estimate for a subscription including the billing schedule and grand total.","deprecated":null,"version":null,"openapi":"https://api.salesbricks.com/api/v2/openapi.yaml post /subscriptions/estimate","href":"/api-reference/subscriptions/estimate-a-subscription","autogeneratedByOpenApi":true},"description":{"compiledSource":"\"use strict\";\nconst {jsx: _jsx} = arguments[0];\nconst {useMDXComponents: _provideComponents} = arguments[0];\nfunction _createMdxContent(props) {\n const _components = {\n p: \"p\",\n ..._provideComponents(),\n ...props.components\n };\n return _jsx(_components.p, {\n children: \"Gets a pricing estimate for a subscription including the billing schedule and grand total.\"\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":"Estimate a subscription","description":"Gets a pricing estimate for a subscription including the billing schedule and grand total.","deprecated":null,"version":null,"openapi":"https://api.salesbricks.com/api/v2/openapi.yaml post /subscriptions/estimate","href":"/api-reference/subscriptions/estimate-a-subscription","autogeneratedByOpenApi":true}}},"mdxSourceWithNoJs":null},"mdxExtracts":{"tableOfContents":[],"codeExamples":{}},"jsLinks":[],"openApiReferenceData":{"operation":{"operationId":"getSubscriptionEstimate","description":"Gets a pricing estimate for a subscription including the billing schedule and grand total.","summary":"Estimate a subscription","tags":["Subscriptions"],"requestBody":"26482b87-98f8-4b4a-93c2-cf5e7b086ea8","responses":{"200":"336e9e12-0ee2-4058-9859-ba3cfeaf661e","400":"c1c3a3cc-fd0c-42b5-bc69-7942999b992b","404":"8e4f54a8-c8e4-4ae0-bcc5-d8dd98e5f134"},"method":"post","type":"path","servers":["473a595f-0b07-4538-b033-faf5582d0b46"],"security":["96e2b814-4b2f-4ec1-a062-fb177ecfca77"],"path":"/subscriptions/estimate","baseUrlOptions":["https://api.salesbricks.com/api/v2"],"title":"Estimate a subscription","codeSamples":[],"requiredOnlyExamples":false,"requestExampleType":"generated","responseExampleType":"generated"},"dependencies":{"parameters":{},"requestBody":{"content":{"application/json":{"schema":{"oneOf":[{"type":"object","title":"SubscriptionInputEstimateSinglePhase","description":"Subscription estimate input serializer for generating a pricing estimate.\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.\n\nEvery phase needs a plan, so the multi-phase form splits in two: send an order-level `plan_id` (the plan for any phase that names none), or give every phase its own `plan_id`. A multi-phase payload naming no plan at all is a 400.","required":["starts_at","contract_length","billing_frequency","bricks","plan_id"],"properties":{"starts_at":{"type":"string","description":"The start date of the subscription. Required unless `phases` is provided, in which case phase 0's start date is used.","format":"date","isRequired":true,"uniqueKey":"oneOf.0.starts_at","typeLabel":"string\u003cdate>"},"contract_length":{"type":"integer","description":"The length of the contract in months. Required unless `phases` is provided, in which case it is the sum of the phase lengths.","minimum":1,"isRequired":true,"uniqueKey":"oneOf.0.contract_length","typeLabel":"integer"},"billing_frequency":{"type":"string","description":"The billing frequency. Required unless `phases` is provided, in which case each phase declares its own `billing_frequency`.\n\n* `MONTHLY` - Monthly\n* `QUARTERLY` - Quarterly\n* `SEMI_ANNUALLY` - Semi-annually\n* `ANNUALLY` - Annually\n* `ALL_UPFRONT` - All upfront","enum":["MONTHLY","QUARTERLY","SEMI_ANNUALLY","ANNUALLY","ALL_UPFRONT"],"x-spec-enum-id":"f41da4a34f13f89b","isRequired":true,"uniqueKey":"oneOf.0.billing_frequency","typeLabel":"enum\u003cstring>"},"plan_id":{"type":"string","description":"The ID of the plan. Required unless every phase declares its own `plan_id` — it is the plan for any phase that does not.","format":"uuid","isRequired":true,"uniqueKey":"oneOf.0.plan_id","typeLabel":"string\u003cuuid>"},"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.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","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.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","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.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","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"}},"uniqueKey":"oneOf.0.bricks.items.[INDEX]","typeLabel":"object"},"description":"The bricks included in the subscription. Required unless `phases` is provided, in which case every brick comes from the phases.","isRequired":true,"uniqueKey":"oneOf.0.bricks","typeLabel":"object[]"},"currency":{"enum":["USD","EUR","GBP","AUD","CAD","INR"],"type":"string","x-spec-enum-id":"fde863feba7c4cf4","default":"USD","description":"Optional currency to be used for the subscription. Defaults to USD.\n\n* `USD` - United States Dollar\n* `EUR` - Euros\n* `GBP` - Great British Pound\n* `AUD` - Australian Dollar\n* `CAD` - Canadian Dollar\n* `INR` - Indian Rupee","uniqueKey":"oneOf.0.currency","typeLabel":"enum\u003cstring>"},"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. 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 multi-phase orders. When provided, ALL phases come from this array (first element = phase 0, second = phase 1, etc.) and `starts_at`, `contract_length`, `billing_frequency` and `bricks` become optional — omit them and they are derived from the phases. `plan_id` is still required, and every brick in every phase must belong to it. When absent, the order-level fields define a single phase.","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 multi-phase orders. When provided, ALL phases come from this array (first element = phase 0, second = phase 1, etc.) and `starts_at`, `contract_length`, `billing_frequency` and `bricks` become optional — omit them and they are derived from the phases. `plan_id` is still required, and every brick in every phase must belong to it. When absent, the order-level fields define a single phase.","uniqueKey":"oneOf.0.phases.oneOf.1","typeLabel":"null"}],"uniqueKey":"oneOf.0.phases","typeLabel":"object[] | null"}},"uniqueKey":"oneOf.0","typeLabel":"SubscriptionInputEstimateSinglePhase · object"},{"type":"object","title":"SubscriptionInputEstimateMultiPhasePerPhasePlans","description":"Subscription estimate input serializer for generating a pricing estimate.\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.\n\nEvery phase needs a plan, so the multi-phase form splits in two: send an order-level `plan_id` (the plan for any phase that names none), or give every phase its own `plan_id`. A multi-phase payload naming no plan at all is a 400.","required":["phases"],"properties":{"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":["plan_id","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"},"plan_id":{"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","isRequired":true,"uniqueKey":"oneOf.1.phases.items.[INDEX].plan_id","typeLabel":"string\u003cuuid>"},"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>"},"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 multi-phase orders. When provided, ALL phases come from this array (first element = phase 0, second = phase 1, etc.) and `starts_at`, `contract_length`, `billing_frequency` and `bricks` become optional — omit them and they are derived from the phases. `plan_id` is still required, and every brick in every phase must belong to it. When absent, the order-level fields define a single phase.","minItems":1,"isRequired":true,"uniqueKey":"oneOf.1.phases","typeLabel":"object[]"},"starts_at":{"type":"string","format":"date","description":"The start date of the subscription. Required unless `phases` is provided, in which case phase 0's start date is used.","uniqueKey":"oneOf.1.starts_at","typeLabel":"string\u003cdate>"},"contract_length":{"type":"integer","minimum":1,"description":"The length of the contract in months. Required unless `phases` is provided, in which case it is the sum of the phase lengths.","uniqueKey":"oneOf.1.contract_length","typeLabel":"integer"},"billing_frequency":{"enum":["MONTHLY","QUARTERLY","SEMI_ANNUALLY","ANNUALLY","ALL_UPFRONT"],"type":"string","x-spec-enum-id":"f41da4a34f13f89b","description":"The billing frequency. Required unless `phases` is provided, in which case each phase declares its own `billing_frequency`.\n\n* `MONTHLY` - Monthly\n* `QUARTERLY` - Quarterly\n* `SEMI_ANNUALLY` - Semi-annually\n* `ANNUALLY` - Annually\n* `ALL_UPFRONT` - All upfront","uniqueKey":"oneOf.1.billing_frequency","typeLabel":"enum\u003cstring>"},"plan_id":{"type":"string","format":"uuid","description":"The ID of the plan. Required unless every phase declares its own `plan_id` — it is the plan for any phase that does not.","uniqueKey":"oneOf.1.plan_id","typeLabel":"string\u003cuuid>"},"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 the subscription. Required unless `phases` is provided, in which case every brick comes from the phases.","uniqueKey":"oneOf.1.bricks","typeLabel":"object[]"},"currency":{"enum":["USD","EUR","GBP","AUD","CAD","INR"],"type":"string","x-spec-enum-id":"fde863feba7c4cf4","default":"USD","description":"Optional currency to be used for the subscription. Defaults to USD.\n\n* `USD` - United States Dollar\n* `EUR` - Euros\n* `GBP` - Great British Pound\n* `AUD` - Australian Dollar\n* `CAD` - Canadian Dollar\n* `INR` - Indian Rupee","uniqueKey":"oneOf.1.currency","typeLabel":"enum\u003cstring>"},"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. Currently only supports one discount coupon - only the first one in the list will be applied.","uniqueKey":"oneOf.1.discount_coupons","typeLabel":"string[]"}},"uniqueKey":"oneOf.1","typeLabel":"SubscriptionInputEstimateMultiPhasePerPhasePlans · object"},{"type":"object","title":"SubscriptionInputEstimateMultiPhase","description":"Subscription estimate input serializer for generating a pricing estimate.\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.\n\nEvery phase needs a plan, so the multi-phase form splits in two: send an order-level `plan_id` (the plan for any phase that names none), or give every phase its own `plan_id`. A multi-phase payload naming no plan at all is a 400.","required":["phases","plan_id"],"properties":{"plan_id":{"type":"string","description":"The ID of the plan. Required unless every phase declares its own `plan_id` — it is the plan for any phase that does not.","format":"uuid","isRequired":true,"uniqueKey":"oneOf.2.plan_id","typeLabel":"string\u003cuuid>"},"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.2.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.2.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.2.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.2.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.2.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.2.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.2.phases.items.[INDEX].bricks.items.[INDEX].discount.oneOf.0.items.[INDEX].renews","typeLabel":"boolean"}},"uniqueKey":"oneOf.2.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.2.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.2.phases.items.[INDEX].bricks.items.[INDEX].discount.oneOf.1","typeLabel":"null"}],"uniqueKey":"oneOf.2.phases.items.[INDEX].bricks.items.[INDEX].discount","typeLabel":"object[] | null"}},"uniqueKey":"oneOf.2.phases.items.[INDEX].bricks.items.[INDEX]","typeLabel":"object"},"description":"The bricks included in this phase.","isRequired":true,"uniqueKey":"oneOf.2.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.2.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.2.phases.items.[INDEX].starts_at.oneOf.1","typeLabel":"null"}],"uniqueKey":"oneOf.2.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.2.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.2.phases.items.[INDEX].contract_length.oneOf.1","typeLabel":"null"}],"uniqueKey":"oneOf.2.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.2.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.2.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.2.phases.items.[INDEX].plan_id.oneOf.1","typeLabel":"null"}],"uniqueKey":"oneOf.2.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.2.phases.items.[INDEX].payment_terms","typeLabel":"integer"},"discount_coupons":{"type":"array","items":{"type":"string","uniqueKey":"oneOf.2.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.2.phases.items.[INDEX].discount_coupons","typeLabel":"string[]"}},"uniqueKey":"oneOf.2.phases.items.[INDEX]","typeLabel":"object"},"description":"Optional list of phases for multi-phase orders. When provided, ALL phases come from this array (first element = phase 0, second = phase 1, etc.) and `starts_at`, `contract_length`, `billing_frequency` and `bricks` become optional — omit them and they are derived from the phases. `plan_id` is still required, and every brick in every phase must belong to it. When absent, the order-level fields define a single phase.","minItems":1,"isRequired":true,"uniqueKey":"oneOf.2.phases","typeLabel":"object[]"},"starts_at":{"type":"string","format":"date","description":"The start date of the subscription. Required unless `phases` is provided, in which case phase 0's start date is used.","uniqueKey":"oneOf.2.starts_at","typeLabel":"string\u003cdate>"},"contract_length":{"type":"integer","minimum":1,"description":"The length of the contract in months. Required unless `phases` is provided, in which case it is the sum of the phase lengths.","uniqueKey":"oneOf.2.contract_length","typeLabel":"integer"},"billing_frequency":{"enum":["MONTHLY","QUARTERLY","SEMI_ANNUALLY","ANNUALLY","ALL_UPFRONT"],"type":"string","x-spec-enum-id":"f41da4a34f13f89b","description":"The billing frequency. Required unless `phases` is provided, in which case each phase declares its own `billing_frequency`.\n\n* `MONTHLY` - Monthly\n* `QUARTERLY` - Quarterly\n* `SEMI_ANNUALLY` - Semi-annually\n* `ANNUALLY` - Annually\n* `ALL_UPFRONT` - All upfront","uniqueKey":"oneOf.2.billing_frequency","typeLabel":"enum\u003cstring>"},"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.2.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.2.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.2.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.2.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.2.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.2.bricks.items.[INDEX].discount.oneOf.0.items.[INDEX].renews","typeLabel":"boolean"}},"uniqueKey":"oneOf.2.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.2.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.2.bricks.items.[INDEX].discount.oneOf.1","typeLabel":"null"}],"uniqueKey":"oneOf.2.bricks.items.[INDEX].discount","typeLabel":"object[] | null"}},"required":["brick_id"],"uniqueKey":"oneOf.2.bricks.items.[INDEX]","typeLabel":"object"},"description":"The bricks included in the subscription. Required unless `phases` is provided, in which case every brick comes from the phases.","uniqueKey":"oneOf.2.bricks","typeLabel":"object[]"},"currency":{"enum":["USD","EUR","GBP","AUD","CAD","INR"],"type":"string","x-spec-enum-id":"fde863feba7c4cf4","default":"USD","description":"Optional currency to be used for the subscription. Defaults to USD.\n\n* `USD` - United States Dollar\n* `EUR` - Euros\n* `GBP` - Great British Pound\n* `AUD` - Australian Dollar\n* `CAD` - Canadian Dollar\n* `INR` - Indian Rupee","uniqueKey":"oneOf.2.currency","typeLabel":"enum\u003cstring>"},"discount_coupons":{"type":"array","items":{"type":"string","uniqueKey":"oneOf.2.discount_coupons.items.[INDEX]","typeLabel":"string"},"description":"Discount coupon codes to apply to the subscription. Currently only supports one discount coupon - only the first one in the list will be applied.","uniqueKey":"oneOf.2.discount_coupons","typeLabel":"string[]"}},"uniqueKey":"oneOf.2","typeLabel":"SubscriptionInputEstimateMultiPhase · object"}],"uniqueKey":"","typeLabel":"SubscriptionInputEstimateSinglePhase · object | SubscriptionInputEstimateMultiPhasePerPhasePlans · object | SubscriptionInputEstimateMultiPhase · object"},"examples":{"Example":{"title":"Example","value":{"starts_at":"2023-12-25","contract_length":2,"plan_id":"3c90c3cc-0d44-4b50-8888-8dd25736052a","bricks":[{"brick_id":"3c90c3cc-0d44-4b50-8888-8dd25736052a","quantity":123,"is_unlimited":true,"discount":[{"rate":"\u003cstring>","amount":123,"renews":false}]}],"currency":"USD","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>"]}]}}},"exampleType":"generated"},"application/x-www-form-urlencoded":{"schema":{"oneOf":[{"type":"object","title":"SubscriptionInputEstimateSinglePhase","description":"Subscription estimate input serializer for generating a pricing estimate.\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.\n\nEvery phase needs a plan, so the multi-phase form splits in two: send an order-level `plan_id` (the plan for any phase that names none), or give every phase its own `plan_id`. A multi-phase payload naming no plan at all is a 400.","required":["starts_at","contract_length","billing_frequency","bricks","plan_id"],"properties":{"starts_at":{"type":"string","description":"The start date of the subscription. Required unless `phases` is provided, in which case phase 0's start date is used.","format":"date","isRequired":true,"uniqueKey":"oneOf.0.starts_at","typeLabel":"string\u003cdate>"},"contract_length":{"type":"integer","description":"The length of the contract in months. Required unless `phases` is provided, in which case it is the sum of the phase lengths.","minimum":1,"isRequired":true,"uniqueKey":"oneOf.0.contract_length","typeLabel":"integer"},"billing_frequency":{"type":"string","description":"The billing frequency. Required unless `phases` is provided, in which case each phase declares its own `billing_frequency`.\n\n* `MONTHLY` - Monthly\n* `QUARTERLY` - Quarterly\n* `SEMI_ANNUALLY` - Semi-annually\n* `ANNUALLY` - Annually\n* `ALL_UPFRONT` - All upfront","enum":["MONTHLY","QUARTERLY","SEMI_ANNUALLY","ANNUALLY","ALL_UPFRONT"],"x-spec-enum-id":"f41da4a34f13f89b","isRequired":true,"uniqueKey":"oneOf.0.billing_frequency","typeLabel":"enum\u003cstring>"},"plan_id":{"type":"string","description":"The ID of the plan. Required unless every phase declares its own `plan_id` — it is the plan for any phase that does not.","format":"uuid","isRequired":true,"uniqueKey":"oneOf.0.plan_id","typeLabel":"string\u003cuuid>"},"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.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","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.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","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.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","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"}},"uniqueKey":"oneOf.0.bricks.items.[INDEX]","typeLabel":"object"},"description":"The bricks included in the subscription. Required unless `phases` is provided, in which case every brick comes from the phases.","isRequired":true,"uniqueKey":"oneOf.0.bricks","typeLabel":"object[]"},"currency":{"enum":["USD","EUR","GBP","AUD","CAD","INR"],"type":"string","x-spec-enum-id":"fde863feba7c4cf4","default":"USD","description":"Optional currency to be used for the subscription. Defaults to USD.\n\n* `USD` - United States Dollar\n* `EUR` - Euros\n* `GBP` - Great British Pound\n* `AUD` - Australian Dollar\n* `CAD` - Canadian Dollar\n* `INR` - Indian Rupee","uniqueKey":"oneOf.0.currency","typeLabel":"enum\u003cstring>"},"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. 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 multi-phase orders. When provided, ALL phases come from this array (first element = phase 0, second = phase 1, etc.) and `starts_at`, `contract_length`, `billing_frequency` and `bricks` become optional — omit them and they are derived from the phases. `plan_id` is still required, and every brick in every phase must belong to it. When absent, the order-level fields define a single phase.","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 multi-phase orders. When provided, ALL phases come from this array (first element = phase 0, second = phase 1, etc.) and `starts_at`, `contract_length`, `billing_frequency` and `bricks` become optional — omit them and they are derived from the phases. `plan_id` is still required, and every brick in every phase must belong to it. When absent, the order-level fields define a single phase.","uniqueKey":"oneOf.0.phases.oneOf.1","typeLabel":"null"}],"uniqueKey":"oneOf.0.phases","typeLabel":"object[] | null"}},"uniqueKey":"oneOf.0","typeLabel":"SubscriptionInputEstimateSinglePhase · object"},{"type":"object","title":"SubscriptionInputEstimateMultiPhasePerPhasePlans","description":"Subscription estimate input serializer for generating a pricing estimate.\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.\n\nEvery phase needs a plan, so the multi-phase form splits in two: send an order-level `plan_id` (the plan for any phase that names none), or give every phase its own `plan_id`. A multi-phase payload naming no plan at all is a 400.","required":["phases"],"properties":{"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":["plan_id","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"},"plan_id":{"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","isRequired":true,"uniqueKey":"oneOf.1.phases.items.[INDEX].plan_id","typeLabel":"string\u003cuuid>"},"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>"},"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 multi-phase orders. When provided, ALL phases come from this array (first element = phase 0, second = phase 1, etc.) and `starts_at`, `contract_length`, `billing_frequency` and `bricks` become optional — omit them and they are derived from the phases. `plan_id` is still required, and every brick in every phase must belong to it. When absent, the order-level fields define a single phase.","minItems":1,"isRequired":true,"uniqueKey":"oneOf.1.phases","typeLabel":"object[]"},"starts_at":{"type":"string","format":"date","description":"The start date of the subscription. Required unless `phases` is provided, in which case phase 0's start date is used.","uniqueKey":"oneOf.1.starts_at","typeLabel":"string\u003cdate>"},"contract_length":{"type":"integer","minimum":1,"description":"The length of the contract in months. Required unless `phases` is provided, in which case it is the sum of the phase lengths.","uniqueKey":"oneOf.1.contract_length","typeLabel":"integer"},"billing_frequency":{"enum":["MONTHLY","QUARTERLY","SEMI_ANNUALLY","ANNUALLY","ALL_UPFRONT"],"type":"string","x-spec-enum-id":"f41da4a34f13f89b","description":"The billing frequency. Required unless `phases` is provided, in which case each phase declares its own `billing_frequency`.\n\n* `MONTHLY` - Monthly\n* `QUARTERLY` - Quarterly\n* `SEMI_ANNUALLY` - Semi-annually\n* `ANNUALLY` - Annually\n* `ALL_UPFRONT` - All upfront","uniqueKey":"oneOf.1.billing_frequency","typeLabel":"enum\u003cstring>"},"plan_id":{"type":"string","format":"uuid","description":"The ID of the plan. Required unless every phase declares its own `plan_id` — it is the plan for any phase that does not.","uniqueKey":"oneOf.1.plan_id","typeLabel":"string\u003cuuid>"},"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 the subscription. Required unless `phases` is provided, in which case every brick comes from the phases.","uniqueKey":"oneOf.1.bricks","typeLabel":"object[]"},"currency":{"enum":["USD","EUR","GBP","AUD","CAD","INR"],"type":"string","x-spec-enum-id":"fde863feba7c4cf4","default":"USD","description":"Optional currency to be used for the subscription. Defaults to USD.\n\n* `USD` - United States Dollar\n* `EUR` - Euros\n* `GBP` - Great British Pound\n* `AUD` - Australian Dollar\n* `CAD` - Canadian Dollar\n* `INR` - Indian Rupee","uniqueKey":"oneOf.1.currency","typeLabel":"enum\u003cstring>"},"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. Currently only supports one discount coupon - only the first one in the list will be applied.","uniqueKey":"oneOf.1.discount_coupons","typeLabel":"string[]"}},"uniqueKey":"oneOf.1","typeLabel":"SubscriptionInputEstimateMultiPhasePerPhasePlans · object"},{"type":"object","title":"SubscriptionInputEstimateMultiPhase","description":"Subscription estimate input serializer for generating a pricing estimate.\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.\n\nEvery phase needs a plan, so the multi-phase form splits in two: send an order-level `plan_id` (the plan for any phase that names none), or give every phase its own `plan_id`. A multi-phase payload naming no plan at all is a 400.","required":["phases","plan_id"],"properties":{"plan_id":{"type":"string","description":"The ID of the plan. Required unless every phase declares its own `plan_id` — it is the plan for any phase that does not.","format":"uuid","isRequired":true,"uniqueKey":"oneOf.2.plan_id","typeLabel":"string\u003cuuid>"},"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.2.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.2.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.2.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.2.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.2.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.2.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.2.phases.items.[INDEX].bricks.items.[INDEX].discount.oneOf.0.items.[INDEX].renews","typeLabel":"boolean"}},"uniqueKey":"oneOf.2.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.2.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.2.phases.items.[INDEX].bricks.items.[INDEX].discount.oneOf.1","typeLabel":"null"}],"uniqueKey":"oneOf.2.phases.items.[INDEX].bricks.items.[INDEX].discount","typeLabel":"object[] | null"}},"uniqueKey":"oneOf.2.phases.items.[INDEX].bricks.items.[INDEX]","typeLabel":"object"},"description":"The bricks included in this phase.","isRequired":true,"uniqueKey":"oneOf.2.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.2.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.2.phases.items.[INDEX].starts_at.oneOf.1","typeLabel":"null"}],"uniqueKey":"oneOf.2.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.2.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.2.phases.items.[INDEX].contract_length.oneOf.1","typeLabel":"null"}],"uniqueKey":"oneOf.2.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.2.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.2.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.2.phases.items.[INDEX].plan_id.oneOf.1","typeLabel":"null"}],"uniqueKey":"oneOf.2.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.2.phases.items.[INDEX].payment_terms","typeLabel":"integer"},"discount_coupons":{"type":"array","items":{"type":"string","uniqueKey":"oneOf.2.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.2.phases.items.[INDEX].discount_coupons","typeLabel":"string[]"}},"uniqueKey":"oneOf.2.phases.items.[INDEX]","typeLabel":"object"},"description":"Optional list of phases for multi-phase orders. When provided, ALL phases come from this array (first element = phase 0, second = phase 1, etc.) and `starts_at`, `contract_length`, `billing_frequency` and `bricks` become optional — omit them and they are derived from the phases. `plan_id` is still required, and every brick in every phase must belong to it. When absent, the order-level fields define a single phase.","minItems":1,"isRequired":true,"uniqueKey":"oneOf.2.phases","typeLabel":"object[]"},"starts_at":{"type":"string","format":"date","description":"The start date of the subscription. Required unless `phases` is provided, in which case phase 0's start date is used.","uniqueKey":"oneOf.2.starts_at","typeLabel":"string\u003cdate>"},"contract_length":{"type":"integer","minimum":1,"description":"The length of the contract in months. Required unless `phases` is provided, in which case it is the sum of the phase lengths.","uniqueKey":"oneOf.2.contract_length","typeLabel":"integer"},"billing_frequency":{"enum":["MONTHLY","QUARTERLY","SEMI_ANNUALLY","ANNUALLY","ALL_UPFRONT"],"type":"string","x-spec-enum-id":"f41da4a34f13f89b","description":"The billing frequency. Required unless `phases` is provided, in which case each phase declares its own `billing_frequency`.\n\n* `MONTHLY` - Monthly\n* `QUARTERLY` - Quarterly\n* `SEMI_ANNUALLY` - Semi-annually\n* `ANNUALLY` - Annually\n* `ALL_UPFRONT` - All upfront","uniqueKey":"oneOf.2.billing_frequency","typeLabel":"enum\u003cstring>"},"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.2.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.2.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.2.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.2.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.2.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.2.bricks.items.[INDEX].discount.oneOf.0.items.[INDEX].renews","typeLabel":"boolean"}},"uniqueKey":"oneOf.2.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.2.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.2.bricks.items.[INDEX].discount.oneOf.1","typeLabel":"null"}],"uniqueKey":"oneOf.2.bricks.items.[INDEX].discount","typeLabel":"object[] | null"}},"required":["brick_id"],"uniqueKey":"oneOf.2.bricks.items.[INDEX]","typeLabel":"object"},"description":"The bricks included in the subscription. Required unless `phases` is provided, in which case every brick comes from the phases.","uniqueKey":"oneOf.2.bricks","typeLabel":"object[]"},"currency":{"enum":["USD","EUR","GBP","AUD","CAD","INR"],"type":"string","x-spec-enum-id":"fde863feba7c4cf4","default":"USD","description":"Optional currency to be used for the subscription. Defaults to USD.\n\n* `USD` - United States Dollar\n* `EUR` - Euros\n* `GBP` - Great British Pound\n* `AUD` - Australian Dollar\n* `CAD` - Canadian Dollar\n* `INR` - Indian Rupee","uniqueKey":"oneOf.2.currency","typeLabel":"enum\u003cstring>"},"discount_coupons":{"type":"array","items":{"type":"string","uniqueKey":"oneOf.2.discount_coupons.items.[INDEX]","typeLabel":"string"},"description":"Discount coupon codes to apply to the subscription. Currently only supports one discount coupon - only the first one in the list will be applied.","uniqueKey":"oneOf.2.discount_coupons","typeLabel":"string[]"}},"uniqueKey":"oneOf.2","typeLabel":"SubscriptionInputEstimateMultiPhase · object"}],"uniqueKey":"","typeLabel":"SubscriptionInputEstimateSinglePhase · object | SubscriptionInputEstimateMultiPhasePerPhasePlans · object | SubscriptionInputEstimateMultiPhase · object"},"examples":{"Example":{"title":"Example","value":{"starts_at":"2023-12-25","contract_length":2,"plan_id":"3c90c3cc-0d44-4b50-8888-8dd25736052a","bricks":[{"brick_id":"3c90c3cc-0d44-4b50-8888-8dd25736052a","quantity":123,"is_unlimited":true,"discount":[{"rate":"\u003cstring>","amount":123,"renews":false}]}],"currency":"USD","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>"]}]}}},"exampleType":"generated"},"multipart/form-data":{"schema":{"oneOf":[{"type":"object","title":"SubscriptionInputEstimateSinglePhase","description":"Subscription estimate input serializer for generating a pricing estimate.\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.\n\nEvery phase needs a plan, so the multi-phase form splits in two: send an order-level `plan_id` (the plan for any phase that names none), or give every phase its own `plan_id`. A multi-phase payload naming no plan at all is a 400.","required":["starts_at","contract_length","billing_frequency","bricks","plan_id"],"properties":{"starts_at":{"type":"string","description":"The start date of the subscription. Required unless `phases` is provided, in which case phase 0's start date is used.","format":"date","isRequired":true,"uniqueKey":"oneOf.0.starts_at","typeLabel":"string\u003cdate>"},"contract_length":{"type":"integer","description":"The length of the contract in months. Required unless `phases` is provided, in which case it is the sum of the phase lengths.","minimum":1,"isRequired":true,"uniqueKey":"oneOf.0.contract_length","typeLabel":"integer"},"billing_frequency":{"type":"string","description":"The billing frequency. Required unless `phases` is provided, in which case each phase declares its own `billing_frequency`.\n\n* `MONTHLY` - Monthly\n* `QUARTERLY` - Quarterly\n* `SEMI_ANNUALLY` - Semi-annually\n* `ANNUALLY` - Annually\n* `ALL_UPFRONT` - All upfront","enum":["MONTHLY","QUARTERLY","SEMI_ANNUALLY","ANNUALLY","ALL_UPFRONT"],"x-spec-enum-id":"f41da4a34f13f89b","isRequired":true,"uniqueKey":"oneOf.0.billing_frequency","typeLabel":"enum\u003cstring>"},"plan_id":{"type":"string","description":"The ID of the plan. Required unless every phase declares its own `plan_id` — it is the plan for any phase that does not.","format":"uuid","isRequired":true,"uniqueKey":"oneOf.0.plan_id","typeLabel":"string\u003cuuid>"},"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.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","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.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","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.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","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"}},"uniqueKey":"oneOf.0.bricks.items.[INDEX]","typeLabel":"object"},"description":"The bricks included in the subscription. Required unless `phases` is provided, in which case every brick comes from the phases.","isRequired":true,"uniqueKey":"oneOf.0.bricks","typeLabel":"object[]"},"currency":{"enum":["USD","EUR","GBP","AUD","CAD","INR"],"type":"string","x-spec-enum-id":"fde863feba7c4cf4","default":"USD","description":"Optional currency to be used for the subscription. Defaults to USD.\n\n* `USD` - United States Dollar\n* `EUR` - Euros\n* `GBP` - Great British Pound\n* `AUD` - Australian Dollar\n* `CAD` - Canadian Dollar\n* `INR` - Indian Rupee","uniqueKey":"oneOf.0.currency","typeLabel":"enum\u003cstring>"},"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. 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 multi-phase orders. When provided, ALL phases come from this array (first element = phase 0, second = phase 1, etc.) and `starts_at`, `contract_length`, `billing_frequency` and `bricks` become optional — omit them and they are derived from the phases. `plan_id` is still required, and every brick in every phase must belong to it. When absent, the order-level fields define a single phase.","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 multi-phase orders. When provided, ALL phases come from this array (first element = phase 0, second = phase 1, etc.) and `starts_at`, `contract_length`, `billing_frequency` and `bricks` become optional — omit them and they are derived from the phases. `plan_id` is still required, and every brick in every phase must belong to it. When absent, the order-level fields define a single phase.","uniqueKey":"oneOf.0.phases.oneOf.1","typeLabel":"null"}],"uniqueKey":"oneOf.0.phases","typeLabel":"object[] | null"}},"uniqueKey":"oneOf.0","typeLabel":"SubscriptionInputEstimateSinglePhase · object"},{"type":"object","title":"SubscriptionInputEstimateMultiPhasePerPhasePlans","description":"Subscription estimate input serializer for generating a pricing estimate.\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.\n\nEvery phase needs a plan, so the multi-phase form splits in two: send an order-level `plan_id` (the plan for any phase that names none), or give every phase its own `plan_id`. A multi-phase payload naming no plan at all is a 400.","required":["phases"],"properties":{"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":["plan_id","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"},"plan_id":{"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","isRequired":true,"uniqueKey":"oneOf.1.phases.items.[INDEX].plan_id","typeLabel":"string\u003cuuid>"},"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>"},"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 multi-phase orders. When provided, ALL phases come from this array (first element = phase 0, second = phase 1, etc.) and `starts_at`, `contract_length`, `billing_frequency` and `bricks` become optional — omit them and they are derived from the phases. `plan_id` is still required, and every brick in every phase must belong to it. When absent, the order-level fields define a single phase.","minItems":1,"isRequired":true,"uniqueKey":"oneOf.1.phases","typeLabel":"object[]"},"starts_at":{"type":"string","format":"date","description":"The start date of the subscription. Required unless `phases` is provided, in which case phase 0's start date is used.","uniqueKey":"oneOf.1.starts_at","typeLabel":"string\u003cdate>"},"contract_length":{"type":"integer","minimum":1,"description":"The length of the contract in months. Required unless `phases` is provided, in which case it is the sum of the phase lengths.","uniqueKey":"oneOf.1.contract_length","typeLabel":"integer"},"billing_frequency":{"enum":["MONTHLY","QUARTERLY","SEMI_ANNUALLY","ANNUALLY","ALL_UPFRONT"],"type":"string","x-spec-enum-id":"f41da4a34f13f89b","description":"The billing frequency. Required unless `phases` is provided, in which case each phase declares its own `billing_frequency`.\n\n* `MONTHLY` - Monthly\n* `QUARTERLY` - Quarterly\n* `SEMI_ANNUALLY` - Semi-annually\n* `ANNUALLY` - Annually\n* `ALL_UPFRONT` - All upfront","uniqueKey":"oneOf.1.billing_frequency","typeLabel":"enum\u003cstring>"},"plan_id":{"type":"string","format":"uuid","description":"The ID of the plan. Required unless every phase declares its own `plan_id` — it is the plan for any phase that does not.","uniqueKey":"oneOf.1.plan_id","typeLabel":"string\u003cuuid>"},"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 the subscription. Required unless `phases` is provided, in which case every brick comes from the phases.","uniqueKey":"oneOf.1.bricks","typeLabel":"object[]"},"currency":{"enum":["USD","EUR","GBP","AUD","CAD","INR"],"type":"string","x-spec-enum-id":"fde863feba7c4cf4","default":"USD","description":"Optional currency to be used for the subscription. Defaults to USD.\n\n* `USD` - United States Dollar\n* `EUR` - Euros\n* `GBP` - Great British Pound\n* `AUD` - Australian Dollar\n* `CAD` - Canadian Dollar\n* `INR` - Indian Rupee","uniqueKey":"oneOf.1.currency","typeLabel":"enum\u003cstring>"},"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. Currently only supports one discount coupon - only the first one in the list will be applied.","uniqueKey":"oneOf.1.discount_coupons","typeLabel":"string[]"}},"uniqueKey":"oneOf.1","typeLabel":"SubscriptionInputEstimateMultiPhasePerPhasePlans · object"},{"type":"object","title":"SubscriptionInputEstimateMultiPhase","description":"Subscription estimate input serializer for generating a pricing estimate.\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.\n\nEvery phase needs a plan, so the multi-phase form splits in two: send an order-level `plan_id` (the plan for any phase that names none), or give every phase its own `plan_id`. A multi-phase payload naming no plan at all is a 400.","required":["phases","plan_id"],"properties":{"plan_id":{"type":"string","description":"The ID of the plan. Required unless every phase declares its own `plan_id` — it is the plan for any phase that does not.","format":"uuid","isRequired":true,"uniqueKey":"oneOf.2.plan_id","typeLabel":"string\u003cuuid>"},"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.2.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.2.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.2.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.2.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.2.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.2.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.2.phases.items.[INDEX].bricks.items.[INDEX].discount.oneOf.0.items.[INDEX].renews","typeLabel":"boolean"}},"uniqueKey":"oneOf.2.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.2.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.2.phases.items.[INDEX].bricks.items.[INDEX].discount.oneOf.1","typeLabel":"null"}],"uniqueKey":"oneOf.2.phases.items.[INDEX].bricks.items.[INDEX].discount","typeLabel":"object[] | null"}},"uniqueKey":"oneOf.2.phases.items.[INDEX].bricks.items.[INDEX]","typeLabel":"object"},"description":"The bricks included in this phase.","isRequired":true,"uniqueKey":"oneOf.2.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.2.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.2.phases.items.[INDEX].starts_at.oneOf.1","typeLabel":"null"}],"uniqueKey":"oneOf.2.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.2.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.2.phases.items.[INDEX].contract_length.oneOf.1","typeLabel":"null"}],"uniqueKey":"oneOf.2.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.2.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.2.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.2.phases.items.[INDEX].plan_id.oneOf.1","typeLabel":"null"}],"uniqueKey":"oneOf.2.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.2.phases.items.[INDEX].payment_terms","typeLabel":"integer"},"discount_coupons":{"type":"array","items":{"type":"string","uniqueKey":"oneOf.2.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.2.phases.items.[INDEX].discount_coupons","typeLabel":"string[]"}},"uniqueKey":"oneOf.2.phases.items.[INDEX]","typeLabel":"object"},"description":"Optional list of phases for multi-phase orders. When provided, ALL phases come from this array (first element = phase 0, second = phase 1, etc.) and `starts_at`, `contract_length`, `billing_frequency` and `bricks` become optional — omit them and they are derived from the phases. `plan_id` is still required, and every brick in every phase must belong to it. When absent, the order-level fields define a single phase.","minItems":1,"isRequired":true,"uniqueKey":"oneOf.2.phases","typeLabel":"object[]"},"starts_at":{"type":"string","format":"date","description":"The start date of the subscription. Required unless `phases` is provided, in which case phase 0's start date is used.","uniqueKey":"oneOf.2.starts_at","typeLabel":"string\u003cdate>"},"contract_length":{"type":"integer","minimum":1,"description":"The length of the contract in months. Required unless `phases` is provided, in which case it is the sum of the phase lengths.","uniqueKey":"oneOf.2.contract_length","typeLabel":"integer"},"billing_frequency":{"enum":["MONTHLY","QUARTERLY","SEMI_ANNUALLY","ANNUALLY","ALL_UPFRONT"],"type":"string","x-spec-enum-id":"f41da4a34f13f89b","description":"The billing frequency. Required unless `phases` is provided, in which case each phase declares its own `billing_frequency`.\n\n* `MONTHLY` - Monthly\n* `QUARTERLY` - Quarterly\n* `SEMI_ANNUALLY` - Semi-annually\n* `ANNUALLY` - Annually\n* `ALL_UPFRONT` - All upfront","uniqueKey":"oneOf.2.billing_frequency","typeLabel":"enum\u003cstring>"},"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.2.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.2.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.2.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.2.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.2.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.2.bricks.items.[INDEX].discount.oneOf.0.items.[INDEX].renews","typeLabel":"boolean"}},"uniqueKey":"oneOf.2.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.2.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.2.bricks.items.[INDEX].discount.oneOf.1","typeLabel":"null"}],"uniqueKey":"oneOf.2.bricks.items.[INDEX].discount","typeLabel":"object[] | null"}},"required":["brick_id"],"uniqueKey":"oneOf.2.bricks.items.[INDEX]","typeLabel":"object"},"description":"The bricks included in the subscription. Required unless `phases` is provided, in which case every brick comes from the phases.","uniqueKey":"oneOf.2.bricks","typeLabel":"object[]"},"currency":{"enum":["USD","EUR","GBP","AUD","CAD","INR"],"type":"string","x-spec-enum-id":"fde863feba7c4cf4","default":"USD","description":"Optional currency to be used for the subscription. Defaults to USD.\n\n* `USD` - United States Dollar\n* `EUR` - Euros\n* `GBP` - Great British Pound\n* `AUD` - Australian Dollar\n* `CAD` - Canadian Dollar\n* `INR` - Indian Rupee","uniqueKey":"oneOf.2.currency","typeLabel":"enum\u003cstring>"},"discount_coupons":{"type":"array","items":{"type":"string","uniqueKey":"oneOf.2.discount_coupons.items.[INDEX]","typeLabel":"string"},"description":"Discount coupon codes to apply to the subscription. Currently only supports one discount coupon - only the first one in the list will be applied.","uniqueKey":"oneOf.2.discount_coupons","typeLabel":"string[]"}},"uniqueKey":"oneOf.2","typeLabel":"SubscriptionInputEstimateMultiPhase · object"}],"uniqueKey":"","typeLabel":"SubscriptionInputEstimateSinglePhase · object | SubscriptionInputEstimateMultiPhasePerPhasePlans · object | SubscriptionInputEstimateMultiPhase · object"},"examples":{"Example":{"title":"Example","value":{"starts_at":"2023-12-25","contract_length":2,"plan_id":"3c90c3cc-0d44-4b50-8888-8dd25736052a","bricks":[{"brick_id":"3c90c3cc-0d44-4b50-8888-8dd25736052a","quantity":123,"is_unlimited":true,"discount":[{"rate":"\u003cstring>","amount":123,"renews":false}]}],"currency":"USD","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>"]}]}}},"exampleType":"generated"}},"required":true,"exampleType":"generated"},"responses":{"336e9e12-0ee2-4058-9859-ba3cfeaf661e":{"content":{"application/json":{"schema":{"type":"object","description":"Subscription /estimate output serializer from OrderPricing\n\nSAL-6964: the commercial payload lives at exactly one altitude. A\nmulti-phase order carries it per phase and omits the order-level copies —\nthe same brick appears once per phase and may differ in each, so a single\nflattened set can only misrepresent it. A single-phase order keeps the\norder-level fields and omits ``phases`` entirely, since a lone phase\nrestates the order. See ``PHASE_OWNED_FIELDS``.","properties":{"ends_at":{"type":"string","format":"date","description":"The end date of the subscription","isRequired":true,"uniqueKey":"ends_at","typeLabel":"string\u003cdate>"},"sub_total":{"type":"integer","description":"Subtotal before taxes and discounts","isRequired":true,"uniqueKey":"sub_total","typeLabel":"integer"},"grand_total":{"type":"integer","description":"Final total after taxes and discounts","isRequired":true,"uniqueKey":"grand_total","typeLabel":"integer"},"line_items":{"type":"array","items":{"type":"object","description":"Line item serializer for a subscription estimate","properties":{"quantity":{"oneOf":[{"type":"integer","description":"The quantity of the brick","isRequired":true,"uniqueKey":"line_items.items.[INDEX].quantity.oneOf.0","typeLabel":"integer"},{"type":"number","description":"The quantity of the brick","format":"double","isRequired":true,"uniqueKey":"line_items.items.[INDEX].quantity.oneOf.1","typeLabel":"number\u003cdouble>"}],"isRequired":true,"uniqueKey":"line_items.items.[INDEX].quantity","typeLabel":"integer | number\u003cdouble>"},"brick_id":{"type":"string","format":"uuid","description":"The brick id","isRequired":true,"uniqueKey":"line_items.items.[INDEX].brick_id","typeLabel":"string\u003cuuid>"},"is_unlimited":{"type":"boolean","readOnly":true,"default":false,"description":"Whether this line was sold with an uncapped entitlement. When true, `quantity` is the pricing basis the line's price was calculated from, not a limit on what the buyer may use — a provisioning system should grant unlimited access rather than `quantity` units.","isRequired":true,"uniqueKey":"line_items.items.[INDEX].is_unlimited","typeLabel":"boolean"},"brick_name":{"type":"string","description":"The name of the brick","isRequired":true,"uniqueKey":"line_items.items.[INDEX].brick_name","typeLabel":"string"},"brick_code":{"oneOf":[{"type":"string","readOnly":true,"description":"The internal SKU code you set on the brick. Unlike `brick_id` it stays the same across environments and when a brick is recreated, so use it to map bricks to your own features. Null when the brick has no code.","isRequired":true,"uniqueKey":"line_items.items.[INDEX].brick_code.oneOf.0","typeLabel":"string"},{"type":"null","readOnly":true,"description":"The internal SKU code you set on the brick. Unlike `brick_id` it stays the same across environments and when a brick is recreated, so use it to map bricks to your own features. Null when the brick has no code.","isRequired":true,"uniqueKey":"line_items.items.[INDEX].brick_code.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"line_items.items.[INDEX].brick_code","typeLabel":"string | null"},"sub_total":{"type":"integer","description":"Subtotal for the line item before taxes and discounts","isRequired":true,"uniqueKey":"line_items.items.[INDEX].sub_total","typeLabel":"integer"},"plan_id":{"type":"string","readOnly":true,"description":"ID of the plan this line item belongs to","isRequired":true,"uniqueKey":"line_items.items.[INDEX].plan_id","typeLabel":"string"},"plan_name":{"type":"string","description":"Name of the plan this line item belongs to","isRequired":true,"uniqueKey":"line_items.items.[INDEX].plan_name","typeLabel":"string"},"grand_total":{"type":"string","readOnly":true,"description":"Final total for the line item after taxes and discounts","isRequired":true,"uniqueKey":"line_items.items.[INDEX].grand_total","typeLabel":"string"},"grand_total_details":{"type":"string","readOnly":true,"description":"Breakdown containing total discount amounts for the line item","isRequired":true,"uniqueKey":"line_items.items.[INDEX].grand_total_details","typeLabel":"string"},"tiers_breakdown":{"type":"array","items":{"type":"object","description":"Tier breakdown serializer for line item tiers","properties":{"quantity":{"type":"number","format":"double","maximum":100000000000000,"minimum":-100000000000000,"exclusiveMaximum":true,"exclusiveMinimum":true,"description":"Number of units in this tier","isRequired":true,"uniqueKey":"line_items.items.[INDEX].tiers_breakdown.items.[INDEX].quantity","typeLabel":"number\u003cdouble>"},"unit_price":{"type":"string","format":"decimal","pattern":"^-?\\d{0,14}(?:\\.\\d{0,6})?$","description":"Unit price for this tier","isRequired":true,"uniqueKey":"line_items.items.[INDEX].tiers_breakdown.items.[INDEX].unit_price","typeLabel":"string\u003cdecimal>"},"sub_total":{"type":"string","format":"decimal","pattern":"^-?\\d{0,18}(?:\\.\\d{0,2})?$","description":"Subtotal for this tier","isRequired":true,"uniqueKey":"line_items.items.[INDEX].tiers_breakdown.items.[INDEX].sub_total","typeLabel":"string\u003cdecimal>"},"duration_text":{"type":"string","description":"Duration text for frontend display","isRequired":true,"uniqueKey":"line_items.items.[INDEX].tiers_breakdown.items.[INDEX].duration_text","typeLabel":"string"}},"required":["duration_text","quantity","sub_total","unit_price"],"uniqueKey":"line_items.items.[INDEX].tiers_breakdown.items.[INDEX]","typeLabel":"object"},"readOnly":true,"description":"Tiers breakdown for the line item","isRequired":true,"uniqueKey":"line_items.items.[INDEX].tiers_breakdown","typeLabel":"object[]"},"pre_commitment_schedule":{"oneOf":[{"type":"string","readOnly":true,"description":"The pre-commitment schedule for usage-based line items","isRequired":true,"uniqueKey":"line_items.items.[INDEX].pre_commitment_schedule.oneOf.0","typeLabel":"string"},{"type":"null","readOnly":true,"description":"The pre-commitment schedule for usage-based line items","isRequired":true,"uniqueKey":"line_items.items.[INDEX].pre_commitment_schedule.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"line_items.items.[INDEX].pre_commitment_schedule","typeLabel":"string | null"},"discount":{"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":"line_items.items.[INDEX].discount.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":"line_items.items.[INDEX].discount.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":"line_items.items.[INDEX].discount.items.[INDEX].renews","typeLabel":"boolean"}},"uniqueKey":"line_items.items.[INDEX].discount.items.[INDEX]","typeLabel":"object"},"readOnly":true,"description":"Per-brick discount(s) in the same shape accepted on input, so they can be read off a subscription and carried forward explicitly on upgrade, recast, or renewal. Empty when the line item has no discount.","isRequired":true,"uniqueKey":"line_items.items.[INDEX].discount","typeLabel":"object[]"}},"required":["brick_code","brick_id","brick_name","discount","grand_total","grand_total_details","is_unlimited","plan_id","plan_name","pre_commitment_schedule","quantity","sub_total","tiers_breakdown"],"uniqueKey":"line_items.items.[INDEX]","typeLabel":"object"},"description":"The line items of the subscription","isRequired":true,"uniqueKey":"line_items","typeLabel":"object[]"},"billing_schedule":{"type":"array","items":{"type":"object","description":"Billing schedule for a subscription","properties":{"starts_at":{"type":"string","readOnly":true,"description":"Start date of the billing period","isRequired":true,"uniqueKey":"billing_schedule.items.[INDEX].starts_at","typeLabel":"string"},"ends_at":{"type":"string","readOnly":true,"description":"End date of the billing period","isRequired":true,"uniqueKey":"billing_schedule.items.[INDEX].ends_at","typeLabel":"string"},"sub_total":{"type":"integer","description":"Subtotal for the billing period before taxes and discounts","isRequired":true,"uniqueKey":"billing_schedule.items.[INDEX].sub_total","typeLabel":"integer"},"grand_total":{"type":"string","readOnly":true,"description":"Final total for the billing period after taxes and discounts","isRequired":true,"uniqueKey":"billing_schedule.items.[INDEX].grand_total","typeLabel":"string"},"grand_total_details":{"type":"string","readOnly":true,"description":"Breakdown containing total discount for the billing period","isRequired":true,"uniqueKey":"billing_schedule.items.[INDEX].grand_total_details","typeLabel":"string"}},"required":["ends_at","grand_total","grand_total_details","starts_at","sub_total"],"uniqueKey":"billing_schedule.items.[INDEX]","typeLabel":"object"},"description":"The billing schedule of the subscription","isRequired":true,"uniqueKey":"billing_schedule","typeLabel":"object[]"},"grand_total_details":{"description":"Breakdown containing total discount and tax amounts","isRequired":true,"uniqueKey":"grand_total_details","typeLabel":"any"},"phases":{"type":"array","items":{"type":"object","description":"Output serializer for a single order phase.\n\nDiscounts are exposed per-brick via each brick's discount fields,\nconsistent with how the rest of the API surfaces discounts.","properties":{"phase_position":{"type":"integer","description":"Phase position (0-based).","isRequired":true,"uniqueKey":"phases.items.[INDEX].phase_position","typeLabel":"integer"},"starts_at":{"type":"string","format":"date","description":"Start date of this phase.","isRequired":true,"uniqueKey":"phases.items.[INDEX].starts_at","typeLabel":"string\u003cdate>"},"ends_at":{"type":"string","format":"date","description":"End date of this phase.","isRequired":true,"uniqueKey":"phases.items.[INDEX].ends_at","typeLabel":"string\u003cdate>"},"billing_frequency":{"oneOf":[{"enum":["MONTHLY","QUARTERLY","SEMI_ANNUALLY","ANNUALLY","ALL_UPFRONT","CUSTOM"],"type":"string","x-spec-enum-id":"5f29351b16a5547f","description":"Billing frequency for this phase.\n\n* `MONTHLY` - Monthly\n* `QUARTERLY` - Quarterly\n* `SEMI_ANNUALLY` - Semi-annually\n* `ANNUALLY` - Annually\n* `ALL_UPFRONT` - All upfront\n* `CUSTOM` - Custom","isRequired":true,"uniqueKey":"phases.items.[INDEX].billing_frequency.oneOf.0","typeLabel":"enum\u003cstring>"},{"enum":["MONTHLY","QUARTERLY","SEMI_ANNUALLY","ANNUALLY","ALL_UPFRONT","CUSTOM"],"type":"null","x-spec-enum-id":"5f29351b16a5547f","description":"Billing frequency for this phase.\n\n* `MONTHLY` - Monthly\n* `QUARTERLY` - Quarterly\n* `SEMI_ANNUALLY` - Semi-annually\n* `ANNUALLY` - Annually\n* `ALL_UPFRONT` - All upfront\n* `CUSTOM` - Custom","isRequired":true,"uniqueKey":"phases.items.[INDEX].billing_frequency.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"phases.items.[INDEX].billing_frequency","typeLabel":"enum\u003cstring> | null"},"payment_terms":{"oneOf":[{"type":"integer","description":"Payment terms in days for this phase.","isRequired":true,"uniqueKey":"phases.items.[INDEX].payment_terms.oneOf.0","typeLabel":"integer"},{"type":"null","description":"Payment terms in days for this phase.","isRequired":true,"uniqueKey":"phases.items.[INDEX].payment_terms.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"phases.items.[INDEX].payment_terms","typeLabel":"integer | null"},"sub_total":{"oneOf":[{"type":"integer","description":"Subtotal before taxes and discounts for this phase.","isRequired":true,"uniqueKey":"phases.items.[INDEX].sub_total.oneOf.0","typeLabel":"integer"},{"type":"null","description":"Subtotal before taxes and discounts for this phase.","isRequired":true,"uniqueKey":"phases.items.[INDEX].sub_total.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"phases.items.[INDEX].sub_total","typeLabel":"integer | null"},"grand_total":{"oneOf":[{"type":"integer","description":"Final total after taxes and discounts for this phase.","isRequired":true,"uniqueKey":"phases.items.[INDEX].grand_total.oneOf.0","typeLabel":"integer"},{"type":"null","description":"Final total after taxes and discounts for this phase.","isRequired":true,"uniqueKey":"phases.items.[INDEX].grand_total.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"phases.items.[INDEX].grand_total","typeLabel":"integer | null"},"line_items":{"type":"array","items":{"type":"object","description":"Line item serializer for a subscription estimate","properties":{"quantity":{"oneOf":[{"type":"integer","description":"The quantity of the brick","isRequired":true,"uniqueKey":"phases.items.[INDEX].line_items.items.[INDEX].quantity.oneOf.0","typeLabel":"integer"},{"type":"number","description":"The quantity of the brick","format":"double","isRequired":true,"uniqueKey":"phases.items.[INDEX].line_items.items.[INDEX].quantity.oneOf.1","typeLabel":"number\u003cdouble>"}],"isRequired":true,"uniqueKey":"phases.items.[INDEX].line_items.items.[INDEX].quantity","typeLabel":"integer | number\u003cdouble>"},"brick_id":{"type":"string","format":"uuid","description":"The brick id","isRequired":true,"uniqueKey":"phases.items.[INDEX].line_items.items.[INDEX].brick_id","typeLabel":"string\u003cuuid>"},"is_unlimited":{"type":"boolean","readOnly":true,"default":false,"description":"Whether this line was sold with an uncapped entitlement. When true, `quantity` is the pricing basis the line's price was calculated from, not a limit on what the buyer may use — a provisioning system should grant unlimited access rather than `quantity` units.","isRequired":true,"uniqueKey":"phases.items.[INDEX].line_items.items.[INDEX].is_unlimited","typeLabel":"boolean"},"brick_name":{"type":"string","description":"The name of the brick","isRequired":true,"uniqueKey":"phases.items.[INDEX].line_items.items.[INDEX].brick_name","typeLabel":"string"},"brick_code":{"oneOf":[{"type":"string","readOnly":true,"description":"The internal SKU code you set on the brick. Unlike `brick_id` it stays the same across environments and when a brick is recreated, so use it to map bricks to your own features. Null when the brick has no code.","isRequired":true,"uniqueKey":"phases.items.[INDEX].line_items.items.[INDEX].brick_code.oneOf.0","typeLabel":"string"},{"type":"null","readOnly":true,"description":"The internal SKU code you set on the brick. Unlike `brick_id` it stays the same across environments and when a brick is recreated, so use it to map bricks to your own features. Null when the brick has no code.","isRequired":true,"uniqueKey":"phases.items.[INDEX].line_items.items.[INDEX].brick_code.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"phases.items.[INDEX].line_items.items.[INDEX].brick_code","typeLabel":"string | null"},"sub_total":{"type":"integer","description":"Subtotal for the line item before taxes and discounts","isRequired":true,"uniqueKey":"phases.items.[INDEX].line_items.items.[INDEX].sub_total","typeLabel":"integer"},"plan_id":{"type":"string","readOnly":true,"description":"ID of the plan this line item belongs to","isRequired":true,"uniqueKey":"phases.items.[INDEX].line_items.items.[INDEX].plan_id","typeLabel":"string"},"plan_name":{"type":"string","description":"Name of the plan this line item belongs to","isRequired":true,"uniqueKey":"phases.items.[INDEX].line_items.items.[INDEX].plan_name","typeLabel":"string"},"grand_total":{"type":"string","readOnly":true,"description":"Final total for the line item after taxes and discounts","isRequired":true,"uniqueKey":"phases.items.[INDEX].line_items.items.[INDEX].grand_total","typeLabel":"string"},"grand_total_details":{"type":"string","readOnly":true,"description":"Breakdown containing total discount amounts for the line item","isRequired":true,"uniqueKey":"phases.items.[INDEX].line_items.items.[INDEX].grand_total_details","typeLabel":"string"},"tiers_breakdown":{"type":"array","items":{"type":"object","description":"Tier breakdown serializer for line item tiers","properties":{"quantity":{"type":"number","format":"double","maximum":100000000000000,"minimum":-100000000000000,"exclusiveMaximum":true,"exclusiveMinimum":true,"description":"Number of units in this tier","isRequired":true,"uniqueKey":"phases.items.[INDEX].line_items.items.[INDEX].tiers_breakdown.items.[INDEX].quantity","typeLabel":"number\u003cdouble>"},"unit_price":{"type":"string","format":"decimal","pattern":"^-?\\d{0,14}(?:\\.\\d{0,6})?$","description":"Unit price for this tier","isRequired":true,"uniqueKey":"phases.items.[INDEX].line_items.items.[INDEX].tiers_breakdown.items.[INDEX].unit_price","typeLabel":"string\u003cdecimal>"},"sub_total":{"type":"string","format":"decimal","pattern":"^-?\\d{0,18}(?:\\.\\d{0,2})?$","description":"Subtotal for this tier","isRequired":true,"uniqueKey":"phases.items.[INDEX].line_items.items.[INDEX].tiers_breakdown.items.[INDEX].sub_total","typeLabel":"string\u003cdecimal>"},"duration_text":{"type":"string","description":"Duration text for frontend display","isRequired":true,"uniqueKey":"phases.items.[INDEX].line_items.items.[INDEX].tiers_breakdown.items.[INDEX].duration_text","typeLabel":"string"}},"required":["duration_text","quantity","sub_total","unit_price"],"uniqueKey":"phases.items.[INDEX].line_items.items.[INDEX].tiers_breakdown.items.[INDEX]","typeLabel":"object"},"readOnly":true,"description":"Tiers breakdown for the line item","isRequired":true,"uniqueKey":"phases.items.[INDEX].line_items.items.[INDEX].tiers_breakdown","typeLabel":"object[]"},"pre_commitment_schedule":{"oneOf":[{"type":"string","readOnly":true,"description":"The pre-commitment schedule for usage-based line items","isRequired":true,"uniqueKey":"phases.items.[INDEX].line_items.items.[INDEX].pre_commitment_schedule.oneOf.0","typeLabel":"string"},{"type":"null","readOnly":true,"description":"The pre-commitment schedule for usage-based line items","isRequired":true,"uniqueKey":"phases.items.[INDEX].line_items.items.[INDEX].pre_commitment_schedule.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"phases.items.[INDEX].line_items.items.[INDEX].pre_commitment_schedule","typeLabel":"string | null"},"discount":{"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":"phases.items.[INDEX].line_items.items.[INDEX].discount.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":"phases.items.[INDEX].line_items.items.[INDEX].discount.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":"phases.items.[INDEX].line_items.items.[INDEX].discount.items.[INDEX].renews","typeLabel":"boolean"}},"uniqueKey":"phases.items.[INDEX].line_items.items.[INDEX].discount.items.[INDEX]","typeLabel":"object"},"readOnly":true,"description":"Per-brick discount(s) in the same shape accepted on input, so they can be read off a subscription and carried forward explicitly on upgrade, recast, or renewal. Empty when the line item has no discount.","isRequired":true,"uniqueKey":"phases.items.[INDEX].line_items.items.[INDEX].discount","typeLabel":"object[]"}},"required":["brick_code","brick_id","brick_name","discount","grand_total","grand_total_details","is_unlimited","plan_id","plan_name","pre_commitment_schedule","quantity","sub_total","tiers_breakdown"],"uniqueKey":"phases.items.[INDEX].line_items.items.[INDEX]","typeLabel":"object"},"readOnly":true,"description":"The line items in this phase.","isRequired":true,"uniqueKey":"phases.items.[INDEX].line_items","typeLabel":"object[]"},"is_annual":{"type":"boolean","description":"Whether this phase reads the annual or the monthly unit price. Resolved from your annual rate basis, so a caller renders the rate the phase is charged rather than deriving it from the term length.","uniqueKey":"phases.items.[INDEX].is_annual","typeLabel":"boolean"},"billing_schedule":{"type":"array","items":{"type":"object","description":"Billing schedule for a subscription","properties":{"starts_at":{"type":"string","readOnly":true,"description":"Start date of the billing period","isRequired":true,"uniqueKey":"phases.items.[INDEX].billing_schedule.items.[INDEX].starts_at","typeLabel":"string"},"ends_at":{"type":"string","readOnly":true,"description":"End date of the billing period","isRequired":true,"uniqueKey":"phases.items.[INDEX].billing_schedule.items.[INDEX].ends_at","typeLabel":"string"},"sub_total":{"type":"integer","description":"Subtotal for the billing period before taxes and discounts","isRequired":true,"uniqueKey":"phases.items.[INDEX].billing_schedule.items.[INDEX].sub_total","typeLabel":"integer"},"grand_total":{"type":"string","readOnly":true,"description":"Final total for the billing period after taxes and discounts","isRequired":true,"uniqueKey":"phases.items.[INDEX].billing_schedule.items.[INDEX].grand_total","typeLabel":"string"},"grand_total_details":{"type":"string","readOnly":true,"description":"Breakdown containing total discount for the billing period","isRequired":true,"uniqueKey":"phases.items.[INDEX].billing_schedule.items.[INDEX].grand_total_details","typeLabel":"string"}},"required":["ends_at","grand_total","grand_total_details","starts_at","sub_total"],"uniqueKey":"phases.items.[INDEX].billing_schedule.items.[INDEX]","typeLabel":"object"},"description":"The billing periods falling in this phase. Phases own the billing timeline on a multi-phase order, where the order-level `billing_schedule` is omitted.","uniqueKey":"phases.items.[INDEX].billing_schedule","typeLabel":"object[]"}},"required":["billing_frequency","ends_at","grand_total","line_items","payment_terms","phase_position","starts_at","sub_total"],"uniqueKey":"phases.items.[INDEX]","typeLabel":"object"},"description":"Per-phase breakdown. Only present for multi-phase estimates.","uniqueKey":"phases","typeLabel":"object[]"}},"required":["billing_schedule","ends_at","grand_total","grand_total_details","line_items","sub_total"],"uniqueKey":"","typeLabel":"object"},"examples":{"Example":{"title":"Example","value":{"ends_at":"2023-12-25","sub_total":123,"grand_total":123,"line_items":[{"quantity":123,"brick_id":"3c90c3cc-0d44-4b50-8888-8dd25736052a","is_unlimited":false,"brick_name":"\u003cstring>","brick_code":"\u003cstring>","sub_total":123,"plan_id":"\u003cstring>","plan_name":"\u003cstring>","grand_total":"\u003cstring>","grand_total_details":"\u003cstring>","tiers_breakdown":[{"quantity":0,"unit_price":"\u003cstring>","sub_total":"\u003cstring>","duration_text":"\u003cstring>"}],"pre_commitment_schedule":"\u003cstring>","discount":[{"rate":"\u003cstring>","amount":123,"renews":false}]}],"billing_schedule":[{"starts_at":"\u003cstring>","ends_at":"\u003cstring>","sub_total":123,"grand_total":"\u003cstring>","grand_total_details":"\u003cstring>"}],"grand_total_details":"\u003cunknown>","phases":[{"phase_position":123,"starts_at":"2023-12-25","ends_at":"2023-12-25","billing_frequency":"MONTHLY","payment_terms":123,"sub_total":123,"grand_total":123,"line_items":[{"quantity":123,"brick_id":"3c90c3cc-0d44-4b50-8888-8dd25736052a","is_unlimited":false,"brick_name":"\u003cstring>","brick_code":"\u003cstring>","sub_total":123,"plan_id":"\u003cstring>","plan_name":"\u003cstring>","grand_total":"\u003cstring>","grand_total_details":"\u003cstring>","tiers_breakdown":[{"quantity":0,"unit_price":"\u003cstring>","sub_total":"\u003cstring>","duration_text":"\u003cstring>"}],"pre_commitment_schedule":"\u003cstring>","discount":[{"rate":"\u003cstring>","amount":123,"renews":false}]}],"is_annual":true,"billing_schedule":[{"starts_at":"\u003cstring>","ends_at":"\u003cstring>","sub_total":123,"grand_total":"\u003cstring>","grand_total_details":"\u003cstring>"}]}]}}},"exampleType":"generated"}},"description":"","exampleType":"generated"},"c1c3a3cc-fd0c-42b5-bc69-7942999b992b":{"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"},"8e4f54a8-c8e4-4ae0-bcc5-d8dd98e5f134":{"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":"Estimate a subscription - Salesbricks","relatedPagesConfig":{"enabled":true,"limit":3,"mode":"automatic"},"navMaps":{"firstHrefInVersion":{},"firstHrefInLanguage":{}},"lastModified":"2026-11-05T23:31:31.032Z","originalFileLocation":"api-reference/subscriptions/estimate-a-subscription.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=\"Gets a pricing estimate for a subscription including the billing schedule and grand total.\">\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=\"Estimate a subscription - Salesbricks\">\u003cmeta data-mint-head property=\"og:description\" content=\"Gets a pricing estimate for a subscription including the billing schedule and grand total.\">\u003cmeta data-mint-head property=\"og:site_name\" content=\"Salesbricks\">\u003cmeta data-mint-head property=\"og:url\" content=\"https://docs.salesbricks.com/api-reference/subscriptions/estimate-a-subscription\">\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=Subscriptions\u0026amp;title=Estimate+a+subscription\u0026amp;description=Gets+a+pricing+estimate+for+a+subscription+including+the+billing+schedule+and+grand+total.\u0026amp;theme=c38cf69ba54d28d8add3f8a9\u0026amp;signature=3c679ec94df8e63f2f1e41be609e07e51dde4e7eede10e5c487625d52f2094be\">\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=\"Estimate a subscription - Salesbricks\">\u003cmeta data-mint-head name=\"twitter:description\" content=\"Gets a pricing estimate for a subscription including the billing schedule and grand total.\">\u003cmeta data-mint-head name=\"twitter:image\" content=\"https://salesbricks.mintlify.site/_mintlify/api/og/v2?division=Subscriptions\u0026amp;title=Estimate+a+subscription\u0026amp;description=Gets+a+pricing+estimate+for+a+subscription+including+the+billing+schedule+and+grand+total.\u0026amp;theme=c38cf69ba54d28d8add3f8a9\u0026amp;signature=3c679ec94df8e63f2f1e41be609e07e51dde4e7eede10e5c487625d52f2094be\">\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/subscriptions/estimate-a-subscription\">\u003clink data-mint-head rel=\"alternate\" type=\"application/xml\" href=\"/sitemap.xml\">\u003clink data-mint-head rel=\"alternate\" type=\"text/markdown\" href=\"/api-reference/subscriptions/estimate-a-subscription.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/subscriptions/estimate-a-subscription#webpage\",\"url\":\"https://docs.salesbricks.com/api-reference/subscriptions/estimate-a-subscription\",\"name\":\"Estimate a subscription\",\"description\":\"Gets a pricing estimate for a subscription including the billing schedule and grand total.\",\"dateModified\":\"2026-11-05T23:31:31.032Z\",\"isPartOf\":{\"@id\":\"https://docs.salesbricks.com#website\"},\"breadcrumb\":{\"@id\":\"https://docs.salesbricks.com/api-reference/subscriptions/estimate-a-subscription#breadcrumb\"}},{\"@type\":\"BreadcrumbList\",\"@id\":\"https://docs.salesbricks.com/api-reference/subscriptions/estimate-a-subscription#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\":\"Subscriptions\",\"item\":\"https://docs.salesbricks.com/api-reference/subscriptions/create-a-subscription\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"Estimate a subscription\",\"item\":\"https://docs.salesbricks.com/api-reference/subscriptions/estimate-a-subscription\"}]},{\"@type\":[\"TechArticle\",\"APIReference\"],\"@id\":\"https://docs.salesbricks.com/api-reference/subscriptions/estimate-a-subscription#apireference\",\"headline\":\"Estimate a subscription\",\"name\":\"Estimate a subscription\",\"description\":\"Gets a pricing estimate for a subscription including the billing schedule and grand total.\",\"url\":\"https://docs.salesbricks.com/api-reference/subscriptions/estimate-a-subscription\",\"mainEntityOfPage\":{\"@id\":\"https://docs.salesbricks.com/api-reference/subscriptions/estimate-a-subscription#webpage\"},\"dateModified\":\"2026-11-05T23:31:31.032Z\",\"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","description":"Terminates a subscription either immediately or at a specified future date. This endpoint allows for scheduling termination, adding termination notes and an optional reason code, and specifying notification emails for termination alerts.","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","description":"Retrieves a URL for managing a subscription's billing portal.","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","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","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":"Estimate a subscription - Salesbricks","buildId":"dpl_BLQvU86QFwq3AhPofSTw6q8dGWKm","deploymentId":"dpl_BLQvU86QFwq3AhPofSTw6q8dGWKm","dynamics":["c2aa737661","2b790eda92","b0f84f53ff","a9bb46feb3"],"chunks":["OpenApiReferenceProvider-Myd8dsju.js","utils-C2HkQgW0.js","cloneDeep-izs3Hzxb.js","_Uint8Array-BVIqJ90l.js","isObjectLike-C8vmzPEN.js","isArray-Dcu1dQ5t.js","utils-8rSppmTv.js","toString-BX-iyh8G.js","isSymbol-CSH9U2Gm.js","addUniqueKeysToSchema-B6MjiCFm.js","snippetPresets-DwrSAONL.js","style-to-object-BY3JEAdk.js","v4-DIgz8zy6.js","ApiExamples-1-a5UQKQ.js","isEqual-BfaiBbcl.js","usePlaygroundInputsStore-C541m7wZ.js","shallow-CWELCZ77.js","getApiPlaygroundDisplay-CTo5Zn03.js","CodeSnippet-D--dzvnl.js","CodeSnippets-DM3cXEDh.js","Page-CxAy5y67.js","getPastedJson-C-VECgcL.js","icon-BPq2-Mg3.js","MethodPill-D9J5cUHd.js","DuplicateIcon-BqHaxUnD.js","createIcon-CIbcZHp9.js","DynamicMarkdown-BKiHAm_d.js","SectionHeading-DstQXt3H.js","axios-vUo_bRtp.js","Markdown-CpxgzsKA.js","clsx-C5EfhVm0.js","lib-DuNMoZ05.js","lib-B8HbPgcC.js","html-void-elements-mCSPHezU.js","dist-CJ9Oly2E.js","katex-YMM-FMeD.js","marked.esm-CZWythHk.js","AssistantPageLink-Mk6P3qvh.js"]}