Error Codes
Errors always use a real (non-2xx) HTTP status code, and the same JSON body:
{
"success": false,
"message": "Invalid API key",
"code": 401
}
code repeats the HTTP status. Check the status code (or success) — do not rely on message for conditional logic, its wording may change.
HTTP Status Codes
| Code | Meaning | Common Cause |
|---|---|---|
304 | Not Modified | ETag match — your cached copy is current |
400 | Bad Request | Invalid or unknown query parameters, or a non-numeric {id} path parameter |
401 | Unauthorized | Missing, malformed or unknown x-api-key |
403 | Forbidden | Account blocked or insufficient permissions |
404 | Not Found | Endpoint path wrong, or the requested resource does not exist on RSI |
429 | Too Many Requests | Daily quota exceeded, or a per-minute request or scrape limit was hit |
500 | Internal Server Error | An unexpected error on the server |
503 | Service Unavailable | Scraping is temporarily unavailable, or a backing service is down |
504 | Gateway Timeout | The live scrape took too long to complete |
Common Messages
| Status | Message | Cause |
|---|---|---|
401 | API key is required in x-api-key header | The header is missing |
401 | Invalid API key format | The key is not 32–68 characters of letters, digits or _ |
401 | Invalid API key | The key does not exist (or was deleted or renewed) |
403 | User is blocked: <reason> | The account is blocked (the reason is appended when one was given) |
429 | Daily request quota exhausted | You have used your 500 daily requests on ?refresh=true calls |
429 | Too many requests. Try again in the next minute. | Global per-minute request limit (every request counts). Honour the Retry-After header |
429 | API request rate limit exceeded. Try again in the next minute. | Per-key limit of live scrapes per minute |
429 | Scraping rate limit exceeded. Try again in the next minute. | Global limit of live scrapes per minute |
404 | The requested resource could not be found. | The scrape ran but RSI has no such resource |
504 | The scraping request took too long to complete. | The live scrape timed out and no cached copy exists |
503 | The service is currently unavailable… | Infrastructure failure and no cached copy exists |
Scrape failures end the message with [RequestId: …]. Give that id to the maintainers when you ask for support.
For 400 validation errors, message is an array of strings — one per invalid parameter (for example ["property foo should not exist"]) — rather than a single string.
When a live scrape fails but a cached copy exists, the API returns the cached copy with a 200 instead of an error.
For guidance on handling these errors in your code, see Troubleshooting.
For how the quota works and what triggers a 429, see Rate Limits & Quota.