Download OpenAPI specification:
Payer-browser payment surface, scoped to a single checkout session.
The surface a payer's browser talks to, through our SDK or a hosted checkout page. It operates on one checkout session, created server-side by the merchant, and it never sees a secret key or another tenant.
Version 0.1.0 is a draft written spec-first before any controller exists, like the merchant API it accompanies.
What the SDK renders from: the amount, the currency, the methods that can actually succeed for this session, the branding template, the locale, and the current status. The session token in the request decides which session; there is no ID in the path, because a payer surface must not be able to name another session.
{- "object": "checkout_session",
- "mode": "payment",
- "status": "created",
- "amount": "1250",
- "currency": "USD",
- "merchant": "string",
- "merchant_logo": {
- "light": "string",
- "dark": "string"
}, - "merchant_palette": {
- "Primary": "string",
- "Accent": "string",
- "Surface": "string"
}, - "merchant_css": "string",
- "method_marks": { },
- "interval": {
- "unit": "day",
- "count": 1
}, - "available_methods": [
- "string"
], - "template_config": {
- "theme_mode": "light",
- "methods": {
- "order": [
- "string"
], - "hidden": [
- "string"
]
}, - "attribution": "shown",
- "labels": { },
- "layout": {
- "blocks": [ ],
- "hidden": [ ],
- "gap": 1,
- "measure": 390,
- "boxes": { },
- "summary": "trailing"
}
}, - "locale": "string",
- "expires_at": "2026-09-26T12:00:00Z",
- "template": null
}The payer has chosen a method and entered their details; this submits them. Card details arrive as Evervault CIPHERTEXT, never as a raw PAN, so no card data ever touches a merchant server, which preserves SAQ A.
A decline is NOT an error here either. If the card is refused, this returns 200 with a result whose status is declined and a decline block, the same block the merchant API returns. Only a malformed submission is an HTTP error.
A session succeeds at most once. Confirming a session that already succeeded is rejected and points at the result, which is also the two-tabs guard.
3DS: if the issuer requires authentication, the result status is requires_action
with a three_ds action for the SDK to render. The SDK completes it and
polls GET /session/status.
Submits the payer's payment for this checkout session; it is called from the payer's browser without an Idempotency-Key, a session that has already been paid refuses a second submission, and a payer whose browser lost the answer should read the session status rather than submit again.
| method required | string Enum: "card" "wallet" "apm" Which method the payer chose. The detail object below must match it. |
object (CardCiphertext) Card fields as Evervault CIPHERTEXT strings, not plaintext. Each value is opaque to this API; it is produced by the Evervault iframe in the browser and passed to the gateway through Relay. The normalised request vocabulary that receives it is the "ciphertext card ref". These are ciphertext, so no PAN pattern is asserted on them and none should be: a value here that looks like a bare PAN is itself an integration error. | |
object (WalletPayload) A wallet payment, as the "wallet payload". Whether the gateway or we decrypt it is gateway-specific and settled elsewhere (both testable gateways decrypt it themselves; surface map). This surface carries the payload through; it does not decrypt it. | |
object (ApmSelection) An alternative payment method. Most APMs are a redirect or an instruction flow, so the confirm result will carry a | |
| three_ds_session_id | string non-empty The 3DS session the payer's browser has just completed, on the SECOND confirm of a card payment. Absent on the first, which is what creates the session and answers |
{- "method": "card"
}{- "object": "checkout_result",
- "status": "processing",
- "payment": "payment_01J8XQK3M4N5P6Q7R8S9T0V1W2",
- "action": {
- "type": "three_ds_challenge",
- "mode": "embedded",
- "session": "string"
}, - "decline": null
}The status stream as a poll. After confirm returns processing or the payer completes a 3DS challenge, this is how the SDK learns the result. It carries the same decline block on a decline.
{- "object": "checkout_result",
- "status": "processing",
- "payment": "payment_01J8XQK3M4N5P6Q7R8S9T0V1W2",
- "action": {
- "type": "three_ds_challenge",
- "mode": "embedded",
- "session": "string"
}, - "decline": null
}