API reference · Menu
Get the menu
GET
/v1/menuThe live menu exactly as the POS has it: categories, items, sizes, add-on groups, food type, GST and availability.
- Scope
menu:read - 600 / minute
Request
curl https://api.billzova.com/v1/menu \
-H "Authorization: Bearer $BILLZOVA_KEY"const res = await fetch('https://api.billzova.com/v1/menu', {
headers: { Authorization: `Bearer ${process.env.BILLZOVA_KEY}` },
});
const { categories } = await res.json();Response
{
"object": "menu",
"currency": "INR",
"gstApplies": true,
"categories": [{
"id": "c1", "name": "Biryani", "description": null, "imageUrl": null, "sortOrder": 0,
"items": [{
"id": "grp_7a2…", "name": "Chicken Biryani", "description": "Dum-cooked",
"foodType": "NON_VEG", "available": true, "prepMinutes": 25,
"menuItemId": null, "price": null,
"tax": { "rate": 5, "included": false },
"variants": [
{ "menuItemId": "m-half", "label": "Half", "price": { "amount": 18000, "currency": "INR", "display": "₹180" }, "isDefault": true, "available": true },
{ "menuItemId": "m-full", "label": "Full", "price": { "amount": 32000, "currency": "INR", "display": "₹320" }, "isDefault": false, "available": true }
],
"addOnGroups": [{
"id": "g1", "name": "Pick one dip", "min": 0, "max": 1,
"options": [{ "id": "dip-1", "name": "Mint", "price": { "amount": 1000, "currency": "INR", "display": "₹10" }, "available": true }]
}]
}]
}]
}Good to know
- An item with sizes has
menuItemId: nulland avariantslist — order the chosen variant'smenuItemId. An item without sizes has its ownmenuItemId. - The response has an
ETag. Send it back asIf-None-Matchand you get304 Not Modifiedwhen nothing changed — cheap to poll. - Money is always an integer
amountin paise plus adisplaystring (32000= ₹320.00).
Errors
| Code | HTTP | Meaning |
|---|---|---|
| UNAUTHENTICATED | 401 | Missing or malformed API key. Send it as Authorization: Bearer bz_live_sk_…. |
| SCOPE_MISSING | 403 | The key is not allowed to do that. |
| RATE_LIMITED | 429 | Too many requests — wait for Retry-After seconds. |