There are two independent limits: one on the network address a request comes from, and one on the account it authenticates as. A request has to pass both.
Per address#
Counted in a rolling 60-second window, per route group.
| Routes | Requests per minute |
|---|---|
/v1/* | 60 |
/api/models | 60 |
/auth/* | 20 |
Per account#
Also a 60-second window. These are the defaults; they scale with your plan, so a higher tier gets a proportionally higher ceiling.
| Limit | Default |
|---|---|
| Requests per minute, per account | 60 |
| Requests per minute, per API key | 120 |
| Tokens per minute | Not enforced by default |
| Daily credit cap | Not enforced by default |
Split work across keys
The per-key limit is higher than the per-account one, so the account limit is what you hit first. Separate keys give you separate per-key budgets and much better attribution in your logs — but they do not raise the account ceiling.Reading your budget#
Every response carries the current state of both counters.
X-RateLimit-Limit: 60X-RateLimit-Remaining: 57X-RateLimit-Reset: 1787950470X-UpfynAI-User-RateLimit-Limit: 60X-UpfynAI-User-RateLimit-Remaining: 52
X-RateLimit-*— the address-level window.Resetis a Unix timestamp in seconds.X-UpfynAI-User-RateLimit-*— your account’s window.
Browser JavaScript cannot read the per-key headers
The per-key counters are sent, but they are not in the CORS exposed-headers list, so front-end code cannot see them. Read them from a server.What a 429 looks like#
{"error": {"message": "Too many requests. Please slow down.","type": "rate_limit_error","code": "user_rate_limit_exceeded"},"retry_after": 23,"reset_at": "2026-08-29T10:41:10.000Z"}
Retry-After is set as a header too. Wait that long — the body’s retry_after is seconds and reset_at is the same moment as an ISO timestamp, whichever is easier for you to use.
Repeated 429s make it worse
If you keep hammering after being limited, the account picks up a short automatic block and starts returning temporary_auto_block. It expires on its own. The fix is exponential backoff with jitter, not a tighter retry loop — there is a worked example in Errors.
If you need more#
Rate limits scale with your plan. If you are hitting the account ceiling on a paid plan and backoff is not enough, get in touch through Support with your typical and peak request rates.
