
# Bill Data Model

The receipt payload sent to [`POST /v3/bill`](https://developer.anybill.de/vendor_api/bill_endpoints) is
described here: first the structure of the `BillDTO`, then the reference of the
values its fields accept.

## BillDTO object
Our BillDTO object bundles all receipt information, which are based on the DFKA standard with anybill specific extensions.
As root object of the receipt it links to five different categories of data:
- <b>Cash register*</b> Information about the cash register.
- <b>Head*</b> Head data of the receipt.
- <b>Data*</b> Receipt data.
- <b>Security*</b> Data to secure the receipt via TSE.
- <b>Misc</b> Optional additional data.  

Besides these objects the root carries two scalar fields: `id` (see below) and the optional
`countryCode`, the ISO 3166-1 alpha-3 code of the country the receipt was issued in
(e.g. `DEU`, `FRA`). It selects the country-specific validation rules, for example the French
rules described on the [Fiscalization](https://developer.anybill.de/vendor_api/fiscalization) page. If it is omitted, the
country of the store's address is used.

To guarantee that only valid information is added to the anybill system, a variety of validation rules is executed. If the validation of the receipt object fails a response with a HTTP status code of 400 is returned with a description of validation errors in the body of the request.  
Most of the rules are set in the open api specification, but some rules are far too complex in order to be able to be represented in the open api specification.

### Id
This is `null` by default to let anybill's backend create a unique UUID for each receipt.

The Receipt Id can be set by the POS under two situations:
1. Set an Id that has already been created in advance via the POST `/v3/bill/url` endpoint (recommended from a UX perspective)
2. You have the [Self-generated Receipt ID](https://developer.anybill.de/vendor_api/bill_endpoints#self-generated-receipt-id) feature enabled.

### Cash Register
Contains data about the cash register: `serialNumber` (max. 256 characters), `number` and `version`. The object itself is mandatory, its fields are optional; the serial number is the one that is used by anybill.

### Head
Contains common data of the head of a receipt. E.g. invoice number, date, seller or buyer information.  
Important rules:
- If `deliveryPeriodStart` is set `deliveryPeriodEnd` must be set too or vice versa.
- `date` must be after 1900-01-01
- The `seller` object overrides the internal information set in the anybill system. E.g. if some information about the store has temporarily changed that is not yet updated in the anybill system this can be used to override the defaults. If `seller` is sent, `name` (max. 100 characters) and `vatId` (prefixed with the two-letter country code, e.g. `DE123456789`) are mandatory, and a sent `address` must contain `street`, `postalCode` and `city`.
- `id` and `number` of the head are limited to 128 characters, `buyerText` to 250.

### Data
Contains the most important information for the buyer. The items he has bought and the value of the shopping cart.
Important rules:
- `currency` must be a valid three digit [ISO 4217](https://de.wikipedia.org/wiki/ISO_4217) code.
- `fullAmountInclVat` uses at most 2 decimal places.
- Each `vatAmount` must be unique by the percentage. If you need several entries with the
  same percentage (e.g. different tax groups), give each entry a `groupId` (1–20 letters or
  digits, unique across `vatAmounts`) and reference it from the lines. Either all or none of
  the entries in `vatAmounts` carry a `groupId`; a `groupId` used in a line or discount must
  exist in `data.vatAmounts`.

Important rules `paymentTypes`:
- If `foreignAmount` is set `foreignCurrency` must be set and vice versa.
- `foreignCurrency` must be a valid three digit [ISO 4217](https://de.wikipedia.org/wiki/ISO_4217) code.
- The anybill extension must not be null.
- Only the matching `paymentDetails` for the `type` set in the anybill extension will be read. 

Important rules `lines`:
- The anybill extension must not be null.
- `text` is mandatory for default, text and discount lines (max. 100 characters).
- DefaultLine:
  - `item` is mandatory with `number` (max. 50 characters), `quantity` (max. 5 decimal places) and `pricePerUnit`.
  - `item.quantityMeasure` is mandatory unless `item.extension:anybill.customQuantityMeasure` (max. 32 characters) is used for a unit that is not in the list below.
  - Each `vatAmount` must be unique by the percentage (or by `groupId`, see above).
  - Each `vatAmount` set for a discount in the anybill extensions must have a corresponding `vatAmount` set in the default line.
  - Optional item details in `item.extension:anybill`: `gtin` (see below), `plu` (4–5 characters), `serialNumber` (max. 50 characters), `externalCategory` (hierarchy separated by `>`, e.g. `Food > Dairy > Cheese`) and `pricePerUnitBeforeDiscounts`.

Important rules for data extensions (`data.extension:anybill`):
- If `barcode` is set on a discount `barcodeType` must be set and vice versa.
- Each `vatAmount` must be unique by the percentage.
- Each discount must have a unique `id`
- `fullAmountInclVatBeforeDiscounts` is mandatory as soon as `discounts` is not empty.
- `tip` optionally carries the tip amount (up to 5 decimal places).
- `disableVatAmountsValidation` (default `false`) switches off the server-side check that `data.vatAmounts` must not be empty. Use it only for receipts that legitimately carry no VAT information.
- `equivalentValueName` and `fullEquivalentValue` (plus `equivalentValue` on lines, discounts and payment types) optionally display the amounts in a second currency, e.g. during a currency changeover. They are free text and not validated.

### Security
The security object contains the fiscalization data required in the different countries.
It consists of the `fiscalization` object, whose `type` attribute selects the country-specific structure, and the anybill extension with the flags `required` and `failure`.

Global important rules:
- `security` must always be sent, even if no fiscalization data is available.
- `fiscalization` must be set unless `failure` is set to `true` in the security extension (fiscal unit unavailable).
- `fiscalization` must be set unless `required` is set to `false` in the security extension (no fiscalization obligation in the country).
- If the security extension is omitted, `required` defaults to `true` and `fiscalization` is mandatory.
- If `type` is omitted, the fiscalization object is interpreted as `Tse`. The value is case-sensitive.

The mandatory fields of each fiscalization type, complete examples and the deprecated field names are described on the [Fiscalization](https://developer.anybill.de/vendor_api/fiscalization) page.

### Misc
Optional additional data: `footerText` (max. 4096 characters), `additionalReceipts` (see
[Terminal customer receipt](#terminal-customer-receipt)) and the anybill extension.

Important rules misc extensions (`misc.extension:anybill`):
- If `returnBarcode` is set `returnBarcodeType` must be set (`Ean8`, `Ean13`, `Text`, `Qr`, `Barcode`, `Code128ABarcode`, `Code128BBarcode`, `Code128CBarcode`). For `Ean8`/`Ean13` the barcode must be a valid EAN.
- `receiptType` (default `Receipt`) distinguishes `Receipt`, `DeliveryNote` and `EInvoice`.
- `receiptLanguage` is an ISO 639-1 code (e.g. `de`) and controls the language of the rendered receipt.
- `isHospitalityBill` marks a hospitality receipt (restaurant, hotel) so that it is rendered with the hospitality-specific sections.
- `cashierName` (max. 64 characters) is displayed on the receipt.
- `afterSalesCoupons`, `customSections`, `couponingInformation` and `countrySpecificAttributes` are described in [Bill Examples](https://developer.anybill.de/vendor_api/bill_examples), [Loyalty Endpoints](https://developer.anybill.de/vendor_api/loyalty_endpoints) and [Fiscalization](https://developer.anybill.de/vendor_api/fiscalization).

## Description of possible values
For better understanding some values are described below.

Values for enumerations like QuantityMeasure, PaymentType or the line and fiscalization `type` discriminators are accepted as string names (recommended) or as integer values. Use the string names in new integrations: they are self-explanatory and are not affected when new members are added to an enumeration. The tables below show both.

## Lines
There are four types of lines. The type of the line is determined with the `type`-discriminator in the extension of the line (`extension:anybill.type`, case-insensitive). Possible discriminators:
- `default` or no value (`null`) for default lines
- `text` for text only lines
- `discount` for discount line
- `keyValue` for a key/value line

### Default line
The default line represents an item or service that was sold. You can add useful information in the `additionalText` (max. 1028 characters).

The GTIN/EAN of the item goes into `extension:anybill.gtin` of the item. It accepts 1 to 14 characters, so a merchant-specific article number for goods without a GTIN (loose fruit and vegetables, for example) can be sent as well. Values longer than 14 characters are not rejected but silently dropped: the request succeeds and the receipt is stored without a GTIN.

### Text line
The text line can be used to add text in between other lines. This can be as easy as a product group separation or further useful information.

### Discount line
The discount line displays a discount that is applied to the whole receipt. Therefore the values must have a negative balance.

### Key/value line
The key/value line renders a short label and value pair between the other lines, e.g.
`"key": "Table", "value": "12"`. Both `key` and `value` are mandatory and limited to
20 characters each so that they fit on one receipt line.

``` json
{
  "key": "Table",
  "value": "12",
  "extension:anybill": {
    "type": "keyValue",
    "sequenceNumber": 4
  }
}
```

## Possible QuantityMeasure values
The quantity measure describes the type of quantity of the line item. For bananas, whose price is often measured by weight, you would choose 1 (kilogram) and for t-shirts that are sold per unit you would choose 0 (count).

Name | Value |                   
-------------|-------|
Count        | 0     |
Kilogram     | 1     |
Lbs          | 2     |
Meters       | 3     |
Inches       | 4     |
Liter        | 5     |
CubicMeters  | 6     |
SquareMeters | 7     |
KilowattHour | 8     |
Seconds      | 9     |

> **Example:**
>
> qantityMeasure: "Count"

## PaymentTypes
The payment type describes the type of payment used in the payment type information object. The type used should be specified further with the name-property. E.g. for a payment with visa the payment type should be `CardPayment` (13) and name should be "Visa". The name should be human readable and will be displayed for the user.

`CardPayment` replaces the card-specific values `CreditCard`, `Girocard`, `Maestro` and `VisaElectron`, which are deprecated; put the card brand into `name` instead. An unknown or missing `type` is interpreted as `Miscellaneous`.

### Possible PaymentType values

| Name                      | Value |
|---------------------------| ----- |
| Miscellaneous             | 0     |
| Cash                      | 1     |
| DirectDebit               | 2     |
| CreditCard (Deprecated)   | 3     |
| OnlinePayment             | 4     |
| GiftCard                  | 5     |
| BankTransfer              | 6     |
| Check                     | 7     |
| LoyaltyCard               | 8     |
| Girocard (Deprecated)     | 9     |
| Elv                       | 10    |
| Maestro (Deprecated)      | 11    |
| VisaElectron (Deprecated) | 12    |
| CardPayment               | 13    |

> **Example:**
>
> type: "Cash"

For every payment type, except for miscellaneous, additional details can be provided in the paymentDetails-property. E.g. for the cash payment type the CashPaymentDetails-object can be optionally used. Any details given, that do not match the correct payment type will be ignored.

Terminal-based payment types (`CardPayment`, `BankTransfer`, `DirectDebit`/`Elv`) share the
terminal fields `terminalId` (max. 30 characters), `terminalDateTime` (ISO 8601, preferred),
`terminalDate`/`terminalTime` (legacy alternatives in the formats `dd.MM.yyyy`, `dd.MM.yy`, `MMdd`
and `HH:mm:ss`, `HHmmss`), `traceNumber` (integer), `cardPan` (4–23 characters),
`cardExpiryDate` (`MM/yy`) and `authCode`.

::: details Check payment details
``` json
{
  "name": "Check",
  "amount": 112.90,
  "foreignAmount": null,
  "foreignCurrency": null,
  "extension:anybill": {
     "type": "Check",
     "paymentDetails": {
        "drawee": "The person in whose favour the cheque",
        "payee": "Person who receives payment",
        "dateOfIssue": "Date and Time in iso 8601",
        "drawer": "The one who has written out the cheque",
        "sortCode": "",
        "accountNumber": ""
     }
  }
} 
```
::: 

::: details BankTransfer payment details
``` json
{
  "name": "Bank XY Transfer",
  "amount": 112.90,
  "foreignAmount": null,
  "foreignCurrency": null,
  "extension:anybill": {
     "type": "BankTransfer",
     "paymentDetails": {
        "purposeOfUsage": "Some usage description",
        "iban": "DE 1234",
        "bic": "1342",
        "accountHolderName": "MS Pos GmbH",
        "accountNumber": "1234",
        "bankName": "Bank Name",
        "bankAddress": "Some Address",
        "sortCode": "1234",
        "routingNumber": "abcd",
        "ifscCode": "1234",
        "routingCode": "abcd",
        "terminalId": "1234",
        "terminalDateTime": "2020-07-20T12:37:04+02:00",
        "traceNumber": 4321,
        "cardPan": "The primary account number",
        "cardExpiryDate": "12/27",
        "authCode": "123456"
    }
  }
} 
```
::: 

::: details Cash payment details
``` json
{
  "name": "Cash",
  "amount": 112.90,
  "foreignAmount": null,
  "foreignCurrency": null,
  "extension:anybill": {
     "type": "Cash",
     "paymentDetails": {
        "amountGiven": 120.00,
        "amountReturned": 17.10
    }
  }
} 
```
::: 

::: details CardPayment payment details (CardPayment, Girocard, Maestro, VisaElectron, CreditCard)
``` json
{
  "name": "Visa",
  "amount": 112.90,
  "foreignAmount": null,
  "foreignCurrency": null,
  "extension:anybill": {
     "type": "CardPayment",
     "paymentDetails": {
        "cardNumber": "123456",
        "bankName": "Some Bank",
        "terminalId": "1234",
        "terminalDateTime": "2020-07-20T12:37:04+02:00",
        "traceNumber": 4321,
        "cardPan": "The primary account number",
        "cardExpiryDate": "12/27",
        "authCode": "123456"
    }
  }
} 
```
::: 

::: details DirectDebit payment details (DirectDebit, Elv)
``` json
{
  "name": "Elv",
  "amount": 112.90,
  "foreignAmount": null,
  "foreignCurrency": null,
  "extension:anybill": {
     "type": "Elv",
     "paymentDetails": {
        "sepaCreditorId": "",
        "sepaMandateReference": "",
        "cardNumber": "",
        "bankName": "",
        "terminalId": "1234",
        "terminalDateTime": "2020-07-20T12:37:04+02:00",
        "traceNumber": 4321,
        "cardPan": "The primary account number",
        "cardExpiryDate": "12/27",
        "authCode": "123456"
    }
  }
} 
```
::: 

::: details GiftCard payment details
``` json
{
  "name": "Geschenkkarte",
  "amount": 112.90,
  "foreignAmount": null,
  "foreignCurrency": null,
  "extension:anybill": {
     "type": "GiftCard",
     "paymentDetails": {
        "initialBalance": 200.00,
        "remainingBalance": 87.10,
        "dateOfExpiry": "Date and Time in iso 8601"
    }
  }
} 
```
::: 

::: details LoyaltyCard payment details
``` json
{
  "name": "Shop XY Card",
  "amount": 112.90,
  "foreignAmount": null,
  "foreignCurrency": null,
  "extension:anybill": {
     "type": "LoyaltyCard",
     "paymentDetails": {
        "name": "MS-Pos Loyalty Card",
        "accountNumber": "21341234",
        "pointsUsed": 11290.0,
        "pointsLeft": 1293403.0,
        "pointsGained": 32.0
    }
  }
} 
```
::: 

::: details OnlinePayment payment details 
``` json
{
  "name": "Paypal",
  "amount": 112.90,
  "foreignAmount": null,
  "foreignCurrency": null,
  "extension:anybill": {
     "type": "OnlinePayment",
     "paymentDetails": {
        "senderAccountName": "CSymeoudakis@mspos.net",
        "recipientAccountName": "yourmail@anybill.de",
        "transactionId": "1293403"
    }
  }
} 
```
:::

## Terminal customer receipt
The Terminal text attribute is available on `bill.misc.additonalReceipts` and have to be filled with the payment information text which is provided by the terminal.
This is an example of the terminal text:

> **Tip: Terminal customer receipt example**
> ``` json
> "additionalReceipts": [
>     {
>         "contentType": "text/plain",
>         "content": "Terminal-ID :   61400710
>         TA-Nr 000584    BNr 0062
>         
>              Kartenzahlung
>             Visa kontaktlos
>                   Visa
>         
>         EUR 10,00
>          
>         PAN     ############2515
>         Karte 0
>         EMV-AID   A0000000031010
>         VU-Nr             123456
>         Genehmigungs-Nr   123456
>         Datum 19.02.20 15:38 Uhr
>         EMV-Daten
>         0000000000/0000///"
>     }
> ],
> ```

### Terminal merchant receipt
The Terminal text attribute is available on `bill.misc.additonalReceipts` and have to be filled with the payment information text which is provided by the terminal.
This is an example of the terminal text:

> **Tip: Terminal merchant receipt example**
> ``` json
> "additionalReceipts": [
>    ...,
>     {
>         "type": "VendorReceipt",
>         "contentType": "text/plain",
>         "content": "ICAgICAgLUgtw4QtTi1ELUwtRS1SLUItRS1MLUUtRy1cblxuICAgICAgICAgICAgSm95YHMgU2hvcFxuICAgICAgICAgIEFtIFN0ZWluZmVscyAxXG4gICAgICAgICAgIDY1NjE4IFNlbHRlcnNcblxuVGVybWluYWwtSUQgOiAgICAgICAgICAgICAgNTQwNjE1ODNcblRBLU5yIDA3MDk0MiAgICAgICAgICAgICAgIEJOciA0MzAzXG5cbiAgICAgICAgICAgS2FydGVuemFobHVuZ1xuICAgICAgICAgICAga29udGFrdGxvc1xuICAgICAgICAgICAgTUFTVEVSQ0FSRFxuXG4gICAgRVVSIDExLDU0XG5cblBBTiAgICAgICAgICAgICAgICAjIyMjIyMjIyMjIyMzMjg3XG5LYXJ0ZSAwXG5FTVYtQUlEICAgICAgICAgICAgICBBMDAwMDAwMDA0MTAxMFxuVlUtTnIgICAgICAgICAgICAgICAgICAgICA4MDM2MjQ0NTBcbkFJRFBhcmEgICAgICAgICAgICAgICAgICAwMTAwMDAwMDAyXG5HZW5laG1pZ3VuZ3MtTnIgICAgICAgICAgICAgIDA3MDMxMVxuRGF0dW0gMTMuMDQuMjIgICAgICAgICAgICAyMDoxMyBVaHJcbkVNVi1EYXRlblxuMDAwMDAwODAwMS9BODAwLzAwMDAwMDAwMDAvRjQ1MDg0ODBcbjBDL0Y0NTA4NDgwMEMvM0YwMDAyLy8vMjE3OEEwOTQvODBcblxuWmFobHVuZyBlcmZvbGd0XG5cbj09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5BUy1Qcm9jLUNvZGUgPSAwMCAwNzUgMDBcbkNhcHQuLVJlZi49IDAyNjBcbkFJRDU5OiAxNDI5OTFcbj09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbiAgICAgIEJJVFRFIEJFTEVHIEFVRkJFV0FIUkVOXG5cbg=="
>     }
> ],
> ```

## Possible CurrencyCode values
To specify the currency, the 3-digit [ISO 4217](https://de.wikipedia.org/wiki/ISO_4217) standard is used. Any currency codes that do not match the standard will result in a invalid response.

> **Example 1:**
>
> currency: "EUR"

> **Example 2:**
>
> foreignCurrency: "USD"

