A valid request URL is required to generate request examples{
"subscription": {
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"customer_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"plan_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"status": "incomplete",
"current_period_start": "2023-11-07T05:31:56Z",
"current_period_end": "2023-11-07T05:31:56Z",
"cancel_at_period_end": true,
"canceled_at": "2023-11-07T05:31:56Z",
"trial_ends_at": "2023-11-07T05:31:56Z",
"provider": "stripe",
"provider_account_id": "<string>",
"provider_subscription_id": "<string>",
"provider_synced_at": "2023-11-07T05:31:56Z",
"created_at": "2023-11-07T05:31:56Z",
"updated_at": "2023-11-07T05:31:56Z",
"items": [
{
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"quantity": 123,
"price": {
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"plan_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"kind": "recurring",
"currency": "<string>",
"amount_minor": 123,
"tax_behavior": "inclusive",
"archived": true
}
}
],
"capabilities": {
"scheduled_plan_change": true,
"proration": true,
"cancel_at_period_end": true,
"hosted_portal": true,
"tax_calculation": true,
"resume_subscription": true,
"list_invoices": true,
"list_catalogue": true,
"publish_catalogue": true,
"manage_coupons": true,
"pause_subscription": true,
"discount_subscription": true,
"refund_payment": true
},
"mirror_refreshed": true,
"mirror_stale_reason": "provider_reread_failed",
"unmapped_provider_price_id": "<string>"
},
"checkout": {
"url": "<string>",
"session_ref": "<string>",
"expires_at": "2023-11-07T05:31:56Z"
}
}{
"error": {
"code": "forbidden",
"message": "your role does not allow this action"
}
}{
"error": {
"code": "forbidden",
"message": "your role does not allow this action"
}
}{
"error": {
"code": "forbidden",
"message": "your role does not allow this action"
}
}{
"error": {
"code": "forbidden",
"message": "your role does not allow this action"
}
}{
"error": {
"code": "forbidden",
"message": "your role does not allow this action"
}
}{
"error": {
"code": "forbidden",
"message": "your role does not allow this action"
}
}{
"error": {
"code": "forbidden",
"message": "your role does not allow this action"
}
}{
"error": {
"code": "forbidden",
"message": "your role does not allow this action"
}
}Start a checkout
Requires billing:write. Puts one of your prices in front of one of your customers and answers with somewhere to send them.
What exists after this call
A subscription here, with status incomplete and an empty provider_subscription_id, and a checkout URL at the gateway. Nobody has paid. The subscription becomes real when the payer completes the checkout and the gateway tells us so — until then it is a row that exists here and nowhere else, which is why nothing about it can be changed or cancelled yet.
A checkout the payer abandons leaves that row behind, and that is deliberate: it is never deleted, because a subscription is never deleted. Several pending checkouts in one environment are several real pending checkouts.
Retrying it
Send an Idempotency-Key. A repeat under the same key answers the same subscription and the same checkout URL instead of starting a second one — which is what a lost response needs, since the first attempt’s session is already live and payable.
The price has to be sellable and chargeable
It must be recurring — a one_time price is a payment and has no subscription behind it — and it must not be archived, because withdrawing an offer is exactly the act of no longer selling it.
It must also be mapped onto the gateway: a price in your catalogue is a price here, and the gateway needs its own id for it. The mapping is per merchant account, and the account is only known after the connection’s health check has asked who the keys belong to — so an unverified connection is refused with something to go and do rather than a guess about which account collects the money.
A returning payer is not duplicated
If this customer has paid through this gateway before, the gateway’s own id for them is found and reused, so they keep one payment method and one billing history. Finding it takes a read at the gateway, and if that read cannot be made the checkout is refused rather than falling through to creating a second payer record — there is no un-merge at a gateway either.
If they have never paid, the gateway creates the payer and collects the address itself.
trial_days
Passes a free period to the gateway. Omitted, the checkout carries whatever the price itself promises — trial_days is part of the offer and lives on the catalogue price — so the pricing page and the checkout tell one story by default. Sending a value overrides the price’s for this checkout only, and an explicit 0 waives the trial. The trial’s end date is not written here until the gateway says what it is: now + trial_days would be a date an entitlement expires on that nothing happens at.
Discounting it
coupon_id applies one of this environment’s coupons. The gateway needs a coupon object of its own to honour it, so the first checkout that applies a coupon on a gateway account creates it there and every later one reuses it — which is why the discount needs the gateway’s manage_coupons capability, and a gateway without it answers 501 rather than silently charging full price to somebody who was shown a discount. An amount coupon must discount the price’s own currency; an archived or expired coupon is refused by name.
allow_promotion_codes opens a field at the gateway’s checkout page where the payer types a code of their own — codes you configured at the gateway. It is mutually exclusive with coupon_id (two ways to discount one checkout) and needs the same capability.
A valid request URL is required to generate request examples{
"subscription": {
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"customer_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"plan_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"status": "incomplete",
"current_period_start": "2023-11-07T05:31:56Z",
"current_period_end": "2023-11-07T05:31:56Z",
"cancel_at_period_end": true,
"canceled_at": "2023-11-07T05:31:56Z",
"trial_ends_at": "2023-11-07T05:31:56Z",
"provider": "stripe",
"provider_account_id": "<string>",
"provider_subscription_id": "<string>",
"provider_synced_at": "2023-11-07T05:31:56Z",
"created_at": "2023-11-07T05:31:56Z",
"updated_at": "2023-11-07T05:31:56Z",
"items": [
{
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"quantity": 123,
"price": {
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"plan_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"kind": "recurring",
"currency": "<string>",
"amount_minor": 123,
"tax_behavior": "inclusive",
"archived": true
}
}
],
"capabilities": {
"scheduled_plan_change": true,
"proration": true,
"cancel_at_period_end": true,
"hosted_portal": true,
"tax_calculation": true,
"resume_subscription": true,
"list_invoices": true,
"list_catalogue": true,
"publish_catalogue": true,
"manage_coupons": true,
"pause_subscription": true,
"discount_subscription": true,
"refund_payment": true
},
"mirror_refreshed": true,
"mirror_stale_reason": "provider_reread_failed",
"unmapped_provider_price_id": "<string>"
},
"checkout": {
"url": "<string>",
"session_ref": "<string>",
"expires_at": "2023-11-07T05:31:56Z"
}
}{
"error": {
"code": "forbidden",
"message": "your role does not allow this action"
}
}{
"error": {
"code": "forbidden",
"message": "your role does not allow this action"
}
}{
"error": {
"code": "forbidden",
"message": "your role does not allow this action"
}
}{
"error": {
"code": "forbidden",
"message": "your role does not allow this action"
}
}{
"error": {
"code": "forbidden",
"message": "your role does not allow this action"
}
}{
"error": {
"code": "forbidden",
"message": "your role does not allow this action"
}
}{
"error": {
"code": "forbidden",
"message": "your role does not allow this action"
}
}{
"error": {
"code": "forbidden",
"message": "your role does not allow this action"
}
}Autorizações
A staff session token, uk_st_…. Minted by sign-up, sign-in or the two-factor exchange. Only a 401 means it is spent; not_a_member (403) is about the organization named in X-Organization-Id and leaves the token good for the others.
Cabeçalhos
The organization the caller is acting on — the org_… code that appears in the panel URL. It identifies; the membership JOIN is what authorizes, so a forged code reads nothing: the answer is not_a_member (403), which does not mean the session is over. Absent, the session's default organization answers, or — if that membership was revoked while the session was open — any other one the caller still holds.
A key you choose that makes starting a checkout safe to retry, end to end.
A repeat under the same key does not start a second checkout: it answers the same subscription and the same gateway session as the first attempt, with Idempotent-Replay: true. That is what a lost response needs — the first attempt's session is live and payable, and the answer that went missing carries the only id tying a payment to a row.
The key names one act. Sent with a different customer, price or quantity it is refused (422, idempotency_key_reused), and once the checkout it started has been paid it is refused (409, checkout_already_completed) rather than putting a second session in front of somebody who is already subscribed. Send a fresh key per checkout you mean to start: two checkouts for one customer on one price are two real checkouts, and the key is the only thing that can say otherwise.
It is forwarded to the gateway as its idempotency key too, so the retry and the original arrive there as one request. Retry with the body unchanged — the gateway compares every parameter, including success_url and cancel_url, and answers a mismatch with a refusal of its own.
255Parâmetros de consulta
Which environment to act in. A view parameter, valid only on the staff surface — a machine credential never chooses its environment, it is resolved from the key.
live, test Corpo
Who is being billed. Must be a customer of this environment.
The catalogue price to sell, in this environment. Recurring, not archived, and mapped onto the gateway.
Where the payer lands after paying. Required, and it has to be an http(s) URL.
Seats or units. 1 when omitted; 0 is refused, because a line for none of something is not a line. On a per_seat price it is refused entirely: the quantity is the customer's own member count, derived here and kept in step automatically.
x >= 1Where they land if they back out. Optional — a gateway with no cancel destination returns them itself.
Free days before the first charge. Omit to carry what the price itself promises; send a value to override for this checkout, and an explicit 0 to waive the trial.
x >= 0A coupon from this environment's catalogue to apply. Omit for full price. Needs the gateway's manage_coupons; an amount coupon must be in the price's currency.
Open a field at the gateway's page where the payer types a promotion code of their own. Mutually exclusive with coupon_id, and needs the gateway's manage_coupons.
Which gateway to charge through. Only needed when the environment has more than one connected: with one there is nothing to disambiguate, and with two picking for you would be choosing whose merchant account collects.
stripe Resposta
The subscription row and where to send the payer. expires_at is null when the gateway does not say — a made-up expiry would be a countdown to a moment nothing happens at.
What one of your customers is paying, mirrored from the gateway.
That word decides how to read every field below. The gateway is the source of truth about money; this is a local copy kept so an entitlement can be answered without a network call, joined to the rest of your data, and read while the gateway is unreachable. provider_synced_at is when the copy was last confirmed — null means never, which is what a checkout that was started and not completed looks like.
Show child attributes
Show child attributes
Show child attributes
Show child attributes