Developers

API documentation

Validate XRechnung and ZUGFeRD invoices against the official KoSIT rules and turn raw XML into a readable invoice – with a simple JSON API. Invoices are processed in memory only and never stored.

  • REST · JSON
  • Version v1
  • 15 MB max.
  • Bearer API Key (Pro & Agency)

Overview

All paid REST API endpoints live under the versioned path /api/v1. For interactive manual checks without an API key, use our free browser validator (up to 5 checks per UTC day). The examples below use the shell variables $BELEGBRIDGE_URL and $BELEGBRIDGE_API_KEY.

  • Memory-only processing: uploaded invoices are processed exclusively in memory and discarded as soon as the response has been sent. Nothing is written to disk, a database or logs.
  • Content types: responses are application/json; charset=utf-8 unless stated otherwise. The visualizer can also return HTML or PDF (see Visualize).
  • Versioning: breaking changes are only introduced under a new path (e.g. /api/v2). New optional fields may be added to v1 responses at any time – please ignore unknown fields.
export BELEGBRIDGE_URL="<address-of-this-website>"
export BELEGBRIDGE_API_KEY="bb_live_..."

Authentication

All REST API endpoints under /api/v1/* require an API key in the Authorization: Bearer bb_live_... header and never set cookies. REST API access is included in the Pro and Agency plans. Compare plans on Pricing.

Authorization: Bearer bb_live_...

Requests without a valid API key receive 401 Unauthorized with WWW-Authenticate: Bearer realm="BelegBridge API":

HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer realm="BelegBridge API"
Content-Type: application/json; charset=utf-8

{
  "valid": false,
  "legal_ustg14_compliant": false,
  "status": "UNAUTHORIZED",
  "message": "Missing or invalid API key. Pass 'Authorization: Bearer bb_live_...' — REST API access is included in the Pro and Agency plans (see /#pricing).",
  "pricing_url": "/#pricing"
}

Early access REST API keys for the Pro and Agency plans are currently issued to early-access members. Reserve your key via the waitlist modal below.

Rate limits

Public endpoints are protected by a per-client token bucket. The client is identified by a salted hash of its IP address; the salt rotates daily, so raw IP addresses are never stored – neither in memory nor in logs.

When the limit is exceeded, the API responds with 429 Too Many Requests and the header Retry-After: 60. Wait at least the indicated number of seconds before retrying.

HTTP/1.1 429 Too Many Requests
Retry-After: 60
Content-Type: application/json; charset=utf-8

{
  "valid": false,
  "legal_ustg14_compliant": false,
  "status": "RATE_LIMIT_EXCEEDED",
  "message": "Rate limit exceeded for public validation endpoint. Please try again shortly."
}

Validate an invoice

POST /api/v1/validate

Detects the format, checks the XML against the official KoSIT validator (EN 16931 and XRechnung business rules) and – for PDFs – checks PDF/A-3 conformance. Every finding is translated into German and English with a concrete fix.

Request

  • multipart/form-data with the file in the field file (the field names invoice and document are accepted as well), or
  • the raw file as request body with Content-Type: application/xml, application/pdf or application/octet-stream.
  • Maximum size: 15 MB. Larger requests are rejected with 413.

Supported inputs:

  • UN/CEFACT Cross Industry Invoice (CII) – XRechnung CII, ZUGFeRD 2.x / Factur-X XML
  • OASIS UBL 2.1 Invoice and CreditNote – XRechnung UBL, Peppol BIS Billing 3.0
  • Hybrid PDF/A-3 files with an embedded factur-x.xml, xrechnung.xml or zugferd-invoice.xml attachment (ZUGFeRD 2.x / Factur-X)
# multipart upload
curl -sS -X POST "$BELEGBRIDGE_URL/api/v1/validate" \
  -H "Authorization: Bearer $BELEGBRIDGE_API_KEY" \
  -F "file=@rechnung.xml"

# raw body (PDF)
curl -sS -X POST "$BELEGBRIDGE_URL/api/v1/validate" \
  -H "Authorization: Bearer $BELEGBRIDGE_API_KEY" \
  -H "Content-Type: application/pdf" \
  --data-binary "@rechnung.pdf"

Response fields

FieldTypeDescription
validbooleanOverall verdict (see rules below).
legal_ustg14_compliantbooleantrue only if the document is valid and uses a profile that qualifies as an e-invoice under § 14 UStG (German VAT Act).
statusstring, optionalMachine-readable status for special cases, e.g. INVALID_NOT_EINVOICE for a plain PDF without XML data.
messagestring, optionalHuman-readable explanation accompanying status.
detected_containerstringXML | PDF_A3 | INVALID_NOT_EINVOICE
detected_syntaxstringUN_CEFACT_CII | OASIS_UBL_2_1_INVOICE | OASIS_UBL_2_1_CREDIT_NOTE
detected_profilestringXRECHNUNG_3_0_2, XRECHNUNG_LEGACY, EN16931, EXTENDED, BASIC, PEPPOL_BIS_3_0, BASIC_WL, MINIMUM, ZUGFERD_1_0_LEGACY, UNKNOWN – see Profiles
document_typestring380_INVOICE, 381_CREDIT_NOTE, 384_CORRECTED_INVOICE, 389_SELF_BILLED_INVOICE, 326_PARTIAL_INVOICE
pdfa_compliantbooleanResult of the PDF/A-3 conformance check (only meaningful for PDF_A3).
summary.errors_countintegerNumber of FATAL violations.
summary.warnings_countintegerNumber of WARNING findings.
violations[]arrayAll findings; empty array if there are none.
violations[].rule_idstringRule ID exactly as reported by the validator, e.g. BR-DE-15, BR-CO-15, PEPPOL-EN16931-R008.
violations[].severitystringFATAL | WARNING
violations[].bt_referencestringAffected business term or group (e.g. BT-10, BG-6), if known.
violations[].xpathstringLocation in the XML document.
violations[].raw_messagestringOriginal message from the validator.
violations[].title_de, title_enstringShort, understandable title in German and English.
violations[].fix_de, fix_enstringConcrete fix in German and English.

When is an invoice valid?

valid is true only if all of the following apply:

  • there are zero FATAL violations,
  • the KoSIT validation report recommends acceptance,
  • the detected profile is allowed under § 14 UStG (see Profiles), and
  • for PDFs: the file conforms to PDF/A-3.

Warnings are reported for information and to improve data quality – they never make an invoice invalid.

Example: invoice without buyer reference (BT-10) and seller contact (BG-6)

{
  "valid": false,
  "legal_ustg14_compliant": false,
  "detected_container": "XML",
  "detected_syntax": "UN_CEFACT_CII",
  "detected_profile": "XRECHNUNG_3_0_2",
  "document_type": "380_INVOICE",
  "pdfa_compliant": false,
  "summary": {
    "errors_count": 2,
    "warnings_count": 0
  },
  "violations": [
    {
      "rule_id": "BR-DE-2",
      "severity": "FATAL",
      "bt_reference": "BG-6",
      "xpath": "/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:SellerTradeParty",
      "raw_message": "[BR-DE-2] Die Gruppe \"SELLER CONTACT\" (BG-6) muss übermittelt werden.",
      "title_de": "Kontaktdaten des Verkäufers (BG-6) fehlen",
      "title_en": "Seller contact details (BG-6) are missing",
      "fix_de": "Ergänzen Sie Ansprechpartner (BT-41), Telefonnummer (BT-42) und E-Mail-Adresse (BT-43) des Verkäufers.",
      "fix_en": "Add the seller's contact person (BT-41), phone number (BT-42) and email address (BT-43)."
    },
    {
      "rule_id": "BR-DE-15",
      "severity": "FATAL",
      "bt_reference": "BT-10",
      "xpath": "/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement",
      "raw_message": "[BR-DE-15] Das Element \"Buyer reference\" (BT-10) muss übermittelt werden.",
      "title_de": "Käuferreferenz bzw. Leitweg-ID (BT-10) fehlt",
      "title_en": "Buyer reference / Leitweg-ID (BT-10) is missing",
      "fix_de": "Tragen Sie die Leitweg-ID des öffentlichen Auftraggebers oder eine andere Käuferreferenz in BT-10 ein.",
      "fix_en": "Enter the public-sector routing ID (Leitweg-ID) or another buyer reference in BT-10."
    }
  ]
}

Titles and fixes are maintained editorially and may be refined over time; rely on rule_id and severity for automated processing.

Profiles & § 14 UStG

The field detected_profile tells you which specification the invoice claims to follow. Only profiles that contain the full EN 16931 data set (including invoice lines) qualify as e-invoices under § 14 UStG (German VAT Act).

detected_profileMeaning§ 14 UStG compliant
XRECHNUNG_3_0_2XRechnung 3.0.x (German CIUS of EN 16931)Yes
XRECHNUNG_LEGACYOlder XRechnung version (before 3.0); validated against the current rulesDepends on the validation result
EN16931ZUGFeRD 2.x / Factur-X profile EN 16931 (Comfort)Yes
EXTENDEDZUGFeRD 2.x / Factur-X profile EXTENDEDYes
BASICZUGFeRD 2.x / Factur-X profile BASICYes
PEPPOL_BIS_3_0Peppol BIS Billing 3.0 (validated against the EN 16931 core rules)Yes
BASIC_WLZUGFeRD / Factur-X BASIC WL – no invoice linesNo
MINIMUMZUGFeRD / Factur-X MINIMUM – no invoice linesNo
ZUGFERD_1_0_LEGACYZUGFeRD 1.0 – predates EN 16931No
UNKNOWNSpecification identifier not recognizedNo

Visualize an invoice

POST /api/v1/visualize

Turns an XRechnung or ZUGFeRD invoice into a unified, human-readable view and recalculates the totals. Accepts the same request formats and size limit as /api/v1/validate.

Parameters

ParameterValuesDescription
formatjson | html | pdfQuery parameter. Default: json. HTMX requests receive HTML.
langde | enLanguage of labels in the HTML/PDF view. Query parameter or multipart field.
# JSON
curl -sS -X POST "$BELEGBRIDGE_URL/api/v1/visualize?format=json&lang=de" \
  -H "Authorization: Bearer $BELEGBRIDGE_API_KEY" \
  -F "file=@rechnung.xml"

# PDF download
curl -sS -X POST "$BELEGBRIDGE_URL/api/v1/visualize?format=pdf&lang=de" \
  -H "Authorization: Bearer $BELEGBRIDGE_API_KEY" \
  -F "file=@rechnung.xml" \
  -o invoice-preview.pdf

JSON response

FieldDescription
valid_mathtrue if all recalculated totals match the invoice.
syntaxDetected syntax (same values as detected_syntax).
profile_levelDetected profile (same values as detected_profile).
source_containerXML | ZUGFERD_PDF_A3
invoiceUnified invoice view: invoice_number, issue_date, type_code, currency, buyer_reference, seller{…}, buyer{…}, payment{means_code, iban, bic, payment_terms}, lines[], taxes[], totals{…}, penny_math{…}.
invoice.totalsline_total, tax_basis_total, tax_total, grand_total, due_payable as decimal strings, each with an integer counterpart in cents (line_total_cents, …).
invoice.penny_mathvalid, br_co_10_valid, br_co_13_valid, br_co_14_valid, br_co_15_valid and – only when there are mismatches – discrepancies[].
html_previewReady-to-embed HTML fragment of the invoice.

Example (shortened):

{
  "valid_math": true,
  "syntax": "UN_CEFACT_CII",
  "profile_level": "XRECHNUNG_3_0_2",
  "source_container": "XML",
  "invoice": {
    "invoice_number": "RE-2026-0042",
    "issue_date": "2026-11-02",
    "type_code": "380",
    "currency": "EUR",
    "buyer_reference": "04011000-12345-67",
    "seller": { "name": "Muster Webagentur", "city": "Berlin", "country_code": "DE" },
    "buyer": { "name": "Beispielkunde AG", "city": "Hamburg", "country_code": "DE" },
    "payment": { "means_code": "58", "iban": "DE02120300000000202051", "payment_terms": "14 Tage netto" },
    "lines": [
      { "id": "1", "name": "Webentwicklung", "quantity": "10", "unit_code": "HUR", "net_price": "95.00", "line_net_amount": "950.00", "line_net_cents": 95000, "vat_category": "S", "vat_rate": "19" }
    ],
    "taxes": [
      { "category_code": "S", "rate": "19", "taxable_amount": "950.00", "taxable_cents": 95000, "tax_amount": "180.50", "tax_cents": 18050 }
    ],
    "totals": {
      "line_total": "950.00", "line_total_cents": 95000,
      "tax_basis_total": "950.00", "tax_basis_total_cents": 95000,
      "tax_total": "180.50", "tax_total_cents": 18050,
      "grand_total": "1130.50", "grand_total_cents": 113050,
      "due_payable": "1130.50", "due_payable_cents": 113050
    },
    "penny_math": {
      "valid": true,
      "br_co_10_valid": true,
      "br_co_13_valid": true,
      "br_co_14_valid": true,
      "br_co_15_valid": true
    }
  },
  "html_preview": "<div class=\"bb-invoice\">…</div>"
}

All totals are recalculated with integer cents – never with floating-point numbers – following the EN 16931 rules BR-CO-10 (sum of line net amounts), BR-CO-13 (tax basis), BR-CO-14 (VAT total), BR-CO-15 (grand total), BR-CO-16 (amount due with rounding) and BR-CO-17 (VAT per category). A difference of a single cent is reported.

Errors & status codes

Note: an invoice with validation errors is not an HTTP error – it is returned with 200 OK and "valid": false. HTTP errors indicate that the request itself could not be processed. They share this body:

{
  "valid": false,
  "legal_ustg14_compliant": false,
  "status": "UNSUPPORTED_FORMAT",
  "message": "…"
}
HTTPstatusMeaning
400INVALID_REQUESTMalformed request, e.g. multipart without a file part.
400EMPTY_PAYLOADThe uploaded file is empty.
400UNSUPPORTED_FORMATNeither a supported XML invoice nor a PDF.
400UNSAFE_XML_DECLARATIONThe XML contains <!DOCTYPE or <!ENTITY and was rejected (XXE protection).
401UNAUTHORIZEDMissing or invalid Authorization: Bearer API key (see Authentication).
405–Method not allowed; the Allow header lists the permitted method.
413PAYLOAD_TOO_LARGEThe request exceeds 15 MB or the embedded PDF decompression limit.
429RATE_LIMIT_EXCEEDEDToo many requests; see Rate limits.
502SIDECAR_VALIDATION_ERRORThe validation service could not process the document. Retry later.
503SIDECAR_BUSYValidation concurrency limit reached; retry after Retry-After: 5 seconds.

Security & privacy

  • XXE protection: XML documents containing <!DOCTYPE or <!ENTITY declarations are rejected before parsing.
  • Size limit: requests are capped at 15 MB.
  • Memory-only: invoice contents are never written to disk, a database or logs.
  • No cookies, no tracking: neither the website nor the API sets cookies.
  • Strict Content Security Policy: all scripts, styles and fonts are served from our own domain – no external CDNs.

More details: privacy policy and data processing agreement (AVV).

Planned endpoints

The following endpoints are part of the paid bridge and are not available yet. Paths and schemas may still change.

EndpointPurposeStatus
POST /api/v1/generateCreate EN 16931 XML and a ZUGFeRD 2.3 PDF/A-3 from JSON (API key required).Planned
POST /api/v1/webhooks/stripe/{seller_profile_id}Stripe webhook endpoint per seller profile: turns paid Stripe invoices into compliant ZUGFeRD invoices.Planned
DATEV dispatchAutomatic forwarding of validated invoices to the buyer and your DATEV inbox.Planned
Try the validator