Conservative repair — what gets fixed, what never does

POST /api/v1/repair rewrites structure and notation only, then revalidates the result through the exact same validator every other endpoint uses, so the response shows precisely what changed and what is still wrong. Unlike /api/v1/validate, this endpoint requires an X-Api-Key header on every call.

What gets repaired

  • Empty elements are removed (PEPPOL-EN16931-R008) — except any element whose name ends in "Amount", which this pass never touches, even when empty.
  • A missing currencyID attribute on an Amount element is added, inherited from the document's own DocumentCurrencyCode (PEPPOL-EN16931-R051) — skipped entirely if the document carries more than one currency code, since which amount belongs to which currency can no longer be inferred safely.

What is never repaired — and why that's a safety feature

Monetary amounts, VAT rates, dates, and party identities are never modified by this endpoint, under any circumstance. Arithmetic rule failures (BR-CO-*, e.g. a total that doesn't equal its lines) are only ever reported with expected-vs-found — never silently corrected. Letting software decide what a total "should" be is a decision that belongs to the person who issued the invoice, not to a repair pass; refusing to guess is the guarantee, not a missing feature.

Example response

For an invoice missing a currencyID on its PayableAmount:

{
  "repaired_xml": "...<cbc:PayableAmount currencyID=\"EUR\">121.00</cbc:PayableAmount>...",
  "changes": [
    {
      "rule_id": "PEPPOL-EN16931-R051",
      "location": "/Invoice/cbc:PayableAmount",
      "before": "<cbc:PayableAmount>",
      "after": "<cbc:PayableAmount currencyID=\"EUR\">",
      "changelog": "Added currencyID=\"EUR\" to cbc:PayableAmount, inherited from DocumentCurrencyCode"
    }
  ],
  "revalidation": { "verdict": "acceptable", "remaining_findings": [] }
}

Every applied change carries both halves: the machine diff (location/before/after) and a human-readable changelog line. A repair that changed nothing returns an empty changes array with repaired_xml identical to the input — that is a normal outcome, not an error.

Validate your invoice free