---
title: "ZUGFeRD-Rechnung erzeugen (Abo, Credits oder Freikontingent)"
method: POST
path: "/invoices"
tags: ["Rechnungen"]
---

# ZUGFeRD-Rechnung erzeugen (Abo, Credits oder Freikontingent)

`POST /invoices`

## Request

- Base URL: `https://finisma.de/api/v1`
- URL: `https://finisma.de/api/v1/invoices`
- Auth: one of:
  - HTTP bearer
  - OAuth 2 (authorization code, authorization URL `https://finisma.de/api/oauth/authorize`, token URL `https://finisma.de/api/oauth/token`, scopes: `invoice:verify`, `invoice:create`)

Bettet die EN-16931-Daten als CII-XML in die übergebene PDF ein und liefert die fertige ZUGFeRD-PDF (PDF/A-3). Ohne PDF setzt finisma die Rechnung aus den Daten, optional mit Logo (Part 'logo' bzw. logo_base64; PNG, JPEG oder SVG, max. 500 KB) und Sprache (lang: de oder en); die fertige Datei durchläuft dann vor der Auslieferung die autoritative Prüfung (PDF/A-3, EN 16931). Die Anfrage kommt als multipart/form-data oder als application/json im Format des MCP-Tools create_zugferd. Standardantwort ist die binäre PDF; mit 'Accept: application/json' kommt stattdessen { pdf_base64, bytes }. Ohne Abo zahlt zuerst das Guthaben (1 Credit je Rechnung, ohne Wasserzeichen und ohne Tageslimit; Saldo über GET /me). Ohne Guthaben kostenlos mit Konto: die PDF trägt dann das finisma-Prüfsiegel als Wasserzeichen, standardmäßig bis zu 5 Rechnungen pro Tag (danach 429 free_quota_exhausted). Mit 'format=xml' (oder 'Accept: application/xml') kommt nur das CII-XML: kein Träger-PDF nötig, kein Einbettungsschritt, deutlich schneller. Dieser Weg erfordert ein aktives Abo oder Guthaben, weil das kostenlose Tageskontingent mit dem Prüfsiegel als Wasserzeichen arbeitet und ein XML keines tragen kann.

## Query parameters

- `format` 'pdf' | 'xml'

## Request body

