API errors and rate limits
Every error code the API can return, what the rate limits are, and how to retry safely.
What an error looks like
Any response that is not HTTP 200 is an error. The body is JSON with a short, stable error code, sometimes with extra fields that belong to that code. Match on the code, never on the HTTP status alone.
HTTP/1.1 429 Too Many Requests
Retry-After: 17
X-RateLimit-Limit: 120
X-RateLimit-Remaining: 0
{ "error": "rate_limited" }Key, plan, and access errors
| Error | HTTP | Meaning and fix |
|---|---|---|
missing_api_key | 401 | No Authorization: Bearer header. Dashboard logins do not work on the API. |
invalid_api_key | 401 | The key is wrong, was regenerated, or was deleted. Keys are case sensitive and exactly 64 characters. |
too_many_failed_attempts | 429 | 20 wrong keys from your IP in 10 minutes. Wait for Retry-After seconds. |
ip_not_allowed | 403 | Your IP whitelist is on and this request came from an IP that is not on it, or the list is empty. |
tier3_required | 403 | The plan is not Tier 3 or has expired. |
suspended, banned | 403 | The Console Client account is suspended or banned. |
maintenance | 503 | Console Client is in maintenance. Retry in a few minutes. |
Request errors
| Error | HTTP | Meaning and fix |
|---|---|---|
unknown_endpoint | 404 | The path or the HTTP method is not part of the API. Check the spelling and the method. |
invalid_json | 400 | The body is not valid JSON. |
body_too_large | 413 | The body is over 5 MB. |
invalid_request | 400 | A required field is missing or has the wrong type. |
invalid_account | 400 | The account ID is missing. |
not_found | 404 | No account with that ID. |
not_assigned, account_missing | 404 | The account is not running on a backend. Connect it first. |
not_connected | 409 | The account is not online. |
command_timeout, timeout | 504 | The account did not answer in time. It may be lagging or reconnecting. Retry once. |
server_error | 500 | Something failed on our side. Retry, and open a ticket if it keeps happening. |
Endpoint-specific codes, such as cooldown for connect or macro_not_found, are listed with their endpoint.
Rate limits
| Limit | Value | When you hit it |
|---|---|---|
| Requests | 120 per minute, per key | 429 rate_limited with Retry-After. |
| In flight | 8 requests at the same time | 429 too_many_concurrent_requests. A long poll counts as one for as long as it is open. |
| Wrong keys | 20 per 10 minutes, per IP | 429 too_many_failed_attempts. |
Every authenticated response tells you where you stand:
| Header | Meaning |
|---|---|
X-RateLimit-Limit | Requests allowed per window: 120. |
X-RateLimit-Remaining | Requests left in the current window. |
X-RateLimit-Reset | Unix time in seconds when the window resets. |
Retry-After | Only on a 429: how many seconds to wait. |
The limit is shared by everything that uses your key, and refused requests count too, so a script that hammers a 429 only keeps itself locked out.
Poll less, get more
| You want | Do this |
|---|---|
| Account status | One GET /accounts every 5 to 10 seconds covers every account. Do not call GET /accounts/{id} once per account. |
| Chat in real time | One GET /chat long poll with wait=25000 covers every account, at two or three requests a minute. |
| To know a macro finished | GET /macros/active every few seconds, or have the macro send a chat line or a Discord webhook as its last step. |
| A long click sequence | Build it as a macro and run it with one request. |
Retry safely
| Response | Retry? |
|---|---|
| 429 | Yes, after Retry-After seconds. For cooldown use cooldownRemaining. |
| 500, 503, 504 | Yes, with a growing delay: 1, 2, 4, 8 seconds, then give up and alert yourself. |
| 400, 401, 403, 404, 409 | No. The same request will fail the same way until you change something. |
Connect, disconnect, stop, and close are safe to repeat. Be careful repeating POST /chat/send after a timeout on your side: the first attempt may have gone through, and the account would say it twice.
Check the troubleshooting guide or return to all guides.