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.

Endpoints

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.

EndpointDoesKey
Validation
POST /v1/validateValidate an e-invoiceany key
POST /v1/validate/batchValidate multiple invoicesTeam
POST /v2/validateValidate an invoice (v2, fixability-enriched)any key
Fixer
POST /v1/fixer/categorizeCategorize validation errorsany key
POST /v1/fixer/fixAuto-fix invoice errorsany key
POST /v1/fixer/fix-with-inputApply user-provided input fixesany key
GET /v1/fixer/usageGet fix quota usageany key
GET /v1/fixer/downloadDownload fixed or original invoice XMLany key
Evidence Packs
POST /v1/evidence-packGenerate Evidence PackTeam
GET /v1/evidence-packsList Evidence Packsany key
GET /v1/verify/{id}Verify an Evidence Packno key
Conversion
POST /v1/convertConvert invoice formatTeam
Countries
GET /v1/countriesList all supported countriesany key
GET /v1/countries/{code}Get country detailsany key
GET /v1/rules/{country}Get validation rules for a countryany key
Regulatory Intelligence
GET /v1/deadlinesGet compliance deadlinesany key
GET /v1/requirementsGet trade lane requirementsany key
POST /v1/compliance-scoreCalculate compliance readiness scoreany key
GET /v1/changesGet regulatory changesany key
Reference Data
GET /v1/errorsList validation error codesno key
GET /v1/errors/{ruleId}Get error code detailsno key
GET /v1/facts/searchSearch compliance factsno key
GET /v1/facts/{country}Get country compliance factsno key
Account
GET /v1/usageCurrent usage of the calling keyany key
Remediation
POST /v2/validate-and-fixValidate, surgically fix, re-validate — one callany 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.

The composite call

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.

Request
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 fieldTypeMeaning
xmlstringThe invoice XML (UBL or CII). Required. At most 10 MB.
fileNamestringKept in the evidence pack and the flow record.
autoFixbooleanDefault true. false validates only.
remediation_policy"safe" | "none"Same switch, older name. none validates only.
generate_evidence_packbooleanInline a signed evidence pack in data.evidencePack.
data.*TypeMeaning
validationRefstringReference of this validation; also in meta.
originalValidbooleanThe submitted XML already passed.
fixedValidbooleanThe patched XML passes re-validation. Present when patching ran.
fixesAppliedintegerNumber of structural edits.
fixedXmlstringThe patched file. Present only when it differs from what you sent.
remainingIssues[]objectcode, severity (error · warning · info), title, message.
fixSummaryobject | nulltotalIssues, autoFixable, needsInput, blocked, unknown, canAutoFixAll.
metadataobjectInvoice number, issue date, currency, seller, buyer, total — as read from the file.
flowIdstringIdentifier for follow-up calls. Absent on sk_test_ keys.
enginestringorchestrator, safe-fixer or hybrid.
evidencePackobjectThe signed pack, when requested: id, data, proof (algorithm, keyId, signature, signedAt, publicKeyUrl), verification URL.
_linksobjectself; fixWithInput when needsInput > 0 and a flowId exists; evidencePack.
Envelope

Every response has the same shape

Success
{
  "success": true,
  "data": { … },
  "meta": {
    "validationRef": "VAL-…",
    "processingTimeMs": 1234,
    "testMode": true            // sk_test_ keys only
  }
}
Failure
{
  "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.

Error codes

What a non-2xx means

StatusCodeWhenRetry
400INVALID_JSONThe body is not valid JSON.no
400MISSING_XMLThe "xml" field is missing.no
400INVALID_XMLThe "xml" field is not a string.no
400XML_TOO_LARGEThe XML is larger than 10 MB.no
401UNAUTHORIZEDNo Bearer header, or the key is unknown.no
401KEY_EXPIREDAn instant test key past its hour.no
402QUOTA_EXCEEDEDMonthly quota used up, or the 10 instant-key requests. details.upgradeUrl points to the Team checkout.no
403KEY_INACTIVEThe key was revoked.no
403INSUFFICIENT_TIERA Team-only endpoint called with a Free key.no
429RATE_LIMITEDToo many requests in the sliding hour. Retry-After is set.after Retry-After
500INTERNAL_ERRORThe engine failed. X-Request-Id identifies the call.with backoff
503SERVICE_UNAVAILABLEAPI 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.

Response headers
HeaderOnMeaning
X-Request-Idevery responseIdentifier of this call. Log it; quote it when you write to us.
X-Processing-Time-Msevery responseServer time spent on the call, in milliseconds.
X-RateLimit-Limitevery authenticated responseRequests allowed per sliding hour for this key.
X-RateLimit-Remainingevery authenticated responseRequests left in the current hour.
X-RateLimit-Resetevery authenticated responseUnix seconds at which the window resets.
Retry-After429 onlySeconds to wait before the next attempt.
X-Test-Modesk_test_ keys onlySet to "true"; the body carries meta.testMode as well.
X-Usage-Usedmetered live responsesRequests counted this month, after this call.
X-Usage-Includedmetered live responsesRequests included in the plan for the month.
X-Usage-Overagemetered live responsesRequests beyond the included amount (0 while quotas are hard caps).
X-Usage-Period-Endmetered live responsesDate the month counter resets.
Rate limits and quotas
KeyRequests / hourRequests / monthThen
Free · sk_live_60100402 until the month resets, or Team.
Team · sk_live_1005,000402 until the month resets.
Account test key · sk_test_100not metered429 with Retry-After.
Instant test key · sk_test_10010 in total402; 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.