Bessa Direkt Integration API
Die Bessa Direkt Integration wird für die Digitale Kundenbindung benötigt und übermittelt Rechnungsinformationen an das Bessa System. Weiters kann über die Direkt Integration der Einlöse Prozess von Punkte und Stempelkarten vereinfacht werden.
Sammeln
Die Kasse muss die Rechnungsposition an den Bessa Server senden über eine REST Schnittstelle (siehe REST API Dokumentation). Die Rechnungsposition werden am Server gespeichert.
Variante: Klassischer Rechnungsscan
Kunde scannt eine Rechnung mit Hilfe des QR-Codes. Über die Rechnungspositionen werden ihm die korrekten Artikel aufgebucht.Variante: Kasse scannt App
Jeder Benutzer der Bessa App bekommt eine ID zugeordnet. Die Kasse scannt den Kunden-QR-Code während der Bestellung. Die Kasse speichert diese ID und hinterlegt sie bei den Rechnungspositionen welche auf den Bessa Server geschickt werden. (siehe REST API Dokumentation).Variante: Kundenkarte (digital oder als echte Plastik Kundenkarte)
Jeder Benutzer der Bessa App oder Plastikkartenbesitzer bekommt eine Kundennummer zugeordnet. Diese Kundennummer ist eine Zeichenkette (größer als 10 Zeichen). Mit dieser kann unsere API den Kunden beim Zahlvorgang Punkte oder Stempel aufbuchen oder auch diese beim Zahlvorgang einlösen. (siehe REST API Dokumentation).
Die Position werden dann als gesammelt markiert und sind durch einen Scan der Rechnung nicht mehr sammelbar. Der Benutzer bekommt eine Push-Notification auf sein Gerät bzw. wenn er die Oberfläche neu lädt werden ihm die gesammelten Punkte angezeigt.
Einlösen mit APP
Diese Szenario geht davon aus das der Kunde schon Punkte gesammelt hat die er einlösen kann.
Schritt - (App)
Der Kunde öffnet die Bessa App und löst die Karte ein. Das öffnet in der App eine entsprechende Oberfläche in welcher ein Einlöse-QR-Code angezeigt wird.Schritt - (Kasse)
Die Kasse scannt dann den im Schritt 1 erwähnten QR-Code und sendet den Code an den Bessa Server.Schritt - (Server)
Der Server prüft ob dieser Code schon verwendet wurde, falls er noch nicht verwendet wurde, wird er nun als verwendet markiert. Der Kasse wird mitgeteilt welche PLUs eingelöst werden können. Ein weiteres Ausführen führt zu einem Fehlerfall (z.B.: Code schon eingelöst.)Schritt - (Kasse)
Diese nimmt den eingelösten Code entgegen und bucht ihn mit der entsprechenden Bewegungsart als Rechnungsposition ein.
Einlösen mit Kundenkarte
Diese Szenario geht davon aus das der Kunde schon Punkte gesammelt hat die er einlösen kann.
Schritt - (Kundenkarte)
Der Kunde zeigt an der Kasse seine Karte her.Schritt - (Kasse)
Die Kasse scannt dann den im Schritt 1 erwähnten QR-Code oder Bar-Code und sendet den Code an den Bessa Server, dieser gibt dann für diesen Kunden verfügbare Rabatte zurück.Schritt - (Kasse)
In dem Server Ergebnis können mehr als eine Rabattaktion drin sein, die Kasse muss dann die gewünschte Aktion auswählen. Sollte nur eine Rabattaktion vorhanden sein, kann die Kasse diese sofort auswählen ohne eine Auswahl treffen zu müssen.Schritt - (Server)
Der Server prüft ob dieser Code schon verwendet wurde, falls er noch nicht verwendet wurde, wird er nun als verwendet markiert. Der Kasse wird mitgeteilt welche PLUs eingelöst, bzw. ob ein Rabatt eingelöst werden kann. Ein weiteres Ausführen führt zu einem Fehlerfall (z.B.: Code schon eingelöst.)Schritt - (Kasse)
Diese nimmt den eingelösten Code entgegen und bucht ihn mit der entsprechenden Bewegungsart als Rechnungsposition ein.
REST API - Dokumentation
Für den oben erwähnten Ablauf stehen folgenden REST API Routen zur Verfügung.
Authorization
Authorization läuft über ein Token im Header, mit einer maximalen Länge von 40 chars.
Live-Api: https://api.bessa.app/
Test-Api: https://stg.bessa.app/
Health Check
Diese Route prüft ob die Kassa online ist. Sollte alle 20 sec aufgerufen werden.
Request
curl -X "POST" "https://api.bessa.app/v1/systems/health/" \
-H 'Authorization: Token <dein-token>' \
-H 'Content-Type: application/json; charset=utf-8' \
-d $'{
"cash_box": "<deine-cashbox-id>"
}'Request Body
Name | DataType | Nullable | Description |
|---|---|---|---|
cash_box | string | false | Die Id der Kasse die über ihren Zustand berichtet |
Response Code
Code | Description |
|---|---|
200 | Success |
401 | Invalid Token |
404 | No valid |
Kundenkarten Daten Synchronisieren
Sollte der Kassenbenutzer auch eine Bessa Whitelabel App haben, kann man die Kundenkarten Detailinformationen auch mit Bessa abgleichen, dadurch sieht der Kunde seine Kundenkarte in seiner Whitelabel App.
Folgender Request muss abgesendet werden.
Request
curl -X "POST" "https://api.bessa.app/v1/web/pos/customers/" \
-H 'Authorization: Token <dein-token>' \
-H 'Content-Type: application/json; charset=utf-8' \
-d $'{
"external_id": <kundenkarten_id>,
"first_name": "Max",
"last_name': "Mustermann",
"company_name": "",
"phone": "+43650987",
"email": 'max.mustermann@bessa.app',
"tax_id": ""
}'Request Body
Name | DataType | Max-Length | Nullable | Description |
|---|---|---|---|---|
| string | 64 | false | Kundenkarten ID |
| string | 256 | false | Vorname des Kunden. |
| string | 256 | false | Nachname des Kunden, kann leer sein |
| string | 256 | false | Firmenname des Kunden, kann leer sein |
| string | 15 | false | Telefonnummer des Kunden, kann leer sein |
| string | 254 | false | E-Mail des Kunden, kann leer sein |
| string | 256 | false | Steuernummer des Kunden, kann leer sein |
Response Code
Code | Description |
|---|---|
201 | Success |
400 | Invalid Data, please check the error message. |
401 | Invalid Token |
Kundenkarten Daten laden
Der Kunde hat eine Kundekarte und mit dieser Punkte gesammelt um zu erfahren welche Aktionen dieser sich ersammelt hat muss folgender Request abgesendet werden. Die customer_card_id kann aber auch einen gescannten QR-Code enthalten und zu diesem Informationen zurückgeben.
curl -X "GET" "https://api.bessa.app/v1//web/pos/cards/redeem/{customer_card_id}/" \
-H 'Authorization: Token <dein-token>' \
-H 'Accept: application/json; charset=utf-8' Es folgen 2 Beispiele für das laden von Daten über die Redeem Info Route. Als erstes Beispiel wird das Ergebnis einer Kundenkarte angezeigt und als zweites Beispiel wird eine Artikel Rabattaktion gezeigt.
Das folgende Beispiel zeigt die einlösbaren Aktionen die ein Kunde über die Kundenkarte gesammelt hat. Er bekommt als Ergebnis 2 Aktionen zurück. Das erste Ergebnis ist eine Sammelkarte mit einlösbaren Aktionen zu sehen im children array. Das zweite Ergebnis ist ein einmal Rabatt der Neukunden gewährt wird. Der Kunde muss an der Kasse auswählen was er eingelöst haben will.
[
{
"card": {
"image_thumbnail": null,
"hash_id": "ac_JQ",
"uuid": "98eec0a5-4461-44b0-aa58-22f4cdf0a58b",
"image": null,
"title": "Bier König Sammelkarte",
"subtitle": "Sammele Punkte und löse sie gegen unsere Aktionen ein.",
"details": "",
"card_type": 0,
"bonus_type": 0,
"bonus_value": "99999999.99",
"bonus_usage": 2,
"minimum_value": "0.00",
"article_number": [],
"children": [
{
"image_thumbnail": null,
"hash_id": "cr_JQ:ac_zG:rb_oV4EG",
"uuid": "607b7587-68b6-4310-a7d8-9165aa109904",
"image": null,
"title": "5% Rabatt",
"subtitle": "für 50 Punkte bekommst du 5% Rabatt",
"details": "",
"bonus_type": 2,
"bonus_value": "5.00",
"bonus_usage": 1,
"minimum_value": "50.00",
"article_number": null
},
{
"image_thumbnail": null,
"hash_id": "cr_JQ:ac_8y:rb_oV4EG",
"uuid": "2d86b745-6df9-4796-a0ad-fe445ba4f022",
"image": null,
"title": "Mega Rabatt",
"subtitle": "für 150 Punkte bekommst du 17% Rabatt",
"details": "",
"bonus_type": 2,
"bonus_value": "15.00",
"bonus_usage": 1,
"minimum_value": "100.00",
"article_number": null
}
]
},
"hash_id": "cr_JQ",
"uuid": "abb62e6c-77e9-4c4c-b349-ffbca62b76fb",
"collected": "900.00",
"redeemed": false
},
{
"card": {
"image_thumbnail": null,
"hash_id": "ac_Ly",
"uuid": "fae6c054-7ab8-4b36-8769-0e759cdc97d7",
"image": null,
"title": "Bier König Einmalrabatt",
"subtitle": "",
"details": "10 Euro für deinen ersten Einkauf.",
"card_type": 0,
"bonus_type": 1,
"bonus_value": "10.00",
"bonus_usage": 2,
"minimum_value": "0.00",
"article_number": [
"ART001"
],
"children": []
},
"hash_id": "cr_Bv",
"uuid": "6fda51b7-5f63-4d13-8b31-6f8edbca9367",
"collected": "10.00",
"redeemed": false
}
]
Das folgende Beispiel, gibt eine Artikel Rabatt Aktion zurück. Da nur ein Element zurückgegeben wird kann die Kasse diesen Rabatt sofort einlösen (siehe hier).
[
{
"card": {
"image_thumbnail": null,
"hash_id": "ac_dP",
"uuid": "e3fc7c38-b62c-40a8-a8e5-5043011496c7",
"image": null,
"title": "Bier König Sammelkarte",
"subtitle": "Sammele Punkte und löse sie gegen Artikel ein.",
"details": "Mit dieser Karte kannst du Punkte sammeln und gegen Artikel an unserer Kasse einschränken.",
"card_type": 0,
"bonus_type": 0,
"bonus_value": "99999999.99",
"bonus_usage": 2,
"minimum_value": "0.00",
"article_number": [
"12"
],
"children": []
},
"hash_id": "cr_r0",
"uuid": "ccbbdfa5-499c-4051-bc7c-8f8c73ecd062",
"collected": "120.00",
"redeemed": false
}
]Response Body (wichtige Felder)
Name | DataType | Nullable | Description |
|---|---|---|---|
| string | false | ID die eingelöst werden soll. Für einfache Rabatte. Sollte eine |
| card object | false | Treuepass der eingelöst werden soll, enthält alle notwendigen Detailinformationen. |
Response Body Card
Name | DataType | Nullable | Description |
|---|---|---|---|
| string | false | Titel der Karte die eingelöst werden kann. Dieser Text ist für den Kunden bestimmt. |
| string | false | Sub Titel der Karte die eingelöst werden kann. Dieser Text ist für den Kunden bestimmt. |
| object | false | Detailbeschreibung der Karte. Dieser Text ist für den Kunden bestimmt. |
| Integer | false | Der Type der Karte, für die Kasse gibt es nur 2 Relevante Typen: 0 … Sammelpass (Artikelrabatt) → Siehe Karten Einlösen Response Body (Teil 1) 1 … Rabattkarte → Siehe Karten Einlösen Response Body (Teil 2) 2 … Gutscheinkarte → Siehe Karten Einlösen Response Body (Teil 3) |
| Integer | false | Die Art wie der Bonus gestaltet ist. 1 => Prozent Rabatt 2 => Absoluter Rabatt |
| array | false | Diese Array enthält Artikel PLUs (von der Kasse) die der Kunde in der einlösen kann. |
| decimal | false | Dieses Feld enthält den Wert der eingelöst werden kann. Sollte 9999999.99 als Wert gesetzt sein, kann diese Karte nicht selbst eingelöst werden. (Die Sammelkarte selbst kann nicht eingelöst werden, wohl aber ihre Aktionen im Feld |
| array | false | Ein Array von Der Kunde muss eine auswählen, ist nur eine im Array kann die Auswahl entfallen. |
Karte einlösen
Der Kunde löst eine Karte auf seinem Smartphone ein. Es wird ein QR-Code angezeigt welcher von der Kasse gescannt wird. Der QR-Code wird an den Server geschickt, der Server teilt der Kasse mit um welche Art von Einlösung es sich handelt.
Pro QR-Code handelt es sich um verschiedene Rabatte.
Artikel: Ist ein Artikel im QR-Code kodiert wird immer der Artikel zu 100% eingelöst wird. Es wir davon ausgegangen dass der erste übereinstimmende Artikel der auf der Rechnung auf Bessa gebucht wird. Sollte der Kunde einen anderen Artikel abgebucht haben wollen, muss dieser zuvor rausgesplittet werden.
Rabatt: Ein Standard Rabatt zB. 10% oder 10 Euro. Die Felder discount und usage werden hier verwendet.
Request
curl -X "POST" "https://api.bessa.app/v1/web/pos/cards/redeem/" \
-H 'Authorization: Token <dein-token>' \
-H 'Content-Type: application/json; charset=utf-8' \
-d $'{
"qr_code": "<redeemable-card-qr-code or card-hash-id>",
}'
Request Body
Name | DataType | Nullable | Description |
|---|---|---|---|
| string | false | QR-Code welcher vom Personal gescannt wurde. Bei einer Direkt Integration, ist es die |
Response Body
Der Kasse wird mitgeteilt welche PLUs, Rabatte oder Gutscheine eingelöst werden können. Hier 2 Beispiele:
{
"card_title": "Bier König Punktekarte",
"article_numbers": ["<1. plu>", "<2. plu>"]
}{
"card_title": "Bier König Rabatt",
"usage": 1,
"discount": "10.00"
}Response Code
Code | Description |
|---|---|
200 | Success |
400 | Already used, Card not full, Card not found |
401 | Invalid Token |
Response Structure
Name | DataType | Nullable | Description |
|---|---|---|---|
article_numbers | Array<string> | false | Optionales Feld, PLUs die eingelöst werden können max 10 * 50 |
card_title | String | false | Titel der eingelösten Karte. |
usage | Integer | false | Optionales Feld, Die Art des |
discount | Decimal | false | Optionales Feld, Wert für die Rabattberechnung hängt von vom Feld |
Einlösen abbrechen
Der Kunde hat eine Karte eingelöst, der QR Code wurde bereits von der Kasse gescannt. Jetzt stellt sich heraus dieser Code wurde fälschlicherweise eingelöst. Damit kann das Einlösen rückgängig gemacht werden.
Request
curl -X "POST" "https://api.bessa.app/v1/web/pos/cards/redeem/cancel/" \
-H 'Authorization: Token <dein-token>' \
-H 'Content-Type: application/json; charset=utf-8' \
-d $'{
"qr_code": "<redeemable-card-qr-code>"
}'Request Body
Name | DataType | Nullable | Description |
|---|---|---|---|
qr_code | string | false | QR-Code welcher vom Personal gescannt wurde |
Response Code
Code | Description |
|---|---|
200 | Success |
400 | Already cancelled, not redeemed yet, not found |
401 | Invalid Token |
Upload Phantom Bestellung/Rechnung
Immer wenn eine Rechnung erstellt wird muss die Kasse die Rechnungen inkl. der Positionen auf der Rechnung nach folgendem Schema an den Server schicken.
## Request
curl -X "POST" "https://api.bessa.app/v1/web/pos/invoice/" \
-H 'Authorization: Token <dein-token>' \
-H 'Content-Type: text/plain; charset=utf-8' \
-d $'{
"cash_box": "<deine-cashbox-id>"
"qr_code": "_R1-AT1_DEMO-KASSEN-ID_162_2019...+zA==",
"user": "<user id oder customer_card_id>",
"table": "12-12",
"invoice_number": "140",
"invoice_waiter": "101",
"invoice_timestamp": 1568619900,
"payment_type": "Bar",
"positions": [
{
"receipt_number": "181",
"article_number": "260",
"article_name": "Vini Bianco 0,1",
"article_group": 2,
"amount": 100,
"timestamp": 1568619900,
"vat": 2000,
"subtotal": 208,
"total": 250,
"price": 250,
"waiter": "101",
"position_type": "BON",
"food_type": "Getränk",
"sequence_number": 12,
},
...
...
]}'Request Body
Name | DataType | Max-Length | Nullable | Description |
|---|---|---|---|---|
cash_box | string | 128 | false | Deine Kassen id, es kann mehrere in einer Filiale geben |
work_station | sting | 64 | false | Sollte es mehrere Kassen im Verbund geben wird hier die ID der spezifischen Workstation übertragen |
qr_code | string | 4296 | false | QR-Code der Rechnung |
user | string | 128 | true | Die ID des Kunden zu dem die Rechnung gehört. |
table | string | 64 | true | Der Tisch zu dem diese Rechnung gehört |
invoice_number | string | 128 | false | Die Rechnungsnummer |
invoice_waiter | string | 64 | false | Der Kellner der die Rechnung erstellt hat |
invoice_timestamp | long | - | false | Unix-Timestamp, in Sekunden seit 1970, Beispiel: 1545730073. Der Zeitpunkt and dem die Rechnung erstellt wurde. |
payment_type | string | 16 | true | Bar, Visa, Treuepass, usw. wenn |
discounted | boolean | - | false | Gibt es für diese Rechnungen einen Discount, kann dieses Flag gesetzt werden. Das verhindert das Der Kunde diese Rechnung nochmal zum Punkte/Stempel sammeln verwenden kannst. |