Errors and retries
Status codes
| Code | Meaning | Retry? |
|---|---|---|
200 | Success. The body is the operation's reply object. | — |
400 | The request body failed validation. | No — fix the call. |
401 | Missing, unknown or mismatched credentials. | No — fix the credentials. |
429 | Over the rate limit. Limits apply per organization, not per key. | Yes, after backing off. |
501 | The operation's contract is published but its implementation has not shipped. | No — watch the phase. |
5xx | A fault on our side. | Yes, with backoff. |
Every failure names itself — report it with the transaction id
A failure body carries statusCode, timestamp, path, method, a human-readable message, and txId — the identifier for that one call.
This page is not the only place that says so. Every operation in the API reference declares each of the codes above, and every one of them points at the same ManagementApiError schema — so a client generated from our OpenAPI document gives you this body as a type, without transcribing the table above by hand.
{
"statusCode": 401,
"timestamp": "2026-09-04T14:07:22.113Z",
"path": "/management/stores/fetchStores",
"method": "POST",
"message": "Unauthorized",
"txId": "4f0a9c2e-6b31-4d77-9d0e-2a7f5c8b1e44"
}
The same value comes back on every response, failure or not, as the x-mealco-tx-id header — see Concepts → API conventions, which is also where you will find how to send your own. Log it against every call; quote it when you open a ticket with us and we can pull the complete record of that single call rather than guessing from a time of day.
One case has no id: a request whose body is not valid JSON is rejected before we have looked at it, so that 400 carries a bare message and neither the fields above nor the header.
Retry policy
A 429 may carry Retry-After, in seconds. When it does, honour it — it is a better number than any backoff you would compute, because it is the one we know.
If there is no Retry-After header, wait 60 seconds and add jitter. Some rate limits are enforced at our edge, before a request reaches the service, and an edge rejection is a fixed response that carries neither this header nor the error body described above — not even x-mealco-tx-id. So treat a 429 with no headers and no JSON envelope as a rate limit all the same. Sixty seconds is not a guess: every limit we enforce is counted over a sixty-second window, so a full window is always enough to clear it.
Retry 429 and 5xx with exponential backoff and jitter — start around one second, cap at a minute, give up after a handful of attempts and surface the failure rather than looping forever. Do not retry 400, 401 or 501: none of them becomes a different answer on a second attempt, and a tight retry loop on 401 is the fastest way to get a credential rate-limited as well.
Reads are safe to repeat
Every operation published today is a read, so a retry cannot double-apply anything. When write operations arrive they are idempotent and audit-logged with client attribution, so the same rule will continue to hold.
501 is not an error in your integration
An operation answering 501 has a real, final contract — its fields, types and enum values are committed — and no implementation behind it yet. Build against it if you like; just do not treat the 501 as a transient fault. The alternative, returning an empty result, would be a factual claim that nothing matched, and an integration is entitled to act on that.
Do not parse messages
Branch on the status code and on documented fields. Human-readable messages are for humans, and they change without notice — which is not a breaking change, because nothing promised them.