Skip to content

Backend API — dm-voice-agent

Полный каталог эндпоинтов бэкенда Twinlix.

Stack: Node 20 + Fastify + TypeScript + Prisma + MySQL Prod: https://api.twinlix.comDev: http://localhost:3000Код: dm-voice-agent/backend/


Содержание


Аутентификация и авторизация

Middleware

MiddlewareФайлНазначение
Authsrc/api/middleware/auth.tsJWT Bearer из Authorization header; извлекает user_id, tenant_id, role
RBACsrc/api/middleware/rbac.tsПроверяет role === 'admin' для admin-only endpoints
Rate Limitsrc/api/middleware/rate-limit.tsAuth: 10 req/min, KB upload: 5 req/min, General: 100 req/min
Quotasrc/api/middleware/quota.middleware.tsПроверяет лимиты подписки перед операцией
Subscriptionsrc/api/middleware/subscription.middleware.tsПроверяет наличие активной подписки

JWT Token

typescript
{
  user_id: string;         // UUID
  tenant_id: string;       // UUID или "*" для dev-токена
  organization_id?: string;
  role: "admin" | "member";
  type: "access" | "refresh";
  dev_mode?: boolean;
}
  • Access token: 1 час
  • Refresh token: 30 дней
  • Dev token (tenant_id: "*") работает только в non-production

Rate Limiting

EndpointЛимитОкно
Auth endpoints10 req/minPer email
Forgot password5 req/hourPer email
KB uploads5 req/minPer tenant
General100 req/minPer IP

Auth endpoints

Prefix: /v1/auth · Файл: src/api/routes/auth.ts

POST /v1/auth/register

  • Auth: нет (public)
  • Body: { email, password (min 8), businessName, countryCode?, first_name?, last_name? }
  • Response 201: { user, tenant, workspace, agent, phoneNumber, tokens: { accessToken, refreshToken } }
  • Создаёт бизнес, tenant, workspace, дефолтного агента и trial-подписку

POST /v1/auth/login

  • Auth: нет
  • Body: { email, password }
  • Response 200: { user, tenant, role, tokens }

POST /v1/auth/refresh

  • Auth: нет
  • Body: { refreshToken }
  • Response 200: { tokens: { accessToken, refreshToken } }

POST /v1/auth/change-password

  • Auth: Bearer
  • Body: { currentPassword, newPassword (min 8) }
  • Response 200: { message: "Password changed successfully" }

POST /v1/auth/delete

  • Auth: Bearer
  • Body: { password } (подтверждение)
  • Response 200: { message, deleted: { user, tenant, tenant_id? } }
  • Каскадно удаляет все данные (agents, channels, KB, calls...)

POST /v1/auth/forgot-password

  • Auth: нет
  • Body: { email }
  • Response 202: { message } — отправляет 6-значный код на email

POST /v1/auth/reset-password

  • Auth: нет
  • Body: { email, code (6 цифр), newPassword }
  • Response 200: { message: "Password reset successfully" }

Users — профиль

Prefix: /v1/users · Файл: src/api/routes/users.ts · Auth: Bearer

GET /v1/users/me

  • Response 200: { id, email, first_name, last_name, avatar_url, created_at }

PATCH /v1/users/me

  • Body: { email?, first_name? (max 64), last_name? (max 64) }
  • Response 200: updated user

POST /v1/users/me/avatar

  • Content-Type: multipart/form-data (JPEG/PNG/WebP/GIF, max 5MB)
  • Response 200: { avatar_url }

DELETE /v1/users/me/avatar

  • Response 200: { message: "Avatar deleted" }

Agents — управление ботами

Prefix: /v1/agents · Файл: src/api/routes/agents.ts · Auth: Bearer (mutations: admin)

POST /v1/agents

  • Body: { name (1-255), voice_id?, greeting?, tool_webhook_url?, recording_enabled? }
  • Response 201: { status: "success", data: Agent }

GET /v1/agents

  • Query: limit? (1-100, default 20), offset? (default 0)
  • Response 200: { status: "success", data: Agent[] }

GET /v1/agents/:id

  • Response 200: { status: "success", data: Agent }

PUT /v1/agents/:id

  • Body: partial Agent
  • Response 200: updated Agent

