Для AI-агентов: markdown этой страницы — /docs/events-and-booking.mdиндекс документации — /llms.txt
Мероприятия, регистрация и запись
Обновлено
В TelegaFirst мероприятие собирает участников, а запись резервирует время и ресурс — например, кабинет или мастера. Команда микробизнеса ведёт работу в Telegram, собственный AI-агент владельца использует Hub в рамках выданных прав. Успешный результат нужно читать по объекту: регистрация, отметка посещения, ожидающая подтверждения запись и оплаченный заказ имеют разные состояния.
Это руководство показывает создание и чтение через управляющий доступ бизнеса. Клиентские публичные ссылки открываются по opaque-кодам, а кабинет покупателя дополнительно защищён его сессией. Примеры ниже содержат демонстрационные контрактные значения; реальной регистрации, бронирования, оплаты или проверки конкретного AI-клиента здесь не выполнялось.
Доступ и номера объектов
Перед работой подключите бизнес, проверьте выбранный slug, бота и readiness. MCP использует авторизацию и актуальный tools/list; REST-пути ниже относительны к вашему Hub. На этих REST routes принимается допустимый ключ в X-Api-Key либо Authorization: Bearer tgf_*. JWT владельца/покупателя не подставляется вместо этого ключа.
| Действие | Scope |
|---|---|
| Список мероприятий и регистраций, отдельная регистрация | events:read |
| Создать/изменить мероприятие, зарегистрировать, отменить регистрацию, отметить вход | events:write |
| Ресурсы, расписания и поиск доступности | booking:read |
| Создать/отменить запись, отметить посещение, изменить ресурсы/расписания | booking:write |
Права, тарифное окно, готовность бота и tenant-проверки продолжают действовать после выдачи credential. Для цепочки, каталога или денежной операции понадобятся права соответствующей семьи. Scopes и permissions.
Берите номер мероприятия, пользователя, товара и ресурса из ответа управляющего API. В регистрациях REST тело содержит числовые event_seq_num, user_seq_num, при необходимости catalog_seq_num. Номер в пути регистрации — каноническая десятичная строка положительного int4 (1..2147483647): без нуля, знака, пробелов, дроби, hex или экспоненты. Записи и их ресурсы также используют guarded seq_num; client_id определяется доступом, не JSON-телом.
Ссылки, которые можно открыть без сессии, используют непрозрачный код: /events/{code}, /booking/{code}, кодовый deeplink бота или QR чекина. Номер регистрации/ресурса не является публичным кодом. В кабинете покупателя номер доступен только после проверки владения. Не строите анонимные ссылки из seqNum; внутренние PK никогда не передаются через публичный API. Адреса и пагинация.
Подготовьте мероприятие
Прочитайте GET /api/v1/tools/events (200, events:read). Создание — POST /api/v1/tools/events (201, events:write, непустой POST требует Idempotency-Key). Пример строгого тела:
{"title":"Workshop","capacity":20,"target_registrations":30,"is_marketing_view":false,"auto_notify":true,"is_active":false,"is_public":true,"is_online":false}capacity — ограничение вместимости, target_registrations — цель набора. Цель не увеличивает фактическую вместимость. is_active и is_public — независимые поля; настройте их под ожидаемый способ доступа и проверьте возвращённую phase. Начало/конец, текущие настройки цепочек и привязанные билеты видны в результате чтения.
Изменение — PATCH /api/v1/tools/events (200) с seq_num и изменяемыми полями. Для режима входа доступны checkin_mode:"self_service" и "operator_only". Привязка билетов catalog_ids содержит строки с tenant-local номерами каталога; название поля не разрешает передать PK. [] снимает привязки. Для автоматизации передавайте возвращённые номера цепочки/шага в нужном слоте, например registration_chain_seq_num и registration_chain_step_seq; не придумывайте идентификаторы. Удаление — POST /api/v1/tools/events/delete с {"seq_num":7} (201).
Перед регистрацией проверьте актуальное мероприятие, вместимость, выбранный билет и клиента. Пример следующего раздела относится к уже существующим event 7, user 13, catalog 31 вашего тестового контекста; номера не гарантированы после создания в другом бизнесе.
Зарегистрируйте клиента и прочитайте результат
POST /api/v1/tools/event-registrations
Content-Type: application/json
Idempotency-Key: event-create-19
{"event_seq_num":7,"user_seq_num":13,"catalog_seq_num":31}Полный контрактный ответ 201:
{"outcome":"payment_required","registration":{"seqNum":19,"eventSeqNum":7,"userSeqNum":13,"catalogSeqNum":31,"status":"registered","checkedInAt":null,"createdAt":"2026-09-30T10:00:00.000Z","updatedAt":"2026-09-30T11:00:00.000Z"},"replayed":false}payment_required означает, что выбран платный билет. Эта операция регистрации сама не создаёт заказ или платёж. Для бесплатной регистрации без билета outcome — registered. Продолжение продажи согласуйте отдельно через каталог и продажи и платежи: подготовка → показ сценария человеку → подтверждение → исполнение. Внутренний AI в диалоге клиента только советует и передаёт запрос оператору; собственный агент владельца использует разрешённые money tools.
Для чтения одной регистрации: GET /api/v1/tools/event-registrations/19 (200). Для списка по мероприятию:
GET /api/v1/tools/event-registrations?cursor=8&limit=1&event_seq_num=7Полный контрактный ответ 200:
{"registrations":[{"seqNum":19,"eventSeqNum":7,"userSeqNum":13,"catalogSeqNum":31,"status":"registered","checkedInAt":null,"createdAt":"2026-09-30T10:00:00.000Z","updatedAt":"2026-09-30T11:00:00.000Z"}],"nextCursor":"19"}Default limit — 50, допустимо 1..100. Следующий запрос использует nextCursor при том же бизнесе и фильтре мероприятия; null завершает список. Cursor представляет номер последовательности; 0 и значения за границей int4 отклоняются. Не переносите курсор в другой бизнес или фильтр. Эти GET не используют HTTP response receipt.
MCP-эквиваленты: list_event_registrations, get_event_registration, create_event_registration, cancel_event_registration, check_in_event_registration. Для одиночной операции MCP принимает registration_seq_num; создание — те же числовые адреса. В MCP мутация передаёт обязательный idempotency_key в аргументах, в REST — Idempotency-Key в заголовке.
Отмена регистрации и вход на мероприятие
Отмена POST /api/v1/tools/event-registrations/19/cancel принимает строго пустое тело {} и обязательный новый Idempotency-Key (201). Для платного билета сервер возвращает outcome:"REFUND_REQUIRED" с прежней регистрацией: отмена не выполнена. Передайте финансовое решение человеку; возврат не следует угадывать из факта отмены. Для бесплатной регистрации успешный outcome:"cancelled" сопровождается status:"cancelled" и обновлённым updatedAt.
Отметка оператора: POST /api/v1/tools/event-registrations/19/check-in, строго {} и обязательный ключ. Полный контрактный ответ 201:
{"seqNum":19,"eventSeqNum":7,"userSeqNum":13,"catalogSeqNum":31,"status":"attended","checkedInAt":"2026-10-01T12:00:00.000Z","createdAt":"2026-09-30T10:00:00.000Z","updatedAt":"2026-10-01T12:00:00.000Z"}Это управляющая отметка оператора с проверкой tenant и events:write. QR для самостоятельного входа — отдельный публичный пропуск; не заменяйте его номером регистрации. Команда работает в Telegram. self_service и operator_only регулируют выбранный сценарий входа, а номера в Hub нужны для авторизованных операций.
Три мутации регистраций используют durable квитанцию, привязанную к бизнесу, операции и ключу. Удаление HTTP-кэша не превращает повтор в новую запись. Повтор создания/отмены возвращает сохранённый результат с replayed:true; check-in повторяет сохранённый объект без отдельного replay-флага. Другое тело или другой номер под тем же ключом — 422 IDEMPOTENCY_KEY_MISMATCH. Перед повтором сохраняйте исходные аргументы и проверяйте состояние. Повторы и конфликты.
Найдите время и создайте запись
Прочитайте
GET /api/v1/booking/resources(200) и выберите возвращённыйseqNumресурса. Сверьте активность, slot interval, advance/lead-time и ограничения активных записей клиента.Получите доступность для услуги и календарного диапазона.
start_date/end_date— дниYYYY-MM-DDв часовом поясе бизнеса. В конкретном слотеstartAt/endAtвозвращаются как абсолютные ISO timestamps.Выберите слот с
bookable:true. Результат поиска показывает доступность на момент чтения; окончательные ограничения проверяются при записи.Создайте запись с нужным ресурсом либо явным
resource_seq_num:null, если поручаете выбор серверу. Не опускайте поле вместо явного решения.
GET /api/v1/booking/availability?catalog_item_seq_num=4&resource_seq_num=11&start_date=2026-10-02&end_date=2026-10-03Ответ 200:
{"slots":[{"startAt":"2026-10-02T10:00:00.000Z","endAt":"2026-10-02T11:00:00.000Z","resourceSeqNum":11,"resourceName":"Room","bookable":true},{"startAt":"2026-10-02T11:00:00.000Z","endAt":"2026-10-02T12:00:00.000Z","resourceSeqNum":11,"resourceName":"Room","bookable":false}]}Запрос создания (booking:write):
POST /api/v1/booking/bookings
Content-Type: application/json
Idempotency-Key: booking-command
{"catalog_item_seq_num":4,"resource_seq_num":11,"user_seq_num":51,"start_at":"2026-10-02T10:00:00.000Z","end_at":"2026-10-02T11:00:00.000Z","quantity":2,"selection_mode":"full"}Полный контрактный ответ 201:
{"seqNum":31,"status":"pending","resourceSeqNum":11,"resourceName":"Room","catalogItemSeqNum":4,"userSeqNum":51,"selectionMode":"full","startAt":"2026-10-02T10:00:00.000Z","endAt":"2026-10-02T11:00:00.000Z","durationMinutes":60,"quantity":2,"didAttend":null,"createdAt":"2026-10-01T09:00:00.000Z"}pending — ожидающая решения запись, созданная агентом. Подтверждение остаётся за человеком-оператором; REST /confirm здесь не предусмотрен. Успешный поиск, создание записи и факт оплаты — разные результаты.
Варианты selection_mode: full, time_only, resource_only, open_inquiry. Для открытой заявки start_at:null и/или resource_seq_num:null передаются явно согласно выбранному варианту. Если указан end_at, длительность и множитель определяет сервер по диапазону и правилам услуги; quantity не заменяет эту проверку. Читайте фактические поля ответа, особенно для дневных интервалов и часового пояса бизнеса.
Отметьте посещение или отмените запись
У записи факт визита отмечается через POST /api/v1/booking/bookings/31/attendance (201, booking:write, обязательный Idempotency-Key):
{"did_attend":true}В контрактном ответе запись 31 получает status:"completed" и didAttend:true; при false — status:"no_show" и didAttend:false. Остальные адреса, интервал и дата создания сохраняются. Нельзя прислать собственный идентификатор того, кто поставил отметку: субъект определяется авторизованным доступом. Эта отметка не является /check-in мероприятия; у bookings такой маршрут отсутствует.
Отмена POST /api/v1/booking/bookings/31/cancel принимает, например, {"reason":"Change of plans"} и возвращает 201 с status:"cancelled". Пустое тело допустимо. Для непустого тела используйте ключ; его обязательность следует общему HTTP правилу. Недопустимый переход состояния возвращает конфликт, поэтому сверяйте результат, а не только факт HTTP-вызова. Связанные заказы/возвраты проверяются отдельным финансовым сценарием.
Расписания и изменения ресурсов
GET /api/v1/booking/resource-schedules читает расписания с необязательными resource_seq_num, cursor, limit (50 по умолчанию, максимум 100). Ответ содержит schedules и nextCursor; сохраняйте бизнес и фильтр ресурса между страницами. GET /api/v1/booking/resources/{seqNum} и GET /api/v1/booking/resource-schedules/{seqNum} читают отдельную карточку.
Для создания ресурсов/расписаний используйте POST соответствующего collection path с обязательным ключом. Изменение ресурса — PATCH /api/v1/booking/resources/{seqNum}; изменение/удаление расписания — PATCH/DELETE /api/v1/booking/resource-schedules/{seqNum}. Для этих изменений нужны Idempotency-Key и If-Match текущей прочитанной версии. Например, заголовок версии из контрактной карточки:
If-Match: W/"2026-09-30T11:00:00.000Z"Берите актуальное значение из чтения своей карточки: поле etag содержит timestamp, который в примере заключён в слабый ETag заголовка. При 428 PRECONDITION_REQUIRED добавьте If-Match; при 409 CONFLICT с detail STALE_VERSION перечитайте объект перед новой правкой. Расписание использует year, month, days, минуты суток и явные интервалы перерыва; допустимые сочетания и null проверяются схемой/доменом. Не считайте изменение расписания подтверждением уже ожидающей записи.
Разберите отказ до повтора
| Статус и код | Действие |
|---|---|
400 VALIDATION_ERROR | Исправить типы/поля, допустимый номер, дату и строгую форму тела |
400 IDEMPOTENCY_KEY_REQUIRED | Передать ключ там, где он обязателен; для регистраций пустое {} не отменяет это требование |
401 INVALID_API_KEY | Проверить аутентификацию и не заменять credential JWT другого субъекта |
403 INSUFFICIENT_SCOPE / PUBLISHABLE_KEY_NOT_ALLOWED / NO_ACTIVE_BOT | Проверить полномочия, credential, readiness и выбранный бизнес |
403 FORBIDDEN в durable регистрации | Проверить, принадлежит ли реальный credential текущему бизнесу; сохранённая квитанция не обходит эту проверку |
404 NOT_FOUND | Объект отсутствует или недоступен в вашем tenant; получить номер из актуального чтения |
409 IDEMPOTENCY_KEY_IN_FLIGHT | Сначала проверить состояние; незавершённая durable квитанция не даёт разрешения повторить эффект с новым ключом вслепую |
409 IDEMPOTENCY_KEY_FAILED | Проверить состояние и причину прежнего отказа; для нового согласованного действия нужен новый ключ |
409 CONFLICT | Прочитать detail: некорректный cursor, версия, состояние записи и отсутствие credential provenance требуют разных исправлений |
422 IDEMPOTENCY_KEY_MISMATCH | Повторить исходный запрос либо согласовать новый запрос с новым ключом |
428 PRECONDITION_REQUIRED | Для изменения ресурса/расписания прочитать версию и передать If-Match |
413 PAYLOAD_TOO_LARGE / ITEM_COUNT_EXCEEDED | Уменьшить запрос или пакет |
429 RATE_LIMIT_EXCEEDED / RATE_LIMIT_UNAVAILABLE | Учитывать Retry-After, если он есть; лимитер работает с отказом при недоступности |
500 INTERNAL_ERROR | Сохранить traceId и сначала прочитать состояние операции |
Для показанного POST /api/v1/booking/bookings нужны допустимый API credential и booking:write. Если не передать ни X-Api-Key, ни допустимый Authorization: Bearer tgf_*, проверка аутентификации завершится до создания записи. Полный контрактный отказ — HTTP 401, Content-Type: application/problem+json:
{
"type": "https://telegafirst.ru/docs/errors#INVALID_API_KEY",
"title": "Unauthorized",
"status": 401,
"instance": "/api/v1/booking/bookings",
"code": "INVALID_API_KEY",
"traceId": "0123456789abcdef0123456789abcdef",
"detail": "API key is required (X-Api-Key or Authorization: Bearer tgf_*)",
"hint": {
"reason": "The credential is unknown, revoked or expired.",
"recovery": "Issue a new credential for this account and authenticate with it."
}
}Здесь instance и traceId взяты из принятого контрактного стенда для этого конкретного пути; это не живой отказ и не идентификатор вашего обращения. Для диагностики сохраняйте фактический traceId своего ответа. Восстановите предусмотренную авторизацию и проверьте scope, бизнес и состояние перед повтором; ответ 401 не подтверждает успешную запись или оплату.
У HTTP-квитанций применимых booking/event shell-запросов срок 86400 секунд; durable регистрации используют собственную квитанцию и не зависят от этого срока HTTP-кэша. Возвращённые X-Client-Slug/X-Bot-Username помогают проверить бизнес, X-RateLimit-* — бюджет. ETag/If-Match применяются к указанным ресурсам/расписаниям; GET регистрации и ответы записи не становятся условным чтением только от наличия If-None-Match.
Подробные контракты: мероприятия REST, регистрации REST, записи REST, мероприятия MCP, записи MCP, ошибки. Результаты посещения и участия можно использовать в сегментах и цепочках. Публичные ссылки сайта получают серверный opaque-код в соответствующей .ru или .com зоне; обе зоны предусмотрены платформой, а выбор зоны не заменяет доступ или согласие на действие.