Change plan
const url = 'https://api.sloose.com/orgs/org_9f3c/billing/plan';const options = { method: 'POST', headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'}, body: '{"planKey":"example","interval":"example","previewToken":"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/plan \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data '{ "planKey": "example", "interval": "example", "previewToken": "example" }'Makes the change POST …/plan/preview describes, for an org with a Stripe subscription. A higher plan is charged now, prorated, and refused whole when the card is (402 CARD_DECLINED): it either is paid for or did not happen, and it lands on the org when Stripe’s webhook says so — usually within a minute, since a delivery made while the change holds the org is retried by Stripe. A lower plan is a Stripe subscription schedule from the period’s end, recorded at once and taken back with DELETE …/plan/pending until then. Free is a cancellation at the period’s end, taken back the same way. A change replaces whatever was waiting: an upgrade takes back a move down, a move down takes back a cancellation.
Who asked is written on the subscription, so the org’s history says it was them and not Stripe. Administrators, through their own session; never a staff member’s view.
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
The plan to move to: team, business or enterprise, or free for a cancellation at the period’s end.
month or year, for a paid plan. Defaults to month.
The token of the preview the person confirmed (#1482 review): the change is held to the terms it priced — the subscription as read, the change, and the moment its proration was priced at — and refused PREVIEW_STALE when they no longer hold. Without one, the change is priced as it is made.
Examplegenerated
{ "planKey": "example", "interval": "example", "previewToken": "example"}Responses
Section titled “Responses”What was done, and when it lands.
object
now: a higher plan (or a year in place of a month), charged now with proration. at_renewal: a lower plan (or a month in place of a year), from the period’s end, which can be taken back until then. cancel: Free, the subscription ending at the period’s end.
Example
{ "change": "now"}The plan key is not one we sell, or the interval is neither month nor year.
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"}An upgrade’s card was declined: nothing changed.
object
Example
{ "code": "CARD_DECLINED"}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 (IMPERSONATION_REFUSED): a change of plan spends the org’s money.
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"}As the preview’s 409, and four more. PREVIEW_STALE: the change was sent with a preview’s token, and the subscription, the change or the moment its proration was priced at no longer hold — or half an hour has passed; nothing was changed, so preview it again. CHANGE_IN_PROGRESS: another change to the org’s plan, or a webhook about it, is being made at this moment; nothing was asked of Stripe. CHANGE_INCOMPLETE: Stripe refused the change, and putting back what it replaced — a move waiting at the renewal, or a cancellation — failed, so it is no longer waiting; reload to see the plan as it stands. CHANGE_UNCONFIRMED: Stripe did not answer, so the change may have been made, and nothing was put back over it; the plan as it stands arrives within a minute, so do not try again yet. error says which, in words to show.
object
Example
{ "code": "NOT_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, or the plan’s price, is not configured.
object
Examplegenerated
{ "error": "example"}