Бронь столов
Раздел для сервисов бронирования: приложений и сайтов, где гость выбирает заведение, время и количество гостей. Через API вы видите залы и свободные столы, ставите бронь, переносите и отменяете её, а о посадке гостя, закрытии счёта и неявке узнаёте вебхуком.
Бронь, поставленная через API, — обычная бронь заведения: кассир видит её на схеме зала с названием вашего сервиса, при посадке открывает на столе счёт, а депозит, который вы приняли у гостя, ложится в этот счёт оплатой.
Доступ
Раздел открыт только ключу с галочкой «Бронирование столов». Её включает заведение в кабинете: Интеграции → API-ключи → Редактировать. Без галочки любой метод раздела отвечает 403:
{ "message": "У ключа нет доступа к бронированию столов. Включите его в кабинете: Интеграции → API-ключи" }
Там же, в меню ключа, заведение указывает адрес вашего вебхука.
Порядок работы
- Прочитайте правила точки —
GET /reservations/settings: длительность брони, часы работы, как заведение принимает брони без стола. - Загрузите залы и столы —
GET /reservations/halls. - Когда гость выбирает дату, покажите свободное время —
GET /reservations/availability. - Поставьте бронь —
POST /reservations. На стол или «на заведение», без стола. - Получайте события вебхуком: посадка, закрытие, неявка, отказ заведения.
- Если гость передумал — перенесите или отмените бронь.
Бронь на стол и бронь на заведение
На стол — вы передаёте table_id, выбранный по залам и свободным столам. Такая бронь подтверждается сразу (created): стол проверяется на пересечения при создании, ответ синхронный.
На заведение — table_id не передаётся: «4 гостя в 19:00». Стол назначит кассир заранее или посадит гостя на свободный, когда тот придёт. Так удобно сервисам, которым схема зала не нужна. Как такая бронь подтверждается, решает заведение:
- по умолчанию она приходит заявкой (
pending): кассир подтверждает её (created) или отклоняет с причиной (declined), вы узнаёте об этом вебхуком; - заведение может включить автоподтверждение с лимитом «не больше N гостей без стола на час начала» — в пределах лимита бронь сразу
created, сверх лимита — заявка.
Лимит виден в правилах точки — unassigned_auto_confirm_guests_per_hour. Заявку, которую заведение не подтвердило до начала брони, Mison отклоняет сам (declined, cancelled_by: system).
Статусы
| Статус | Что значит | Кто ставит |
|---|---|---|
pending | Заявка, ждёт решения заведения | Mison (бронь без стола сверх лимита) |
created | Подтверждена, ждём гостя | Mison или заведение |
opened | Гость сел, на столе открыт счёт | Заведение |
closed | Счёт закрыт | Заведение |
cancelled | Отменена — гостем, вами или заведением (cancelled_by) | Вы или заведение |
no_show | Гость не пришёл | Заведение или Mison через no_show_after_minutes после начала |
declined | Заявку отклонили | Заведение или Mison |
Вы можете только создать, перенести и отменить бронь. Посадку, закрытие и «не пришёл» ставит заведение — вы узнаёте о них вебхуком или в ленте изменений.
Время
Всё время — местное время точки без часового пояса (19:00), даты — YYYY-MM-DD. Пояс точки — в правилах точки, поле timezone.
Бронь через полночь допустима: начало 23:30, конец 01:30 — это 2 часа, конец на следующий день. Длительность — от 15 минут до 12 часов, бронь — не дальше чем на 90 дней вперёд и не в прошлом.
Правила точки
GET /reservations/settings?point_id={uuid}
{
"point_id": "c91fdd54-a539-44ab-8a8f-103838d31388",
"point_name": "Центральная",
"timezone": "Asia/Tashkent",
"default_duration_minutes": 120,
"min_duration_minutes": 15,
"max_duration_minutes": 720,
"max_days_ahead": 90,
"slot_step_minutes": 30,
"no_show_after_minutes": 60,
"unassigned_auto_confirm_guests_per_hour": null,
"working_hours": [
{ "day": 1, "is_open": true, "open": "10:00", "close": "23:00" },
{ "day": 7, "is_open": true, "open": "10:00", "close": "02:00" }
]
}
| Поле | Описание |
|---|---|
default_duration_minutes | Сколько длится бронь, если вы не передали конец |
no_show_after_minutes | Через сколько минут после начала бронь без посадки становится no_show. 0 — заведение отмечает неявку только вручную |
unassigned_auto_confirm_guests_per_hour | Лимит автоподтверждения броней без стола. null — каждая такая бронь приходит заявкой |
working_hours | День недели 1 — понедельник … 7 — воскресенье. close раньше open — работает за полночь |
Залы и столы
GET /reservations/halls?point_id={uuid}
{
"point_id": "c91fdd54-a539-44ab-8a8f-103838d31388",
"halls": [
{
"id": 2332,
"name": "Основной зал",
"tables": [
{ "id": 11237, "name": "1", "capacity": 4 },
{ "id": 11238, "name": "2", "capacity": null }
]
}
]
}
capacity — вместимость стола; null — заведение её не указало. Залы и столы меняются редко — кешируйте их на час.
Свободные столы и время
GET /reservations/availability?point_id={uuid}&date=2026-10-25&guests=4&time=19:00
| Параметр | Описание |
|---|---|
point_id | UUID точки, обязательно |
date | Дата брони, обязательно |
guests | Число гостей, обязательно. Столы меньшей вместимости отсеиваются, столы без вместимости — нет |
time | Время начала. С ним — свободные столы на этот интервал, без него — сетка слотов на день |
duration_minutes | Длительность. По умолчанию — default_duration_minutes точки |
На конкретное время:
{
"point_id": "c91fdd54-a539-44ab-8a8f-103838d31388",
"date": "2026-10-25",
"time": "19:00",
"end_time": "21:00",
"duration_minutes": 120,
"guests": 4,
"is_available": true,
"free_tables_count": 6,
"unassigned_reservations": 1,
"tables": [
{ "id": 11237, "name": "1", "hall_id": 2332, "hall_name": "Основной зал", "capacity": 4 }
]
}
Без time — сетка на день по часам работы точки с шагом slot_step_minutes; прошедшее время сегодняшнего дня не показывается:
{
"point_id": "c91fdd54-a539-44ab-8a8f-103838d31388",
"date": "2026-10-25",
"guests": 4,
"duration_minutes": 120,
"is_open": true,
"slots": [
{ "time": "10:00", "date": "2026-10-25", "is_available": true, "free_tables_count": 7, "table_ids": [11237, 11238] }
]
}
Как считается свободное:
- стол занимают брони в статусах
pending,created,opened— от всех источников: кассы, колл-центра, других сервисов. Отменённые, закрытые и «не пришёл» стол не держат; - брони без стола на это время уменьшают
free_tables_count— каждая займёт один стол, но какой, пока неизвестно (unassigned_reservations); - на сегодня занятыми считаются и столы, за которыми сейчас сидят гости без брони.
Ответ — снимок на момент запроса. Стол могут занять между вашими запросами, поэтому окончательно занятость проверяет создание брони.
Создать бронь
POST /reservations
{
"point_id": "c91fdd54-a539-44ab-8a8f-103838d31388",
"external_id": "booking-58123",
"date": "2026-10-25",
"start_time": "19:00",
"guests": 4,
"table_id": 11237,
"guest": { "phone": "+998901234567", "name": "Азиз" },
"comment": "У окна, день рождения",
"deposit": { "amount": 200000, "payment_type_id": 810 }
}
| Поле | Описание |
|---|---|
external_id | Обязательно. Ваш id брони. Повтор с тем же external_id вернёт уже созданную бронь с кодом 200 — повторяйте запрос при таймауте без опаски |
date, start_time | Обязательно. Местное время точки |
end_time или duration_minutes | Конец брони. Без них — default_duration_minutes точки |
guests | Обязательно, число гостей |
table_id | Стол. Без него — бронь на заведение, см. выше |
guest.phone | Обязательно. Гость находится по телефону или заводится в базе заведения |
guest.name | Как гость назвался у вас. Кассир увидит это имя; карточку клиента заведения оно не переписывает |
type | table (по умолчанию) или banquet |
comment | До 255 символов |
deposit | Депозит, который вы приняли у гостя |
Ответ 201 — бронь целиком:
{
"id": "72179267-7a2c-47a7-a4ae-8d1b48b2f977",
"external_id": "booking-58123",
"point_id": "c91fdd54-a539-44ab-8a8f-103838d31388",
"status": "created",
"type": "table",
"table": { "id": 11237, "name": "1", "hall_id": 2332, "hall_name": "Основной зал" },
"date": "2026-10-25",
"start_time": "19:00",
"end_time": "21:00",
"duration_minutes": 120,
"guests": 4,
"guest": { "name": "Азиз", "phone": "998901234567" },
"comment": "У окна, день рождения",
"deposit": { "amount": 200000, "payment_type_id": 810, "status": "held" },
"cancel_reason": null,
"cancelled_by": null,
"created_at": "2026-10-20 19:28:28",
"updated_at": "2026-10-20 19:28:28",
"status_changed_at": "2026-10-20 19:28:28"
}
id — UUID брони в Mison, по нему работают остальные методы.
Стол занят — 409, в conflict — интервал, которым он занят (без данных чужого гостя):
{
"message": "Стол уже занят: 19:00 - 21:00",
"conflict": { "table_id": 11237, "date": "2026-10-25", "start_time": "19:00", "end_time": "21:00" }
}
Депозит
Если гость внёс у вас предоплату, передайте её в deposit:
amount— сумма;payment_type_id— тип оплаты изGET /payment-types, который заведение завело под ваши депозиты (например, «Депозит — ваш сервис»). От его настройки зависит, как заведение учитывает эти деньги: поступлением на счёт или долгом сервиса.
Деньги держите вы — своим эквайрингом на счёт заведения или у себя с выплатой по договору с заведением. Mison в расчёты не вмешивается, он учитывает депозит:
deposit.status | Когда |
|---|---|
held | Внесён, ждёт визита |
applied | Гость сел — депозит лёг в счёт оплатой, кассир берёт только остаток |
retained | Гость не пришёл или отменил, депозит удержан |
refunded | Депозит возвращён гостю |
После неявки (no_show) Mison депозит сам не возвращает и не удерживает: решение — по вашим условиям с гостем, итог сообщите методом POST /reservations/{id}/deposit.
Перенести бронь
PATCH /reservations/{id}
Передавайте только то, что меняется: date, start_time, end_time, duration_minutes, guests, table_id (null — снять стол), comment, guest.name, deposit. Только пока бронь ждёт гостя (pending, created), иначе 409.
{ "start_time": "19:30", "guests": 5 }
Сдвиг начала сохраняет длительность брони. Ответ — бронь целиком; занятый стол — 409 с conflict. Перенос брони без стола заново проверяет лимит автоподтверждения: сверх лимита бронь вернётся в заявку.
Отменить бронь
POST /reservations/{id}/cancel
{ "reason": "Гость передумал", "cancelled_by": "guest" }
| Поле | Описание |
|---|---|
reason | Причина, её увидит кассир |
cancelled_by | guest (по умолчанию) — отменил гость; partner — отменили вы |
deposit_status | Обязательно, если по брони внесён депозит: retained или refunded |
Только пока бронь ждёт гостя. Повторная отмена уже отменённой брони отвечает 200.
Итог депозита
POST /reservations/{id}/deposit
{ "status": "retained" }
После неявки (no_show), отмены или отказа заведения: retained — депозит удержан, refunded — возвращён гостю. Сообщается один раз.
Список броней
GET /reservations?point_id={uuid}&date_from=2026-10-25&date_to=2026-10-31&status=created,pending
Ваши брони за период по дате брони, до 31 дня. Без дат — на сегодня. status — один или несколько через запятую.
С include=occupancy в ответе ещё и занятость столов чужими бронями за тот же период — без данных гостя:
{
"count": 1,
"has_more": false,
"reservations": [ { "id": "72179267-…", "status": "created" } ],
"occupancy": [
{ "point_id": "c91fdd54-…", "table_id": 11238, "date": "2026-10-25", "start_time": "18:00", "end_time": "20:00", "guests": 2, "is_seated": false }
]
}
Лента изменений
GET /reservations?changed_since=2026-10-20T00:00:00&after_id=0&limit=100
Ваши брони, изменённые после момента, по возрастанию времени изменения. В ответе next — подставьте его в следующий запрос, пока has_more равно true:
{ "count": 100, "has_more": true, "reservations": [], "next": { "changed_since": "2026-10-20 19:26:56", "after_id": 16121 } }
Лента — страховка к вебхукам: если ваш сервер был недоступен дольше, чем Mison повторяет отправку, догоните пропущенное здесь.
Одна бронь
GET /reservations/{id}
Только ваша бронь; чужая — 404.