API-Referenz

Alle Endpunkte der invoiceapi.io-REST-API, erzeugt aus ihrer OpenAPI-3.1-Beschreibung.

Basis-URL
https://invoiceapi.io/v1
Authentifizierung
Authorization: Bearer sk_test_… oder sk_live_…
OpenAPI
OpenAPI 3.1 JSON
Postman
Collection zum Import in Postman (JSON)

Schnellstart: Ihre erste Testrechnung

Vom neuen Konto bis zur ersten Testrechnung aus Ihrem eigenen Code. Sie brauchen dafür nur eine E-Mail-Adresse und den HTTP-Client Ihrer Programmiersprache.

  1. Anmelden

    Melden Sie sich unter /login mit Ihrer E-Mail-Adresse an. Wir senden Ihnen einen einmaligen Code per E-Mail. Ist die Adresse neu, legt die Anmeldung Ihr Konto an.

  2. Den Einrichtungsassistenten durchlaufen

    Der Assistent fragt nacheinander nach Ihrer Organisation, dem Rechnungssteller, Layout und Nutzungsbedingungen und dem Logo. Zum Schluss erstellt er einen Test-API-Schlüssel. Kopieren Sie den Schlüssel sofort: Er wird nur einmal angezeigt.

  3. Die Vorlagen-ID ermitteln

    Die ID steht im curl-Befehl am Ende des Assistenten. Sie können sie auch mit dem Test-API-Schlüssel abfragen: GET /v1/templates liefert jede Vorlage mit ihrer id. Nehmen Sie eine Vorlage, die eine profileId hat. Eine Vorlage ohne Profil beantwortet den Aufruf mit 404 „Template has no associated profile“.

  4. Die erste Rechnung erzeugen

    Senden Sie den Rechnungsdatensatz an diesen Endpunkt, mit einem eigenen Idempotency-Key für jede Rechnung. 201 heißt: Die Rechnung wurde erzeugt. 200 heißt: Derselbe Schlüssel kam schon einmal, und Sie erhalten die bereits erzeugte Rechnung zurück.

    POST /v1/templates/{id}/invoices

    Der Datensatz enthält weder Verkäufer noch Bankverbindung: Beides ergänzt das Rechnungsprofil der Vorlage. Was Sie im Datensatz mitsenden, hat Vorrang vor dem Profil.

    {
      "buyer": {
        "name": "Kunde AG",
        "vatId": "DE987654321",
        "electronicAddress": "rechnung@kunde.example",
        "address": {
          "line1": "Kundenweg 1",
          "city": "München",
          "postCode": "80331",
          "countryCode": "DE"
        }
      },
      "invoice": {
        "number": "R-2026-1001",
        "issueDate": "2026-07-01",
        "dueDate": "2026-07-31",
        "currency": "EUR",
        "buyerReference": "KND-2026-77"
      },
      "items": [
        {
          "name": "Beratung",
          "quantity": "8",
          "unit": "HUR",
          "unitPrice": "120.00",
          "vatRate": "19"
        }
      ],
      "payment": {
        "reference": "R-2026-1001"
      }
    }

    Laden Sie die Dateien unter outputs[].url bald herunter, denn die Links laufen ab. Neue Links erhalten Sie jederzeit mit GET /v1/invoices und der id der Rechnung.

  5. Derselbe Aufruf in Ihrer Sprache

    Ein SDK brauchen Sie nicht. Jedes Beispiel nutzt den HTTP-Client, den die Sprache mitbringt, und liest Schlüssel und Vorlagen-ID aus den Umgebungsvariablen INVOICEAPI_KEY und TEMPLATE_ID. Das Python-Beispiel setzt einen eigenen User-Agent, weil ein Aufruf mit dem Standard-User-Agent von urllib mit 403 abgewiesen wird.

    : "${INVOICEAPI_KEY:?Set INVOICEAPI_KEY and TEMPLATE_ID first.}" "${TEMPLATE_ID:?Set INVOICEAPI_KEY and TEMPLATE_ID first.}" && \
    curl -X POST "https://invoiceapi.io/v1/templates/$TEMPLATE_ID/invoices" \
      -H "Authorization: Bearer $INVOICEAPI_KEY" \
      -H "Content-Type: application/json" \
      -H "Idempotency-Key: $(uuidgen 2>/dev/null || openssl rand -hex 16)" \
      --data-binary @- <<'JSON'
    {
      "buyer": {
        "name": "Kunde AG",
        "vatId": "DE987654321",
        "electronicAddress": "rechnung@kunde.example",
        "address": {
          "line1": "Kundenweg 1",
          "city": "München",
          "postCode": "80331",
          "countryCode": "DE"
        }
      },
      "invoice": {
        "number": "R-2026-1001",
        "issueDate": "2026-07-01",
        "dueDate": "2026-07-31",
        "currency": "EUR",
        "buyerReference": "KND-2026-77"
      },
      "items": [
        {
          "name": "Beratung",
          "quantity": "8",
          "unit": "HUR",
          "unitPrice": "120.00",
          "vatRate": "19"
        }
      ],
      "payment": {
        "reference": "R-2026-1001"
      }
    }
    JSON
  6. Ausgabeformate

    Ohne Angabe erzeugt die API eine ZUGFeRD-PDF. Mit ?output= wählen Sie selbst; der Parameter lässt sich wiederholen, etwa ?output=zugferd_pdf&output=xrechnung_xml.

    zugferd_pdf
    Die Voreinstellung: PDF/A-3 mit eingebettetem XML, geprüft mit dem KoSIT-Validator und veraPDF.
    xrechnung_xml
    Das XML für öffentliche Auftraggeber, geprüft mit dem KoSIT-Validator. Es braucht BT-10 (invoice.buyerReference), BT-34 und BT-49 (die elektronischen Adressen von Verkäufer und Käufer). BT-10 und BT-49 stehen im Datensatz oben, BT-34 kommt aus dem Rechnungsprofil der Vorlage.
    pdf
    Die einfache PDF, ohne Prüfung.

    Mögliche Antworten auf den ersten Aufruf

    Fehler kommen als application/problem+json mit dem englischen Titel der API.

    401 Invalid or missing API key
    Der Schlüssel fehlt, ist unbekannt oder wurde widerrufen.
    404 Template not found
    Die Vorlagen-ID ist falsch oder gehört nicht zu Ihrer Organisation.
    404 Template has no associated profile
    Die Vorlage hat kein Rechnungsprofil. Nehmen Sie eine Vorlage mit profileId.
    400 Invalid invoice payload
    Der Datensatz passt nicht zum Schema. errors nennt jeden fehlerhaften Pfad mit seiner Meldung.
    400 Payload is not XRechnung-ready
    Sie haben xrechnung_xml angefordert, aber im Datensatz fehlt BT-10, BT-34 oder BT-49.
    422 Invoice failed compliance validation
    Die Rechnung hat die Prüfung nicht bestanden. errors nennt jede verletzte Regel mit ihrer ID, etwa BR-DE-15.

