☰ Menu · Restaurants and cafes
Restaurants and cafes
Three things a venue's POS can do with Loyaltyfy: keep the QR menu in sync, take orders from tables, and run loyalty at the till.
Menu sync
The POS is usually the source of truth for prices and what is out of stock. Give every dish your SKU in external_id, then address dishes by that SKU; you never need to store our ids.
- 1Read what is there
GET /v1/menureturns categories, dishes and modifiers in all languages. Add?lang=ento get plain strings in one language. - 2Create what is missing
POST /v1/menu/itemswithcategory(a category id or your category code; an unknown code creates the category),external_id,namein one or more languages andprice. Sending the sameexternal_idagain returns the existing dish. - 3Push changes
On every change, or every few minutes, send
POST /v1/menu/items/bulkwith prices and availability. Up to 500 dishes per call; unknown SKUs come back innot_found.
curl https://loyaltyfy.io/api/v1/menu/items/bulk \
-H "Authorization: Bearer sk_test_..." \
-H "Content-Type: application/json" \
-d '{
"items": [
{ "item": "1001", "price": 4800 },
{ "item": "2040", "available": false },
{ "item": "3017", "price": 9900, "old_price": 12000 }
]
}'{
"object": "menu_bulk_result",
"updated": ["1001", "2040"],
"unchanged": [],
"not_found": ["3017"],
"failed": []
}Stop list: available: false keeps the dish visible with a "sold out" label and removes the order button; visible: false hides it. Modifiers have their own switch, so you can turn off oat milk without turning off coffee:
curl -X PATCH https://loyaltyfy.io/api/v1/menu/option_values/MOD-OAT \
-H "Authorization: Bearer sk_test_..." \
-H "Content-Type: application/json" \
-d '{ "available": false }'Orders from the table
With ordering turned on (Menu → Orders in the dashboard), guests who scan the table QR can send their cart to the venue. Each table gets its own link with the table number:
https://loyaltyfy.io/m/your-venue?table=12We price every order on our side from the current menu, so the POS can trust the amounts. Orders for a dish or a modifier on the stop list are refused before they reach you.
- 1Get new orders
Subscribe to the
order.createdwebhook, or pollGET /v1/orders?status=newevery 10 to 15 seconds. - 2Accept
Create the order in the POS, then call
POST /v1/orders/{id}/acceptwith your own order id asexternal_id. Use each line'sexternal_idto match your SKUs. - 3Move it along
PATCH /v1/orders/{id}withpreparing,ready,served,completed. OrPOST /v1/orders/{id}/rejectwith a reason if the kitchen cannot take it.
curl "https://loyaltyfy.io/api/v1/orders?status=new" \
-H "Authorization: Bearer sk_test_..."{
"object": "order",
"id": "0c69a81c-0fbc-4333-b26c-789566b9bea4",
"number": 10,
"status": "new",
"table": "7",
"note": "No onions, please",
"currency": "MDL",
"subtotal": 14000,
"item_count": 2,
"items": [
{
"item_id": "a48343bd-9f6e-424a-b003-fe790617f4d6",
"external_id": "2040",
"name": "Zeamă",
"quantity": 2,
"unit_price": 7000,
"total": 14000,
"options": []
}
],
"external_id": null,
"reject_reason": null,
"guest_language": "en",
"source": "qr_menu",
"livemode": true,
"created_at": "2026-10-06T18:14:48.233+00:00",
"accepted_at": null,
"completed_at": null,
"updated_at": "2026-10-06T18:14:48.233+00:00"
}curl -X POST https://loyaltyfy.io/api/v1/orders/0c69a81c-0fbc-4333-b26c-789566b9bea4/accept \
-H "Authorization: Bearer sk_test_..." \
-H "Content-Type: application/json" \
-d '{ "external_id": "POS-ORDER-55821" }'Statuses go forward only: new → accepted → preparing → ready → served → completed; new can also become rejected, and any open order can become cancelled. Steps can be skipped (accepted straight to completed is fine). A move backwards gets 409 invalid_status_transition. Venues without a POS integration manage the same statuses on the Orders screen, so it is fine if your POS only accepts and completes.
Loyalty at the cafe till
Same as any POS integration: look the guest up when the card is scanned, send the check when it is paid. For cafes with stamp cards ("every 6th coffee free"), the check is what earns the stamp. Send line_items with your SKUs so the venue sees which products guests buy.