Skip to content

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
StateMeaning
pending_activationCreated, awaiting trial start or first invoice.
trialingIn a free trial. No invoices issued yet.
activeHealthy. Invoices issuing on schedule.
past_dueAn invoice payment failed; in dunning.
pausedManually or programmatically paused. Auto-resumes on paused_until.
canceledTerminal. Will not bill again.
endedTerminal. Reached its commitment end without renewal.
incomplete_expiredTerminal. Initial activation never completed.

The full transition table lives in the Status & lifecycle reference.

Creating a subscription

POST /v1/subscriptions
Content-Type: application/json
Idempotency-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:

  1. Computes per-component charges (flat / per-unit / tiered / etc).
  2. Aggregates usage events for any usage components.
  3. Applies discounts (subscription-level, then plan-level, then promo).
  4. Computes tax via the tax engine.
  5. 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 marked uncollectible.
  • 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

EventWhen it fires
subscription.createdObject created (any state).
subscription.activatedEntered active (from any source).
subscription.trial_will_end3 days before trial ends.
subscription.updatedAny plan / quantity / metadata change.
subscription.pausedEntered paused.
subscription.resumedReturned to active from paused.
subscription.past_dueEntered past_due (a payment failed).
subscription.canceledEntered canceled.

Where to next