Subscriptions

Manage recurring billing with trials, discounts, and lifecycle events

Subscriptions automate recurring billing by charging customers at regular intervals. RevKeen handles billing dates, invoicing, payment collection, and dunning automatically. This page covers the complete subscription lifecycle.

A subscription that collects by Direct Debit still needs an Active mandate and advance notice before each collection. If the mandate is missing at renewal, RevKeen sends a setup invitation — that email authorises the mandate; it does not take the renewal by itself. See Direct Debit.

Subscription Lifecycle

┌─────────┐     ┌──────────┐     ┌────────┐
│ PENDING │────>│ TRIALING │────>│ ACTIVE │
└─────────┘     └──────────┘     └───┬────┘
                                     │
                    ┌────────────────┼────────────────┐
                    │                │                │
                    v                v                v
              ┌──────────┐    ┌──────────┐    ┌──────────┐
              │ PAST_DUE │    │  PAUSED  │    │ CANCELED │
              └────┬─────┘    └──────────┘    └──────────┘
                   │
                   v
              ┌──────────┐
              │  UNPAID  │
              └────┬─────┘
                   │
                   v
              ┌──────────┐
              │ EXPIRED  │
              └──────────┘

Subscription Statuses

StatusDescriptionBilling
pendingSubscription created, awaiting first paymentNot billing
trialingIn free trial periodNot billing
activeActive and billing normallyBilling
past_duePayment failed, retryingAttempting
pausedTemporarily paused by customer or merchantNot billing
canceledSubscription endedNot billing
unpaidAll payment retries exhaustedStopped
expiredSubscription term ended without renewalStopped

Creating Subscriptions

Via Checkout

The most common way to create subscriptions is through checkout links:

  1. Create a checkout link with a recurring price
  2. Customer completes checkout
  3. Subscription is automatically created
  4. First invoice is generated and charged

Via API

import { RevKeenClient } from "@revkeen/sdk";

const client = new RevKeenClient({ apiKey: process.env.REVKEEN_API_KEY! });

const { data: subscription } = await client.subscriptions.create({
  customerId: "11111111-1111-4111-8111-111111111111",
  priceId: "55555555-5555-4555-8555-555555555555", // a recurring GBP price
  currency: "gbp",
  quantity: 1,

  // Optional: end a free trial on a set date
  trialEnd: "2026-11-01T00:00:00Z",
});

console.log(subscription.status); // "trialing" or "active"

If the price has a trial period (trial_period_days), it is applied automatically. Send trial_period_days to use a different length, or 0 to start without the trial. The billing interval (for example, "Billed monthly") is shown on invoices, receipts, and the checkout success page.

See Create a subscription for every field, including Direct Debit (paymentRail: "direct_debit" with a mandateId).

Quantity

A subscription created through the API bills one price, multiplied by its quantity. For example, a £10.00 per-seat price with quantity: 5 bills £50.00 each period. Each price appears as its own line on the invoice.

await client.subscriptions.update("sub_xxxxxxxx", { quantity: 5 });

Trial Periods

Trials allow customers to try your product before paying:

  • Subscription status is trialing
  • Customer has full access during the trial
  • No payment is collected
  • At trial end, first invoice is created and charged
  • If payment fails, subscription enters past_due

Trial periods can be set on the Price or overridden when creating the subscription, with trial_period_days or an explicit trialEnd (not both).

Billing Cycle

Each subscription has a billing cycle that determines when invoices are generated:

FieldDescription
intervalBilling frequency: day, week, month, quarter, half_year, year
interval_countNumber of intervals between charges (e.g., 2 with month = every 2 months)
current_period_startStart of current billing period
current_period_endEnd of current billing period
billing_cycle_anchorDay of month/year for billing (e.g., 1st of each month)

The billing interval is automatically shown on invoices, receipts, and the checkout success page so customers always know when their next charge will occur.

Where the schedule comes from

The product catalogue holds the Billing Schedule template. Checkout links inherit that template. An invoice can use the product standard or, when Customize for this invoice is on, store sale-time terms that win over the product.

After the sale, the subscription is the only runtime truth. Changing the product schedule later does not rewrite live subscriptions. To change an existing customer’s cadence, update that subscription (or cancel and resell) — do not expect a catalogue edit to flow through.

Changing Plans

A plan or quantity change takes effect straight away. The price difference for the rest of the current period is billed on the next renewal invoice, on card and Direct Debit alike:

  • Upgrade — the difference is added to the next renewal invoice as its own line.
  • Downgrade — the unused time becomes a credit on the next renewal invoice. It is never refunded. If the credit is larger than the renewal, that renewal is £0 and the rest carries to the one after.
  • Several changes in one period — their differences are added together into one line on the next invoice.
  • No proration — the new price simply starts from the next renewal.

Card subscriptions: Charge difference now. On an active card subscription, an upgrade can be charged to the customer's card at the moment you change the plan, from the dashboard. You confirm the amount, including tax, and prove it is you with a passkey or authenticator app. The plan changes only if the charge succeeds; a declined card changes nothing. Owners and admins are emailed each time. A downgrade credit is never refunded; it stays on the next invoice. Direct Debit subscriptions are always billed on the next invoice. This option is being rolled out and may not be on your account yet.

Change a subscription's plan from its page in the dashboard, where you can review the proration before you confirm, or through the API:

  • POST /v2/subscriptions/{id}/preview-change-plan shows what the change would do: the new renewal amount, the proration for this change, and what the next renewal invoice would add or credit (pending_proration_net_amount_minor). It changes nothing. It needs the subscriptions:read scope and the subscription:read permission.
  • POST /v2/subscriptions/{id}/change-plan makes the change with the same calculation, so it stores the figures the preview showed (as of the moment you call it). Nothing is charged when the plan changes. It needs the subscriptions:write scope and the subscription:update permission, and sends subscription.plan_changed.

