Back to API Docs

Validate Invoice

POST/v1/validate

Validate an e-invoice against EN16931, Peppol BIS, and country-specific rules.

Request

Headers

HeaderRequiredDescription
AuthorizationYesBearer token with API key
Content-TypeYesapplication/json

Request Body

Send a JSON object with the invoice XML content:

{
  "xml": "<Invoice xmlns=\"urn:oasis:names:specification:ubl...\">....</Invoice>",
  "fileName": "invoice-2025-001.xml"
}
FieldTypeRequiredDescription
xmlstringYesThe invoice XML content as a string
fileNamestringNoOriginal filename (for logging)
options.ruleset_versionsobjectNoPin specific ruleset versions

Query Parameters

ParameterTypeDescription
profilestringForce specific profile: peppol-bis-3.0, xrechnung, etc.
countrystringForce country rules: DE, FR, etc.

Response

Success (200)

{
  "success": true,
  "data": {
    "validationRef": "val_abc123xyz",
    "isValid": true,
    "format": "ubl",
    "formatVersion": "2.1",
    "rulesetsApplied": [
      { "id": "en16931", "version": "1.3.11", "pinned": false },
      { "id": "peppol-bis", "version": "3.0.17", "pinned": false }
    ],
    "errors": [],
    "warnings": [
      {
        "code": "BR-CL-01",
        "message": "Payment means code should use UNCL4461",
        "location": "/Invoice/PaymentMeans/PaymentMeansCode"
      }
    ],
    "metadata": {
      "invoiceNumber": "INV-2025-001234",
      "issueDate": "2025-12-20",
      "currency": "EUR",
      "sellerName": "Acme GmbH",
      "sellerCountry": "DE",
      "buyerName": "Example BV",
      "buyerCountry": "NL",
      "totalAmount": "12450.00"
    }
  },
  "meta": {
    "validationRef": "val_abc123xyz",
    "processingTimeMs": 247
  }
}

Validation Failed (200)

{
  "success": true,
  "data": {
    "validationRef": "val_def456uvw",
    "isValid": false,
    "format": "ubl",
    "formatVersion": "2.1",
    "rulesetsApplied": [
      { "id": "en16931", "version": "1.3.11", "pinned": false },
      { "id": "de-xrechnung", "version": "3.0.2", "pinned": false }
    ],
    "errors": [
      {
        "code": "BR-02",
        "message": "An Invoice shall have an Invoice number",
        "location": "/Invoice",
        "suggestion": "Add the cbc:ID element to your invoice"
      },
      {
        "code": "BR-DE-01",
        "message": "Leitweg-ID is required for German B2G invoices",
        "location": "/Invoice/AccountingCustomerParty",
        "suggestion": "Add BuyerReference with Leitweg-ID"
      }
    ],
    "warnings": [],
    "metadata": {
      "issueDate": "2025-12-20",
      "currency": "EUR",
      "sellerCountry": "DE"
    }
  },
  "meta": {
    "validationRef": "val_def456uvw",
    "processingTimeMs": 312
  }
}

Error Responses

StatusCodeDescription
400invalid_xmlRequest body is not valid XML
401unauthorizedInvalid or missing API key
402quota_exceededAPI quota exceeded
413file_too_largeInvoice exceeds 5MB limit
429rate_limitedToo many requests

Code Examples

cURL

curl -X POST https://api.invoicenavigator.eu/v1/validate \
  -H "Authorization: Bearer sk_live_abc123..." \
  -H "Content-Type: application/json" \
  -d '{"xml": "'"$(cat invoice.xml)"'"}'

Node.js

const fs = require('fs');

const invoiceXml = fs.readFileSync('invoice.xml', 'utf-8');

const response = await fetch('https://api.invoicenavigator.eu/v1/validate', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer sk_live_abc123...',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ xml: invoiceXml }),
});

const result = await response.json();
const { data } = result;
console.log(data.isValid ? 'Valid!' : 'Invalid:', data.errors);

Python

import requests

with open('invoice.xml', 'r') as f:
    invoice_xml = f.read()

response = requests.post(
    'https://api.invoicenavigator.eu/v1/validate',
    headers={
        'Authorization': 'Bearer sk_live_abc123...',
        'Content-Type': 'application/json',
    },
    json={'xml': invoice_xml},
)

result = response.json()
data = result['data']
print('Valid!' if data['isValid'] else f"Invalid: {data['errors']}")

PHP

<?php
$invoiceXml = file_get_contents('invoice.xml');

$ch = curl_init('https://api.invoicenavigator.eu/v1/validate');
curl_setopt_array($ch, [
    CURLOPT_POST => true,
    CURLOPT_POSTFIELDS => json_encode(['xml' => $invoiceXml]),
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer sk_live_abc123...',
        'Content-Type: application/json',
    ],
    CURLOPT_RETURNTRANSFER => true,
]);

$response = curl_exec($ch);
$result = json_decode($response, true);
$data = $result['data'];

echo $data['isValid'] ? 'Valid!' : 'Invalid: ' . print_r($data['errors'], true);
?>