Billing milestones are percentage-based checkpoints tied to a subscription's product delivery. They're designed for project-based or milestone-based billing - where charges are triggered when specific deliverables are completed rather than on a recurring schedule.
Example: A consulting engagement billed 25% at kickoff, 50% at mid-point, and 25% at completion.
Key concepts:
- Trigger type -
manual(you mark it complete) ordate(triggers automatically at a scheduled date) - Percentage - the fraction of total contract value to invoice when this milestone triggers
- Status -
pending,triggered, orinvoiced
List milestone plans
Every milestone plan on the subscription with its instalments and the percentage of the price still unallocated. A plan is authored by scheduling a milestone_plan.create change; its instalments are edited with milestone.update and milestone.cancel.
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 milestone plans › Responses
OK
Get a milestone plan
One milestone plan with its instalments in order and the percentage of the price still unallocated.
path Parameters
idSubscription UUID
planIdMilestone plan 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 milestone plan › Responses
OK
List billing milestones
Every billing milestone on the subscription, newest first — the flat list across all its milestone plans, plus any standalone milestones. Use the milestone-plans routes to read them grouped by plan with the remaining percentage.
path Parameters
idSubscription UUID
query Parameters
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.
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 billing milestones › Responses
OK
Create a standalone billing milestone
Creates one milestone with no plan behind it. Its percentage is measured against the other plan-less milestones on the same (subscription, product) pair. To author a whole plan — the 30/40/30 — schedule a milestone_plan.create change instead: it validates the instalments together and gives them a plan to belong to.
path Parameters
idSubscription UUID
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 standalone billing milestone › Request Body
nameOperator-facing milestone name; required.
percentage^-?\d+(\.\d+)?$ · requiredFraction of the resolved price to bill, as a decimal in (0,1] (e.g. 0.25 = 25%). NOT money.
product_idThe product whose resolved price a fraction is billed; required.
trigger_typeWhat fires the milestone: MANUAL (operator triggers) or DATE (fires on trigger_date).
descriptionOptional operator-facing description of the milestone.
Arbitrary caller-supplied key/value pairs.
trigger_dateDate the milestone fires; required when trigger_type is DATE.
Create a standalone billing milestone › Responses
Created
Get a billing milestone
path Parameters
idSubscription UUID
milestoneIdMilestone 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 billing milestone › Responses
OK
Trigger a billing milestone
Fires the milestone and mints its invoice. Exactly once: a concurrent trigger, the hourly sweep and the milestone's own dated job all claim the same row and only one of them can win. The invoice is a DRAFT unless invoice_now is set, and the response says whether it was actually finalised.
path Parameters
idSubscription UUID
milestoneIdMilestone UUID
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.
Trigger a billing milestone › Request Body
invoice_nowFinalise the invoice this trigger mints instead of leaving it as a draft. The response says whether it actually was finalised.
Trigger a billing milestone › Responses
OK