Developer's Guide to XRechnung: EN 16931 Compliance via API

Published on March 15, 2026

A hands-on guide to generating and validating XRechnung invoices using the Postscale API, with code examples and common pitfalls.

XRechnung is Germany's implementation of the EN 16931 European e-invoicing standard. This guide walks through the practical steps of generating and validating XRechnung invoices with the Postscale API.

Understanding XRechnung

XRechnung is a Core Invoice Usage Specification (CIUS) — it takes the broad EN 16931 standard and adds Germany-specific constraints. Think of EN 16931 as the interface and XRechnung as the implementation.

Key differences from a plain EN 16931 invoice:

  • Seller contact is mandatory — name, phone, and email (BR-DE-02 through BR-DE-04)
  • Buyer reference required — Leitweg-ID for government invoices (BR-DE-15)
  • Payment terms in text — human-readable payment conditions (BR-DE-18)
  • Restricted type codes — only 380, 381, 384, 389 are allowed (BR-DE-17)

Validation First

Before generating invoices, validate your existing ones:

curl -X POST https://api.postscale.io/v1/invoices/validate \
  -H "Authorization: Bearer ps_live_..." \
  -H "Content-Type: application/xml" \
  -d @your-invoice.xml

The response tells you exactly what's wrong:

{
  "valid": false,
  "format": "xrechnung-ubl",
  "errors": [
    {
      "rule": "BR-DE-02",
      "path": "/Invoice/AccountingSupplierParty/Party/Contact/Name",
      "message": "The element 'Seller contact point' (BT-41) is required"
    }
  ]
}

Each error includes the XRechnung rule ID, the XPath where the violation occurs, and a description referencing the EN 16931 business term ID (BT-*). This makes it straightforward to map errors back to your data model.

Generating Invoices from JSON

Rather than constructing UBL XML by hand, pass structured JSON to the send endpoint:

curl -X POST https://api.postscale.io/v1/invoices/send \
  -H "Authorization: Bearer ps_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "from": "billing@yourdomain.com",
    "to": "invoices@customer.de",
    "format": "xrechnung-ubl",
    "invoice": {
      "number": "2026-0089",
      "issue_date": "2026-03-18",
      "due_date": "2026-04-17",
      "currency": "EUR",
      "seller": {
        "name": "Your Company GmbH",
        "street": "Hauptstr. 42",
        "city": "Munich",
        "postal_code": "80331",
        "country": "DE",
        "tax_id": "DE987654321",
        "contact_name": "Billing Team",
        "contact_email": "billing@yourdomain.com",
        "contact_phone": "+49 89 1234567"
      },
      "buyer": {
        "name": "Customer AG",
        "street": "Berliner Str. 10",
        "city": "Berlin",
        "postal_code": "10115",
        "country": "DE"
      },
      "payment": {
        "means_code": "58",
        "iban": "DE89370400440532013000",
        "terms": "Net 30 days"
      },
      "line_items": [
        {
          "description": "Consulting — March 2026",
          "quantity": 40,
          "unit": "HUR",
          "unit_price": "120.00",
          "tax_category": "S",
          "tax_rate": "19.00"
        }
      ]
    }
  }'

The API generates valid UBL 2.1 XML, validates it, and sends it as an email with the XML attached.

Common Pitfalls

Missing seller contact — XRechnung requires all three: contact name (BT-41), phone (BT-42), and email (BT-43). EN 16931 makes these optional, so invoices valid under the base standard may fail XRechnung validation.

Wrong payment means code — Code 58 (SEPA credit transfer) is the most common for German B2B. Don't use 1 (not defined) or ZZZ (mutually agreed).

Tax rounding — Calculate tax per line item, then sum. Don't calculate tax on the total net amount. XRechnung expects line-level tax calculation matching the invoice total.

Date format — Always use ISO 8601 (YYYY-MM-DD). The API accepts this format in JSON and produces the correct XML date representations.

Testing

Use the validation endpoint to test your invoices before going live. Common test scenarios:

  1. Standard B2B invoice with 19% VAT
  2. Mixed VAT rates (19% and 7%)
  3. Credit note (type code 381)
  4. B2G invoice with Leitweg-ID
  5. Reverse charge / intra-community supply

The validation endpoint is free and doesn't generate or send anything — use it as part of your CI/CD pipeline or pre-send checks.