- object: Dasselbe Format wie das MCP-Tool create_zugferd. Dateien kommen hier Base64-kodiert.
  - `invoice` Invoice, required
    - `invoiceNumber` string, required
    - `profile` 'en16931' | 'xrechnung'
    - `documentTypeCode` string
    - `precedingInvoiceNumber` string
    - `precedingInvoiceDate` string
    - `issueDate` string, required
    - `dueDate` string
    - `deliveryDate` string
    - `deliveryCountryCode` string
    - `delivery` object
      - `name` string
      - `gln` string
      - `address` object
        - `line1` string
        - `line2` string
        - `postalCode` string
        - `city` string
        - `countryCode` string
    - `currency` string
    - `buyerReference` string
    - `costCenter` string
    - `purchaseOrderReference` string
    - `contractReference` string
    - `invoicingPeriod` object
      - `start` string
      - `end` string
    - `projectReference` string
    - `despatchAdviceRef` string
    - `receivingAdviceRef` string
    - `allowanceCharges` object[]
      - `charge` boolean, required: true = Zuschlag (BG-21), false = Abzug/Nachlass (BG-20).
      - `amount` number: BT-92/BT-99: Betrag ohne Vorzeichen. Darf fehlen, wenn percent gesetzt ist: dann gilt round2(basisAmount × percent / 100).
      - `basisAmount` number: BT-93/BT-100: Grundbetrag des Prozentsatzes. Ohne Angabe die Summe der lineNetAmount aller Positionen mit ratePercent (bei gemischten Kategorien desselben Satzes nur die mit categoryCode).
      - `percent` number: BT-94/BT-101: Prozentsatz, z. B. 2 für 2 % Nachlass.
      - `categoryCode` string
      - `ratePercent` number: BT-96/BT-103: Steuersatz in Prozent. Darf beim Prozent-Eintrag ohne basisAmount fehlen, wenn alle Positionen denselben Satz haben.
      - `reason` string
      - `reasonCode` string
    - `seller` object, required
      - `name` string, required
      - `vatId` string
      - `gln` string
      - `registrationId` string: BT-30 (Verkäufer) / BT-47 (Käufer): Handelsregisternummer bzw. Registerkennung der Partei, z. B. "HRB 12345, Amtsgericht München". Nur angeben, wenn sie auf der Rechnung steht. Beim Käufer reicht sie bei Reverse Charge (Kategorie AE) statt der USt-IdNr., bei innergemeinschaftlicher Lieferung (K) nicht.
      - `address` object
        - `line1` string
        - `line2` string
        - `city` string
        - `postalCode` string
        - `countryCode` string
      - `contact` object
        - `name` string
        - `email` string
        - `phone` string
      - `electronicAddress` object
        - `id` string, required
        - `scheme` string
      - `customerAssignedId` string
    - `buyer` object, required
      - `name` string, required
      - `vatId` string
      - `gln` string
      - `registrationId` string: BT-30 (Verkäufer) / BT-47 (Käufer): Handelsregisternummer bzw. Registerkennung der Partei, z. B. "HRB 12345, Amtsgericht München". Nur angeben, wenn sie auf der Rechnung steht. Beim Käufer reicht sie bei Reverse Charge (Kategorie AE) statt der USt-IdNr., bei innergemeinschaftlicher Lieferung (K) nicht.
      - `address` object
        - `line1` string
        - `line2` string
        - `city` string
        - `postalCode` string
        - `countryCode` string
      - `contact` object
        - `name` string
        - `email` string
        - `phone` string
      - `electronicAddress` object
        - `id` string, required
        - `scheme` string
    - `lines` object[], required
      - `name` string, required
      - `quantity` number, required
      - `unitCode` string
      - `sellerArticleId` string
      - `buyerArticleId` string
      - `globalArticleId` string
      - `globalArticleScheme` string
      - `unitPriceNet` number, required
      - `vatRatePercent` number, required
      - `categoryCode` string
      - `allowanceCharges` object[]
        - `charge` boolean, required: true = Zuschlag (BG-28), false = Abzug/Rabatt (BG-27).
        - `amount` number: BT-136/BT-141: Betrag ohne Vorzeichen. Darf fehlen, wenn percent gesetzt ist: dann gilt round2(basisAmount × percent / 100).
        - `basisAmount` number: BT-137/BT-142: Grundbetrag des Prozentsatzes. Ohne Angabe Menge × unitPriceNet der Position (je Eintrag, nicht gestaffelt).
        - `percent` number: BT-138/BT-143: Prozentsatz, z. B. 10 für 10 % Rabatt.
        - `reason` string
        - `reasonCode` string
      - `lineNetAmount` number, required
    - `vatBreakdown` object[], required
      - `ratePercent` number, required
      - `basisAmount` number, required
      - `taxAmount` number, required
      - `categoryCode` string
      - `exemptionReason` string
      - `exemptionReasonCode` string
    - `totalNet` number, required
    - `totalVat` number, required
    - `totalGross` number, required
    - `paidAmount` number
    - `notes` union[]
      - union
        - string
        - object
          - `text` string, required
          - `subjectCode` string
    - `taxCurrencyCode` string
    - `totalVatInTaxCurrency` number
    - `payee` object
      - `name` string, required
      - `gln` string
      - `registrationId` string
    - `payment` object
      - `terms` string
      - `iban` string
      - `bic` string
      - `reference` string
      - `meansCode` string
      - `mandateId` string
      - `creditorId` string
      - `debitedIban` string
      - `accountName` string
      - `discountPercent` number
      - `discountDays` integer
  - `pdf_base64` string, byte: Optional: die visuelle Rechnungs-PDF (max. 25 MB). Fehlt sie, wird die Rechnung aus den Daten gesetzt.
  - `logo_base64` string, byte: Optionales Logo (PNG, JPEG oder SVG, max. 500 KB), Base64 oder data:-URI. Nur ohne pdf_base64.
  - `logo_mime` 'image/png' | 'image/jpeg' | 'image/svg+xml': Optional; der Typ wird sonst aus dem Inhalt erkannt.
  - `lang` 'de' | 'en'
  - `filename` string: Ausgabedateiname (Standard: invoice.pdf).
  - `attachments` object[]: Optionale Anhänge (PDF, PNG, JPEG, CSV, XLSX, ODS, XML; je max. 10 MB).
    - `filename` string, required
    - `mime_type` string
    - `description` string: Beschreibung (BT-123).
    - `data_base64` string, byte, required

## Response `200`

Erzeugte ZUGFeRD-PDF, bei format=xml das CII-XML. Die Größe der Antwort steht zusätzlich im Header X-Invoice-Bytes.

- union
  - object: Standardweg (format=pdf).
    - `pdf_base64` string, byte, required
    - `bytes` integer, required
  - object: XML-Weg (format=xml).
    - `xml` string, required: Das CII-XML als Text.
    - `bytes` integer, required: Länge des XML in Bytes (UTF-8).

## Other responses

- `400`: Ungültige Eingabe.
- `401`: Kein oder ungültiges Credential.
- `403`: Kein aktives Abo. Bei format=xml gilt das Freikontingent nicht, weil ein XML kein Prüfsiegel als Wasserzeichen tragen kann.
- `429`: Rate-Limit oder kostenloses Tageskontingent erschöpft (siehe Retry-After).
- `502`: Fehler im nachgelagerten Dienst.

---

[API](https://skmtc.dev/finisma/apis/finisma-rest-api.md) · [All operations](https://skmtc.dev/finisma/apis/finisma-rest-api/llms.txt) · [OpenAPI document](https://skmtc.dev/finisma/apis/finisma-rest-api/revisions/c1a9acfab69b?raw)
