Subscriptions API
Recurring billing on saved cards: plans, subscriptions, invoices, coupons and hosted checkout sessions. Concepts (trials, proration, dunning, entitlements) are explained in the Subscriptions guide.
All objects use Stripe-style string ids (plan_…, sub_…, in_…, cpn_…,
promo_…) and an object discriminator. Amounts are integer minor units with
a lowercase 3-letter currency.
Create a plan
The reusable pricing template subscriptions are created from. Price fields are immutable after creation — existing subscribers keep their grandfathered price; create a new plan to change pricing.
Parameters
namestringDisplay name, e.g. "Pro Monthly".
amountintegerPrice per billing cycle in cents. E.g. $5.00 is 500.
currencystringA 3 letter ISO currency, e.g. USD.
intervalstringBilling cadence: daily, weekly, monthly or yearly.
interval_countoptional, integerBill every N intervals (default 1). E.g. weekly + 2 bills every two weeks.
descriptionoptional, stringShown on the hosted subscribe page.
trial_daysoptional, integerFixed-duration trial length in days. With no trial_amount the trial is free (the card is saved with no charge).
trial_amountoptional, integerIntro price in cents during the trial. Omit for a free trial.
trial_cyclesoptional, integerCycle-based trial: the first N billing cycles are charged at trial_amount.
grace_period_daysoptional, integerDays a past_due subscription keeps its entitlements (default 7).
dunning_scheduleoptional, arrayDays after a failed charge to retry, e.g. [1, 3, 7] (the default). When exhausted the subscription is canceled.
featuresoptional, objectEntitlements granted by the plan: boolean flags or numeric limits, e.g. {"api_access": true, "seats": 5}. Queried via the entitlement endpoints.
const plan = await orchestrapay.plans.create({
name: 'Pro Monthly',
amount: 500,
currency: 'usd',
interval: 'monthly',
trial_days: 14,
features: { api_access: true, seats: 5 },
});{
"id": "plan_eu1_1f0e9d8c7b6a5f4e3d2c1b0a99887766",
"object": "plan",
"name": "Pro Monthly",
"description": null,
"amount": 500,
"currency": "usd",
"interval": "monthly",
"interval_count": 1,
"trial_days": 14,
"trial_amount": null,
"trial_cycles": 0,
"grace_period_days": 7,
"dunning_schedule": [1, 3, 7],
"features": { "api_access": true, "seats": 5 },
"is_active": true,
"created_at": "2026-07-18T00:00:00.000Z"
}Create a subscription
Subscribes a saved card to a plan. With no trial the first cycle is charged
immediately; renewals charge automatically on schedule. The card comes from a
payment made with save_on_file (or a setup) — the payment form returns the
pm_… handle.
Parameters
plan_uuidstringThe plan to subscribe to (plan_…).
payment_methodstringThe saved card to charge (pm_…), returned by a save-on-file payment or card setup.
customer_uuidoptional, stringThe customer (cus_…). Enables receipts, the customer portal and entitlement lookups by customer.
promotion_codeoptional, stringA customer-facing promotion code, e.g. "WELCOME20". The discount snapshots onto the subscription.
tax_rate_uuidoptional, stringManual tax rate to apply to every invoice.
external_idoptional, stringYour own reference; also usable in entitlement checks.
feature_overridesoptional, objectPer-subscription entitlement overrides layered over the plan features (enterprise/custom deals).
webhook_urlsoptional, arrayHTTPS endpoints for subscription.* and invoice.* events (Stripe-style envelope: id / type / created_at / data).
Statuses
trialing → active ⇄ past_due (dunning) → canceled, plus paused.
Entitlements: active and trialing allow; past_due allows during the grace
period; paused and canceled deny.
const sub = await orchestrapay.subscriptions.create({
plan_uuid: 'plan_eu1_...',
payment_method: 'pm_eu1_...',
customer_uuid: 'cus_eu1_...',
promotion_code: 'WELCOME20',
});{
"id": "sub_eu1_265ec4c71e314901a7b01885d05ecc96",
"object": "subscription",
"status": "active",
"amount": 500,
"currency": "usd",
"interval": "monthly",
"interval_count": 1,
"discount": {
"coupon_uuid": "…",
"name": "20% off 3 months",
"percent_off": 20,
"remaining_cycles": 2
},
"current_period_start": "2026-07-18T00:00:00.000Z",
"current_period_end": "2026-08-18T00:00:00.000Z",
"next_billing_at": "2026-08-18T00:00:00.000Z",
"cancel_at_period_end": false,
"plan": { "id": "plan_eu1_…", "object": "plan", "name": "Pro Monthly" },
"customer": { "id": "cus_eu1_…", "object": "customer", "email": "jo@example.com" }
}Update a subscription
Change the card, apply an immediate prorated plan change, queue a period-end switch, or adjust overrides and webhooks.
Parameters
plan_uuidoptional, stringChange plan NOW. Prorated per proration_behavior; the billing anchor does not move. Requires the same currency and interval as the current plan.
proration_behavioroptional, string"create_prorations" (default): an upgrade charges the prorated difference immediately, a downgrade credits the customer balance. "none": swap with no settlement. "always_invoice" is an alias of create_prorations.
pending_plan_uuidoptional, stringQueue a plan change for the next renewal instead (no proration).
payment_methodoptional, stringPoint the subscription at a different saved card (pm_…).
feature_overridesoptional, objectReplace the per-subscription entitlement overrides.
webhook_urlsoptional, arrayReplace the webhook targets.
Other subscription endpoints
GET /v202607/subscriptions— list (filter with?plan=plan_…)GET /v202607/subscriptions/:id— retrieve (includes plan, customer, invoices)GET /v202607/subscriptions/:id/upcoming— preview the next renewal, or a plan change's proration with?plan=plan_…POST /v202607/subscriptions/:id/cancel— body{ "immediately": false, "reason": "…" }; default cancels at period endPOST /v202607/subscriptions/:id/pause/…/resume— pause billing / resume (bills immediately)POST /v202607/subscriptions/:id/reactivate— undo a scheduled cancel-at-period-end
// Preview, then apply an immediate prorated upgrade
const preview = await orchestrapay.subscriptions.upcoming(
'sub_eu1_...',
{ plan: 'plan_eu1_...' },
);
// preview.amount_due_now -> 1500
await orchestrapay.subscriptions.update('sub_eu1_...', {
plan_uuid: 'plan_eu1_...',
proration_behavior: 'create_prorations',
});// GET /v202607/subscriptions/:id/upcoming?plan=plan_…
{
"object": "upcoming_invoice",
"preview_type": "plan_change",
"currency": "usd",
"credit_unused": 500,
"charge_remaining": 2000,
"amount_due_now": 1500,
"credit_to_balance": 0,
"period_end": "2026-08-18T00:00:00.000Z"
}Invoices
One invoice per billing attempt (paid or failed) with the full amount
breakdown: amount = subtotal - discount + tax - credit_applied.
Endpoints
GET /v202607/invoices— list (filter with?subscription=sub_…)GET /v202607/invoices/:id— retrieve
Billing reasons
subscription_create— the first cyclesubscription_cycle— a scheduled renewalsubscription_update— a proration charge from an immediate upgrade
{
"id": "in_eu1_b201396b19db40e8b46a6cfb42958c34",
"object": "invoice",
"amount": 400,
"subtotal": 500,
"discount": 100,
"tax": 0,
"credit_applied": 0,
"currency": "usd",
"status": "paid",
"billing_reason": "subscription_create",
"period_start": "2026-07-18T00:00:00.000Z",
"period_end": "2026-08-18T00:00:00.000Z",
"transaction_intent": "ti_eu1_…",
"is_trial": false,
"attempt_count": 1,
"paid_at": "2026-07-18T00:00:00.000Z",
"subscription": "sub_eu1_…"
}Coupons and promotion codes
Coupon parameters
namestringShown to the customer, e.g. "20% off 3 months".
percent_offoptional, numberPercentage discount. Exactly one of percent_off / amount_off is required.
amount_offoptional, integerFixed discount in cents. Requires currency.
durationstring"once" (first invoice), "repeating" (next duration_in_months invoices) or "forever".
duration_in_monthsoptional, integerRequired when duration is "repeating".
max_redemptionsoptional, integerCap on total redemptions.
redeem_byoptional, stringISO date after which the coupon can no longer be redeemed.
Endpoints
POST /v202607/coupons,GET /v202607/coupons,DELETE /v202607/coupons/:idPOST /v202607/promotion-codes— body{ "coupon_uuid": "cpn_…", "code": "WELCOME20" }GET /v202607/promotion-codes,DELETE /v202607/promotion-codes/:idPOST /v202607/tax-rates,GET /v202607/tax-rates,DELETE /v202607/tax-rates/:id
const coupon = await orchestrapay.coupons.create({
name: '20% off 3 months',
percent_off: 20,
duration: 'repeating',
duration_in_months: 3,
});
await orchestrapay.promotionCodes.create({
coupon_uuid: coupon.id,
code: 'WELCOME20',
});Products, items, usage and schedules
Products
Group the price variants of one offering; pass product_uuid when creating
plans.
POST /v202607/products— body{ "name": "…", "description": "…" }GET /v202607/products,GET /v202607/products/:id,PATCH /v202607/products/:id
Pricing models on plans
Plans accept pricing_model (flat / per_unit / tiered / metered),
tiers + tiers_mode (graduated / volume), and currency_options
(alternate currencies for the hosted page). See the
guide for the math.
Add-on items
POST /v202607/subscriptions/:id/items— body{ "plan": "plan_…", "quantity": 1, "proration_behavior": "create_prorations" }GET /v202607/subscriptions/:id/itemsDELETE /v202607/subscriptions/:id/items/:item— unused time credits the balance
Metered usage
POST /v202607/subscriptions/:id/usage-records— body{ "quantity": 120, "action": "increment" }(setoverrides the period total;subscription_itemtargets an add-on)GET /v202607/subscriptions/:id/usage— current-period total
Scheduled changes
POST /v202607/subscriptions/:id/schedules— body{ "effective_at": "2027-01-01T00:00:00Z", "plan": "plan_…", "quantity": 10 }GET /v202607/subscriptions/:id/schedulesDELETE /v202607/subscriptions/:id/schedules/:schedule(not-yet-applied only)
Credit notes
POST /v202607/credit-notes— body{ "invoice": "in_…", "amount": 200, "reason": "…" }; the amount credits the customer balanceGET /v202607/credit-notes?invoice=in_…
Invoice PDF
GET /v202607/invoices/:id/pdf— renders the invoice as a PDF
Billing portal sessions
POST /v202607/billing-portal/sessions— body{ "customer": "jo@example.com" }; returns a 15-minute login-free portalurl
// A tiered per-seat plan
{
"id": "plan_eu1_…",
"object": "plan",
"pricing_model": "tiered",
"tiers_mode": "graduated",
"tiers": [
{ "up_to": 10, "unit_amount": 500 },
{ "up_to": null, "unit_amount": 300 }
],
"currency_options": { "eur": 450 },
"amount": 500,
"currency": "usd",
"interval": "monthly"
}
// An invoice with the per-line breakdown
{
"id": "in_eu1_…",
"object": "invoice",
"amount": 6100,
"lines": [
{ "description": "Team plan", "quantity": 12, "unit_amount": 500, "amount": 5600 },
{ "description": "Priority support", "quantity": 1, "unit_amount": 500, "amount": 500 }
],
"status": "paid"
}Checkout sessions
The zero-integration path: mint a hosted subscribe URL for a plan and share it. The customer enters their card on the hosted page (branded per tenant) and the subscription auto-creates — trials use a no-charge card setup, paid plans charge the first cycle on the spot.
Parameters
planstringThe plan to subscribe to (plan_…).
promotion_codeoptional, stringPrefill a promotion code on the hosted page.
const session = await orchestrapay.checkoutSessions.create({
plan: 'plan_eu1_...',
});
// share session.url with your customer{
"id": "cs_eu1_…",
"object": "checkout_session",
"url": "https://pay.orchestrapay.com/subscribe/acme/plan_eu1_…",
"plan": "plan_eu1_…"
}