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 like line_items[0].unit_amount.

Error types

typeRetry?Meaning
invalid_request_errorNo — fix the requestBad input, or not allowed in the session's state.
authentication_errorNo — fix the keyThe key is missing, invalid or for the other environment.
permission_errorNoThe account can't use the API right now.
not_found_errorNoThe object doesn't exist for this business.
rate_limit_errorYes, with backoffToo many requests.
api_errorYes, with backoffA problem on SaphraONE's side.

Error codes

HTTPtypecodeMeaning
400invalid_request_errorparameter_invalidA parameter is missing or invalid. param names it.
400invalid_request_errorbody_invalidThe body isn't a JSON object.
401authentication_errorapi_key_missingNo secret key was sent.
401authentication_errorapi_key_invalidThe key is unknown or revoked.
401authentication_errorapi_key_wrong_modeThe key belongs to the other environment.
403permission_erroraccount_not_businessThe account isn't a Business account.
403permission_errorbusiness_not_verifiedLive payments need a verified business.
404not_found_errorresource_missingNo such session (or it belongs to another business).
409invalid_request_errorsession_state_invalidThe session can't do that in its current state.
429rate_limit_errorrate_limitedToo many requests. Back off and retry.
500api_errorinternal_errorSomething 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 }),
);