Numina uses HTTP status codes for the class of failure and a stable error code for the exact reason. Branch on error; error_description is for people and may change, and can be in Danish.
{
"error": "validation_error",
"error_description": "Journal entries do not balance",
"details": [
{
"field": "lines",
"message": "Sum of amounts must equal zero."
}
]
}| Field | |
|---|---|
error |
Machine-readable code, listed below |
error_description |
A sentence for logs and people |
details |
For field errors: one entry per field, with a field path such as lines.0.account_number |
scope |
On insufficient_scope: the scopes the route asks for, separated by spaces |
Codes
| Status | error |
Meaning |
|---|---|---|
| 400 | invalid_request |
The body or query is malformed, or names an account, VAT code or contact the company does not have |
| 400 | validation_error |
Well-formed, but breaks an accounting rule: unbalanced lines, a closed accounting year, an incomplete invoice |
| 400 | payment_details_required |
An invoice cannot be booked without a bank account to be paid into. Pass bank_account_id when you create it, or have the company choose a default bank account for invoices |
| 400 | missing_file, invalid_file, file_too_large, upload_error |
An upload has no file, one that is not a PDF, PNG or JPEG, one over 10 MB, or more than 10 files |
| 400 | range_crosses_accounting_year |
A balance period spans two accounting years |
| 401 | unauthorized |
No token, or an Authorization header that is not Bearer |
| 401 | invalid_token |
A token that is wrong, expired or revoked |
| 403 | insufficient_scope |
The token lacks a scope this endpoint needs; scope names them |
| 403 | booking_not_available |
Booking is not available to Fuld Service customers |
| 403 | company_archived |
The company is archived |
| 403 | forbidden |
A sandbox company cannot send invoices by email |
| 404 | not_found |
The resource does not exist in this company |
| 404 | accounting_year_not_found |
No accounting year covers the requested period |
| 409 | conflict |
The request clashes with the resource’s current state: the entry is booked, Numina’s bookkeeping agent is working on it, or the reference or product number is taken |
| 409 | attachment_exists, attachment_not_empty |
The entry already has a document, or the document already has files |
| 409 | attachment_required |
A journal entry needs a document before it can be booked |
| 409 | idempotency_key_in_use |
A request with this Idempotency-Key is still running |
| 422 | idempotency_key_reused |
This Idempotency-Key was used with a different body or endpoint |
| 429 | rate_limit_exceeded |
Too many requests; see Rate limits |
| 500 | internal_error |
Something failed on our side |
A 404 not_found with the description Not found on any route means the OAuth user who connected your app is no longer a member of the company. Someone who is a member has to connect it again.
A few failures are not JSON: a body that is not valid JSON returns 400 with the text Bad request, a JSON body over 4 MB returns 500, and an unknown path returns an HTML 404.
Retrying
To retry a create safely after a timeout, send an Idempotency-Key.