# Vendor API v3
This document describes the usage of the anybill vendor REST API v3.
# Environments
anybill provides two public environments: Production and Staging. While the Production environment is used for all live systems, the staging environment is for testing new features, testing the integration with POS software providers or integration testing. All new features will be released first to the Staging environment, so we can make sure everything is working correctly.
# Production: https://vendor.anybill.de/
This environment is for production use.
SwaggerUI (opens new window)
OpenApi-Specification (opens new window)
# Staging: https://vendor.stg.anybill.de/
This environment is for integration testing.
SwaggerUI (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.
# Authentication
# Basics
Communication with the anybill cloud is only possible after prior authentication. anybill uses OAuth 2.0 or OpenId Access Tokens for authentication. The identities are managed in an Azure Active Directory B2C. To get an access token you need a client id and a service account with username and password.
- The client ID is assigned by anybill once per POS system manufacturer.
- Username and password of the service account are assigned by anybill to the merchant.
# Scopes
The functional areas of the API are secured by scopes. An access token with the requested scopes must be used for the respective functional area. The following scopes currently exist:
- https://ad.anybill.de/vendor/bill (opens new window)
- https://ad.anybill.de/vendor/customer (opens new window)
- https://ad.anybill.de/vendor/store (opens new window)
- https://ad.anybill.de/vendor/user (opens new window)
# Retrieving an Access Token
To retrieve an access token, an HTTP POST request with the following data must be
sent to our OAuth 2.0 endpoint.
URL
https://adanybill.b2clogin.com/ad.anybill.de/oauth2/v2.0/token?p=b2c_1_ropc_vendor (opens new window)
Header
Content-Type: application/x-www-form-urlencoded
Query Parameters
{“p” : “b2c_1_ropc_vendor”}
Body
{
grant_type: password
username: <service account username>
password: <service account password>
client_id: <client id of the POS system manufacturer>
scope: https://ad.anybill.de/vendor/bill offline_access
response_type: token
}
If authentication is successful, the server outputs the access token as a response in the following format:
{
"access_token": "*****",
"token_type": "Bearer",
"expires_in": "86400",
"refresh_token": "*****"
}
For every communication with endpoints of the anybill API the access token must be specified in the header:
Authorization: Bearer <access_token>
# Retrieving a Refresh Token
The access token can be updated as follows.
URL
https://adanybill.b2clogin.com/ad.anybill.de/oauth2/v2.0/token?p=b2c_1_ropc_vendor (opens new window)
Header
Content-Type: application/x-www-form-urlencoded
Query Parameters
{“p” : “b2c_1_ropc_vendor”}
Body
{
refresh_token: <refresh token>
grant_type: refresh_token
client_id: <client id of the POS system manufacturer>
scope: https://ad.anybill.de/vendor/bill offline_access
response_type: token
}
If the update is successful, the server outputs the access token as a response in the following format:
{
"access_token": "*****",
"token_type": "Bearer",
"expires_in": "86400",
"refresh_token": "*****",
“refresh_token_expires_in”: “*****”,
}
# Bill Endpoints
# Retry Policy Guidelines
To ensure the reliable and consistent delivery of digital receipts, we recommend that all partners implement a robust retry policy when interacting with our API. This policy helps manage temporary network issues and ensures that receipts are processed successfully.
# When to Retry
Retry on 5XX Status Codes:
- These status codes indicate temporary server issues:
- 500: Internal Server Error
- 502: Bad Gateway
- 503: Service Unavailable
- 504: Gateway Timeout
- Implement a retry mechanism for these codes using an exponential backoff strategy with jitter to avoid overwhelming our servers.
- These status codes indicate temporary server issues:
Do Not Retry on 4XX Status Codes:
- These status codes indicate client-side errors and should not trigger retries:
- 400: Bad Request
- 401: Unauthorized
- 403: Forbidden
- 404: Not Found
- 409: Conflict
- These status codes indicate client-side errors and should not trigger retries:
# Retry Strategy
- Exponential Backoff with Jitter:
- Start with a base delay of 1 second.
- Use an exponential backoff formula:
wait_time = base_delay * (2^retry_attempt) * random(0.5, 1.5)
. - Cap the maximum delay at 30 seconds.
- Retry up to 3 to 5 times before logging the final failure.
# Idempotency
Ensure that all receipt submission requests are idempotent, meaning that multiple retries of the same request should not result in duplicate receipts or inconsistent state.
# Logging
We recommend logging each retry attempt, capturing the response status code, the time of the attempt, and the reason for the retry. This will assist in troubleshooting and improving integration reliability.
By following these guidelines, you can help ensure smooth and efficient interaction with our API, minimizing disruptions and enhancing the overall user experience.
# Endpoints
The bill controller offers two routes:
- GET
bill/url
: get QR code in advance for a bill. - POST
bill
: add bill to the anybill system. - DELETE
bill/{billId}
: Cancel a receipt based on the billId. - POST
bill/vendorreceipt
: add a VendorReceipt to the anybill services. - POST
bill/{billId}/printed
: Adds a printed timestamp to the bill.
The GET bill
-route can be used to get an advance QR code for a bill.
# Detailed Endpoint Description
for Staging Environment: SwaggerUI (opens new window)
for Production Environment: SwaggerUI (opens new window)
# Request
The store ID must be sent in the body of the request. The BuyerInformation are optional and not necessary.
# Response
The response returns a json object with an url from which the QR code can be generated.
{
"type": "url",
"url": "url to bill",
"billId": "Id of the 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",
"billId": "Id of the bill"
}
When receipt is matched with the user id:
{
"type": "userId",
"isAssigned": true,
"billId": "id of the bill"
}
When receipt is matched with the bank card data:
{
"type": "loyaltyCard",
"isAssigned": true,
"billId": "id of the bill"
}
When receipt is matched with the loyalty card:
{
"type": "externalId",
"isAssigned": true,
"billId": "id of the bill"
}
# 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)
- externalId Id of the user in an external customer system. (Priority 3)
If more than one identification option is specified, the option with the highest priority number is used first. If no user with the specified information could be found, the second and third priority numbers are checked. If no user could be found with the given information a HTTP status code 404 is returned.
# Self-generated ID by the POS (Optional)
The Vendor API offers the possibility that the POS system generates a Bill ID independently. This functionality must be agreed in advance in anybill and actively enabled by anybill. Furthermore, the URL to the receipt differs from the conventional way. Two additional query parameters IsSGId
and VCId
are transmitted.
Existing billID
If the UUID for the bill already exists in the anybill system, the StatusCode 400 is returned with the following error message:
{
"errors": [
{
"message": "Bill with Id 5e952ea6-167d-4001-95d9-a759204c2943 already exists",
"code": "billId-alreadyExists",
"extensions": {}
}
],
"type": "https://tools.ietf.org/html/rfc7231#section-6.5.1",
"title": "One or more business logic errors occurred.",
"status": 400,
"detail": null,
"instance": "/v3/bill",
"extensions": {
"traceId": "00-62c5389aa64965de30dcf0c4313e60c1-cc61c9200d008c1b-00"
}
}
Production:
- Default URL:
https://getmy.anybill.de/<lang:ISO 639-1 code>/<billId:UUID>
- Self-generated URL by POS:
https://getmy.anybill.de/<lang:ISO 639-1 code>/<billId:UUID>?IsSGId=true&VCId=<VendorCustomerId:UUID>
Staging:
- Default URL:
https://getmy.stg.anybill.de/<lang:ISO 639-1 code>/<billId:UUID>
- Self-generated URL by POS:
https://getmy.stg.anybill.de/<lang:ISO 639-1 code>/<billId:UUID>?IsSGId=true&VCId=<VendorCustomerId:UUID>
Test:
- Default URL:
https://getmy.test.anybill.de/<lang:ISO 639-1 code>/<billId:UUID>
- Self-generated URL by POS:
https://getmy.test.anybill.de/<lang:ISO 639-1 code>/<billId:UUID>?IsSGId=true&VCId=<VendorCustomerId:UUID>
# 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.
# Id
Add a receipt to an Id that has already been created in advance via the GET bill/url
endpoint.
anybill also allows the addition of self-generated IDs by the POS system.
This function can only be used after consultation with anybill and must be explicitly activated by anybill.
# Cash Register
Contains data about the cash register. Currently only the serial number of the cash register is needed.
# Head
Contains common data of the head of a bill. E.g. invoice number, date, seller or buyer information.
Important rules:
- If
deliveryPeriodStart
is setdeliveryPeriodEnd
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:
currency
must be a valid three digit ISO 4217 (opens new window) code.- Each
vatAmount
must be unique by the percentage.
Important rules paymentTypes
:
- If
foreignAmount
is setforeignCurrency
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 thetype
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 correspondingvatAmount
set in the default line. - A maximum of 5
reminder
s can be set perwarranty
in theitem
warrantyEnd
must be afterwarrantyStart
.warrantyEnd
andwarrantyStart
must be afte 1900-01-01.
- Each
Important rules data extensions:
- If
barcode
is setbarcodeType
must be set and vice versa. - Each
vatAmount
must be unique by the percentage. - Each discount must have a unique
id
# Security
The security object contains information about the technical security equipment required in the different countries. With the help of the Type attribute, the appropriate TSE can be transmitted depending on the country.
Globale important rules:
tse
must be set unlesstseFailure
is set totrue
in the security extensions.tse
must be set unlesstseRequired
is set tofalse
in the security extensions.
Important rules TSE (Germany)
:
timestampStart
,timestampEnd
andfirstOrder
must be after 1900-01-01.
TSE (Germany)
{
"serialNumber": "623323B6C170DF2200...8F3A78E5BA7C4BA60B",
"signatureAlgorithm": "ecdsa-plain-SHA384",
"logTimeFormat": "unixTime",
"certificate": "LS0tLS...S0tCg ==",
"timestampStart": "2021-11-29T15:00:57.22976+01:00",
"timestampEnd": "2021-11-29T15:00:57.22976+01:00",
"firstOrder": "2021-11-29T15:00:57.22976+01:00",
"transactionNumber": 50,
"signatureNumber": 121,
"processData": "Kassenbeleg-V1",
"processType": "Beleg^42.31_16.26_0.00_0.00_0.00^58.57:Bar:Visa",
"signature": "AjEGS...dhRitb",
"extension:anybill": {
"posInspectionQrData": "_R1-AT1_4690F01D01_68_2021-10-04T13:54:19_4,00_0,00_0,00_0,00_0,00_jVWJIf9wOCDo544VtmI7dQ==_15BE7FD2_eUwHgkS8AGE=_GkWvZVamt1RKsUBSbGACKgcfhX7iNiRq4iQgZ8E4CUPHStNAnC6k7IPA5cG4OFlyAh0GsbSRanKBUfy0PsyVqg==",
"additionalLegalText": "Additional legal text",
"additionalTseData": {
"firstName": {
"displayName": "display value",
"value": "Value"
},
"secondName": {
"displayName": "display value",
"value": "Value"
}
}
}
}
RKSV (Austria)
{
"type": "rksv",
"signature": "AjEGS...dhRitb",
"serialNumber": "Tpzx/mesZGSu/XO6ZaKZO/bk87HKejMaU2VCDoAgmp4=",
"transactionNumber": 1459,
"signatureNumber": 3833,
"posInspectionQrData": "_R1-AT1_4690F01D01_68_2021-10-04T13:54:19_4,00_0,00_0,00_0,00_0,00_jVWJIf9wOCDo544VtmI7dQ==_15BE7FD2_eUwHgkS8AGE=_GkWvZVamt1RKsUBSbGACKgcfhX7iNiRq4iQgZ8E4CUPHStNAnC6k7IPA5cG4OFlyAh0GsbSRanKBUfy0PsyVqg==",
"additionalLegalText": "Additional legal text",
"additionalData": {
"firstName": {
"displayName": "display value",
"value": "Value"
},
"secondName": {
"displayName": "display value",
"value": "Value"
}
}
}
# Misc
Optional additional data.
Important rules misc extensions:
- If
returnBarcodeType
is setreturnBarcode
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 linestext
for text only linesdiscount
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 |
KilowattHour | 8 |
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 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 (Deprecated) | 3 |
OnlinePayment | 4 |
GiftCard | 5 |
BankTransfer | 6 |
Check | 7 |
LoyaltyCard | 8 |
Girocard (Deprecated) | 9 |
Elv | 10 |
Maestro (Deprecated) | 11 |
VisaElectron (Deprecated) | 12 |
CardPayment | 12 |
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.
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",
"terminalDateTime": null,
"terminalTime": "12:37:04",
"terminalDate": "20.07.2020",
"traceNumber": "4321",
"cardPan": "The primary account number",
"cardSequenceNumber": 1234,
"cardExpiryDate": "12/27"
}
}
}
Cash payment details
{
"name": "Cash",
"amount": 112.90,
"foreignAmount": null,
"foreignCurrency": null,
"extension:anybill": {
"type": "Cash",
"paymentDetails": {
"amountGiven": 120.00,
"amountReturned": 17.10
}
}
}
CardPayment payment details (CardPayment, Girocard, Maestro, VisaElectron, CreditCard)
{
"name": "Visa",
"amount": 112.90,
"foreignAmount": null,
"foreignCurrency": null,
"extension:anybill": {
"type": "CardPayment",
"paymentDetails": {
"cardNumber": "123456",
"bankName": "Some Bank",
"terminalId": "1234",
"terminalDateTime": null,
"terminalTime": "12:37:04",
"terminalDate": "20.07.2020",
"traceNumber": "4321",
"cardPan": "The primary account number",
"cardSequenceNumber": 1234,
"cardExpiryDate": "12/27",
}
}
}
DirectDebit payment details (DirectDebit, Elv)
{
"name": "Elv",
"amount": 112.90,
"foreignAmount": null,
"foreignCurrency": null,
"extension:anybill": {
"type": "Elv",
"paymentDetails": {
"sepaCreditorId": "",
"sepaMandateReference": "",
"cardNumber": "",
"bankName": "",
"terminalId": "1234",
"terminalDateTime": null,
"terminalTime": "12:37:04",
"terminalDate": "20.07.2020",
"traceNumber": "4321",
"cardPan": "The primary account number",
"cardSequenceNumber": 1234,
"cardExpiryDate": "12/27",
}
}
}
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 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:
Terminal customer receipt example
"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:
Terminal merchant receipt example
"additionalReceipts": [
...,
{
"type": "VendorReceipt",
"contentType": "text/plain",
"content": "ICAgICAgLUgtw4QtTi1ELUwtRS1SLUItRS1MLUUtRy1cblxuICAgICAgICAgICAgSm95YHMgU2hvcFxuICAgICAgICAgIEFtIFN0ZWluZmVscyAxXG4gICAgICAgICAgIDY1NjE4IFNlbHRlcnNcblxuVGVybWluYWwtSUQgOiAgICAgICAgICAgICAgNTQwNjE1ODNcblRBLU5yIDA3MDk0MiAgICAgICAgICAgICAgIEJOciA0MzAzXG5cbiAgICAgICAgICAgS2FydGVuemFobHVuZ1xuICAgICAgICAgICAga29udGFrdGxvc1xuICAgICAgICAgICAgTUFTVEVSQ0FSRFxuXG4gICAgRVVSIDExLDU0XG5cblBBTiAgICAgICAgICAgICAgICAjIyMjIyMjIyMjIyMzMjg3XG5LYXJ0ZSAwXG5FTVYtQUlEICAgICAgICAgICAgICBBMDAwMDAwMDA0MTAxMFxuVlUtTnIgICAgICAgICAgICAgICAgICAgICA4MDM2MjQ0NTBcbkFJRFBhcmEgICAgICAgICAgICAgICAgICAwMTAwMDAwMDAyXG5HZW5laG1pZ3VuZ3MtTnIgICAgICAgICAgICAgIDA3MDMxMVxuRGF0dW0gMTMuMDQuMjIgICAgICAgICAgICAyMDoxMyBVaHJcbkVNVi1EYXRlblxuMDAwMDAwODAwMS9BODAwLzAwMDAwMDAwMDAvRjQ1MDg0ODBcbjBDL0Y0NTA4NDgwMEMvM0YwMDAyLy8vMjE3OEEwOTQvODBcblxuWmFobHVuZyBlcmZvbGd0XG5cbj09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5BUy1Qcm9jLUNvZGUgPSAwMCAwNzUgMDBcbkNhcHQuLVJlZi49IDAyNjBcbkFJRDU5OiAxNDI5OTFcbj09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbiAgICAgIEJJVFRFIEJFTEVHIEFVRkJFV0FIUkVOXG5cbg=="
}
],
# 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.
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 itemA1
. - Create a new bill
B
with an extra line itemB1
which represents the returned line itemA1
. - Set the property
ReturnBarcodeReference
of line itemB1
to the value of propertyReturnBarcode
of billA
. - 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
},
...
}
]
},
...
}
}
# Custom sections
Custom sections allow you to insert your own attributes between the defined areas in order to individualize the receipt and display the necessary information.
A custom section can be inserted either before
or after
a defined area, contains a title
and a list of data
which are displayed in the given order by the sequenceNumber
.
The title will not be displayed on pdf. May be used in digital display formats.
The customSectionId
can be used if it should be needed again later via the SDK. Must be unique across all customSections.
# Areas
The receipt is generally divided into the following areas:
Head
Lines
PaymentDetails
VatDetails
AdditionalData
Buyer
FooterText
TseInformation
AfterSalesCoupons
HospitalityInformation
A receipt with the marked sections can be downloaded here.
# Types
Currently, data of type text
, keyValue
, barcode
or qrCode
can be added to a custom section.
text
{
"sequenceNumber": 0,
"customSectionId": "NameId",
"type": "text",
"text": "text message",
"alignment": "Left|Center|Right"
}
keyValue
{
"sequenceNumber": 1,
"customSectionId": "NameId",
"type": "keyValue",
"key": "LoyaltyCard number:",
"value": "123456789"
}
barcode
{
"sequenceNumber": 0,
"customSectionId": "NameId",
"type": "barcode",
"barcodeType": "Barcode|Code128ABarcode|Code128BBarcode|Code128CBarcode",
"value": "Value of the barcode"
}
qrCode
{
"sequenceNumber": 0,
"customSectionId": "NameId",
"type": "qrCode",
"value": "Value of the qrCode"
}
# Custom section example
"customSections": [
{
"position": "Before",
"section": "Head",
"title": "Title of the custom head section",
"data": [
{
"sequenceNumber": 0,
"type": "Text",
"text": "Before Head text"
},
{
"sequenceNumber": 1,
"type": "KeyValue",
"key": "LoyaltyCard number:",
"value": "123456789"
}
]
},
{
"position": "After",
"section": "VatAmounts",
"title": "Title of the custom vatAmounts section",
"data": [
{
"sequenceNumber": 0,
"type": "barcode",
"barcodeType": "Code128ABarcode",
"value": "Value of the barcode"
},
{
"sequenceNumber": 1,
"type": "qrCode",
"value": "Value of the qrCode"
}
]
}
]
# Print buffer
The print buffer solution is an additional option to transmit the print buffer content in the additionalReceipts
section as Base64 if isPrintBuffer
is true and IsPrimaryReceipt
is true. Then the transmitted print buffer will be used for the PDF generation.
With this solutions the receipt looks like the printed receipt but also have the advantages of the digital receipt.
Currently we are supporting the following control commands:
\x{BOLD}
à bold (coming soon)\x{DHIGH}
à double height (coming soon)\x{DWIDE}
à double with (coming soon)\x{DWIDEDHIGH}
à double height double with\x{RIGHT}
à text alignment = right (coming soon)\x{CENTER}
à text alignment = center (coming soon)\x{INVERSE}
à print inverse (coming soon)
In addition we still support:
\x{Bar, PTR_BCS_Code128,50,1000} 4000540000306 \x
à print Barcode128\x{Bar, PTR_BCS_QRCODE,300,300,PTR_BC_CENTER,PTR_BC_TEXT_NONE}5600 \x
à print QR-Code
Usage of the print buffer
If this option will be used it is necessary to talk with us. There are configuration settings needed for every customer on the anybill side.
The DELETE bill
-route can be used to cancel a receipt based on the billId.
# Detailed Endpoint Description
for Staging Environment: SwaggerUI (opens new window)
for Production Environment: SwaggerUI (opens new window)
# Request
The billId must be sent with the request as a query parameter.
# Response
tip The response returns a statusCode 204 if the receipt could be cancelled or 404 if the receipt couldn't be found.
# Customer Endpoint
This endpoint is used to check if the customer finished the onboarding and is allowed to use the bill endpoints.
# Endpoint
- GET customer/activated
# Detailed Endpoint Description
for Staging Environment: SwaggerUI (opens new window)
for Production Environment: SwaggerUI (opens new window)
# Response
- If the customer finished the onboarding successfull, the HTTP status code
200 Ok
is returned with aCustomerActivatedDto
response.
{
"type": "activated",
"customerId": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
}
- If the customer did not finish the onboarding, the HTTP status code
200 Ok
is returned with aCustomerNotActivatedDto
response. This means that the customer can not send receipts via the bill endpoints.
{
"type": "notActivated",
"customerId": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
}
# Store Endpoints
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
- GET
store/search
# Create Store
To automate the onboarding process of a merchant, anybill provides an endpoint to onboard and activate stores for digital receipts. This operation creates stores at anybill and assigns a unique Store ID. Additionally, this interface replaces the manual entry of stores in the Anybill portal. It can also be utilized in special cases, such as when store IDs cannot be manually entered into the cash register (e.g., due to a lack of a feedback channel to the cash register).
Request Body:
"id": "string",
"displayName": "string",
"legalName": "string",
"address": {
"country": "string",
"countryCode": "str",
"zip": "string",
"city": "string",
"street": "string",
"number": "string"
},
"vatId": "string",
"googlePlacesId": "string",
"phoneNumber": "string",
"description": "string",
"isHidden": true,
"website": "string",
"language": "string",
"storeOpeningHours": [
{
"dayOfWeek": "Sunday",
"open": "string",
"close": "string"
}
],
}
# Search store by address
Additionally, it can occur that cash registers in a shop cannot communicate with each other, and thus, calling the Create Store Endpoint might create duplicates. For this scenario, anybill provides the Search Store Endpoint, allowing you to check in advance whether a store already exists for the address integrated into the cash register. If no store exists, you need to create a store using the Create Store Endpoint. If a store already exists, the Store ID is returned, which should then be used in the receipt data for creating digital receipts.
# Detailed Endpoint Description
for Staging Environment: SwaggerUI (opens new window)
for Production Environment: SwaggerUI (opens new window)
# User Endpoint
This endpoint is used to identify a user by userId
, loyaltyCardBarcode
or externalId
.
# Endpoint
- POST
user/identify
# Detailed Endpoint Description
for Staging Environment: SwaggerUI (opens new window)
for Production Environment: SwaggerUI (opens new window)
# Request
In the request, userId
, loyaltyCardBarcode
or externalId
can be passed.
The following prioritization is used:
userId
loyaltyCardBarcode
externalId
Only the identification option with the highest priority is processed.
{
"userId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"loyaltyCardBarcode": "string",
"externalId": "string"
}
# Response
If a user could be found by userId
, loyaltyCardBarcode
or externalId
, the Id of the user with the Http status code 200 Ok
is returned.
If no user could be found, a response with the Http status code 404 Not Found
is returned.
{
"userId": "3fa85f64-5717-4562-b3fc-2c963f66afa6"
}
# 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).
# 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.