DELETE /v1/agents/:id

  • Каскадно удаляет channels, calls

GET /v1/agents/:id/prompt

  • Response 200: { finalPrompt } — собранный из всех секций промпт

Agent Prompts — настройка промптов

Prefix: /v1/agents/:id/prompts · Файл: src/api/routes/agent-prompt.ts · Auth: Bearer + admin

Скалярные секции (POST/GET)

EndpointПоля
/identityprompt_assistant_name, prompt_assistant_slug, prompt_who_you_are
/welcome-messageprompt_welcome_message, prompt_welcome_message_description
/general-infoprompt_general_info
/languageprompt_language_instruction
/how-to-answerprompt_clarify_critical, prompt_how_to_give_instructions, prompt_response_length, prompt_escalation
/signoffprompt_signoff_message, prompt_signoff_message_description

Списочные секции (CRUD)

Каждая секция поддерживает: POST (create), GET (list), PUT /:itemId (update), DELETE /:itemId

EndpointПоля элемента
/greetingswelcome_message, welcome_message_description?, sort_order?
/signoffsаналогично greetings
/starter-questionsquestion_text, question_type?, answer_text?, select?, sort_order?

Members — команда

Prefix: /v1/tenants/:tenant_id/members · Файл: src/api/routes/members.ts

POST — пригласить

  • Auth: admin
  • Body: { email, role: "admin" | "member" }
  • Response 201: { status, data: { member, message } } — отправляет email с приглашением

GET — список

  • Query: limit?, offset?

PUT /:member_id — изменить роль

  • Auth: admin
  • Body: { role? }

DELETE /:member_id — удалить

  • Auth: admin

Channels — каналы связи

Prefix: /v1/channels · Файл: src/api/routes/channels.ts · Auth: Bearer

Типы: voice, webvoice, webchat, instagram, messenger, whatsapp, telegram

GET /v1/channels/types

  • Response 200: [{ value, label, provider, description, capabilities, available }]
  • available: -1 = unlimited, 0 = none (по тарифу)

POST /v1/channels

  • Auth: admin
  • Body: { type, name, agent_id, ...type-specific config }

GET /v1/channels

  • Query: tenant_id, type?, status?, limit?, offset?

GET /v1/channels/:channel_id

PUT /v1/channels/:channel_id — обновить конфиг

DELETE /v1/channels/:channel_id

POST /v1/channels/:channel_id/avatar

  • Content-Type: multipart/form-data (max 5MB)

PATCH /v1/channels/:channel_id/widget-settings

  • Body: { theme, position, placeholder, banner }

Calls — звонки

Prefix: /v1/tenants/:tenant_id/calls · Файл: src/api/routes/calls.ts · Auth: Bearer

POST .../calls/outbound

  • Body: { agent_id, to_number (E.164), from_number?, first_message? (max 1000), context?, callback_url? }
  • Response 202: { call_id, message } — звонок инициирован асинхронно
  • Error 429: { quota: { metric, used, limit }, action: { type: "upgrade" } }

GET .../calls

  • Query: page?, page_size? (max 100), direction?, status?, start_date?, end_date?
  • Status: initiated, ringing, connected, completed, failed

GET .../calls/:call_id — детали и транскрипт

POST .../calls/export

  • Query: format? ("csv"|"json"), direction?, status?, start_date?, end_date?

Scheduled Calls

Prefix: /v1/tenants/:tenant_id/calls/scheduled · Файл: src/api/routes/scheduled-calls.ts

POST — запланировать

  • Body: { agent_id, to_number, scheduled_at (ISO 8601, future), timezone?, from_number?, first_message?, context?, callback_url? }

GET — список (page?, page_size?, status?)

GET /:scheduled_call_id

PUT /:scheduled_call_id — перенести

DELETE /:scheduled_call_id — отменить


Campaigns — массовый обзвон

Prefix: /v1/tenants/:tenant_id/campaigns · Файл: src/api/routes/campaigns.ts

POST — создать кампанию

  • Body: { name, agent_id, from_number?, first_message?, max_concurrent? (max 50), calls_per_minute? (max 100), max_retries? (max 10), retry_delay_min?, retry_on?, schedule_start?, schedule_end?, timezone?, callback_url? }

