Docs › API reference › Rate limits
API rate limits, 429 responses and Retry-After
How many requests you can make per minute, how OmniPosts counts them, and what to do when you get a 429.
OmniPosts limits how fast you can call the API. The limits protect everyone's posting from a runaway script. Normal use does not come near them.
The buckets
Every request is counted in one bucket. Counting uses fixed windows: a one-minute bucket starts fresh at the start of each clock minute.
| Bucket | Limit | Window | Counted per | Which requests |
|---|---|---|---|---|
| Read | 600 | 1 minute | organization | Every GET (and HEAD) |
| Write | 60 | 1 minute | organization | Every other write: POST, PUT, PATCH, DELETE |
| Autosave | 30 | 1 minute | organization | PATCH /v1/ideas/{id} only |
| Media | 10 | 1 minute | organization | Writes under /v1/media: uploads and PATCH /v1/media/{id} |
| Auth | 20 | 1 minute | client IP address | /v1/auth/*: sign up, log in, log out |
| Auth, per account | 20 | 1 minute | email address | POST /v1/auth/login, on top of the IP limit |
| Export | 3 | 1 hour | organization | GET /v1/settings/export, on top of the Read bucket |
"Per organization" means everything you do with any key or session of one organization shares the bucket. Two keys in the same organization do not get two budgets.
The Read, Write, Autosave and Media counts are kept per API server. If OmniPosts runs more than one API server, each one allows its own budget, so the real ceiling can be higher than the number above, never lower. Auth and Export are shared across servers.
Requests that fail to authenticate (401) are not counted.
The beta waitlist form on the pricing page (POST /waitlist) is not part of the API. It has its own limit of 5
attempts an hour per client address, and answers with a redirect back to the page instead of a 429.
Headers
| Header | When | Meaning |
|---|---|---|
X-RateLimit-Remaining |
Every request that was counted, not only a refused one | Requests left in the current window. 0 on a refusal |
Retry-After |
Every 429 |
Whole seconds until the current window ends. At least 1 |
HTTP/1.1 200 OK
X-RateLimit-Remaining: 587
What a 429 looks like
The export and log-in limits have their own wording in message (for example, how many exports you can
download an hour), with the same code and the same Retry-After.
HTTP/1.1 429 Too Many Requests
Retry-After: 23
X-RateLimit-Remaining: 0
Content-Type: application/json
{
"error": {
"code": "rate_limited",
"message": "Too many requests. Wait a moment and try again."
}
}
What to do
- Wait
Retry-Afterseconds, then try again. Do not retry in a tight loop. - Watch
X-RateLimit-Remainingand slow down before it reaches 0. - To post to many channels, put them in one post with several targets. One
call to
POST /v1/groupscounts once, however many channels it names. - Use an
Idempotency-Keyon everyPOST /v1/groups, so retrying after a429or a timeout is safe. See Idempotency. - Use webhooks instead of polling for results.
Related
- Errors for the envelope.