@invoicenavigator/sdk
v0.1.1
Published
Official TypeScript SDK for Invoice Navigator — EU e-invoicing compliance API. Validate, remediate, and certify invoices against EN 16931, Peppol BIS 3.0, XRechnung, and ZUGFeRD.
Maintainers
Readme
@invoicenavigator/sdk
Official TypeScript/JavaScript SDK for Invoice Navigator — the compliance engine for EU e-invoicing pipelines.
Validate, auto-remediate, and certify invoices against EN 16931, Peppol BIS 3.0, XRechnung, ZUGFeRD/Factur-X, and country-specific CIUS rules.
Install
npm install @invoicenavigator/sdkQuick Start
import { InvoiceNavigator } from '@invoicenavigator/sdk'
const client = new InvoiceNavigator({ apiKey: 'sk_live_...' })
// 1. Validate
const result = await client.validate({ xml: invoiceXml })
if (result.isValid) {
console.log('Already compliant')
} else {
// 2. Fix — auto-remediate every fixable error
const fix = await client.fix({
xml: invoiceXml,
error_codes: result.errors.map(e => e.code),
})
console.log(`Fixed ${fix.stats.totalFixesApplied} issues`)
console.log(`Compliant: ${fix.is_compliant}`)
// 3. Use the fixed XML downstream
if (fix.is_compliant) {
sendToPeppol(fix.fixed_xml)
}
}What It Does
| Method | Description |
|--------|-------------|
| Validation | |
| validate(options) | Validate against EN 16931 + Peppol/XRechnung/ZUGFeRD rules |
| validateBatch(invoices) | Batch validate up to 100 invoices |
| Remediation | |
| fix(options) | Auto-remediate structural compliance errors |
| fixWithInput(options) | Resolve errors that need user-provided values |
| validateAndFix(options) | Validate + auto-remediate in a single call |
| categorize(options) | Preview which errors are auto-fixable, need input, or blocked |
| fixerUsage() | Check remediation quota and usage stats |
| fixFlow(id) | Track status of a multi-step remediation flow |
| Evidence | |
| evidencePack(options) | Generate signed compliance evidence (PDF or JSON) |
| verify(id) | Verify an evidence pack's cryptographic signature |
| Conversion | |
| convert(options) | Convert between UBL and CII formats |
| Intelligence | |
| countries() | List supported countries and their mandate status |
| country(code) | Get country-specific compliance details |
| rules(country) | Get country-specific validation rules |
| deadlines(options) | Get upcoming compliance deadlines |
| requirements(options) | Get requirements for a seller/buyer trade lane |
| complianceScore(options) | Calculate compliance readiness score |
| changes(options) | Get regulatory changes since a date |
| errors(options) | List all validation error definitions |
| error(ruleId) | Get details for a specific error code |
| searchFacts(options) | Search compliance facts across countries |
| facts(country) | Get all facts for a country |
Test Mode
Use sk_test_ keys for development. Same engine, same rules — no quota consumed.
const client = new InvoiceNavigator({
apiKey: 'sk_test_...' // 100 requests/hour, no charge
})Remediation
Invoice Navigator doesn't just find errors — it fixes them.
Validate + Fix (one call)
The fastest path. Validates and auto-remediates in a single request.
const result = await client.validateAndFix({
xml: invoiceXml,
generate_evidence_pack: true,
})
if (result.fixedValid) {
console.log(`Fixed ${result.fixesApplied} issues — now compliant`)
// result.fixedXml is the remediated XML
// result.evidencePackUrl has the signed proof
}Fix specific errors
When you already have validation results and want granular control:
const validation = await client.validate({ xml: invoiceXml })
if (!validation.isValid) {
const fix = await client.fix({
xml: invoiceXml,
error_codes: validation.errors.map(e => e.code),
})
console.log(`Applied: ${fix.stats.totalFixesApplied}`)
console.log(`Remaining: ${fix.remaining_errors.length}`)
console.log(`Engine: ${fix.engine}`)
// fix.flow_id tracks this remediation session
}Input-required workflow
Some errors can't be auto-fixed — they need values only the user knows (a missing VAT number, a wrong bank account). This is what makes Invoice Navigator different from every other validator: instead of just listing errors, we tell you exactly which fields to collect and apply them surgically.
// 1. Categorize errors to see what's fixable
const cat = await client.categorize({
error_codes: validation.errors.map(e => e.code),
})
console.log(`Auto-fixable: ${cat.stats.auto}`) // e.g. 5
console.log(`Needs input: ${cat.stats.input}`) // e.g. 2
console.log(`Blocked: ${cat.stats.blocked}`) // e.g. 0
// 2. Auto-fix the safe ones first
const fix = await client.fix({
xml: invoiceXml,
error_codes: validation.errors.map(e => e.code),
})
// 3. Prompt the user for input-required fields, then apply
if (!fix.is_compliant) {
const result = await client.fixWithInput({
xml: fix.fixed_xml,
flow_id: fix.flow_id,
values: {
'BT-48': 'DE123456789', // buyer VAT number
'BT-49': 'VAT', // buyer tax registration scheme
},
skipped: ['BR-CO-26'], // accept this error as-is
})
console.log(`Compliant: ${result.is_compliant}`)
}Track a remediation flow
Monitor multi-step remediation progress:
const flow = await client.fixFlow(fix.flow_id)
console.log(`Status: ${flow.status}`)
console.log(`Auto-fixed: ${flow.auto_fixes_applied}`)
console.log(`User inputs: ${flow.user_inputs_provided}`)
console.log(`Final compliant: ${flow.final_compliant}`)Usage tracking
Monitor remediation quota consumption:
const usage = await client.fixerUsage()
console.log(`Flows: ${usage.usage.flows_used}/${usage.usage.flows_limit}`)
console.log(`Resets: ${usage.resets_at}`)Validation
const result = await client.validate({
xml: '<Invoice>...</Invoice>',
fileName: 'invoice-001.xml', // optional
webhookUrl: 'https://...', // optional — receive async notification
})
result.validationRef // "val_abc123" — reference for evidence packs
result.isValid // boolean
result.format // "XRechnung-UBL" | "Factur-X" | ...
result.formatVersion // "3.0.1"
result.errors // ValidationError[]
result.warnings // ValidationWarning[]
result.metadata // extracted invoice metadataBatch Validation
Validate multiple invoices in one request. Requires Pro tier or higher.
const batch = await client.validateBatch([
{ xml: invoice1Xml, id: 'inv-001' },
{ xml: invoice2Xml, id: 'inv-002' },
])
console.log(`${batch.validCount}/${batch.totalCount} valid`)Evidence Packs
Generate cryptographically signed compliance evidence.
// PDF format
const pdf = await client.evidencePack({
validationRef: 'val_abc123',
format: 'pdf',
companyName: 'ACME GmbH',
})
import { writeFileSync } from 'fs'
writeFileSync('evidence.pdf', Buffer.from(pdf.pdf))
// JSON format
const json = await client.evidencePack({
validationRef: 'val_abc123',
format: 'json',
})
console.log(`Verify at: ${json.verifyUrl}`)
// Verify an Evidence Pack (public endpoint, no auth required)
const verification = await client.verify('EP-ABC123-DEF456')
console.log(`Verified: ${verification.verified}`)Format Conversion
Convert between UBL and CII invoice formats. Requires Pro tier or higher.
const result = await client.convert({
source: Buffer.from(xml).toString('base64'),
sourceFormat: 'auto',
targetFormat: 'xrechnung-ubl',
})
const convertedXml = Buffer.from(result.result, 'base64').toString()Supported formats: ubl-2.1, xrechnung-ubl, xrechnung-cii, peppol-bis, factur-x-minimum, factur-x-basic, factur-x-extended, cii.
Regulatory Intelligence
// Countries and mandate status
const countries = await client.countries()
const germany = await client.country('DE')
// Upcoming deadlines
const deadlines = await client.deadlines({ country: 'DE', months: 6 })
// Trade lane requirements
const reqs = await client.requirements({ from: 'DE', to: 'FR', type: 'b2b' })
// Regulatory changes since a date
const changes = await client.changes({ since: '2025-01-01', countries: ['DE', 'FR'] })
// Compliance score
const score = await client.complianceScore({
businessCountry: 'DE',
customerCountries: ['FR', 'BE', 'NL'],
})Error Handling
import { InvoiceNavigator, InvoiceNavigatorError } from '@invoicenavigator/sdk'
try {
const result = await client.validate({ xml })
} catch (error) {
if (error instanceof InvoiceNavigatorError) {
console.log(error.code) // 'RATE_LIMIT_EXCEEDED'
console.log(error.statusCode) // 429
console.log(error.message) // 'Hourly rate limit exceeded'
}
}| Code | Status | Meaning |
|------|--------|---------|
| VALIDATION_ERROR | 400 | Invalid request parameters |
| UNAUTHORIZED | 401 | Missing or invalid API key |
| FORBIDDEN | 403 | Insufficient tier for this endpoint |
| RATE_LIMIT_EXCEEDED | 429 | Rate limit hit |
| TIMEOUT | 408 | Request exceeded configured timeout |
| NETWORK_ERROR | 0 | Network failure |
Rate Limits
Available after each request via client.rateLimit:
await client.validate({ xml })
console.log(client.rateLimit)
// { limit: 100, remaining: 97, reset: 1709312400 }Webhooks
Verify and parse webhook payloads:
import {
verifyWebhookSignature,
parseWebhookPayload,
isValidationCompletedEvent,
} from '@invoicenavigator/sdk'
const isValid = await verifyWebhookSignature(rawBody, signature, webhookSecret)
const payload = parseWebhookPayload(body)
if (isValidationCompletedEvent(payload)) {
console.log('Validation completed:', payload.data.validationRef)
}Configuration
const client = new InvoiceNavigator({
apiKey: 'sk_live_...', // required
baseUrl: 'https://api.invoicenavigator.eu', // optional, default shown
timeout: 30000, // optional, ms
fetch: customFetchFn, // optional, for older runtimes
})Supported Standards
- EN 16931 (European e-invoicing standard)
- Peppol BIS Billing 3.0
- XRechnung 3.0 (Germany)
- ZUGFeRD 2.3 / Factur-X (Germany/France)
- Country CIUS: DE, FR, IT, NL, BE, AT, and more
Requirements
- Node.js 18+ (uses native
fetchandcrypto.subtle) - Works in modern browsers, Deno, Bun, and Cloudflare Workers
Links
License
MIT
