Skip to content
GitHub

Conversion API (HTTP)

einvoice serve starts a small stateless server that implements openapi/openapi.yaml (OpenAPI 3.1) with the same convert(), inspect() and detectXml() as the library. The rendered reference is at /api-reference/ on the site.

Terminal window
einvoice serve --port 8080 --cors # or: bun src/cli.ts serve
curl -X POST --data-binary @invoice.xml -H 'Content-Type: application/xml' 'http://localhost:8080/v1/convert?relations=true'
curl -X POST -F file=@invoice.pdf http://localhost:8080/v1/inspect
Endpoint Does
POST /v1/convert File (multipart file or raw body) to ConvertResult. Query: validate, relations, provenance, euTrust, filename.
POST /v1/inspect Unwrap and detect to InspectResult.
POST /v1/detect Raw XML to a Detection.
GET /v1/formats The format registry: id, name, family, countries, status.
GET /v1/schemas/{name} canonical-invoice, convert-result or inspect-result JSON Schema.
GET /health Liveness, package and schema versions.

Errors are application/problem+json (RFC 9457) and use the CLI’s exit-code categories as type URIs (listed here): unsafe-or-malformed (400, and 413 for a limit), unsupported, validation-failed and partial (422, with the full result in result), validator-unavailable (503) and internal (500). ?euTrust=true needs a trusted-list snapshot, so start the server with --eu-trust; ?validate=true runs the XSD and Schematron layers (when the bundles are not readable it answers 503).

The server writes nothing to disk and keeps no state. The upload is read through a counting reader and refused with 413 as soon as it passes maxFileBytes (50 MiB; --limits '{"maxFileBytes":10485760}' lowers it, the other UnwrapLimits apply too). CORS is off unless you pass --cors (any origin) or --cors=https://app.example. It listens on 127.0.0.1 by default; there is no authentication, so put it behind your own gateway before exposing it.

The Docker image runs the same command from the Bun runtime image:

Terminal window
docker build -t einvoice-api .
docker run --rm --read-only -p 8080:8080 einvoice-api # add --cors or --limits after the image name

Contract tests (test/api-contract.test.ts) start the server in-process, send every fixture through every endpoint and check status, headers and body of each response against openapi.yaml; the spec itself is validated as OpenAPI 3.1 and its references into schemas/ are checked, so the spec and the generated schemas cannot drift.