Rate limits
WhatIsUp uses a token-bucket limiter, scoped per API key.
Defaults
- 60 burst. A full bucket holds 60 tokens. Spend them as fast as you like.
- 1 request per second sustained. The bucket refills at 1 token / sec.
Plan-scoped overrides exist; the headers below always reflect your actual limits.
Response headers
Every response carries:
| Header | Meaning |
|---|---|
X-RateLimit-Limit | Bucket capacity. |
X-RateLimit-Remaining | Tokens left after this request was counted. |
X-RateLimit-Reset | Unix timestamp (seconds) when the bucket will be full again. |
On 429 Too Many Requests, you also get:
| Header | Meaning |
|---|---|
Retry-After | Seconds to wait before the next request. Honor this. |
The body uses the standard envelope with code: "rate_limited".
Reading limits without consuming
GET /v1/limits returns your current headroom across every bucket
(outbound messages, webhook deliveries, etc.) without spending a token.
Useful from a dashboard before a burst.
Backoff pattern
async function callApi(url, init) {
for (let attempt = 0; attempt < 5; attempt++) {
const res = await fetch(url, init);
if (res.status !== 429) return res;
const wait = Number(res.headers.get('Retry-After') ?? 1) * 1000;
await new Promise((r) => setTimeout(r, wait + Math.random() * 250));
}
throw new Error('Rate limited after 5 retries');
}Don't use exponential backoff against 429 — Retry-After is authoritative
and respects refill rate exactly. Reserve exponential backoff for transient
5xx.
What counts as one request
One HTTP request = one token, regardless of payload size. Webhook delivery attempts originate from us, so they don't count against your inbound limit.
Need more?
Hit the support form (POST /v1/support/tickets) or email hello@whatisup.dev. Higher limits are part of the Pro plan and bespoke for Scale.