Rate limits & errors
How the API says no, and what to do about it.
Rate limits
| What | Limit |
|---|---|
| Every API call | 800 requests per minute, per app (all its secrets and channels together), like Twitch's default bucket. |
| Sending chat messages | 20 messages per 30 seconds, per app, per channel. Counted over a rolling 30-second window. |
| Gateway tokens | Each token lasts 1 hour. Mint one when you connect and when it is about to expire, not per request. |
| Webhook reconciliation | Follow next_poll_after. See Creator webhooks. |
Every response from /api/apps/… carries the app's budget, as on Twitch:
| Header | Meaning |
|---|---|
Ratelimit-Limit | Requests allowed per window (800). |
Ratelimit-Remaining | Requests left in this window. |
Ratelimit-Reset | When the window resets, as a Unix timestamp in seconds. |
Over the app limit you get 429 with a Retry-After header (seconds) and retry_after in the body. Over the chat limit you get a 429 whose Retry-After (and retry_after) is when the oldest message in the window ages out, which is when the next send fits:
HTTP/1.1 429 Too Many Requests
{ "success": false, "error": "Rate limited: 20 messages per 30 seconds per channel" }
The limit is per channel, so a busy channel can't slow your bot down on the others. Even under the limit, don't post more than the chat needs. See Developer policies.
Error shape
Every endpoint under /api/apps/… answers an error as:
{ "success": false, "error": "A sentence describing what went wrong" }
A missing scope adds a missing_scope field naming the scope. The error text is for people; branch on the HTTP status code instead.
Status codes
| Status | Meaning | What to do |
|---|---|---|
200 | It worked. The body has "success": true. | |
400 | The request is invalid: empty or over-long content, blocked by the content filter, a missing user_id or message_id. | Fix the request. Retrying it unchanged will fail again. |
401 | The secret is missing, wrong or revoked. | Check the Authorization header. Don't retry in a loop. |
403 | Your app isn't on that channel with the scope this needs (missing_scope), or a bot tried to act on the broadcaster or a moderator. | Stop calling for that channel until the creator re-adds the scope. |
404 | Unknown channel id, a channel with no chat yet, or an unknown message. | Re-read /api/apps/@me/channels. |
429 | Rate limited. | Wait, then retry. See below. |
500 | Something failed on Xive's side. | Retry with backoff. |
503 | Channel apps are not available right now ("Channel apps are not available yet"). | Retry later with backoff. |
Backing off
- On
429,500and503, wait and retry with exponential backoff and a little random jitter: for example 1 s, 2 s, 4 s, … up to a minute. - For chat, keep your own per-channel queue and send at most 20 messages per 30 seconds. That avoids
429s in the first place. - Never retry
400,401or403automatically. - If the gateway disconnects, reconnect with backoff and a freshly minted token.