POST
/
api
/
v1
/
payment-sessions
/
{sessionId}
/
submit
Submit a payment (widget)
curl --request POST \
  --url https://api.switchflows.net/api/v1/payment-sessions/{sessionId}/submit \
  --header 'Content-Type: application/json' \
  --data '
{
  "clientSecret": "<string>",
  "vaultToken": "<string>"
}
'
The checkout widget calls this endpoint for you. It is documented so you can reason about the full flow (and build a custom client if you must), but a standard integration never calls it directly.
Executes the payment for a session: the routing engine loads your active rule set, attempts capture on the priority-1 gateway, and fails over per your rules — all within one request. The request authenticates with the session’s clientSecret in the body (no Authorization header); the card is referenced only by an opaque vault token.

Request

{
  "clientSecret": "ps_1a2b3c4d_secret_e5f6g7h8",
  "vaultToken": "vault_tok_9f8a7b6c"
}
clientSecret
string
required
The session’s client secret.
vaultToken
string
required
The opaque token the vault returned when the widget tokenized the card (vault_tok_…, or a pm_… payment-method id in SaaS vault mode).

Responses

The call resolves to exactly one of four shapes:
// Captured (possibly after failover)
{ "status": "SUCCEEDED", "capturedVia": "ADYEN", "failoverUsed": true }
// Terminal decline
{ "status": "DECLINED", "declineCode": "do_not_honor" }
// All gateways down — widget shows the alternative payment method
{ "action": "RETRY_ALTERNATIVE_METHOD" }
// Integration-level problem (e.g. expired token — widget re-collects the card)
{ "error": { "code": "token_expired", "message": "…" } }
The routing engine’s total budget is bounded: ≤ 2,500 ms at p95 for a two-attempt checkout, with an absolute 4,500 ms ceiling before it returns the degradation response. See Failover behavior.