{"openapi":"3.1.0","info":{"title":"AGIL Calls API","version":"0.1.0","description":"AGIL Calls — встраиваемая платформа видеозвонков: комнаты и WebRTC-сигналинг,\nчат и файлы, запись и субтитры, темы, права и аудит, AI-ассистенты, вебхуки.\n\n**С чего начать:** человекочитаемое руководство — `/docs/api-guide.md`,\nподробный справочник — `/docs/api.md`, контракт — `/docs/contract.md`.\nИнтерактивный офлайн-эксплорер — `/docs` (без CDN).\n\n**Авторизация:** `x-api-key` — админский ключ тенанта, только с сервера\n(никогда не отдавайте его в браузер); `authorization: Bearer <join token>` —\nкороткоживущий токен участника для звонка, чата, файлов, STT и ассистента.\n`GET /openapi.json` — только публичная спека, `/openapi.admin.json` — полная\n(доступ управляется `AGIL_DOCS_*` / `AGIL_ADMIN_*`).\n\n**Ошибки:** всегда `{error:{code,message}}`; коды — `unauthorized`, `forbidden`,\n`validation_failed`, `password_required`, `password_invalid`, `geo_blocked`,\n`room_locked`, `room_full`, `rate_limited`, `not_found`, `feature_disabled`,\n`provider_failed`, `stt_not_configured`, `internal_error`.\n\nWebSocket-сигналинг — `/ws?token=<join token>` (см. docs/api.md §10).","x-websocket":{"path":"/ws","auth":"token query param or anonymous room/tenant/name when AGIL_ALLOW_ANONYMOUS=1","messages":["hello","sdp","ice","chat","state","reaction","caption","integrity","location","ping","history","bye","analysis-request","assistant-query"]}},"servers":[{"url":"https://calls.guardify.ru","description":"AGIL Calls server"}],"tags":[{"name":"Public","description":"Доступно без авторизации: здоровье, ICE, публичный конфиг, фоны"},{"name":"Config","description":"Конфигурация тенанта (темы, фичи, безопасность, провайдеры)"},{"name":"Rooms","description":"Создание комнат и токенов (комнаты — in-memory)"},{"name":"Join","description":"Вход в звонок, чат и AI-ассистент от имени участника"},{"name":"Files","description":"Файлы: подписанные ссылки, лимиты, feature-gating"},{"name":"Recordings","description":"Записи звонков (серверное хранилище)"},{"name":"STT","description":"Серверный speech-to-text (501, если не настроен)"},{"name":"Admin","description":"Админ API тенанта: x-api-key, только с сервера"},{"name":"Docs","description":"OpenAPI и офлайн-эксплорер"}],"security":[],"paths":{"/v1/health":{"get":{"tags":["Public"],"summary":"Проверка живости и флаги безопасности","responses":{"200":{"description":"Server health","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HealthResponse"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"401":{"description":"Missing/invalid credentials","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"403":{"description":"Forbidden (wrong tenant, policy, feature)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"409":{"description":"Conflict (room full/exists)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"413":{"description":"Payload too large","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"423":{"description":"Room is locked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"429":{"description":"Rate limited / lockout","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"501":{"description":"Not configured (e.g. server STT)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}}}}},"/v1/ice":{"get":{"tags":["Public"],"summary":"ICE-серверы для RTCPeerConnection (STUN + TURN-пул)","responses":{"200":{"description":"ICE config","content":{"application/json":{"schema":{"type":"object","properties":{"iceServers":{"type":"array","items":{"$ref":"#/components/schemas/IceServer"}}}}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"401":{"description":"Missing/invalid credentials","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"403":{"description":"Forbidden (wrong tenant, policy, feature)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"409":{"description":"Conflict (room full/exists)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"413":{"description":"Payload too large","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"423":{"description":"Room is locked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"429":{"description":"Rate limited / lockout","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"501":{"description":"Not configured (e.g. server STT)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}}}}},"/v1/tenants/{tenantId}/config":{"get":{"tags":["Public"],"summary":"Публичный конфиг тенанта (тема, фичи)","parameters":[{"name":"tenantId","in":"path","required":true,"description":"Tenant id","schema":{"type":"string"}}],"responses":{"200":{"description":"Config + etag","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConfigEnvelope"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"401":{"description":"Missing/invalid credentials","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"403":{"description":"Forbidden (wrong tenant, policy, feature)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"409":{"description":"Conflict (room full/exists)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"413":{"description":"Payload too large","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"423":{"description":"Room is locked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"429":{"description":"Rate limited / lockout","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"501":{"description":"Not configured (e.g. server STT)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}}}},"put":{"tags":["Config"],"summary":"Заменить конфиг тенанта","security":[{"apiKey":[]}],"parameters":[{"name":"tenantId","in":"path","required":true,"description":"Tenant id","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TenantConfig"}}}},"responses":{"200":{"description":"Updated config","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConfigEnvelope"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"401":{"description":"Missing/invalid credentials","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"403":{"description":"Forbidden (wrong tenant, policy, feature)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"409":{"description":"Conflict (room full/exists)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"413":{"description":"Payload too large","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"423":{"description":"Room is locked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"429":{"description":"Rate limited / lockout","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"501":{"description":"Not configured (e.g. server STT)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}}}},"patch":{"tags":["Config"],"summary":"Частичное обновление конфига (тема, фичи, безопасность, провайдеры)","security":[{"apiKey":[]}],"parameters":[{"name":"tenantId","in":"path","required":true,"description":"Tenant id","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TenantConfigPatch"}}}},"responses":{"200":{"description":"Updated config","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConfigEnvelope"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"401":{"description":"Missing/invalid credentials","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"403":{"description":"Forbidden (wrong tenant, policy, feature)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"409":{"description":"Conflict (room full/exists)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"413":{"description":"Payload too large","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"423":{"description":"Room is locked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"429":{"description":"Rate limited / lockout","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"501":{"description":"Not configured (e.g. server STT)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}}}}},"/v1/tenants/{tenantId}/backgrounds":{"get":{"tags":["Public"],"summary":"Библиотека виртуальных фонов (builtin или внешний провайдер)","parameters":[{"name":"tenantId","in":"path","required":true,"description":"Tenant id","schema":{"type":"string"}}],"responses":{"200":{"description":"Available backgrounds","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BackgroundsResponse"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"401":{"description":"Missing/invalid credentials","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"403":{"description":"Forbidden (wrong tenant, policy, feature)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"409":{"description":"Conflict (room full/exists)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"413":{"description":"Payload too large","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"423":{"description":"Room is locked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"429":{"description":"Rate limited / lockout","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"501":{"description":"Not configured (e.g. server STT)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}}}}},"/v1/rooms":{"post":{"tags":["Rooms"],"summary":"Создать комнату (анонимно при AGIL_ALLOW_ANONYMOUS=1)","security":[{},{"apiKey":[]}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateRoomRequest"},"example":{"tenantId":"demo","name":"Планёрка","mode":"group"}}}},"responses":{"200":{"description":"Created room","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateRoomResponse"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"401":{"description":"Missing/invalid credentials","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"403":{"description":"Forbidden (wrong tenant, policy, feature)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"409":{"description":"Conflict (room full/exists)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"413":{"description":"Payload too large","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"423":{"description":"Room is locked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"429":{"description":"Rate limited / lockout","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"501":{"description":"Not configured (e.g. server STT)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}}},"description":"Вызывается сервером компании. Создаёт комнату и (для открытых комнат) сразу возвращает join-токен, joinUrl и embedUrl. Пароль комнаты хранится только хэшем."}},"/v1/tokens":{"post":{"tags":["Rooms"],"summary":"Выдать join-токен с фиксированными правами (admin)","security":[{"apiKey":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TokenRequest"},"example":{"tenantId":"demo","roomId":"room-1","participant":{"name":"Анна","role":"guest"},"permissions":["chat","fileShare","screenShare"]}}}},"responses":{"200":{"description":"Issued token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TokenResponse"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"401":{"description":"Missing/invalid credentials","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"403":{"description":"Forbidden (wrong tenant, policy, feature)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"409":{"description":"Conflict (room full/exists)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"413":{"description":"Payload too large","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"423":{"description":"Room is locked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"429":{"description":"Rate limited / lockout","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"501":{"description":"Not configured (e.g. server STT)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}}},"description":"Вызывается сервером компании. Выдаёт короткоживущий токен участника с `permissions` (или правами роли, включая кастомную `roleId`). Токен передаётся браузеру; админский ключ — никогда."}},"/v1/rooms/{roomId}":{"get":{"tags":["Rooms"],"summary":"Информация о комнате и участники","security":[{"apiKey":[]}],"parameters":[{"name":"roomId","in":"path","required":true,"description":"Room id","schema":{"type":"string"}}],"responses":{"200":{"description":"Room snapshot","content":{"application/json":{"schema":{"type":"object","properties":{"room":{"$ref":"#/components/schemas/RoomInfo"},"participants":{"type":"array","items":{"$ref":"#/components/schemas/Participant"}},"createdAt":{"type":"number"}}}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"401":{"description":"Missing/invalid credentials","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"403":{"description":"Forbidden (wrong tenant, policy, feature)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"409":{"description":"Conflict (room full/exists)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"413":{"description":"Payload too large","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"423":{"description":"Room is locked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"429":{"description":"Rate limited / lockout","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"501":{"description":"Not configured (e.g. server STT)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}}}},"delete":{"tags":["Rooms"],"summary":"Закрыть комнату","security":[{"apiKey":[]}],"parameters":[{"name":"roomId","in":"path","required":true,"description":"Room id","schema":{"type":"string"}}],"responses":{"200":{"description":"Closed","content":{"application/json":{"schema":{"type":"object","properties":{"closed":{"type":"boolean"}}}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"401":{"description":"Missing/invalid credentials","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"403":{"description":"Forbidden (wrong tenant, policy, feature)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"409":{"description":"Conflict (room full/exists)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"413":{"description":"Payload too large","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"423":{"description":"Room is locked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"429":{"description":"Rate limited / lockout","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"501":{"description":"Not configured (e.g. server STT)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}}}}},"/v1/rooms/{roomId}/messages":{"get":{"tags":["Rooms"],"summary":"История чата комнаты","security":[{"apiKey":[]}],"parameters":[{"name":"roomId","in":"path","required":true,"description":"Room id","schema":{"type":"string"}},{"name":"limit","in":"query","required":false,"description":"Max messages (1..200)","schema":{"type":"integer"}}],"responses":{"200":{"description":"Messages","content":{"application/json":{"schema":{"type":"object","properties":{"messages":{"type":"array","items":{"$ref":"#/components/schemas/ChatMessage"}}}}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"401":{"description":"Missing/invalid credentials","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"403":{"description":"Forbidden (wrong tenant, policy, feature)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"409":{"description":"Conflict (room full/exists)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"413":{"description":"Payload too large","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"423":{"description":"Room is locked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"429":{"description":"Rate limited / lockout","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"501":{"description":"Not configured (e.g. server STT)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}}}}},"/v1/rooms/{roomId}/calendar.ics":{"get":{"tags":["Join"],"summary":"Download a room as an .ics calendar event (UTC VEVENT)","parameters":[{"name":"roomId","in":"path","required":true,"description":"Room id","schema":{"type":"string"}},{"name":"start","in":"query","required":false,"description":"Event start (ISO 8601, default now)","schema":{"type":"string"}},{"name":"durationMin","in":"query","required":false,"description":"Duration 15..1440 (default 60)","schema":{"type":"integer"}},{"name":"download","in":"query","required":false,"description":"1 = attachment","schema":{"type":"string"}}],"responses":{"200":{"description":"text/calendar","content":{"text/calendar":{"schema":{"type":"string"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"401":{"description":"Missing/invalid credentials","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"403":{"description":"Forbidden (wrong tenant, policy, feature)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"409":{"description":"Conflict (room full/exists)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"413":{"description":"Payload too large","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"423":{"description":"Room is locked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"429":{"description":"Rate limited / lockout","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"501":{"description":"Not configured (e.g. server STT)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}}}}},"/v1/rooms/{roomId}/lobby":{"get":{"tags":["Join"],"summary":"Waiting-room queue (host/moderator or tenant admin key)","security":[{},{"bearer":[]},{"apiKey":[]}],"parameters":[{"name":"roomId","in":"path","required":true,"description":"Room id","schema":{"type":"string"}}],"responses":{"200":{"description":"Pending join requests","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LobbyRequestsResponse"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"401":{"description":"Missing/invalid credentials","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"403":{"description":"Forbidden (wrong tenant, policy, feature)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"409":{"description":"Conflict (room full/exists)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"413":{"description":"Payload too large","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"423":{"description":"Room is locked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"429":{"description":"Rate limited / lockout","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"501":{"description":"Not configured (e.g. server STT)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}}}}},"/v1/rooms/{roomId}/lobby/{requestId}":{"get":{"tags":["Join"],"summary":"Poll a waiting-room request (admitted token returned once)","parameters":[{"name":"roomId","in":"path","required":true,"description":"Room id","schema":{"type":"string"}},{"name":"requestId","in":"path","required":true,"description":"Lobby request id","schema":{"type":"string"}}],"responses":{"200":{"description":"Request status","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LobbyStatusResponse"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"401":{"description":"Missing/invalid credentials","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"403":{"description":"Forbidden (wrong tenant, policy, feature)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"409":{"description":"Conflict (room full/exists)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"413":{"description":"Payload too large","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"423":{"description":"Room is locked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"429":{"description":"Rate limited / lockout","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"501":{"description":"Not configured (e.g. server STT)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}}}},"delete":{"tags":["Join"],"summary":"Kick/remove a waiting guest from the queue","security":[{},{"bearer":[]},{"apiKey":[]}],"parameters":[{"name":"roomId","in":"path","required":true,"description":"Room id","schema":{"type":"string"}},{"name":"requestId","in":"path","required":true,"description":"Lobby request id","schema":{"type":"string"}}],"responses":{"200":{"description":"Removed from the queue","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LobbyDecisionResponse"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"401":{"description":"Missing/invalid credentials","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"403":{"description":"Forbidden (wrong tenant, policy, feature)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"409":{"description":"Conflict (room full/exists)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"413":{"description":"Payload too large","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"423":{"description":"Room is locked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"429":{"description":"Rate limited / lockout","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"501":{"description":"Not configured (e.g. server STT)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}}}}},"/v1/rooms/{roomId}/lobby/{requestId}/admit":{"post":{"tags":["Join"],"summary":"Admit a waiting guest (host/moderator or tenant admin key)","security":[{},{"bearer":[]},{"apiKey":[]}],"parameters":[{"name":"roomId","in":"path","required":true,"description":"Room id","schema":{"type":"string"}},{"name":"requestId","in":"path","required":true,"description":"Lobby request id","schema":{"type":"string"}}],"responses":{"200":{"description":"Admitted guest with a join token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JoinRoomResponse"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"401":{"description":"Missing/invalid credentials","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"403":{"description":"Forbidden (wrong tenant, policy, feature)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"409":{"description":"Conflict (room full/exists)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"413":{"description":"Payload too large","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"423":{"description":"Room is locked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"429":{"description":"Rate limited / lockout","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"501":{"description":"Not configured (e.g. server STT)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}}}}},"/v1/rooms/{roomId}/lobby/{requestId}/reject":{"post":{"tags":["Join"],"summary":"Reject a waiting guest (body {reason?})","security":[{},{"bearer":[]},{"apiKey":[]}],"parameters":[{"name":"roomId","in":"path","required":true,"description":"Room id","schema":{"type":"string"}},{"name":"requestId","in":"path","required":true,"description":"Lobby request id","schema":{"type":"string"}}],"responses":{"200":{"description":"Rejected","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LobbyDecisionResponse"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"401":{"description":"Missing/invalid credentials","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"403":{"description":"Forbidden (wrong tenant, policy, feature)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"409":{"description":"Conflict (room full/exists)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"413":{"description":"Payload too large","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"423":{"description":"Room is locked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"429":{"description":"Rate limited / lockout","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"501":{"description":"Not configured (e.g. server STT)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}}}}},"/v1/rooms/{roomId}/breakouts":{"get":{"tags":["Join"],"summary":"Current breakout plan (host/moderator or tenant admin key)","security":[{},{"bearer":[]},{"apiKey":[]}],"parameters":[{"name":"roomId","in":"path","required":true,"description":"Room id","schema":{"type":"string"}}],"responses":{"200":{"description":"Active/last plan","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BreakoutListResponse"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"401":{"description":"Missing/invalid credentials","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"403":{"description":"Forbidden (wrong tenant, policy, feature)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"409":{"description":"Conflict (room full/exists)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"413":{"description":"Payload too large","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"423":{"description":"Room is locked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"429":{"description":"Rate limited / lockout","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"501":{"description":"Not configured (e.g. server STT)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}}}}},"/v1/rooms/{roomId}/breakouts/start":{"post":{"tags":["Join"],"summary":"Start breakout rooms: create child rooms, assign participants, issue child-room tokens","security":[{},{"bearer":[]},{"apiKey":[]}],"parameters":[{"name":"roomId","in":"path","required":true,"description":"Room id","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateBreakoutRequest"},"example":{"mode":"random","count":2,"durationMin":15,"allowReturn":true}}}},"responses":{"200":{"description":"Created plan (WS: breakout.started + per-participant breakout.assigned)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BreakoutPlan"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"401":{"description":"Missing/invalid credentials","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"403":{"description":"Forbidden (wrong tenant, policy, feature)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"409":{"description":"Conflict (room full/exists)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"413":{"description":"Payload too large","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"423":{"description":"Room is locked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"429":{"description":"Rate limited / lockout","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"501":{"description":"Not configured (e.g. server STT)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}}}}},"/v1/rooms/{roomId}/breakouts/close":{"post":{"tags":["Join"],"summary":"Close breakout rooms (child rooms removed, plan closed)","security":[{},{"bearer":[]},{"apiKey":[]}],"parameters":[{"name":"roomId","in":"path","required":true,"description":"Room id","schema":{"type":"string"}}],"responses":{"200":{"description":"Closed plan","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BreakoutPlan"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"401":{"description":"Missing/invalid credentials","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"403":{"description":"Forbidden (wrong tenant, policy, feature)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"409":{"description":"Conflict (room full/exists)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"413":{"description":"Payload too large","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"423":{"description":"Room is locked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"429":{"description":"Rate limited / lockout","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"501":{"description":"Not configured (e.g. server STT)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}}}}},"/v1/rooms/{roomId}/breakouts/return":{"post":{"tags":["Join"],"summary":"Return to the main room (participant token; 403 when allowReturn=false)","security":[{"bearer":[]}],"parameters":[{"name":"roomId","in":"path","required":true,"description":"Room id","schema":{"type":"string"}}],"responses":{"200":{"description":"Return target","content":{"application/json":{"schema":{"type":"object","properties":{"returnToRoomId":{"type":"string"}}}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"401":{"description":"Missing/invalid credentials","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"403":{"description":"Forbidden (wrong tenant, policy, feature)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"409":{"description":"Conflict (room full/exists)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"413":{"description":"Payload too large","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"423":{"description":"Room is locked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"429":{"description":"Rate limited / lockout","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"501":{"description":"Not configured (e.g. server STT)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}}}}},"/v1/rooms/{roomId}/polls":{"get":{"tags":["Join"],"summary":"Room polls/Q&A with results and personal selected/voted flags","security":[{},{"bearer":[]},{"apiKey":[]}],"parameters":[{"name":"roomId","in":"path","required":true,"description":"Room id","schema":{"type":"string"}}],"responses":{"200":{"description":"Polls","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PollListResponse"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"401":{"description":"Missing/invalid credentials","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"403":{"description":"Forbidden (wrong tenant, policy, feature)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"409":{"description":"Conflict (room full/exists)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"413":{"description":"Payload too large","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"423":{"description":"Room is locked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"429":{"description":"Rate limited / lockout","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"501":{"description":"Not configured (e.g. server STT)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}}}},"post":{"tags":["Join"],"summary":"Create a poll or Q&A (host/moderator only)","security":[{},{"bearer":[]},{"apiKey":[]}],"parameters":[{"name":"roomId","in":"path","required":true,"description":"Room id","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreatePollRequest"},"example":{"question":"Куда идём на обед?","options":[{"text":"Пицца"},{"text":"Суши"}],"multiple":false,"kind":"poll"}}}},"responses":{"200":{"description":"Created poll (broadcast via poll.updated)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RoomPoll"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"401":{"description":"Missing/invalid credentials","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"403":{"description":"Forbidden (wrong tenant, policy, feature)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"409":{"description":"Conflict (room full/exists)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"413":{"description":"Payload too large","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"423":{"description":"Room is locked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"429":{"description":"Rate limited / lockout","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"501":{"description":"Not configured (e.g. server STT)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}}}}},"/v1/rooms/{roomId}/polls/{pollId}/vote":{"post":{"tags":["Join"],"summary":"Vote in a poll (one vote per participant; multiple optionIds when multiple=true)","security":[{"bearer":[]}],"parameters":[{"name":"roomId","in":"path","required":true,"description":"Room id","schema":{"type":"string"}},{"name":"pollId","in":"path","required":true,"description":"Poll id","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VotePollRequest"},"example":{"optionIds":["option-id"]}}}},"responses":{"200":{"description":"Vote result (accepted or already_voted)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PollVoteResponse"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"401":{"description":"Missing/invalid credentials","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"403":{"description":"Forbidden (wrong tenant, policy, feature)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"409":{"description":"Conflict (room full/exists)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"413":{"description":"Payload too large","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"423":{"description":"Room is locked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"429":{"description":"Rate limited / lockout","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"501":{"description":"Not configured (e.g. server STT)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}}}}},"/v1/rooms/{roomId}/polls/{pollId}/close":{"post":{"tags":["Join"],"summary":"Close a poll (host/moderator only)","security":[{},{"bearer":[]},{"apiKey":[]}],"parameters":[{"name":"roomId","in":"path","required":true,"description":"Room id","schema":{"type":"string"}},{"name":"pollId","in":"path","required":true,"description":"Poll id","schema":{"type":"string"}}],"responses":{"200":{"description":"Closed poll","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RoomPoll"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"401":{"description":"Missing/invalid credentials","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"403":{"description":"Forbidden (wrong tenant, policy, feature)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"409":{"description":"Conflict (room full/exists)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"413":{"description":"Payload too large","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"423":{"description":"Room is locked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"429":{"description":"Rate limited / lockout","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"501":{"description":"Not configured (e.g. server STT)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}}}}},"/v1/rooms/{roomId}/join":{"post":{"tags":["Join"],"summary":"Войти в комнату: пароль, lock, лимит, гео, rate-limit; возвращает join-токен","parameters":[{"name":"roomId","in":"path","required":true,"description":"Room id","schema":{"type":"string"}}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/JoinRoomRequest"},"example":{"name":"Анна","password":"secret","locale":"ru"}}}},"responses":{"200":{"description":"Join accepted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JoinRoomResponse"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"401":{"description":"Missing/invalid credentials","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"403":{"description":"Forbidden (wrong tenant, policy, feature)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"409":{"description":"Conflict (room full/exists)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"413":{"description":"Payload too large","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"423":{"description":"Room is locked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"429":{"description":"Rate limited / lockout","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"501":{"description":"Not configured (e.g. server STT)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}}},"description":"Вызывается браузером/сервером компании. Проверяет пароль, lock, гео-политику, лимит участников и rate-limit; возвращает токен и эффективные права для UI."}},"/v1/rooms/{roomId}/chat":{"post":{"tags":["Join"],"summary":"Отправить сообщение в чат звонка (внешний чат; идемпотентно по id)","description":"Вызывается сервером компании (внешний чат/бот) с join-токеном. Сообщение бродкастится в звонок, пишется в историю, уходит вебхуком chat.message; повтор с тем же `id` не дублирует.\n\nRequires the effective `chat` permission. Text messages need `session.chat.allowHostInjection`; system notices need `session.chat.allowSystemMessages` and a host/moderator role.","security":[{"bearer":[]}],"parameters":[{"name":"roomId","in":"path","required":true,"description":"Room id","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatPostRequest"},"example":{"text":"Привет из корпоративного чата","id":"msg-1"}}}},"responses":{"200":{"description":"Stored and broadcast message","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatPostResponse"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"401":{"description":"Missing/invalid credentials","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"403":{"description":"Forbidden (wrong tenant, policy, feature)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"409":{"description":"Conflict (room full/exists)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"413":{"description":"Payload too large","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"423":{"description":"Room is locked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"429":{"description":"Rate limited / lockout","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"501":{"description":"Not configured (e.g. server STT)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}}}}},"/v1/rooms/{roomId}/assistant":{"post":{"tags":["Join"],"summary":"AI-ассистент в звонке с правами участника","description":"Вызывается браузером с join-токеном. Ассистент отвечает от имени пользователя: сервер фильтрует предложенные действия по эффективным правам; `mode:local` — 501, движок в виджете.\n\nRequires `session.inCallAgent.enabled`. `mode:\"local\"` answers 501 assistant_local_only (the widget runs the offline assistant). `hybrid` falls back to 501 on endpoint failure; `external` is fail-closed (502 provider_failed). Actions are filtered through the effective permissions and `maxActionsPerReply`.","security":[{"bearer":[]}],"parameters":[{"name":"roomId","in":"path","required":true,"description":"Room id","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InCallAssistantRequest"}}}},"responses":{"200":{"description":"Assistant reply with permission-filtered actions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AssistantReply"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"401":{"description":"Missing/invalid credentials","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"403":{"description":"Forbidden (wrong tenant, policy, feature)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"409":{"description":"Conflict (room full/exists)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"413":{"description":"Payload too large","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"423":{"description":"Room is locked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"429":{"description":"Rate limited / lockout","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"501":{"description":"Not configured (e.g. server STT)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}}}}},"/v1/files":{"post":{"tags":["Files"],"summary":"Загрузить файл в чат (raw body, лимит из конфига)","security":[{"bearer":[]}],"parameters":[{"name":"x-file-name","in":"query","required":false,"description":"Original file name","schema":{"type":"header"}}],"requestBody":{"required":true,"content":{"application/octet-stream":{"schema":{"type":"string","format":"binary"}}}},"responses":{"200":{"description":"Stored file with signed URL","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FileRecord"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"401":{"description":"Missing/invalid credentials","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"403":{"description":"Forbidden (wrong tenant, policy, feature)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"409":{"description":"Conflict (room full/exists)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"413":{"description":"Payload too large","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"423":{"description":"Room is locked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"429":{"description":"Rate limited / lockout","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"501":{"description":"Not configured (e.g. server STT)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}}},"description":"Вызывается браузером с join-токеном. Требует features.fileShare и права fileShare; возвращает запись с подписанной ссылкой."}},"/v1/files/{id}":{"get":{"tags":["Files"],"summary":"Скачать файл по подписанной ссылке","parameters":[{"name":"id","in":"path","required":true,"description":"File id","schema":{"type":"string"}},{"name":"sig","in":"query","required":false,"description":"HMAC signature","schema":{"type":"string"}},{"name":"exp","in":"query","required":false,"description":"Expiry (epoch ms)","schema":{"type":"integer"}}],"responses":{"200":{"description":"Raw bytes","content":{"application/octet-stream":{"schema":{"type":"string","format":"binary"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"401":{"description":"Missing/invalid credentials","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"403":{"description":"Forbidden (wrong tenant, policy, feature)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"409":{"description":"Conflict (room full/exists)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"413":{"description":"Payload too large","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"423":{"description":"Room is locked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"429":{"description":"Rate limited / lockout","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"501":{"description":"Not configured (e.g. server STT)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}}}}},"/v1/recordings":{"post":{"tags":["Recordings"],"summary":"Загрузить запись (raw webm/mp4 + x-recording-meta)","security":[{"bearer":[]}],"parameters":[{"name":"x-recording-meta","in":"query","required":false,"description":"JSON {roomId,durationSec,mimeType}","schema":{"type":"header"}}],"requestBody":{"required":true,"content":{"application/octet-stream":{"schema":{"type":"string","format":"binary"}}}},"responses":{"200":{"description":"Stored recording","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecordingRecord"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"401":{"description":"Missing/invalid credentials","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"403":{"description":"Forbidden (wrong tenant, policy, feature)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"409":{"description":"Conflict (room full/exists)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"413":{"description":"Payload too large","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"423":{"description":"Room is locked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"429":{"description":"Rate limited / lockout","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"501":{"description":"Not configured (e.g. server STT)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}}}}},"/v1/recordings/{id}":{"get":{"tags":["Recordings"],"summary":"Скачать запись по подписанной ссылке","parameters":[{"name":"id","in":"path","required":true,"description":"Recording id","schema":{"type":"string"}},{"name":"sig","in":"query","required":false,"description":"HMAC signature","schema":{"type":"string"}},{"name":"exp","in":"query","required":false,"description":"Expiry (epoch ms)","schema":{"type":"integer"}}],"responses":{"200":{"description":"Raw bytes","content":{"application/octet-stream":{"schema":{"type":"string","format":"binary"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"401":{"description":"Missing/invalid credentials","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"403":{"description":"Forbidden (wrong tenant, policy, feature)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"409":{"description":"Conflict (room full/exists)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"413":{"description":"Payload too large","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"423":{"description":"Room is locked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"429":{"description":"Rate limited / lockout","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"501":{"description":"Not configured (e.g. server STT)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}}}}},"/v1/stt/transcribe":{"post":{"tags":["STT"],"summary":"Серверный speech-to-text (501, если не настроен)","security":[{"bearer":[]}],"parameters":[{"name":"x-language","in":"query","required":false,"description":"ru|en (header)","schema":{"type":"header"}}],"requestBody":{"required":true,"content":{"audio/webm":{"schema":{"type":"string","format":"binary"}},"audio/wav":{"schema":{"type":"string","format":"binary"}}}},"responses":{"200":{"description":"Transcript","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SttResponse"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"401":{"description":"Missing/invalid credentials","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"403":{"description":"Forbidden (wrong tenant, policy, feature)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"409":{"description":"Conflict (room full/exists)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"413":{"description":"Payload too large","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"423":{"description":"Room is locked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"429":{"description":"Rate limited / lockout","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"501":{"description":"Not configured (e.g. server STT)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}}}}},"/openapi.json":{"get":{"tags":["Docs"],"summary":"Эта OpenAPI 3.1 спека (только публичные пути)","responses":{"200":{"description":"OpenAPI spec","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"401":{"description":"Missing/invalid credentials","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"403":{"description":"Forbidden (wrong tenant, policy, feature)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"409":{"description":"Conflict (room full/exists)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"413":{"description":"Payload too large","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"423":{"description":"Room is locked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"429":{"description":"Rate limited / lockout","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"501":{"description":"Not configured (e.g. server STT)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}}}}},"/docs":{"get":{"tags":["Docs"],"summary":"Офлайн API-эксплорер (self-contained HTML)","responses":{"200":{"description":"HTML","content":{"text/html":{"schema":{"type":"string"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"401":{"description":"Missing/invalid credentials","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"403":{"description":"Forbidden (wrong tenant, policy, feature)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"409":{"description":"Conflict (room full/exists)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"413":{"description":"Payload too large","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"423":{"description":"Room is locked","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"429":{"description":"Rate limited / lockout","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}},"501":{"description":"Not configured (e.g. server STT)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorBody"}}}}}}}},"components":{"securitySchemes":{"bearer":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"Join token from /v1/rooms/:id/join or an invite"}},"schemas":{"ApiErrorBody":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","description":"Stable machine-readable code"},"message":{"type":"string"},"details":{}}}}},"HealthResponse":{"type":"object","properties":{"ok":{"type":"boolean"},"name":{"type":"string"},"version":{"type":"string"},"uptimeSec":{"type":"number"},"rooms":{"type":"number"},"tenants":{"type":"number"},"security":{"type":"object","properties":{"geoEnabled":{"type":"boolean"},"integrityEnabled":{"type":"boolean"},"sttConfigured":{"type":"boolean"},"aiAgentConfigured":{"type":"boolean"},"recordingsDir":{"type":"string"}}}}},"TenantConfig":{"type":"object","description":"Complete tenant configuration (see @agil/protocol tenantConfigSchema)","additionalProperties":true},"TenantConfigPatch":{"type":"object","description":"Deep-partial tenant configuration","additionalProperties":true},"ConfigEnvelope":{"type":"object","required":["config","etag"],"properties":{"config":{"$ref":"#/components/schemas/TenantConfig"},"etag":{"type":"string","description":"sha256 of the config"}}},"IceServer":{"type":"object","required":["urls"],"properties":{"urls":{"oneOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}]},"username":{"type":"string"},"credential":{"type":"string"}}},"RoomContext":{"type":"object","properties":{"messenger":{"type":"string","description":"telegram|slack|teams|matrix|corp-messenger"},"conversationId":{"type":"string"},"directPeerId":{"type":"string"},"title":{"type":"string"}}},"RoomInfo":{"type":"object","required":["id","tenantId","name","createdAt","locked"],"properties":{"id":{"type":"string"},"tenantId":{"type":"string"},"name":{"type":"string"},"createdAt":{"type":"number"},"locked":{"type":"boolean"},"mode":{"type":"string","enum":["direct","group"]},"context":{"$ref":"#/components/schemas/RoomContext"}}},"ParticipantState":{"type":"object","properties":{"mic":{"type":"string","enum":["on","off"]},"cam":{"type":"string","enum":["on","off"]},"screen":{"type":"boolean"},"handRaised":{"type":"boolean"},"network":{"type":"string","enum":["good","fair","poor"]}}},"ParticipantLocation":{"type":"object","required":["source"],"properties":{"country":{"type":"string"},"city":{"type":"string"},"source":{"type":"string","enum":["ip","gps","none"]},"vpnSuspected":{"type":"boolean"},"accuracyM":{"type":"number"}}},"Participant":{"type":"object","required":["id","name","role","joinedAt","state","verified","integrity"],"properties":{"id":{"type":"string"},"name":{"type":"string"},"role":{"type":"string","enum":["host","moderator","guest"]},"joinedAt":{"type":"number"},"state":{"$ref":"#/components/schemas/ParticipantState"},"country":{"type":"string"},"verified":{"type":"boolean"},"integrity":{"type":"string","enum":["unknown","verified","suspicious"]},"permissions":{"type":"array","items":{"type":"string"}},"roleName":{"type":"string","description":"Display name of a custom role"},"location":{"$ref":"#/components/schemas/ParticipantLocation"}}},"ChatMessage":{"type":"object","required":["id","roomId","from","text","ts","kind"],"properties":{"id":{"type":"string"},"roomId":{"type":"string"},"from":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"role":{"type":"string","enum":["host","moderator","guest"]}}},"text":{"type":"string"},"ts":{"type":"number"},"kind":{"type":"string","enum":["text","system","file"]},"attachment":{"type":"object","properties":{"name":{"type":"string"},"size":{"type":"number"},"mime":{"type":"string"},"url":{"type":"string"}}}}},"CreateRoomRequest":{"type":"object","properties":{"tenantId":{"type":"string"},"roomId":{"type":"string"},"name":{"type":"string"},"password":{"type":"string"},"maxParticipants":{"type":"integer","minimum":2,"maximum":200},"ttlSec":{"type":"integer"},"configOverrides":{"$ref":"#/components/schemas/TenantConfigPatch"},"mode":{"type":"string","enum":["direct","group"],"description":"direct = 1:1 messenger call (max 2 participants); group = default"},"context":{"$ref":"#/components/schemas/RoomContext"}}},"CreateRoomResponse":{"type":"object","required":["room","joinUrl","embedUrl","passwordProtected"],"properties":{"room":{"$ref":"#/components/schemas/RoomInfo"},"joinUrl":{"type":"string"},"embedUrl":{"type":"string"},"token":{"type":"string"},"expiresAt":{"type":"number"},"passwordProtected":{"type":"boolean"}}},"JoinRoomRequest":{"type":"object","properties":{"name":{"type":"string"},"password":{"type":"string"},"participantId":{"type":"string"},"locale":{"type":"string","enum":["ru","en"]},"token":{"type":"string"}}},"JoinRoomResponse":{"type":"object","required":["token","expiresAt","room","participant","config","passwordAccepted"],"properties":{"token":{"type":"string"},"expiresAt":{"type":"number"},"room":{"$ref":"#/components/schemas/RoomInfo"},"participant":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"role":{"type":"string"}}},"config":{"$ref":"#/components/schemas/TenantConfig"},"passwordAccepted":{"type":"boolean"},"permissions":{"type":"array","items":{"type":"string"}},"media":{"$ref":"#/components/schemas/SfuMediaSession"}}},"TokenRequest":{"type":"object","required":["tenantId","roomId","participant"],"properties":{"tenantId":{"type":"string"},"roomId":{"type":"string"},"participant":{"type":"object","properties":{"name":{"type":"string"},"role":{"type":"string","enum":["host","moderator","guest"]},"participantId":{"type":"string"},"roleId":{"type":"string","description":"Custom role id (security.accessPolicy.customRoles)"}}},"ttlSec":{"type":"integer"},"permissions":{"type":"array","items":{"type":"string"}}}},"TokenResponse":{"type":"object","required":["token","expiresAt","tenantId","roomId","permissions"],"properties":{"token":{"type":"string"},"expiresAt":{"type":"number"},"tenantId":{"type":"string"},"roomId":{"type":"string"},"permissions":{"type":"array","items":{"type":"string"}},"roleId":{"type":"string"},"roleName":{"type":"string"}}},"BreakoutRoomInfo":{"type":"object","required":["id","roomId","name","index","participantIds","status"],"properties":{"id":{"type":"string"},"roomId":{"type":"string"},"name":{"type":"string"},"index":{"type":"integer"},"participantIds":{"type":"array","items":{"type":"string"}},"status":{"type":"string","enum":["open","closed"]}}},"BreakoutPlan":{"type":"object","required":["id","mainRoomId","status","mode","rooms","assignments","allowReturn","createdAt"],"properties":{"id":{"type":"string"},"mainRoomId":{"type":"string"},"status":{"type":"string","enum":["active","closed"]},"mode":{"type":"string","enum":["random","manual"]},"rooms":{"type":"array","items":{"$ref":"#/components/schemas/BreakoutRoomInfo"}},"assignments":{"type":"object","additionalProperties":{"type":"string"}},"allowReturn":{"type":"boolean"},"createdAt":{"type":"number"},"endsAt":{"type":"number"},"closedAt":{"type":"number"}}},"BreakoutListResponse":{"type":"object","required":["roomId"],"properties":{"roomId":{"type":"string"},"plan":{"$ref":"#/components/schemas/BreakoutPlan"}}},"BreakoutAssignedMessage":{"type":"object","required":["planId","breakoutRoomId","roomId","name","token","joinUrl"],"properties":{"planId":{"type":"string"},"breakoutRoomId":{"type":"string"},"roomId":{"type":"string"},"name":{"type":"string"},"token":{"type":"string"},"joinUrl":{"type":"string"}}},"PollOptionResult":{"type":"object","required":["id","text","votes","share"],"properties":{"id":{"type":"string"},"text":{"type":"string"},"votes":{"type":"integer"},"share":{"type":"number"},"selected":{"type":"boolean"}}},"RoomPoll":{"type":"object","required":["id","roomId","tenantId","question","options","multiple","anonymous","kind","status","createdAt","totalVotes"],"properties":{"id":{"type":"string"},"roomId":{"type":"string"},"tenantId":{"type":"string"},"question":{"type":"string"},"options":{"type":"array","items":{"$ref":"#/components/schemas/PollOptionResult"}},"multiple":{"type":"boolean"},"anonymous":{"type":"boolean"},"kind":{"type":"string","enum":["poll","qna"]},"status":{"type":"string","enum":["open","closed"]},"createdBy":{"type":"object","additionalProperties":true},"createdAt":{"type":"number"},"closedAt":{"type":"number"},"totalVotes":{"type":"integer"},"voted":{"type":"boolean"}}},"PollListResponse":{"type":"object","required":["roomId","polls"],"properties":{"roomId":{"type":"string"},"polls":{"type":"array","items":{"$ref":"#/components/schemas/RoomPoll"}}}},"PollVoteResponse":{"type":"object","required":["poll","accepted"],"properties":{"poll":{"$ref":"#/components/schemas/RoomPoll"},"accepted":{"type":"boolean"},"reason":{"type":"string"}}},"CreateBreakoutRequest":{"type":"object","properties":{"mode":{"type":"string","enum":["random","manual"]},"rooms":{"type":"array","items":{"type":"object","additionalProperties":true},"minItems":2,"maxItems":20},"count":{"type":"integer"},"durationMin":{"type":"integer"},"allowReturn":{"type":"boolean"}}},"CreatePollRequest":{"type":"object","required":["question","options"],"properties":{"question":{"type":"string"},"options":{"type":"array","items":{"type":"object","required":["text"],"properties":{"text":{"type":"string"}}},"minItems":2,"maxItems":10},"multiple":{"type":"boolean"},"anonymous":{"type":"boolean"},"kind":{"type":"string","enum":["poll","qna"]}}},"VotePollRequest":{"type":"object","required":["optionIds"],"properties":{"optionIds":{"type":"array","items":{"type":"string"}}}},"SfuMediaSession":{"type":"object","required":["mode","url","token","room","canPublish","expiresAt"],"properties":{"mode":{"type":"string","enum":["sfu"]},"url":{"type":"string"},"token":{"type":"string","description":"HS256 LiveKit-compatible JWT"},"room":{"type":"string"},"canPublish":{"type":"boolean"},"expiresAt":{"type":"number"}}},"LobbyRequestInfo":{"type":"object","required":["id","name","createdAt","expiresAt","status"],"properties":{"id":{"type":"string"},"name":{"type":"string"},"country":{"type":"string"},"createdAt":{"type":"number"},"expiresAt":{"type":"number"},"status":{"type":"string","enum":["pending"]}}},"LobbyJoinResponse":{"type":"object","required":["pending","requestId","roomId","status","expiresAt","pollAfterMs"],"properties":{"pending":{"type":"boolean"},"requestId":{"type":"string"},"roomId":{"type":"string"},"status":{"type":"string","enum":["pending"]},"expiresAt":{"type":"number"},"pollAfterMs":{"type":"integer"}}},"LobbyRequestsResponse":{"type":"object","required":["roomId","requests"],"properties":{"roomId":{"type":"string"},"requests":{"type":"array","items":{"$ref":"#/components/schemas/LobbyRequestInfo"}}}},"LobbyStatusResponse":{"type":"object","required":["requestId","status"],"properties":{"requestId":{"type":"string"},"status":{"type":"string","enum":["pending","admitted","rejected","expired"]},"token":{"type":"string","description":"Join token, returned once after admit"},"expiresAt":{"type":"number"},"joinUrl":{"type":"string"},"embedUrl":{"type":"string"},"reason":{"type":"string"}}},"LobbyDecisionResponse":{"type":"object","required":["requestId","status"],"properties":{"requestId":{"type":"string"},"status":{"type":"string","enum":["admitted","rejected"]}}},"FileRecord":{"type":"object","required":["id","tenantId","roomId","name","size","mime","url","createdAt","expiresAt","uploadedBy"],"properties":{"id":{"type":"string"},"tenantId":{"type":"string"},"roomId":{"type":"string"},"name":{"type":"string"},"size":{"type":"number"},"mime":{"type":"string"},"url":{"type":"string"},"createdAt":{"type":"number"},"expiresAt":{"type":"number"},"uploadedBy":{"type":"string"}}},"RecordingRecord":{"type":"object","required":["id","tenantId","roomId","mime","size","durationSec","url","createdAt","createdBy"],"properties":{"id":{"type":"string"},"tenantId":{"type":"string"},"roomId":{"type":"string"},"mime":{"type":"string"},"size":{"type":"number"},"durationSec":{"type":"number"},"url":{"type":"string"},"createdAt":{"type":"number"},"createdBy":{"type":"string"},"transcript":{"type":"string"}}},"SttResponse":{"type":"object","required":["text","provider"],"properties":{"text":{"type":"string"},"provider":{"type":"string","enum":["browser","server","stub"]},"language":{"type":"string"},"durationSec":{"type":"number"},"segments":{"type":"array","items":{"type":"object","properties":{"start":{"type":"number"},"end":{"type":"number"},"text":{"type":"string"}}}}}},"TranscriptResponse":{"type":"object","required":["roomId","segments","updatedAt"],"properties":{"roomId":{"type":"string"},"segments":{"type":"array","items":{"type":"object","additionalProperties":true}},"updatedAt":{"type":"number"}}},"ChatPostRequest":{"type":"object","required":["text"],"properties":{"text":{"type":"string","description":"1..4000 characters"},"kind":{"type":"string","enum":["text","system"]},"from":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"role":{"type":"string","enum":["host","moderator","guest"]}}},"id":{"type":"string","description":"Idempotency key"}}},"ChatPostResponse":{"type":"object","required":["message"],"properties":{"message":{"$ref":"#/components/schemas/ChatMessage"}}},"ComplianceFinding":{"type":"object","additionalProperties":true,"description":"ComplianceFinding from @agil/protocol"},"MeetingNotes":{"type":"object","additionalProperties":true,"description":"MeetingNotes (summary, verbatim excerpts, action items)"},"AnalysisResponse":{"type":"object","required":["roomId","report","findings","notes"],"properties":{"roomId":{"type":"string"},"report":{"type":["object","null"],"additionalProperties":true},"findings":{"type":"array","items":{"$ref":"#/components/schemas/ComplianceFinding"}},"notes":{"oneOf":[{"$ref":"#/components/schemas/MeetingNotes"},{"type":"null"}]}}},"KnowledgeCitation":{"type":"object","required":["title","url"],"properties":{"title":{"type":"string"},"url":{"type":"string"},"snippet":{"type":"string"}}},"BackgroundItem":{"type":"object","required":["id","name","url"],"properties":{"id":{"type":"string"},"name":{"type":"string"},"url":{"type":"string"}}},"BackgroundsResponse":{"type":"object","required":["backgrounds","provider"],"properties":{"backgrounds":{"type":"array","items":{"$ref":"#/components/schemas/BackgroundItem"}},"provider":{"type":"string"}}},"AssistantAction":{"type":"object","required":["tool"],"properties":{"tool":{"type":"string","enum":["start_recording","stop_recording","toggle_mic","toggle_camera","toggle_screen_share","raise_hand","send_chat","open_chat","open_files","open_participants","open_notes","open_settings","set_blur","minimize","restore","request_fullscreen","open_new_tab","copy_invite_link"]},"args":{"type":"object","additionalProperties":true}}},"AssistantSpotlight":{"type":"object","required":["target","text"],"properties":{"target":{"type":"string"},"text":{"type":"string"},"step":{"type":"integer"}}},"AssistantReply":{"type":"object","required":["id","text","actions","spotlight","source","ts"],"properties":{"id":{"type":"string"},"text":{"type":"string"},"actions":{"type":"array","items":{"$ref":"#/components/schemas/AssistantAction"}},"spotlight":{"type":"array","items":{"$ref":"#/components/schemas/AssistantSpotlight"}},"source":{"type":"string","enum":["local","external"]},"ts":{"type":"number"}}},"InCallAssistantState":{"type":"object","properties":{"participants":{"type":"integer"},"recording":{"type":"boolean"},"mic":{"type":"string","enum":["on","off"]},"camera":{"type":"string","enum":["on","off"]},"screenSharing":{"type":"boolean"},"chatOpen":{"type":"boolean"},"layoutMode":{"type":"string"},"qualityTier":{"type":"string"}}},"InCallAssistantRequest":{"type":"object","required":["text"],"properties":{"text":{"type":"string","description":"1..2000 characters"},"locale":{"type":"string","enum":["ru","en"]},"state":{"$ref":"#/components/schemas/InCallAssistantState"}}}}}}