Skip to content

Error handling

{ "error": { "code": "insufficient_scope", "message": "Token lacks scope products:write", "requestId": "4b9e…" } }

Quote requestId when you contact support.

HTTP code Meaning Retry?
400 validation_failed Body/query invalid; details lists { path, message } No — fix the request
400 bad_request Semantically wrong request No
401 unauthenticated Missing, expired or revoked token Refresh / re-authorise once
401 mfa_required Dashboard sessions only —
402 payment_required A card/EFT payment was not confirmed No
402 plan_limit_reached Business plan limit (registers, staff, products…) No
403 forbidden Not allowed (role, suspended business, token on a dashboard-only route) No
403 insufficient_scope Token lacks the scope No — request the scope
404 not_found Missing or not yours (indistinguishable by design) No
409 conflict Unique clash (SKU, barcode), already done, ledger integrity rule No
409 idempotency_conflict Same Idempotency-Key, different body No
409 period_closed Posting into a closed accounting period No
422 unprocessable Valid shape, impossible request (unknown variant, totals mismatch, over-refund) No
429 rate_limited Slow down; honour retry-after Yes
5xx internal_error Our fault Yes, with backoff and the same idempotency key

OAuth endpoints use RFC 6749 errors: { "error": "invalid_grant", "error_description": "…" }.

Retrying safely

Retry only 429, 5xx and network errors, with exponential backoff (250 ms × 2ⁿ, capped) plus jitter, and the same idempotency key each time. The SDK's TechturPosError.retryable tells you which errors qualify.