MenuLabБаза знаний Быстрый старт API

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 не запрещает бронь вне часов работы — администратор может принять гостей и в особый день, — поэтому не предлагайте гостю время, когда ресторан закрыт, на своей стороне.

Как собрать форму бронирования

  1. Покажите гостю выбор даты, времени и количества гостей. Время предлагайте с шагом 15 или 30 минут в часы работы из /restaurant/hours.
  2. Когда гость выбрал время, вызовите POST /reservations/availability.
  3. Если total_available равно 0 — предложите соседнее время.
  4. Покажите подходящие столы (fits_guests: true) или выберите стол сами — например, самый маленький из подходящих.
  5. Создайте бронь POST /reservations. Если пришёл 409 TIME_SLOT_UNAVAILABLE, вернитесь к шагу 2.

Нужны ключи или права для интеграции? Их выдаёт администратор ресторана в бэк-офисе: Настройки → Интеграции → API-клиенты.