К содержанию
TelegaFirst

Для 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. Перед повтором сохраняйте исходные аргументы и проверяйте состояние. Повторы и конфликты.

Найдите время и создайте запись

  1. Прочитайте GET /api/v1/booking/resources (200) и выберите возвращённый seqNum ресурса. Сверьте активность, slot interval, advance/lead-time и ограничения активных записей клиента.

  2. Получите доступность для услуги и календарного диапазона. start_date/end_date — дни YYYY-MM-DD в часовом поясе бизнеса. В конкретном слоте startAt/endAt возвращаются как абсолютные ISO timestamps.

  3. Выберите слот с bookable:true. Результат поиска показывает доступность на момент чтения; окончательные ограничения проверяются при записи.

  4. Создайте запись с нужным ресурсом либо явным 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 зоне; обе зоны предусмотрены платформой, а выбор зоны не заменяет доступ или согласие на действие.