Errors and limits
Status codes, the error shape, rate limits and what is logged.
Status codes
| Code | Meaning |
|---|---|
200 | Success. The body is the operation's result. |
400 | The request was understood but refused: a body that is not a JSON object, a missing organisation (organisation_required), or an input the operation rejects (the body says which). |
401 | No token, an expired token, or one the API does not recognise. |
403 | The token lacks the scope, the user's role may not call this operation (role_not_allowed), or the organisation is not one the token may act for. |
404 | No such operation, or it is no longer exposed. |
409 | The organisation's accounting connection needs attention (AccountingConnection), for operations that read Xero or QuickBooks live. |
429 | Rate limited. Wait and retry. |
Errors are JSON. OAuth-style errors carry error and error_description; an operation's own errors carry what that operation documents, usually a code and a message.
{ "error": "invalid_request", "error_description": "The body must be a JSON object." }
Rate limits
| Limit | Default |
|---|---|
Requests to /v1 and /mcp | 120 per minute per token |
| Token requests | 600 per minute per IP |
| Password sign-ins | 30 per minute per IP |
| Dynamic client registrations | 200 per hour per IP |
A limited request gets 429. Spread work out rather than retrying in a tight loop.
Audit
Every call to an operation is recorded: the client, the user (for a user's connection), the organisation, the operation, the status and how long it took. Synced admins can see this under Admin › Integrations › API activity, and an organisation's admins can see which apps are connected and revoke them.
Changes
New operations appear here as admins expose them. An operation's inputs can gain optional fields; a required field is never added to an existing operation without a new version. Removing an operation from the public API makes it 404.
