The SpeyBooks API uses conventional HTTP status codes to indicate the outcome of a request. Codes in the 2xx range indicate success, codes in the 4xx range indicate a problem with the request, and codes in the 5xx range indicate an issue on our end.

Error response format

Every error response follows a consistent envelope. The code field is a machine-readable string you can match against in your code. The message field is a human-readable explanation suitable for logging — it should not be displayed directly to end users.

HTTP status codes

StatusMeaning
200Success — the request completed normally
201Created — a new resource was created
204No Content — the request succeeded with no response body
400Bad Request — the request was malformed or contained invalid parameters
401Unauthorized — no valid authentication credentials were provided
403Forbidden — the credentials are valid but lack permission for this action
404Not Found — the requested resource does not exist
409Conflict — the request conflicts with the current state of a resource
422Unprocessable Entity — the request was well-formed but failed business logic validation
429Too Many Requests — you have exceeded the rate limit
500Internal Server Error — something went wrong on our end

Error codes

CodeStatusDescription
validation_error400One or more fields failed validation. Check the message for details.
invalid_id400The ID does not match the expected format. SpeyBooks uses prefixed IDs — for example, inv_42 for invoices, cont_3 for contacts.
not_found404The resource does not exist, or it belongs to a different organisation.
unauthorized401The request lacks valid authentication. Either the session has expired, the API key is missing, or the token is invalid.
forbidden403Authentication succeeded but the credentials lack the required scope.
insufficient_scope403The API key does not have the required scope for this endpoint. The message field indicates which scope is needed.
conflict409The action conflicts with the current state of the resource — for example, deleting a finalised invoice.
unprocessable_entity422The request is syntactically valid but violates a business rule — for example, declaring a dividend that exceeds retained profits.
rate_limited429Too many requests. Back off and retry after the period indicated in the Retry-After header.
internal_error500An unexpected error on our side. If this persists, contact support with the request timestamp and endpoint.

Idempotency errors

When using the Idempotency-Key header, two additional scenarios can occur. If you reuse a key with different request parameters, the API returns a 409 Conflict. If the original request failed with a 5xx error, the key is released and can be retried. Keys expire after 24 hours.

Handling errors

For robust integration, your client should:

  1. Always check the success field before accessing data.
  2. Match on the error.code string for programmatic handling, not the HTTP status code alone — multiple error codes can share the same status.
  3. Log the full error response including code and message for debugging.
  4. Implement exponential backoff for 429 and 5xx responses.
  5. Never display error.message directly to end users — it is intended for developers and may change between releases.