Заказы
Зал, самовывоз и доставка отправляются одним методом — тип задаётся полем order_type_id. Отдельных эндпоинтов для разных типов нет.
Расчёт корзины
POST /orders/calculate
Возвращает итоговую сумму без создания заказа. Вызывайте перед показом кнопки «Заказать»: здесь же проверяется стоп-лист и стоимость доставки, поэтому вы узнаете о недоступной позиции или недоступном адресе до того, как пользователь нажмёт оплату.
{
"point_id": "f40d9ea6-bb66-4d8a-9185-219916b68224",
"items": [
{ "product_id": 777, "quantity": 2, "modifiers": [{ "product_id": 3884, "quantity": 1 }] }
]
}
{
"items": [
{ "product_id": 777, "name": "Fanta 1 l", "quantity": 2, "price": 12000, "total": 24000, "is_modifier": false },
{ "product_id": 3884, "name": "Соус барбекю", "quantity": 1, "price": 2500, "total": 2500, "is_modifier": true }
],
"items_amount": 26500,
"delivery": null,
"total_amount": 26500
}
Модификаторы приходят отдельными строками с is_modifier: true — так же, как они попадут в чек.
items_amount — сумма позиций, total_amount — итог к оплате вместе с доставкой.
Расчёт доставки
Чтобы узнать стоимость доставки, добавьте order_type_id: 3 и координаты адреса:
{
"point_id": "f40d9ea6-bb66-4d8a-9185-219916b68224",
"order_type_id": 3,
"address": { "latitude": 41.1568, "longitude": 70.2103 },
"items": [{ "product_id": 16972, "quantity": 1 }]
}
{
"items": [ ... ],
"items_amount": 300000,
"delivery": {
"price": 10000,
"zone_id": 3,
"zone_name": "shohzone",
"minutes": 60,
"min_order_amount": 50000
},
"total_amount": 310000
}
| Поле | Описание |
|---|---|
price | Стоимость доставки по зоне, в которую попал адрес |
zone_name | Название зоны — можно показать пользователю |
minutes | Ориентировочное время доставки |
min_order_amount | Минимальная сумма заказа для этой зоны |
delivery: null — заказ не доставочный (не передан order_type_id: 3). price: 0 при заполненной зоне — доставка бесплатная.
Создание заказа
POST /orders
{
"point_id": "f40d9ea6-bb66-4d8a-9185-219916b68224",
"order_type_id": 3,
"payment_type_id": 59,
"external_id": "my-app-order-1",
"comment": "Не звонить в домофон",
"persons": 2,
"client": { "name": "Азиз", "phone": "998901112233" },
"address": {
"street": "Амира Темура 15",
"apartment": "42",
"floor": "4",
"entrance": "2",
"intercom": "42K",
"latitude": 41.311,
"longitude": 69.279
},
"items": [
{
"product_id": 777,
"quantity": 2,
"comment": "без льда",
"modifiers": [{ "product_id": 3884, "quantity": 1 }]
}
]
}
Параметры
| Поле | Обязательно | Описание |
|---|---|---|
point_id | да | UUID точки из GET /points |
order_type_id | да | 1 зал, 2 с собой, 3 доставка |
payment_type_id | да | Из GET /payment-types для этой точки |
client.phone | да | Телефон, только цифры или с + |
client.name | нет | Имя гостя |
items | да | Минимум одна позиция |
items[].product_id | да | Товар из меню |
items[].quantity | да | Количество, дробное допустимо |
items[].comment | нет | Пожелание по позиции, уйдёт на кухню |
items[].modifiers | нет | Выбранные модификаторы |
address | для доставки | Обязателен при order_type_id: 3 |
address.street | с адресом | Улица и дом |
external_id | нет, но присылайте | Ваш идентификатор заказа |
order_type_sub_id | нет | Подтип. По умолчанию — закреплённый за ключом |
table_id | нет | Стол, для заказа в зале |
persons | нет | Количество гостей, по умолчанию 1 |
comment | нет | Комментарий к заказу целиком |
scheduled_at | нет | Предзаказ, ISO-8601 с часовым поясом |
Ответ
{
"order_id": 11537716,
"external_id": "my-app-order-1",
"point_id": "f40d9ea6-bb66-4d8a-9185-219916b68224",
"status": "CREATED",
"status_name": "Создан",
"order_type_id": 3,
"order_type_sub_id": 65,
"payment_type_id": 59,
"client": { "name": "Азиз", "phone": "998901112233" },
"persons": 2,
"comment": "Не звонить в домофон",
"total_amount": 26500,
"total_amount_service": 26500,
"delivery_price": 0,
"discount": 0,
"created_at": "2026-08-18 23:06:29",
"scheduled_at": null,
"items": [
{
"product_id": 777,
"name": "Fanta 1 l",
"quantity": 2,
"price": 12000,
"total": 24000,
"comment": "без льда",
"modifiers": [
{ "product_id": 3884, "name": "Соус барбекю", "quantity": 1, "price": 2500, "total": 2500, "comment": null }
]
}
]
}
order_id — идентификатор заказа в Mison, по нему запрашивается статус. В ответе модификаторы вложены в свою позицию, а не идут отдельными строками.
Идемпотентность
Присылайте external_id всегда. Повторный запрос с тем же external_id на ту же точку вернёт уже созданный заказ, а не создаст второй.
Это значит, что при таймауте, обрыве связи или 502 можно спокойно повторить запрос тем же телом — дубля не будет. Без external_id такой защиты нет, и повтор создаст второй заказ.
Цены
Сумма считается по ценам заведения. Если вы пришлёте цену в запросе, она будет проигнорирована — заказ по своей цене отправить нельзя.
Считается ровно тот же прайс, что отдаёт меню для этой точки: прейскурант филиала и действующая на нём колонка цен. Меню и заказ берут цену по одному правилу, поэтому сумма сходится, если меню свежее.
Расхождение вашей суммы с total_amount в ответе означает, что кеш меню устарел — например, у заведения по времени включилась другая колонка цен. Перезагрузите меню.
Стоимость доставки
Доставку вы не присылаете — её считает сервер по зонам, которые заведение настроило в своём кабинете. Поэтому её нет в меню: доставка не товар, её цена зависит от адреса, а не от корзины.
Что нужно с вашей стороны — координаты адреса в блоке address. По ним определяется зона и её тариф.
Возможные исходы:
| Ситуация | Что происходит |
|---|---|
| Адрес попал в зону | Стоимость зоны попадает в заказ, total_amount уже с ней |
| Адрес вне всех зон | 400 — «Адрес вне зоны доставки этого заведения» |
| Сумма меньше минимальной для зоны | 400 — с указанием минимальной суммы |
| Координат нет, а зоны настроены | 400 — «Для доставки нужны координаты адреса» |
| У заведения зоны не настроены | Доставка 0, заказ проходит |
Узнать стоимость заранее и показать её пользователю — через POST /orders/calculate с теми же координатами.
Проверяйте адрес до оплаты
Вызывайте calculate сразу после того, как пользователь выбрал адрес. Иначе он соберёт корзину, нажмёт «Оплатить» и только тогда узнает, что заведение туда не доставляет.
Предзаказ
scheduled_at — заказ к определённому времени:
{ "scheduled_at": "2026-08-19T19:30:00+05:00" }
Требования: формат ISO-8601 с указанием часового пояса, время минимум на 30 минут вперёд от текущего. Заказ попадёт в статус PREORDER и уйдёт на кухню ближе к сроку.
Статус заказа
GET /orders/{order_id}
Ответ — тот же объект, что при создании, с актуальными status и составом.
Опрашивайте раз в 30 секунд, пока заказ не придёт в конечное состояние (CLOSED или DELETED). Чаще смысла нет.
Статусы заказа
status | status_name | Что произошло |
|---|---|---|
CREATED | Создан | Заказ принят системой, ждёт кассу |
AWAITING_PAYMENT | Ожидает оплаты | Онлайн-оплата не прошла, на кухню не ушёл |
AWAITING_CONFIRMATION | Ожидает подтверждения | Ждёт оператора заведения |
PREORDER | Предзаказ | Принят, ждёт своего времени |
UNCONFIRMED_ORDER | Ожидается | Касса приняла заказ |
COOKING | Готовится | Ушёл на кухню |
PACKED | Упакован | Готов к выдаче или передаче курьеру |
TAKEN_BY_COURIER | В пути | Курьер забрал |
DELIVERED | Доставлен | Доставлен клиенту |
CLOSED | Закрыт | Заказ завершён и оплачен |
DELETED | Удалён | Отменён |
Обычный путь доставки: CREATED → UNCONFIRMED_ORDER → COOKING → PACKED → TAKEN_BY_COURIER → DELIVERED → CLOSED.
Для зала и самовывоза курьерских статусов не будет: CREATED → UNCONFIRMED_ORDER → COOKING → CLOSED.
Порядок не гарантирован: заказ может перескочить статус, если на точке работают быстро. Ориентируйтесь на текущее значение, а не на ожидаемую последовательность.
Статусы вы только читаете
В запросе на создание заказа нет полей статуса: ни статуса заказа, ни статуса позиций, ни признака «отправлено на кухню». Вы присылаете состав и тип заказа, а статусы ведёт Mison сам и отдаёт их в ответе. Если пришлёте такие поля, они будут проигнорированы.
Так задумано намеренно: внутренние статусы Mison могут меняться, а ваша интеграция от этого не должна ломаться. Опирайтесь только на status из таблицы выше.
Когда заказ уходит на кухню
Каждая позиция печатается на кухне один раз. Когда именно, зависит от настройки ключа в кабинете:
| Настройка ключа | Когда кухня получает заказ |
|---|---|
| Автоподтверждение включено | Сразу, как только касса точки получила заказ. Подтверждать вручную не нужно |
| Автоподтверждение выключено | После того, как кассир подтвердит заказ |
Что при этом гарантируется:
- подтверждение заказа кассиром не печатает бланк второй раз, если кухня его уже получила;
- повторный запрос с тем же
external_idвозвращает уже созданный заказ и ничего не отправляет на кухню; - заказ, отменённый до того, как кухня его получила, не создаёт на кухне бланк отмены.
Заказ с scheduled_at (предзаказ) на кухню уходит ближе к назначенному времени, а не при создании.
Отмена заказа
POST /orders/{order_id}/cancel
{ "cancel_cause_id": 12, "comment": "Клиент передумал" }
Оба поля необязательны, но cancel_cause_id из GET /cancel-causes лучше передавать: без него отмена не попадёт в отчёт заведения по причинам.
В ответе — заказ со статусом DELETED.
Отмена возможна не всегда
Отменить через API можно, только пока заказ не принят кассой. После этого продукты уже списаны со склада, и отмена делается на самой кассе — API вернёт 409:
{ "message": "Заказ уже принят на точке, отмена возможна только через кассу" }
Повторная отмена уже отменённого заказа тоже даёт 409 с сообщением «Заказ уже отменён».
Заказ в зале и самовывоз
Отличаются от доставки только полями:
Зал (order_type_id: 1) — адрес не нужен, можно указать table_id:
{
"point_id": "f40d9ea6-bb66-4d8a-9185-219916b68224",
"order_type_id": 1,
"payment_type_id": 59,
"table_id": 14,
"persons": 4,
"external_id": "my-app-order-2",
"client": { "phone": "998901112233" },
"items": [{ "product_id": 777, "quantity": 1 }]
}
С собой (order_type_id: 2) — ни адреса, ни стола:
{
"point_id": "f40d9ea6-bb66-4d8a-9185-219916b68224",
"order_type_id": 2,
"payment_type_id": 59,
"external_id": "my-app-order-3",
"client": { "phone": "998901112233" },
"items": [{ "product_id": 777, "quantity": 1 }]
}
Клиент
Клиент определяется по телефону: если гость с таким номером у заведения уже есть, заказ привяжется к нему, а имя обновится. Отдельно создавать клиента не нужно.
Телефон присылайте в любом формате — лишние символы отбрасываются. 998901112233 и +998 90 111-22-33 дадут одного и того же клиента.