Both take newPlanId (a price, or a product, which resolves to its default price) and optionally prorationBehavior (next_invoice or none) and effectiveDate. prorationBehavior: invoice_immediately is applied as next_invoice and never charges, on every API version up to 2026-05-01; the response carries a Deprecation header and a Link to the versioning guide. From RevKeen-Version 2026-11-02 it means "charge the card now", which is a dashboard action: a card subscription gets 403 charge_now_requires_interactive_session and any other gets 400 charge_now_card_only, and nothing is changed. The new price must bill on the subscription's own interval and in its currency, and must have an amount above zero; otherwise the call is refused with 400 (interval_mismatch, currency_mismatch, price_amount_missing) and nothing changes.

A Direct Debit subscription cannot change plan through the API: a new amount needs advance notice to the payer, so the call is refused with 409 direct_debit_plan_change_unsupported. Change it from the dashboard.

Cancelling Subscriptions

Active, paused, and past-due subscriptions can be cancelled immediately. Cancellation stops future renewals and revokes access, while preserving existing invoices and payment history. It does not settle or write off unpaid invoices. Cancellation at the end of the billing period is available for active subscriptions.

// Cancel at end of billing period (recommended)
await client.subscriptions.cancel("sub_xxxxxxxx", {
  mode: "period_end",
  reason: "Customer requested",
});

// Cancel immediately (stop access now)
await client.subscriptions.cancel("sub_xxxxxxxx", {
  mode: "immediately",
});

Warning: Immediate cancellation stops access right away. Use mode: "period_end" to let customers use their remaining time.

Pausing and Resuming Subscriptions

Pause an active or trialing subscription immediately, and resume it later:

await client.subscriptions.pause("sub_xxxxxxxx");

// Later
await client.subscriptions.resume("sub_xxxxxxxx");

Neither call takes any parameters. They need the subscriptions:write scope and a role that holds the subscription:pause and subscription:resume permissions. Send an Idempotency-Key header to make retries safe.

While paused the subscription has status paused and no renewal invoices are generated or collected. A pause never ends by itself: resume it when you are ready. Nothing already issued is voided or recalled, and invoices that were open when you paused stay open. A Direct Debit subscription also stops collecting, and the pause response lists those open invoices in dd_collection_stopped so you can decide how to collect them.

On resume the subscription returns to active. The periods that elapsed while it was paused are not billed: it keeps its billing day, and the next charge is the next billing date after you resume. A Direct Debit subscription resumes only if its mandate can collect now. Otherwise the call is refused with 409 mandate_not_usable (or 409 direct_debit_not_configured), the subscription stays paused, and details.mandate_usability_code says why.

A subscription in any other status is refused with 400 invalid_status, and nothing changes.

To pause a subscription once its current paid period ends instead, set pauseAtPeriodEnd:

await client.subscriptions.update("sub_xxxxxxxx", { pauseAtPeriodEnd: true });

This lets customers use their remaining paid time before the pause.

Billing Anchor Day

Set the day of the month the subscription bills on, when you create it or later:

// Bill on the 15th of each month
await client.subscriptions.update("sub_xxxxxxxx", {
  billingAnchorDay: 15, // 1-31
});

// For days 29-31, billing falls back to the last day of shorter months

Smart Payment

RevKeen automatically retries failed payments, distinguishing between temporary and permanent failures.

Failure TypeExamplesRetry Behavior
Soft DeclineInsufficient funds, expired cardRetry on days 1, 3, 7
Hard DeclineLost/stolen card, fraudNo retry, request new card

See Smart Payment for the collection strategy, and Dunning for the full recovery schedule, including Direct Debit.

Order Creation on Renewal

When a subscription renews and the invoice is paid, RevKeen checks whether the subscription contains products with a fulfillment_type of physical or digital. If so, an Order is automatically created to track fulfillment for that billing period.

This means a subscription for a monthly physical product (e.g., a supplement box) will create a new order every month when the renewal invoice is paid. Products with fulfillment_type: none (e.g., SaaS access) do not create orders.

Dunning (Payment Recovery)

When a subscription payment fails, RevKeen automatically enters the dunning process:

  1. Subscription status changes to past_due
  2. Payment is retried according to your retry schedule
  3. Customer receives reminder emails
  4. If all retries fail, subscription becomes unpaid or canceled

Configure dunning behavior at Settings > Dunning including retry intervals, email templates, and end behavior. See the Dunning page for details.

Subscription Events

These public webhook events cover the subscription lifecycle. The full list is in the event catalogue.

EventWhen Triggered
subscription.createdSubscription is created (before activation)
subscription.activatedSubscription becomes active after a successful payment
subscription.renewedBilling period renews successfully; a new invoice has been created and paid
subscription.canceledSubscription is cancelled
subscription.pausedSubscription is paused immediately, through the API or the dashboard, or by the customer in the portal
subscription.resumedA paused subscription is resumed, through the API or the dashboard
subscription.plan_changedA subscription moves to another price, through the API or the dashboard
invoice.createdA renewal invoice is created
invoice.paidA renewal invoice is paid
payment.failedA renewal payment attempt failed
collection.failedA Direct Debit renewal collection failed

There are no public events for trial endings or dunning transitions yet. A resume the customer makes in the portal, and a pause scheduled for the end of the period taking effect, are not announced by subscription.resumed or subscription.paused. Read the subscription with client.subscriptions.get to see its current status.

API reference for this workflow

Owner: david · Reviewed 10 Oct 2026 · Next review 30 Oct 2026

On this page