Appearance
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
- anybill activates the e-invoice module for the merchant (see the note below).
- The POS sends the receipt with
POST /v3/billand setsbill.misc.extension:anybill.receiptTypetoEInvoice. Optionally, it adds the customer data from its CRM inbill.misc.extension:anybill.merchantCustomObject(see below). - The buyer opens the receipt URL, e.g. by scanning the QR code. The receipt page offers to complete the e-invoice data.
- 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.
- 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"
}
}
}
}receiptTypeacceptsReceipt(default),DeliveryNoteandEInvoice. The string name is recommended; the integer value2is accepted as well.- Set
EInvoiceon every receipt for which the buyer should be able to request an e-invoice. Receipts sent withReceiptshow 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
EInvoiceon 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:
| Field | Type | Description |
|---|---|---|
type | string | Identifier 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. |
contentType | string | Format of content, e.g. application/json or application/xml. |
content | string | The 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:
merchantCustomObjectis optional and only relevant for receipts withreceiptTypeEInvoice.- 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
typeand the structure ofcontentstable across all stores and POS versions that send the same data, so that one mapping covers all of them. contentcontains 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 element | Taken from |
|---|---|
| Invoice number | bill.head.number. If it is missing, the anybill receipt id is used, so send the POS receipt number. |
| Invoice date and delivery date | bill.head.date |
| Seller name, address and VAT ID | bill.head.seller (name, vatId, address.street, address.postalCode, address.city). If seller is omitted, the store data stored at anybill is used. |
| Line items | Every 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. |
| Allowances | Every discount line in bill.data.lines: text, fullAmountInclVat and vatAmounts[0].percentage. |
| VAT breakdown and totals | Recalculated per VAT rate from the net amounts of the item lines minus the allowances. |
| Payment | The 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
vatAmountsentry withpercentage,exclVatandinclVatfor the whole line (after line discounts). Lines withoutvatAmountslead 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 negativefullAmountInclVatand the VAT rate invatAmounts. - The recalculated totals have to match
bill.data.vatAmountsandbill.data.fullAmountInclVatof 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
- Ask anybill to enable the e-invoice module for your Staging merchant.
- Send a receipt with
receiptTypeEInvoicetohttps://vendor.stg.anybill.de/api/v3/billwithoutuserIdentification(see curl examples). - Open the
urlfrom the response, complete the e-invoice data and download both a ZUGFeRD PDF and an XRechnung XML. - Compare the invoice number, seller, line items, VAT breakdown and total with the receipt sent by the POS.