E-invoice validation API
POST an XML invoice, receive a structured JSON validation report. Supports XRechnung, Factur-X, ZUGFeRD, Peppol BIS 3.0, UBL 2.1, and UN/CEFACT CII. No data is stored or logged.
Authentication
All requests require an API key passed in the X-Api-Key header. Retrieve your key from the account dashboard after subscribing.
X-Api-Key: bi_live_xxxxxxxxxxxxxxxxxxxxxxxx
Keep your API key secret — treat it like a password. Do not expose it in client-side code or public repositories.
Endpoint
https://baseinvoice.eu/api/v1/validateSingle endpoint. Accepts one invoice per request. Returns immediately — no polling required.
Request
Option A — multipart/form-data
Send the XML file as a file field. Recommended for most integrations.
POST /api/v1/validate Content-Type: multipart/form-data X-Api-Key: bi_live_... file=<your-invoice.xml>
Option B — raw XML body
Send the XML directly as the request body.
POST /api/v1/validate Content-Type: application/xml X-Api-Key: bi_live_... <?xml version="1.0" encoding="UTF-8"?> <Invoice xmlns="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2"> ... </Invoice>
PDF files are not accepted. For Factur-X or ZUGFeRD hybrid PDFs, extract the embedded XML first and submit that.
Response
Returns application/json with HTTP 200 for all processed invoices — including invalid ones. HTTP errors only occur for authentication failures or malformed requests.
{
"valid": false,
"format": "xrechnung-ubl",
"profile": "urn:cen.eu:en16931:2017#compliant#urn:xoev-de:kosit:standard:xrechnung_3.0",
"errorCount": 2,
"warningCount": 1,
"issues": [
{
"code": "BR-02",
"severity": "error",
"field": "cbc:ID",
"message": "An Invoice shall have a Specification identifier (BT-24)."
},
{
"code": "BR-DE-1",
"severity": "error",
"field": "cbc:CustomizationID",
"message": "Das Element 'Specification identifier' muss angegeben werden."
},
{
"code": "BR-CO-15",
"severity": "warning",
"field": "cac:TaxTotal",
"message": "Tax amount may not match sum of tax category amounts."
}
]
}Response fields
| valid | boolean | true if errorCount is 0 |
| format | string | Detected format: xrechnung-ubl, xrechnung-cii, facturx-cii, zugferd-cii, peppol-bis3-ubl, ubl, cii, unknown |
| profile | string | null | Detected customization ID / profile URN |
| errorCount | number | Number of rule violations (must-fix) |
| warningCount | number | Number of warnings (should-fix) |
| issues[].code | string | EN 16931 or format-specific rule code (e.g. BR-02, BR-DE-1) |
| issues[].severity | string | "error" or "warning" |
| issues[].field | string | null | XPath field name or element where the issue was found |
| issues[].message | string | Plain-language description and fix guidance |
Error responses
| 401 | Missing or invalid X-Api-Key header |
| 400 | Empty body or missing file field |
| 415 | PDF submitted — extract XML first |
| 503 | API not configured (contact support) |
All error responses include a JSON body: { "error": "..." }
Code examples
cURL
curl -X POST https://baseinvoice.eu/api/v1/validate \ -H "X-Api-Key: bi_live_..." \ -F "file=@invoice.xml"
Python
import requests
with open("invoice.xml", "rb") as f:
response = requests.post(
"https://baseinvoice.eu/api/v1/validate",
headers={"X-Api-Key": "bi_live_..."},
files={"file": f},
)
result = response.json()
if result["valid"]:
print("Invoice is valid")
else:
for issue in result["issues"]:
print(f"[{issue['severity'].upper()}] {issue['code']}: {issue['message']}")JavaScript / Node.js
import { readFileSync } from "fs";
const xml = readFileSync("invoice.xml");
const form = new FormData();
form.append("file", new Blob([xml], { type: "application/xml" }), "invoice.xml");
const res = await fetch("https://baseinvoice.eu/api/v1/validate", {
method: "POST",
headers: { "X-Api-Key": "bi_live_..." },
body: form,
});
const result = await res.json();
console.log(result.valid, result.issues);Rate limits & quotas
| Included calls | 1,000 / month |
| Overage | €0.05 per additional call |
| Max request size | 5 MB |
| Timeout | 30 seconds |
| Concurrency | No hard limit |
| Counter reset | Monthly on billing date |
Ready to integrate?
7-day free trial — card required, no charge until trial ends.