# Vendor API v3

This document describes the usage of the anybill vendor REST API v3.

# Environments

There are currently two public environments:

# Production: https://vendor.anybill.de/api

This environment is for production use.
SwaggerUI (opens new window)
ReDoc (opens new window)
OpenApi-Specification (opens new window)

# Staging: https://vendor.stg.anybill.de/api

This environment is for integration testing.
SwaggerUI (opens new window)
ReDoc (opens new window)
OpenApi-Specification (opens new window)

App Envirnoment

Use the correct environment so that you can load digital receipts into the anybill app. Instructions on how to change the environment on the anybill app can be found here.

# Bill Api

# Endpoints

The bill controller offers two routes:

  • POST bill: add bill to the anybill system
  • GET bill: get QR code in advance for a bill

The GET bill-route can be used to get an advance QR code for a bill.

# Request

The store ID must be sent with the request as a query parameter.

# Response

The response returns a json object with an url from which the QR code can be generated.

{
   "type": "url",
   "url": "url to bill"
}

The POST bill-route can be used to add following types of bill.

  • Anonymous This is the case if the customer does not scan his QR code at the POS. This enables the vendor to issue a digital receipt to the customer. On success a response with a HTTP status code of 200 containing a JSON object with the URL to get the receipt is returned.

    Example:

    { "url": "https://path-to-receipt.anybill.de/{receiptId}" }

  • User This is the case if the QR code provided by the app gets scanned at the POS. For a better description of the structure of the QR code have a look here. On success a response with a HTTP status code of 204, containing no body is returned.

The expected object in the body of the request forms an envelope with required information around the actual bill object.

If the user identification object or all its property are null, the bill will be treated as anonymous.

The storeId is expected be set so that on the one hand the required complementary information about the customer (Name, address, etc.) can be added and on the other hand for invoicing purposes. As seen in the open api specification, the respective store from which the receipt is to be issued must have already been added via the Store API or the anybill Partner Portal.

Information:

The storeId must be unique per customer.

# Response

The endpoint has 4 diffrent response objects

When no user identification is provided:

{
   "type": "url",
   "url": "url to bill"
}

When receipt is matched with the user id:

{
   "type": "userId",
   "isAssigned": true
}

When receipt is matched with the bank card data:

{
   "type": "bankCard",
   "isAssigned": true
}

When receipt is matched with the loyalty card:

{
   "type": "loyaltyCard",
   "isAssigned": true
}

# User identification

If a user-bill should be added the property userIdentification must be filled with the required link to identify the user. Possible ways to identify the user:

  • userId The id of the anybill user that is available through the QR code of the app. (Priority 1)
  • loyaltyCardBarcode The barcode of the loyalty card of the requesting customer that is linked to an anybill user. (Priority 2)

Only one identification option should be used. If more than one identification option is set the option with the lowest priority number will be used. If no user could be found with the given information a response with a HTTP status code of 404 is returned.

# Bill object

The bill object is based on the dfka standard with anybill specific extensions. As root object of the bill it links to five different categories of data:

  • Cash register* Information about the cash register.
  • Head* Head data of the bill.
  • Data* Bill data.
  • Security* Data to secure the receipt via TSE.
  • Misc Optional additional data.

To guarantee that only valid information is added to the anybill system, a variety of validation rules is executed. If the validation of the bill 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.

# Cash Register

Contains data about the cash register. Currently only the serial number of the cash register is needed.

Contains common data of the head of a bill. 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.

# Data

Contains the most important information for the buyer. The items he has bought and the value of the shopping cart. Important rules:

Important rules paymentTypes:

  • If foreignAmount is set foreignCurrency must be set and vice versa.
  • foreignCurrency must be a valid three digit ISO 4217 (opens new window) 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.
  • DefaultLine
    • Each vatAmount must be unique by the percentage.
    • Each vatAmount set for a discount in the anybill extensions must have a corresponding vatAmount set in the default line.
    • A maximum of 5 reminders can be set per warranty in the item
    • warrantyEnd must be after warrantyStart.
    • warrantyEnd and warrantyStart must be afte 1900-01-01.

Important rules data extensions:

  • If barcode is set barcodeType must be set and vice versa.
  • Each vatAmount must be unique by the percentage.
  • Each discount must have a unique id

# Security

