Zum Inhalt springen

Externe Bestellung API

Die Externe-Bestellung-API nimmt eine vollständig formulierte Bestellung aus einem beliebigen Fremdsystem entgegen — Lieferaggregator, White-Label- App, Kiosk, Voice-Agent — und steuert sie in die laufende APRO-Kassa am Zielstandort ein. Ein einziger POST genügt; die Bestellung erscheint sofort im Bestellmanager.

  • Endpunkt: POST https://my.apro.at/api/v1/external/order
  • Auth: API-Key im x-api-key
  • Content type: application/json

Bestellung einem Standort zuordnen

Die Bestellung muss genau einem Standort zugeordnet sein. Geben Sie einen der folgenden Werte mit — der erste nicht-leere Wert gewinnt:

  1. LocationID — numerische ID
  2. LocationShortCode — Kurz-Identifier (z. B. vienna-main)
  3. SpotID — konkreter Tisch/Zimmer/Abholpunkt (Standort wird abgeleitet)
  4. QRCode — gescannter APRO-QR-Code (Standort und Spot werden abgeleitet)

Fehlen alle, wird die Anfrage abgelehnt.

Request-Body

FeldTypPflichtBeschreibung
guidstringIdempotenz-Schlüssel. Kommt derselbe guid zweimal, wird das Duplikat ignoriert.
locationIdint?◻︎Siehe Routing oben.
locationShortCodestring◻︎Siehe Routing oben.
spotIdint?ID des Bestellziels (Tisch, Zimmer, Abhol-, Lieferstandort — alles Spots, nur unterschiedliche Typen). Entspricht spot.id der Externer-Katalog-API.
spotNumberint?Nummer des Spots, wenn die ID unbekannt ist. Aufgelöst über spot.number.
spotNamestringFallback, wenn weder spotId noch spotNumber auflöst. Lookup über spot.name — bevorzugt einen Spot vom Typ Table, danach beliebiger Spot am Standort.
roomNumberint?Nummer des Zimmer-Spots für Hotel-/Zimmerabrechnungs-Flows. Aufgelöst gegen einen SpotType.Room-Spot über spot.number (verschoben um RoomNrSpotNrOffset des Standorts); Fallback auf spot.alternativeName gegen die rohe Zimmernummer. Bei Treffer wird spotId gesetzt (falls noch nicht vorhanden) und die Bestellung an die aktive Reservierung des Zimmers gebunden.
roomIdint?Für zukünftige Erweiterungen reserviert. Wird aktuell akzeptiert, aber ignoriert — für ein Zimmer den spotId eines Room-Spots verwenden.
userInfoUserInfoWer bestellt — email ist Pflicht.
deliveryInfoDeliveryInfoLieferadresse. Pflicht bei Zustellung.
takeawaybooltrue für Mitnehmen, false für Vor Ort.
notestringFreitext-Notiz des Gastes (Allergene, Sonderwünsche).
qrCodestringSiehe Routing.
entriesEntry[]Bestellte Artikel.
preOrderTimelong?Vorbestellzeitpunkt, Unix-Zeit in Millisekunden UTC.
shortCodestringAbhol-/Lieferreferenz (z. B. zw1356).
tipdecimal?Trinkgeldhöhe.
isPaidbooltrue, wenn die Bestellung bereits extern bezahlt wurde.
grandTotaldecimal?Summe aller Artikel + Tip. Wird serverseitig gegengeprüft.

Entry

FeldTypPflichtBeschreibung
productNrstringProduktnummer in APRO.
namestringAnzeigename — rein informativ; APRO vertraut auf productNr.
preOrderTimelong?Vorbestellzeit pro Artikel.
quantitydoubleBestellmenge.
pricedouble?Übersteuert den Systempreis dieser Position (Rabatte, Kampagnen).
notestringArtikel-Notiz (z. B. Ohne Zwiebeln).
addonsAddon[]Zusatzoptionen.

Addon

FeldTypPflichtBeschreibung
productNrstringProduktnummer des Addons.
namestringAnzeigename.
quantitydoubleMenge.
pricedouble?Übersteuert den Systempreis.

UserInfo

FeldTypPflichtBeschreibung
firstNamestring
lastNamestring
emailstringKontakt-E-Mail für Belege und Status-Updates.
phonestring
localestringIETF-Locale, z. B. de-DE.
nicknamestringKurzname für Besteller/Abholer.

DeliveryInfo

FeldTypBeschreibung
namestringBezeichnung der Lieferadresse.
companyNamestringFirmenname.
citystringOrt.
zipstringPLZ.
streetstringStraße.
countrystringLand.
floorstringStockwerk.
stairwaystringStiege.
doorstringTüre.
notestringHinweis zur Lieferadresse.

Beispiele

Minimalbestellung

POST /api/v1/external/order
{
"locationShortCode": "vienna-main",
"takeaway": true,
"userInfo": { "email": "guest@example.com" },
"entries": [{ "productNr": "123", "quantity": 1 }],
"grandTotal": 9.99
}

Download: external-order-minimal.json

Vollständige Bestellung mit Lieferung und Beilagen

POST /api/v1/external/order
{
"guid": "123e4567-e89b-12d3-a456-426614174000",
"locationId": 101,
"spotId": 15,
"spotNumber": 10,
"shortCode": "zw1356",
"userInfo": {
"firstName": "Max",
"lastName": "Mustermann",
"email": "max.mustermann@example.com",
"phone": "+491234567890",
"locale": "de-DE",
"nickname": "Max"
},
"takeaway": false,
"note": "Bitte schnell liefern",
"qrCode": "QR1234567890",
"deliveryInfo": {
"name": "Max Mustermann",
"city": "Wien",
"zip": "1010",
"street": "Stephansplatz 1",
"country": "AT",
"floor": "3",
"stairway": "A",
"door": "12"
},
"entries": [
{
"productNr": "123",
"name": "Wiener Schnitzel",
"quantity": 2,
"price": 9.99,
"note": "Extra scharf",
"addons": [
{ "productNr": "501", "name": "Pommes", "quantity": 2, "price": 3.5 }
]
},
{ "productNr": "31231", "name": "Burger Classic", "quantity": 1, "note": "Ohne Zwiebeln" }
],
"preOrderTime": 1723574400000,
"tip": 1.2,
"isPaid": true,
"grandTotal": 28.18
}

Download: external-order-full.json

Idempotenz

Setzen Sie guid immer auf eine stabile, client-generierte UUID. APRO nutzt sie zur Deduplizierung bei Retries — geht eine Antwort verloren und Sie senden erneut, ist der zweite POST ein No-Op und liefert Erfolg.

Preisberechnung

APRO berechnet jede Position serverseitig aus productNr neu. price auf einem Entry oder Addon greift nur, wenn explizit übergeben; grandTotal wird mit dem Server-Total abgeglichen, inkonsistente Payloads werden abgelehnt. So wird der Wert zugleich Sicherheitsnetz und Vehikel für Kampagnen-Rabatte.