Skip to main content

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

namestring

Display name, e.g. "Pro Monthly".

amountinteger

Price per billing cycle in cents. E.g. $5.00 is 500.

currencystring

A 3 letter ISO currency, e.g. USD.

intervalstring

Billing cadence: daily, weekly, monthly or yearly.

interval_countoptional, integer

Bill every N intervals (default 1). E.g. weekly + 2 bills every two weeks.

descriptionoptional, string

Shown on the hosted subscribe page.

trial_daysoptional, integer

Fixed-duration trial length in days. With no trial_amount the trial is free (the card is saved with no charge).

trial_amountoptional, integer

Intro price in cents during the trial. Omit for a free trial.

trial_cyclesoptional, integer

Cycle-based trial: the first N billing cycles are charged at trial_amount.

grace_period_daysoptional, integer

Days a past_due subscription keeps its entitlements (default 7).

dunning_scheduleoptional, array

Days after a failed charge to retry, e.g. [1, 3, 7] (the default). When exhausted the subscription is canceled.

featuresoptional, object

Entitlements granted by the plan: boolean flags or numeric limits, e.g. {"api_access": true, "seats": 5}. Queried via the entitlement endpoints.

POST /v202607/plans
const plan = await orchestrapay.plans.create({
name: 'Pro Monthly',
amount: 500,
currency: 'usd',
interval: 'monthly',
trial_days: 14,
features: { api_access: true, seats: 5 },
});
RESPONSE
{
"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_uuidstring

The plan to subscribe to (plan_…).

payment_methodstring

The saved card to charge (pm_…), returned by a save-on-file payment or card setup.

customer_uuidoptional, string

The customer (cus_…). Enables receipts, the customer portal and entitlement lookups by customer.

promotion_codeoptional, string

A customer-facing promotion code, e.g. "WELCOME20". The discount snapshots onto the subscription.

tax_rate_uuidoptional, string

Manual tax rate to apply to every invoice.

external_idoptional, string

Your own reference; also usable in entitlement checks.

feature_overridesoptional, object

Per-subscription entitlement overrides layered over the plan features (enterprise/custom deals).

webhook_urlsoptional, array

HTTPS endpoints for subscription.* and invoice.* events (Stripe-style envelope: id / type / created_at / data).

Statuses

trialingactivepast_due (dunning) → canceled, plus paused. Entitlements: active and trialing allow; past_due allows during the grace period; paused and canceled deny.

POST /v202607/subscriptions
const sub = await orchestrapay.subscriptions.create({
plan_uuid: 'plan_eu1_...',
payment_method: 'pm_eu1_...',
customer_uuid: 'cus_eu1_...',
promotion_code: 'WELCOME20',
});
RESPONSE
{
"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, string

Change 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, string

Queue a plan change for the next renewal instead (no proration).

payment_methodoptional, string

Point the subscription at a different saved card (pm_…).

feature_overridesoptional, object

Replace the per-subscription entitlement overrides.

webhook_urlsoptional, array

Replace 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 end
  • POST /v202607/subscriptions/:id/pause / …/resume — pause billing / resume (bills immediately)
  • POST /v202607/subscriptions/:id/reactivate — undo a scheduled cancel-at-period-end
PATCH /v202607/subscriptions/:id
// 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',
});
RESPONSE
// 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 cycle
  • subscription_cycle — a scheduled renewal
  • subscription_update — a proration charge from an immediate upgrade
RESPONSE
{
"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

namestring

Shown to the customer, e.g. "20% off 3 months".

percent_offoptional, number

Percentage discount. Exactly one of percent_off / amount_off is required.

amount_offoptional, integer

Fixed discount in cents. Requires currency.

durationstring

"once" (first invoice), "repeating" (next duration_in_months invoices) or "forever".

duration_in_monthsoptional, integer

Required when duration is "repeating".

max_redemptionsoptional, integer

Cap on total redemptions.

redeem_byoptional, string

ISO date after which the coupon can no longer be redeemed.

Endpoints

  • POST /v202607/coupons, GET /v202607/coupons, DELETE /v202607/coupons/:id
  • POST /v202607/promotion-codes — body { "coupon_uuid": "cpn_…", "code": "WELCOME20" }
  • GET /v202607/promotion-codes, DELETE /v202607/promotion-codes/:id
  • POST /v202607/tax-rates, GET /v202607/tax-rates, DELETE /v202607/tax-rates/:id
POST /v202607/coupons
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/items
  • DELETE /v202607/subscriptions/:id/items/:item — unused time credits the balance

Metered usage

  • POST /v202607/subscriptions/:id/usage-records — body { "quantity": 120, "action": "increment" } (set overrides the period total; subscription_item targets 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/schedules
  • DELETE /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 balance
  • GET /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 portal url
RESPONSE
// 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

planstring

The plan to subscribe to (plan_…).

promotion_codeoptional, string

Prefill a promotion code on the hosted page.

POST /v202607/checkout/sessions
const session = await orchestrapay.checkoutSessions.create({
plan: 'plan_eu1_...',
});
// share session.url with your customer
RESPONSE
{
"id": "cs_eu1_…",
"object": "checkout_session",
"url": "https://pay.orchestrapay.com/subscribe/acme/plan_eu1_…",
"plan": "plan_eu1_…"
}