Checkout sessions
A checkout session is the handoff between your trusted order system and the
buyer experience. Create it on your server with POST /api/checkout-sessions.
The public contract returns both checkout_url and embed_url, so one session
contract supports the hosted and embedded choices.
Request fields are strict: an unrecognized top-level property, or an
unrecognized property within an items entry, returns 422 Unprocessable Entity. Send only the documented fields and field names.
Server responsibilities
Section titled “Server responsibilities”- Read amount, currency, line items, and merchant identity from your own trusted order record.
- Authenticate with the credential alternative declared for the operation.
- Supply
Idempotency-Keywhen retrying session creation. - Store the returned checkout-session identifier with your order.
- Supply
allowed_originswhen the buyer experience will run on merchant-owned pages.
Buyer responsibilities
Section titled “Buyer responsibilities”The buyer receives a session identifier or returned checkout URL, never the merchant secret. The public session read is buyer-safe and returns no secrets. Do not allow the browser to become the authority for price, currency, line items, or merchant ownership.
Choose Hosted Checkout or Embedded Checkout after session creation. The same session contract can be mounted with the published maxanapay.js when its current rail and capability limits fit the checkout.
How long a session lasts
Section titled “How long a session lasts”A session expires, and its clock starts when you create it, not when the buyer
arrives. expires_in_minutes sets the lifetime: omit it and the session lasts
30 minutes, or send any whole number from
5 to 1440 — five minutes to a full
day. Anything outside that range is refused with 422 naming the field.
Choose it against the page the buyer will be looking at rather than against the call you are making. A session created while a checkout page loads spends its life while the buyer reads and fills the page in; one created when the buyer presses Pay starts whole. The default suits the second and can be short for the first.
An expired session cannot start a new payment, and the buyer’s page is where
that surfaces: the API answers 400 with checkout_session_id has expired and
the SDK reports it as session_expired, which is not retryable. See the SDK
error vocabulary. A session is
immutable, so there is nothing to extend — create another one and mount that.
Expiry does not strand a payment the buyer already approved. The session clock
gates the buyer’s page and the anonymous capture it makes, not an authenticated
one: if the buyer approved and only the capture never followed, the merchant —
or a channel naming the merchant with X-Merchant-Id — can still complete it
with POST /api/payments/orders/{order_id}/capture,
whose authenticated path is governed by the order’s state, not the session’s
clock. An approved order does not have to be abandoned when its session expires.
Platform-supplied shipping
Section titled “Platform-supplied shipping”When your checkout has already calculated shipping, send
shipping_amount_cents with shipping_address; the item total plus shipping
must equal amount. The authenticated merchant-facing creation response
returns both stored values. The buyer-facing public session response returns
shipping_amount_cents but does not return shipping_address.
Current limits
Section titled “Current limits”A checkout session is immutable buyer state, not a cart-update API. The buyer cannot change its merchant, amount, currency, or line items, and a browser callback is not proof of capture. Create a replacement session when trusted order facts change.