Fatorly
Developers

Errors

The Integration API error model (RFC 7807 problem+json) and the full catalog of status codes with their meaning and fix.

When a request fails, the Integration API returns a standard HTTP status code and an RFC 7807 application/problem+json body:

{
  "type": "https://integration.fatorly.com/errors/validation-failed",
  "title": "Validation Failed",
  "status": 422,
  "detail": "2 business-rule violations",
  "instance": "/v1/invoices",
  "traceId": "00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01",
  "errors": [
    { "field": "lines[0].vatRate", "message": "VAT rate not permitted for category S" }
  ]
}
FieldMeaning
typeStable machine-readable identifier. Branch on this (or on status) — never on title/detail text, which may change.
titleShort human-readable summary of the error class.
statusThe HTTP status code, repeated in the body.
detailWhat went wrong in this specific case (optional).
instanceThe request path that produced the error (optional).
traceIdCorrelation id — include it when contacting support (optional).
errorsField-level validation errors, each with field and message (optional).

Error catalog

All type identifiers live under https://integration.fatorly.com/errors/:

Statustype suffixMeaningHow to fix
400 Bad Requestbad-requestMalformed/unparseable JSON, a field that fails validation, or the required Idempotency-Key header is missing or too long.Check detail and errors[]. Add an Idempotency-Key header and correct any invalid fields.
401 UnauthorizedunauthorizedThe X-Api-Key header is missing or the key is invalid or revoked.Send a valid key in X-Api-Key. If it was revoked, create a new key.
402 Quota Exceededquota-exceededYour monthly document quota has been reached.Wait for the quota to reset or upgrade your plan.
403 ForbiddenforbiddenThe key is valid but lacks the scope the endpoint requires (e.g. invoices:write).Adjust the key's scopes in Settings → API Keys, or use a key that has the scope.
404 Not Foundnot-foundThe endpoint or referenced resource doesn't exist.Verify the URL, the resource id, and that the key's company owns it.
409 ConflictconflictAn Idempotency-Key was reused with a different body, or the document is in a state that forbids the operation (e.g. cancelling a submitted invoice).Use a fresh key for a new request, or resolve the document-state conflict.
422 Validation Failedvalidation-failedThe document failed PINT-AE schematron validation.Read errors[] for the failing rules and correct the invoice data (for example a missing exemptionReasonCode on an exempt line).
429 Too Many Requestsrate-limitedRate limit exceeded (default 100 requests per 10 seconds per company).Wait for the number of seconds in the Retry-After header, then retry.
500 Internal Server Errorinternal-errorAn unexpected platform fault.Retry with backoff; report the traceId if it persists.
502 Upstream Errorupstream-errorThe gateway could not get a valid response from an upstream service — your request itself was well-formed.Retry with backoff.

Note

400 vs 422. A 400 means the request itself is malformed — bad JSON, a missing header, or a field that doesn't validate. A 422 means the request was well-formed but the resulting e-invoice doesn't pass the UAE PINT-AE rules.

Note

500 vs 502. A 502 means your request was fine but an upstream hop failed — safe to retry with backoff. A 500 is an unexpected fault; if it persists, contact support with the traceId.

Rate limiting

Requests are limited per company. A 429 response carries two headers:

  • Retry-After — seconds to wait before retrying.
  • X-RateLimit-Remaining — always 0 on a rejected request.

Validation and quota

  • Idempotency-Key is mandatory on every POST (except …/validate); omitting it is the most common cause of 400. See Idempotency.
  • An exemptionReasonCode is required on any line whose taxCategoryCode is E; omitting it triggers a validation error.
  • A 402 is about your plan, not your request — the request was otherwise valid. Retrying won't help until the quota resets.

Delivery failures after submit

POST /invoices/{id}/submit is asynchronous: it returns 202 with status Pending, and the PINT-AE validation and Peppol delivery happen in the background. If either fails, the document's status becomes DeliveryFailed — a successful 202 on submit therefore does not guarantee delivery.

  • List every failed document with GET /invoices/failed — each item carries a submissionError with the reason (a PINT-AE rule failure or a Peppol delivery error).
  • Or poll a single document with GET /invoices/{id} — when its status is DeliveryFailed, the response includes the same submissionError.

To recover: fix the data with PUT /invoices/{id}, re-check it with POST /invoices/{id}/validate until it returns "valid": true, then submit again with POST /invoices/{id}/submit.

Note

POST /invoices/{id}/validate runs the same checks as the background submission and persists nothing — call it as often as you like while fixing a document. It is the one POST that does not require an Idempotency-Key.

Handling errors in code

  • Branch on the type URI (or status), never on title/detail text.
  • Retry transient failures (429, 500, 502, network errors, timeouts) with backoff, and reuse the same Idempotency-Key on POSTs so you never duplicate a document.
  • Do not blindly retry 400/401/402/403/404/409/422 — these need a fix (correct the payload, the key, its scopes, or your plan), not another attempt.
  • Log the traceId of any unexpected 500/502 — support can use it to find the exact request in the platform logs.

On this page