Skip to content

CRM Integration Guide: Voice Channel API

📋 Руководство по интеграции голосовых каналов через API

Это руководство для разработчиков CRM-систем, которые хотят интегрировать создание и управление голосовыми каналами с AI-агентами.


🔐 Аутентификация

Все запросы требуют JWT токен в заголовке:

bash
Authorization: Bearer YOUR_JWT_TOKEN

Получение токена

http
POST /v1/auth/login
Content-Type: application/json

{
  "email": "user@example.com",
  "password": "your_password"
}

Response:

json
{
  "status": "success",
  "data": {
    "access_token": "eyJhbGciOiJSUzI1NiJ9...",
    "refresh_token": "eyJhbGciOiJSUzI1NiJ9...",
    "user": {
      "id": "user-uuid",
      "email": "user@example.com",
      "tenant_id": "tenant-uuid"
    }
  }
}

🎯 Шаг 1: Создание AI-агента

Сначала создайте AI-агента, который будет обрабатывать звонки:

http
POST /v1/agents
Authorization: Bearer YOUR_JWT_TOKEN
Content-Type: application/json

{
  "name": "Customer Support Agent",
  "language": "ru",
  "prompt": "Вы - профессиональный помощник службы поддержки. Отвечайте вежливо и помогайте клиентам решать их вопросы.",
  "voice_id": "21m00Tcm4TlvDq8ikWAM",
  "workspace_id": "workspace-uuid"
}

Response:

json
{
  "status": "success",
  "data": {
    "id": "agent-uuid",
    "name": "Customer Support Agent",
    "language": "ru",
    "provider_agent_id": "agent_xxxxxxxxxxxxxxxxxx",
    "status": "active"
  }
}

💡 Важно: Сохраните id агента - он понадобится для создания канала.


🎯 Шаг 2: Создание голосового канала (webvoice)

Базовый запрос

http
POST /v1/channels
Authorization: Bearer YOUR_JWT_TOKEN
Content-Type: application/json

{
  "type": "webvoice",
  "name": "Website Voice Widget",
  "agent_id": "agent-uuid",
  "workspace_id": "workspace-uuid",
  "allowed_origins": ["https://yourwebsite.com", "https://www.yourwebsite.com"]
}

Запрос с полной кастомизацией виджета

http
POST /v1/channels
Authorization: Bearer YOUR_JWT_TOKEN
Content-Type: application/json

{
  "type": "webvoice",
  "name": "Website Voice Widget",
  "agent_id": "agent-uuid",
  "workspace_id": "workspace-uuid",
  "allowed_origins": ["https://yourwebsite.com"],
  
  "greeting_message": "Здравствуйте! Чем могу помочь?",
  
  "widget_variant": "expandable",
  "widget_placement": "bottom-right",
  "widget_btn_color": "#007bff",
  "widget_btn_text_color": "#ffffff",
  "widget_bg_color": "#f8f9fa",
  "widget_text_color": "#212529",
  "widget_avatar_type": "orb",
  "widget_avatar_color_1": "#007bff",
  "widget_avatar_color_2": "#0056b3",
  "widget_disable_banner": true,
  
  "voice_language": "ru",
  "voice_stability": 0.5,
  "voice_similarity_boost": 0.75
}

Response:

json
{
  "status": "success",
  "data": {
    "id": "channel-uuid",
    "type": "webvoice",
    "name": "Website Voice Widget",
    "agent_id": "agent-uuid",
    "status": "active",
    "resource_ref": "wss://backend-dev.dmva.acebox.eu/v1/voice/webvoice/channel-uuid",
    
    "widget_variant": "expandable",
    "widget_placement": "bottom-right",
    "widget_btn_color": "#007bff",
    "widget_btn_text_color": "#ffffff",
    "widget_bg_color": "#f8f9fa",
    "widget_text_color": "#212529",
    "widget_avatar_type": "orb",
    "widget_avatar_color_1": "#007bff",
    "widget_avatar_color_2": "#0056b3",
    "widget_disable_banner": true,
    
    "created_at": "2025-11-17T10:00:00.000Z"
  }
}