Endpunkte

POST/templates/{id}/invoices

Generate an invoice from a template

Generates a ZUGFeRD PDF/A-3, an XRechnung XML and/or a plain PDF from the template and payload (see the `output` parameter for which checks each kind gets). Idempotent per Idempotency-Key: a repeat with the same key and an identical body replays the original invoice with a 200 instead of creating a new one. Supply the optional `deliverEmail` block to also email the finished invoice: delivery is attempted synchronously and its outcome is reported on the 201, but a delivery failure NEVER fails the request — the invoice is archived either way. The seller and the bank details (`iban`, `bic`, `accountName`) come from the template's invoice profile for every field the request leaves out; a field the request sends wins.

Parameter

FeldOrtErforderlichBeschreibung
idpathErforderlichResource id.
outputquery—Repeatable. Which artifact kind(s) to produce. Defaults to zugferd_pdf when omitted. `zugferd_pdf`: a PDF/A-3 with the ZUGFeRD XML embedded; KoSIT checks the XML and veraPDF checks the PDF/A-3U. `xrechnung_xml`: the XRechnung XML, checked by KoSIT only; it needs BT-10 (`invoice.buyerReference`), BT-34 (`seller.electronicAddress`, usually from the template's profile) and BT-49 (`buyer.electronicAddress`), or the request gets a 400 "Payload is not XRechnung-ready". `pdf`: the rendered PDF only, with no embedded XML and no KoSIT or veraPDF check (the renderer's plain PDF, NOT validated), so an invoice that requests only `pdf` has an empty `validation.summary`.
Idempotency-Keyheader—Client-supplied key. A repeat with the same key and body returns the original invoice (200); the same key with a different body returns 409.

