A subscription is the deal between your business and one customer: what is billed, at which price, from when to when.
Status: DRAFT → ACTIVE ⇄ PAUSED → CANCELLED. A trial is not a status; it is a phase whose price is free.
Revisions, phases and lines. The deal is held in a revision. A revision is an ordered list of phases (each with an opening rule, a closing rule and what follows it), and each phase bills lines: one per product, pre-filled from a plan or product version (the line's origin). A line value — quantity, price, allowance, cadence, timing, track — is either stated on the phase, carried from an earlier phase, or taken from the catalogue.
Lifecycle through the API:
POST /subscriptionscreates the envelope (customer, name, currency) inDRAFTwith an empty draft revision 1.PUT /subscriptions/{id}/revisions/draftwrites the phases and lines of revision 1.POST /subscriptions/{id}/activatepublishes revision 1 and starts the subscription.- To change a running deal, open the next revision (
POST /subscriptions/{id}/revisions/cutorPOST /subscriptions/{id}/revisions/draft), edit it, and publish it withPOST /subscriptions/{id}/revisions/draft/publish. POST /subscriptions/{id}/pause,/resumeand/cancel(now, at a date, or at the end of the billing period);DELETE /subscriptions/{id}/scheduled-cancellationwithdraws a planned cancellation.
To plan a change for later instead of making it now, use the Changes operations.
List subscriptions
Cursor-paginated list with optional column filters (status, customer_id, …) and custom_fields.
Required scope: subscription.read (Read subscriptions).
query Parameters
created_atFilter on created_at (date-time). Operators: eq, gt, gte, lt, lte — dot grammar, e.g. created_at.gt=value; a bare created_at=value means eq.
currencyFilter on currency (string). Operators: eq, in — dot grammar, e.g. currency.in=value; a bare currency=value means eq. A bare comma-separated value is in-sugar: currency=a,b means currency.in=a,b.
current_period_endFilter on current_period_end (date-time). Operators: eq, gt, gte, lt, lte — dot grammar, e.g. current_period_end.gt=value; a bare current_period_end=value means eq.
customer_idFilter on customer_id (uuid). Operators: eq, in — dot grammar, e.g. customer_id.in=value; a bare customer_id=value means eq. A bare comma-separated value is in-sugar: customer_id=a,b means customer_id.in=a,b.
plan_idFilter on plan_id (uuid). Operators: eq, in — dot grammar, e.g. plan_id.in=value; a bare plan_id=value means eq. A bare comma-separated value is in-sugar: plan_id=a,b means plan_id.in=a,b.
started_atFilter on started_at (date-time). Operators: eq, gt, gte, lt, lte — dot grammar, e.g. started_at.gt=value; a bare started_at=value means eq.
updated_atFilter on updated_at (date-time). Operators: eq, gt, gte, lt, lte — dot grammar, e.g. updated_at.gt=value; a bare updated_at=value means eq.
includeExtra data to add to the response: tags, live, revisions, actions, scheduled_cancellation, scheduled_cancellation.created_by, billing_state, display, localized. Send a comma-separated list or repeat the parameter. An unknown name is refused with 400. tags is sent without being asked until 2026-11-30; after that date it is sent only when named here. display is sent without being asked until 2026-11-30; after that date it is sent only when named here.
limitPage size. Values above the server-side cap are clamped (standard default 50, cap 200; a few document-heavy lists use larger windows). Invalid values fall back to the default.
cursorOpaque continuation token from the previous response's pagination.cursor. Omit for the first page. Cursors are stateless and do not expire, but are only valid for the list and filters that produced them.
searchCase-insensitive substring match over customer name/email, plan name and the subscription's human reference (e.g. SUB-000123)
statusFilter by status. Filterable fields (status, customer_id, plan_id, currency, started_at, current_period_end, created_at, updated_at) accept apifilter operator suffixes; custom_fields.
tagFilter by tag name (repeatable, containment semantics)
countsComma-separated countable fields (status) to include per-value counts for
sortOrdering: created_at with an optional :asc/:desc suffix (default created_at:desc). An unknown value is rejected. Cursors are bound to the ordering that issued them, so changing sort mid-walk needs a fresh first page.
Headers
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
List subscriptions › Responses
OK
Create a subscription
Creates a subscription for a customer, in DRAFT, with its first revision held as a draft. The deal is authored on that revision and starts when the revision is published.
Required scope: subscription.write (Write subscriptions).
query Parameters
includeExtra data to add to the response: tags, live, revisions, actions, scheduled_cancellation, scheduled_cancellation.created_by, billing_state, display, localized. Send a comma-separated list or repeat the parameter. An unknown name is refused with 400. tags is sent without being asked until 2026-11-30; after that date it is sent only when named here. display is sent without being asked until 2026-11-30; after that date it is sent only when named here.
Headers
Idempotency-KeyUnique key that makes this POST safe to retry: repeats with the same key replay the first response instead of re-executing. Replays are scoped to the retrying principal (same API key / user) and kept for 24 hours. Required on every POST.
Client-generated idempotency key (e.g. a UUID).
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
Create a subscription › Request Body
customer_idThe customer this subscription will bill.
currencyISO 4217 currency for the whole deal. Defaults to EUR.
nameInternal operator-facing name.
on_early_stopWhat a stop inside a billing period paid in advance does with the unused part: no_credit keeps it billed, credit_unused credits it on the closing invoice. Omit to take the plan version's default (no_credit when it states none).
Locale-keyed overrides for name, description and public_description.
Create a subscription › Responses
Created
Preview subscription prices
Prices a candidate plan and items without creating a subscription. Name a stored customer (customer_id) to price with that customer's tax, describe a buyer (buyer: country, customer_type, optional vat_id) to price with the tax that buyer would pay, or send neither for net amounts only.
Required scope: subscription.read (Read subscriptions).
Headers
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
Preview subscription prices › Request Body
plan_idas_ofDate to price for; omit to price for now. Folded to day granularity.
A buyer described instead of named, priced with the tax that buyer would pay. Mutually exclusive with customer_id.
currencycustomer_idStored customer to price for: their prices, and tax at their VAT position. Mutually exclusive with buyer.
plan_versionPublished plan version to price against; omit to price the plan's current head.
Preview subscription prices › Responses
OK
Preview subscription prices
Deprecated: use POST /subscriptions/preview instead. Removed on 2026-11-30.
Prices a candidate plan and items without creating a subscription. Name a stored customer (customer_id) to price with that customer's tax, describe a buyer (buyer: country, customer_type, optional vat_id) to price with the tax that buyer would pay, or send neither for net amounts only.
Required scope: subscription.read (Read subscriptions).
Headers
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
Preview subscription prices › Request Body
plan_idas_ofDate to price for; omit to price for now. Folded to day granularity.
A buyer described instead of named, priced with the tax that buyer would pay. Mutually exclusive with customer_id.
currencycustomer_idStored customer to price for: their prices, and tax at their VAT position. Mutually exclusive with buyer.
plan_versionPublished plan version to price against; omit to price the plan's current head.
Preview subscription prices › Responses
OK
List usage no line bills
Usage events are accepted against the product's key set, and the invoice reads usage only for a metered line of the deal over the time its phase holds. Usage the deal has no line for - a key, a product, a time no phase carries the line, a product billed by stated quantity, or a subscription the workspace does not have - is accepted (201) and billed by nothing. This returns the workspace's open findings, per subscription, product and price key, biggest first. Filled hourly by the usage_without_line_scan sweep and bounded at 100 open findings per workspace. A renegotiation that adds the missing line bills usage from its cut on; it does not reach the events counted here.
Required scope: subscription.read (Read subscriptions).
Headers
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
List usage no line bills › Responses
OK
Get a subscription
The subscription. What its live revision says now (the billing period, the next cut, MRR) is include=live; the live revision and the open draft are include=revisions; the lifecycle actions it accepts are include=actions. The promotions that apply to it are GET /subscriptions/{id}/promotions. The deal itself — phases, lines and the values in force — is the live revision: GET /subscriptions/{id}/revisions/live.
Required scope: subscription.read (Read subscriptions).
path Parameters
idSubscription UUID
query Parameters
includeExtra data to add to the response: tags, live, revisions, actions, scheduled_cancellation, scheduled_cancellation.created_by, billing_state, display, localized. Send a comma-separated list or repeat the parameter. An unknown name is refused with 400. tags is sent without being asked until 2026-11-30; after that date it is sent only when named here. display is sent without being asked until 2026-11-30; after that date it is sent only when named here. billing_state is sent without being asked until 2026-11-30; after that date it is sent only when named here.
Headers
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
Get a subscription › Responses
OK
Update a subscription's envelope
Updates the subscription's own descriptive fields — name, description and custom-field values — and nothing that was agreed. Omitted fields are left unchanged; a body that states none of them is refused. To change what is being billed, cut a draft revision and publish it: POST /subscriptions/{id}/revisions/cut.
Required scope: subscription.write (Write subscriptions).
path Parameters
idSubscription UUID
query Parameters
includeExtra data to add to the response: tags, live, revisions, actions, scheduled_cancellation, scheduled_cancellation.created_by, billing_state, display, localized. Send a comma-separated list or repeat the parameter. An unknown name is refused with 400. tags is sent without being asked until 2026-11-30; after that date it is sent only when named here. display is sent without being asked until 2026-11-30; after that date it is sent only when named here.
Headers
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
Update a subscription's envelope › Request Body
Values for the org's configured subscription custom fields; replaces the stored map. Omitted leaves it unchanged.
descriptionNew internal operator-facing description; omitted leaves it unchanged.
nameNew internal operator-facing name; omitted leaves it unchanged.
on_early_stopThe deal's own early-stop term: no_credit keeps the unused part of an advance-billed period billed, credit_unused credits it on the closing invoice. null clears it, so each phase's plans' defaults apply. Omitted leaves it unchanged. Accepted only while the subscription has never been activated; afterwards SUBSCRIPTION_EARLY_STOP_FIXED (409).
Locale-keyed overrides for name, description and public_description; replaces the stored map. Omitted leaves it unchanged.
Update a subscription's envelope › Responses
OK
Start a DRAFT subscription
Publishes the parked first revision of a subscription that is still DRAFT and flips it to ACTIVE at the request instant: the entitlements are seeded, the first billing window opens at the first phase, and subscription.revision_published is emitted — exactly what a quote's signature does, for a deal that arrived without one. Refuses with SUBSCRIPTION_NOT_DRAFT when the subscription has already started (publish the draft instead) and SUBSCRIPTION_NO_DRAFT when nothing is parked on it. The answer is the deal wrapper until 2026-11-30; from then on data is the Subscription the action changed and the wrapper's other fields are gone (their homes are named on each field). The Subscription's include names (live, revisions, actions, scheduled_cancellation, billing_state, …) are accepted now and shape that answer from 2026-11-30.
Required scope: subscription.write (Write subscriptions).
path Parameters
idSubscription UUID
query Parameters
includeExtra data to add to the response: phases, phases.lines, phases.lines.product, phases.lines.resolution, phases.lines.schedule, phases.totals, superseded_phases, tags, live, revisions, actions, scheduled_cancellation, scheduled_cancellation.created_by, billing_state, display, localized. Send a comma-separated list or repeat the parameter. An unknown name is refused with 400. phases is sent without being asked until 2026-11-30; after that date it is sent only when named here. phases.lines is sent without being asked until 2026-11-30; after that date it is sent only when named here. phases.lines.resolution is sent without being asked until 2026-11-30; after that date it is sent only when named here. phases.lines.schedule is sent without being asked until 2026-11-30; after that date it is sent only when named here. phases.totals is sent without being asked until 2026-11-30; after that date it is sent only when named here.
Headers
Idempotency-KeyUnique key that makes this POST safe to retry: repeats with the same key replay the first response instead of re-executing. Replays are scoped to the retrying principal (same API key / user) and kept for 24 hours. Required on every POST.
Client-generated idempotency key (e.g. a UUID).
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
Start a DRAFT subscription › Responses
OK
Get a subscription's allowance state
What the customer gets and what they have used, per product of the plan in force: the included amount and where it came from, carry-forward, credits, a durable pool's balance, and the billable overage — resolved through the same functions the invoice pipeline bills with, so the card cannot quote a number the bill will not honour.
Required scope: subscription.read (Read subscriptions).
path Parameters
idSubscription UUID
Headers
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
Get a subscription's allowance state › Responses
OK
List the billing periods
Each billing period the subscription's documents billed or settled (a discarded draft billed nothing; a reversed invoice is listed under its status), with those documents, read from the windows the billing run recorded — and each period its next cut bills or settles. Earliest first.
Required scope: subscription.read (Read subscriptions).
path Parameters
idSubscription UUID
Headers
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
List the billing periods › Responses
OK
Cancel the subscription
when says when it takes effect, as one value: now (the default) ends the subscription and applies any pending scheduled cancellation instead of minting a second one; at plans it for a future instant; period_end plans it for the end of the billing period in force, resolved once when this is called (409 SUBSCRIPTION_CANCEL_NO_PERIOD when no period is in force). A planned cancellation is read back as pending_cancel. A past instant is refused (422 SUBSCRIPTION_CANCEL_IN_PAST). The exit rules of the phase in force are evaluated here and nowhere else: a block gate whose not-before phase — of this subscription or of another one, for a co-terminated deal — has not ended refuses with 409. Notice periods and fees are carried and shown; what they charge is the stop path's business. The answer is the deal wrapper until 2026-11-30; from then on data is the Subscription the action changed and the wrapper's other fields are gone (their homes are named on each field). The Subscription's include names (live, revisions, actions, scheduled_cancellation, billing_state, …) are accepted now and shape that answer from 2026-11-30.
Required scope: subscription.cancel (Cancel subscriptions).
path Parameters
idSubscription UUID
query Parameters
includeExtra data to add to the response: phases, phases.lines, phases.lines.product, phases.lines.resolution, phases.lines.schedule, phases.totals, superseded_phases, tags, live, revisions, actions, scheduled_cancellation, scheduled_cancellation.created_by, billing_state, display, localized. Send a comma-separated list or repeat the parameter. An unknown name is refused with 400. phases is sent without being asked until 2026-11-30; after that date it is sent only when named here. phases.lines is sent without being asked until 2026-11-30; after that date it is sent only when named here. phases.lines.resolution is sent without being asked until 2026-11-30; after that date it is sent only when named here. phases.lines.schedule is sent without being asked until 2026-11-30; after that date it is sent only when named here. phases.totals is sent without being asked until 2026-11-30; after that date it is sent only when named here.
Headers
Idempotency-KeyUnique key that makes this POST safe to retry: repeats with the same key replay the first response instead of re-executing. Replays are scoped to the retrying principal (same API key / user) and kept for 24 hours. Required on every POST.
Client-generated idempotency key (e.g. a UUID).
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
Cancel the subscription › Request Body
reasonWhy.
When the cancellation takes effect: now (the default when absent), at a future instant, or at the end of the billing period in force — resolved once, when this is called. A past instant is refused.
Cancel the subscription › Responses
OK
Get the next invoice
What the billing run will bill at the subscription's next cut — the opening cut that ends a trial, a phase change inside the period, or the period's close — priced by a preview of the very draft it writes there: the same windows, promotions, settlements and tax. The customer portal's estimate. Nothing is written. Empty lines when no cut is next.
Required scope: subscription.read (Read subscriptions).
path Parameters
idSubscription UUID
Headers
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
Get the next invoice › Responses
OK
Pause the subscription
Status on the subscription, never a phase. The instant is recorded so the resume can stretch the phases by exactly the paused time: phase clocks are frozen, not lost. Only an active subscription pauses. The answer is the deal wrapper until 2026-11-30; from then on data is the Subscription the action changed and the wrapper's other fields are gone (their homes are named on each field). The Subscription's include names (live, revisions, actions, scheduled_cancellation, billing_state, …) are accepted now and shape that answer from 2026-11-30.
Required scope: subscription.write (Write subscriptions).
path Parameters
idSubscription UUID
query Parameters
includeExtra data to add to the response: phases, phases.lines, phases.lines.product, phases.lines.resolution, phases.lines.schedule, phases.totals, superseded_phases, tags, live, revisions, actions, scheduled_cancellation, scheduled_cancellation.created_by, billing_state, display, localized. Send a comma-separated list or repeat the parameter. An unknown name is refused with 400. phases is sent without being asked until 2026-11-30; after that date it is sent only when named here. phases.lines is sent without being asked until 2026-11-30; after that date it is sent only when named here. phases.lines.resolution is sent without being asked until 2026-11-30; after that date it is sent only when named here. phases.lines.schedule is sent without being asked until 2026-11-30; after that date it is sent only when named here. phases.totals is sent without being asked until 2026-11-30; after that date it is sent only when named here.
Headers
Idempotency-KeyUnique key that makes this POST safe to retry: repeats with the same key replay the first response instead of re-executing. Replays are scoped to the retrying principal (same API key / user) and kept for 24 hours. Required on every POST.
Client-generated idempotency key (e.g. a UUID).
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
Pause the subscription › Request Body
atWhen the transition takes effect. Defaults to now.
reasonWhy.
Pause the subscription › Responses
OK
Get what the next invoice settles
A change inside a period already billed in advance — a quantity, a price, a catalog version under immediate_prorate — is settled on the invoice of the cut that closes the period: a credit of what the period's start billed and a charge of the terms in force, over the part that changed. This answers those lines before that invoice exists, priced by the same assembly. Empty lines when nothing is pending.
Required scope: subscription.read (Read subscriptions).
path Parameters
idSubscription UUID
Headers
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
Get what the next invoice settles › Responses
OK
Set a product's allowance-refresh cadence
Overrides how often the included allowance pool refreshes for one product (e.g. daily). Both fields omitted clears the override (refreshes once per billing cycle).
Required scope: subscription.write (Write subscriptions).
path Parameters
idSubscription UUID
productIdProduct UUID
Headers
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
Set a product's allowance-refresh cadence › Request Body
refresh_countHow often the included pool refreshes, as a count of refresh_unit; both fields null clears the override.
refresh_unitUnit of the refresh cadence: day, week, month, year or billing_cycle; both fields null clears the override.
Set a product's allowance-refresh cadence › Responses
No Content
Override a product's included quantity
Sets how many units are included for ONE subscription, overriding the plan version's pin. Works for any product the subscription carries, INCLUDING one whose plan pins no included quantity. The next invoice bills this number, and it survives a plan version bump. 0 is a valid override meaning nothing is included; use DELETE to go back to the plan's number. 404 when the subscription does not carry the product at all.
Required scope: subscription.write (Write subscriptions).
path Parameters
idSubscription UUID
productIdProduct UUID
Headers
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
Override a product's included quantity › Request Body
included_quantityUnits included for this subscription, as a non-negative decimal string. 0 is a valid override meaning nothing is included; to go back to the plan's number use DELETE instead.
Override a product's included quantity › Responses
No Content
Drop a product's included-quantity override
Removes the per-subscription override so the product follows its plan version's included quantity again, now and after every future publish.
Required scope: subscription.write (Write subscriptions).
path Parameters
idSubscription UUID
productIdProduct UUID
Headers
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
Drop a product's included-quantity override › Responses
No Content
Make a product a durable credit pool
Converts (or creates) the (subscription, product) entitlement into a durable POOL — a cross-period balance that drains as usage is metered. Clears any refresh cadence.
Required scope: subscription.write (Write subscriptions).
path Parameters
idSubscription UUID
productIdProduct UUID
Headers
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
Make a product a durable credit pool › Request Body
unit_limitMaximum pool balance in units, as a decimal string; null for no unit ceiling.
Make a product a durable credit pool › Responses
No Content
Resume a paused subscription
The live revision is shifted by the paused duration from the pause instant and published as revision n+1, then the status returns to active — the shift is a revision of its own, which is why a draft open across the pause blocks the resume. A fixed date the shift had to move is reported in the server log rather than silently overlapping. The answer is the deal wrapper until 2026-11-30; from then on data is the Subscription the action changed and the wrapper's other fields are gone (their homes are named on each field). The Subscription's include names (live, revisions, actions, scheduled_cancellation, billing_state, …) are accepted now and shape that answer from 2026-11-30.
Required scope: subscription.write (Write subscriptions).
path Parameters
idSubscription UUID
query Parameters
includeExtra data to add to the response: phases, phases.lines, phases.lines.product, phases.lines.resolution, phases.lines.schedule, phases.totals, superseded_phases, tags, live, revisions, actions, scheduled_cancellation, scheduled_cancellation.created_by, billing_state, display, localized. Send a comma-separated list or repeat the parameter. An unknown name is refused with 400. phases is sent without being asked until 2026-11-30; after that date it is sent only when named here. phases.lines is sent without being asked until 2026-11-30; after that date it is sent only when named here. phases.lines.resolution is sent without being asked until 2026-11-30; after that date it is sent only when named here. phases.lines.schedule is sent without being asked until 2026-11-30; after that date it is sent only when named here. phases.totals is sent without being asked until 2026-11-30; after that date it is sent only when named here.
Headers
Idempotency-KeyUnique key that makes this POST safe to retry: repeats with the same key replay the first response instead of re-executing. Replays are scoped to the retrying principal (same API key / user) and kept for 24 hours. Required on every POST.
Client-generated idempotency key (e.g. a UUID).
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
Resume a paused subscription › Request Body
atWhen the transition takes effect. Defaults to now.
reasonWhy.
Resume a paused subscription › Responses
OK
List the subscription's revisions
Every revision in number order, without its phases: the subscription's whole negotiated history. A revision is the unit of history and of signing — exactly one is live, earlier ones are immutable and readable, and at most one draft is open. Unpaginated: a subscription's revision count is its renegotiation count.
Required scope: subscription.read (Read subscriptions).
path Parameters
idSubscription UUID
query Parameters
includeExtra data to add to the response: phases, phases.lines, phases.lines.product, phases.lines.resolution, phases.lines.schedule, phases.totals, superseded_phases. Send a comma-separated list or repeat the parameter. An unknown name is refused with 400.
Headers
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
List the subscription's revisions › Responses
OK
Write the subscription's first revision
Publishes revision 1 from the phases given: the deal as signed. This is the only write that goes live without passing through a draft, because there is no live revision to renegotiate from. A subscription that has one already is refused with 409 — open a draft or cut instead. The answer is the deal wrapper until 2026-11-30; from then on data is the SubscriptionRevision itself (today's revision) and the wrapper's other fields are gone (their homes are named on each field).
Required scope: subscription.write (Write subscriptions).
path Parameters
idSubscription UUID
query Parameters
includeExtra data to add to the response: phases, phases.lines, phases.lines.product, phases.lines.resolution, phases.lines.schedule, phases.totals, superseded_phases. Send a comma-separated list or repeat the parameter. An unknown name is refused with 400. phases is sent without being asked until 2026-11-30; after that date it is sent only when named here. phases.lines is sent without being asked until 2026-11-30; after that date it is sent only when named here. phases.lines.resolution is sent without being asked until 2026-11-30; after that date it is sent only when named here. phases.lines.schedule is sent without being asked until 2026-11-30; after that date it is sent only when named here. phases.totals is sent without being asked until 2026-11-30; after that date it is sent only when named here.
Headers
Idempotency-KeyUnique key that makes this POST safe to retry: repeats with the same key replay the first response instead of re-executing. Replays are scoped to the retrying principal (same API key / user) and kept for 24 hours. Required on every POST.
Client-generated idempotency key (e.g. a UUID).
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
Write the subscription's first revision › Request Body
The ordered phases of revision 1.
reasonWhy this deal exists: signed quote, operator edit.
Write the subscription's first revision › Responses
Created
Cut the live revision at an instant
Opens draft n+1 from a cut: phases wholly before the instant are kept, the phase containing it is split into an elapsed part that ends there, and the tail and every later phase are superseded and retained for history. The draft's last kept phase says stop, so "invalidate everything planned from now so I can negotiate anew" is valid as it stands; appending a phase flips it to next. A cut exactly on a phase's start supersedes that phase whole and splits nothing.
Required scope: subscription.write (Write subscriptions).
path Parameters
idSubscription UUID
query Parameters
includeExtra data to add to the response: phases, phases.lines, phases.lines.product, phases.lines.resolution, phases.lines.schedule, phases.totals, superseded_phases. Send a comma-separated list or repeat the parameter. An unknown name is refused with 400. phases is sent without being asked until 2026-11-30; after that date it is sent only when named here. phases.lines is sent without being asked until 2026-11-30; after that date it is sent only when named here. phases.lines.resolution is sent without being asked until 2026-11-30; after that date it is sent only when named here. phases.lines.schedule is sent without being asked until 2026-11-30; after that date it is sent only when named here. phases.totals is sent without being asked until 2026-11-30; after that date it is sent only when named here.
Headers
Idempotency-KeyUnique key that makes this POST safe to retry: repeats with the same key replay the first response instead of re-executing. Replays are scoped to the retrying principal (same API key / user) and kept for 24 hours. Required on every POST.
Client-generated idempotency key (e.g. a UUID).
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
Cut the live revision at an instant › Request Body
atThe cut instant; omit it to cut at now. The phase containing it is split; everything after it is superseded and kept for history. It may not be in the past — a renegotiation takes effect at or after now.
reasonWhy the revision exists.
replace_draftDiscard the open draft and cut the live revision anyway. Without it an open draft refuses the cut.
Cut the live revision at an instant › Responses
Created
Read the open draft revision
The draft being negotiated, resolved exactly as the live revision is. Refused with 409 when no draft is open. The answer is the deal wrapper until 2026-11-30; from then on data is the SubscriptionRevision itself (today's revision) and the wrapper's other fields are gone (their homes are named on each field).
Required scope: subscription.read (Read subscriptions).
path Parameters
idSubscription UUID
query Parameters
includeExtra data to add to the response: phases, phases.lines, phases.lines.product, phases.lines.resolution, phases.lines.schedule, phases.totals, superseded_phases. Send a comma-separated list or repeat the parameter. An unknown name is refused with 400. phases is sent without being asked until 2026-11-30; after that date it is sent only when named here. phases.lines is sent without being asked until 2026-11-30; after that date it is sent only when named here. phases.lines.resolution is sent without being asked until 2026-11-30; after that date it is sent only when named here. phases.lines.schedule is sent without being asked until 2026-11-30; after that date it is sent only when named here. phases.totals is sent without being asked until 2026-11-30; after that date it is sent only when named here.
Headers
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
Read the open draft revision › Responses
OK
Replace what the draft contains
States what the draft CONTAINS: its reason and every active phase, in order. The server derives the change against the draft and checks the result. It works on revision 1 before the subscription starts, and on a later draft that POST …/revisions/cut or POST …/revisions/draft opened (409 SUBSCRIPTION_NO_DRAFT when none is open). Nothing is published. The phases a cut superseded are kept as history. PUT because the write replaces: the same body twice gives the same draft, so it needs no Idempotency-Key.
The rules, each answered with its own code:
- The first phase starts on a date. A later phase starts on a date or after the previous one.
- A phase that starts on a date starts exactly where the previous phase ends: no overlap, no gap, and not after a phase that has no known end.
- A phase ends after it starts.
thenisnextwhen a phase follows,openorstoponly on the last phase, andopenon a phase that never ends.- A phase that has started (it opened before the draft's cut and before now) cannot change, except its
endsandthen, and its new end may not be before now. Removing it, or putting a phase before it, is a change. - To change the deal from a date inside a phase, end that phase at the date (not before now) and add the next phase with
continues: true: it is the rest of the same phase, as a split leaves it. continuesneeds a phase that starts after the previous one, and a previous phase that ends on a date or after a length. The first phase continues nothing.- One line per product and price key in a phase. Each line names a plan or product version that was published (revision 1 may name one still being finished).
- A value carries only its attribute's payload. A reset carries none.
- A one-time line is not carried to a later phase. An
on_eventline needs a phase that ends on an event. - A line paid in advance for the whole phase is recurring, in a phase with an end date or a length.
- A
not_beforecommitment names a phase of this body, in this body's numbering. - The draft must not be held by an offer that is out with the customer (409).
A refused write lists EVERY problem in problems: each item has pointer (a JSON pointer into this body, such as /phases/1/lines/0/values/quantity), phase and line (product_id, price_key) where it applies, the rule's code, and a message that says what to change. A later draft answers 422 SUBSCRIPTION_DRAFT_INVALID. Revision 1 answers with the first problem's own code at the top until 2026-11-30, and SUBSCRIPTION_DRAFT_INVALID from then on.
Required scope: subscription.write (Write subscriptions).
path Parameters
idSubscription UUID
query Parameters
includeExtra data to add to the response: phases, phases.lines, phases.lines.product, phases.lines.resolution, phases.lines.schedule, phases.totals, superseded_phases. Send a comma-separated list or repeat the parameter. An unknown name is refused with 400. phases is sent without being asked until 2026-11-30; after that date it is sent only when named here. phases.lines is sent without being asked until 2026-11-30; after that date it is sent only when named here. phases.lines.resolution is sent without being asked until 2026-11-30; after that date it is sent only when named here. phases.lines.schedule is sent without being asked until 2026-11-30; after that date it is sent only when named here. phases.totals is sent without being asked until 2026-11-30; after that date it is sent only when named here.
Headers
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
Replace what the draft contains › Request Body
Every active phase of the draft, in order. They replace the draft's active phases; the phases a cut superseded are kept as history.
reasonWhy the revision exists: signed quote, renegotiation, operator edit.
Replace what the draft contains › Responses
OK
Open the next revision without a cut
Copies the live revision into draft n+1 so a not-yet-started phase can be corrected. Phases never multiply from edits; revisions do — a correction is a revision whose diff is one field, with the same phase count as its predecessor. Phases that have already started are frozen. Use the cut instead when a timeframe changes. Refused with 409 when a draft is already open.
Required scope: subscription.write (Write subscriptions).
path Parameters
idSubscription UUID
query Parameters
includeExtra data to add to the response: phases, phases.lines, phases.lines.product, phases.lines.resolution, phases.lines.schedule, phases.totals, superseded_phases. Send a comma-separated list or repeat the parameter. An unknown name is refused with 400. phases is sent without being asked until 2026-11-30; after that date it is sent only when named here. phases.lines is sent without being asked until 2026-11-30; after that date it is sent only when named here. phases.lines.resolution is sent without being asked until 2026-11-30; after that date it is sent only when named here. phases.lines.schedule is sent without being asked until 2026-11-30; after that date it is sent only when named here. phases.totals is sent without being asked until 2026-11-30; after that date it is sent only when named here.
Headers
Idempotency-KeyUnique key that makes this POST safe to retry: repeats with the same key replay the first response instead of re-executing. Replays are scoped to the retrying principal (same API key / user) and kept for 24 hours. Required on every POST.
Client-generated idempotency key (e.g. a UUID).
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
Open the next revision without a cut › Responses
Created
Throw the open draft away
Discards the draft revision and everything negotiated in it. A no-op when none is open. The live revision is untouched.
Required scope: subscription.write (Write subscriptions).
path Parameters
idSubscription UUID
Headers
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
Throw the open draft away › Responses
No Content
Append a phase to the open draft
Deprecated: use PUT /subscriptions/{id}/revisions/draft instead. Removed on 2026-11-30.
Adds a phase after the draft's last active one and flips that one from stop to next. An unset start kind means after previous. A fixed-date start must meet the previous phase's end exactly: overlap and gap are both refused, and a fixed date after an open end cannot be placed at all. The first appended phase inherits from the elapsed part by the ladder.
Required scope: subscription.write (Write subscriptions).
path Parameters
idSubscription UUID
query Parameters
includeExtra data to add to the response: phases, phases.lines, phases.lines.product, phases.lines.resolution, phases.lines.schedule, phases.totals, superseded_phases. Send a comma-separated list or repeat the parameter. An unknown name is refused with 400. phases is sent without being asked until 2026-11-30; after that date it is sent only when named here. phases.lines is sent without being asked until 2026-11-30; after that date it is sent only when named here. phases.lines.resolution is sent without being asked until 2026-11-30; after that date it is sent only when named here. phases.lines.schedule is sent without being asked until 2026-11-30; after that date it is sent only when named here. phases.totals is sent without being asked until 2026-11-30; after that date it is sent only when named here.
Headers
Idempotency-KeyUnique key that makes this POST safe to retry: repeats with the same key replay the first response instead of re-executing. Replays are scoped to the retrying principal (same API key / user) and kept for 24 hours. Required on every POST.
Client-generated idempotency key (e.g. a UUID).
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
Append a phase to the open draft › Request Body
The closing rule.
The opening rule.
continuesTrue when this phase is the rest of the phase before it, as a split or a cut leaves it: a line whose version_change is at_phase_change keeps its version across this boundary, and an event end is measured from the start of the first part. Only a phase that starts after_previous, after a phase that ends on a date or after a length, can continue it. Read only by PUT /subscriptions/{id}/revisions/draft and its preview; omitted there, a phase keeps what the draft says at its position.
Notice, gate, fee and commitment.
One entry per product billed in this window.
reasonWhy the phase exists: signed quote, renegotiation, operator edit, transform run.
thenWhat follows: next iff a successor exists, open or stop only on the last phase. stop ends the subscription.
Append a phase to the open draft › Responses
Created
Preview the whole draft
Takes the body PUT /subscriptions/{id}/revisions/draft takes and answers the revision that write would leave, with every value resolved and every line priced. Nothing is saved. It is refused as the write refuses: 422 SUBSCRIPTION_DRAFT_INVALID with every problem in problems.
Required scope: subscription.read (Read subscriptions).
path Parameters
idSubscription UUID
query Parameters
includeExtra data to add to the response: phases, phases.lines, phases.lines.product, phases.lines.resolution, phases.lines.schedule, phases.totals, superseded_phases. Send a comma-separated list or repeat the parameter. An unknown name is refused with 400. phases is sent without being asked until 2026-11-30; after that date it is sent only when named here. phases.lines is sent without being asked until 2026-11-30; after that date it is sent only when named here. phases.lines.resolution is sent without being asked until 2026-11-30; after that date it is sent only when named here. phases.lines.schedule is sent without being asked until 2026-11-30; after that date it is sent only when named here. phases.totals is sent without being asked until 2026-11-30; after that date it is sent only when named here.
Headers
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
Preview the whole draft › Request Body
Every active phase of the draft, in order. They replace the draft's active phases; the phases a cut superseded are kept as history.
reasonWhy the revision exists: signed quote, renegotiation, operator edit.
Preview the whole draft › Responses
OK
Make the open draft the live revision
The draft goes live, the previous live revision is superseded, subscription.revision_published is emitted, and the durable timer is re-armed at the new next boundary. The draft is checked whole first: phases must not overlap or leave gaps, and every rule of the model must hold. The answer is the deal wrapper until 2026-11-30; from then on data is the SubscriptionRevision itself (today's revision) and the wrapper's other fields are gone (their homes are named on each field).
Required scope: subscription.write (Write subscriptions).
path Parameters
idSubscription UUID
query Parameters
includeExtra data to add to the response: phases, phases.lines, phases.lines.product, phases.lines.resolution, phases.lines.schedule, phases.totals, superseded_phases. Send a comma-separated list or repeat the parameter. An unknown name is refused with 400. phases is sent without being asked until 2026-11-30; after that date it is sent only when named here. phases.lines is sent without being asked until 2026-11-30; after that date it is sent only when named here. phases.lines.resolution is sent without being asked until 2026-11-30; after that date it is sent only when named here. phases.lines.schedule is sent without being asked until 2026-11-30; after that date it is sent only when named here. phases.totals is sent without being asked until 2026-11-30; after that date it is sent only when named here.
Headers
Idempotency-KeyUnique key that makes this POST safe to retry: repeats with the same key replay the first response instead of re-executing. Replays are scoped to the retrying principal (same API key / user) and kept for 24 hours. Required on every POST.
Client-generated idempotency key (e.g. a UUID).
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
Make the open draft the live revision › Responses
OK
Read the deal as it stands
The live revision with every line value resolved down the ladder: stated on this phase's line, else carried from an earlier phase, else the catalogue origin, else the subscription default. Each value carries the rung it came from and the chip that names it — agreed, agreed since phase N, list or default — so an operator can see at a glance what the deal says and what merely follows the catalogue. A value no rung supplies comes back unresolved rather than failing the read. 404 until the first revision is published: a DRAFT subscription has no deal yet, and re-asking will not produce one. The WRITES refuse the same absence with 409 SUBSCRIPTION_NO_LIVE_REVISION, because there the caller can resolve it by publishing revision 1. The answer is the deal wrapper until 2026-11-30; from then on data is the SubscriptionRevision itself (today's revision) and the wrapper's other fields are gone (their homes are named on each field).
Required scope: subscription.read (Read subscriptions).
path Parameters
idSubscription UUID
query Parameters
includeExtra data to add to the response: phases, phases.lines, phases.lines.product, phases.lines.resolution, phases.lines.schedule, phases.totals, superseded_phases. Send a comma-separated list or repeat the parameter. An unknown name is refused with 400. phases is sent without being asked until 2026-11-30; after that date it is sent only when named here. phases.lines is sent without being asked until 2026-11-30; after that date it is sent only when named here. phases.lines.resolution is sent without being asked until 2026-11-30; after that date it is sent only when named here. phases.lines.schedule is sent without being asked until 2026-11-30; after that date it is sent only when named here. phases.totals is sent without being asked until 2026-11-30; after that date it is sent only when named here.
Headers
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
Read the deal as it stands › Responses
OK
Get the live revision's phase windows
Deprecated: use GET /subscriptions/{id}/revisions/live?include=phases instead. Removed on 2026-11-30.
One materialised window per active phase — opening and closing instants once fixed dates, durations and fired events are applied — plus the next boundary the durable timer will wake on. A bound is absent when it is genuinely unknown: an event end that has not fired, or a phase waiting behind one. The clock labels each window past, current, future or pending and moves no bound. next_boundary is absent when every remaining edge is an unfired event or a never end; the event evaluator wakes the system for those instead. 404 until the first revision is published, exactly as the live read is: there are no windows before there is a deal.
Required scope: subscription.read (Read subscriptions).
path Parameters
idSubscription UUID
Headers
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
Get the live revision's phase windows › Responses
OK
Get one revision by number
One revision with its phases, the superseded ones included. A cut marks the phases it replaced as superseded rather than deleting them, so what was agreed before a renegotiation stays readable; superseded phases take no part in time or in resolution and carry no window. The answer is the deal wrapper until 2026-11-30; from then on data is the SubscriptionRevision itself (today's revision) and the wrapper's other fields are gone (their homes are named on each field).
Required scope: subscription.read (Read subscriptions).
path Parameters
idSubscription UUID
numberRevision number, 1-based
query Parameters
includeExtra data to add to the response: phases, phases.lines, phases.lines.product, phases.lines.resolution, phases.lines.schedule, phases.totals, superseded_phases. Send a comma-separated list or repeat the parameter. An unknown name is refused with 400. phases is sent without being asked until 2026-11-30; after that date it is sent only when named here. phases.lines is sent without being asked until 2026-11-30; after that date it is sent only when named here. phases.lines.resolution is sent without being asked until 2026-11-30; after that date it is sent only when named here. phases.lines.schedule is sent without being asked until 2026-11-30; after that date it is sent only when named here. phases.totals is sent without being asked until 2026-11-30; after that date it is sent only when named here.
Headers
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
Get one revision by number › Responses
OK
Drop the pending cancellation
Removes the cancellation the cancel operation planned (when at or period_end). A no-op when none is pending; the subscription's status is untouched either way.
Required scope: subscription.cancel (Cancel subscriptions).
path Parameters
idSubscription UUID
Headers
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
Drop the pending cancellation › Responses
No Content
Add tags to a subscription
Adds the given tags to the subscription and keeps the tags it already has. Returns all tags on the subscription after the change. The subscription itself lists them in tag_ids, and in tags with include=tags.
Required scope: tag.write (Manage tags).
path Parameters
idResource UUID
query Parameters
includeExtra data to add to the response: usage_count. Send a comma-separated list or repeat the parameter. An unknown name is refused with 400.
Headers
Idempotency-KeyUnique key that makes this POST safe to retry: repeats with the same key replay the first response instead of re-executing. Replays are scoped to the retrying principal (same API key / user) and kept for 24 hours. Required on every POST.
Client-generated idempotency key (e.g. a UUID).
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
Add tags to a subscription › Request Body
tag_idsThe tags to add. Each must be a tag for this kind of record.
Add tags to a subscription › Responses
OK
Remove tags from a subscription
Removes the tags given in the tag_ids query parameter from the subscription in one call. Its other tags stay; an id it does not carry is ignored.
Required scope: tag.write (Manage tags).
path Parameters
idResource UUID
query Parameters
tag_idsTag UUIDs to remove
Headers
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
Remove tags from a subscription › Responses
No Content
Grant usage credits to a subscription
Grants a metered product usage the customer did not buy, as an entitlement grant the allowance ladder spends before the plan's own included amount. Distinct from POST /wallets/{id}/topup, which credits money to a wallet.
Required scope: subscription.write (Write subscriptions).
path Parameters
idSubscription UUID
Headers
Idempotency-KeyThreaded into the grant as its dedup token: the same key collapses onto one grant, a new key grants again.
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
Grant usage credits to a subscription › Request Body
product_idProduct to grant usage against.
quantity^-?\d+(\.\d+)?$ · requiredUsage quantity to grant (metered units, NOT money).
descriptionOptional note recorded on the grant.
Grant usage credits to a subscription › Responses
Created
Sum a subscription's usage in a window
The usage events of the subscription and its customer in [timestamp.gte, timestamp.lt), summed per product, metric key and price key: the grain the meter bills a line by, over every event in the window however many there are. Usage no line of the deal bills is summed here too; GET /subscriptions/{id}/usage-without-line says which. Requires the usage.read permission.
Required scope: usage.read (Read usage).
path Parameters
idSubscription UUID
query Parameters
timestamp.gteKeep events whose timestamp is at or after this instant (RFC 3339).
timestamp.ltKeep events whose timestamp is before this instant (RFC 3339).
limitGrains per page (default 100, max 1000).
cursorOpaque continuation token from the previous response's pagination.cursor. Omit for the first page. Cursors are stateless and do not expire, but are only valid for the list and filters that produced them.
Headers
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
Sum a subscription's usage in a window › Responses
OK
List a subscription's usage no line bills
The usage this subscription was sent that no line of its deal bills, per product and price key: how many events, what quantity, over what window, why, and when a line for the key starts if one was added later. Open findings first; include_closed adds the waived ones and those the deal turned out to cover.
Required scope: subscription.read (Read subscriptions).
path Parameters
idSubscription UUID
query Parameters
include_closedAlso return the findings that were waived or turned out to be covered: the record of what went unbilled and what did not.
Headers
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
List a subscription's usage no line bills › Responses
OK
Waive usage no line bills
Deprecated: use PATCH /subscriptions/{id}/usage-without-line/{finding_id} instead. Removed on 2026-11-30.
Closes one open finding without billing it, and records who did. Usage that keeps arriving under the key opens a new finding. A finding already waived, or one the deal turned out to cover, is refused with USAGE_FINDING_CLOSED.
Required scope: subscription.write (Write subscriptions).
path Parameters
idSubscription UUID
findingIdThe finding to waive
Headers
Idempotency-KeyUnique key that makes this POST safe to retry: repeats with the same key replay the first response instead of re-executing. Replays are scoped to the retrying principal (same API key / user) and kept for 24 hours. Required on every POST.
Client-generated idempotency key (e.g. a UUID).
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
Waive usage no line bills › Responses
OK
Change the status of usage no line bills
Sets the finding's status and answers the finding. waived closes an open finding without billing it, and records who did. Usage that keeps arriving under the key opens a new finding. A finding already waived, or one the deal turned out to cover, is refused with USAGE_FINDING_CLOSED. open and resolved cannot be requested (400 VALIDATION).
Required scope: subscription.write (Write subscriptions).
path Parameters
idSubscription UUID
finding_idThe finding to change
Headers
X-Workspace-IdSelects the workspace this request operates in, by workspace UUID or slug (e.g. a sandbox workspace for test integrations). Omitted: the organization's default live workspace. Unknown workspace: 404; workspace outside your organization: 403. Discover workspaces via GET /workspaces.
Workspace UUID or slug.
Change the status of usage no line bills › Request Body
statuswaived closes an open finding without billing it. open and resolved cannot be requested: a finding opens when usage arrives, and resolved is set when the deal turns out to cover the usage.
Change the status of usage no line bills › Responses
OK