Rate limits
Budget active keys and requests, then handle throttling.
Check the plan limits
| Plan | Active keys | Requests per minute per key |
|---|---|---|
| Free | 1 | 1,000 |
| Pro | 5 | 1,000 |
| Pro+ | 5 | 1,000 |
The key limit counts non-revoked keys. The request limit is the same on every plan and is shared across v1 resource routes for a given key. The implementation uses fixed minute buckets, keyed by the API key ID. Authentication and scope checks run before the rate check.
Do not rely on retry headers
The v1 limiter does not attach Retry-After, remaining-quota or reset-time headers. Its JSON error helper sets the status and body only. A successful request does not advertise the remaining quota either.
Handle HTTP 429
{
"code": "RATE_LIMITED",
"message": "API rate limit exceeded (1000 requests per minute). Retry shortly."
}Pause requests made with that key and retry with a bounded delay. The example below retries a read with increasing delays and jitter. These delays are client guidance, not a server-provided schedule.
// Server-side GET only. These delays are client guidance, not an API guarantee.
async function readMembers() {
for (let attempt = 0; attempt < 5; attempt++) {
const response = await fetch(
'https://floralitys.com/api/v1/members/page?limit=10',
{ headers: { Authorization: `Bearer ${process.env.FLORALITY_KEY}` } }
);
if (response.status !== 429) {
if (!response.ok) throw new Error(await response.text());
return response.json();
}
await response.body?.cancel();
if (attempt === 4) throw new Error('Rate limited; try again later.');
const delay = Math.min(60000, 10000 * 2 ** attempt);
await new Promise(resolve => setTimeout(resolve, delay + Math.random() * 1000));
}
}Avoid blind write retries
This example is for GET requests. Check an operation’s behaviour before retrying a write after an ambiguous network failure.
