Rate limits
The request budgets per API key, test key, organisation and MCP connection, the RateLimit headers that show where you stand, and what to do on a 429.
Plek's API limits how many requests a client may make, so one busy integration can't slow down the booking site or another organisation. The limits are generous: a well-behaved client that reads the headers below never sees a refusal.
How the budgets work
Every request draws from one or more budgets. A budget is a token bucket: it holds up to its quota, refills continuously at quota per minute, and a request takes one token. So a client that was quiet may send its whole quota at once (a burst), and after that one request every 60 / quota seconds.
Requests come in three classes, each with its own budget:
- read:
GETrequests, and thePOSTrequests that only calculate (…/quote,…/preview); - write: every other
POST,PUT,PATCHandDELETE; - expensive: exports, reports, analytics, free-slot search and availability, the personal-data export.
| Who | read / min | write / min | expensive / min |
|---|---|---|---|
| One API key | 600 | 120 | 20 |
| One test key (1 hour) | 60 | 20 | 5 |
| The whole organisation: all its API keys, connected apps (OAuth) and test keys together | 1200 | 300 | 40 |
One MCP connection (API key or connected app) on /mcp, any request |
120 |
A request made with an API key draws from the key's budget and from the organisation's. A refused request costs nothing. Plek may give an organisation other budgets; the headers always tell what applies.
The staff app (per staff member: 1200 / 300 / 60) and the public booking API (per visitor IP address and organisation: 600 / 60 / 120, plus stricter per-hour limits on checkout and sign-in) have their own budgets, apart from the organisation's.
Headers
Every response to a request with an API key carries the headers of draft-ietf-httpapi-ratelimit-headers, one item per budget the request drew from:
RateLimit-Policy: "key-read";q=600;w=60, "organisation-read";q=1200;w=60
RateLimit: "key-read";r=599;t=1, "organisation-read";r=1187;t=10
RateLimit-Policy: the budget's name, its quotaqand windowwin seconds.RateLimit:rrequests you may still send right now,tseconds until the whole quota is back.
Policy names: key-read, key-write, key-expensive, temporary-key-…, organisation-… and
mcp. Browsers may read the headers (they are exposed through CORS).
When you go over
The API answers 429 Too Many Requests with a Retry-After header (seconds) and:
{ "error": "Too many requests. Please slow down and retry later.", "code": "rate_limited", "retryAfter": 20 }
On /mcp the body is a JSON-RPC error whose data holds code: "rate_limited" and retryAfter.
Wait Retry-After seconds before the next request. Better still, pace yourself: when r gets
low, spread the remaining requests over t seconds. Use webhooks instead of polling where you
can, and page through lists rather than fetching them again.
Seeing your usage
Settings > API & webhooks shows, for the whole organisation and for every API key and connected
app, how much of each budget is used this minute and how many requests were made and refused
in the last 24 hours (GET /api/org/{organisation_id}/api-usage, staff with integration:read).