Subscriptions
Throttle subscriptions turn a one-time embed payment into a recurring billing relationship. The card vaulted during checkout is reused on a 5-minute renewal cron, with built-in dunning and a webhook stream that lets your backend stay in sync.
What ships in v1
- Recurring on the embed. Pass a
recurringblock on a checkout session, the embed vaults the card, and (whencreate: 'auto'is set) Throttle creates the subscription on your behalf. - Lifecycle API. Cancel, pause, resume, change plan, list, and fetch
subscriptions through
@usethrottle/subscriptions/serverfrom your backend, or through the React hooks routed via your backend proxy. - Mid-period proration. A plan or seat change sent with
effective: 'now'credits the unused portion of the period the buyer already paid for, then charges the net — and skips the charge entirely when the credit covers it. The response carries aprorationbreakdown (creditCents,chargedCents,fullAmount). Sendeffective: 'period_end'to schedule the change for the next renewal instead, with no charge now. - React management package.
@usethrottle/subscriptionsexposes hooks and primitive components so your buyer-facing portal does not have to re-derive the API plumbing. - Built-in dunning. Hardcoded retry curve of
[1, 3, 7]days; after three failed renewal attempts the subscription auto-cancels with adunning_exhaustedreason. - Trial-fraud protection. Auto-create checks the card fingerprint against
prior subscriptions on this merchant; same card already used for a trial → new
subscription is created without a trial and a
subscription.trial_blockedwebhook fires. Pre-flight viaPOST /api/v1/subscriptions/eligibility-check. See Trial Fraud Protection . - Webhook stream.
subscription.created,.updated,.activated,.renewed,.past_due,.payment_failed,.paused,.resumed,.cancelled.
What is intentionally out of v1
- No-card free trials. Trials always require a vaulted card up front; the
embed does not yet support a "subscribe now, add card later" flow. Trials with a card
behave the way you expect — Throttle delays the first charge until
trialEnd. - Net30 recurring. Renewals charge a stored card via the payment provider. Net30 is supported for one-time orders today; Net30 recurring (invoice every period) is not part of the current subscription package surface.
- Customer-scoped JWTs. The React package authenticates by proxying through your backend. Direct browser → Throttle calls require a customer token system that is not yet built. See Buyer Portal for the proxy pattern documented for v1.
- Throttle-sent emails. All notifications flow through your webhook
endpoint; you decide which emails to send. Subscribing to
subscription.payment_failedis enough to wire the standard "your card was declined" copy. - Recurring discounts. Promotion codes apply to cart-backed checkout totals today. Ongoing subscription-cycle discounts are deferred.
- Configurable dunning curve. The retry schedule is fixed at
[1, 3, 7]days. Per-merchant or per-subscription overrides are deferred.
How the pieces fit
- Subscribe. Your backend creates a checkout session with a
recurringblock. Buyer pays through<PaymentEmbed />. Card is vaulted. Throttle auto-creates the subscription.onSucceededreturnssubscriptionId. - Renew. A cron runs every 5 minutes. For any subscription whose
currentPeriodEndhas passed, it charges the stored card with an idempotentchargeStoredcall and advances the period. On failure it follows the[1, 3, 7]retry curve. - Manage. Your buyer portal calls your backend, which proxies to the Throttle API. The React package gives you hooks for the common flows.
- React. Your webhook handler stays in sync — record renewals, send
dunning emails, gate access on
past_due.
Tax on renewals
A renewal has no cart and no shipping address, so there is nothing for a tax provider to quote against. Throttle solves that by freezing an address on the subscription at signup and reusing it on every renewal.
-
taxAddressSnapshot— the address renewals are quoted against. A subscription created through checkout inherits the address the buyer was taxed on. -
taxAddressSource—checkoutwhen it came from the buyer's session,manualonce a merchant has edited it. A later checkout never overwrites a manual correction.
To correct it, PATCH /api/v1/subscriptions/:id with a taxAddress object (countryCode
is required; the rest are optional). Merchants can do the same from the Tax card on the
subscription detail page in the dashboard. Sending null clears the snapshot, which leaves renewals untaxed.
Sequence: auto-subscribe on card capture
When a session ships with a recurring block and create: 'auto', Throttle vaults the card
during the embed's capture, runs the trial-fraud check, and creates the subscription
before returning to the parent page.
sequenceDiagram
participant B as Buyer
participant F as Throttle Iframe
participant P as Payment Provider
participant T as Throttle Backend
participant H as Webhook Endpoint
B->>F: fills card details
F->>P: authorize + tokenize
P-->>F: paymentMethodId
F->>T: POST /complete (recurring + create:auto)
T->>P: capture + vault payment method
P-->>T: vaulted token
T->>T: checkTrialEligibility(card fingerprint)
alt eligible for trial
T->>T: set trialEnd = now + trialDays
else fingerprint already used
T->>H: subscription.trial_blocked
end
T->>T: subscriptionService.create(...)
T-->>F: { orderId, paymentId, subscriptionId }
T->>H: subscription.created
F->>B: throttle.completed Pages in this section
- Quickstart — five-minute end-to-end.
- Creating Subscriptions — auto, manual, and webhook patterns.
- Customer Identity — externalCustomerId pattern + alternates.
- Lifecycle and States — state machine, trials, dunning.
- Trial Fraud Protection — card-fingerprint check + eligibility-check API.
- Testing — sandbox smoke tests and webhook assertions.
- Managing Subscriptions — pause, resume, cancel, change plan.
- Buyer Portal — the proxy pattern with templates.
- React Package —
@usethrottle/subscriptionsreference. - Subscription Webhooks — event types and payloads.
- Usage Reporting —
metered usage via
POST/GET .../usage; billed at renewal.