Automation Features Blog Pricing Contact

Error Handling

Every failed request returns a structured JSON error you can act on programmatically. This page covers the response envelope, the error categories, and how to handle them in code.

One envelope for every error. Whichever endpoint you call and whatever goes wrong, a failed request always returns the same JSON shape, an RFC 7807 ProblemDetails object. There is no endpoint-specific error parsing to write: read status for the HTTP outcome, branch on errorCode for the category, and you have handled every error the API can return.

The error envelope

Every error response, on every endpoint, contains the same top-level fields:

Field Type Description
type string RFC 7807 type URI for the error class.
title string Short, human-readable summary of the error class.
status int The HTTP status code, repeated in the body for convenience.
errorCode int The InvoiceXML category code. This is the one value to branch on.
detail string Longer human-readable explanation, safe to show to end users.
errors array An array of finding objects, one per validation error. Present on validation failures, and identical in shape whether the failure is XML validation (4001) or model validation (4002).
warnings array Non-blocking findings, same object shape as a 4001 finding. Advisory only, they never cause a request to fail.

Error codes

The errorCode identifies the category of error. Branch on it to decide how to handle the response. The errors column shows what, if anything, the errors field carries for that code.

errorCode Name Description errors
4000 General Error An unclassified processing error. Check title and detail for information. none
4001 XML Validation The invoice XML violates EN 16931 Schematron business rules (e.g. BR-01, BR-CO-15). Each violation is a finding object. errors[]
4002 Model Validation One or more request fields are missing or malformed before processing could start. errors[]
4003 File Too Large The uploaded file exceeds the 20 MB size limit. none
4004 Unsupported Format The uploaded file type is not supported for that endpoint. none
4005 Extraction Failed The API could not extract invoice data from the PDF. The document may not be an invoice, or the file may be corrupted. none
4006 Rate Limited You have exceeded the request rate limit for your plan. Retry after the period in the Retry-After header. none
4007 Quota Exceeded Your monthly request quota has been reached. Upgrade your plan or wait for the next billing cycle. none

Example responses

The envelope is identical in all of them. Both validation categories (4001 and 4002) use the very same errors array of finding objects, so you handle them with one code path. Every other error code carries no errors field at all.

XML validation, errorCode 4001

The generated or uploaded XML violates EN 16931 Schematron rules. errors is an array of finding objects, one per violated rule.

{
  "type": "https://tools.ietf.org/html/rfc9110#section-15.5.1",
  "title": "Validation Failed",
  "status": 400,
  "errorCode": 4001,
  "detail": "The invoice contains 2 validation error(s).",
  "errors": [
    {
      "rule": "BR-01",
      "line": null,
      "message": "The invoice is missing a specification identifier (BT-24).",
      "btCodes": ["BT-24"],
      "fields": ["specificationId"],
      "raw": "[BR-01] An invoice shall have a specification identifier."
    },
    {
      "rule": "BR-25",
      "line": 3,
      "message": "Line item 3: each invoice line must have an item name (BT-153).",
      "btCodes": ["BT-153"],
      "fields": ["lines[2].item.name"],
      "raw": "[BR-25] Each Invoice line shall contain the Item name."
    }
  ],
  "warnings": []
}

Each finding is self-describing. Use message for end-user display and raw for debugging or logs. The btCodes and fields arrays let you map a finding back to a form input.

Field Type Description
rule string The validated rule identifier, e.g. BR-01.
line int | null 1-based invoice line number, or null for a document-level finding.
message string Plain-language explanation, safe to show end users.
btCodes string[] EN 16931 Business Term codes the rule references.
fields string[] Dotted JSON paths into the invoice the finding maps to. Line-scoped paths use a zero-based index (line 3 maps to lines[2]).
raw string Verbatim validator output, including the rule id, layer and XPath location.
Map findings straight to your form. Key your invoice-form inputs by the same dotted paths (or keep a lookup from BT code to input). On an error response, match each finding's fields or btCodes to the matching input, mark it invalid, and show the friendly message beside it. The user is taken straight to the field that needs fixing, with no XPath decoding.

Model validation, errorCode 4002

A request field is missing or malformed, so processing never started. errors is the exact same flat array of finding objects as 4001. rule and raw are null (model validation has no Schematron rule), while btCodes and fields are resolved from the field path, so the finding maps to the offending input by both BT code and JSON path.

{
  "type": "https://tools.ietf.org/html/rfc9110#section-15.5.1",
  "title": "One or more validation errors occurred.",
  "status": 400,
  "errorCode": 4002,
  "valid": false,
  "detail": "The request failed validation with 2 error(s).",
  "errors": [
    {
      "rule": null,
      "line": null,
      "message": "The seller name is required.",
      "btCodes": ["BT-27"],
      "fields": ["seller.name"],
      "raw": null
    },
    {
      "rule": null,
      "line": 1,
      "message": "Quantity must be greater than zero.",
      "btCodes": ["BT-129"],
      "fields": ["lines[0].quantity"],
      "raw": null
    }
  ],
  "warnings": []
}

Other errors, errorCode 4000 and 4003 to 4007

File size, unsupported format, extraction, rate limit and quota errors carry no errors field. The title and detail tell you what happened.

{
  "type": "https://tools.ietf.org/html/rfc9110#section-15.5.1",
  "title": "File Too Large",
  "status": 400,
  "errorCode": 4003,
  "detail": "The uploaded file exceeds the 20 MB size limit."
}
Warnings never fail a request. The warnings array uses the exact same finding shape as 4001 errors, but it is advisory. A response can be successful and still carry warnings. Only entries in errors make a request fail.

Handling errors in code

Parse the JSON body and branch on errorCode. Because both validation categories share the same errors array, they need just one branch between them; every other code falls through to a generic handler.

const response = await fetch(apiUrl, { method: 'POST', body: formData });

if (!response.ok) {
  const problem = await response.json();

  switch (problem.errorCode) {
    case 4001: // XML validation, Schematron rule violations
    case 4002: // Model validation, malformed request fields
      // Both return the same flat array of finding objects.
      problem.errors.forEach(f => {
        const where = f.line != null ? `line ${f.line}` : 'document';
        console.error(`${where}: ${f.message}`);
        // f.fields and f.btCodes map the finding to a form input
      });
      break;

    default: // 4000, 4003 to 4007: no errors array, use title + detail
      console.error(`${problem.title}: ${problem.detail}`);
  }
}