Flavoso APILeitfädenBestellablauf
Bestellablauf
Der Lebenslauf einer Bestellung, ihre Felder, Steuerzeilen, Zahlarten und Quellen.
Der Lebenslauf
pending
neu, wartet auf den Betrieb
confirmed
angenommen
preparing
in Zubereitung
ready
fertig, bei Lieferung bereit für den Fahrer
completed
abgeholt, serviert oder geliefert
cancelled storniert, aus jedem offenen Stand; aus pending heißt das ablehnen
Vorwärts darf übersprungen werden (confirmed → ready), rückwärts geht nichts.
Ein Betrieb kann confirmed, preparing und ready abschalten; Annehmen schaltet dann auf den nächsten Stand, den er benutzt. Welche Stände er benutzt, steht in GET /store unter order_statuses.
Die Stände
| status | Bedeutung | Wie man dorthin kommt |
|---|---|---|
pending | Neu, wartet auf den Betrieb. | Die Bestellung entsteht. |
confirmed | Angenommen. | POST /orders/{id}/accept (wenn der Betrieb confirmed benutzt; sonst schaltet Annehmen auf seinen nächsten Stand) |
preparing | In Zubereitung. | POST /orders/{id}/status mit preparing |
ready | Fertig; bei Lieferung bereit für den Fahrer. | POST /orders/{id}/status mit ready |
completed | Abgeholt, serviert oder geliefert. | POST /orders/{id}/status mit completed |
cancelled | Storniert oder abgelehnt. | POST /orders/{id}/reject (nur aus pending) oder POST /orders/{id}/cancel |
Weiterschalten
- Vorwärts darf übersprungen werden, etwa
confirmed→ready. Rückwärts geht nicht: 409invalid_transition. - Ein Betrieb kann Stände abschalten. Welche er benutzt, steht in
GET /storeunterorder_statuses; ein abgeschalteter Stand antwortet mit 409stage_not_used. - Steht die Bestellung schon auf dem Ziel, kommt sie unverändert mit 200 zurück.
acceptschaltet eine Bestellung auspendingauf den nächsten Stand, den der Betrieb benutzt (hat erconfirmed,preparingundreadyabgeschaltet,completed); steht sie schon dahinter, kommt sie unverändert zurück, eine fertige oder stornierte antwortet mit 409invalid_transition. - Ablehnen und Stornieren nehmen einen Grund (
reason, bis 200 Zeichen; länger ergibt 400) für das Protokoll des Betriebs; der Gast sieht ihn nicht. - Jeder Wechsel läuft wie ein Klick im Dashboard: der Gast bekommt seine Nachricht, das Team seine Meldung, und das Protokoll des Betriebs nennt deine App.
# Accept (pending → confirmed)
curl -X POST https://api.flavoso.com/v1/orders/ORDER_ID/accept \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Idempotency-Key: accept-ORDER_ID"
# Advance: confirmed → preparing → ready → completed (skipping ahead is allowed)
curl -X POST https://api.flavoso.com/v1/orders/ORDER_ID/status \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{"status": "preparing"}'
# Reject an order that was not accepted yet; the reason goes to the audit log
curl -X POST https://api.flavoso.com/v1/orders/ORDER_ID/reject \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{"reason": "Out of dough"}'
# Cancel from any open status
curl -X POST https://api.flavoso.com/v1/orders/ORDER_ID/cancel \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{"reason": "Guest called to cancel"}'Wann es eine Bestellung gibt
Mit Zahlung vor Ort gibt es die Bestellung sofort. Mit Online-Zahlung erst, wenn die Zahlung bestätigt ist: vorher steht sie in keiner Liste und löst kein Ereignis aus. order.created kommt genau einmal je Bestellung.
Die Felder
| Feld | Bedeutung |
|---|---|
code | Kurzer Code, den der Gast sieht, etwa 3271CD. |
type | pickup, delivery oder dine_in. |
source | Woher sie kommt, siehe unten. |
requested_for | Wunschzeit einer Vorbestellung; null heißt so bald wie möglich. |
amounts | subtotal, delivery_fee, service_fee, discount, tip, total, alles in Cent. |
tax | Die Steuer nach Satz, siehe unten. |
payment | method, status, paid_at. |
customer | Name, bei Abholung und Lieferung die Telefonnummer. |
delivery | Bei Lieferung die Anschrift. |
table | Am Tisch: Kennung und Bezeichnung. |
note | Anmerkung des Gastes für die Küche. Allergien stehen oft hier. |
items | Positionen mit Menge, Einzel- und Zeilenpreis, Optionen (mit id, group_id und group_name) und dem beim Bestellen eingefrorenen Steuersatz (tax_rate_bps, null ohne hinterlegten Satz). |
external_id, acknowledged_at | Kennung und Übernahme durch deine App, siehe Kassenanbindung. In Ereignissen immer null. |
{
"object": "order",
"id": "cce01f52-5188-410f-9659-6ce26ba9b784",
"code": "3271CD",
"type": "delivery",
"status": "pending",
"source": "storefront",
"created_at": "2026-10-04T17:44:59.942Z",
"updated_at": "2026-10-04T17:45:10.118Z",
"requested_for": null,
"currency": "EUR",
"amounts": {
"subtotal": 2490,
"delivery_fee": 250,
"service_fee": 0,
"discount": 0,
"tip": 200,
"total": 2940
},
"tax": {
"included": true,
"lines": [
{
"rate_bps": 700,
"gross": 2421,
"net": 2263,
"tax": 158
},
{
"rate_bps": 1900,
"gross": 319,
"net": 268,
"tax": 51
}
]
},
"payment": {
"method": "online",
"status": "paid",
"paid_at": "2026-10-04T17:45:10.000Z"
},
"customer": {
"name": "Alex",
"phone": "+49 151 00000000"
},
"delivery": {
"address": "Musterstraße 1",
"postal_code": "10115",
"city": "Berlin"
},
"table": null,
"note": "Please ring twice",
"external_id": null,
"acknowledged_at": null,
"items": [
{
"id": "e9c0ce66-7f7f-42cf-a4bf-7d66f87768c1",
"product_id": "303b87c9-58a3-4644-9a8b-2841cc1f89d6",
"name": "Pizza Margherita",
"quantity": 2,
"unit_price": 1100,
"line_total": 2200,
"tax_rate_bps": 700,
"options": [
{
"id": "1f2e3d4c-5b6a-4798-8a7b-6c5d4e3f2a1b",
"name": "Extra cheese",
"price_delta": 150,
"group_id": "8e7d6c5b-4a39-4281-b0f9-e8d7c6b5a4f3",
"group_name": "Extras"
}
]
},
{
"id": "0d1e2f3a-4b5c-4d6e-8f70-81a2b3c4d5e6",
"product_id": "6a7b8c9d-0e1f-4a2b-9c3d-4e5f6a7b8c9d",
"name": "Cola 0,33 l",
"quantity": 1,
"unit_price": 290,
"line_total": 290,
"tax_rate_bps": 1900,
"options": []
}
]
}Steuerzeilen
tax teilt den Bruttobetrag der Bestellung nach Steuersatz auf: { "included": true, "lines": [{ "rate_bps", "gross", "net", "tax" }] }. Die Zeilen umfassen Positionen, Liefergebühr und Servicegebühr, nach derselben Rechnung wie Bon und DATEV-Export. Die Steuer ist im Preis enthalten (included: true).
Im Beispiel oben: Pizza zu 7 %, Cola zu 19 %, die Liefergebühr anteilig auf beide verteilt. Das Trinkgeld ist kein Umsatz und steht in keiner Zeile.
Hat der Betrieb für einen Anteil keinen Satz hinterlegt, steht dieser Anteil in einer Zeile mit rate_bps: null, und net und tax sind dort null, nicht 0. Buch ihn zur Klärung, nicht als steuerfrei.
Zahlarten
| payment.method | payment.status | Bedeutung |
|---|---|---|
online | paid | Online bezahlt. Die Bestellung gibt es erst ab hier. |
on_site | open | Zahlung vor Ort, noch offen: bar oder mit Karte bei Abholung, Lieferung oder am Tisch. |
online | open | Nie sichtbar: eine Online-Bestellung gibt es für die Schnittstelle erst, wenn sie bezahlt ist. Zahlungen vor Ort vermerkt Flavoso nicht, on_site bleibt deshalb open. |
Das Geld geht bei Online-Zahlung direkt an den Betrieb; Flavoso ist nie Zahlungsempfänger. Das Trinkgeld steht in amounts.tip und ist in total enthalten.
Quellen
| source | Woher |
|---|---|
storefront | Die Bestellseite des Betriebs, auch eingebettet auf seiner Website. |
table | Der QR-Code am Tisch. |
app | Die Flavoso-App für Gäste. |
Gastdaten
Eine Bestellung enthält nur, was für die Übergabe nötig ist: den Namen, bei Abholung und Lieferung die Telefonnummer, bei Lieferung die Anschrift. Nie die E-Mail-Adresse, nie das Gastkonto. Am Tisch fehlt auch die Telefonnummer. Siehe Datenschutz.
Etwas unklar geblieben? Schreib an support@flavoso.com und nenne die Kennung aus X-Request-Id. Damit finden wir deine Anfrage im Protokoll.