💡 Важно: Сохраните id канала для дальнейшей настройки.


🎨 Шаг 3: Настройка виджета (опционально)

Если нужно изменить настройки виджета после создания канала:

Вариант 1: Dedicated endpoint (рекомендуется)

http
PATCH /v1/channels/{channel-id}/voice-widget-settings
Authorization: Bearer YOUR_JWT_TOKEN
Content-Type: application/json

{
  "widget_variant": "full",
  "widget_placement": "bottom-right",
  "widget_btn_color": "#00d4ff",
  "widget_btn_text_color": "#000000",
  "widget_bg_color": "#ffffff",
  "widget_text_color": "#333333",
  "widget_avatar_type": "orb",
  "widget_avatar_color_1": "#00d4ff",
  "widget_avatar_color_2": "#0095ff",
  "widget_disable_banner": true
}

Response:

json
{
  "status": "success",
  "data": {
    "id": "channel-uuid",
    "widget_variant": "full",
    "widget_placement": "bottom-right",
    "widget_btn_color": "#00d4ff",
    "widget_btn_text_color": "#000000",
    "widget_bg_color": "#ffffff",
    "widget_text_color": "#333333",
    "widget_avatar_type": "orb",
    "widget_avatar_color_1": "#00d4ff",
    "widget_avatar_color_2": "#0095ff",
    "widget_disable_banner": true,
    "updated_at": "2025-11-17T11:00:00.000Z",
    "synced": true
  }
}

synced: true означает, что настройки автоматически синхронизированы с ElevenLabs.

Вариант 2: Общий endpoint канала

http
PATCH /v1/channels/{channel-id}
Authorization: Bearer YOUR_JWT_TOKEN
Content-Type: application/json

{
  "widget_btn_color": "#ff0000",
  "widget_text_color": "#ffffff"
}

📊 Получение информации о канале

Получить один канал

http
GET /v1/channels/{channel-id}
Authorization: Bearer YOUR_JWT_TOKEN

Response:

json
{
  "status": "success",
  "data": {
    "id": "channel-uuid",
    "type": "webvoice",
    "name": "Website Voice Widget",
    "agent_id": "agent-uuid",
    "status": "active",
    "resource_ref": "wss://...",
    
    "widget_variant": "expandable",
    "widget_placement": "bottom-right",
    "widget_btn_color": "#007bff",
    "widget_btn_text_color": "#ffffff",
    "widget_bg_color": "#f8f9fa",
    "widget_text_color": "#212529",
    "widget_avatar_type": "orb",
    "widget_avatar_color_1": "#007bff",
    "widget_avatar_color_2": "#0056b3",
    "widget_disable_banner": true,
    
    "created_at": "2025-11-17T10:00:00.000Z",
    "updated_at": "2025-11-17T11:00:00.000Z"
  }
}

Получить только настройки виджета

http
GET /v1/channels/{channel-id}/voice-widget-settings
Authorization: Bearer YOUR_JWT_TOKEN

Response:

json
{
  "status": "success",
  "data": {
    "id": "channel-uuid",
    "widget_variant": "expandable",
    "widget_placement": "bottom-right",
    "widget_btn_color": "#007bff",
    "widget_btn_text_color": "#ffffff",
    "widget_bg_color": "#f8f9fa",
    "widget_text_color": "#212529",
    "widget_avatar_type": "orb",
    "widget_avatar_color_1": "#007bff",
    "widget_avatar_color_2": "#0056b3",
    "widget_avatar_url": null,
    "widget_disable_banner": true
  }
}

Получить все каналы

http
GET /v1/channels?type=webvoice&workspace_id={workspace-uuid}
Authorization: Bearer YOUR_JWT_TOKEN

🚀 Шаг 4: Получить код для встраивания виджета

После создания webvoice канала, получите готовый код для встраивания на ваш сайт:

http
GET /v1/voice-widget/{channel-id}/direct

Базовый запрос

bash
curl "https://backend-dev.dmva.acebox.eu/v1/voice-widget/30f45496-35a9-402c-9ca6-525fd8455d8c/direct"

