Subscription
A Subscription is a Customer’s standing acceptance of an Offer, billed each Period until canceled.
A Subscription is a Customer’s standing acceptance of a recurring Offer, renewed and billed each period until canceled.
Properties
| Property | Type | Required | Description |
|---|---|---|---|
status | string | required | One of active, trialing, pastDue, paused, incomplete, or canceled. |
renewsAt | datetime | When it next renews. | |
quantity | integer | How many units of the Offer’s Price it holds, such as 12 members; 1 by default. | |
trialEndsAt | datetime | When a trial ends and the first paid period starts. | |
termEndsAt | datetime | When a committed term ends; the Renewal and the renewal notice read it. |
Object
{
"$id": "https: //api.sb/ routewise.dev/ subscriptions/ subscription_1",
"$type": "Subscription",
"status": "active",
"renewsAt": "2026-10-22T12: 00: 00Z",
"quantity": 1,
"trialEndsAt": "2026-10-22T12: 00: 00Z",
"termEndsAt": "2026-10-22T12: 00: 00Z"
}Relationships
- A Subscription bills many Invoices: the Invoices the Subscription issues, one for each period it renews.
bills, inversebilledFor. - A Subscription has one Quote: the Subscription for a Quote’s recurring lines, started when the Customer accepts it.
quote, inversestartsSubscription. - A Subscription has many Renewals: each Renewal decides one term of one Subscription; a Subscription has one Renewal per term.
renewals, inverserenews. - A Subscription renews one Offer: a Subscription bills one recurring Offer each Period until canceled.
renews, inversesubscriptions. - A Subscription’s subscriber is one Customer: a Customer holds Subscriptions, each billed once per Period.
subscriber, inversemaintains.
Lifecycle
| State | Meaning | Moves to |
|---|---|---|
incomplete (first) | The Subscription exists and its first period is billed but not yet paid. | trialing by Offer.trial; active on Invoice.collected when the Invoice bills this Subscription’s first period; canceled by Subscription.unsubscribe |
trialing | The Customer uses the Offer free until trialEndsAt. | active by Subscription.renew; canceled by Subscription.unsubscribe |
active | The Subscription renews each period and its Entitlements hold. | paused by Subscription.pause; pastDue on Invoice.overdue when the Invoice bills this Subscription; canceled by Subscription.unsubscribe |
pastDue | A renewal Invoice is unpaid while its retries run; Entitlements still hold. | active on Invoice.collected when the Invoice bills this Subscription; canceled on Invoice.overdue when every retry on the Startup’s retry schedule has failed |
paused | Billing and Entitlements stop until the pause ends, and the term moves by the paused days. | active by Subscription.resume; canceled by Subscription.unsubscribe |
canceled | The Subscription has ended; the Customer starts again with a new one. | None: it ends here. |
Verbs
createCreates a Subscription.POST /{namespace}/subscriptionsgetReturns one Subscription by id.GET /{namespace}/subscriptions/{id}listReturns Subscriptions, newest first, one page at a time.GET /{namespace}/subscriptionsupdateChanges the given properties of a Subscription.PATCH /{namespace}/subscriptions/{id}keepKeep takes back a cancel before the period closes, so the Subscription renews on its date at the same terms.POST /{namespace}/subscriptions/{subscription}/keeppausePause stops billing and Entitlements on a Subscription until a date, without ending it.POST /{namespace}/subscriptions/{subscription}/pauserenewRenew starts a Subscription’s next period and bills it at the Offer Version the Customer accepted.POST /{namespace}/subscriptions/{subscription}/renewresizeResize changes how many units a Subscription holds and prorates the current period.POST /{namespace}/subscriptions/{subscription}/resizeresumeResume restarts billing and Entitlements on a paused Subscription before its pause ends.POST /{namespace}/subscriptions/{subscription}/resumeswitchSwitch moves a Subscription to another Offer and prorates the current period.POST /{namespace}/subscriptions/{subscription}/switchunsubscribeUnsubscribe ends a Subscription at the close of its current period, and the Customer keeps access until then.POST /{namespace}/subscriptions/{subscription}/unsubscribe
Events
Events no Verb emits. Each Verb’s Event is in the Verbs table above; every Event is delivered in the same shape.
Subscription.pastDue
A Subscription moved to pastDue because its renewal Invoice went overdue. Raised by a state change.
| Field | Type | Required | Description |
|---|---|---|---|
name | string | required | Subscription.pastDue. |
at | datetime | required | When it happened. |
seq | integer | Its position in the namespace, one more than the Event before; any seq is a cursor into the history. | |
data | json | required | The Thing as the Action left it. |
data.subscription | Subscription | required | The Subscription as the change left it. |
data.subscription.status | string | required | One of active, trialing, pastDue, paused, incomplete, or canceled. |
data.subscription.renewsAt | datetime | When it next renews. | |
data.subscription.quantity | integer | How many units of the Offer’s Price it holds, such as 12 members; 1 by default. | |
data.subscription.trialEndsAt | datetime | When a trial ends and the first paid period starts. | |
data.subscription.termEndsAt | datetime | When a committed term ends; the Renewal and the renewal notice read it. | |
data.invoice | Invoice | required | The overdue renewal Invoice. |
data.previous.status | string | required | The status before this Event: active. |
{
"$id": "https: //api.sb/ routewise.dev/ events/ event_1",
"$type": "Event",
"name": "Subscription.pastDue",
"at": "2026-10-22T12: 00: 00Z",
"data": {
"subscription": {
"$id": "https: //api.sb/ routewise.dev/ subscriptions/ subscription_1",
"$type": "Subscription",
"status": "pastDue",
"renewsAt": "2026-10-22T12: 00: 00Z",
"quantity": 1,
"trialEndsAt": "2026-10-22T12: 00: 00Z",
"termEndsAt": "2026-10-22T12: 00: 00Z"
},
"invoice": {
"$id": "https: //api.sb/ routewise.dev/ invoices/ invoice_1",
"$type": "Invoice",
"total": {
"amount": 25,
"currency": "USD"
},
"due": "2026-10-22"
},
"previous": {
"status": "active"
}
},
"seq": 1
}Permissions
Which Access level may call each Verb. One-way Verbs wait their delay window.
| Operation | owner | admin | member | viewer |
|---|---|---|---|---|
Subscription.create | Yes | Yes | Yes | No |
Subscription.get | Yes | Yes | Yes | Yes |
Subscription.list | Yes | Yes | Yes | Yes |
Subscription.update | Yes | Yes | Yes | No |
Subscription.keep | Yes | Yes | Yes | No |
Subscription.pause | Yes | Yes | Yes | No |
Subscription.renew | Yes | Yes | Yes | No |
Subscription.resize | Yes | Yes | Yes | No |
Subscription.resume | Yes | Yes | Yes | No |
Subscription.switch | Yes | Yes | Yes | No |
Subscription.unsubscribe | Yes | Yes | Yes | No |
Stripe
Subscription (subscription). The source of truth is db.sb, and Stripe holds a copy written from it.
| Property | Stripe field | Source of truth |
|---|---|---|
status | status | Stripe |
renewsAt | items.data[].current_period_end | Stripe |
quantity | items.data[].quantity | db.sb |
trialEndsAt | trial_end | db.sb |
| State | Stripe status |
|---|---|
incomplete | incomplete |
trialing | trialing |
active | active |
pastDue | past_due |
paused | paused |
canceled | canceled |
Call it
Renew the latest subscription.Example
A dental office's Subscription to the $99 monthly reminders Offer renews on the 1st and bills one Invoice each month until the office unsubscribes.