Rate limits
The Public API rate-limits its credential endpoints (the OAuth token and revocation endpoints) and MCP tool calls. The limits absorb retry storms and credential-guessing; a client that caches its tokens never sees a 429.
OAuth endpoints
| Endpoint | Counted per | Limit |
|---|---|---|
POST /api/v1/auth/token | client IP and client_id (two separate buckets) | 10 requests / 60 s each |
POST /api/v1/oauth/revoke | client IP | 10 requests / 60 s |
The window is sliding: each request is timestamped, and requests older than
60 seconds fall out of the bucket. On the token endpoint the per-client_id
check runs before the grant is exchanged, so a 429 never consumes an
authorization code or refresh token. Retrying after the window is always safe.
Response headers
Both endpoints report the state of the per-IP bucket on their responses. The headers are set before authentication, so they appear on auth failures too:
| Header | Meaning |
|---|---|
X-Rate-Limit-Remaining | Requests left in the current 60 s window |
X-Rate-Limit-Reset | Unix timestamp (seconds) when the window resets |
Both headers are CORS-exposed, so browser-based clients can read them.
The 429 response
A breached limit returns HTTP 429 with an error body in the OAuth RFC 6749 shape, not the regular error envelope described in Errors:
Code
Backing off
- Cache tokens. Access tokens live for 3600 seconds. Request one and reuse it until shortly before expiry. A client that requests a fresh token per API call hits the 10-per-minute limit immediately.
- Serialize refreshes. Keep one in-flight token request per
client_idand have concurrent callers wait on its result. - Honor the reset header. On a 429, wait until the time in
X-Rate-Limit-Resetbefore retrying; it is at most 60 seconds away. Where headers aren't available, use exponential backoff with jitter, starting at a few seconds.
Resource endpoints
Resource endpoints (/api/v1/customers, /api/v1/invoices, …) do not
currently enforce a fixed request quota. The authoritative view for your key
is GET /api/v1/api-key: its rateLimitTiers field lists the tiers in
effect (today a single unlimited tier). Build clients defensively anyway:
treat any 429 as retryable and honor the headers above.
MCP tool calls
Calls to the MCP server are limited separately, per (OAuth grant, tool), with per-minute caps and per-hour caps on some tools. A breached cap fails the tool call with an MCP protocol error rather than an HTTP 429; the error states how many seconds to wait before retrying.