HTTP status codes
Every response carries one of these status codes. Check the code first, then read the response body for details:Create endpoints do not all return the same status code. Transaction and record endpoints (for example
POST /public/v2/bills/) return 200; master-data endpoints (for example POST /public/v2/customers/) return 201. Check the specific endpoint in the API reference for the documented response code.Error response format
All errors follow this structure:errors.__all__: General errors not specific to a fielderrors.<field_name>: Errors specific to a particular field
errors:
error_code(string, optional): Stable identifier of the errorerror_reason(string, optional): General explanation of the error
409 and 422 responses tied to retry handling are described in the idempotency and write validation guide.
Common errors
Authentication error (403)
Returned when theX-API-KEY header is missing or empty, or the key is unknown or revoked. A key that authenticates but lacks the roles for the operation also returns 403, with Access denied as the message. Authentication covers both cases.
Subscription required (402)
Returned when your organization does not have the subscription required for the requested feature.Validation error (422)
Returned when the request body fails validation. Each key inerrors names a field that failed, with the reasons as a list:
error_code and error_reason, from a write in a locked accounting period:
Not found (404)
Returned when no record matches the ID or number in the request path:Rate limit exceeded (429)
Returned when the API key exceeds its rate limit. Rate limiting covers the limits and how to use theRetry-After header:
Handling errors
Best Practices:
- Always check HTTP status codes
- Parse the
errorsobject for field-specific details - Implement retry logic for rate limits (
429) and server errors (5xx) - Use the
Idempotency-Keyheader so retries do not create duplicate records - Log error responses for debugging
Retrying safely with idempotency keys
Write requests (POST, PUT, PATCH, DELETE) accept an optional Idempotency-Key header so a retry after a network error or timeout does not create a duplicate record.
- Send a unique value in the
Idempotency-Keyheader on the original request. A UUID works well. - If you retry with the same key, the API replays the original response instead of processing the request again. No duplicate record is created.
- Replays are available for 48 hours after the original request. After that window, the key is forgotten and a retry with the same key is treated as a new request.
- Reusing the same key with a different request body returns
422. Either use a new key for the new request, or send the exact same body.
Example
Next: Explore the API Reference →