Меню
Меню можно получить двумя способами. Разница существенная, выберите осознанно.
Витрина /menus | Номенклатура /nomenclature | |
|---|---|---|
| Что внутри | Меню, собранное заведением для внешнего канала | Полный каталог товаров бренда |
| Названия, описания, картинки | Отдельные, под ваш канал | Внутренние, как в системе заведения |
| Цены | Цены витрины | Цены точки |
| Состав | Только отобранные заведением позиции | Все товары, включая непродаваемые |
| Когда использовать | По умолчанию | Если собираете витрину сами |
Начинайте с витрины. К номенклатуре переходите, только если витрины не хватает.
Витрина должна быть выбрана
Оба метода работают только если заведение выбрало для вашего ключа внешнее меню (Интеграции → API-ключи). Иначе /menus вернёт 409 с просьбой обратиться в заведение.
Так сделано, чтобы цена в меню всегда совпадала с ценой заказа: без выбранной витрины непонятно, по какому прайсу считать, и вы показали бы одну сумму, а в кассу ушла бы другая.
Список витрин
GET /menus
{
"menus": [
{ "id": 2, "name": "Мобильное приложение", "description": null, "updated_at": "2026-08-09 19:07:39" }
]
}
Ваш ключ, как правило, привязан к одной витрине — тогда в списке будет она одна. Так и должно быть: у заведения могут быть другие витрины (для агрегаторов доставки), и цены в них отличаются от ваших.
updated_at — когда витрину меняли последний раз. Удобно для решения, перезагружать меню или нет.
Витрина целиком
GET /menus/{id}?point_id={uuid}
point_id обязателен: от точки зависит стоп-лист.
{
"id": 2,
"name": "Мобильное приложение",
"categories": [
{
"id": 1964,
"name": "🥪 Сэндвичи и донеры",
"order_number": 2,
"image": "https://backend.mison.uz/uploads/menu/abc.webp"
}
],
"products": [
{
"product_id": 777,
"category_id": 1964,
"name": "Fanta 1 л",
"description": "Освежающий газированный напиток со вкусом апельсина",
"price": 12000,
"weight": 1000,
"unit": "мл",
"order_number": 1,
"image": "https://backend.mison.uz/uploads/products/xyz.webp",
"calories": 48,
"proteins": 0,
"fat": 0,
"carbohydrates": 12,
"is_available": true,
"available_quantity": null,
"modifier_groups": [
{
"id": 9,
"name": "Соусы",
"min": 0,
"max": 2,
"required": false,
"items": [
{ "product_id": 3884, "name": "Соус барбекю", "price": 2500, "min_amount": 0, "max_amount": 1 }
]
}
]
}
]
}
Поля товара
| Поле | Описание |
|---|---|
product_id | Идентификатор товара. Его передаёте в заказе |
category_id | Категория из categories |
price | Цена в валюте заведения, целое число |
weight / unit | Вес и единица измерения, могут быть null |
image | Готовая ссылка на картинку или null |
is_available | false — товар в стоп-листе, не показывайте его как доступный |
available_quantity | Остаток, если он ограничен. null — ограничения нет |
modifier_groups | Группы модификаторов, пустой массив если их нет |
order_number — порядок сортировки, задан заведением. Соблюдайте его: заведение расставило позиции осознанно.
Модификаторы
Группа модификаторов — это выбор, который делает пользователь: соус, размер, добавка.
| Поле группы | Описание |
|---|---|
min | Минимум позиций к выбору. 0 — можно ничего не выбирать |
max | Максимум позиций. 0 — без ограничения |
required | true — без выбора заказ отправлять нельзя |
items | Варианты выбора |
У варианта price — доплата за него, отдельной строкой в сумме заказа. min_amount / max_amount — сколько единиц одного варианта можно взять.
Группы без вариантов в ответе не приходят.
Номенклатура
GET /nomenclature?point_id={uuid}
Полный каталог бренда. Структура ответа такая же, как у витрины — categories и products с теми же полями, — но состав шире и названия внутренние.
{
"categories": [{ "id": 38627, "name": "Напитки", "parent_id": null, "order_number": 1, "image": null }],
"products": [
{
"product_id": 777,
"category_id": 38627,
"name": "Fanta 1 l",
"price": 12000,
"is_available": true,
"modifier_groups": []
}
]
}
Отличия от витрины:
- у категорий есть
parent_id— дерево может быть вложенным; - в списке есть товары, которые заведение не выставляет на продажу.
Цены здесь те же, что в вашей витрине: для товаров, которых в витрине нет, берётся цена точки. Это ровно те цены, по которым посчитается заказ.
Стоп-лист
GET /stop-list?point_id={uuid}
Позиции, которых сейчас нет или осталось ограниченное количество.
{
"stop_list": [
{ "product_id": 777, "quantity": 0 },
{ "product_id": 783, "quantity": 3 }
]
}
quantity | Значение |
|---|---|
0 | Товара нет. Заказ с ним будет отклонён |
> 0 | Осталось столько единиц. Больше заказать нельзя |
Товара нет в списке — ограничений нет.
Зачем отдельный метод
Меню тяжёлое и меняется редко, стоп-лист лёгкий и меняется в течение дня. Забирайте меню раз в час, стоп-лист — раз в минуту. Флаги is_available в меню тоже актуальны, но на момент запроса меню.
Кеширование
| Что | Как часто обновлять |
|---|---|
| Витрина, номенклатура | Раз в час, либо по изменению updated_at |
| Стоп-лист | Раз в 1–2 минуты |
| Справочники | Раз в сутки |
Сервер отклонит заказ с позицией из стоп-листа, даже если ваш кеш устарел, — деньги пользователя не пострадают. Но лучше не доводить до отказа: пользователь уже собрал корзину.