С кастомизацией через параметры

bash
curl "https://backend-dev.dmva.acebox.eu/v1/voice-widget/{channel-id}/direct?theme=dark&language=ru&size=large"

Доступные параметры:

  • theme - light | dark | custom
  • position - bottom-right | bottom-left | top-right | top-left
  • size - small | medium | large
  • language - en | ru | pl | de | fr и т.д.
  • color - Hex код цвета (например, %23007bff)
  • hidebranding - true | false

Response

json
{
  "status": "success",
  "data": {
    "agent_id": "agent_2701ka2qwdvsfsx8k1a7zk6rwhk4",
    "channel_id": "30f45496-35a9-402c-9ca6-525fd8455d8c",
    "channel_name": "Website Voice Widget",
    
    "html_snippet": "<elevenlabs-convai agent-id=\"agent_xxx\" background-color=\"#007bff\"></elevenlabs-convai>",
    "script_tag": "<script src=\"https://unpkg.com/@elevenlabs/convai-widget-embed\" async></script>",
    "full_code": "<!-- Полный HTML код для вставки -->",
    
    "configuration": {
      "theme": "light",
      "position": "bottom-right",
      "size": "medium",
      "language": "en",
      "color": "#007bff",
      "hide_branding": true
    },
    
    "usage_examples": {
      "html": "<!-- HTML пример -->",
      "react": "// React компонент",
      "vue": "// Vue компонент"
    }
  }
}

Встраивание на сайт

Шаг 1: Скопируйте full_code из ответа API

Шаг 2: Вставьте код перед закрывающим тегом </body> на вашей странице:

html
<!DOCTYPE html>
<html>
<head>
    <title>Мой сайт</title>
</head>
<body>
    <!-- Ваш контент -->
    <h1>Добро пожаловать!</h1>
    
    <!-- Voice Widget - вставьте здесь -->
    <elevenlabs-convai 
        agent-id="agent_2701ka2qwdvsfsx8k1a7zk6rwhk4"
        background-color="#007bff"
        widget-position="bottom-right">
    </elevenlabs-convai>
    
    <script src="https://unpkg.com/@elevenlabs/convai-widget-embed" async></script>
</body>
</html>

Готово! Виджет появится на вашей странице и будет готов к использованию.

Интеграция с React

jsx
import React, { useEffect } from 'react';

function VoiceWidget({ channelId }) {
  useEffect(() => {
    // Получаем код виджета
    fetch(`https://backend-dev.dmva.acebox.eu/v1/voice-widget/${channelId}/direct`)
      .then(res => res.json())
      .then(data => {
        // Вставляем виджет на страницу
        const widget = document.createElement('div');
        widget.innerHTML = data.data.html_snippet;
        document.body.appendChild(widget);
        
        // Загружаем скрипт ElevenLabs
        const script = document.createElement('script');
        script.src = 'https://unpkg.com/@elevenlabs/convai-widget-embed';
        script.async = true;
        document.body.appendChild(script);
      });
  }, [channelId]);

  return null;
}

export default VoiceWidget;

Интеграция с Vue.js

vue
<template>
  <div></div>
</template>

<script>
export default {
  props: ['channelId'],
  async mounted() {
    const response = await fetch(
      `https://backend-dev.dmva.acebox.eu/v1/voice-widget/${this.channelId}/direct`
    );
    const data = await response.json();
    
    // Вставляем виджет
    const widget = document.createElement('div');
    widget.innerHTML = data.data.html_snippet;
    document.body.appendChild(widget);
    
    // Загружаем скрипт
    const script = document.createElement('script');
    script.src = 'https://unpkg.com/@elevenlabs/convai-widget-embed';
    script.async = true;
    document.body.appendChild(script);
  }
}
</script>

💡 Важно: Виджет интегрируется напрямую в DOM вашей страницы (БЕЗ iframe), что обеспечивает:

  • ✅ Идеальное изменение размера при раскрытии/сворачивании
  • ✅ Отличный UX на мобильных устройствах
  • ✅ Плавные анимации
  • ✅ Отсутствие проблем с CORS
  • ✅ Быструю загрузку

