ideas.
October 22, 2026 3 min read apib2bfinance

JSON in, legally valid e-invoice out

An API that turns a simple invoice JSON into a compliant structured e-invoice for whichever country the buyer is in, and validates it before you send.

The idea

A single HTTP endpoint that accepts a plain invoice object — seller, buyer, line items, tax rates, payment terms — and returns a structured electronic invoice in whatever format the buyer's jurisdiction demands: EN 16931 UBL, UN/CEFACT CII, a Factur-X/ZUGFeRD PDF with the XML embedded, XRechnung for German public buyers, FatturaPA for Italy. The response includes the artifact, a validation report, and a human-readable PDF rendering. A second endpoint hands it to the Peppol network if the buyer is registered there.

The pitch is that you send the same JSON every time and the API absorbs the format churn.

Why build this

Structured e-invoicing stopped being a Nordic curiosity and became a legal requirement across most of the EU, with mandates and reporting obligations phasing in through 2027–2028 and similar schemes live in Latin America, India, Saudi Arabia and Singapore. The semantic model (EN 16931) is shared, but every country layers on its own CIUS, its own Schematron rules, its own transport channel, and its own idea of what a rounding difference means.

That is fine for an enterprise ERP with a compliance team. It is brutal for the long tail: the indie SaaS billing a German university, the agency invoicing an Italian client, the Stripe-based business whose first public-sector customer just asked for XRechnung 3.x and will reject a PDF. Those businesses have engineers, no compliance department, and no appetite for a six-figure ERP module. Today they either bolt together half-maintained libraries or pay an enterprise e-invoicing vendor whose smallest plan assumes thousands of documents a month.

The gap is a developer-grade, per-document product: good docs, a sandbox, one JSON schema, and an honest validation report instead of a silent rejection three days later.

Stack sketch

  • API: FastAPI with Pydantic models for the canonical invoice, generating an OpenAPI spec that doubles as the docs.
  • Mapping layer: one module per target syntax, emitting UBL 2.1 and CII with lxml from a single internal representation. Keep the mapping tables as data, not code — they change.
  • Validation: the official Schematron artifacts from CEN and the Peppol releases, compiled to XSLT with SchXslt and run per document. Return every failed assertion with its rule ID, not a boolean.
  • Hybrid PDFs: generate the visual invoice with Typst or WeasyPrint, then attach the CII XML as a PDF/A-3 embedded file with pikepdf, and verify conformance with veraPDF in CI.
  • Transport: don't build a Peppol Access Point. Start by relaying through an existing certified provider's API, and do SMP participant lookups yourself so you can tell the caller whether the buyer is even reachable.
  • Storage: Postgres for documents and validation history, object storage for the artifacts, with a retention setting per customer — these are tax records.

Scope for v1

In: the canonical JSON schema, EN 16931 UBL and CII output, Factur-X/ZUGFeRD PDF, XRechnung, Schematron validation with a readable report, a sandbox key, and a conformance test suite built from the official example files.

Out: Peppol delivery, Italy's SdI, non-EU regimes, inbound parsing, archiving guarantees, a dashboard. Ship with a CLI and a webhook instead of a UI, and let the validation endpoint be free and unauthenticated for small payloads — it is the best possible demo.

Where it could go

The obvious next layer is receiving. Every business under a mandate also has to accept structured invoices, and parsing an arbitrary UBL document into something an accounting system can book is the same mapping problem in reverse, with a larger surface of real-world malformedness. An inbound endpoint that normalises whatever arrives into your canonical JSON is a second product sold to the same customer.

After that, the interesting asset is the corpus. Once you have run a few hundred thousand documents through official Schematron, you know which rules actually trip people, for which country, and why — which makes a genuinely useful public reference, a pre-flight linter for ERP teams, and the foundation for plugins into Stripe Invoicing, Lago, Odoo and the smaller billing tools that will all need this and would rather not build it.

Watch out for

The rules move on a schedule you don't control: Schematron releases land with short notice, and a document that validated last quarter can fail this one, so version pinning per customer and an automated upgrade pipeline are v1 features, not polish. Check the licence on every validation artifact and library you embed before you resell output built with it.