Operating

Rate limits

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.

RoutesRequests per minute
/v1/*60
/api/models60
/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.

LimitDefault
Requests per minute, per account60
Requests per minute, per API key120
Tokens per minuteNot enforced by default
Daily credit capNot 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.

Response headers
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 57
X-RateLimit-Reset: 1787950470
 
X-UpfynAI-User-RateLimit-Limit: 60
X-UpfynAI-User-RateLimit-Remaining: 52
  • X-RateLimit-* — the address-level window. Reset is 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#

429 Too Many Requests
{
"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.