How to Add E-Invoice Compliance to Your Pipeline
This guide walks you through integrating validation, remediation, revalidation, and evidence pack generation into your production pipeline using the Invoice Navigator SDK.
Overview
A compliant e-invoicing pipeline needs four capabilities: validation against 1,300+ rules (EN 16931, Peppol, country-specific), remediation of structural issues without altering financial data, revalidation via KoSIT to confirm fixes, and evidence pack generation for audit-ready documentation.
The Invoice Navigator API handles all four in a single call. This guide shows you how to wire it into your existing pipeline with code examples in JavaScript/TypeScript and Python.
Architecture
The integration sits between your ERP invoice export and your delivery channel (Peppol Access Point, email, or archive). Here is the data flow:
Source
Your ERP
UBL / CII XML
Engine
Invoice Navigator API
Validate + Remediate + Evidence
Delivery
Peppol Access Point
Compliant invoice
Get Your API Key
Create an account and generate your API key from the dashboard. Every account includes a sandbox environment for testing.
- Sandbox keys start with
sk_test_— free, unlimited validations - Production keys start with
sk_live_— metered, full engine access
Validate an Invoice
Send your invoice XML to the validation endpoint. The engine checks against EN 16931 base rules, Peppol BIS 3.0, and all applicable country-specific rule sets automatically.
const response = await fetch('https://api.invoicenavigator.eu/api/v1/validate', {
method: 'POST',
headers: {
'Authorization': 'Bearer sk_test_...',
'Content-Type': 'application/json'
},
body: JSON.stringify({
xml: invoiceXml,
fileName: 'invoice-001.xml'
})
});
const { data } = await response.json();
console.log(data.isValid); // true | false
console.log(data.errors.length); // number of validation errors
console.log(data.warnings.length); // number of warnings
// Each error includes rule ID, severity, XPath, and human-readable message
for (const error of data.errors) {
console.log(`[${error.code}] ${error.message}`);
}import requests
response = requests.post(
"https://api.invoicenavigator.eu/api/v1/validate",
headers={
"Authorization": "Bearer sk_test_...",
"Content-Type": "application/json"
},
json={"xml": invoice_xml, "fileName": "invoice-001.xml"}
)
data = response.json()["data"]
print(f"Valid: {data['isValid']}")
print(f"Errors: {len(data['errors'])}")
for error in data["errors"]:
print(f"[{error['code']}] {error['message']}")Remediate Issues
Use the validate-and-fix endpoint to automatically remediate structural issues. The engine classifies every fix into one of three categories:
- auto— Structural fixes that do not alter commercial meaning (whitespace, namespaces, code lists)
- input— Missing business data that requires your input (e.g., missing buyer reference)
- blocked— Financial fields that are never modified (amounts, VAT totals, IBANs)
const response = await fetch('https://api.invoicenavigator.eu/api/v2/validate-and-fix', {
method: 'POST',
headers: {
'Authorization': 'Bearer sk_test_...',
'Content-Type': 'application/json'
},
body: JSON.stringify({
xml: invoiceXml,
fileName: 'invoice-001.xml',
autoFix: true
})
});
const { data } = await response.json();
console.log(data.originalValid); // false
console.log(data.fixedValid); // true (after remediation)
console.log(data.fixesApplied); // number of auto-fixes applied
// Check fix classification
console.log(data.fixSummary);
// {
// totalIssues: 3,
// autoFixable: 2,
// needsInput: 1,
// blocked: 0,
// canAutoFixAll: false
// }
// Handle issues that need user input
for (const issue of data.remainingIssues) {
if (issue.fixType === 'input') {
console.log(`Needs input: ${issue.field} — ${issue.message}`);
}
}import requests
response = requests.post(
"https://api.invoicenavigator.eu/api/v2/validate-and-fix",
headers={
"Authorization": "Bearer sk_test_...",
"Content-Type": "application/json"
},
json={
"xml": invoice_xml,
"fileName": "invoice-001.xml",
"autoFix": True
}
)
data = response.json()["data"]
print(f"Original valid: {data['originalValid']}")
print(f"Fixed valid: {data['fixedValid']}")
print(f"Fixes applied: {data['fixesApplied']}")
# Handle remaining issues
for issue in data["remainingIssues"]:
if issue["fixType"] == "input":
print(f"Needs input: {issue['field']} — {issue['message']}")Handle Evidence Packs
Every validation generates an evidence pack containing the original invoice, validation findings, remediation diffs, blocked field confirmations, and revalidation proof. Download as a ZIP for your audit archive.
import { writeFileSync } from 'fs';
// Generate evidence pack from a validation reference
const response = await fetch('https://api.invoicenavigator.eu/api/v1/evidence-pack', {
method: 'POST',
headers: {
'Authorization': 'Bearer sk_test_...',
'Content-Type': 'application/json'
},
body: JSON.stringify({
validationRef: 'val_8x7kM2nP9q',
format: 'pdf'
})
});
// Save the PDF
const pdfBuffer = await response.arrayBuffer();
writeFileSync('evidence-pack.pdf', Buffer.from(pdfBuffer));
// Verify authenticity later
const verifyResponse = await fetch(
'https://api.invoicenavigator.eu/api/v1/verify/EP-ABC123',
);
const verification = await verifyResponse.json();
console.log(verification.data.verified); // trueimport requests
# Generate evidence pack
response = requests.post(
"https://api.invoicenavigator.eu/api/v1/evidence-pack",
headers={
"Authorization": "Bearer sk_test_...",
"Content-Type": "application/json"
},
json={
"validationRef": "val_8x7kM2nP9q",
"format": "pdf"
}
)
# Save the PDF
with open("evidence-pack.pdf", "wb") as f:
f.write(response.content)
# Verify authenticity later
verification = requests.get(
"https://api.invoicenavigator.eu/api/v1/verify/EP-ABC123"
).json()
print(f"Verified: {verification['data']['verified']}")Go to Production
Before switching from sandbox to production, verify the following checklist:
Frequently Asked Questions
How long does a typical integration take?
Most teams complete the integration in under one sprint. The SDK handles authentication, retries, and error parsing, so you only need to wire up the validate-and-fix endpoint between your ERP export and delivery step.
Can I test without affecting production data?
Yes. Every account includes a sandbox environment with test API keys (sk_test_...). Sandbox validations do not count toward your quota and use the same engine as production.
Which invoice formats are supported?
The API validates UBL 2.1, CII (Cross Industry Invoice), Peppol BIS 3.0, XRechnung, Factur-X/ZUGFeRD, and FatturaPA. Format detection is automatic — just send the XML.
What happens if the API is unavailable?
The SDK includes automatic retries with exponential backoff. For critical pipelines, we recommend a queue-based architecture where invoices are retried until validated. Evidence packs are stored for 90 days.
Do I need separate API keys for each environment?
Yes. Use sk_test_ keys for development and staging, and sk_live_ keys for production. Each environment has its own quota tracking and rate limits.
Ready to integrate?
Start with 100 free validations. No credit card required. Full engine access from day one.
Get Started Free