API reference
Errors
Errors use conventional HTTP status codes and always return the same JSON shape, so you can handle them in one place.
HTTP/1.1 400 Bad Request
{
"error": {
"type": "invalid_request_error",
"code": "parameter_invalid",
"message": "line_items must add up to amount.",
"param": "line_items"
}
}The error object
typestring- The category: decides how your code should react.
codestring- A stable, machine-readable code. Branch on this.
messagestring- A human-readable explanation. It may change; don't parse it.
paramstring, optional- The parameter at fault, for
parameter_invalid. Nested fields look likeline_items[0].unit_amount.
Error types
| type | Retry? | Meaning |
|---|---|---|
invalid_request_error | No — fix the request | Bad input, or not allowed in the session's state. |
authentication_error | No — fix the key | The key is missing, invalid or for the other environment. |
permission_error | No | The account can't use the API right now. |
not_found_error | No | The object doesn't exist for this business. |
rate_limit_error | Yes, with backoff | Too many requests. |
api_error | Yes, with backoff | A problem on SaphraONE's side. |
Error codes
| HTTP | type | code | Meaning |
|---|---|---|---|
| 400 | invalid_request_error | parameter_invalid | A parameter is missing or invalid. param names it. |
| 400 | invalid_request_error | body_invalid | The body isn't a JSON object. |
| 401 | authentication_error | api_key_missing | No secret key was sent. |
| 401 | authentication_error | api_key_invalid | The key is unknown or revoked. |
| 401 | authentication_error | api_key_wrong_mode | The key belongs to the other environment. |
| 403 | permission_error | account_not_business | The account isn't a Business account. |
| 403 | permission_error | business_not_verified | Live payments need a verified business. |
| 404 | not_found_error | resource_missing | No such session (or it belongs to another business). |
| 409 | invalid_request_error | session_state_invalid | The session can't do that in its current state. |
| 429 | rate_limit_error | rate_limited | Too many requests. Back off and retry. |
| 500 | api_error | internal_error | Something failed on our side. Retry with the same Idempotency-Key. |
Amount limits from the payment engine (for example below 0.50) come back as parameter_invalid with param: "amount".
Handling errors
async function withRetry(call, attempts = 4) {
for (let attempt = 0; ; attempt += 1) {
try {
return await call();
} catch (error) {
const retryable = error.status === 429 || error.status >= 500 || error.status === undefined;
if (!retryable || attempt + 1 >= attempts) throw error;
const delay = 2 ** attempt * 1000 + Math.random() * 250;
await new Promise((resolve) => setTimeout(resolve, delay));
}
}
}
// Safe: the Idempotency-Key makes the retried create return the same session.
const session = await withRetry(() =>
saphra("/checkout/sessions", { method: "POST", headers: { "Idempotency-Key": "order-1042" }, body }),
);