Anfrage

FeldTypErforderlichBeschreibung
sellerobject—Optional. Each field you leave out is taken from the template's invoice profile, where the profile has it; a field you send wins.
seller.namestring—Seller name (BT-27)
seller.tradingNamestring—Seller trading name (BT-28)
seller.vatIdstring—Seller VAT identifier (BT-31)
seller.taxNumberstring—Seller Steuernummer (BT-32)
seller.electronicAddressstring—Seller electronic address, scheme EM (BT-34; mandatory for XRechnung)
seller.addressobject—Seller postal address (BG-5)
seller.address.line1string—Street line 1 (BT-35 / BT-50)
seller.address.line2string—Street line 2 (BT-36 / BT-51)
seller.address.citystring—City (BT-37 / BT-52; BR-DE-3/BR-DE-8)
seller.address.postCodestring—Post code (BT-38 / BT-53; BR-DE-4/BR-DE-9)
seller.address.countryCodestring—Country code (BT-40 / BT-55)
seller.contactobject—Seller contact (BG-6; mandatory per BR-DE-2)
seller.contact.namestring—Contact point (BT-41; BR-DE-5)
seller.contact.phonestring—Contact phone (BT-42; BR-DE-6)
seller.contact.emailstring—Contact email (BT-43; BR-DE-7/BR-DE-28)
buyerobjectErforderlich—
buyer.namestringErforderlichBuyer name (BT-44)
buyer.vatIdstring—Buyer VAT identifier (BT-48)
buyer.legalRegistrationIdstring—Buyer legal registration id (BT-47)
buyer.electronicAddressstring—Buyer electronic address, scheme EM (BT-49; mandatory for XRechnung)
buyer.addressobjectErforderlichBuyer postal address (BG-8)
buyer.address.line1stringErforderlichStreet line 1 (BT-35 / BT-50)
buyer.address.line2string—Street line 2 (BT-36 / BT-51)
buyer.address.citystringErforderlichCity (BT-37 / BT-52; BR-DE-3/BR-DE-8)
buyer.address.postCodestringErforderlichPost code (BT-38 / BT-53; BR-DE-4/BR-DE-9)
buyer.address.countryCodestringErforderlichCountry code (BT-40 / BT-55)
invoiceobjectErforderlich—
invoice.numberstringErforderlichInvoice number (BT-1)
invoice.issueDatestringErforderlichIssue date (BT-2)
invoice.dueDatestring—Payment due date (BT-9)
invoice.currency"EUR"ErforderlichInvoice currency (BT-5); v1 is EUR-only — non-EUR is a documented seam
invoice.buyerReferencestring—Buyer reference (BT-10); Leitweg-ID for B2G; mandatory for XRechnung (BR-DE-15)
invoice.paymentTermsstring—Payment terms free text (BT-20)
invoice.notesstring[]—Invoice notes (BT-22)
itemsobject[]Erforderlich—
items[].namestringErforderlichItem name (BT-153)
items[].descriptionstring—Item description (BT-154)
items[].quantitystring | numberErforderlichInvoiced quantity (BT-129); negative lines are permitted
items[].unit"H87" | "C62" | "HUR" | "DAY" | "KGM" | "MTR" | "MTK" | "MTQ" | "LTR" | "MON" | "KMT" | "XPP"ErforderlichUnit of measure, UN/ECE Rec 20/21 (BT-130), e.g. H87=piece, HUR=hour
items[].unitPricestring | numberErforderlichItem net price (BT-146); must not be negative (BR-27)
items[].priceBaseQuantitystring | number—Price base quantity (BT-149), default 1
items[].vatRatestring | number—VAT rate percent (BT-152), e.g. "19", "7", "0"
items[].vatCategory"S" | "Z" | "E" | "AE" | "K" | "G"—VAT category (BT-151, UNTDID 5305); default S when vatRate > 0
items[].exemptionReasonstring—VAT exemption reason text (BT-120); required for category E, e.g. §19 UStG wording
items[].allowancesobject[]—Line allowances (BG-27)
items[].allowances[].amountstring | number—Allowance amount (BT-136)
items[].allowances[].percentstring | number—Allowance percentage of the line gross (BT-138)
items[].allowances[].reasonstring—Allowance reason (BT-139)
items[].chargesobject[]—Line charges (BG-28)
items[].charges[].amountstring | number—Charge amount (BT-141)
items[].charges[].percentstring | number—Charge percentage of the line gross (BT-143)
items[].charges[].reasonstring—Charge reason (BT-144)
allowancesobject[]—Document level allowances (BG-20)
allowances[].amountstring | numberErforderlichDocument level allowance amount (BT-92)
allowances[].vatCategory"S" | "Z" | "E" | "AE" | "K" | "G"ErforderlichVAT category of the allowance (BT-95; required per BR-32)
allowances[].vatRatestring | number—VAT rate of the allowance (BT-96)
allowances[].reasonstring—Reason (BT-97)
allowances[].reasonCodestring—Reason code, UNTDID 5189 (BT-98)
chargesobject[]—Document level charges (BG-21)
charges[].amountstring | numberErforderlichDocument level charge amount (BT-99)
charges[].vatCategory"S" | "Z" | "E" | "AE" | "K" | "G"ErforderlichVAT category of the charge (BT-102; required per BR-37)
charges[].vatRatestring | number—VAT rate of the charge (BT-103)
charges[].reasonstring—Reason (BT-104)
charges[].reasonCodestring—Reason code, UNTDID 7161 (BT-105)
paymentobject—Optional. `iban`, `bic` and `accountName` you leave out are taken from the profile's payment defaults; a field you send wins.
payment.meansCode"30" | "58"—Payment means code, UNTDID 4461 (BT-81); v1 supports credit transfer only
payment.ibanstring—Payment account IBAN (BT-84)
payment.bicstring—BIC (BT-86)
payment.accountNamestring—Payment account name (BT-85)
payment.referencestring—Remittance information (BT-83)
deliveryobject——
delivery.datestring—Actual delivery date (BT-72)
delivery.countryCodestring—Deliver-to country (BT-80)
totalsobject—Optional client-side totals; generation is rejected if they mismatch the computed totals
totals.taxExclusivestring | number—Client-asserted invoice total without VAT (BT-109)
totals.totalVatstring | number—Client-asserted total VAT (BT-110)
totals.taxInclusivestring | number—Client-asserted invoice total with VAT (BT-112)
deliverEmailDeliverEmail—Optional: email the generated invoice to these recipients. Delivery is attempted synchronously and NEVER fails the request — the invoice is archived either way.
deliverEmail.tostring[]ErforderlichRecipient addresses; lower-cased. IDN domains must be punycoded.
deliverEmail.ccstring[]—Carbon-copy addresses; lower-cased. IDN domains must be punycoded.
deliverEmail.subjectOverridestring—Replaces the generated subject line entirely.
deliverEmail.messagestring—Free-text note rendered above the standard body.