GET — список (page?, page_size?, status?)

GET /:campaign_id

PUT /:campaign_id — обновить

DELETE /:campaign_id

POST /:campaign_id/contacts — импорт контактов

  • Body: { contacts: [{ phone_number, phones?, contact_name?, context? }] } (1-50000)

GET /:campaign_id/contacts — список контактов

POST /:campaign_id/start — запустить

POST /:campaign_id/pause — пауза

POST /:campaign_id/cancel — отменить


DNC — Do Not Call

Prefix: /v1/tenants/:tenant_id/dnc · Файл: src/api/routes/dnc.ts · Auth: admin

POST — добавить номер

  • Body: { phone_number (E.164), reason? (max 255) }

GET — список (page?, page_size?)

DELETE /:phone_number — удалить (URL-encoded)

POST /bulk-import

  • Body: { numbers: [{ phone_number, reason? }] } (max 10000)

Knowledge Base — база знаний

Prefix: /v1/tenants/:tenant_id/kb · Файл: src/api/routes/kb.ts

POST /v1/tenants/:tenant_id/kb — загрузить документ

  • Auth: admin · Rate: 5 req/min
  • Content-Type: multipart/form-data (TXT/DOC/DOCX, max 10MB)
  • Response 201: { id, tenant_id, filename, file_url, size_bytes, status, chunk_count, created_at }
  • Status: uploadedvectorization_pendingready

GET /v1/tenants/:tenant_id/kb — список

  • Query: source_type? (upload|url|text|web|faq), status?, search?, page?, limit?
  • Response 200: { items, total, page }

GET /v1/kb/:kb_id — детали

POST /v1/kb-delete/:kb_id — удалить (MySQL + vector DB + disk)

POST /v1/kb-delete/bulk — массовое удаление

  • Body: { ids: string[] } (max 100)
  • Response 200|207: { total, succeeded, failed, items }

KB Web Documents

Prefix: /v1/kb-web · Файл: src/api/routes/kb-web.ts · Auth: admin

POST — добавить URL

  • Body: { title (max 255), link (valid URL), content?, suggest_source_link? }
  • Асинхронный скрапинг через n8n

GET — список (page?, limit?)

PUT /:id — обновить

DELETE /:id


KB Text Documents

Prefix: /v1/kb-text · Файл: src/api/routes/kb-text.ts · Auth: admin

POST — создать

  • Body: { title, content }

GET — список (page?, limit?)

PUT /:id — обновить

DELETE /:id


Messages & Conversations

Prefix: /v1/messages · Файл: src/api/routes/messages.ts, messages-send.ts · Auth: Bearer

GET /v1/messages/conversation — история переписки

  • Query: tenant_id, channel_id, external_user_id, start_date?, updated_since?, end_date?, direction?, limit? (1-100), offset?
  • Response 200: { messages: [{ id, direction, message_type, message_text, metadata, created_at }], total }

GET /v1/messages/conversations — список диалогов

  • Response 200: { conversations: [{ id, channel_id, external_user_id, last_message, last_message_time, message_count }], total }

GET /v1/messages/conversations/:conversation_id

PATCH /v1/messages/conversations/:conversationId/labels

  • Body: { labels } — пометить important/archived/is_ai_disabled

POST /v1/messages/conversations/batch-delete

  • Body: { conversationIds } — массовое удаление

POST /v1/messages/send

  • Body: { tenant_id, channel_id, external_user_id, message, message_type? }

Webchat (public)

Prefix: /v1/webchat · Файл: src/api/routes/webchat.ts · Auth: нет

POST /v1/webchat/init

  • Body: { tenant_id, channel_id, external_user_id?, metadata? }
  • Response 200: { session_id, channel_id, external_user_id, greeting_message?, theme_color?, agent_name?, starter_questions? }

POST /v1/webchat/send

  • Body: { tenant_id, channel_id, external_user_id, content, message_type? }

GET /v1/webchat/messages — поллинг

  • Query: tenant_id, channel_id, external_user_id, since?, limit?

GET /v1/webchat/history — полная история


Setup Agent — интерактивная настройка

Prefix: /v1/setup-agent · Файл: src/api/routes/setup-agent.ts · Auth: нет

