Skip to content

API for developers

JSON in, validated e-invoice out

Send your invoice data as JSON and receive a ZUGFeRD PDF/A-3 or an XRechnung XML according to EN 16931. Before a file is created, the invoice is checked against the official KoSIT validation rules; if it does not pass, you receive the validator messages instead of a file. You do not have to implement the standards, Schematron rules or the PDF/A conversion yourself – a versioned REST API with an OpenAPI description is all you need.

How it works

  1. Create an API key
    Create a key in your account and send it with every request in the header Authorization: Api-Key <key>. API Keys
  2. Send the invoice as JSON
    POST /api/v1/invoices/ creates the invoice; the response contains its id. In tax_breakdowns, specify one entry per tax category and rate; totals and tax amounts are recalculated from the line items.
  3. Retrieve PDF/A-3 or XRechnung XML
    POST /api/v1/invoices/{invoice_id}/generate_zugferd_pdf/ returns the ZUGFeRD PDF/A-3 with embedded XML. For invoices with the profile XRECHNUNG (public authorities, with Leitweg-ID in buyer_reference), POST /api/v1/invoices/{invoice_id}/generate_xrechnung/ returns the XRechnung XML. Created files can be downloaded again via GET /api/v1/invoices/{invoice_id}/download/.
  4. Check the result
    If the validation fails, you receive HTTP 400 with the validator messages instead of a file. You can also check existing XML files: POST /api/v1/validate/ with the file in the form field invoice_file returns errors and warnings.

Examples

Invoice data (invoice.json)

{
  "invoice_number": "RE-2026-001",
  "issue_date": "2026-10-01",
  "delivery_date": "2026-10-01",
  "type_code": "380",
  "currency_code": "EUR",
  "payment_terms": "Zahlbar innerhalb von 14 Tagen ohne Abzug",
  "seller": {
    "name": "Muster GmbH",
    "street": "Musterstraße 1",
    "postal_code": "10115",
    "city": "Berlin",
    "country_code": "DE",
    "vat_id": "DE123456789",
    "contact_name": "Max Mustermann",
    "contact_phone": "+49 30 12345678",
    "contact_email": "rechnung@muster.example"
  },
  "buyer": {
    "name": "Käufer AG",
    "street": "Käuferstraße 5",
    "postal_code": "80331",
    "city": "München",
    "country_code": "DE",
    "vat_id": "DE987654321"
  },
  "items": [
    {
      "line_id": "1",
      "name": "Beratungsleistung",
      "quantity": "8",
      "unit_code": "HUR",
      "net_price": "95.00",
      "tax_category": "S",
      "tax_rate": "19.00"
    }
  ],
  "tax_breakdowns": [
    {
      "tax_category": "S",
      "tax_rate": "19.00",
      "basis_amount": "760.00",
      "tax_amount": "144.40"
    }
  ]
}

curl

curl -X POST "https://www.e-rechnungsfreund.de/api/v1/invoices/" \
  -H "Authorization: Api-Key $API_KEY" \
  -H "Content-Type: application/json" \
  -d @invoice.json

curl -X POST "https://www.e-rechnungsfreund.de/api/v1/invoices/$INVOICE_ID/generate_zugferd_pdf/" \
  -H "Authorization: Api-Key $API_KEY" \
  -o invoice.pdf

curl -X POST "https://www.e-rechnungsfreund.de/api/v1/validate/" \
  -H "Authorization: Api-Key $API_KEY" \
  -F "invoice_file=@invoice.xml"

Python (requests)

import json

import requests

BASE_URL = "https://www.e-rechnungsfreund.de"
HEADERS = {"Authorization": "Api-Key YOUR_API_KEY"}

with open("invoice.json", encoding="utf-8") as f:
    invoice = json.load(f)

response = requests.post(f"{BASE_URL}/api/v1/invoices/", json=invoice, headers=HEADERS, timeout=30)
response.raise_for_status()
invoice_id = response.json()["id"]

pdf = requests.post(
    f"{BASE_URL}/api/v1/invoices/{invoice_id}/generate_zugferd_pdf/",
    headers=HEADERS,
    timeout=120,
)
if pdf.status_code == 400:
    print(pdf.json())
else:
    pdf.raise_for_status()
    with open("invoice.pdf", "wb") as f:
        f.write(pdf.content)

All fields, optional information (e.g. payment means, allowances and charges, notes) and the response formats are described in the API documentation. Open API documentation

Rate limits

  • Regular endpoints (e.g. creating, retrieving and downloading invoices): 120 requests per minute per account. Resource-intensive requests also count towards this limit.
  • Resource-intensive endpoints (validation, PDF/A-3 and XRechnung generation): a separate, stricter limit of 6 requests per minute per account by default; higher plans allow more (see below).

If a limit is exceeded, the API responds with HTTP 429. The monthly number of invoices included in your plan also applies to the API (HTTP 402 when reached).

Versioning and documentation

The API version is part of the path: /api/v1/. The current OpenAPI description has the version 1.0.0.

Which plans include API access?

API access is included in the following plans:

  • Pro (resource-intensive endpoints: 15 requests per minute)
  • Business (resource-intensive endpoints: 30 requests per minute)
View plans with API access

Security and data protection