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: GET requests, and the POST requests that only calculate (…/quote, …/preview);
  • write: every other POST, PUT, PATCH and DELETE;
  • 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 quota q and window w in seconds.
  • RateLimit: r requests you may still send right now, t seconds 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).