Skip to content

E-Invoice (ZUGFeRD / XRechnung) ​

Business customers often need a structured, machine-readable invoice instead of a receipt. anybill can turn a receipt sent via POST /v3/bill into an e-invoice in the ZUGFeRD format (PDF with embedded XML) or the XRechnung format (XML). The POS does not call an additional endpoint: it marks the receipt as an e-invoice and can optionally pass the customer data it already knows. The buyer adds missing recipient data on the receipt page and downloads the e-invoice there.

How it works ​

  1. anybill activates the e-invoice module for the merchant (see the note below).
  2. The POS sends the receipt with POST /v3/bill and sets bill.misc.extension:anybill.receiptType to EInvoice. Optionally, it adds the customer data from its CRM in bill.misc.extension:anybill.merchantCustomObject (see below).
  3. The buyer opens the receipt URL, e.g. by scanning the QR code. The receipt page offers to complete the e-invoice data.
  4. The buyer selects the format (ZUGFeRD or XRechnung) and enters the invoice recipient: name, email address, phone number and address, and optionally a VAT ID, a Leitweg-ID and a scheme ID.
  5. anybill builds the e-invoice from the receipt data and the recipient data. The buyer downloads it from the receipt page as a ZUGFeRD PDF or as an XRechnung XML file.

The recipient data can be entered only once per receipt. A second attempt is rejected, so the e-invoice that was issued cannot be changed afterwards.

WARNING

The e-invoice module has to be enabled per merchant on the anybill side, both on Staging and on Production. If it is relevant for your integration, please contact dev@anybill.de or your anybill contact person.

Marking a receipt as e-invoice ​

Set the receipt type in the anybill extension of the misc object:

json
{
  "storeId": "3QT1su7Wtl",
  "bill": {
    "head": { "...": "..." },
    "data": { "...": "..." },
    "security": { "...": "..." },
    "misc": {
      "extension:anybill": {
        "receiptType": "EInvoice"
      }
    }
  }
}
  • receiptType accepts Receipt (default), DeliveryNote and EInvoice. The string name is recommended; the integer value 2 is accepted as well.
  • Set EInvoice on every receipt for which the buyer should be able to request an e-invoice. Receipts sent with Receipt show no e-invoice option on the receipt page.
  • The merchant can also have all of its receipts marked as e-invoices by default. In that case anybill sets EInvoice on every incoming receipt of the merchant, regardless of the value the POS sends.

The e-invoice is requested on the page behind the receipt URL. It is therefore available for anonymous receipts, for which POST /v3/bill returns a response of type url (see Response objects). Receipts that are assigned to a consumer directly via userIdentification.externalId have no receipt URL and are not offered as e-invoices.

Sending customer data from the POS (merchantCustomObject) ​

Planned

merchantCustomObject is not processed by the Vendor API yet. Until it is available, the API accepts receipts that contain the field and ignores it. Please contact dev@anybill.de or your anybill contact person before you rely on it.

Many POS systems already know the business customer at checkout, e.g. from a scanned customer card or a CRM lookup. Data such as the company name, the invoice address, the customer's VAT ID or an order reference is usually not part of the receipt schema. bill.misc.extension:anybill.merchantCustomObject transports this data together with the receipt, so that the buyer does not have to enter it on the receipt page.

The object is a small container with three fields:

FieldTypeDescription
typestringIdentifier of the content structure, chosen by the POS system. Use a stable name that includes a version, e.g. examplepos.customer.v1, and change the version when the structure changes.
contentTypestringFormat of content, e.g. application/json or application/xml.
contentstringThe data itself as text. JSON content is sent as a serialised (escaped) string, not as a nested JSON object.

The structure of content is entirely up to the POS system. anybill does not prescribe field names, nesting, naming conventions or a format. Send the data the way your POS or CRM already holds it; there is no need to convert it into an anybill model. anybill sets up the mapping from your structure to the e-invoice fields together with you, once per type. Content with a type for which no mapping exists is ignored for the e-invoice.

Example: a POS system that holds the following customer record for the buyer