Antwort

  • 200application/json

    Idempotency-Key replay: the invoice already generated for this key and body. A replay NEVER sends email and never reports delivery — the `deliverEmail` field is absent, even if the replayed request carried a `deliverEmail` block. The original request owns the delivery; consult the invoice to see its state.

    FeldTypErforderlichBeschreibung
    idstringErforderlichInvoice id.
    numberstringErforderlichInvoice number (BT-1).
    mode"live" | "test"Erforderlich—
    status"generated" | "delivered" | "delivery_failed"Erforderlich—
    templateVersionintegerErforderlich—
    createdAtstringErforderlich—
    validationobjectErforderlich—
    validation.summarystringErforderlich—
    outputsobject[]Erforderlich—
    outputs[].kind"zugferd_pdf" | "xrechnung_xml" | "pdf"Erforderlich—
    outputs[].sha256stringErforderlich—
    outputs[].bytesintegerErforderlich—
    outputs[].urlstringErforderlichSigned GET URL (expires in <= 15 minutes).
  • 201application/json

    Invoice generated. `deliverEmail` reports the delivery outcome, or is null.

    FeldTypErforderlichBeschreibung
    idstringErforderlichInvoice id.
    numberstringErforderlichInvoice number (BT-1).
    mode"live" | "test"Erforderlich—
    status"generated" | "delivered" | "delivery_failed"Erforderlich—
    templateVersionintegerErforderlich—
    createdAtstringErforderlich—
    validationobjectErforderlich—
    validation.summarystringErforderlich—
    outputsobject[]Erforderlich—
    outputs[].kind"zugferd_pdf" | "xrechnung_xml" | "pdf"Erforderlich—
    outputs[].sha256stringErforderlich—
    outputs[].bytesintegerErforderlich—
    outputs[].urlstringErforderlichSigned GET URL (expires in <= 15 minutes).
    deliverEmailDeliverEmailResult | nullErforderlichnull unless the request carried a `deliverEmail` block.
  • 400application/problem+json

    Malformed payload or deliverEmail block (schema validation failed, after the template's profile filled in the seller and bank details); an unknown `output` kind; or "Payload is not XRechnung-ready" when `xrechnung_xml` is requested without BT-10, BT-34 or BT-49.

  • 401application/problem+json

    Missing or invalid API key (Authorization: Bearer <key>).

  • 402application/problem+json

    Monthly quota exceeded (only enforced when billing is enabled).

  • 403application/problem+json

    Recipient not allowed (`https://invoiceapi.io/problems/recipient-not-allowed`): on the Free plan `deliverEmail` may address only members of your organization, in `to` and `cc`; customers from Starter. Checked before generation, so the request uses no document. Only enforced when billing is enabled.

  • 404application/problem+json

    Template, template version, or profile not found.

  • 409application/problem+json

    Idempotency-Key reused with a different request body.

  • 422application/problem+json

    Compliance validation failed (KoSIT / veraPDF findings: each `errors[]` entry names its engine in `source`; the example is a veraPDF rejection), or a live invoice carries the sample seller VAT ID or IBAN (type https://invoiceapi.io/problems/sample-seller-data). To fix the latter, remove `seller` and the bank details (`payment.iban`, `bic`, `accountName`) from the request so the template's profile fills them, or send your own values; if the profile itself carries the sample data, fix it under /profiles.

  • 429application/problem+json

    Rate limit exceeded; see the Retry-After header.

GET/invoices

List invoices

Cursor-paginated. Test-mode invoices are excluded unless mode=test.

Parameter

FeldOrtErforderlichBeschreibung
profilequery—Filter by profile id.
fromquery—Filter by record creation time (createdAt), lower bound, inclusive (any Date.parse-able value). NOT the invoice issue date (BT-2).
toquery—Filter by record creation time (createdAt), upper bound, inclusive (any Date.parse-able value). NOT the invoice issue date (BT-2).
modequery—live (default) or test.
cursorquery—Opaque pagination cursor from a previous nextCursor.
limitquery—Page size, clamped to [1, 100] (default 25).

Antwort

  • 200application/json

    A page of invoices.

    FeldTypErforderlichBeschreibung
    dataPublicInvoice[]Erforderlich—
    data[].idstringErforderlichInvoice id.
    data[].numberstringErforderlichInvoice number (BT-1).
    data[].mode"live" | "test"Erforderlich—
    data[].status"generated" | "delivered" | "delivery_failed"Erforderlich—
    data[].templateVersionintegerErforderlich—
    data[].createdAtstringErforderlich—
    data[].validationobjectErforderlich—
    data[].validation.summarystringErforderlich—
    data[].outputsobject[]Erforderlich—
    data[].outputs[].kind"zugferd_pdf" | "xrechnung_xml" | "pdf"Erforderlich—
    data[].outputs[].sha256stringErforderlich—
    data[].outputs[].bytesintegerErforderlich—
    data[].outputs[].urlstringErforderlichSigned GET URL (expires in <= 15 minutes).
    nextCursorstring | nullErforderlich—
  • 400application/problem+json

    Invalid profile/cursor/from/to query parameter.

  • 401application/problem+json

    Missing or invalid API key (Authorization: Bearer <key>).

  • 429application/problem+json

    Rate limit exceeded; see the Retry-After header.

GET/invoices/{id}

Retrieve an invoice

Returns invoice metadata with freshly signed artifact URLs.

Parameter

FeldOrtErforderlichBeschreibung
idpathErforderlichResource id.

Antwort

  • 200application/json

    The invoice.

    FeldTypErforderlichBeschreibung
    idstringErforderlichInvoice id.
    numberstringErforderlichInvoice number (BT-1).
    mode"live" | "test"Erforderlich—
    status"generated" | "delivered" | "delivery_failed"Erforderlich—
    templateVersionintegerErforderlich—
    createdAtstringErforderlich—
    validationobjectErforderlich—
    validation.summarystringErforderlich—
    outputsobject[]Erforderlich—
    outputs[].kind"zugferd_pdf" | "xrechnung_xml" | "pdf"Erforderlich—
    outputs[].sha256stringErforderlich—
    outputs[].bytesintegerErforderlich—
    outputs[].urlstringErforderlichSigned GET URL (expires in <= 15 minutes).
  • 401application/problem+json

    Missing or invalid API key (Authorization: Bearer <key>).

  • 404application/problem+json

    No such invoice for this account.

  • 429application/problem+json

    Rate limit exceeded; see the Retry-After header.

GET/templates

List templates

Unpaginated: org template counts are small (plan-limited).

Antwort

  • 200application/json

    The account templates.

    FeldTypErforderlichBeschreibung
    dataPublicTemplate[]Erforderlich—
    data[].idstringErforderlich—
    data[].namestringErforderlich—
    data[].layoutId"classic" | "modern" | "compact" | "bold" | "minimal"Erforderlich—
    data[].versionintegerErforderlich—
    data[].profileIdstring—Present only for profile-scoped templates.
    data[].createdAtstringErforderlich—
  • 401application/problem+json

    Missing or invalid API key (Authorization: Bearer <key>).

  • 429application/problem+json

    Rate limit exceeded; see the Retry-After header.

GET/templates/{id}

Retrieve a template

Parameter

FeldOrtErforderlichBeschreibung
idpathErforderlichResource id.

Antwort

  • 200application/json

    The template.

    FeldTypErforderlichBeschreibung
    idstringErforderlich—
    namestringErforderlich—
    layoutId"classic" | "modern" | "compact" | "bold" | "minimal"Erforderlich—
    versionintegerErforderlich—
    profileIdstring—Present only for profile-scoped templates.
    createdAtstringErforderlich—
  • 401application/problem+json

    Missing or invalid API key (Authorization: Bearer <key>).

  • 404application/problem+json

    No such template for this account.

  • 429application/problem+json

    Rate limit exceeded; see the Retry-After header.

POST/validate

Validate an invoice document

Validates an XRechnung/UBL/CII XML or a ZUGFeRD PDF against KoSIT (Schematron) and veraPDF. Quota-exempt. Findings are translated to DE/EN.

Akzeptierte Content-Types

application/xmlapplication/pdfmultipart/form-data
FeldTypErforderlichBeschreibung
filestringErforderlichThe XML or PDF document to validate.

Antwort

  • 200application/json

    The validation report.

    FeldTypErforderlichBeschreibung
    validationobjectErforderlichRaw compliance-engine validation result (engine-specific shape).
    versionsobject——
    findingsobject[]Erforderlich—
    findings[].pathstringErforderlich—
    findings[].btstring——
    findings[].codestring——
    findings[].messageobjectErforderlich—
    findings[].message.destringErforderlich—
    findings[].message.enstringErforderlich—
    findings[].untranslatedboolean——
  • 400application/problem+json

    Empty body, or the compliance engine could not decode it.

  • 401application/problem+json

    Missing or invalid API key (Authorization: Bearer <key>).

  • 429application/problem+json

    Rate limit exceeded; see the Retry-After header.

  • 502application/problem+json

    The compliance engine is unreachable.

GET/health

Liveness and dependency reachability

Public. Reports compliance-engine reachability and engine versions.

Antwort

  • 200application/json

    Service health.

    FeldTypErforderlichBeschreibung
    status"ok" | "degraded"Erforderlich—
    compliance"ok" | "unreachable"Erforderlich—
    versionsobject——