Skip to main content
The Just Flow It API enforces two independent limits, both scoped per API key. Every response tells you exactly where you stand via the RateLimit-* headers, and a 429 response includes Retry-After so you know how long to wait before retrying.

Burst limit

120 requests / 60s across all endpoints. Smooths out spikes of traffic.

Generation quota

500 generations / rolling 30 days. Both POST /diagrams/generate and POST /diagrams/{id}/edit count.

The two limits

120 requests / 60s
Applies to every request made with a given key, regardless of endpoint. When you exceed it you receive a 429 with code rate_limit_exceeded. The window is a rolling 60 seconds.
500 generations / rolling 30 days
Applies to POST /diagrams/generate and POST /diagrams/{id}/edit (both use scope generate and run an AI generation). Each accepted job counts once against the quota. When the quota is exhausted you receive a 429 with code quota_exceeded. The window is a rolling 30 days.
Both limits are tracked per key. A personal Pro key and a Team org key each have their own independent counters.

Response headers

Every API response carries the rate-limit headers, so you can read your remaining allowance without waiting for a 429.
integer
The maximum number of requests allowed in the current window.
integer
The number of requests remaining in the current window.
integer
The number of seconds until the current window resets.
integer
Present only on 429 responses. The number of seconds to wait before retrying.

Example: a normal response

Read RateLimit-Remaining on every response and proactively slow down as it approaches 0, rather than waiting to be throttled.

Handling 429 responses

A 429 Too Many Requests always has error.type of rate_limit_error. Inspect error.code to tell the two limits apart, then use the Retry-After header to decide how long to wait.

Example: a 429 burst response

rate_limit_exceeded is transient — wait Retry-After seconds and retry. quota_exceeded is not retryable within the window: retrying immediately will keep failing until your rolling 30-day generation count drops below 500. Back off until the quota resets, or upgrade your plan.
1

Read the code

On a 429, branch on error.code. Treat rate_limit_exceeded as retryable and quota_exceeded as a hard stop for the current window.
2

Honor Retry-After

Wait at least Retry-After seconds (it is provided in seconds) before retrying. Never retry sooner.
3

Add exponential backoff with jitter

For repeated rate_limit_exceeded responses, increase the delay on each attempt (e.g. Retry-After, then 2x, 4x…) and add random jitter to avoid thundering-herd retries. Cap the number of attempts.
4

Stop on quota_exceeded

Do not retry quota_exceeded in a loop. Surface it to the operator and resume after the rolling window frees up capacity.

Backoff example

FAQ

Yes. RateLimit-Limit, RateLimit-Remaining, and RateLimit-Reset are returned on every API call. Retry-After is added only on 429 responses.
Only POST /diagrams/generate. Each accepted job (returned as 202 Accepted with a queued Generation) counts once. Polling GET /generations/{id} does not count against the quota, but every request still counts against the 120/60s burst limit.
Per key. Each key — personal Pro or Team org — maintains its own burst and quota counters.
Both are 429 with error.type rate_limit_error. rate_limit_exceeded means you hit the short-term burst limit (120/60s) — retry after Retry-After seconds. quota_exceeded means you exhausted the 500-generations rolling 30-day quota — retrying immediately won’t help; wait for the window to free up or upgrade.