Skip to content
Get API key

Concepts

Errors

Errors come back as JSON with a stable code. Build your handling on error.code; the message is for people and may change.

Error shape

Error response
{
  "error": {
    "code": "insufficient_scope",
    "message": "Key is missing required scope: transactions.read",
    "request_id": "…"
  }
}
  • error.code: the contract. Branch on it.
  • error.message: a sentence for logs and people. Don't parse it.
  • error.request_id: the same value as the x-request-id header. Quote it when you ask for help.
  • error.details: on a 422, what failed. For an order, one entry per failing item with its item_index and a code such as item_unavailable, invalid_variant, invalid_modifiers or quantity_invalid.

Error bodies never contain database text. If something breaks on our side you get internal_error and a request_id; the detail stays in our logs.

Error codes

CodeHTTPWhenDo
invalid_key401The key is missing, malformed or revoked.Fix the request
payment_required402The business is not on Sansflow Premium. The key itself is fine; the owner upgrades the plan.Tell the person
insufficient_scope403The key lacks the scope this endpoint needs, or it is pinned to another outlet. The message says which.Fix the request
validation_failed400A query parameter did not parse (the message names it), or from/to span more than 400 days.Fix the request
validation_failed422On a POST: the body failed validation. error.details lists what failed.Fix the request
invalid_request400The id in the path is not a UUID, or a required query parameter is missing.Fix the request
invalid_json400The POST body is not valid JSON.Fix the request
idempotency_key_required400A POST without an Idempotency-Key header (1 to 255 characters).Fix the request
not_found404Unknown path under an endpoint.Fix the request
transaction_not_found404No such transaction for this key (another business, deleted, or across the test/live split).Fix the request
customer_not_found404No such customer for this business.Fix the request
order_not_found404The order was not created through the API, belongs elsewhere, or is across the test/live split.Fix the request
booking_not_found404No such booking request for this business, or it is at an outlet the key is not pinned to.Fix the request
table_not_found404table_id is not an active table at the booking's outlet.Fix the request
location_not_found404location_id is unknown or inactive for this business.Fix the request
method_not_allowed405Read endpoints accept GET only; write endpoints POST only.Fix the request
idempotency_key_conflict409The Idempotency-Key was already used with a different request. Use a new key.Fix the request
capacity_full409The slot has no free capacity. The booking stays pending; retry later or ask the venue.Retry later
table_taken409The named table already has an overlapping reservation.Retry later
proof_required409The booking has a pre-order and no transfer proof yet. Confirm again once the guest uploads it.Retry later
booking_not_confirmable409The booking is rejected or expired and cannot be confirmed.Tell the person
booking_not_rejectable409The booking is already confirmed or expired and cannot be rejected.Tell the person
rate_limited429Too many requests this minute. Wait the seconds in Retry-After.Retry later
internal_error500Something failed on our side. Retry with backoff and quote the request_id if it persists.Retry with backoff

Retrying

  • 4xx (except 429 and the slot-related 409s): the same request will fail the same way. Fix it first.
  • 429: wait the number of seconds in the Retry-After header, then retry. See Rate limits.
  • 5xx and timeouts: retry with exponential backoff. For a POST, reuse the same Idempotency-Key so a request that did succeed is replayed, not repeated. See Idempotency.

Stuck? Quote the request_id from the response and write toSansflow support.Checked against API v1 on .