🎨 Параметры кастомизации виджета

Widget Variant (внешний вид)

ЗначениеОписание
tinyМинимальный размер, только иконка
compactКомпактный вид с кнопкой
fullПолноразмерный виджет
expandableРаскрывающийся виджет (рекомендуется)

Widget Placement (позиция на странице)

ЗначениеОписание
top-leftВерхний левый угол
topВерх по центру
top-rightВерхний правый угол
bottom-leftНижний левый угол
bottomНиз по центру
bottom-rightНижний правый угол (рекомендуется)

Widget Colors (цвета в формате #RRGGBB)

ПараметрОписание
widget_btn_colorЦвет кнопки виджета
widget_btn_text_colorЦвет текста на кнопке
widget_bg_colorЦвет фона виджета
widget_text_colorЦвет текста в виджете

Widget Avatar (аватар ассистента)

widget_avatar_type:

  • orb - Анимированная сфера (использует color_1 и color_2)
  • url - Изображение по URL
  • image - Загруженное изображение

Для type="orb":

json
{
  "widget_avatar_type": "orb",
  "widget_avatar_color_1": "#007bff",
  "widget_avatar_color_2": "#0056b3"
}

Для type="url":

json
{
  "widget_avatar_type": "url",
  "widget_avatar_url": "https://yourcdn.com/avatar.png"
}

Widget Branding

ПараметрОписание
widget_disable_bannertrue - скрыть "Powered by ElevenLabs"

📞 Настройки голоса

Параметры голоса агента

json
{
  "voice_language": "ru",
  "voice_id": "21m00Tcm4TlvDq8ikWAM",
  "voice_speed": 1.0,
  "voice_stability": 0.5,
  "voice_similarity_boost": 0.75,
  "voice_style": 0.0,
  "voice_optimize_latency": 3,
  "voice_turn_timeout": 1500,
  "voice_turn_eagerness": 1.0
}
ПараметрТипДиапазонОписание
voice_languagestring-Код языка (ru, en, es, etc.)
voice_idstring-ID голоса из ElevenLabs
voice_speedfloat0.5-2.0Скорость речи
voice_stabilityfloat0.0-1.0Стабильность голоса
voice_similarity_boostfloat0.0-1.0Похожесть на оригинал
voice_stylefloat0.0-1.0Экспрессивность
voice_optimize_latencyint0-4Оптимизация задержки
voice_turn_timeoutintмсТаймаут ожидания ответа
voice_turn_eagernessfloat0.0-1.0Готовность прервать пользователя

🔄 Полный пример: Создание и настройка канала

javascript
// 1. Получить токен
const loginResponse = await fetch('https://api.example.com/v1/auth/login', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    email: 'user@example.com',
    password: 'password'
  })
});
const { data: { access_token } } = await loginResponse.json();

// 2. Создать агента
const agentResponse = await fetch('https://api.example.com/v1/agents', {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${access_token}`,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    name: 'Support Agent',
    language: 'ru',
    prompt: 'Вы - помощник службы поддержки',
    voice_id: '21m00Tcm4TlvDq8ikWAM',
    workspace_id: 'workspace-uuid'
  })
});
const { data: agent } = await agentResponse.json();

// 3. Создать webvoice канал с кастомным виджетом
const channelResponse = await fetch('https://api.example.com/v1/channels', {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${access_token}`,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    type: 'webvoice',
    name: 'Website Voice Widget',
    agent_id: agent.id,
    workspace_id: 'workspace-uuid',
    allowed_origins: ['https://yourwebsite.com'],
    
    // Кастомизация виджета
    widget_variant: 'expandable',
    widget_placement: 'bottom-right',
    widget_btn_color: '#007bff',
    widget_btn_text_color: '#ffffff',
    widget_bg_color: '#f8f9fa',
    widget_text_color: '#212529',
    widget_avatar_type: 'orb',
    widget_avatar_color_1: '#007bff',
    widget_avatar_color_2: '#0056b3',
    widget_disable_banner: true,
    
    // Настройки голоса
    voice_language: 'ru',
    voice_stability: 0.5,
    voice_similarity_boost: 0.75
  })
});
const { data: channel } = await channelResponse.json();

