Subscriptions
A subscription puts a customer on a plan and recurs on the plan’s interval until something changes. Everything else — invoices, payments, dunning, revenue recognition — descends from this one object.
States
pending_activation ──► trialing ──► active ──► past_due ──► canceled │ │ │ ▼ ▼ ▼ active paused canceled │ └──► active| State | Meaning |
|---|---|
pending_activation | Created, awaiting trial start or first invoice. |
trialing | In a free trial. No invoices issued yet. |
active | Healthy. Invoices issuing on schedule. |
past_due | An invoice payment failed; in dunning. |
paused | Manually or programmatically paused. Auto-resumes on paused_until. |
canceled | Terminal. Will not bill again. |
ended | Terminal. Reached its commitment end without renewal. |
incomplete_expired | Terminal. Initial activation never completed. |
The full transition table lives in the Status & lifecycle reference.
Creating a subscription
POST /v1/subscriptionsContent-Type: application/jsonIdempotency-Key: <uuid>
{ "customer_id": "cus_…", "plan_code": "starter-monthly-usd", "default_payment_method_id": "pm_…", "trial_days": 14, "billing_cycle_anchor": "2026-06-01T00:00:00Z", "quantities": { "active_seats": 5 }, "metadata": { "team": "alpha" }}If trial_days is set (or the plan has a default trial), the subscription
starts in trialing. Otherwise it transitions to active immediately and
the first invoice is issued.
Billing cycles
A subscription bills on its billing cycle anchor. By default, that’s
the activation timestamp. You can pin it (billing_cycle_anchor) to align
all your customers’ renewals to, say, the 1st of the month.
When a cycle ends, the invoice engine:
- Computes per-component charges (flat / per-unit / tiered / etc).
- Aggregates usage events for any
usagecomponents. - Applies discounts (subscription-level, then plan-level, then promo).
- Computes tax via the tax engine.
- Sums to a total, finalises the invoice, and triggers payment.
Changing a subscription
PATCH /v1/subscriptions/{id}{ "plan_code": "pro-monthly-usd", "proration_behavior": "create_prorations"}proration_behavior options:
create_prorations(default) — credit the unused portion of the current plan, charge the prorated portion of the new plan. Posts as invoice items on the next invoice.none— change takes effect at the next period boundary; no prorations.always_invoice— bill the proration immediately.
Quantities
For per-unit and tiered components with a meter, push quantity changes:
POST /v1/subscriptions/{id}/quantities{ "meter": "active_seats", "quantity": 12, "effective_at": "now" }Quantities can be set now (default) or next_period. Future-dated
changes are scheduled and emitted as subscription.quantity_scheduled.
Pause / resume
POST /v1/subscriptions/{id}/pause{ "until": "2026-08-01T00:00:00Z", "behavior": "void_invoices" }behavior options:
void_invoices— open invoices are voided; no charges during the pause.mark_uncollectible— open invoices are markeduncollectible.keep_as_draft— invoices continue to issue as drafts; nothing collected.
The subscription-maintenance worker auto-resumes the subscription on
paused_until and emits subscription.resumed.
Cancellation
POST /v1/subscriptions/{id}/cancel{ "at": "period_end", "reason": "customer_request" }at options: now (immediate, with proration credit) or period_end
(continues until the current period closes, then transitions to
canceled).
reason is recorded and surfaced in churn reporting. Free-form notes
are also accepted.
Common events
| Event | When it fires |
|---|---|
subscription.created | Object created (any state). |
subscription.activated | Entered active (from any source). |
subscription.trial_will_end | 3 days before trial ends. |
subscription.updated | Any plan / quantity / metadata change. |
subscription.paused | Entered paused. |
subscription.resumed | Returned to active from paused. |
subscription.past_due | Entered past_due (a payment failed). |
subscription.canceled | Entered canceled. |
Where to next
- Trials & commitments — modelling trial periods and minimum-term commitments.
- Create a subscription — the integration recipe.