{"templateId":"markdown","sharedDataIds":{"sidebar":"sidebar-api-docs/sidebars.yaml"},"props":{"metadata":{"markdoc":{"tagList":[]},"type":"markdown"},"seo":{"title":"Errors and status codes"},"dynamicMarkdocComponents":[],"compilationErrors":[],"ast":{"$$mdtype":"Tag","name":"article","attributes":{},"children":[{"$$mdtype":"Tag","name":"Heading","attributes":{"level":1,"id":"errors-and-status-codes","__idx":0},"children":["Errors and status codes"]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"404-means-not-found-or-not-yours","__idx":1},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["404"]}," means \"not found, or not yours\""]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["When a caller is not allowed to see a resource, the API returns ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["404 Not Found"]}," ","— not ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["403 Forbidden"]},". The response is deliberately identical to the one you get"," ","for an ID that was never issued, so that the API never confirms whether a"," ","resource exists to someone who is not entitled to read it."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["A ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["404"]}," is not proof that a resource was deleted."]}," It means one of:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["the ID does not exist, or never did"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["the resource exists but belongs to another account"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["the resource exists in your account but your token may not read it"]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["your token is missing, expired, or invalid"]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Do not build reconciliation, sync or clean-up logic that treats a ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["404"]}," as a"," ","deletion signal — you will delete records on your side that are alive and well"," ","on ours, merely because a permission changed. If you need to know that something"," ","was deleted, use webhooks."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["These ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["404"]}," responses have an ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["empty body"]},". There is no ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["message"]}," to parse and"," ","no code to branch on, so do not expect the error envelope described below."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"the-error-envelope","__idx":2},"children":["The error envelope"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Every other error returns JSON with a human-readable ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["message"]},":"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"json","header":{"controls":{"copy":{}}},"source":"{\n  \"message\": \"Sorry, we found issues with some of the submitted data - please review and try again.\"\n}\n","lang":"json"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Two responses add a field to it:"]},{"$$mdtype":"Tag","name":"div","attributes":{"className":"md-table-wrapper"},"children":[{"$$mdtype":"Tag","name":"table","attributes":{"className":"md"},"children":[{"$$mdtype":"Tag","name":"thead","attributes":{},"children":[{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"Field"},"children":["Field"]},{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"Appears on"},"children":["Appears on"]},{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"Meaning"},"children":["Meaning"]}]}]},{"$$mdtype":"Tag","name":"tbody","attributes":{},"children":[{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["errors"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["422"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Per-field validation failures"]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["code"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Unexpected server errors"]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["A reference to quote to support"]}]}]}]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["message"]}," is translated, so its wording follows the request's locale and is not"," ","stable enough to branch on. Branch on the status code and, for ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["422"]},", on the"," ","keys inside ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["errors"]},"."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"common-status-codes","__idx":3},"children":["Common status codes"]},{"$$mdtype":"Tag","name":"div","attributes":{"className":"md-table-wrapper"},"children":[{"$$mdtype":"Tag","name":"table","attributes":{"className":"md"},"children":[{"$$mdtype":"Tag","name":"thead","attributes":{},"children":[{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"Status"},"children":["Status"]},{"$$mdtype":"Tag","name":"th","attributes":{"data-label":"When"},"children":["When"]}]}]},{"$$mdtype":"Tag","name":"tbody","attributes":{},"children":[{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["200 OK"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["A successful read, update, or a write that returns the resource"]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["201 Created"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["A successful create, returning the new resource"]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["204 No Content"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["A successful delete, with an empty body"]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["401 Unauthorized"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Bad credentials ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["at the token endpoint only"]}," — see below"]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["403 Forbidden"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["A business rule refused the action — see below"]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["404 Not Found"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["Not found, or not yours — see above"]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["422 Unprocessable Entity"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["The request was understood but the data failed validation"]}]},{"$$mdtype":"Tag","name":"tr","attributes":{},"children":[{"$$mdtype":"Tag","name":"td","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["429 Too Many Requests"]}]},{"$$mdtype":"Tag","name":"td","attributes":{},"children":["A rate limit window was exceeded — see ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Rate limits"]}]}]}]}]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"on-401","__idx":4},"children":["On ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["401"]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["401"]}," is narrower than it looks. It comes from the token endpoint, when the"," ","credentials you exchanged for a token were rejected."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["It is ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["not"]}," what you get for a missing or expired token on a normal API"," ","endpoint. That returns the same bare ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["404"]}," as everything else in the section"," ","above. So if a previously working integration starts returning ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["404"]}," across"," ","every endpoint at once, suspect the token before you suspect the data."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"on-403","__idx":5},"children":["On ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["403"]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Because authorisation failures collapse into ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["404"]},", a ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["403"]}," never means \"you may"," ","not see this\". It means the opposite: the resource is yours and we know who you"," ","are, but a rule specific to that operation refused it — a quota exhausted, a"," ","duplicate that is not permitted, a state that forbids the change."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["A ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["403"]}," is therefore always endpoint-specific, and is documented on the endpoint"," ","that can return it, together with the message it sends."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"validation-errors","__idx":6},"children":["Validation errors"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["A ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["422"]}," names every field at fault. ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["errors"]}," is keyed by field name, and each"," ","value is the list of problems with that field. Nested fields are dotted."]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"json","header":{"controls":{"copy":{}}},"source":"{\n  \"message\": \"Sorry, we found issues with some of the submitted data - please review and try again.\",\n  \"errors\": {\n    \"status\": [\"The selected status is invalid.\"],\n    \"user_id\": [\"The user id field is required.\"]\n  }\n}\n","lang":"json"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Read ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["errors"]}," rather than the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["message"]}," — the message is the same generic"," ","sentence on every validation failure."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"unexpected-errors","__idx":7},"children":["Unexpected errors"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["If something fails on our side, the response carries a reference instead of the"," ","underlying detail:"]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"json","header":{"controls":{"copy":{}}},"source":"{\n  \"message\": \"Unexpected Error on Rosterfy\",\n  \"code\": \"ACEH292\"\n}\n","lang":"json"},"children":[]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Log ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["code"]}," and quote it to support; it identifies the specific failure. Treat"," ","these as retryable only if the operation is safe to repeat."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"endpoint-specific-statuses","__idx":8},"children":["Endpoint-specific statuses"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Some endpoints return a status that does not follow from any of the above — a"," ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["402"]}," where a payment is outstanding, a ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["410"]}," where a form has closed, a ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["403"]}," ","for a rule unique to that operation. Those are documented on the endpoint"," ","itself, so check its reference page as well as this one."]}]},"headings":[{"value":"Errors and status codes","id":"errors-and-status-codes","depth":1},{"value":"404 means \"not found, or not yours\"","id":"404-means-not-found-or-not-yours","depth":2},{"value":"The error envelope","id":"the-error-envelope","depth":2},{"value":"Common status codes","id":"common-status-codes","depth":2},{"value":"On 401","id":"on-401","depth":3},{"value":"On 403","id":"on-403","depth":3},{"value":"Validation errors","id":"validation-errors","depth":2},{"value":"Unexpected errors","id":"unexpected-errors","depth":2},{"value":"Endpoint-specific statuses","id":"endpoint-specific-statuses","depth":2}],"frontmatter":{"seo":{"title":"Errors and status codes"}},"lastModified":"2026-08-18T06:10:52.000Z","pagePropGetterError":{"message":"","name":""}},"slug":"/api-docs/guides/errors","userData":{"isAuthenticated":false,"teams":["anonymous"]},"isPublic":true}