Data to secure the receipt via TSE. Important rules:

  • tse must be set unless tseFailure is set to true in the security extensions.
  • tse must be set unless tseRequiredis set to false in the security extensions.

Important rules tse:

  • timestampStart, timestampEnd and firstOrder must be after 1900-01-01.

# Misc

Optional additional data. Important rules:

  • If the contentType of the logo or the additionalReceipt is set to text/x-uri a well formed url is expected.

Important rules misc extensions:

  • If returnBarcodeType is set returnBarcode must be set and vice versa.

# Description of possible values

For better understanding some values are descibed below.

Values for enumerations like QuantityMeasure, PriceModifier or PaymentType can be the integer value or the string equivalent, whereas integers are prefered. The descriptions always show the integer value and the string equivalent/meaning of the value.

# Lines

There are three types of lines. The type of the line is determined with the type-discriminator in the extension of the line. Possible discriminators:

  • default or no value (null) for default lines
  • text for text only lines
  • discount for discount line

# Default line

The default line represents an item or service that was sold. You can add useful information in the additionalText or even add warranty information and let the user be notified before the warranty ends.

# Text line

The text line can be used to add text in between other lines. This can be as easy as a product group seperation 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.

# 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

Example 1:

qantityMeasure: "Count"

Example 2:

quantityMeasure: 3

# 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 3 (credit card) and name should be "Visa". The name should be human readable and will be displayed for the user.

# Possible PaymentType values:

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

Example 1:

type: "Cash"

Example 2:

type: 8

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.

Check payment details
{
  "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": ""
     }
  }
} 
BankTransfer payment details
{
  "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",
        "paymentReceipt": "The payment receipt.",
        "terminalDateTime": null,
        "terminalTime": "12:37:04",
        "terminalDate": "20.07.2020",
        "traceNumber": "4321",
        "cardPan": "The primary account number",
        "cardSequenceNumber": 1234,
        "cardExpiryDate": "12/27",
        "additionalTerminalText": "Additional text that was emitted by the terminal"
    }
  }
} 
Cash payment details
{
  "name": "Cash",
  "amount": 112.90,
  "foreignAmount": null,
  "foreignCurrency": null,
  "extension:anybill": {
     "type": "Cash",
     "paymentDetails": {
        "amountGiven": 120.00,
        "amountReturned": 17.10
    }
  }
} 
CreditCard payment details
{
  "name": "Visa",
  "amount": 112.90,
  "foreignAmount": null,
  "foreignCurrency": null,
  "extension:anybill": {
     "type": "CreditCard",
     "paymentDetails": {
        "cardNumber": "123456",
        "bankName": "Some Bank",
        "terminalId": "1234",
        "paymentReceipt": "The payment receipt.",
        "terminalDateTime": null,
        "terminalTime": "12:37:04",
        "terminalDate": "20.07.2020",
        "traceNumber": "4321",
        "cardPan": "The primary account number",
        "cardSequenceNumber": 1234,
        "cardExpiryDate": "12/27",
        "additionalTerminalText": "Additional text that was emitted by the terminal"
    }
  }
} 
DirectDebit payment details (DirectDebit, Girocard, Elv, Maestro, VisaElectron)
{
  "name": "Elv",
  "amount": 112.90,
  "foreignAmount": null,
  "foreignCurrency": null,
  "extension:anybill": {
     "type": "Elv",
     "paymentDetails": {
        "sepaCreditorId": "",
        "sepaMandateReference": "",
        "cardNumber": "",
        "bankName": "",
        "terminalId": "1234",
        "paymentReceipt": "The payment receipt.",
        "terminalDateTime": null,
        "terminalTime": "12:37:04",
        "terminalDate": "20.07.2020",
        "traceNumber": "4321",
        "cardPan": "The primary account number",
        "cardSequenceNumber": 1234,
        "cardExpiryDate": "12/27",
        "additionalTerminalText": "Additional text that was emitted by the terminal"
    }
  }
} 
GiftCard payment details
{
  "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"
    }
  }
} 
LoyaltyCard payment details
{
  "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
    }
  }
} 
OnlinePayment payment details
{
  "name": "Paypal",
  "amount": 112.90,
  "foreignAmount": null,
  "foreignCurrency": null,
  "extension:anybill": {
     "type": "OnlinePayment",
     "paymentDetails": {
        "senderAccountName": "CSymeoudakis@mspos.net",
        "recipientAccountName": "tobias.gubo@anybill.de",
        "transactionId": "1293403"
    }
  }
} 