// 4. Опционально: Обновить настройки виджета позже
const updateResponse = await fetch(
  `https://api.example.com/v1/channels/${channel.id}/voice-widget-settings`,
  {
    method: 'PATCH',
    headers: {
      'Authorization': `Bearer ${access_token}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      widget_btn_color: '#ff0000',
      widget_btn_text_color: '#ffffff'
    })
  }
);
const { data: updatedWidget } = await updateResponse.json();

console.log('Widget updated, synced:', updatedWidget.synced); // true

🔌 Интеграция виджета на сайт

После создания канала, добавьте виджет на сайт клиента:

html
<!DOCTYPE html>
<html>
<head>
  <title>Website with Voice Widget</title>
</head>
<body>
  <!-- Ваш контент -->
  
  <!-- ElevenLabs Voice Widget -->
  <elevenlabs-convai agent-id="agent_xxxxxxxxxxxxxxxxxx"></elevenlabs-convai>
  <script src="https://elevenlabs.io/convai-widget/index.js" async type="text/javascript"></script>
</body>
</html>

💡 Используйте provider_agent_id из ответа создания агента вместо agent_xxxxxxxxxxxxxxxxxx.


🛠️ Управление каналами

Обновить канал

http
PATCH /v1/channels/{channel-id}
Authorization: Bearer YOUR_JWT_TOKEN
Content-Type: application/json

{
  "name": "Updated Channel Name",
  "status": "active",
  "greeting_message": "Новое приветствие"
}

Удалить канал

http
DELETE /v1/channels/{channel-id}
Authorization: Bearer YOUR_JWT_TOKEN

Отключить/включить канал

http
PATCH /v1/channels/{channel-id}
Authorization: Bearer YOUR_JWT_TOKEN
Content-Type: application/json

{
  "status": "disabled"  // или "active"
}

📋 Список доступных голосов

Получить список голосов

http
GET /v1/voices
Authorization: Bearer YOUR_JWT_TOKEN

Response:

json
{
  "status": "success",
  "data": [
    {
      "voice_id": "21m00Tcm4TlvDq8ikWAM",
      "name": "Rachel",
      "language": "en",
      "gender": "female"
    },
    {
      "voice_id": "AZnzlk1XvdvUeBnXmlld",
      "name": "Domi",
      "language": "en",
      "gender": "female"
    }
  ]
}

❌ Обработка ошибок

Стандартный формат ошибок

json
{
  "status": "error",
  "message": "Описание ошибки",
  "code": "ERROR_CODE"
}

Типичные ошибки

HTTP CodeОписаниеРешение
401UnauthorizedПроверьте токен авторизации
403ForbiddenНедостаточно прав
404Not FoundКанал/агент не найден
400Bad RequestПроверьте формат данных
422Validation ErrorПроверьте обязательные поля
500Server ErrorОбратитесь в поддержку

Пример обработки ошибок

javascript
try {
  const response = await fetch('https://api.example.com/v1/channels', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${token}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify(channelData)
  });
  
  const result = await response.json();
  
  if (result.status === 'error') {
    console.error('API Error:', result.message);
    // Обработка ошибки
  } else {
    console.log('Channel created:', result.data);
  }
} catch (error) {
  console.error('Network error:', error);
}

📞 Поддержка

При возникновении вопросов или проблем:

  1. Проверьте формат данных в запросе
  2. Убедитесь, что токен авторизации актуален
  3. Проверьте права доступа пользователя
  4. Обратитесь в техническую поддержку: support@example.com

🔗 Полезные ссылки


📝 Changelog

2025-11-17:

  • ✅ Добавлены dedicated endpoints для настройки виджета
  • ✅ Автоматическая синхронизация с ElevenLabs
  • ✅ Исправлены названия полей (widget_btn_color, widget_btn_text_color)
  • ✅ Поддержка кастомизации виджета при создании канала

Twinlix platform documentation.