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
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.