Recurring billing
Recurring billing charges Subscriptions on Stripe Billing, with trials, proration, metered usage, retries and dunning, while db.sb stays the record.
Recurring billing charges Subscriptions each period on Stripe, with trials, pauses, quantity changes, proration and renewal notices. db.sb keeps the record, and Stripe moves the money.
Contract
A Subscription is always in one of six statuses, and only a Verb call or the calendar moves it.
| Status | What the Customer has | Entered by |
|---|---|---|
trialing | The Offer free until Subscription.trialEndsAt | Offer.trial |
active | The Offer, billed each period at the Offer Version it accepted | Offer.subscribe, Subscription.resume or Subscription.keep |
paused | Nothing billed and no Entitlements until the pause ends | Subscription.pause |
ending | Full access until the period closes, then nothing | Subscription.unsubscribe |
pastDue | Access while Dunning retries a failed renewal | Subscription.renew |
canceled | No access, and still a Customer forever | The period closing after ending, or the last failed retry of Dunning |
| Move | Rule |
|---|---|
| Start a trial | Offer.trial takes days and card. With a card it converts when the trial ends; without one it ends and opens a conversion Task for the Success Manager. |
| Resize | Subscription.resize bills the prorated difference at once; a lower quantity takes effect at the next period. |
| Switch Offers | Subscription.switch prorates at once. A move to a cheaper Offer never waits; a higher Price reaches existing Customers only at their first renewal after notice. |
| Pause | Subscription.pause stops billing and Entitlements until until, and moves Subscription.renewsAt and Subscription.termEndsAt by the paused days. Subscription.resume ends a pause early. |
| Cancel | Subscription.unsubscribe runs at once, with no Limit, Approval or delay window, and records a reason code and the Customer’s own words as Evidence. |
| Take a cancel back | Subscription.keep restores renewal on the original date, on a cheaper Offer when the Customer took the one save offer. |
| Renew | Subscription.renew bills the next period at the accepted Version, never a newer Price, and adds each Meter’s usage exactly once. |
| Remind | Renewal notice writes 15 to 45 days before a term of a year or longer renews, and 3 to 21 days before a trial over 31 days converts. |
A cancel’s reason code is one of tooExpensive, missingCapability, switched, unused, notNeeded, wrongFit, service or other. Each maps one to one onto Stripe’s cancellation feedback, so both records agree.
Verbs
Interfaces
Example
import { $ } from 'startup-builder'
// tutorloop.com sells Family at $40 a month per learner. A parent starts a 14-day trial with a card.
const { subscription } = await $.Offer.trial({ offer: 'offer_family', customer: 'customer_1', days: 14, card: true })
// The trial converted on May 1. On May 16 a second learner joins: $20 prorated is billed at once.
await $.Subscription.resize({ subscription: subscription.$id, quantity: 2 })
// The family travels in July. Billing stops until August 1, and each later renewal moves by the paused days.
await $.Subscription.pause({ subscription: subscription.$id, until: '2026-08-01' })
// In September the parent cancels in one step; the status is ending, and access lasts until the period closes.
await $.Subscription.unsubscribe({ subscription: 'subscription_1', reason: 'tooExpensive', comment: 'Two learners is a stretch this term.' })
// The one save offer is the $30 Family Lite Offer. The parent takes it before the period closes.
await $.Subscription.keep({ subscription: 'subscription_1', offer: 'offer_family_lite' })