Developers · API reference · OpenAPI 2.0.0
Every endpoint, one contract.
25 endpoints under https://www.invoicenavigator.eu/api. JSON in, JSON out, Bearer key in the header. The table below is generated from openapi.json; the spec is the source of truth.
Validate and repair: use v3. The v1/v2 validate and repair endpoints keep working but are deprecated for new integrations; their repair runs the earlier engine, which rebuilds the document. API v3 repairs with the patch engine the web tool uses (targeted edits, checked by the official validators). No v2 switch-off without at least six months notice.
| Endpoint | Does | Key |
|---|---|---|
| Validation | ||
| POST /v1/validate | Validate an e-invoice | any key |
| POST /v1/validate/batch | Validate multiple invoices | Team |
| POST /v2/validate | Validate an invoice (v2, fixability-enriched) | any key |
| Fixer | ||
| POST /v1/fixer/categorize | Categorize validation errors | any key |
| POST /v1/fixer/fix | Auto-fix invoice errors | any key |
| POST /v1/fixer/fix-with-input | Apply user-provided input fixes | any key |
| GET /v1/fixer/usage | Get fix quota usage | any key |
| GET /v1/fixer/download | Download fixed or original invoice XML | any key |
| Evidence Packs | ||
| POST /v1/evidence-pack | Generate Evidence Pack | Team |
| GET /v1/evidence-packs | List Evidence Packs | any key |
| GET /v1/verify/{id} | Verify an Evidence Pack | no key |
| Conversion | ||
| POST /v1/convert | Convert invoice format | Team |
| Countries | ||
| GET /v1/countries | List all supported countries | any key |
| GET /v1/countries/{code} | Get country details | any key |
| GET /v1/rules/{country} | Get validation rules for a country | any key |
| Regulatory Intelligence | ||
| GET /v1/deadlines | Get compliance deadlines | any key |
| GET /v1/requirements | Get trade lane requirements | any key |
| POST /v1/compliance-score | Calculate compliance readiness score | any key |
| GET /v1/changes | Get regulatory changes | any key |
| Reference Data | ||
| GET /v1/errors | List validation error codes | no key |
| GET /v1/errors/{ruleId} | Get error code details | no key |
| GET /v1/facts/search | Search compliance facts | no key |
| GET /v1/facts/{country} | Get country compliance facts | no key |
| Account | ||
| GET /v1/usage | Current usage of the calling key | any key |
| Remediation | ||
| POST /v2/validate-and-fix | Validate, surgically fix, re-validate — one call | any key |
no key — public. any key — Free or Team. Team — a Free key receives 403 INSUFFICIENT_TIER. https://api.invoicenavigator.eu/api is an alias of the base URL. Download openapi.json or the Postman collection.
POST /v2/validate-and-fix
Validates the XML, patches what is structural, re-validates the patched file against the official validators, and optionally signs an evidence pack. Counts as 2 requests against the monthly quota.
POST /v2/validate-and-fix
Authorization: Bearer sk_live_…
Content-Type: application/json
{
"xml": "<Invoice xmlns=\"urn:oasis:names:specification:ubl:schema:xsd:Invoice-2\">…</Invoice>",
"fileName": "INV-2026-0847.xml",
"autoFix": true,
"generate_evidence_pack": false
}| Body field | Type | Meaning |
|---|---|---|
| xml | string | The invoice XML (UBL or CII). Required. At most 10 MB. |
| fileName | string | Kept in the evidence pack and the flow record. |
| autoFix | boolean | Default true. false validates only. |
| remediation_policy | "safe" | "none" | Same switch, older name. none validates only. |
| generate_evidence_pack | boolean | Inline a signed evidence pack in data.evidencePack. |
| data.* | Type | Meaning |
|---|---|---|
| validationRef | string | Reference of this validation; also in meta. |
| originalValid | boolean | The submitted XML already passed. |
| fixedValid | boolean | The patched XML passes re-validation. Present when patching ran. |
| fixesApplied | integer | Number of structural edits. |
| fixedXml | string | The patched file. Present only when it differs from what you sent. |
| remainingIssues[] | object | code, severity (error · warning · info), title, message. |
| fixSummary | object | null | totalIssues, autoFixable, needsInput, blocked, unknown, canAutoFixAll. |
| metadata | object | Invoice number, issue date, currency, seller, buyer, total — as read from the file. |
| flowId | string | Identifier for follow-up calls. Absent on sk_test_ keys. |
| engine | string | orchestrator, safe-fixer or hybrid. |
| evidencePack | object | The signed pack, when requested: id, data, proof (algorithm, keyId, signature, signedAt, publicKeyUrl), verification URL. |
| _links | object | self; fixWithInput when needsInput > 0 and a flowId exists; evidencePack. |
Every response has the same shape
{
"success": true,
"data": { … },
"meta": {
"validationRef": "VAL-…",
"processingTimeMs": 1234,
"testMode": true // sk_test_ keys only
}
}{
"success": false,
"error": {
"code": "QUOTA_EXCEEDED",
"message": "Monthly quota exceeded. Upgrade your plan for more validations.",
"details": {
"used": 100,
"limit": 100,
"tier": "free",
"upgradeUrl": "/checkout/start?tier=pro"
}
}
}Test success first. error.details is optional and endpoint-specific; on QUOTA_EXCEEDED it carries the counter and the checkout URL.
What a non-2xx means
| Status | Code | When | Retry |
|---|---|---|---|
| 400 | INVALID_JSON | The body is not valid JSON. | no |
| 400 | MISSING_XML | The "xml" field is missing. | no |
| 400 | INVALID_XML | The "xml" field is not a string. | no |
| 400 | XML_TOO_LARGE | The XML is larger than 10 MB. | no |
| 401 | UNAUTHORIZED | No Bearer header, or the key is unknown. | no |
| 401 | KEY_EXPIRED | An instant test key past its hour. | no |
| 402 | QUOTA_EXCEEDED | Monthly quota used up, or the 10 instant-key requests. details.upgradeUrl points to the Team checkout. | no |
| 403 | KEY_INACTIVE | The key was revoked. | no |
| 403 | INSUFFICIENT_TIER | A Team-only endpoint called with a Free key. | no |
| 429 | RATE_LIMITED | Too many requests in the sliding hour. Retry-After is set. | after Retry-After |
| 500 | INTERNAL_ERROR | The engine failed. X-Request-Id identifies the call. | with backoff |
| 503 | SERVICE_UNAVAILABLE | API authentication is not configured on the server. | with backoff |
Validation findings are never HTTP errors: an invoice that fails its rules still returns 200 with success: true and the codes in data. Each code has a page under /errors.
| Header | On | Meaning |
|---|---|---|
| X-Request-Id | every response | Identifier of this call. Log it; quote it when you write to us. |
| X-Processing-Time-Ms | every response | Server time spent on the call, in milliseconds. |
| X-RateLimit-Limit | every authenticated response | Requests allowed per sliding hour for this key. |
| X-RateLimit-Remaining | every authenticated response | Requests left in the current hour. |
| X-RateLimit-Reset | every authenticated response | Unix seconds at which the window resets. |
| Retry-After | 429 only | Seconds to wait before the next attempt. |
| X-Test-Mode | sk_test_ keys only | Set to "true"; the body carries meta.testMode as well. |
| X-Usage-Used | metered live responses | Requests counted this month, after this call. |
| X-Usage-Included | metered live responses | Requests included in the plan for the month. |
| X-Usage-Overage | metered live responses | Requests beyond the included amount (0 while quotas are hard caps). |
| X-Usage-Period-End | metered live responses | Date the month counter resets. |
| Key | Requests / hour | Requests / month | Then |
|---|---|---|---|
| Free · sk_live_ | 60 | 100 | 402 until the month resets, or Team. |
| Team · sk_live_ | 100 | 5,000 | 402 until the month resets. |
| Account test key · sk_test_ | 100 | not metered | 429 with Retry-After. |
| Instant test key · sk_test_ | 100 | 10 in total | 402; the key expires after one hour. |
Hourly limits are a sliding window per key. The month counter is what GET /v1/usage returns and what the dashboard shows; reading it costs nothing. POST /v2/validate-and-fix counts as 2.