POST /init — начать сессию

  • Body: { channel_id, setup_context?: { business_type?, pain_points?, goals? } }

POST /chat — сообщение в чат

  • Body: { channel_id, session_id, user_message }
  • Response 200: { response, next_step?, completed? }

GET /context — текущий прогресс

  • Query: channel_id, session_id

Tenants — аккаунт

Prefix: /v1/tenants/:tenant_id · Файл: src/api/routes/tenants.ts · Auth: Bearer

GET .../account

  • Response 200: { company_name, assistant_name?, assistant_slug?, logo_url?, created_at }

PUT .../account — обновить

  • Content-Type: multipart/form-data (max 5MB)
  • Response 200: { logo_url }

GET .../retention — политика хранения данных

PUT .../retention — обновить ({ retention_days: 1-365 })


Phone Numbers

Файлы: src/api/routes/numbers.ts, phone-numbers.ts · Auth: Bearer (admin для мутаций)

POST /v1/tenants/:tenant_id/numbers — купить номер

  • Body: { country_code (ISO 2), area_code?, capabilities: ["voice","sms"] }
  • Покупка через Twilio, проверка квоты тарифа

GET /v1/tenants/:tenant_id/phone-numbers

  • Query: status?, country?, available?
  • Response 200: [{ id, e164, country, provider, capabilities, status, created_at }]

DELETE /v1/tenants/:tenant_id/phone-numbers/:number_id — отпустить номер


Billing & Subscriptions

GET /v1/pricing-tiers — тарифы (public)

  • Файл: src/api/routes/billing.ts
  • Response 200: [{ id, slug, name, price_monthly, currency, is_trial, quota_call_minutes, quota_storage_gb, quota_messages, quota_channels_*, features_json, sort_order }]

GET /v1/pricing-tiers/:slug — детали тарифа

GET /v1/stripe/checkout — создать Checkout сессию

  • Файл: src/api/routes/stripe-checkout.ts
  • Query: { tenant_id, tier_slug, return_url, cancel_url }
  • Response 302: redirect на Stripe или return_url (для бесплатных)

GET /v1/tenants/:tenant_id/subscription

  • Файл: src/api/routes/subscriptions.ts
  • Response 200: { id, status (trial|active|past_due|canceled|suspended|expired), trial_start, trial_end, current_period_start, current_period_end, tier: {...} }

POST /v1/tenants/:tenant_id/subscription — создать/upgrade

  • Body: { tier_slug, payment_method_id? }

PATCH /v1/tenants/:tenant_id/subscription — upgrade/downgrade

  • Body: { tier_slug }

DELETE /v1/tenants/:tenant_id/subscription — отменить

  • Query: immediate? (сразу или в конце периода)

POST /v1/tenants/:tenant_id/subscription/force-downgrade

  • Body: { tier_slug }

Usage & Invoices

GET /v1/tenants/:tenant_id/usage/current

  • Файл: src/api/routes/usage.ts
  • Response 200: { call_minutes: { used, quota, remaining, overage, cost_cents }, storage_gb, messages, api_calls, kb_characters, total_cost_cents }

GET /v1/tenants/:tenant_id/usage/history

  • Query: months? (1-12, default 6)

GET /v1/tenants/:tenant_id/invoices

  • Файл: src/api/routes/invoices.ts
  • Query: page?, limit?, status? (draft|pending|paid|failed|void)
  • Response 200: { invoices: [{ id, invoice_number, status, billing_period_start, billing_period_end, subtotal, tax, total, currency, due_date, paid_at, pdf_url }], total, page, pages }

GET /v1/tenants/:tenant_id/invoices/:invoice_id

GET /v1/tenants/:tenant_id/invoices/:invoice_id/pdf — скачать PDF


Payment Methods & Payments

GET /v1/tenants/:tenant_id/payment-methods

  • Файл: src/api/routes/payment-methods.ts
  • Response 200: { payment_methods: [{ id, stripe_payment_method_id, type, brand, last4, exp_month, exp_year, is_default }] }

POST .../payment-methods — добавить

DELETE .../payment-methods/:id — удалить

