Developer
Rate limits & errors
One error shape, named codes, and limits per credential.
Limits
| Kind | Limit | Keyed by |
|---|---|---|
| Reads (GET) | 100 per minute | the credential (key or OAuth client) |
| Writes (POST / PATCH / DELETE) | 30 per minute | the credential |
| Token endpoint | 10 per 15 minutes | IP |
Responses carry RateLimit-Limit, RateLimit-Remaining and RateLimit-Reset. On 429 rate_limit_exceeded, wait for the reset — do not hammer.
Errors
Every error, from any endpoint, is:
json
{ "error": "<code>", "error_description": "<what to do about it>", "details": [ { "field": "…", "message": "…" } ] }| HTTP | error | Meaning |
|---|---|---|
| 400 | bad_request | Malformed request (e.g. no JSON object body) |
| 400 | validation_error | A field is missing or wrong; every offending field is named in `details` |
| 401 | unauthorized | No bearer credential |
| 401 | invalid_token | Credential unknown, expired or revoked; or its user no longer exists |
| 403 | insufficient_scope | The credential was never granted this feature |
| 403 | insufficient_permissions | Granted the feature but not this verb — or the bound user no longer holds it |
| 404 | not_found | Not in your business (ids from other businesses are indistinguishable from missing ones) |
| 409 | conflict | Already exists (e.g. a party with that email) |
| 429 | rate_limit_exceeded | Slow down |
| 5xx | server_error | Ours. Retry with backoff; the response carries a request id — quote it to support. |
ℹ️A bad id is never a 5xx
If you can make the API answer 500 by changing an id or a field, that is a bug on our side — report it.