json
{
  "customerNumber": "K-104711",
  "companyName": "Example Trading GmbH",
  "contactPerson": "Erika Example",
  "invoiceEmail": "invoices@example-trading.de",
  "invoiceAddress": {
    "street": "Sample Street 12",
    "postalCode": "10115",
    "city": "Berlin",
    "countryCode": "DE"
  },
  "vatId": "DE123456789",
  "purchaseOrderReference": "PO-2026-0815"
}

sends it as the content of the merchantCustomObject:

json
{
  "storeId": "3QT1su7Wtl",
  "bill": {
    "head": { "...": "..." },
    "data": { "...": "..." },
    "security": { "...": "..." },
    "misc": {
      "extension:anybill": {
        "receiptType": "EInvoice",
        "merchantCustomObject": {
          "type": "examplepos.customer.v1",
          "contentType": "application/json",
          "content": "{\"customerNumber\":\"K-104711\",\"companyName\":\"Example Trading GmbH\",\"contactPerson\":\"Erika Example\",\"invoiceEmail\":\"invoices@example-trading.de\",\"invoiceAddress\":{\"street\":\"Sample Street 12\",\"postalCode\":\"10115\",\"city\":\"Berlin\",\"countryCode\":\"DE\"},\"vatId\":\"DE123456789\",\"purchaseOrderReference\":\"PO-2026-0815\"}"
        }
      }
    }
  }
}

Important rules:

  • merchantCustomObject is optional and only relevant for receipts with receiptTypeEInvoice.
  • It complements the receipt, it does not replace it: seller, line items, VAT and totals are always taken from the regular receipt fields described below.
  • Keep type and the structure of content stable across all stores and POS versions that send the same data, so that one mapping covers all of them.
  • content contains personal data. Send only what the e-invoice needs and leave out unrelated CRM data such as credit limits, loyalty balances or marketing attributes.
  • If data is missing in content, the buyer can still complete it on the receipt page.

Receipt content used for the e-invoice ​

The e-invoice is built from the receipt as stored by anybill. The following fields determine its content, so they must be complete and consistent for e-invoice receipts:

E-invoice elementTaken from
Invoice numberbill.head.number. If it is missing, the anybill receipt id is used, so send the POS receipt number.
Invoice date and delivery datebill.head.date
Seller name, address and VAT IDbill.head.seller (name, vatId, address.street, address.postalCode, address.city). If seller is omitted, the store data stored at anybill is used.
Line itemsEvery default line in bill.data.lines: text, item.quantity and the first entry of vatAmounts (percentage, exclVat, inclVat). Net and gross unit prices are derived from these amounts and the quantity.
AllowancesEvery discount line in bill.data.lines: text, fullAmountInclVat and vatAmounts[0].percentage.
VAT breakdown and totalsRecalculated per VAT rate from the net amounts of the item lines minus the allowances.
PaymentThe e-invoice is marked as paid: the prepaid amount equals the total, the amount due is 0.

Important rules:

  • Every default line carries exactly one vatAmounts entry with percentage, exclVat and inclVat for the whole line (after line discounts). Lines without vatAmounts lead to wrong amounts on the e-invoice.
  • Receipt-level discounts that should appear as allowances are sent as discount lines (extension:anybill.type = discount) with a negative fullAmountInclVat and the VAT rate in vatAmounts.
  • The recalculated totals have to match bill.data.vatAmounts and bill.data.fullAmountInclVat of the receipt. Check this with a few receipts that combine several VAT rates and discounts.
  • Text lines and key/value lines are shown on the PDF receipt but are not part of the structured invoice data.
  • E-invoices are currently generated in EUR for stores in Germany. All items are reported in the standard VAT category with their percentage; receipts with tax-exempt items (0 %) are not suitable for e-invoices yet.

Testing on Staging ​

  1. Ask anybill to enable the e-invoice module for your Staging merchant.
  2. Send a receipt with receiptType EInvoice to https://vendor.stg.anybill.de/api/v3/bill without userIdentification (see curl examples).
  3. Open the url from the response, complete the e-invoice data and download both a ZUGFeRD PDF and an XRechnung XML.
  4. Compare the invoice number, seller, line items, VAT breakdown and total with the receipt sent by the POS.

Built 2026-10-06 19:46 CEST from commit 4087b69