GET /v1/tenants/:tenant_id/payments

  • Файл: src/api/routes/payments.ts
  • Query: page?, limit?, status? (pending|succeeded|failed|refunded)
  • Response 200: { payments: [{ id, invoice_id, amount_cents, status, paid_at, invoice }], total, page, pages }

Voice Widget (public)

Prefix: /v1/voice-widget/:channelId · Файл: src/api/routes/voice-widget.ts · Auth: нет

GET / — конфиг виджета

  • Response 200: { channel, agent, config: { theme_color, position, greeting_message } }

GET /embed — HTML embed code

GET /conversation-token — WebSocket токен для голосовой сессии

GET /voice-call-button.js — встраиваемый JS скрипт


Meta Integration

GET /v1/meta/oauth/connect — инициировать OAuth

  • Файл: src/api/routes/meta-oauth.ts
  • Query: { tenant_id, workspace_id?, return_url }
  • Response 302: redirect на Meta consent

GET /v1/meta/callback — OAuth callback

GET /v1/meta/connect — статус подключения

POST /v1/meta/messages — отправить сообщение через Meta


FAQ

Prefix: /v1/faqs (или /v1/tenants/:tenantId/faqs) · Файл: src/api/routes/faq.ts

POST — создать { question, answer, category?, sort_order? }

GET — список (workspace_id?, category?, limit?, offset?)

PUT /:id — обновить

DELETE /:id


Webhooks (inbound)

Входящие вебхуки от внешних сервисов.

EndpointВерификацияОписаниеФайл
POST /webhooks/twilio/voiceTwilio HMAC-SHA1Входящий звонок → TwiMLwebhooks/twilio.ts
POST /webhooks/twilio/statusTwilio HMAC-SHA1Статус звонкаwebhooks/twilio.ts
GET /v1/webhooks/metaverify_tokenMeta webhook verificationmeta-webhook.ts
POST /v1/webhooks/metaHMAC-SHA256Meta events (messages, reads)meta-webhook.ts
POST /v1/webhooks/stripeStripe HMAC-SHA256Billing eventswebhooks/stripe.ts
POST /webhooks/n8nCustom headerKB processing callbackwebhooks/n8n-kb.ts
POST /webhooks/elevenlabsElevenLabs signatureAgent eventswebhooks/elevenlabs.ts
POST /webhooks/elevenlabs/toolsElevenLabs signatureTool invocationswebhooks/elevenlabs-tools.ts
POST /v1/pdf-parser-webhookService signaturePDF parsing callbackwebhooks/pdf-parser.ts

WebSocket endpoints

EndpointОписаниеФайл
WS /socket/voice-streamДвунаправленный голосовой стрим (binary audio frames)src/index.ts:323
WS /socket/elevenlabs-proxyПрокси к ElevenLabs WebSocket для low-latency voicesrc/index.ts:325

Авторизация через токен из GET /v1/voice-widget/:channelId/conversation-token.


Admin Panel

Prefix: /v1/admin · Auth: Bearer + admin role

Organizations

  • POST/GET /v1/admin/organizations — CRUD организаций
  • GET /v1/admin/organizations/:id
  • PUT /v1/admin/organizations/:id
  • POST /v1/admin/organizations/:id/api-keys{ key: "org_live_..." }

Config

  • POST/GET /v1/admin/config — системные настройки (key-value)
  • POST /v1/admin/system-config — платформенные настройки

Testing

  • POST /v1/admin/testing/setup — подготовка тестовых данных
  • POST /v1/admin/testing/run — запуск тестов
  • POST /v1/admin/testing/full-cycle — полный E2E цикл
  • GET /v1/admin/testing/status

Other

  • POST/GET /v1/admin/email-templates — шаблоны email
  • POST /v1/admin/kb-revectorize — массовая ре-векторизация KB
  • POST /v1/admin/elevenlabs/phone-numbers — конфиг номеров ElevenLabs

Health & Metrics

GET /healthz

  • Auth: нет
  • Response 200: { status: "healthy"|"unhealthy", timestamp, uptime, database: "connected"|"disconnected" }
  • Файл: src/api/routes/health.ts

GET /health → redirect на /healthz

GET /metrics

  • Auth: нет
  • Response 200: Prometheus-формат (counters, gauges, histograms)
  • Файл: src/api/routes/metrics.ts

