Flavoso APIGuidesOrder flow

Order flow

The lifecycle of an order, its fields, tax lines, payment methods and sources.

The lifecycle

pending

new, waiting for the restaurant

confirmed

accepted

preparing

being prepared

ready

done; for delivery, ready for the driver

completed

picked up, served or delivered

cancelled cancelled, from any open status; from pending this means rejecting

Moving forward may skip statuses (confirmed → ready), moving back is not possible.

A restaurant can switch off confirmed, preparing and ready; accepting then moves to the next status it uses. Which statuses it uses is listed in GET /store under order_statuses.

The statuses

statusMeaningHow to get there
pendingNew, waiting for the restaurant.The order is created.
confirmedAccepted.POST /orders/{id}/accept (if the restaurant uses confirmed; otherwise accept moves to its next status)
preparingBeing prepared.POST /orders/{id}/status with preparing
readyDone; for delivery, ready for the driver.POST /orders/{id}/status with ready
completedPicked up, served or delivered.POST /orders/{id}/status with completed
cancelledCancelled or rejected.POST /orders/{id}/reject (only from pending) or POST /orders/{id}/cancel

Advancing

  • Moving forward may skip statuses, for example confirmed → ready. Moving back is not possible: 409 invalid_transition.
  • A restaurant can switch statuses off. Which ones it uses is listed in GET /store under order_statuses; a switched-off status answers 409 stage_not_used.
  • If the order is already at the target, it comes back unchanged with 200. accept moves a pending order to the next status the restaurant uses (if it switched off confirmed, preparing and ready, completed); an order already past pending comes back unchanged, a completed or cancelled one answers 409 invalid_transition.
  • Reject and cancel take a reason (reason, up to 200 characters; longer gets 400) for the restaurant's audit log; the guest does not see it.
  • Every change works like a click in the dashboard: the guest gets their message, the team its notification, and the restaurant's audit log names your 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"}'

When an order exists

With payment on site, the order exists immediately. With online payment, only once the payment is confirmed: before that, it appears in no list and triggers no event. order.created arrives exactly once per order.

The fields

FieldMeaning
codeShort code the guest sees, for example 3271CD.
typepickup, delivery or dine_in.
sourceWhere it comes from, see below.
requested_forRequested time of a pre-order; null means as soon as possible.
amountssubtotal, delivery_fee, service_fee, discount, tip, total, all in cents.
taxThe tax per rate, see below.
paymentmethod, status, paid_at.
customerName, for pickup and delivery the phone number.
deliveryFor delivery, the address.
tableAt the table: id and label.
noteThe guest's note for the kitchen. Allergies are often here.
itemsItems with quantity, unit and line price, options (with id, group_id and group_name) and the tax rate frozen at order time (tax_rate_bps, null without a rate on file).
external_id, acknowledged_atYour app's id and takeover, see POS integration. Always null in events.
{
  "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": []
    }
  ]
}

Tax lines

tax splits the order's gross amount by tax rate: { "included": true, "lines": [{ "rate_bps", "gross", "net", "tax" }] }. The lines cover items, delivery fee and service fee, by the same calculation as the receipt and the DATEV export. The tax is included in the price (included: true).

In the example above: pizza at 7 %, cola at 19 %, the delivery fee split proportionally between both. The tip is not revenue and appears in no line.

If the restaurant has no rate on file for a share, that share is in a line with rate_bps: null, and net and tax are null there, not 0. Book it as needing clarification, not as tax-free.

Payment methods

payment.methodpayment.statusMeaning
onlinepaidPaid online. The order only exists from here on.
on_siteopenPayment on site, still open: cash or card at pickup, delivery or at the table.
onlineopenNever visible: an online order exists for the API only once it is paid. Payments on site are not recorded in Flavoso, so on_site stays open.

With online payment the money goes directly to the restaurant; Flavoso is never the payee. The tip is in amounts.tip and included in total.

Sources

sourceFrom
storefrontThe restaurant's ordering page, including when embedded on its website.
tableThe QR code at the table.
appThe Flavoso app for guests.

Guest data

An order contains only what is needed to hand it over: the name, for pickup and delivery the phone number, for delivery the address. Never the e-mail address, never the guest account. At the table the phone number is left out as well. See Privacy.

Still unclear? Write to support@flavoso.com and include the id from X-Request-Id. It lets us find your request in the log.