# Errors One error shape: a message, a code, the request id and a link here. The keyless tier still answers only 404 and 503. ## The shape An error answer is a JSON object: `error` is a short reason in words (the two the keyless tier has always answered, `not found` and `unavailable`, keep their exact text), `code` is the machine value to match on, `requestId` is what to quote when you write to us, `param` names the offending field when there is one, and `docUrl` points at the code's row below. A 429 also carries `Retry-After`; a used-up quota carries `resetsAt`. 404 Not Found: ```json { "error": "not found", "code": "not_found", "requestId": "req_01J9X4Q2M7V8K3B5N6P7R8S9T0", "docUrl": "https://api.dietbloxycola.com/docs/errors#not_found" } ``` 400 Bad Request: ```json { "error": "universeId: expected a positive integer", "code": "invalid_request", "requestId": "req_01J9X4Q2M7V8K3B5N6P7R8S9T1", "param": "universeId", "docUrl": "https://api.dietbloxycola.com/docs/errors#invalid_request" } ``` ## Every code | Status | Code | When | What to do | | --- | --- | --- | --- | | 400 | `invalid_request` | The body or the query fails its schema; `param` names the field. | Fix the field and send again. | | 401 | `unauthorized` | No key, a key nobody issued, or one that was revoked or has expired. | Send `Authorization: Bearer ` with a live key from your account. | | 403 | `insufficient_scope` | The key is real and was issued without this product's scope. | Issue a key with the scope the page names, or add it to this one. | | 403 | `tenant_pending` | The account exists and has not been approved yet. | Wait for the approval mail; nothing to change on your side. | | 403 | `tenant_suspended` | The account was suspended, or asked for its own deletion. | Write to us if you did not expect it. | | 403 | `product_disabled` | This product is off for your account, or off for everyone during an incident. | Read the status page; write to us if it is only you. | | 404 | `not_found` | The path, or the thing the id names, does not exist. | Check the id against the list endpoint. | | 409 | `idempotency_conflict` | The same `Idempotency-Key` arrived with a different body or path within a day. | Use a fresh key for a different request. | | 409 | `idempotency_in_progress` | A repeat arrived while the first request with the key was still running. | Wait a moment and repeat; the first answer will replay. | | 409 | `lease_expired` | A report arrived for a request this caller no longer holds. | Fetch the pending list again. | | 413 | `payload_too_large` | The body is over the cap the page states. | Send less. | | 429 | `rate_limited` | The token bucket is empty; `Retry-After` says how long, and the `RateLimit-*` headers say how much. | Wait it out; poll no faster than the window. | | 429 | `quota_exceeded` | This month's quota for the product is spent; `resetsAt` is the first of next month, UTC. | Wait for the reset, or ask about a bigger plan. | | 502 | `upstream_error` | Roblox or Discord answered with something the API could not use. | Try again in a minute. | | 503 | `unavailable` | The API could not do this now: Roblox could not be read, or a store is not configured. | Try again in a minute; the CDN keeps serving the last good keyless answer for a while. | | 503 | `upstream_unavailable` | Roblox or Discord did not answer in time. | Try again in a minute; a `Retry-After` may say when. | | 500 | `internal` | Something on our side broke. | Send us the `requestId`. | On the keyless tier only `not_found` and `unavailable` can happen. A cached keyless answer replays the request id of the read that produced it.