Audit & Logging

GET /v1/audit/logs

  • Auth: admin
  • Файл: src/api/routes/audit.ts
  • Query: tenant_id?, user_id?, action?, resource_type?, page?, limit?
  • Response 200: { logs: [{ action, resource_type, resource_id, changes, ip_address, timestamp }], total }

POST /v1/frontend-logs

  • Auth: нет (public)
  • Файл: src/api/routes/logs.ts
  • Body: { tenant_id, channel_id, level: "error"|"warn"|"info", message, stack?, context? }

Стандартные ответы об ошибках

КодФормат
400{ status: "error", message, errors?: ZodError[] }
401{ error: "Unauthorized", message }
403{ error: "Forbidden", message }
404{ error: "Not Found", message }
429{ error: "Too Many Requests", retryAfter? }
500{ status: "error", error: "Internal Server Error", message }

Структура файлов роутов

src/api/routes/
├── auth.ts                    # Регистрация, логин, токены
├── users.ts                   # Профиль, аватар
├── agents.ts                  # Agent CRUD
├── agent-prompt.ts            # Секции промптов
├── members.ts                 # Команда
├── calls.ts                   # Звонки
├── campaigns.ts               # Массовый обзвон
├── scheduled-calls.ts         # Запланированные звонки
├── dnc.ts                     # Do Not Call
├── channels.ts                # Каналы связи
├── numbers.ts                 # Покупка номеров
├── phone-numbers.ts           # Управление номерами
├── kb.ts                      # Загрузка документов
├── kb-web.ts                  # Web-документы
├── kb-text.ts                 # Текстовые документы
├── kb-delete.ts               # Удаление KB
├── messages.ts                # Переписка
├── messages-send.ts           # Отправка сообщений
├── webchat.ts                 # Public webchat API
├── setup-agent.ts             # Интерактивная настройка
├── tenants.ts                 # Аккаунт
├── billing.ts                 # Тарифы (public)
├── subscriptions.ts           # Подписки
├── stripe-checkout.ts         # Stripe Checkout
├── usage.ts                   # Метрики использования
├── payments.ts                # Платежи
├── payment-methods.ts         # Способы оплаты
├── invoices.ts                # Счета
├── audit.ts                   # Аудит
├── health.ts                  # Health checks
├── metrics.ts                 # Prometheus метрики
├── voice-widget.ts            # Виджет
├── faq.ts                     # FAQ
├── meta-oauth.ts              # Meta OAuth
├── meta-webhook.ts            # Meta webhook
├── meta-message.ts            # Meta сообщения
├── meta-connect.routes.ts     # Meta статус
├── logs.ts                    # Frontend логирование
├── webhooks/
│   ├── twilio.ts              # Twilio звонки/статусы
│   ├── stripe.ts              # Stripe биллинг
│   ├── elevenlabs.ts          # ElevenLabs агент
│   ├── elevenlabs-tools.ts    # ElevenLabs tools
│   ├── n8n-kb.ts              # n8n KB processing
│   └── pdf-parser.ts          # PDF парсер
└── admin/
    ├── organizations.ts       # Организации
    ├── organization-api-keys.ts
    ├── config.ts              # Системные настройки
    ├── system-config.ts
    ├── testing.ts             # Тестирование
    ├── email-templates.ts     # Email шаблоны
    ├── kb-revectorize.ts      # Ре-векторизация
    └── elevenlabs-phone.ts    # ElevenLabs номера

Prisma модели (основные)

МодельИспользуется в
UserAuth, Users, Members
TenantTenants, Auth, Billing
OrganizationAdmin
AgentAgents, Channels, Calls
ChannelChannels, Messages, Webhooks
CallCalls, Campaigns
PhoneNumberNumbers, Channels
MessageMessages, Conversations, Webchat
KnowledgeBaseKB CRUD
SubscriptionBilling, Usage, Quotas
InvoiceInvoices, Payments
PaymentMethodPayment methods
CampaignCampaigns
ScheduledCallScheduled calls
DncEntryDNC
MetaAccessTokenMeta integration
AuditLogAudit

Обновлено: 2026-04-15

Twinlix platform documentation.