Справочник API: IM, Embed и файловая служба
Управление каналами IM и веб-встраивания (Embed), а также интерфейсы обратных вызовов каналов, сессий посетителей и доступа к файлам. Административная часть, обратные вызовы платформ IM и посетители Embed используют собственные способы аутентификации.
Обратные вызовы IM (без глобальной аутентификации)
GET|POST /api/v1/im/callback/:channel_id
Назначение: обратный вызов событий и проверка URL для платформ IM (WeChat/Feishu/Slack/Telegram/DingTalk/QQBot/Yunzhijia/MAX/LINE/Viber/OK и т. п.). Регистрируется до промежуточного слоя аутентификации и использует собственную проверку подписи каждой платформы; при неудачной проверке подписи 403, если канал не существует — 404. При получении сообщения сразу отправляется ACK, обработка выполняется асинхронно. Handler: internal/handler/im.go
Ответ: 200 {"success":true} или формат ACK, требуемый платформой.
curl -X POST $BASE/api/v1/im/callback/ch-1 -H 'Content-Type: application/json' -d '{"event":"..."}'Управление каналами IM (требуется аутентификация)
API key: manage_channels/full. Каналы IM содержат учётные данные внешнего бота: список — Viewer+, изменение/переключение/вход по QR-коду — Admin+.
Feishu/Lark credentials.api_base_url влияет одновременно на HTTP API и bootstrap WebSocket; Yunzhijia поддерживает session_mode=thread. Примеры конфигурации и требования к сети см. в Интеграция с IM. Предпочтения памяти IM/Embed берутся из config.memory_enabled привязанного агента; в текущем интерфейсе канала нет отдельного параметра memory_enabled.
POST /api/v1/agents/:id/im-channels
Назначение: создание канала IM для агента. Права: Admin+.
| Поле | Тип | Обязательно | Описание |
|---|---|---|---|
platform | string | да | wecom/feishu/lark/slack/telegram/dingtalk/mattermost/wechat/qqbot/yunzhijia/max/line/viber/whatsapp/ok/discord |
name | string | нет | отображаемое имя |
mode | string | нет | websocket (по умолчанию; для mattermost/yunzhijia/max/line/viber/ok по умолчанию webhook)/webhook/longpoll (для wechat принудительно longpoll, для whatsapp по умолчанию longpoll, для discord только websocket) |
output_mode | string | нет | stream (по умолчанию)/full (для wechat принудительно full; для line/viber/ok/whatsapp по умолчанию full — правка сообщений не поддерживается) |
locale | string | нет | язык ответа: zh-CN/en-US/ja-JP/ko-KR/ru-RU; пустое значение (по умолчанию) использует язык развёртывания по умолчанию (WEKNORA_LANGUAGE, при отсутствии — zh-CN); другие значения — 400 |
session_mode | string | нет | user (по умолчанию)/thread |
knowledge_base_id | string | нет | KB для дополнительного приёма вложений; должна принадлежать текущему пространству, иначе 400 |
credentials | object | нет | учётные данные платформы |
enabled | bool | нет | по умолчанию true |
Ответ: 200 {"data":{IMChannel}}; если бот для этого канала уже существует, возвращается 409.
curl -X POST $BASE/api/v1/agents/agent-1/im-channels -H "Authorization: Bearer $TOKEN" \
-H 'Content-Type: application/json' -d '{"platform":"feishu","name":"Поддержка Feishu","locale":"en-US"}'GET /api/v1/agents/:id/im-channels
Назначение: список каналов IM агента (краткая сводка). Права: Viewer+.
Ответ: 200 {"data":[IMChannel]}
curl $BASE/api/v1/agents/agent-1/im-channels -H "Authorization: Bearer $TOKEN"GET /api/v1/im-channels
Назначение: обзор каналов IM всего пространства (без учётных данных). Права: Viewer+.
Ответ: 200 {"data":[IMChannel]}
curl $BASE/api/v1/im-channels -H "Authorization: Bearer $TOKEN"PUT /api/v1/im-channels/:id
Назначение: обновление канала (частичное обновление: name/mode/output_mode/locale/session_mode/knowledge_base_id/credentials/enabled/agent_id — все необязательны; передача пустой строки в knowledge_base_id снимает связь, передача пустой строки в locale восстанавливает язык по умолчанию). Права: Admin+.
Ответ: 200 {"data":{IMChannel}}
curl -X PUT $BASE/api/v1/im-channels/ch-1 -H "Authorization: Bearer $TOKEN" \
-H 'Content-Type: application/json' -d '{"enabled":false}'DELETE /api/v1/im-channels/:id
Назначение: удаление канала. Права: Admin+.
Ответ: 200 {"success":true}
curl -X DELETE $BASE/api/v1/im-channels/ch-1 -H "Authorization: Bearer $TOKEN"POST /api/v1/im-channels/:id/toggle
Назначение: переключение включения/выключения. Права: Admin+. Тело запроса отсутствует.
Ответ: 200 {"data":{IMChannel}}
curl -X POST $BASE/api/v1/im-channels/ch-1/toggle -H "Authorization: Bearer $TOKEN"POST /api/v1/wechat/qrcode
Назначение: генерация QR-кода для входа в WeChat (привязка личного WeChat к пространству). Права: Admin+. Тело запроса отсутствует. Handler: internal/handler/wechat_qrcode.go
Ответ: 200 {"data":{"qrcode_url","qrcode"}}
curl -X POST $BASE/api/v1/wechat/qrcode -H "Authorization: Bearer $TOKEN"POST /api/v1/wechat/qrcode/status
Назначение: опрос состояния сканирования кода; после подтверждения возвращаются учётные данные. Права: Admin+. Тело запроса: {"qrcode":"<идентификатор>"} (обязательно).
Ответ: 200 {"data":{"status":"pending|scanned|confirmed|expired","credentials":{bot_token,ilink_bot_id,ilink_user_id,baseurl}}}
curl -X POST $BASE/api/v1/wechat/qrcode/status -H "Authorization: Bearer $TOKEN" \
-H 'Content-Type: application/json' -d '{"qrcode":"qr-1"}'Управление каналами Embed (требуется аутентификация)
API key: manage_channels/full. Handler: internal/handler/embed_channel.go
POST /api/v1/agents/:id/embed-channels
Назначение: создание канала веб-встраивания для агента. Права: Admin+.
| Поле | Тип | Обязательно | Описание |
|---|---|---|---|
name | string | нет | имя |
enabled | bool | нет | по умолчанию true |
allowed_origins | []string | да | не менее одного источника (точный URL / *.domain; в продакшене * запрещён) |
welcome_message | string | нет | приветственное сообщение |
rate_limit_per_minute | int | нет | на IP/минуту, по умолчанию 30 |
rate_limit_per_day | int | нет | на канал/день, по умолчанию 10000 |
primary_color / page_title / widget_position | string | нет | внешний вид (position: bottom-right по умолчанию и другие из четырёх углов) |
header_title_mode | string | нет | channel (по умолчанию)/session |
show_suggested_questions | bool | нет | по умолчанию true |
allow_web_search / allow_file_upload | bool | нет | по умолчанию false |
default_locale | string | нет | zh-CN/en-US/ko-KR/ja-JP/ru-RU/пусто (по браузеру) |
webhook_url / webhook_secret | string | нет | webhook событий посетителей |
agent_id | string | нет | привязанный агент |
Ответ: 201 {"success":true,"data":{embedChannelResponse с publish_token}}
curl -X POST $BASE/api/v1/agents/agent-1/embed-channels -H "Authorization: Bearer $TOKEN" \
-H 'Content-Type: application/json' -d '{"name":"Поддержка сайта","allowed_origins":["https://example.com"]}'GET /api/v1/agents/:id/embed-channels
Назначение: список каналов встраивания агента. Права: Viewer+.
Ответ: 200 {"success":true,"data":[embedChannelResponse]}
curl $BASE/api/v1/agents/agent-1/embed-channels -H "Authorization: Bearer $TOKEN"GET /api/v1/embed-channels
Назначение: список каналов встраивания всего пространства (без publish token). Права: Viewer+.
Ответ: 200 {"success":true,"data":[embedChannelResponse]}
curl $BASE/api/v1/embed-channels -H "Authorization: Bearer $TOKEN"GET /api/v1/embed-channels/:channel_id
Назначение: подробности канала (включая publish token, для копирования кода развёртывания). Права: Viewer+.
Ответ: 200 {"success":true,"data":{embedChannelResponse}}
curl $BASE/api/v1/embed-channels/ec-1 -H "Authorization: Bearer $TOKEN"PUT /api/v1/embed-channels/:channel_id
Назначение: обновление канала (поля те же, что при создании, все необязательны). Права: Admin+.
Ответ: 200 {"success":true,"data":{embedChannelResponse}}
curl -X PUT $BASE/api/v1/embed-channels/ec-1 -H "Authorization: Bearer $TOKEN" \
-H 'Content-Type: application/json' -d '{"enabled":false}'DELETE /api/v1/embed-channels/:channel_id
Назначение: удаление канала. Права: Admin+.
Ответ: 200 {"success":true}
curl -X DELETE $BASE/api/v1/embed-channels/ec-1 -H "Authorization: Bearer $TOKEN"POST /api/v1/embed-channels/:channel_id/rotate-token
Назначение: ротация publish token (старый token теряет силу). Права: Admin+. Тело запроса отсутствует.
Ответ: 200 {"success":true,"data":{embedChannelResponse с новым publish_token}}
curl -X POST $BASE/api/v1/embed-channels/ec-1/rotate-token -H "Authorization: Bearer $TOKEN"POST /api/v1/embed-channels/:channel_id/preview-session
Назначение: выдача короткоживущего session token для предпросмотра в административной части (без publish token). Права: Viewer+.
Ответ: 200 {"success":true,"data":{"session_token","expires_in"}}; при отключённом канале 403.
curl -X POST $BASE/api/v1/embed-channels/ec-1/preview-session -H "Authorization: Bearer $TOKEN"GET /api/v1/embed-channels/:channel_id/stats
Назначение: статистика использования канала. Права: Viewer+.
Ответ: 200 {"success":true,"data":{"session_count":N}}
curl $BASE/api/v1/embed-channels/ec-1/stats -H "Authorization: Bearer $TOKEN"Политика фреймов страницы встраивания Embed
GET /api/v1/embed-frame-policy
Назначение: для подзапроса auth_request Nginx перед возвратом страницы /embed/:channel_id получить для этого канала Content-Security-Policy: frame-ancestors. Без token; возвращается только заголовок политики, без конфигурации канала; ответ Cache-Control: no-store.
| Заголовок запроса | Обязательно | Описание |
|---|---|---|
X-Embed-Page-URI | да | относительный URI страницы встраивания, например /embed/<channel_id> |
Ответ: 204 с заголовком CSP; если канал не существует, отключён, путь недопустим или белый список пуст — 403.
curl -i $BASE/api/v1/embed-frame-policy -H "X-Embed-Page-URI: /embed/ec-1"Публичные маршруты Embed (/api/v1/embed/:channel_id, EmbedAuth)
Аутентификация: Authorization: Embed <publish_token|session_token>; для операций уровня сессии дополнительно X-Embed-Session: <sig>. Ограничение частоты и проверка Origin см. в обзоре. Handler: internal/handler/embed_channel.go; промежуточный слой: internal/middleware/embed_auth.go
Ниже $ET обозначает заголовок Embed token: -H "Authorization: Embed $EMBED_TOKEN".
POST /api/v1/embed/:channel_id/exchange
Назначение: обмен publish token на короткоживущий session token (session token нельзя повторно обменять). Тело запроса отсутствует.
Ответ: 200 {"success":true,"data":{"session_token","expires_in"}}
curl -X POST $BASE/api/v1/embed/ec-1/exchange -H "Authorization: Embed $PUBLISH_TOKEN"GET /api/v1/embed/:channel_id/config
Назначение: публичная конфигурация канала (без секретов).
Ответ: 200 {"success":true,"data":{channel_id,name,display_title,knowledge_base_ids,agent_id,agent_name,welcome_message,primary_color,widget_position,allow_web_search,allow_file_upload,default_locale,...}}
curl $BASE/api/v1/embed/ec-1/config -H "Authorization: Embed $EMBED_TOKEN"GET /api/v1/embed/:channel_id/suggested-questions
Назначение: стартовые предлагаемые вопросы. Параметры запроса: limit (≤12).
Ответ: 200 {"success":true,"data":{"questions":[...]}}
curl "$BASE/api/v1/embed/ec-1/suggested-questions?limit=6" -H "Authorization: Embed $EMBED_TOKEN"GET /api/v1/embed/:channel_id/chunks/:chunk_id
Назначение: просмотр цитируемого блока (содержимое обезличено; при превышении прав 403).
Ответ: 200 {"success":true,"data":{chunk}}
curl $BASE/api/v1/embed/ec-1/chunks/c-1 -H "Authorization: Embed $EMBED_TOKEN"POST /api/v1/embed/:channel_id/sessions
Назначение: создание сессии посетителя; возвращаются ID сессии и подписанный дескриптор. Тело запроса отсутствует.
Ответ: 201 {"success":true,"data":{"id":"<session_id>","sig":"<подпись>"}}
curl -X POST $BASE/api/v1/embed/ec-1/sessions -H "Authorization: Embed $EMBED_TOKEN"POST /api/v1/embed/:channel_id/knowledge-chat/:session_id
Назначение: вопросно-ответная работа по знаниям для посетителя (SSE; payload переписывается с учётом ограничений канала и передаётся в KnowledgeQA). Требуется X-Embed-Session. Тело запроса такое же, как у /knowledge-chat (query обязательно).
curl -N -X POST $BASE/api/v1/embed/ec-1/knowledge-chat/s-1 \
-H "Authorization: Embed $EMBED_TOKEN" -H "X-Embed-Session: $SIG" \
-H 'Content-Type: application/json' -d '{"query":"Часы работы?"}'POST /api/v1/embed/:channel_id/agent-chat/:session_id
Назначение: вопросно-ответная работа агента с посетителем (SSE). Требуется X-Embed-Session. Тело запроса то же.
curl -N -X POST $BASE/api/v1/embed/ec-1/agent-chat/s-1 \
-H "Authorization: Embed $EMBED_TOKEN" -H "X-Embed-Session: $SIG" \
-H 'Content-Type: application/json' -d '{"query":"Помоги оформить заказ"}'GET /api/v1/embed/:channel_id/messages/:session_id/load
Назначение: загрузка сообщений сессии посетителя (делегируется LoadMessages, параметры запроса limit/before_time). Требуется X-Embed-Session.
Ответ: 200 {"success":true,"data":[Message]}
curl "$BASE/api/v1/embed/ec-1/messages/s-1/load?limit=20" \
-H "Authorization: Embed $EMBED_TOKEN" -H "X-Embed-Session: $SIG"POST /api/v1/embed/:channel_id/sessions/:session_id/stop
Назначение: остановка генерации (делегируется StopSession; тело запроса {"message_id":"..."}). Требуется X-Embed-Session.
curl -X POST $BASE/api/v1/embed/ec-1/sessions/s-1/stop \
-H "Authorization: Embed $EMBED_TOKEN" -H "X-Embed-Session: $SIG" \
-H 'Content-Type: application/json' -d '{"message_id":"m-1"}'GET|POST /api/v1/embed/:channel_id/sessions/:session_id/messages/:message_id/suggestions
Назначение: чтение / запуск генерации предложений для сообщения (если предложения отключены на канале, возвращается suppressed). Требуется X-Embed-Session.
Ответ: 200 {"success":true,"data":{"status","questions":[...]}}
curl $BASE/api/v1/embed/ec-1/sessions/s-1/messages/m-1/suggestions \
-H "Authorization: Embed $EMBED_TOKEN" -H "X-Embed-Session: $SIG"POST /api/v1/embed/:channel_id/sessions/:session_id/suggestion-events
Назначение: отправка событий взаимодействия с предложениями (делегируется RecordEvent; поля как в версии с аутентификацией). Требуется X-Embed-Session. Ответ: 204.
curl -X POST $BASE/api/v1/embed/ec-1/sessions/s-1/suggestion-events \
-H "Authorization: Embed $EMBED_TOKEN" -H "X-Embed-Session: $SIG" \
-H 'Content-Type: application/json' -d '{"suggestion_set_id":"ss-1","event_type":"impression"}'POST /api/v1/embed/:channel_id/sessions/:session_id/events
Назначение: пересылка событий посетителя в webhook канала. Требуется X-Embed-Session.
| Поле | Тип | Обязательно | Описание |
|---|---|---|---|
type | string | да | message_sent / message_received |
query / content | string | нет | вопрос пользователя / ответ бота |
Ответ: 200 {"success":true}; при неподдерживаемом типе 400.
curl -X POST $BASE/api/v1/embed/ec-1/sessions/s-1/events \
-H "Authorization: Embed $EMBED_TOKEN" -H "X-Embed-Session: $SIG" \
-H 'Content-Type: application/json' -d '{"type":"message_sent","query":"Привет"}'MCP OAuth и утверждение инструментов (на стороне посетителя)
Все перечисленные маршруты требуют X-Embed-Session и делегируются соответствующему handler с аутентификацией (internal/handler/mcp_oauth.go, internal/handler/mcp_service.go):
| Метод+путь | Назначение |
|---|---|
POST /api/v1/embed/:channel_id/sessions/:session_id/mcp-oauth-resolutions/:pending_id | возобновление работы, приостановленной для OAuth (тело: service_id обязательно, decision необязательно) |
POST /api/v1/embed/:channel_id/sessions/:session_id/mcp-oauth-resolutions/:pending_id/cancel | отмена процесса OAuth |
POST /api/v1/embed/:channel_id/sessions/:session_id/mcp-services/:id/oauth/authorize-url | генерация URL авторизации (тело: redirect_uri обязательно) |
GET /api/v1/embed/:channel_id/sessions/:session_id/mcp-services/:id/oauth/status | запрос состояния авторизации |
POST /api/v1/embed/:channel_id/sessions/:session_id/tool-approvals/:pending_id | утверждение инструмента (тело: decision обязательно) |
curl -X POST $BASE/api/v1/embed/ec-1/sessions/s-1/tool-approvals/p-1 \
-H "Authorization: Embed $EMBED_TOKEN" -H "X-Embed-Session: $SIG" \
-H 'Content-Type: application/json' -d '{"decision":"approve"}'GET /api/v1/embed/:channel_id/files
Назначение: прокси изображений на стороне посетителя (встроенные изображения в ответах бота; EmbedAuth внедряет пространство канала, handler принудительно проверяет путь в том же пространстве). Параметры запроса: file_path (обязательно).
Ответ: 200 поток файла.
curl "$BASE/api/v1/embed/ec-1/files?file_path=local://1/exports/chart.png" \
-H "Authorization: Embed $EMBED_TOKEN" -o chart.pngФайловая служба
Реализовано в internal/router/files.go (не в пакете handler).
GET /files
Назначение: единый прокси файлов после аутентификации (local/MinIO/COS/TOS и т. п.). Права: любой аутентифицированный участник пространства; API key должен быть не ограничен KB (full-access или retrieve по всему пространству, middleware.AllowFileServeAPIKey()); путь принудительно проверяется на принадлежность тому же пространству (ValidateStoragePathTenant).
| Параметр запроса | Тип | Обязательно | Описание |
|---|---|---|---|
file_path | string | да | путь provider://... (.. запрещено; при переходе между пространствами 403) |
Ответ: 200 поток файла (X-Content-Type-Options: nosniff; для типов вне белого списка принудительно Content-Disposition: attachment).
curl "$BASE/files?file_path=local://1/docs/a.png" -H "Authorization: Bearer $TOKEN" -o a.pngGET|HEAD /api/v1/files/presigned
Назначение: доступ к файлам по URL с подписью HMAC (встроенные изображения в платформах IM; без аутентификации, проверка подписи и срока действия, SYSTEM_AES_KEY участвует в подписи).
| Параметр запроса | Тип | Обязательно | Описание |
|---|---|---|---|
file_path | string | да | путь в хранилище |
tenant_id | uint64 | да | ID пространства |
expires | string | да | время истечения в Unix |
sig | string | да | подпись HMAC |
Ответ: 200 поток файла (для HEAD возвращаются только заголовки); при недействительной/просроченной подписи 403.
curl "$BASE/api/v1/files/presigned?file_path=local://1/x.png&tenant_id=1&expires=1790000000&sig=abc" -o x.pngGET /api/v1/files/presigned-preview
Назначение: диагностический эндпоинт: возвращает предподписанный HTTP URL, который будет сгенерирован для заданного пути. Права: Admin+, API key явно запрещён (DenyAPIKeyPrincipal). Параметры запроса: file_path (обязательно).
file_path должен принадлежать текущему пространству, как и в /files: для дескрипторов resource:// требуется, чтобы ресурс принадлежал текущему пространству, а для пути в хранилище — чтобы сегмент тенанта был ID текущего пространства; иначе 403 и никакой URL не выдаётся.
Ответ: 200 {"file_path","provider","url","rewritten":bool,"hint"}
curl "$BASE/api/v1/files/presigned-preview?file_path=local://1/x.png" -H "Authorization: Bearer $TOKEN"GET|HEAD /r/:token
Назначение: короткоживущий URL авторизации доступа к ресурсу (для клиентов вроде IM, которые не могут передавать заголовок аутентификации). Без аутентификации; token сам является полномочием; при недействительном/просроченном token 404.
Ответ: 200 поток файла (Cache-Control: private, max-age=300).
curl $BASE/r/abc123 -o file.pngСправочник по реализации
Регистрация маршрутов: RegisterIMRoutes, RegisterIMChannelRoutes, RegisterEmbedChannelRoutes, RegisterEmbedPublicRoutes в internal/router/routes_agent.go; serveFilesWithResources, servePresignedFiles, servePresignedPreview, serveResourceGrants в internal/router/files.go. Handler: internal/handler/im.go, internal/handler/wechat_qrcode.go, internal/handler/embed_channel.go.
