Pick a path
Three situations, three different endpoints:POST /checkout/session and POST /subscription are not two spellings of the same call. The first gives the customer an interactive checkout; the second is for a server that already has both a customer and a payment instrument.1. Prepare a recurring product and price
Subscriptions require a pre-registered Product and a recurring price. The inlinepriceDataList approach cannot create one.
interval accepts day, week, month, year, quarter, half_year, and custom.
quarter and half_year are resolved by the platform — do not convert them into 3 or 6 months yourself. intervalCount only means a number of days when interval is custom.flat_rate price. For other pricing models, see the field reference in Create price.
2. Recommended: create the first subscription through Checkout
The shape is identical to a one-time payment — your backend creates the Session, the frontend opens checkout, webhooks update local state. Only the item changes, from an inline product to a recurring price.3. Server-side: create the subscription directly
Use this when the customer already has a Clink Customer record and a usable payment instrument.customerId, customerEmail, or referenceCustomerId. The recurring price must belong to your merchant and support the paymentCurrency you send.
Whether a given payment method works for subscriptions also depends on your channel configuration and currency. Verify each method your account has actually enabled rather than assuming a shared list.
status in the response describes this payment attempt:
The response also returns
subscriptionId, sessionId, paymentInstrumentId, orderId, and invoiceId. Store all five on your own subscription record — one field alone will not be enough for later queries and reconciliation.
4. Mapping subscription status to access
This is where subscription integrations most often go wrong. Payment status and entitlement status are two different things.5. Events to subscribe to
Theorder.* events from one-time payments still apply. Subscriptions add these.
Lifecycle
subscription.created, subscription.trialing, subscription.activated, subscription.past_due, subscription.incomplete_expired, subscription.cancelled
Plan changes
subscription.updated.plan_changed, subscription.updated.plan_change_canceled, subscription.updated.renewed, subscription.updated.cancel_at_period_end_set, subscription.updated.cancel_at_period_end_revoked
Invoices
invoice.open, invoice.paid, invoice.void
Events are retried and arrive out of order. Your handler must at least:
- Deduplicate atomically on
event.id - Resolve out-of-order arrivals by subscription status precedence, so an older event cannot overwrite a newer state
- Run fulfillment for a given
invoiceIdexactly once
6. Cancellation
reason is required, 1 to 255 characters. cancelReasonCode is optional and accepts too_expensive, need_more_features, found_alternative, no_longer_needed, poor_customer_service, poor_usability, poor_quality, and other_reasons.
Omitting cancelImmediately or sending false cancels at the end of the current period. Sending true cancels immediately.
7. Plan changes
Preview first, then confirm. Both steps requirequantity.
Step one — preview
priceSnapshotId from the preview
immediate: true may produce a prorated charge and return an action. false schedules the change for the next billing boundary. A pending change can be withdrawn with POST /subscription/{id}/update/cancel.
The current API Reference request examples for preview and confirm omit
quantity, but the server requires it. Follow this page and send it in both calls.8. Scheduled phases
scheduledPhases lets a subscription switch plans automatically at future renewal boundaries, up to 10 phases, with sequence and effectiveCycle both starting at 1 and strictly increasing.
This is an advanced capability you will not need for a first integration. Field details are in Checkout Session.
Next
Discounts and promotion codes
Adding discounts, and how many periods they last.
Go live
Subscription checks before production.