API reference, Console billing
Change the plan, or undo a cancellation
PATCH/v1/console/subscriptionoperation id updateSubscription
plan to a dearer plan applies at once: Stripe prorates the price difference on the next invoice and the
weekly allowance switches to the new plan immediately (the current week's used amount is carried over).
plan to a cheaper plan is scheduled for the end of the paid month (scheduled_plan); until then the current
plan stays. cancel_at_period_end: false undoes a cancellation that has not taken effect yet. Without an
active subscription: 409 no_subscription. A plan with no founding-round seat left: 409 plan_sold_out (a
downgrade too, since it takes a seat on the cheaper plan). When Stripe refuses the change (the restricted API
key lacks the permission, see the billing runbook): 503 maintenance; use the Customer Portal instead.
Authentication. Console session cookie (__Host-dex_session), or an app session token (Authorization: Bearer dex_ses_...). With the cookie, state-changing routes also need the x-dex-csrf header.
Parameters
x-dex-csrfheader ยท stringcsrf_token returned by createSession (or handed over in the completeGoogleSignIn redirect). Required
with the session cookie on every state-changing console route; not used with a bearer app session.32 to 64 characters
Request body
application/json, schema UpdateSubscriptionRequest
planPlanIdone of "base", "hot", "fierce"
cancel_at_period_endbooleanfalse is accepted here, to undo a cancellation; cancel with cancelSubscription.Responses
200The subscription after the change.
Headers: x-request-id
objectstringrequiredalways "subscription"
planstring | nullrequiredone of "base", "hot", "fierce", null
statusstringrequirednone: never subscribed, or the last subscription ended and the account is back on pay as you go.
incomplete: Checkout started, the first payment is not settled yet (delayed payment methods).
active: paid up; the weekly allowance is available. past_due: a renewal payment failed, the
allowance stays available during the grace period. frozen: the grace period passed, requests are paid
from the balance until the subscription is paid or ends. canceled: ended; plan is null.one of "none", "incomplete", "active", "past_due", "frozen", "canceled"
cancel_at_period_endbooleanrequiredcurrent_period_end (cancelSubscription).scheduled_planstring | nullrequiredcurrent_period_end (updateSubscription to a cheaper plan); null otherwise.one of "base", "hot", "fierce", null
current_period_startstring | nullrequiredformat date-time
current_period_endstring | nullrequiredformat date-time
week_started_atstring | nullrequiredformat date-time
week_resets_atstring | nullrequiredformat date-time
week_allowance_tokensintegerrequiredformat int64at least 0
week_used_tokensintegerrequiredformat int64at least 0
reset_price_centsinteger | nullrequiredresets_bought_this_weekintegerrequiredat least 0
billing_portalbooleanrequiredcreateBillingPortalSession works (the Stripe Customer Portal is configured for Dex and the account has a Stripe customer).currencystring | nullrequiredbilling_currency); null without a plan or before it is known. reset_price_cents stays in euro cents:
the reset in this currency is Plan.prices[currency].reset_price_cents. New currencies may appear within v1.one of "EUR", "USD", "GBP", "INR", null
400The request could not be read. Codes: invalid_json (not JSON, not UTF-8, or a \u escape that is half of a
surrogate pair, such as "\ud800" without its low half), duplicate_key (a JSON object
repeats a key; param is the JSON pointer of the repeated member, such as /questions/q1/options/a),
unsupported_media_type (not application/json) and invalid_header (a malformed idempotency-key or
x-client-request-id; param names the header).
Headers: x-request-id, x-client-request-id
Error envelope. See Errors for every type and code.
401Missing, unknown, revoked or expired credentials.
Headers: x-request-id, x-client-request-id
Error envelope. See Errors for every type and code.
403The credentials are valid but not allowed to do this (missing scope, suspended account or failed CSRF check).
Headers: x-request-id, x-client-request-id
Error envelope. See Errors for every type and code.
409The idempotency key was used with a different body, or the first request with this key is still running.
Console billing routes also answer 409 for a state conflict: subscription_exists (createSubscriptionCheckout
while a subscription is live, joinWaitingList for a plan the account holds), no_subscription
(updateSubscription, cancelSubscription, createResetCheckout or createBillingPortalSession without one),
plan_sold_out (createSubscriptionCheckout or updateSubscription to a plan with no founding-round seat left;
with hints), key_revoked (updateKey on a revoked key).
Headers: x-request-id, x-client-request-id, retry-after
Error envelope. See Errors for every type and code.
422The request is well-formed JSON but breaks a validation rule. param names the field as a dotted path.
Codes: unknown_field, missing_field, invalid_type (wrong JSON type), invalid_value (right type, value
out of range: an empty or over-long string, a state, instructions, criteria string or option description
of only whitespace, an empty questions or options object, an empty state object or array, a pattern or
allowed-value mismatch such as a label or level with outer whitespace, a state nested deeper than 32 levels, a
bad date or date range), field_not_allowed (options or levels on the wrong question type),
invalid_question_id, too_many_questions, too_many_options, invalid_levels (including two levels equal
after Unicode NFC normalisation and lower-casing), invalid_min_confidence, duplicate_label (two option
labels equal after Unicode NFC normalisation and lower-casing, such as Billing and billing),
state_path_not_found, state_not_json and, on the console, top_up_limit_exceeded.
Headers: x-request-id, x-client-request-id
Error envelope. See Errors for every type and code.
500An unexpected error. Any charge was refunded. Retry with the same idempotency key.
Headers: x-request-id, x-client-request-id
Error envelope. See Errors for every type and code.
503maintenance: the console's database, sign-in or payments are unavailable for a moment (for
createGoogleSession also: Google sign-in is not configured, or Google's signing keys cannot be fetched).
Retry after retry-after. Nothing was changed.
Headers: x-request-id, retry-after
Error envelope. See Errors for every type and code.
Examples
Illustrative values. Examples show the shape of requests and responses; the numbers in them are not measured results.
Request: upgrade
{
"plan": "hot"
}Request: keep
{
"cancel_at_period_end": false
}