# Buy a refill of this week's allowance (25% of the plan price)

`POST /v1/console/subscription/reset-checkout` (operation id `createResetCheckout`)

Creates a one-off Stripe Checkout Session for the plan's reset price (25% of the monthly price, excluding
VAT). When Stripe reports the payment, the current week's allowance is refilled to the full amount at once:
the used counter goes back to zero, nothing stacks or carries over, and the week keeps its reset time. It can
be bought any number of times. Without an active subscription: 409 `no_subscription`.

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

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `x-dex-csrf` | header | string | no | The `csrf_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) |
| `idempotency-key` | header | string | no | Makes retries safe. Within 24 hours, a repeat with the same key and the same body is never charged again. It answers with `idempotent-replayed: true` and the original response: the same `id`, `created`, `model`, answers and `usage`, including the original charge fields. The same key with a different body answers 409.  (1 to 255 characters; pattern ^[\x21-\x7E]+$) |

## Request body

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `return_path` | string | no | Console path to return to after checkout. (pattern ^/[A-Za-z0-9/_-]{0,200}$) |

## Responses

### 201

Checkout session created; send the browser to `url`.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `id` | string | yes |  |
| `object` | string | yes | (always "checkout_session") |
| `kind` | string | yes | A prepaid top-up (payment mode), a plan subscription (subscription mode) or a weekly allowance reset (payment mode). (one of "top_up", "subscription", "reset") |
| `plan` | string \| null | yes | The plan a subscription or reset session is for; null for a top-up. (one of "base", "hot", "fierce", null) |
| `url` | string | yes | (format uri) |
| `amount_cents` | integer | yes | The EUR value excluding VAT: a top-up's credit, a subscription's monthly price or a reset's price in euro cents. What the buyer pays is the regional price (`Plan.prices`, `PlanList.top_up_packs`) in the currency Stripe presents; the balance and the plan are the same in every currency.  |
| `currency` | string | yes | The currency of `amount_cents` (always EUR); see `charge_currency` for the payment. (always "EUR") |
| `charge_currency` | string \| null | yes | The currency Stripe will charge when it is fixed in advance: the account's `billing_currency`, or EUR for a top-up of a free amount. null when Stripe picks it from the buyer's location at checkout. New currencies may appear within v1.  (one of "EUR", "USD", "GBP", "INR", null) |
| `expires_at` | string | yes | (format date-time) |

### 400

The 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).


### 401

Missing, unknown, revoked or expired credentials.

### 403

The credentials are valid but not allowed to do this (missing scope, suspended account or failed CSRF check).

### 409

The 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).


### 422

The 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`.


### 429

A rate limit or quota is exhausted. Retry after the given number of seconds. For `test_daily_quota` that is
the time until 00:00 UTC; clients should not retry it automatically.


### 500

An unexpected error. Any charge was refunded. Retry with the same idempotency key.

### 503

`maintenance`: 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.


## Examples

Illustrative values. Examples show the shape of requests and responses; the numbers in them are not measured results.

Request: reset

```json
{
  "return_path": "/console/billing"
}
```

Response: session

```json
{
  "id": "cs_live_c3D4e5F6g7H8i9J0",
  "object": "checkout_session",
  "kind": "reset",
  "plan": "base",
  "url": "https://checkout.stripe.com/c/pay/cs_live_c3D4e5F6g7H8i9J0",
  "amount_cents": 250,
  "currency": "EUR",
  "charge_currency": "EUR",
  "expires_at": "2026-10-20T12:30:00Z"
}
```