# Terminal text

The TerminalText attribute is available on every card payment type. It has to be filled with the payment information text which is provided by the terminal. This is an example of the terminal text:

Terminal text example

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///

# Possible CurrencyCode values:

To specify the currency, the 3-digit ISO 4217 (opens new window) 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"

# Discounts:

A discount can either be set to each line item individually or to the whole bill.

# Discount for individual line items

To discount a single line item fill the discounts array property in the extension of the line. If multiple discounts are applied to one line item, the sequence number can be set to give the consumer the ability to understand how the final price is composed. Positive numbers are to be used as the values describe the amount the discount is worth.

Example with multiple discounts

{
  "sequenceNumber": 1,
  "fullAmountInclVatBeforeDiscounts": 799.9,
  "discounts": [
    {
      "sequenceNumber": 0,
      "discountId": "LAPTOP21",
      "vatAmounts": [
        {
          "percentage": 19,
          "inclVat": 100,
          "exclVat": 84.03362,
          "vat": 15.96638
        }
      ],
      "fullAmountInclVat": 100
    },
    {
      "sequenceNumber": 1,
      "discountId": "LAPTOP10",
      "vatAmounts": [
        {
          "percentage": 19,
          "inclVat": 69.99,
          "exclVat": 58.81512,
          "vat": 11.17488
        }
      ],
      "fullAmountInclVat": 69.99
    }
  ],
  ...
}

To further describe a single line discount a definition can be added in the extension of the data of the bill. To reference a discount the same set the discountId of the applied discount to the id of the definition. The values won't be shown to the customer and can therefore be any value. If the same discount is applied to multiple line items only one reference should be used. If a discount is referenced multiple times the vatAmounts and fullAmountInclVat of the definition in the data extension is supposed to be filled.

{
  "discounts": [
    {
      "id": "LAPTOP21",
      "name": "100 € off on 2 laptops",
      "additionalText": "This discount only applies if at least 2 laptops of the same type are bought.",
      "value": 100,
      "type": "Monetary",
      "vatAmounts": [
        {
          "percentage": 19,
          "inclVat": 100,
          "exclVat": 84.03362,
          "vat": 15.96638
        }
      ],
      "fullAmountInclVat": 100
    },
    {
      "id": "LAPTOP10",
      "name": "10 % on laptops",
      "additionalText": "This discount applies to all laptops bought. Can be combined with other discounts.",
      "value": 10,
      "type": "Percentage",
      "vatAmounts": [
        {
          "percentage": 19,
          "inclVat": 69.99,
          "exclVat": 58.81512,
          "vat": 11.17488
        }
      ],
      "fullAmountInclVat": 69.99
    }
  ]
}

# Discount for the whole bill

To add a discount that is applied to the whole bill the discount line can be used. Multiple discount lines can be used for different discounts.
To enhance the information from which line items the discount is made up the relatedLines property can be used. Either use it on the vatAmounts to link the to the line item by the sequenceNumber or set all lines on the root.

Example:

{
  "text": "Wochenendrabatt 3 %",
  "additionalText": "3 % Rabatt am Wochenende",
  "vatAmounts": [
    {
      "percentage": 7,
      "inclVat": 0.09,
      "exclVat": 0.08411,
      "vat": 0.00589,
      "relatedLines": [
        0
      ]
    },
    {
      "percentage": 19,
      "inclVat": 0.08,
      "exclVat": 0.06723,
      "vat": 0.01277,
      "relatedLines": [
        2
      ]
    }
  ],
  "fullAmountInclVat": 0.17,
  "relatedLines": null,
  "extension:anybill": {
    "sequenceNumber": 3,
    "type": "discount"
  },
  ...
}

# Returning a line item:

If you want to return a bills line item the following steps are necessary:

  • Given an existing bill A with a line item A1.
  • Create a new bill B with an extra line item B1 which represents the returned line item A1.
  • Set the property ReturnBarcodeReference of line item B1 to the value of property ReturnBarcode of bill A.
  • Save bill B.

A line item is then displayed as "returned" in bill B.

Example

Bill A:

{
  "storeId": "8192538C-CC23-488B-B35B-0F16BE1B8F43",
  "bill": {
     "head": {
        "date": "2020-06-20T13:00:00+00:00",
        ...
     },
     "data": {
        "lines": [
           {
              "text": "A1",
              "quantity": 1,
              "fullAmountInclVat": 1.00,
              ...
           },
           {
              "text": "A2",
              "quantity": 3,
              ...
           }
        ]
     },
     "misc": {
        "extension:anybill": {
           "returnBarcode": "123",
           ...
        },
        ...
     },
     ...
   } 
}

Bill B:

{
  "storeId": "8192538C-CC23-488B-B35B-0F16BE1B8F43",
   "bill": {
      "head": {
         "date": "2020-06-20T15:00:00+00:00",
         ...
      },
      "data": {
         "lines": [
            {
               "text": "B1",
               "quantity": 1,
               "fullAmountInclVat": -1.00,
               "extension:anybill": {
                  "returnBarcodeReference": "123", // see returnBarcode of Bill A
               },
               ...
            }
         ]
      },
      ...
   }
}

# PDF example receipt

The following image shows a complete example receipt. The different sections have been highlighted and marked so that a link can be established with the Bill API data model.

full receipt with notes

# Store Api

These endpoints are used to manage the stores of a vendor. This can also be done on the anybill Partner Portal.
The most important usecase of these endpoints is to enable larger companies to automate the process of syncing store details.

# Endpoints

  • GET store
  • POST store
  • GET store/{id}
  • DELETE store/{id}
  • GET store/{id}/history

# Detailed Endpoint Description

for Staging Environment: SwaggerUI (opens new window)
for Production Environment: SwaggerUI (opens new window)

# Category Api

These endpoints list all categories which are available to categorize the line items and the bill.

# Endpoints

  • GET category
  • GET category/{id}

# Detailed Endpoint Description

for Staging Environment: SwaggerUI (opens new window)
for Production Environment: SwaggerUI (opens new window)

# Category FAQ

# Can I add my own Category?

For now, the answer is unfortunately no. The problem with own categories is that we have to display the categories with icons in a unified manner inside the app. However, we are working on the functionality that our API automatically matches the provided line items to the categories by using the ean number. This way no categories have to be provided. Stay tuned!

# Postman

A postman collection can be found here.

To acquire an access_token first set your credentials for the following collection variables:

  • username
  • password
  • client_id

After your credentials are set, send a request with the GetToken request. The acquired access token will be set automatically for all requests in the collection. Choose the environment and you are good to go.

If you want to switch between staging and production environment, you have to change the base path from https://vendor.stg.anybill.de (opens new window) to https://vendor.anybill.de (opens new window).

# Migration information from v2

  • Removed UnitOriginalGrossPrice, DiscountValue and PriceModifier from LineItemDto in favor of discounts array.

# Changelog

Changes to the V3 Api will be documented here.

# 2021-10-12

  • Added new optional attribute isHospitalityBill in bill.misc.extension:anybill. If this flag is set to true, then the pdf contains hospitality information and the user has the option to fill the necessary data via the website or the app.

# 2021-09-07

  • Added new optional attribute Tip in bill.data.extension:anybill. If this attribute is set, then the pdf contain the tip.

# 2021-08-05

  • New endpoint created, with which a QR code can be generated in advance. When uploading the bill via the POST endpoint, the id must be specified under bill.
  • Added new optional attribute isInvoice in misc.extension:anybill. If this attribute is set to true, then the pdf looks like an invoice.

# 2021-07-14

  • PaymentDetails in extension:anybill is now optional for BankTransfer, CreditCard and DirectDebitCard in case the payment terminal is not connected to the cash register.
  • PaymentTypes in data is now optional.

# 2021-06-23

  • Changed validation for the CountryCode in the BuyerAddressDto and SellerAddressDto. In addition to the country code, the country can now simply be transmitted in the CountryCode attribute. If the country code is 3 letters long, it is interpreted as ISO 3166 alpha-3, else the country code is interpreted as normal string.

# 2021-06-11

  • Added TseRequired to the securityExtension

# License

The anybill vendor API v3 data model builds upon the DFKA e.V. EKaBS-Json-Scheme. This scheme is licenced under the Creative Commons Licence CC BY-SA 4.0.

This results in the following rights for the user: The EKaBS-JSON schema and the documentation may be reproduced, redistributed, modified and used in any form as long as the reference to the DFKA e.V. as licensor is kept and modifications are only passed on under the same conditions.