PUBLIC API V1 · ДЛЯ РАЗРАБОТЧИКОВ
Столы, зоны и свободное время
План зала, занятость стола за день и часы работы для формы брони.
Содержание
Зачем нужны столы
Бронь в MenuLab всегда относится к конкретному столу: так администратор видит её на плане зала, а два гостя не получают один стол на одно время. Перед созданием брони интеграция выбирает стол — сама или вместе с гостем.
Все методы этой статьи требуют права tables:read (свободное время на интервал — reservations:read). Заголовки и адрес — как в статье «Бронирование столов».
Список столов
GET /tables
| Параметр | Описание |
|---|---|
zone_id |
Только столы зоны |
min_seats |
Только столы, где мест не меньше указанного |
bookable_only |
По умолчанию 1: только активные столы в активных зонах. 0 — все столы, включая архивные |
curl "https://menulab.ru/api/v1/tables?min_seats=4" \
-H "X-API-Key: $MENULAB_API_KEY" \
-H "X-API-Secret: $MENULAB_API_SECRET" \
-H "Accept: application/json"
{
"success": true,
"data": [
{
"id": 12,
"number": "5",
"name": "Стол 5",
"seats": 4,
"is_active": true,
"zone": {"id": 3, "name": "Основной зал", "is_active": true}
}
]
}
| Поле | Описание |
|---|---|
id |
ID стола — его передают в table_id брони |
number |
Номер стола в зале, строка |
name |
Название для гостя. Если ресторан его не задал — «Стол {номер}» |
seats |
Количество мест |
zone |
Зона зала: основной зал, терраса, VIP и т. п. |
Один стол — GET /tables/{id}, ответ в том же формате.
Состав зала меняется редко. Кэшируйте список на несколько минут или до следующего открытия формы бронирования, но не на дни: ресторан может убрать стол в архив.
Зоны
GET /tables/zones
{
"success": true,
"data": [
{"id": 3, "name": "Основной зал", "is_active": true, "tables_count": 12, "sort_order": 10},
{"id": 4, "name": "Терраса", "is_active": false, "tables_count": 6, "sort_order": 20}
]
}
Зоны отсортированы так же, как в зале ресторана. В выключенной зоне (is_active: false) бронировать нельзя — например, летнюю террасу зимой. tables_count — количество активных столов зоны.
Свободные столы на время визита
POST /reservations/availability — права reservations:read. Это основной способ проверить, можно ли забронировать на конкретное время.
{"date": "2026-11-07", "time": "19:30", "duration_minutes": 120, "guests_count": 3}
В ответе — столы, свободные на весь интервал визита, с флагом fits_guests, и busy_table_ids — столы, занятые в этот интервал. Пример ответа — в статье «Бронирование столов».
Занятость стола за день
GET /tables/{id}/availability?date=YYYY-MM-DD
Возвращает занятые интервалы стола за сутки ресторана — удобно, чтобы нарисовать гостю шкалу времени конкретного стола.
{
"success": true,
"data": {
"table_id": 12,
"date": "2026-11-07",
"timezone": "Asia/Yekaterinburg",
"busy": [
{
"starts_at": "2026-11-07T19:30:00+05:00",
"ends_at": "2026-11-07T21:30:00+05:00",
"time_from": "19:30",
"time_to": "21:30",
"status": "confirmed"
}
]
}
}
Учитываются брони в статусах pending, confirmed и seated, в том числе брони, где стол объединён с другими. Интервал, начавшийся накануне и заканчивающийся после полуночи, тоже попадает в список. Имена и телефоны гостей не раскрываются.
Свободно всё время между занятыми интервалами. Брони можно ставить вплотную: если одна заканчивается в 21:30, следующая может начаться в 21:30.
Часы работы
GET /restaurant/hours (право menu:read) возвращает часы работы так, как они заданы в карточке ресторана в бэк-офисе, и особые дни — праздники, санитарные дни, сокращённые часы:
{
"success": true,
"data": {
"timezone": "Asia/Yekaterinburg",
"schedule": {
"monday": {"is_open": false, "mode": "closed", "open": null, "close": null, "intervals": []},
"friday": {"is_open": true, "mode": "open", "open": "12:00", "close": "02:00", "intervals": [{"from": "12:00", "to": "02:00"}]},
"saturday": {"is_open": true, "mode": "always", "open": "00:00", "close": "24:00", "intervals": []}
},
"special_days": [
{"date": "2026-12-31", "label": "Новый год", "is_open": true, "mode": "open", "open": "12:00", "close": "18:00", "intervals": [{"from": "12:00", "to": "18:00"}]}
]
}
}
mode:open— по интервалам,always— круглосуточно,closed— выходной.intervals— до трёх промежутков за день (например, перерыв днём).openиclose— начало первого и конец последнего, для простых сайтов.closeраньшеopen(как12:00–02:00) означает работу после полуночи.- Особый день заменяет обычный день недели на эту дату.
GET /restaurant/is-open отвечает, открыт ли ресторан прямо сейчас (is_open), до скольки (closes_at) и когда откроется (next_open_at).
MenuLab не запрещает бронь вне часов работы — администратор может принять гостей и в особый день, — поэтому не предлагайте гостю время, когда ресторан закрыт, на своей стороне.
Как собрать форму бронирования
- Покажите гостю выбор даты, времени и количества гостей. Время предлагайте с шагом 15 или 30 минут в часы работы из
/restaurant/hours. - Когда гость выбрал время, вызовите
POST /reservations/availability. - Если
total_availableравно 0 — предложите соседнее время. - Покажите подходящие столы (
fits_guests: true) или выберите стол сами — например, самый маленький из подходящих. - Создайте бронь
POST /reservations. Если пришёл409 TIME_SLOT_UNAVAILABLE, вернитесь к шагу 2.
Нужны ключи или права для интеграции? Их выдаёт администратор ресторана в бэк-офисе: Настройки → Интеграции → API-клиенты.