> ## Documentation Index
> Fetch the complete documentation index at: https://docs.slash.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Checkout Sessions

> What a checkout session is and how its lifecycle works.

<Info>
  Slash Payment Processing is in beta and not enabled for all accounts. Contact
  [support@joinslash.com](mailto:support@joinslash.com) to get access.
</Info>

A checkout session represents one buyer's attempt to pay you through the
Slash hosted checkout. It is the buyer-facing wrapper around a
[payment intent](/docs/checkout/payment-intents): the session carries the
hosted `url`, the expiry window, and page configuration, while the payment
intent inside it tracks the money.

Create one session per buyer checkout with
[`POST /checkout-session`](/api-reference/checkout-session-post) and mount
its `url` with the [`@slashfi/checkout-js`](/docs/checkout/embedded-checkout)
SDK. Treat the `url` as single-use — mint a fresh session each time a
buyer reaches your checkout rather than reusing one across buyers.

## Statuses

| Status     | Meaning                                                                          |
| ---------- | -------------------------------------------------------------------------------- |
| `open`     | Payable. The buyer can complete the payment form.                                |
| `complete` | The payment settled. This is the terminal success state.                         |
| `expired`  | `expiresAt` passed without a settled payment; the session can no longer be paid. |

A session's status is derived from its payment intent: it is `complete`
exactly when the intent is `succeeded`. A payment that is in flight when
the expiry passes still settles — an `open` session with a `processing`
intent stays `open` until the payment resolves.

## Idempotency and expiry

* `POST /checkout-session` requires an `X-Idempotency-Key` header, unique
  per session you intend to create. Retrying with the same key returns the
  existing session; reusing a key with different parameters is rejected
  with a `400`.
* `expiresAt` defaults to 24 hours after creation and must be between 30
  minutes and 7 days out.

## Metadata

`customMetadata` is echoed back on reads and on the
`checkout_session.completed` webhook — use it to carry your own order
reference (for example `{ "orderId": "ord_123" }`) so fulfillment can
correlate the webhook to the right order without extra lookups.

## Payment methods

Card payments are always enabled. Apple Pay and Google Pay are enabled by
default and can be disabled per session from your backend with
`config.paymentMethods`, for example
`{ "paymentMethods": { "applePay": false } }` inside `config`.

## Updating a session

While a session is `open` you can change its amount, expiry, or page
configuration with
[`PATCH /checkout-session/{id}`](/api-reference/checkout-session-patch).
Send only the fields you want to change.

The session keeps its `id` and hosted `url`, so a buyer who already has
the checkout open picks up the new amount in place.

Updates only apply to `open` sessions. Once the buyer's payment is in
flight the update is rejected with `409`, and `complete` or `expired`
sessions cannot be updated at all.

## Fulfillment

Fulfill from the `checkout_session.completed` webhook, or poll
[`GET /checkout-session/{id}`](/api-reference/checkout-session-get-by-id)
and check for `status: "complete"`. The SDK's `onComplete` callback is a
browser signal for updating the UI — never grant goods or services on it
alone.
