Developer API · Receiving side
InvoiceIn.
Every e-invoice you receive, as one JSON.
One stateless endpoint. POST whatever lands in your inbox — XRechnung, ZUGFeRD, Factur-X, Peppol BIS 3, FatturaPA, KSeF — and get back canonical EN 16931 JSON, a validation report that says what the sender must fix, a PDF you can show a human, and CSV or DATEV for the books. Processed in memory, ~10–50 ms per document.
In memory only. Nothing stored. No Peppol access point required.
Why this exists
Your customers now receive invoices as XML — XRechnung in Germany, KSeF in Poland, FatturaPA in Italy, Factur-X in France — and your code was written for PDFs. Instead of five parsers and five rule sets, you send us the file and get one JSON back, plus a list of what is wrong with it in words a bookkeeper can forward to the supplier. We never keep the document.
Live demo
Drop a real invoice you received. We parse it, validate it against the official rule sets, and show the hints — nothing is kept.
Header
Issues
Raw JSON
Five outputs. One call.
Canonical EN 16931 JSON
One shape for every syntax. Fields named by the semantic model with BT/BG numbers: seller, buyer, lines, VAT breakdown, totals, payment and IBAN, references, attachments. National extras live under extensions.
Report with fix hints
Official rule sets plus arithmetic cross-checks. Every failed rule carries a plain-language hint in English, German, French, Italian or Polish — what the sender must change and which field (BT number) it concerns.
Human-readable PDF or HTML
Same A4 layout for every syntax, labels in English, German, French, Italian or Polish. For the approver who wants to see the invoice, not the XML.
CSV and DATEV
Flat CSV per line or per document, and a DATEV Buchungsstapel (EXTF 700) for the incoming invoice — SKR03 or SKR04, your creditor account.
MCP server
Remote at /mcp or local over stdio. Claude, Cursor, n8n or your own agent reads and validates an invoice with one tool call.
What goes in, what gets checked.
Detection is automatic — send the file, we tell you what it was. Hybrid PDFs are opened and the embedded XML is extracted; the PDF itself is never written to disk.
| Format | Syntax | Container | Validation applied |
|---|---|---|---|
| XRechnung 3.0 | UBL 2.1 or CII D16B | XML | XSD · EN 16931 Schematron 1.3.17 · XRechnung 3.0.2 · arithmetic |
| EN 16931 | UBL 2.1 or CII D16B | XML | XSD · EN 16931 Schematron 1.3.17 · arithmetic |
| Peppol BIS Billing 3 | UBL 2.1 | XML | XSD · EN 16931 · Peppol BIS 3 rules · arithmetic |
| ZUGFeRD 2.x / Factur-X — EN 16931, EXTENDED, XRECHNUNG | CII D16B | PDF/A-3 hybrid or bare XML | XSD · EN 16931 Schematron 1.3.17 · arithmetic |
| ZUGFeRD 2.x / Factur-X — BASIC, BASIC WL, MINIMUM | CII D16B | PDF/A-3 hybrid or bare XML | XSD · Factur-X 1.09.2 profile rules (FX-SCH) · arithmetic (the EN 16931 core rules do not apply below the EN 16931 profile) |
| ZUGFeRD 1.0 | CII (CrossIndustryDocument 1p0) | PDF/A-3 hybrid or bare XML | Schema · arithmetic |
| FatturaPA 1.2 | FatturaPA | XML | FatturaPA 1.2.2 XSD · arithmetic (multi-body files returned as a batch) |
| KSeF FA(2) / FA(3) | FA schema | XML | FA(2) / FA(3) XSD · arithmetic |
| France — CTC-FR (seller and buyer both in FR) | UBL 2.1 or CII D16B | XML or Factur-X PDF | XSD · EN 16931 · FNFE CTC-FR 1.4.0.04 (BR-FR rules, Flux 2) · arithmetic |
| RO e-Factura (CIUS-RO) | UBL 2.1 | XML | XSD · CIUS-RO 1.0.1, which carries the EN 16931 rules inside it · arithmetic |
| UAE PINT AE (Billing, Self-Billing) | UBL 2.1 | XML | XSD · OpenPeppol PINT AE 1.0.4 (shared PINT rules + UAE rules) · free check page |
Rule versions are also listed live at GET /v1/formats. Missing a format you receive? Tell us.
Built for the teams that now have to receive these.
Receiving structured invoices stopped being optional: Germany since 1 Jan 2025, Belgium via Peppol since Jan 2026, Poland's KSeF for B2B from 1 Apr 2026, France from 1 Sep 2026. The receive side needs a parser, a validator and a way to show the thing to a human — that is the whole product.
AP & bookkeeping SaaS
Your customers forward whatever their suppliers send. One endpoint turns six syntaxes into one JSON your matching and approval flow already understands — plus a hint you can forward to the supplier when their file is wrong.
ERP & shop plugins
Dolibarr, InvoicePlane, Sylius, Shopware, Odoo — a plugin that can read incoming XRechnung and Factur-X is a feature you can ship this sprint instead of a six-month parser project. No Java, no Schematron toolchain in your build.
Agencies building SMB tooling
Small clients in DE, FR, IT, PL and Benelux are getting e-invoices and asking you what to do with them. Validate, render, export to DATEV or CSV — and hand the rejection back to the sender with the exact field to fix.
Three lines to your first parse.
Send the file as multipart field file or as the raw XML/PDF body. Authenticate with Authorization: Bearer <key> or X-Api-Key. Without a key you get the demo quota: 20 invoices per IP per day.
curl -X POST "https://invoicein-api.peculiar.systems/v1/invoice?include=validation&lang=en" \
-H "Authorization: Bearer $INVOICEIN_KEY" \
-F "[email protected]"
import { readFile } from "node:fs/promises";
const form = new FormData();
form.append("file", new Blob([await readFile("invoice.xml")]), "invoice.xml");
const res = await fetch("https://invoicein-api.peculiar.systems/v1/invoice?include=validation,datev&lang=de", {
method: "POST",
headers: { Authorization: `Bearer ${process.env.INVOICEIN_KEY}` },
body: form,
});
const data = await res.json();
if (!data.ok) throw new Error(`${data.error.code}: ${data.error.message}`);
console.log(data.invoice.totals); // { net, tax, gross, due, … }
console.log(data.validation.issues); // [{ id, severity, hint, field, who }]
import os, requests
r = requests.post(
"https://invoicein-api.peculiar.systems/v1/invoice",
params={"include": "validation,pdf", "lang": "en"},
headers={"X-Api-Key": os.environ["INVOICEIN_KEY"]},
files={"file": open("invoice.pdf", "rb")},
timeout=30,
)
data = r.json()
if not data["ok"]:
raise SystemExit(f'{data["error"]["code"]}: {data["error"]["message"]}')
print(data["source"]["format"], data["source"]["profile"])
print(data["validation"]["valid"], data["validation"]["errors"], "errors")
Example response (abbreviated)
{
"ok": true,
"source": {
"format": "xrechnung-ubl",
"syntax": "UBL",
"profile": "XRechnung 3.0",
"container": "xml"
},
"invoice": {
"document": {
"id": "RE-2026-0421",
"issue_date": "2026-08-30",
"type_code": "380",
"currency": "EUR",
"buyer_reference": "04011000-12345-03"
},
"seller": {
"name": "Nordlicht Werkstatt GmbH",
"vat_id": "DE123456789",
"electronic_address": { "value": "[email protected]", "scheme": "EM" },
"address": { "line1": "Kanalstraße 12", "city": "Kiel", "postcode": "24103", "country": "DE" }
},
"buyer": { "name": "Beispiel Bau AG", "address": { "city": "Hamburg", "country": "DE" } },
"payment": {
"means_code": "58",
"credit_transfers": [{ "iban": "DE02120300000000202051" }]
},
"totals": { "line_net": 314.86, "net": 314.86, "tax": 22.04, "gross": 336.09, "due": 336.09 },
"tax_breakdown": [{ "category": "S", "rate": 7, "taxable": 314.86, "tax": 22.04 }],
"lines": [
{ "id": "1", "quantity": 3.5, "unit": "HUR", "net_amount": 314.86,
"price": { "amount": 89.96 }, "tax": { "category": "S", "rate": 7 },
"item": { "name": "Wartung Lüftungsanlage" } }
],
"extensions": {}
},
"validation": {
"valid": false,
"errors": 1,
"warnings": 0,
"rule_sets": [
{ "id": "EN16931-UBL", "version": "EN 16931 validation artefacts 1.3.17" },
{ "id": "XRechnung-UBL", "version": "XRechnung 3.0.2 Schematron 2.6.0" }
],
"issues": [
{
"id": "BR-CO-15",
"severity": "error",
"rule_set": "EN16931-UBL",
"message": "[BR-CO-15]-Invoice total amount with VAT (BT-112) = Invoice total amount without VAT (BT-109) + Invoice total VAT amount (BT-110).",
"hint": "Invoice total with VAT (BT-112) must equal total without VAT (BT-109) plus total VAT (BT-110). 314.86 + 22.04 = 336.90, but the document says 336.09 — the sender's totals were rounded independently of the lines.",
"field": "totals.gross (BT-112)",
"who": "sender"
}
]
},
"timings_ms": { "detect": 1.2, "map": 3.8, "validate": 18.1, "total": 23.4 }
}
Endpoints
- POST /v1/invoice
- Everything in one JSON.
?include=validation,html,pdf,csv,datev&lang=en|de|fr|it|pl - POST /v1/validate
- Report only.
- POST /v1/parse
- Canonical JSON only, no validation.
- POST /v1/render.html
- Human-readable HTML.
- POST /v1/render.pdf
- Human-readable A4 PDF.
- POST /v1/export.csv
- Flat CSV.
?level=lines|documents - POST /v1/export.datev
- DATEV Buchungsstapel.
?skr=03|04&creditor_account=70000 - GET /v1/formats
- Supported inputs and rule-set versions.
- GET /v1/rules/{id}
- Explain a rule id in plain language.
?lang=de - GET /v1/countries
- Which format each country's mandate asks for, and what we validate it with.
- GET /v1/vat/{number}
- Check an EU VAT number: format offline, then live VIES, with a dated receipt.
- GET /v1/peppol/{id}
- Is a counterparty published on Peppol, and what can it receive.
- GET /docs
- OpenAPI reference.
- MCP /mcp
- Remote MCP server; local stdio build on request.
Errors come back as {"ok": false, "error": {"code", "message", "hint"}} with a matching HTTP status. Remaining credits are in the X-Credits-Remaining header.
Pay per document. Paid credits never expire.
One invoice = one credit, whatever outputs you request in that call; a file that carries several invoices costs one per invoice. No monthly minimum, no seats.
With your first key, valid 30 days. No card. Enough to wire up the integration and run it against real supplier files.
For a plugin in production with a handful of customers.
The usual band for an AP tool or an agency running several clients.
Higher volumes and on-premise images by invoice — ask.
Prices exclude VAT. Payment by invoice or payment link; self-serve checkout coming. Invoice on request for higher volumes. The demo quota (20 invoices per IP per day) needs no key at all.
Request a key.
Leave your email and, if you like, what you receive. We reply with a key and the invoice or payment link for paid tiers.
Validation results describe what the official rule sets say about a file. They are not legal or tax advice, and no automated check can certify a document as accepted by a tax authority or a buyer.
Short answers.
Is this a Peppol access point?
Do you store my invoices?
Which rule versions do you run?
- EN 16931 validation artefacts 1.3.17 (UBL and CII Schematron)
- XRechnung 3.0.2 — KoSIT Schematron 2.6.0 (UBL and CII)
- Peppol BIS Billing 3.0 rules, current master
- FNFE CTC-FR 1.4.0.04 transition profile (BR-FR rules, Flux 2) — runs when seller and buyer are both established in France
- CIUS-RO 1.0.1 (ro16931-ubl-1.0.9) — the verdict and wording match what ANAF's SPV returns
- Market conventions no Schematron reads: German Skonto terms in free text, and the Polish KSeF number (
?ksef=) - UBL 2.1 XSD · CII D16B XSD · FatturaPA 1.2.2 XSD · KSeF FA(2) and FA(3) XSD
- Arithmetic cross-checks (line sums, VAT per category, totals) on every format
Every answer names the versions it used: validation.rule_sets in the body and the X-Invoicein-Rulesets header. Changes are dated at /rules/changelog (Atom feed) and GET /v1/rulesets; any rule id can be explained via GET /v1/rules/{id}?lang=de.
What about Factur-X BASIC and MINIMUM?
coverage: schema.