{"openapi": "3.1.0", "info": {"title": "Uplexity API", "version": "1.0.0", "description": "API для управления ассистентами, версиями промптов, клиентами, диалогами, сообщениями и аналитикой. Данные изолированы в пределах организации API-ключа. Для получения API-ключа свяжитесь с поддержкой: support@uplexity.com или Telegram @uplexity.", "contact": {"name": "Uplexity Support", "email": "support@uplexity.com", "url": "https://t.me/uplexity"}}, "servers": [{"url": "https://api.uplexity.com", "description": "Production"}], "tags": [{"name": "System", "description": "Состояние API."}, {"name": "Authorization", "description": "Проверка API-ключа. Чтобы получить ключ, напишите на support@uplexity.com или в Telegram @uplexity."}, {"name": "Assistants", "description": "Управление ассистентами."}, {"name": "Prompts", "description": "Версии промптов ассистента."}, {"name": "Clients", "description": "Профили клиентов организации."}, {"name": "Conversations", "description": "Диалоги и поиск сообщений."}, {"name": "Analytics", "description": "Приём событий и агрегированные отчёты."}, {"name": "Error reports", "description": "Отправка ошибок администратору в Telegram."}, {"name": "Support requests", "description": "Передача текстовых запросов человеку из поддержки."}], "security": [{"bearerAuth": []}], "paths": {"/health": {"get": {"tags": ["System"], "summary": "Проверить доступность API", "operationId": "getHealth", "security": [], "responses": {"200": {"description": "API работает.", "content": {"application/json": {"schema": {"type": "object", "properties": {"ok": {"type": "boolean", "const": true}}, "required": ["ok"]}}}}}}}, "/v1/auth/key-login": {"post": {"tags": ["Authorization"], "summary": "Проверить API-ключ", "description": "Публичная первичная проверка ключа. Для получения API-ключа свяжитесь с поддержкой: support@uplexity.com или Telegram @uplexity.", "operationId": "loginWithApiKey", "security": [], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/KeyLoginRequest"}, "example": {"api_key": "upx_live_xxxxxxxxxxxxxxxxx"}}}}, "responses": {"200": {"description": "Ключ действителен.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/KeyLoginResponse"}}}}, "401": {"$ref": "#/components/responses/Unauthorized"}}}}, "/v1/auth/me": {"get": {"tags": ["Authorization"], "summary": "Получить текущий доступ", "operationId": "getCurrentAuth", "responses": {"200": {"description": "Данные текущего API-ключа и организации.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ApiKeyAuthState"}}}}, "401": {"$ref": "#/components/responses/Unauthorized"}}}}, "/v1/assistants": {"get": {"tags": ["Assistants"], "summary": "Получить список ассистентов", "operationId": "listAssistants", "responses": {"200": {"description": "Неархивированные ассистенты организации.", "content": {"application/json": {"schema": {"type": "object", "properties": {"assistants": {"type": "array", "items": {"$ref": "#/components/schemas/Assistant"}}}, "required": ["assistants"]}}}}, "401": {"$ref": "#/components/responses/Unauthorized"}}}, "post": {"tags": ["Assistants"], "summary": "Создать ассистента", "operationId": "createAssistant", "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/AssistantInput"}, "example": {"name": "Website assistant", "description": "Квалифицирует заявки с сайта"}}}}, "responses": {"201": {"description": "Ассистент создан.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Assistant"}}}}, "400": {"$ref": "#/components/responses/BadRequest"}, "401": {"$ref": "#/components/responses/Unauthorized"}}}}, "/v1/assistants/{assistant_id}": {"parameters": [{"$ref": "#/components/parameters/AssistantId"}], "get": {"tags": ["Assistants"], "summary": "Получить ассистента", "operationId": "getAssistant", "responses": {"200": {"description": "Ассистент.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Assistant"}}}}, "401": {"$ref": "#/components/responses/Unauthorized"}, "404": {"$ref": "#/components/responses/NotFound"}}}, "patch": {"tags": ["Assistants"], "summary": "Изменить ассистента", "operationId": "updateAssistant", "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/AssistantPatch"}}}}, "responses": {"200": {"description": "Ассистент изменён.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Assistant"}}}}, "400": {"$ref": "#/components/responses/BadRequest"}, "401": {"$ref": "#/components/responses/Unauthorized"}, "404": {"$ref": "#/components/responses/NotFound"}}}, "delete": {"tags": ["Assistants"], "summary": "Архивировать ассистента", "operationId": "deleteAssistant", "responses": {"200": {"description": "Ассистент архивирован.", "content": {"application/json": {"schema": {"type": "object", "properties": {"deleted": {"type": "boolean", "const": true}}, "required": ["deleted"]}}}}, "401": {"$ref": "#/components/responses/Unauthorized"}, "404": {"$ref": "#/components/responses/NotFound"}}}}, "/v1/assistants/{assistant_id}/prompts": {"parameters": [{"$ref": "#/components/parameters/AssistantId"}], "get": {"tags": ["Prompts"], "summary": "Получить версии промпта", "operationId": "listPrompts", "parameters": [{"name": "status", "in": "query", "required": false, "schema": {"$ref": "#/components/schemas/PromptStatus"}, "description": "Фильтр по статусу."}], "responses": {"200": {"description": "Версии от новой к старой.", "content": {"application/json": {"schema": {"type": "object", "properties": {"prompts": {"type": "array", "items": {"$ref": "#/components/schemas/Prompt"}}}, "required": ["prompts"]}}}}, "401": {"$ref": "#/components/responses/Unauthorized"}, "404": {"$ref": "#/components/responses/NotFound"}}}, "post": {"tags": ["Prompts"], "summary": "Создать черновик версии", "description": "Номер версии назначается автоматически. Поля model и reasoning_effort сохраняются вместе с версией.", "operationId": "createPrompt", "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/PromptInput"}, "example": {"title": "Main sales prompt", "content": "Ты ассистент компании...", "model": "gpt-5.4-mini", "reasoning_effort": "medium"}}}}, "responses": {"201": {"description": "Черновик создан.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Prompt"}}}}, "400": {"$ref": "#/components/responses/BadRequest"}, "401": {"$ref": "#/components/responses/Unauthorized"}, "404": {"$ref": "#/components/responses/NotFound"}}}}, "/v1/assistants/{assistant_id}/prompts/active": {"parameters": [{"$ref": "#/components/parameters/AssistantId"}], "get": {"tags": ["Prompts"], "summary": "Получить активный промпт", "description": "Runtime-метод для получения текущего текста и конфигурации модели.", "operationId": "getActivePrompt", "responses": {"200": {"description": "Активная версия.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Prompt"}}}}, "401": {"$ref": "#/components/responses/Unauthorized"}, "404": {"$ref": "#/components/responses/NotFound"}}}}, "/v1/assistants/{assistant_id}/prompts/{prompt_id}": {"parameters": [{"$ref": "#/components/parameters/AssistantId"}, {"$ref": "#/components/parameters/PromptId"}], "get": {"tags": ["Prompts"], "summary": "Получить версию промпта", "operationId": "getPrompt", "responses": {"200": {"description": "Версия промпта.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Prompt"}}}}, "401": {"$ref": "#/components/responses/Unauthorized"}, "404": {"$ref": "#/components/responses/NotFound"}}}, "patch": {"tags": ["Prompts"], "summary": "Изменить черновик", "description": "Редактировать можно только версию со статусом draft.", "operationId": "updatePrompt", "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/PromptPatch"}}}}, "responses": {"200": {"description": "Черновик изменён.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Prompt"}}}}, "400": {"$ref": "#/components/responses/BadRequest"}, "401": {"$ref": "#/components/responses/Unauthorized"}, "404": {"$ref": "#/components/responses/NotFound"}, "409": {"$ref": "#/components/responses/Conflict"}}}, "delete": {"tags": ["Prompts"], "summary": "Архивировать версию", "description": "Активную версию нельзя архивировать напрямую.", "operationId": "deletePrompt", "responses": {"200": {"description": "Архивированная версия.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Prompt"}}}}, "401": {"$ref": "#/components/responses/Unauthorized"}, "404": {"$ref": "#/components/responses/NotFound"}, "409": {"$ref": "#/components/responses/Conflict"}}}}, "/v1/assistants/{assistant_id}/prompts/{prompt_id}/activate": {"parameters": [{"$ref": "#/components/parameters/AssistantId"}, {"$ref": "#/components/parameters/PromptId"}], "post": {"tags": ["Prompts"], "summary": "Активировать версию", "description": "Предыдущая активная версия автоматически архивируется.", "operationId": "activatePrompt", "responses": {"200": {"description": "Активная версия.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Prompt"}}}}, "401": {"$ref": "#/components/responses/Unauthorized"}, "404": {"$ref": "#/components/responses/NotFound"}}}}, "/v1/assistants/{assistant_id}/prompts/{prompt_id}/archive": {"parameters": [{"$ref": "#/components/parameters/AssistantId"}, {"$ref": "#/components/parameters/PromptId"}], "post": {"tags": ["Prompts"], "summary": "Архивировать версию", "description": "Активную версию нельзя архивировать напрямую.", "operationId": "archivePrompt", "responses": {"200": {"description": "Архивированная версия.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Prompt"}}}}, "401": {"$ref": "#/components/responses/Unauthorized"}, "404": {"$ref": "#/components/responses/NotFound"}, "409": {"$ref": "#/components/responses/Conflict"}}}}, "/v1/clients": {"get": {"tags": ["Clients"], "summary": "Получить список клиентов", "operationId": "listClients", "description": "Возвращает активных клиентов от недавно изменённых к более старым. search регистронезависимо ищет подстроку в id, nickname, name, phone_number и comment.", "parameters": [{"$ref": "#/components/parameters/Ids"}, {"$ref": "#/components/parameters/ClientIdQuery"}, {"$ref": "#/components/parameters/Search"}, {"$ref": "#/components/parameters/Limit"}, {"$ref": "#/components/parameters/Cursor"}], "responses": {"200": {"description": "Страница клиентов.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ClientsPage"}}}}, "400": {"$ref": "#/components/responses/BadRequest"}, "401": {"$ref": "#/components/responses/Unauthorized"}}}, "post": {"tags": ["Clients"], "summary": "Создать клиента", "operationId": "createClient", "description": "id обязателен, уникален в пределах организации и неизменяем.", "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ClientInput"}}}}, "responses": {"201": {"description": "Клиент создан.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Client"}}}}, "400": {"$ref": "#/components/responses/BadRequest"}, "401": {"$ref": "#/components/responses/Unauthorized"}, "409": {"$ref": "#/components/responses/Conflict"}}}}, "/v1/clients/{client_id}": {"parameters": [{"$ref": "#/components/parameters/ClientIdPath"}], "get": {"tags": ["Clients"], "summary": "Получить клиента", "operationId": "getClient", "responses": {"200": {"description": "Активный клиент.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Client"}}}}, "401": {"$ref": "#/components/responses/Unauthorized"}, "404": {"$ref": "#/components/responses/NotFound"}}}, "patch": {"tags": ["Clients"], "summary": "Изменить клиента", "operationId": "updateClient", "description": "Изменяемы только nickname, name, phone_number и comment. Поля можно очистить значением null; id неизменяем.", "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ClientPatch"}}}}, "responses": {"200": {"description": "Клиент изменён.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Client"}}}}, "400": {"$ref": "#/components/responses/BadRequest"}, "401": {"$ref": "#/components/responses/Unauthorized"}, "404": {"$ref": "#/components/responses/NotFound"}}}, "delete": {"tags": ["Clients"], "summary": "Архивировать клиента", "operationId": "deleteClient", "description": "Мягкое удаление переводит клиента в статус archived.", "responses": {"200": {"description": "Клиент архивирован.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/DeleteResult"}}}}, "401": {"$ref": "#/components/responses/Unauthorized"}, "404": {"$ref": "#/components/responses/NotFound"}}}}, "/v1/conversations": {"get": {"tags": ["Conversations"], "summary": "Получить список диалогов", "operationId": "listConversations", "description": "Диалог определяется сочетанием organization_id, assistant_id и внешнего conversation_id. Возвращает диалоги от самой новой активности. from/to — включительный календарный диапазон: диалог должен иметь в нём хотя бы одно сообщение. search ищет по внутреннему и внешнему ID диалога, всем полям клиента и тексту сообщений. Старые записи не мигрируются и недоступны здесь.", "parameters": [{"$ref": "#/components/parameters/Ids"}, {"$ref": "#/components/parameters/ExternalConversationId"}, {"$ref": "#/components/parameters/ClientIdQuery"}, {"$ref": "#/components/parameters/AnalyticsAssistantId"}, {"$ref": "#/components/parameters/MessageId"}, {"$ref": "#/components/parameters/Channel"}, {"$ref": "#/components/parameters/From"}, {"$ref": "#/components/parameters/To"}, {"$ref": "#/components/parameters/Timezone"}, {"$ref": "#/components/parameters/Search"}, {"$ref": "#/components/parameters/Limit"}, {"$ref": "#/components/parameters/Cursor"}], "responses": {"200": {"description": "Страница диалогов.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ConversationsPage"}}}}, "400": {"$ref": "#/components/responses/BadRequest"}, "401": {"$ref": "#/components/responses/Unauthorized"}, "404": {"$ref": "#/components/responses/NotFound"}}}}, "/v1/conversations/{conversation_id}": {"parameters": [{"$ref": "#/components/parameters/InternalConversationId"}], "get": {"tags": ["Conversations"], "summary": "Получить диалог", "operationId": "getConversation", "description": "conversation_id в пути — внутренний ID с префиксом cnv.", "responses": {"200": {"description": "Диалог.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Conversation"}}}}, "401": {"$ref": "#/components/responses/Unauthorized"}, "404": {"$ref": "#/components/responses/NotFound"}}}}, "/v1/conversations/{conversation_id}/messages": {"parameters": [{"$ref": "#/components/parameters/InternalConversationId"}], "get": {"tags": ["Conversations"], "summary": "Получить сообщения диалога", "operationId": "listConversationMessages", "description": "Возвращает сообщения от новых к старым. ids содержит внешние ID сообщений.", "parameters": [{"$ref": "#/components/parameters/MessageId"}, {"$ref": "#/components/parameters/ClientIdQuery"}, {"$ref": "#/components/parameters/AnalyticsAssistantId"}, {"$ref": "#/components/parameters/Role"}, {"$ref": "#/components/parameters/MessageIds"}, {"$ref": "#/components/parameters/From"}, {"$ref": "#/components/parameters/To"}, {"$ref": "#/components/parameters/Timezone"}, {"$ref": "#/components/parameters/Search"}, {"$ref": "#/components/parameters/Limit"}, {"$ref": "#/components/parameters/Cursor"}], "responses": {"200": {"description": "Страница сообщений.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/MessagesPage"}}}}, "400": {"$ref": "#/components/responses/BadRequest"}, "401": {"$ref": "#/components/responses/Unauthorized"}, "404": {"$ref": "#/components/responses/NotFound"}}}}, "/v1/messages/search": {"get": {"tags": ["Conversations"], "summary": "Найти сообщения", "operationId": "searchMessages", "description": "search обязателен и содержит минимум 2 символа. Регистронезависимый поиск выполняется по полному тексту; результаты от новых к старым. Старые строки без сохранённого текста не мигрируются и недоступны.", "parameters": [{"$ref": "#/components/parameters/RequiredSearch"}, {"$ref": "#/components/parameters/MessageId"}, {"$ref": "#/components/parameters/ClientIdQuery"}, {"$ref": "#/components/parameters/AnalyticsAssistantId"}, {"$ref": "#/components/parameters/Role"}, {"$ref": "#/components/parameters/MessageIds"}, {"$ref": "#/components/parameters/From"}, {"$ref": "#/components/parameters/To"}, {"$ref": "#/components/parameters/Timezone"}, {"$ref": "#/components/parameters/Limit"}, {"$ref": "#/components/parameters/Cursor"}], "responses": {"200": {"description": "Страница найденных сообщений.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/MessagesPage"}}}}, "400": {"$ref": "#/components/responses/BadRequest"}, "401": {"$ref": "#/components/responses/Unauthorized"}, "404": {"$ref": "#/components/responses/NotFound"}}}}, "/v1/analytics/events": {"post": {"tags": ["Analytics"], "summary": "Записать события", "description": "Принимает от 1 до 100 событий одной атомарной операцией. Строковый client_id сохраняется в пределах организации; ingest создаёт пустого active клиента, если его нет. Диалог определяется organization_id, assistant_id и внешним conversation_id; конфликт client_id или channel возвращает 409. Полный текст сообщений сохраняется бессрочно.", "operationId": "ingestAnalyticsEvents", "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/AnalyticsEventBatch"}}}}, "responses": {"202": {"description": "События приняты.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/IngestResult"}}}}, "400": {"$ref": "#/components/responses/BadRequest"}, "401": {"$ref": "#/components/responses/Unauthorized"}, "404": {"$ref": "#/components/responses/NotFound"}, "409": {"$ref": "#/components/responses/Conflict"}, "413": {"$ref": "#/components/responses/PayloadTooLarge"}, "415": {"$ref": "#/components/responses/UnsupportedMediaType"}}}}, "/v1/analytics": {"get": {"tags": ["Analytics"], "summary": "Получить общий отчёт", "operationId": "getAnalyticsReport", "parameters": [{"$ref": "#/components/parameters/From"}, {"$ref": "#/components/parameters/To"}, {"$ref": "#/components/parameters/Timezone"}, {"$ref": "#/components/parameters/AnalyticsAssistantId"}, {"$ref": "#/components/parameters/Channel"}], "responses": {"200": {"description": "Агрегированный отчёт.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/AnalyticsReport"}}}}, "400": {"$ref": "#/components/responses/BadRequest"}, "401": {"$ref": "#/components/responses/Unauthorized"}, "404": {"$ref": "#/components/responses/NotFound"}}}}, "/v1/analytics/audience": {"get": {"tags": ["Analytics"], "summary": "Получить аудиторию", "operationId": "getAnalyticsAudience", "parameters": [{"$ref": "#/components/parameters/From"}, {"$ref": "#/components/parameters/To"}, {"$ref": "#/components/parameters/Timezone"}, {"$ref": "#/components/parameters/AnalyticsAssistantId"}, {"$ref": "#/components/parameters/Channel"}], "responses": {"200": {"description": "Метрики аудитории.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/AudienceReport"}}}}, "400": {"$ref": "#/components/responses/BadRequest"}, "401": {"$ref": "#/components/responses/Unauthorized"}, "404": {"$ref": "#/components/responses/NotFound"}}}}, "/v1/analytics/usage": {"get": {"tags": ["Analytics"], "summary": "Получить использование", "operationId": "getAnalyticsUsage", "parameters": [{"$ref": "#/components/parameters/From"}, {"$ref": "#/components/parameters/To"}, {"$ref": "#/components/parameters/Timezone"}, {"$ref": "#/components/parameters/AnalyticsAssistantId"}, {"$ref": "#/components/parameters/Channel"}], "responses": {"200": {"description": "Сообщения, запросы, токены и стоимость.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/UsageReport"}}}}, "400": {"$ref": "#/components/responses/BadRequest"}, "401": {"$ref": "#/components/responses/Unauthorized"}, "404": {"$ref": "#/components/responses/NotFound"}}}}, "/v1/analytics/performance": {"get": {"tags": ["Analytics"], "summary": "Получить производительность", "operationId": "getAnalyticsPerformance", "parameters": [{"$ref": "#/components/parameters/From"}, {"$ref": "#/components/parameters/To"}, {"$ref": "#/components/parameters/Timezone"}, {"$ref": "#/components/parameters/AnalyticsAssistantId"}, {"$ref": "#/components/parameters/Channel"}], "responses": {"200": {"description": "Метрики latency успешных ответов ассистента.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/PerformanceReport"}}}}, "400": {"$ref": "#/components/responses/BadRequest"}, "401": {"$ref": "#/components/responses/Unauthorized"}, "404": {"$ref": "#/components/responses/NotFound"}}}}, "/v1/analytics/breakdowns": {"get": {"tags": ["Analytics"], "summary": "Получить разбивки", "operationId": "getAnalyticsBreakdowns", "parameters": [{"$ref": "#/components/parameters/From"}, {"$ref": "#/components/parameters/To"}, {"$ref": "#/components/parameters/Timezone"}, {"$ref": "#/components/parameters/AnalyticsAssistantId"}, {"$ref": "#/components/parameters/Channel"}], "responses": {"200": {"description": "Разбивки по моделям и версиям промпта.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/BreakdownsReport"}}}}, "400": {"$ref": "#/components/responses/BadRequest"}, "401": {"$ref": "#/components/responses/Unauthorized"}, "404": {"$ref": "#/components/responses/NotFound"}}}}, "/v1/analytics/errors": {"get": {"tags": ["Analytics"], "summary": "Получить ошибки", "operationId": "getAnalyticsErrors", "parameters": [{"$ref": "#/components/parameters/From"}, {"$ref": "#/components/parameters/To"}, {"$ref": "#/components/parameters/Timezone"}, {"$ref": "#/components/parameters/AnalyticsAssistantId"}, {"$ref": "#/components/parameters/Channel"}], "responses": {"200": {"description": "Частота и последние ошибки.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ErrorsReport"}}}}, "400": {"$ref": "#/components/responses/BadRequest"}, "401": {"$ref": "#/components/responses/Unauthorized"}, "404": {"$ref": "#/components/responses/NotFound"}}}}, "/v1/analytics/timeseries": {"get": {"tags": ["Analytics"], "summary": "Получить временной ряд", "operationId": "getAnalyticsTimeseries", "parameters": [{"$ref": "#/components/parameters/From"}, {"$ref": "#/components/parameters/To"}, {"$ref": "#/components/parameters/Timezone"}, {"$ref": "#/components/parameters/AnalyticsAssistantId"}, {"$ref": "#/components/parameters/Channel"}, {"name": "interval", "in": "query", "required": false, "schema": {"type": "string", "enum": ["day", "week"], "default": "day"}}], "responses": {"200": {"description": "Точки временного ряда.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/TimeseriesReport"}}}}, "400": {"$ref": "#/components/responses/BadRequest"}, "401": {"$ref": "#/components/responses/Unauthorized"}, "404": {"$ref": "#/components/responses/NotFound"}}}}, "/v1/analytics/goals": {"get": {"tags": ["Analytics"], "summary": "Получить цели и конверсии", "operationId": "getAnalyticsGoals", "parameters": [{"$ref": "#/components/parameters/From"}, {"$ref": "#/components/parameters/To"}, {"$ref": "#/components/parameters/Timezone"}, {"$ref": "#/components/parameters/AnalyticsAssistantId"}, {"$ref": "#/components/parameters/Channel"}], "responses": {"200": {"description": "Цели и метрики.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/GoalsReport"}}}}, "400": {"$ref": "#/components/responses/BadRequest"}, "401": {"$ref": "#/components/responses/Unauthorized"}, "404": {"$ref": "#/components/responses/NotFound"}}}, "post": {"tags": ["Analytics"], "summary": "Создать цель", "operationId": "createAnalyticsGoal", "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/GoalInput"}, "example": {"key": "lead_created", "name": "Создан лид", "description": "В CRM появилась новая сделка"}}}}, "responses": {"201": {"description": "Цель создана.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Goal"}}}}, "400": {"$ref": "#/components/responses/BadRequest"}, "401": {"$ref": "#/components/responses/Unauthorized"}, "409": {"$ref": "#/components/responses/Conflict"}}}}, "/v1/analytics/goals/{goal_id}": {"patch": {"tags": ["Analytics"], "summary": "Изменить цель", "operationId": "updateAnalyticsGoal", "parameters": [{"name": "goal_id", "in": "path", "required": true, "schema": {"type": "string"}}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/GoalPatch"}}}}, "responses": {"200": {"description": "Цель изменена.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/Goal"}}}}, "400": {"$ref": "#/components/responses/BadRequest"}, "401": {"$ref": "#/components/responses/Unauthorized"}, "404": {"$ref": "#/components/responses/NotFound"}}}}, "/v1/error-reports": {"post": {"tags": ["Error reports"], "summary": "Отправить уведомление об ошибке", "description": "Уведомить об ошибке в служебном топике «Ошибки». Иконка топика: ❗️, поле Telegram icon_custom_emoji_id: 5379748062124056162.", "operationId": "createErrorReport", "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ErrorReportInput"}, "example": {"source": "widget/checkout", "content": "Payment provider returned HTTP 502"}}}}, "responses": {"200": {"description": "Ошибка доставлена администратору.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/SuccessResponse"}}}}, "400": {"$ref": "#/components/responses/BadRequest"}, "401": {"$ref": "#/components/responses/Unauthorized"}, "502": {"description": "Telegram отклонил сообщение или недоступен.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ErrorResponse"}}}}, "503": {"description": "Доставка уведомлений не настроена.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ErrorResponse"}}}}}}}, "/v1/support-requests": {"post": {"tags": ["Support requests"], "summary": "Отправить запрос в поддержку", "description": "Отправляет текст в служебный топик «Запросы в поддержку». Иконка топика: ❓, поле Telegram icon_custom_emoji_id: 5377316857231450742. Организация и доступные данные отправителя определяются по авторизации; передать или подменить их в теле запроса нельзя.", "operationId": "createSupportRequest", "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/SupportRequestInput"}, "example": {"description": "Нужно добавить новый экран настройки, для которого требуется изменение исходного кода."}}}}, "responses": {"200": {"description": "Запрос доставлен в поддержку.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/SuccessResponse"}}}}, "400": {"$ref": "#/components/responses/BadRequest"}, "401": {"$ref": "#/components/responses/Unauthorized"}, "502": {"description": "Telegram отклонил сообщение.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ErrorResponse"}}}}, "503": {"description": "Доставка запросов в поддержку не настроена или временно недоступна.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ErrorResponse"}}}}}}}}, "components": {"securitySchemes": {"bearerAuth": {"type": "http", "scheme": "bearer", "bearerFormat": "API key", "description": "API-ключ вида upx_live_.... Получить ключ: support@uplexity.com или Telegram @uplexity."}}, "parameters": {"AssistantId": {"name": "assistant_id", "in": "path", "required": true, "schema": {"type": "string"}, "example": "ast_123"}, "PromptId": {"name": "prompt_id", "in": "path", "required": true, "schema": {"type": "string"}, "example": "prm_123"}, "ClientIdPath": {"name": "client_id", "in": "path", "required": true, "schema": {"type": "string", "minLength": 1, "maxLength": 500}}, "InternalConversationId": {"name": "conversation_id", "in": "path", "required": true, "schema": {"type": "string"}, "description": "Внутренний ID из поля id."}, "Ids": {"name": "ids", "in": "query", "required": false, "schema": {"type": "string"}, "description": "ID через запятую."}, "MessageIds": {"name": "ids", "in": "query", "required": false, "schema": {"type": "string"}, "description": "Внешние ID сообщений через запятую."}, "ClientIdQuery": {"name": "client_id", "in": "query", "required": false, "schema": {"type": "string"}}, "ExternalConversationId": {"name": "conversation_id", "in": "query", "required": false, "schema": {"type": "string"}, "description": "Внешний ID диалога."}, "MessageId": {"name": "message_id", "in": "query", "required": false, "schema": {"type": "string"}, "description": "Внешний ID сообщения."}, "Role": {"name": "role", "in": "query", "required": false, "schema": {"type": "string", "enum": ["user", "assistant"]}}, "Search": {"name": "search", "in": "query", "required": false, "schema": {"type": "string", "minLength": 2}, "description": "Регистронезависимый поиск по подстроке."}, "RequiredSearch": {"name": "search", "in": "query", "required": true, "schema": {"type": "string", "minLength": 2}, "description": "Регистронезависимый поиск по тексту."}, "Limit": {"name": "limit", "in": "query", "required": false, "schema": {"type": "integer", "minimum": 1, "maximum": 100, "default": 20}}, "Cursor": {"name": "cursor", "in": "query", "required": false, "schema": {"type": "string"}, "description": "Курсор из next_cursor."}, "From": {"name": "from", "in": "query", "required": false, "schema": {"type": "string", "format": "date"}, "description": "Начало периода включительно. from и to передаются вместе."}, "To": {"name": "to", "in": "query", "required": false, "schema": {"type": "string", "format": "date"}, "description": "Конец периода включительно. Максимальный период — 366 дней."}, "Timezone": {"name": "timezone", "in": "query", "required": false, "schema": {"type": "string", "default": "UTC"}, "description": "IANA timezone."}, "AnalyticsAssistantId": {"name": "assistant_id", "in": "query", "required": false, "schema": {"type": "string"}}, "Channel": {"name": "channel", "in": "query", "required": false, "schema": {"type": "string"}}}, "responses": {"BadRequest": {"description": "Некорректный запрос.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ErrorResponse"}}}}, "Unauthorized": {"description": "API-ключ отсутствует, недействителен или отозван.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ErrorResponse"}}}}, "NotFound": {"description": "Ресурс не найден.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ErrorResponse"}}}}, "Conflict": {"description": "Конфликт с текущим состоянием ресурса.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ErrorResponse"}}}}, "PayloadTooLarge": {"description": "Тело запроса превышает 1 МиБ.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ErrorResponse"}}}}, "UnsupportedMediaType": {"description": "Используйте application/json.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ErrorResponse"}}}}, "InternalError": {"description": "Внутренняя ошибка API.", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ErrorResponse"}}}}}, "schemas": {"KeyLoginRequest": {"type": "object", "properties": {"api_key": {"type": "string", "minLength": 1}}, "required": ["api_key"], "additionalProperties": false}, "KeyLoginResponse": {"type": "object", "properties": {"authenticated": {"type": "boolean", "const": true}, "key_name": {"type": "string"}, "organization_name": {"type": "string"}}, "required": ["authenticated", "key_name", "organization_name"]}, "ApiKeyAuthState": {"type": "object", "properties": {"authenticated": {"type": "boolean", "const": true}, "auth_method": {"type": "string", "const": "api_key"}, "key_name": {"type": "string"}, "organization_name": {"type": "string"}, "is_admin": {"type": "boolean", "const": false}}, "required": ["authenticated", "auth_method", "key_name", "organization_name", "is_admin"]}, "ErrorReportInput": {"type": "object", "properties": {"source": {"type": "string", "minLength": 1, "maxLength": 200, "description": "Сервис, модуль или операция, где произошла ошибка."}, "content": {"type": "string", "minLength": 1, "maxLength": 3400, "description": "Сообщение, stack trace или диагностические данные."}}, "required": ["source", "content"], "additionalProperties": false}, "SupportRequestInput": {"type": "object", "properties": {"description": {"type": "string", "minLength": 1, "maxLength": 2500, "description": "Краткое описание требуемой правки. Для вызова ИИ-инструментом текст формулирует сам ИИ; исходное сообщение пользователя автоматически не пересылается."}}, "required": ["description"], "additionalProperties": false}, "SuccessResponse": {"type": "object", "properties": {"ok": {"type": "boolean", "const": true}}, "required": ["ok"]}, "AssistantInput": {"type": "object", "properties": {"name": {"type": "string", "minLength": 1}, "description": {"type": "string", "maxLength": 200, "default": ""}}, "required": ["name"], "additionalProperties": false}, "AssistantPatch": {"type": "object", "properties": {"name": {"type": "string", "minLength": 1}, "description": {"type": "string", "maxLength": 200}}, "minProperties": 1, "additionalProperties": false}, "Assistant": {"type": "object", "properties": {"id": {"type": "string"}, "name": {"type": "string"}, "description": {"type": "string"}, "status": {"type": "string", "enum": ["active", "archived"]}, "created_at": {"type": "string", "format": "date-time"}, "updated_at": {"type": "string", "format": "date-time"}}, "required": ["id", "name", "description", "status", "created_at", "updated_at"]}, "PromptStatus": {"type": "string", "enum": ["draft", "active", "archived"]}, "PromptInput": {"type": "object", "properties": {"title": {"type": ["string", "null"]}, "content": {"type": "string", "minLength": 1}, "model": {"type": "string", "maxLength": 120, "pattern": "^gpt-[A-Za-z0-9._:-]*$", "description": "GPT-модель. Значение по умолчанию настраивается на сервере."}, "reasoning_effort": {"type": "string", "enum": ["none", "minimal", "low", "medium", "high", "xhigh", "max"], "description": "Допустимые значения зависят от семейства модели."}, "source_prompt_id": {"type": ["string", "null"], "description": "Непроверяемые метаданные происхождения версии."}}, "required": ["content"], "additionalProperties": false}, "PromptPatch": {"type": "object", "properties": {"title": {"type": ["string", "null"]}, "content": {"type": "string", "minLength": 1}, "model": {"type": "string", "maxLength": 120, "pattern": "^gpt-[A-Za-z0-9._:-]*$"}, "reasoning_effort": {"type": "string", "enum": ["none", "minimal", "low", "medium", "high", "xhigh", "max"]}}, "minProperties": 1, "additionalProperties": false}, "Prompt": {"type": "object", "properties": {"id": {"type": "string"}, "assistant_id": {"type": "string"}, "version": {"type": "integer", "minimum": 1}, "title": {"type": ["string", "null"]}, "content": {"type": "string"}, "model": {"type": ["string", "null"]}, "reasoning_effort": {"type": ["string", "null"]}, "created_by": {"type": "string", "enum": ["human", "ai"]}, "created_by_telegram_user_id": {"type": ["string", "null"]}, "source_prompt_id": {"type": ["string", "null"]}, "status": {"$ref": "#/components/schemas/PromptStatus"}, "created_at": {"type": "string", "format": "date-time"}, "updated_at": {"type": "string", "format": "date-time"}, "activated_at": {"type": ["string", "null"], "format": "date-time"}, "archived_at": {"type": ["string", "null"], "format": "date-time"}}, "required": ["id", "assistant_id", "version", "title", "content", "model", "reasoning_effort", "created_by", "status", "created_at", "updated_at"]}, "AnalyticsEventBatch": {"type": "object", "properties": {"events": {"type": "array", "minItems": 1, "maxItems": 100, "items": {"$ref": "#/components/schemas/AnalyticsEvent"}}}, "required": ["events"], "additionalProperties": false}, "AnalyticsEvent": {"oneOf": [{"$ref": "#/components/schemas/MessageEvent"}, {"$ref": "#/components/schemas/ErrorEvent"}, {"$ref": "#/components/schemas/GoalEvent"}], "discriminator": {"propertyName": "type", "mapping": {"message": "#/components/schemas/MessageEvent", "error": "#/components/schemas/ErrorEvent", "goal": "#/components/schemas/GoalEvent"}}}, "EventBase": {"type": "object", "properties": {"event_id": {"type": "string", "minLength": 1, "maxLength": 200}, "type": {"type": "string"}, "occurred_at": {"type": "string", "format": "date-time", "description": "RFC 3339 timestamp с часовым поясом."}, "assistant_id": {"type": "string", "minLength": 1, "maxLength": 100}, "conversation_id": {"type": "string", "minLength": 1, "maxLength": 300}, "client_id": {"type": "string", "minLength": 1, "maxLength": 500, "description": "Сохраняется в пределах организации; ingest при необходимости создаёт пустого active клиента."}, "channel": {"type": "string", "minLength": 1, "maxLength": 50, "description": "Сохраняется в нижнем регистре."}}, "required": ["event_id", "type", "occurred_at", "assistant_id", "conversation_id", "client_id", "channel"]}, "MessageEvent": {"allOf": [{"$ref": "#/components/schemas/EventBase"}, {"type": "object", "properties": {"type": {"const": "message"}, "message": {"$ref": "#/components/schemas/MessagePayload"}}, "required": ["message"]}]}, "MessagePayload": {"oneOf": [{"$ref": "#/components/schemas/UserMessagePayload"}, {"$ref": "#/components/schemas/AssistantMessagePayload"}], "discriminator": {"propertyName": "role", "mapping": {"user": "#/components/schemas/UserMessagePayload", "assistant": "#/components/schemas/AssistantMessagePayload"}}}, "UserMessagePayload": {"type": "object", "properties": {"id": {"type": "string", "minLength": 1, "maxLength": 300}, "role": {"type": "string", "const": "user"}, "text": {"type": "string", "maxLength": 100000, "description": "Сохраняется полностью и бессрочно."}, "openai_file_id": {"type": "string", "maxLength": 300}, "model": {"type": "string"}, "prompt_version_id": {"type": "string"}}, "required": ["id", "role", "text"]}, "AssistantMessagePayload": {"type": "object", "properties": {"id": {"type": "string", "minLength": 1, "maxLength": 300}, "role": {"type": "string", "const": "assistant"}, "text": {"type": "string", "maxLength": 100000, "description": "Сохраняется полностью и бессрочно."}, "openai_file_id": {"type": "string", "maxLength": 300}, "latency_ms": {"type": "integer", "minimum": 0}, "input_tokens": {"type": "integer", "minimum": 0}, "output_tokens": {"type": "integer", "minimum": 0}, "cost_usd": {"type": "number", "minimum": 0}, "model": {"type": "string"}, "prompt_version_id": {"type": "string"}}, "required": ["id", "role", "text", "latency_ms", "input_tokens", "output_tokens"]}, "ErrorEvent": {"allOf": [{"$ref": "#/components/schemas/EventBase"}, {"type": "object", "properties": {"type": {"const": "error"}, "error": {"$ref": "#/components/schemas/ErrorEventPayload"}}, "required": ["error"]}]}, "ErrorEventPayload": {"type": "object", "properties": {"id": {"type": "string", "maxLength": 300, "description": "Необязательно; по умолчанию используется event_id."}, "code": {"type": "string", "minLength": 1, "maxLength": 200}, "message": {"type": "string", "maxLength": 2000}, "http_status": {"type": "integer", "minimum": 100, "maximum": 599}, "model": {"type": "string"}, "prompt_version_id": {"type": "string"}, "latency_ms": {"type": "integer", "minimum": 0}, "input_tokens": {"type": "integer", "minimum": 0}, "output_tokens": {"type": "integer", "minimum": 0}, "cost_usd": {"type": "number", "minimum": 0}}, "required": ["code"]}, "GoalEvent": {"allOf": [{"$ref": "#/components/schemas/EventBase"}, {"type": "object", "properties": {"type": {"const": "goal"}, "goal": {"type": "object", "properties": {"key": {"type": "string", "maxLength": 64, "pattern": "^[a-z][a-z0-9_]{0,63}$"}, "occurrence_id": {"type": "string", "minLength": 1, "maxLength": 300}}, "required": ["key", "occurrence_id"]}}, "required": ["goal"]}]}, "IngestResult": {"type": "object", "properties": {"accepted": {"type": "integer", "minimum": 0}, "duplicates": {"type": "integer", "minimum": 0}, "total": {"type": "integer", "minimum": 0}, "results": {"type": "array", "items": {"type": "object", "properties": {"event_id": {"type": "string"}, "status": {"type": "string", "enum": ["accepted", "duplicate"]}}, "required": ["event_id", "status"]}}}, "required": ["accepted", "duplicates", "total", "results"]}, "NullableClientField": {"type": ["string", "null"], "maxLength": 500}, "NullableClientComment": {"type": ["string", "null"], "maxLength": 10000}, "ClientInput": {"type": "object", "properties": {"id": {"type": "string", "minLength": 1, "maxLength": 500, "description": "Неизменяемый ID клиента."}, "nickname": {"$ref": "#/components/schemas/NullableClientField"}, "name": {"$ref": "#/components/schemas/NullableClientField"}, "phone_number": {"$ref": "#/components/schemas/NullableClientField"}, "comment": {"$ref": "#/components/schemas/NullableClientComment"}}, "required": ["id"], "additionalProperties": false}, "ClientPatch": {"type": "object", "properties": {"nickname": {"$ref": "#/components/schemas/NullableClientField"}, "name": {"$ref": "#/components/schemas/NullableClientField"}, "phone_number": {"$ref": "#/components/schemas/NullableClientField"}, "comment": {"$ref": "#/components/schemas/NullableClientComment"}}, "minProperties": 1, "additionalProperties": false}, "ClientProfile": {"type": "object", "properties": {"id": {"type": "string", "maxLength": 500}, "nickname": {"$ref": "#/components/schemas/NullableClientField"}, "name": {"$ref": "#/components/schemas/NullableClientField"}, "phone_number": {"$ref": "#/components/schemas/NullableClientField"}, "comment": {"$ref": "#/components/schemas/NullableClientComment"}}, "required": ["id", "nickname", "name", "phone_number", "comment"]}, "Client": {"allOf": [{"$ref": "#/components/schemas/ClientProfile"}, {"type": "object", "properties": {"status": {"type": "string", "enum": ["active", "archived"]}, "created_at": {"type": "string", "format": "date-time"}, "updated_at": {"type": "string", "format": "date-time"}, "archived_at": {"type": ["string", "null"], "format": "date-time"}}, "required": ["status", "created_at", "updated_at", "archived_at"]}]}, "DeleteResult": {"type": "object", "properties": {"deleted": {"type": "boolean", "const": true}}, "required": ["deleted"]}, "ClientsPage": {"type": "object", "properties": {"clients": {"type": "array", "items": {"$ref": "#/components/schemas/Client"}}, "next_cursor": {"type": ["string", "null"]}}, "required": ["clients", "next_cursor"]}, "Conversation": {"type": "object", "properties": {"id": {"type": "string", "description": "Внутренний ID диалога."}, "conversation_id": {"type": "string", "description": "Внешний ID диалога, переданный при ingest."}, "assistant_id": {"type": "string"}, "client_id": {"type": "string"}, "channel": {"type": "string"}, "created_at": {"type": "string", "format": "date-time"}, "updated_at": {"type": "string", "format": "date-time"}, "last_message_at": {"type": ["string", "null"], "format": "date-time"}, "message_count": {"type": "integer", "minimum": 0}, "client": {"$ref": "#/components/schemas/ClientProfile"}}, "required": ["id", "conversation_id", "assistant_id", "client_id", "channel", "created_at", "updated_at", "last_message_at", "message_count", "client"]}, "ConversationsPage": {"type": "object", "properties": {"conversations": {"type": "array", "items": {"$ref": "#/components/schemas/Conversation"}}, "next_cursor": {"type": ["string", "null"]}}, "required": ["conversations", "next_cursor"]}, "Message": {"type": "object", "properties": {"id": {"type": "string", "description": "Внешний ID сообщения."}, "conversation_id": {"type": "string", "description": "Внутренний ID диалога."}, "role": {"type": "string", "enum": ["user", "assistant"]}, "text": {"type": "string"}, "openai_file_id": {"type": ["string", "null"], "maxLength": 300}, "prompt_version_id": {"type": ["string", "null"]}, "model": {"type": ["string", "null"]}, "latency_ms": {"type": ["integer", "null"], "minimum": 0}, "input_tokens": {"type": ["integer", "null"], "minimum": 0}, "output_tokens": {"type": ["integer", "null"], "minimum": 0}, "cost_usd": {"type": ["number", "null"], "minimum": 0}, "occurred_at": {"type": "string", "format": "date-time"}}, "required": ["id", "conversation_id", "role", "text", "openai_file_id", "prompt_version_id", "model", "latency_ms", "input_tokens", "output_tokens", "cost_usd", "occurred_at"]}, "MessagesPage": {"type": "object", "properties": {"messages": {"type": "array", "items": {"$ref": "#/components/schemas/Message"}}, "next_cursor": {"type": ["string", "null"]}}, "required": ["messages", "next_cursor"]}, "GoalInput": {"type": "object", "properties": {"key": {"type": "string", "maxLength": 64, "pattern": "^[a-z][a-z0-9_]{0,63}$"}, "name": {"type": "string", "minLength": 1, "maxLength": 100}, "description": {"type": "string", "maxLength": 200}}, "required": ["key", "name"], "additionalProperties": false}, "GoalPatch": {"type": "object", "properties": {"name": {"type": "string", "minLength": 1, "maxLength": 100}, "description": {"type": "string", "maxLength": 200}, "status": {"type": "string", "enum": ["active", "archived"]}}, "minProperties": 1, "additionalProperties": false}, "Goal": {"type": "object", "properties": {"id": {"type": "string"}, "key": {"type": "string"}, "name": {"type": "string"}, "description": {"type": "string"}, "status": {"type": "string", "enum": ["active", "archived"]}, "created_at": {"type": "string", "format": "date-time"}, "updated_at": {"type": "string", "format": "date-time"}}, "required": ["id", "key", "name", "description", "status", "created_at", "updated_at"]}, "ReportEnvelope": {"type": "object", "properties": {"period": {"$ref": "#/components/schemas/ReportPeriod"}, "filters": {"$ref": "#/components/schemas/ReportFilters"}, "generated_at": {"type": "string", "format": "date-time"}}, "required": ["period", "filters", "generated_at"]}, "ReportPeriod": {"type": "object", "properties": {"from": {"type": "string", "format": "date"}, "to": {"type": "string", "format": "date"}, "timezone": {"type": "string"}}, "required": ["from", "to", "timezone"]}, "ReportFilters": {"type": "object", "properties": {"assistant_id": {"type": ["string", "null"]}, "channel": {"type": ["string", "null"]}}, "required": ["assistant_id", "channel"]}, "AudienceMetrics": {"type": "object", "properties": {"unique_people": {"type": "integer", "minimum": 0, "description": "Уникальные client_id только из пользовательских сообщений."}}, "required": ["unique_people"]}, "MessageMetrics": {"type": "object", "properties": {"user": {"type": "integer", "minimum": 0}, "assistant": {"type": "integer", "minimum": 0}, "total": {"type": "integer", "minimum": 0}}, "required": ["user", "assistant", "total"]}, "RequestMetrics": {"type": "object", "properties": {"successful": {"type": "integer", "minimum": 0}, "failed": {"type": "integer", "minimum": 0}, "total": {"type": "integer", "minimum": 0}, "success_rate": {"type": ["number", "null"], "minimum": 0, "maximum": 1}}, "required": ["successful", "failed", "total", "success_rate"]}, "TokenMetrics": {"type": "object", "properties": {"input": {"type": "integer", "minimum": 0}, "output": {"type": "integer", "minimum": 0}, "total": {"type": "integer", "minimum": 0}}, "required": ["input", "output", "total"]}, "CostMetrics": {"type": "object", "properties": {"usd": {"type": "number", "minimum": 0}}, "required": ["usd"]}, "DialogOutcomeMetrics": {"type": "object", "properties": {"conversations": {"type": "integer", "minimum": 0}, "with_outcome": {"type": "integer", "minimum": 0}, "goal_occurrences": {"type": "integer", "minimum": 0}, "outcome_rate": {"type": ["number", "null"], "minimum": 0, "maximum": 1}}, "required": ["conversations", "with_outcome", "goal_occurrences", "outcome_rate"]}, "LatencyMetrics": {"type": "object", "properties": {"average_ms": {"type": ["integer", "null"], "minimum": 0}, "p50_ms": {"type": ["integer", "null"], "minimum": 0}, "p95_ms": {"type": ["integer", "null"], "minimum": 0}, "sample_count": {"type": "integer", "minimum": 0}, "show_p95": {"type": "boolean"}, "p95_direction": {"type": ["string", "null"], "enum": ["above", "below", null]}}, "required": ["average_ms", "p50_ms", "p95_ms", "sample_count", "show_p95", "p95_direction"]}, "GoalMetrics": {"allOf": [{"$ref": "#/components/schemas/Goal"}, {"type": "object", "properties": {"occurrences": {"type": "integer", "minimum": 0}, "unique_people": {"type": "integer", "minimum": 0}, "conversations": {"type": "integer", "minimum": 0}, "conversion_rate": {"type": ["number", "null"], "minimum": 0}}, "required": ["occurrences", "unique_people", "conversations", "conversion_rate"]}]}, "BreakdownItem": {"type": "object", "properties": {"model": {"type": ["string", "null"]}, "prompt_version_id": {"type": ["string", "null"]}, "successful": {"type": "integer", "minimum": 0}, "failed": {"type": "integer", "minimum": 0}, "requests": {"type": "integer", "minimum": 0}, "input_tokens": {"type": "integer", "minimum": 0}, "output_tokens": {"type": "integer", "minimum": 0}, "total_tokens": {"type": "integer", "minimum": 0}, "cost_usd": {"type": "number", "minimum": 0}}, "required": ["successful", "failed", "requests", "input_tokens", "output_tokens", "total_tokens", "cost_usd"]}, "BreakdownMetrics": {"type": "object", "properties": {"models": {"type": "array", "items": {"$ref": "#/components/schemas/BreakdownItem"}}, "prompt_versions": {"type": "array", "items": {"$ref": "#/components/schemas/BreakdownItem"}}}, "required": ["models", "prompt_versions"]}, "ErrorMetrics": {"type": "object", "properties": {"total": {"type": "integer", "minimum": 0}, "rate": {"type": ["number", "null"], "minimum": 0}, "by_code": {"type": "array", "items": {"type": "object", "properties": {"code": {"type": "string"}, "count": {"type": "integer", "minimum": 0}}, "required": ["code", "count"]}}, "by_http_status": {"type": "array", "items": {"type": "object", "properties": {"http_status": {"type": ["integer", "null"]}, "count": {"type": "integer", "minimum": 0}}, "required": ["http_status", "count"]}}, "recent": {"type": "array", "maxItems": 20, "items": {"$ref": "#/components/schemas/RecentError"}}}, "required": ["total", "rate", "by_code", "by_http_status", "recent"]}, "RecentError": {"type": "object", "properties": {"code": {"type": "string"}, "message": {"type": "string"}, "http_status": {"type": ["integer", "null"]}, "model": {"type": ["string", "null"]}, "prompt_version_id": {"type": ["string", "null"]}, "occurred_at": {"type": "string", "format": "date-time"}}, "required": ["code", "message", "http_status", "model", "prompt_version_id", "occurred_at"]}, "AudienceReport": {"allOf": [{"$ref": "#/components/schemas/ReportEnvelope"}, {"$ref": "#/components/schemas/AudienceMetrics"}]}, "UsageReport": {"allOf": [{"$ref": "#/components/schemas/ReportEnvelope"}, {"type": "object", "properties": {"messages": {"$ref": "#/components/schemas/MessageMetrics"}, "requests": {"$ref": "#/components/schemas/RequestMetrics"}, "tokens": {"$ref": "#/components/schemas/TokenMetrics"}, "cost": {"$ref": "#/components/schemas/CostMetrics"}, "dialog_outcomes": {"$ref": "#/components/schemas/DialogOutcomeMetrics"}}, "required": ["messages", "requests", "tokens", "cost", "dialog_outcomes"]}]}, "PerformanceReport": {"allOf": [{"$ref": "#/components/schemas/ReportEnvelope"}, {"type": "object", "properties": {"latency": {"$ref": "#/components/schemas/LatencyMetrics"}}, "required": ["latency"]}]}, "GoalsReport": {"allOf": [{"$ref": "#/components/schemas/ReportEnvelope"}, {"type": "object", "properties": {"items": {"type": "array", "items": {"$ref": "#/components/schemas/GoalMetrics"}}}, "required": ["items"]}]}, "BreakdownsReport": {"allOf": [{"$ref": "#/components/schemas/ReportEnvelope"}, {"$ref": "#/components/schemas/BreakdownMetrics"}]}, "ErrorsReport": {"allOf": [{"$ref": "#/components/schemas/ReportEnvelope"}, {"$ref": "#/components/schemas/ErrorMetrics"}]}, "TimeseriesPoint": {"type": "object", "properties": {"bucket_start": {"type": "string", "format": "date"}, "audience": {"$ref": "#/components/schemas/AudienceMetrics"}, "messages": {"$ref": "#/components/schemas/MessageMetrics"}, "requests": {"$ref": "#/components/schemas/RequestMetrics"}, "errors": {"type": "integer", "minimum": 0}, "tokens": {"$ref": "#/components/schemas/TokenMetrics"}, "cost": {"$ref": "#/components/schemas/CostMetrics"}, "latency": {"$ref": "#/components/schemas/LatencyMetrics"}, "goal_occurrences": {"type": "integer", "minimum": 0}, "dialog_outcomes": {"$ref": "#/components/schemas/DialogOutcomeMetrics"}}, "required": ["bucket_start", "audience", "messages", "requests", "errors", "tokens", "cost", "latency", "goal_occurrences", "dialog_outcomes"]}, "TimeseriesReport": {"allOf": [{"$ref": "#/components/schemas/ReportEnvelope"}, {"type": "object", "properties": {"interval": {"type": "string", "enum": ["day", "week"]}, "points": {"type": "array", "items": {"$ref": "#/components/schemas/TimeseriesPoint"}}}, "required": ["interval", "points"]}]}, "AnalyticsReport": {"allOf": [{"$ref": "#/components/schemas/ReportEnvelope"}, {"type": "object", "properties": {"audience": {"$ref": "#/components/schemas/AudienceMetrics"}, "messages": {"$ref": "#/components/schemas/MessageMetrics"}, "requests": {"$ref": "#/components/schemas/RequestMetrics"}, "tokens": {"$ref": "#/components/schemas/TokenMetrics"}, "cost": {"$ref": "#/components/schemas/CostMetrics"}, "dialog_outcomes": {"$ref": "#/components/schemas/DialogOutcomeMetrics"}, "latency": {"$ref": "#/components/schemas/LatencyMetrics"}, "goals": {"type": "array", "items": {"$ref": "#/components/schemas/GoalMetrics"}}, "breakdowns": {"$ref": "#/components/schemas/BreakdownMetrics"}, "errors": {"$ref": "#/components/schemas/ErrorMetrics"}}, "required": ["audience", "messages", "requests", "tokens", "cost", "dialog_outcomes", "latency", "goals", "breakdowns", "errors"]}]}, "ErrorResponse": {"type": "object", "properties": {"error": {"type": "object", "properties": {"code": {"type": "string"}, "message": {"type": "string"}, "details": {"type": "object", "additionalProperties": true}}, "required": ["code", "message"]}}, "required": ["error"]}}}}