Start a Stripe Checkout session
const url = 'https://api.sloose.com/orgs/org_9f3c/billing/checkout';const options = { method: 'POST', headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'}, body: '{"kind":"plan","planKey":"free","interval":"month","afterTrial":true,"packKey":"example","quantity":1,"successUrl":"example","cancelUrl":"example"}'};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request POST \ --url https://api.sloose.com/orgs/org_9f3c/billing/checkout \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data '{ "kind": "plan", "planKey": "free", "interval": "month", "afterTrial": true, "packKey": "example", "quantity": 1, "successUrl": "example", "cancelUrl": "example" }'For a plan subscription or a one-off credit pack: every plan through Checkout, by card, Enterprise included (#1337). Paying by invoice is on request, through support.
Session only: billing is a person’s to manage, never an org’s API token’s (D5).
Authorizations
Section titled “Authorizations”Parameters
Section titled “Parameters”Path Parameters
Section titled “Path Parameters”The org id the session was issued for. A token for one org can never read another.
Example
org_9f3cThe org id the session was issued for. A token for one org can never read another.
Request Body
Section titled “Request Body”object
With kind: plan. One of team, business or enterprise.
With kind: plan. Defaults to month.
With kind: plan: what the page promised, that the plan starts when the org’s own trial ends. Refused TRIAL_ENDING once the trial is too close to its end to wait for (49 hours), so the page reads again rather than a Checkout charging at once.
With kind: credit_pack.
With kind: credit_pack. Defaults to 1.
Responses
Section titled “Responses”A Checkout URL.
object
Send the browser here.
Example
{ "kind": "checkout"}kind is missing, or the plan or pack key is not one we sell.
object
Examplegenerated
{ "error": "example"}No bearer, or one that is expired, revoked or no longer resolves to a member.
The error envelope every non-2xx answer uses.
object
Human-readable explanation.
Machine-readable reason. Absent on a few legacy 400s.
Examplegenerated
{ "error": "example", "code": "example"}The bearer’s role is too low, it was issued for a different org, it is an API token (SESSION_REQUIRED), or it is a staff member’s view of the org (IMPERSONATION_REFUSED; a read-only view is refused before this, IMPERSONATION_READ_ONLY): billing spends and changes the org’s money, and a view would do it in the member’s name.
The error envelope every non-2xx answer uses.
object
Human-readable explanation.
Machine-readable reason. Absent on a few legacy 400s.
Examplegenerated
{ "error": "example", "code": "example"}ALREADY_SUBSCRIBED: this org already has a Stripe subscription — named by the org, or live at Stripe before its webhook has named it here (a Checkout just completed) — and Checkout creates one rather than replacing it, so changing between paid plans is POST /orgs/{org}/billing/plan’s. CHECKOUT_SUPERSEDED: another plan Checkout of the org was opened at the same moment and outranks this one, which is taken back. Only one plan Checkout of an org is open at a time — the one made last — and making it expires the rest. TRIAL_ENDING: the page promised the plan would start when the org’s trial ends (afterTrial), and the trial is now too close to its end for that; nothing was made. error says which, in words to show.
object
Example
{ "code": "ALREADY_SUBSCRIBED"}Stripe refused the request (PAYMENT_PROVIDER_REFUSED) — nothing was charged, though a step taken before the refusal stands: the org’s first Stripe customer, or an existing customer’s billing email brought up to date — or was unavailable (PAYMENT_PROVIDER_UNAVAILABLE: unreachable, failing or rate-limiting), which may or may not have gone through — check before retrying. Stripe’s own words are logged, not returned.
object
Example
{ "code": "PAYMENT_PROVIDER_REFUSED"}Stripe is not configured on this deployment.
object
Examplegenerated
{ "error": "example"}