Довідник API

Усі ендпоінти API v1. Приклади на curl, JavaScript (fetch) і Python (requests); обрана мова запам’ятовується для всієї сторінки.

Базова URL-адресаhttps://hubvocal.com/v1
АвтентифікаціяAuthorization: Bearer vt_live_…
Ліміт запитів120 запитів/хв на ключ · 429 + Retry-After
Області доступуread · write · calls
Кожен ключ має read, write та/або calls. read охоплює GET-запити, write — зміни, calls — вихідні дзвінки. Запит поза областями доступу ключа отримує 403.
Тіло помилки{"detail": "..."}
OpenAPIGET /v1/openapi.json

Про автентифікацію, вбудовування й коди помилок читайте в розділі Розробникам.

Агенти

Розмови відбуваються в текстовому режимі, тож перевіряються інструкції та використання інструментів, а не голос чи затримка. Симуляції запускаються з панелі керування; ендпоінта /v1 для них поки немає.

Список агентів

GET /v1/agents

Повертає всіх агентів вашої організації в тому порядку, в якому вони показані в панелі керування.

Запит

curl
curl "https://hubvocal.com/v1/agents" \
  -H "Authorization: Bearer $VT_API_KEY"

Відповідь · 200

JSON
[
  {
    "id": "front-desk",
    "name": "Front desk",
    "lang": "en",
    "engine": "live",
    "instructions": "You are the front desk assistant for a dental clinic. Help callers book appointments and answer general questions briefly. Never make things up; offer a callback from the team instead.",
    "greeting": "Hello, thanks for calling the clinic. How can I help you today?",
    "voice": {
      "voice": "marin",
      "speed": 1
    },
    "tools": {
      "builtins": [
        "end_call",
        "take_message"
      ],
      "webhooks": [
        "tl_8f3a2c"
      ]
    },
    "turn": {
      "first_speaker": "agent",
      "idle_check_s": 30
    },
    "recording": {
      "enabled": false,
      "announce": true
    },
    "post_call": {
      "summary": true,
      "fields": [
        {
          "name": "appointment_date",
          "type": "date",
          "description": "Requested appointment date, if any"
        },
        {
          "name": "callback",
          "type": "boolean",
          "description": "Does the caller want a callback?"
        }
      ]
    },
    "knowledge": {
      "doc_ids": [
        "kb_7d21e4"
      ],
      "mode": "tool"
    },
    "published_version": 3,
    "draft_changed": false
  }
]

Створення агента

POST /v1/agents

Створює агента. Кожне поле перевіряється на сервері; значення понад ліміти обрізаються. Якщо передати id, який уже існує, запит завершиться помилкою 409. Для оновлення використовуйте PUT.

НазваДеТипОпис
id тіло string Необов’язково. Малі латинські літери, цифри й дефіси, до 48 символів. Якщо не вказано, генерується з назви.
name
обов’язковий
тіло string Назва для відображення, до 60 символів.
lang
обов’язковий
тіло string Код мови розмови, наприклад tr, en, de. Повний список — у GET /v1/voices.
engine
обов’язковий
тіло "live" | "gemini" | "realtime" | "classic" live: GPT-Live 1, gemini: Gemini Live, realtime: OpenAI Realtime, classic: STT → LLM → TTS.
instructions тіло string Системні інструкції, до 8000 символів.
greeting тіло string Що агент каже першим, до 400 символів.
voice тіло object voice (назва з /v1/voices), speed (лише classic і realtime; для live і gemini фіксовано 1.0), tone (манера мовлення довільним текстом, до 600 символів).
tools тіло object builtins (end_call, take_message) і webhooks (id інструментів); загалом до 16 інструментів. Порожнє або відсутнє поле означає, що інструментів немає. mcp: [{server_id, tools}] додає інструменти з ваших MCP-серверів; вони входять у той самий ліміт.
turn тіло object Черговість реплік: sensitivity (low, balanced, high; лише рушій classic), first_speaker (agent або caller), silence_wait_s (1–5), idle_check_s (0 або 10–120), agent_timeout_s (0 або 10–60). Для порожніх полів діють значення за замовчуванням.
recording тіло object recording: {enabled (за замовчуванням false), announce (за замовчуванням true), announce_text?}. Якщо запис увімкнено, агент повідомляє про нього перед привітанням.
post_call тіло object post_call.summary: складати підсумок після завершення дзвінка (за замовчуванням true). post_call.fields: до 24 полів, які заповнюються після дзвінка ({name, type, description, enum?, required?}).
knowledge тіло object doc_ids (до 50 документів бази знань) і mode ("tool"). Тоді агент отримує інструмент search_knowledge.
calendar тіло object integration_id і calendar_id з панелі керування, duration_min (15–240), buffer_min (0–60), timezone, working_hours, min_notice_h (0–72), max_days_ahead (1–90). Вмикає інструменти запису на прийом.

Запит

curl
curl -X POST "https://hubvocal.com/v1/agents" \
  -H "Authorization: Bearer $VT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "Front desk",
  "lang": "en",
  "engine": "live",
  "instructions": "You are the front desk assistant for a dental clinic. Help callers book appointments and answer general questions briefly. Never make things up; offer a callback from the team instead.",
  "greeting": "Hello, thanks for calling the clinic. How can I help you today?",
  "voice": {
    "voice": "marin",
    "speed": 1
  },
  "tools": {
    "builtins": [
      "end_call",
      "take_message"
    ],
    "webhooks": [
      "tl_8f3a2c"
    ]
  },
  "turn": {
    "first_speaker": "agent",
    "idle_check_s": 30
  },
  "recording": {
    "enabled": false,
    "announce": true
  },
  "post_call": {
    "summary": true,
    "fields": [
      {
        "name": "appointment_date",
        "type": "date",
        "description": "Requested appointment date, if any"
      },
      {
        "name": "callback",
        "type": "boolean",
        "description": "Does the caller want a callback?"
      }
    ]
  },
  "knowledge": {
    "doc_ids": [
      "kb_7d21e4"
    ],
    "mode": "tool"
  }
}'

Відповідь · 201

JSON
{
  "id": "front-desk",
  "name": "Front desk",
  "lang": "en",
  "engine": "live",
  "instructions": "You are the front desk assistant for a dental clinic. Help callers book appointments and answer general questions briefly. Never make things up; offer a callback from the team instead.",
  "greeting": "Hello, thanks for calling the clinic. How can I help you today?",
  "voice": {
    "voice": "marin",
    "speed": 1
  },
  "tools": {
    "builtins": [
      "end_call",
      "take_message"
    ],
    "webhooks": [
      "tl_8f3a2c"
    ]
  },
  "turn": {
    "first_speaker": "agent",
    "idle_check_s": 30
  },
  "recording": {
    "enabled": false,
    "announce": true
  },
  "post_call": {
    "summary": true,
    "fields": [
      {
        "name": "appointment_date",
        "type": "date",
        "description": "Requested appointment date, if any"
      },
      {
        "name": "callback",
        "type": "boolean",
        "description": "Does the caller want a callback?"
      }
    ]
  },
  "knowledge": {
    "doc_ids": [
      "kb_7d21e4"
    ],
    "mode": "tool"
  },
  "published_version": null,
  "draft_changed": true
}

Помилки

  • 409 Агент із таким id уже існує.

Отримання агента

GET /v1/agents/{id}

Повертає одного агента. published_version — номер опублікованої версії (null, якщо агента жодного разу не публікували), а draft_changed показує, чи відрізняється від неї чернетка.

НазваДеТипОпис
id
обов’язковий
шлях string Id агента, наприклад front-desk.

Запит

curl
curl "https://hubvocal.com/v1/agents/front-desk" \
  -H "Authorization: Bearer $VT_API_KEY"

Відповідь · 200

JSON
{
  "id": "front-desk",
  "name": "Front desk",
  "lang": "en",
  "engine": "live",
  "instructions": "You are the front desk assistant for a dental clinic. Help callers book appointments and answer general questions briefly. Never make things up; offer a callback from the team instead.",
  "greeting": "Hello, thanks for calling the clinic. How can I help you today?",
  "voice": {
    "voice": "marin",
    "speed": 1
  },
  "tools": {
    "builtins": [
      "end_call",
      "take_message"
    ],
    "webhooks": [
      "tl_8f3a2c"
    ]
  },
  "turn": {
    "first_speaker": "agent",
    "idle_check_s": 30
  },
  "recording": {
    "enabled": false,
    "announce": true
  },
  "post_call": {
    "summary": true,
    "fields": [
      {
        "name": "appointment_date",
        "type": "date",
        "description": "Requested appointment date, if any"
      },
      {
        "name": "callback",
        "type": "boolean",
        "description": "Does the caller want a callback?"
      }
    ]
  },
  "knowledge": {
    "doc_ids": [
      "kb_7d21e4"
    ],
    "mode": "tool"
  },
  "published_version": 3,
  "draft_changed": false
}

Помилки

  • 404 Агента з таким id немає.

Оновлення агента

PUT /v1/agents/{id}

Замінює агента надісланим об’єктом. Надсилайте об’єкт повністю: пропущені поля повертаються до значень за замовчуванням. id у шляху має пріоритет над id у тілі.

НазваДеТипОпис
id
обов’язковий
шлях string Id агента, наприклад front-desk.
name
обов’язковий
тіло string Назва для відображення, до 60 символів.
lang
обов’язковий
тіло string Код мови розмови, наприклад tr, en, de. Повний список — у GET /v1/voices.
engine
обов’язковий
тіло "live" | "gemini" | "realtime" | "classic" live: GPT-Live 1, gemini: Gemini Live, realtime: OpenAI Realtime, classic: STT → LLM → TTS.
instructions тіло string Системні інструкції, до 8000 символів.
greeting тіло string Що агент каже першим, до 400 символів.
voice тіло object voice (назва з /v1/voices), speed (лише classic і realtime; для live і gemini фіксовано 1.0), tone (манера мовлення довільним текстом, до 600 символів).
tools тіло object builtins (end_call, take_message) і webhooks (id інструментів); загалом до 16 інструментів. Порожнє або відсутнє поле означає, що інструментів немає. mcp: [{server_id, tools}] додає інструменти з ваших MCP-серверів; вони входять у той самий ліміт.
turn тіло object Черговість реплік: sensitivity (low, balanced, high; лише рушій classic), first_speaker (agent або caller), silence_wait_s (1–5), idle_check_s (0 або 10–120), agent_timeout_s (0 або 10–60). Для порожніх полів діють значення за замовчуванням.
recording тіло object recording: {enabled (за замовчуванням false), announce (за замовчуванням true), announce_text?}. Якщо запис увімкнено, агент повідомляє про нього перед привітанням.
post_call тіло object post_call.summary: складати підсумок після завершення дзвінка (за замовчуванням true). post_call.fields: до 24 полів, які заповнюються після дзвінка ({name, type, description, enum?, required?}).
knowledge тіло object doc_ids (до 50 документів бази знань) і mode ("tool"). Тоді агент отримує інструмент search_knowledge.
calendar тіло object integration_id і calendar_id з панелі керування, duration_min (15–240), buffer_min (0–60), timezone, working_hours, min_notice_h (0–72), max_days_ahead (1–90). Вмикає інструменти запису на прийом.

Запит

curl
curl -X PUT "https://hubvocal.com/v1/agents/front-desk" \
  -H "Authorization: Bearer $VT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "Front desk",
  "lang": "en",
  "engine": "live",
  "instructions": "You are the front desk assistant for a dental clinic. Help callers book appointments and answer general questions briefly. Never make things up; offer a callback from the team instead.",
  "greeting": "Hello, thanks for calling the clinic. How can I help you today?",
  "voice": {
    "voice": "cedar",
    "speed": 1
  },
  "tools": {
    "builtins": [
      "end_call",
      "take_message"
    ],
    "webhooks": [
      "tl_8f3a2c"
    ]
  },
  "turn": {
    "first_speaker": "agent",
    "idle_check_s": 30
  },
  "recording": {
    "enabled": false,
    "announce": true
  },
  "post_call": {
    "summary": true,
    "fields": [
      {
        "name": "appointment_date",
        "type": "date",
        "description": "Requested appointment date, if any"
      },
      {
        "name": "callback",
        "type": "boolean",
        "description": "Does the caller want a callback?"
      }
    ]
  },
  "knowledge": {
    "doc_ids": [
      "kb_7d21e4"
    ],
    "mode": "tool"
  }
}'

Відповідь · 200

JSON
{
  "id": "front-desk",
  "name": "Front desk",
  "lang": "en",
  "engine": "live",
  "instructions": "You are the front desk assistant for a dental clinic. Help callers book appointments and answer general questions briefly. Never make things up; offer a callback from the team instead.",
  "greeting": "Hello, thanks for calling the clinic. How can I help you today?",
  "voice": {
    "voice": "cedar",
    "speed": 1
  },
  "tools": {
    "builtins": [
      "end_call",
      "take_message"
    ],
    "webhooks": [
      "tl_8f3a2c"
    ]
  },
  "turn": {
    "first_speaker": "agent",
    "idle_check_s": 30
  },
  "recording": {
    "enabled": false,
    "announce": true
  },
  "post_call": {
    "summary": true,
    "fields": [
      {
        "name": "appointment_date",
        "type": "date",
        "description": "Requested appointment date, if any"
      },
      {
        "name": "callback",
        "type": "boolean",
        "description": "Does the caller want a callback?"
      }
    ]
  },
  "knowledge": {
    "doc_ids": [
      "kb_7d21e4"
    ],
    "mode": "tool"
  },
  "published_version": 3,
  "draft_changed": true
}

Помилки

  • 404 Агента з таким id немає. Спершу створіть його через POST.

Видалення агента

DELETE /v1/agents/{id}

Видаляє агента. В організації завжди лишається щонайменше один агент, тому видалити останнього не вийде.

НазваДеТипОпис
id
обов’язковий
шлях string Id агента, наприклад front-desk.

Запит

curl
curl -X DELETE "https://hubvocal.com/v1/agents/front-desk" \
  -H "Authorization: Bearer $VT_API_KEY"

Відповідь · 200

JSON
{
  "deleted": "front-desk"
}

Помилки

  • 400 Це останній агент в організації.
  • 404 Агента з таким id немає.

Список версій

GET /v1/agents/{id}/versions

Опубліковані версії агента, від найновішої до найстарішої. is_live позначає ту, яку зараз використовують дзвінки.

НазваДеТипОпис
id
обов’язковий
шлях string Id агента, наприклад front-desk.

Запит

curl
curl "https://hubvocal.com/v1/agents/front-desk/versions" \
  -H "Authorization: Bearer $VT_API_KEY"

Відповідь · 200

JSON
[
  {
    "version": 3,
    "note": "Shorter greeting",
    "published_at": 1793829000,
    "published_by": "ayse@example.com",
    "is_live": true
  },
  {
    "version": 2,
    "note": "Added price list",
    "published_at": 1793740000,
    "published_by": "ayse@example.com",
    "is_live": false
  }
]

Помилки

  • 404 Агента з таким id немає.

Отримання версії

GET /v1/agents/{id}/versions/{n}

Повний об’єкт агента в тому вигляді, який він мав у цій версії.

НазваДеТипОпис
id
обов’язковий
шлях string Id агента, наприклад front-desk.
n
обов’язковий
шлях integer Номер версії.

Запит

curl
curl "https://hubvocal.com/v1/agents/front-desk/versions/2" \
  -H "Authorization: Bearer $VT_API_KEY"

Відповідь · 200

JSON
{
  "id": "front-desk",
  "name": "Front desk",
  "lang": "en",
  "engine": "live",
  "instructions": "You are the front desk assistant for a dental clinic. Help callers book appointments and answer general questions briefly. Never make things up; offer a callback from the team instead.",
  "greeting": "Hello, thanks for calling the clinic. How can I help you today?",
  "voice": {
    "voice": "marin",
    "speed": 1
  },
  "tools": {
    "builtins": [
      "end_call",
      "take_message"
    ],
    "webhooks": [
      "tl_8f3a2c"
    ]
  },
  "turn": {
    "first_speaker": "agent",
    "idle_check_s": 30
  },
  "recording": {
    "enabled": false,
    "announce": true
  },
  "post_call": {
    "summary": true,
    "fields": [
      {
        "name": "appointment_date",
        "type": "date",
        "description": "Requested appointment date, if any"
      },
      {
        "name": "callback",
        "type": "boolean",
        "description": "Does the caller want a callback?"
      }
    ]
  },
  "knowledge": {
    "doc_ids": [
      "kb_7d21e4"
    ],
    "mode": "tool"
  },
  "version": 2
}

Помилки

  • 404 Такого агента або такої версії немає.

Публікація чернетки

POST /v1/agents/{id}/publish

Зберігає поточну чернетку як нову версію, і дзвінки починають використовувати її. Дзвінки, що вже тривають, залишаються на своїй версії.

НазваДеТипОпис
id
обов’язковий
шлях string Id агента, наприклад front-desk.
note тіло string Коротка примітка про те, що змінилося.

Запит

curl
curl -X POST "https://hubvocal.com/v1/agents/front-desk/publish" \
  -H "Authorization: Bearer $VT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "note": "Shorter greeting"
}'

Відповідь · 200

JSON
{
  "version": 4
}

Помилки

  • 404 Агента з таким id немає.

Відкат версії

POST /v1/agents/{id}/rollback

Копіює одну з попередніх версій у чернетку й публікує її як нову версію.

НазваДеТипОпис
id
обов’язковий
шлях string Id агента, наприклад front-desk.
version
обов’язковий
тіло integer Версія, яку потрібно повернути.

Запит

curl
curl -X POST "https://hubvocal.com/v1/agents/front-desk/rollback" \
  -H "Authorization: Bearer $VT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "version": 2
}'

Відповідь · 200

JSON
{
  "version": 5
}

Помилки

  • 404 Такого агента або такої версії немає.

База знань

Список документів

GET /v1/knowledge

Документи вашої організації зі статусом обробки, розміром, кількістю фрагментів і агентами, які їх використовують.

Запит

curl
curl "https://hubvocal.com/v1/knowledge" \
  -H "Authorization: Bearer $VT_API_KEY"

Відповідь · 200

JSON
[
  {
    "id": "kb_7d21e4",
    "title": "Price list 2026",
    "kind": "file",
    "filename": "price-list-2026.pdf",
    "url": null,
    "size_bytes": 248113,
    "chunks": 42,
    "status": "ready",
    "error": null,
    "created_at": 1793740000,
    "used_by": [
      "front-desk"
    ]
  }
]

Додавання документа

POST /v1/knowledge

Завантажте файл як multipart/form-data (поле file), надішліть текст як JSON {title, text} або одну вебсторінку як JSON {url}. Повертає 201 зі статусом processing; запитуйте документ, доки статус не стане ready або failed.

НазваДеТипОпис
file тіло file multipart/form-data: pdf, docx, txt, md або html, до 10 МБ.
title тіло string Заголовок, разом із text.
text тіло string Вміст звичайним текстом.
url тіло string Замість файлу чи тексту: одна сторінка за https, яку потрібно завантажити.

Запит

curl
curl -X POST "https://hubvocal.com/v1/knowledge" \
  -H "Authorization: Bearer $VT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "title": "Opening hours",
  "text": "We are open 09:00–18:00 on weekdays and 10:00–14:00 on Saturdays. Closed on Sundays."
}'

Відповідь · 201

JSON
{
  "id": "kb_9f03b1",
  "title": "Opening hours",
  "kind": "text",
  "filename": null,
  "url": null,
  "size_bytes": 96,
  "chunks": 0,
  "status": "processing",
  "error": null,
  "created_at": 1793740000,
  "used_by": []
}

Помилки

  • 400 Непідтримуваний тип файлу, файл понад 10 МБ, URL не https або вказує на приватну адресу, або досягнуто ліміту організації (200 документів, 200 МБ).

Отримання документа

GET /v1/knowledge/{id}

Документ із попереднім переглядом перших 2000 символів.

НазваДеТипОпис
id
обов’язковий
шлях string Id документа.

Запит

curl
curl "https://hubvocal.com/v1/knowledge/kb_7d21e4" \
  -H "Authorization: Bearer $VT_API_KEY"

Відповідь · 200

JSON
{
  "id": "kb_7d21e4",
  "title": "Price list 2026",
  "kind": "file",
  "filename": "price-list-2026.pdf",
  "url": null,
  "size_bytes": 248113,
  "chunks": 42,
  "status": "ready",
  "error": null,
  "created_at": 1793740000,
  "used_by": [
    "front-desk"
  ],
  "preview": "Price list 2026. Check-up 1,500 TRY, scale and polish 2,000 TRY…"
}

Помилки

  • 404 Документа з таким id немає.

Видалення документа

DELETE /v1/knowledge/{id}

Видаляє документ і прибирає його з усіх агентів, які його використовували.

НазваДеТипОпис
id
обов’язковий
шлях string Id документа.

Запит

curl
curl -X DELETE "https://hubvocal.com/v1/knowledge/kb_7d21e4" \
  -H "Authorization: Bearer $VT_API_KEY"

Відповідь · 200

JSON
{
  "deleted": "kb_7d21e4"
}

Помилки

  • 404 Документа з таким id немає.

Пошук

POST /v1/knowledge/search

Виконує той самий пошук, що й агент, і повертає найвідповідніші фрагменти з оцінкою. Зручно, щоб перевірити документи перед запуском.

НазваДеТипОпис
query
обов’язковий
тіло string Що шукати.
doc_ids тіло string[] Шукати лише в цих документах.

Запит

curl
curl -X POST "https://hubvocal.com/v1/knowledge/search" \
  -H "Authorization: Bearer $VT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "query": "how much is a scale and polish"
}'

Відповідь · 200

JSON
[
  {
    "doc_id": "kb_7d21e4",
    "title": "Price list 2026",
    "chunk_index": 3,
    "text": "Scale and polish: 2,000 TRY, about 30 minutes.",
    "score": 0.82
  }
]

Інструменти

Вбудовані інструменти

Ці інструменти не потрібно описувати. Увімкніть їх у tools.builtins агента. search_knowledge додається, коли задано knowledge. Інструменти запису на прийом додаються, коли задано calendar.

НазваЩо робить
end_callАгент прощається й кладе слухавку через 0,75 с після того, як замовкне. Якщо абонент тим часом заговорить, завершення скасовується. У картці дзвінка буде ended_by: "agent".
take_messageПриймає name, phone, message і callback_requested та записує їх у outcomes[] картки дзвінка. Підтвердження не запитує.
search_knowledgeДодається автоматично, коли в агента є документи в knowledge. Шукає в них і записує джерела в картку дзвінка.
check_availabilityТип read. Повертає вільні слоти між date_from і date_to у межах робочих годин агента. Додається, коли задано calendar.
book_appointmentТип write, проходить крок підтвердження. Бронює час start на ім’я name і телефон phone, за бажанням із приміткою note. Запис потрапляє в outcomes[].
cancel_appointmentТип write, проходить крок підтвердження. Скасовує запис за його booking_ref.

Інтеграції з календарями (Google Calendar) підключаються лише в панелі керування; ендпоінта /v1 для них немає. У полі calendar агента вкажіть id інтеграції та календаря з панелі керування.

Список інструментів

GET /v1/tools

Вебхук-інструменти вашої організації. Секрет ніколи не повертається; has_secret показує, чи його задано.

Запит

curl
curl "https://hubvocal.com/v1/tools" \
  -H "Authorization: Bearer $VT_API_KEY"

Відповідь · 200

JSON
[
  {
    "id": "tl_8f3a2c",
    "name": "check_order",
    "description": "Looks up the shipping status of an order by its number.",
    "kind": "read",
    "url": "https://crm.example.com/hooks/order",
    "parameters": {
      "type": "object",
      "properties": {
        "order_id": {
          "type": "string",
          "description": "Order number"
        }
      },
      "required": [
        "order_id"
      ]
    },
    "timeout_s": 8,
    "enabled": true,
    "has_secret": true,
    "created_at": 1793830000,
    "updated_at": 1793830000
  }
]

Отримання інструмента

GET /v1/tools/{id}

Один вебхук-інструмент. Секрет ніколи не повертається.

НазваДеТипОпис
id
обов’язковий
шлях string Id інструмента.

Запит

curl
curl "https://hubvocal.com/v1/tools/tl_8f3a2c" \
  -H "Authorization: Bearer $VT_API_KEY"

Відповідь · 200

JSON
{
  "id": "tl_8f3a2c",
  "name": "check_order",
  "description": "Looks up the shipping status of an order by its number.",
  "kind": "read",
  "url": "https://crm.example.com/hooks/order",
  "parameters": {
    "type": "object",
    "properties": {
      "order_id": {
        "type": "string",
        "description": "Order number"
      }
    },
    "required": [
      "order_id"
    ]
  },
  "timeout_s": 8,
  "enabled": true,
  "has_secret": true,
  "created_at": 1793830000,
  "updated_at": 1793830000
}

Помилки

  • 404 Інструмента з таким id немає.

Створення інструмента

POST /v1/tools

Створює вебхук-інструмент для організації. Щоб ним скористатися, додайте його id у tools.webhooks агента. URL має бути https і не може вказувати на локальну чи приватну адресу.

НазваДеТипОпис
name
обов’язковий
тіло string Малі латинські літери, цифри й підкреслення, першим має бути літера (3–41 символ). Унікальна в межах організації; end_call і take_message зарезервовано.
description
обов’язковий
тіло string Пояснює моделі, коли і як використовувати інструмент.
kind
обов’язковий
тіло "read" | "write" read виконується одразу; write спершу просить абонента підтвердити.
url
обов’язковий
тіло string Ваш ендпоінт. Лише https; локальні й приватні адреси відхиляються.
parameters тіло object Об’єкт JSON Schema: до 20 полів типів string, number, integer або boolean (можна enum).
timeout_s тіло integer Від 2 до 15 секунд.
enabled тіло boolean Вимкнені інструменти моделі не пропонуються.
secret тіло string Використовується для підпису запитів. Лише для запису: під час оновлення порожнє значення зберігає поточний секрет, а "-" видаляє його.

Запит

curl
curl -X POST "https://hubvocal.com/v1/tools" \
  -H "Authorization: Bearer $VT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "check_order",
  "description": "Looks up the shipping status of an order by its number.",
  "kind": "read",
  "url": "https://crm.example.com/hooks/order",
  "parameters": {
    "type": "object",
    "properties": {
      "order_id": {
        "type": "string",
        "description": "Order number"
      }
    },
    "required": [
      "order_id"
    ]
  },
  "timeout_s": 8,
  "enabled": true,
  "secret": "whsec_2b7f…"
}'

Відповідь · 201

JSON
{
  "id": "tl_8f3a2c",
  "name": "check_order",
  "description": "Looks up the shipping status of an order by its number.",
  "kind": "read",
  "url": "https://crm.example.com/hooks/order",
  "parameters": {
    "type": "object",
    "properties": {
      "order_id": {
        "type": "string",
        "description": "Order number"
      }
    },
    "required": [
      "order_id"
    ]
  },
  "timeout_s": 8,
  "enabled": true,
  "has_secret": true,
  "created_at": 1793830000,
  "updated_at": 1793830000
}

Помилки

  • 400 Поле порушує правила: формат назви, URL не https, приватна адреса, понад 20 параметрів або тайм-аут поза діапазоном.
  • 409 Інструмент із такою назвою вже існує, або цю назву зарезервовано.

Оновлення інструмента

PUT /v1/tools/{id}

Замінює інструмент надісланим об’єктом. Щоб залишити поточний secret, не передавайте його або залиште порожнім; щоб видалити — надішліть "-".

НазваДеТипОпис
id
обов’язковий
шлях string Id інструмента.
name
обов’язковий
тіло string Малі латинські літери, цифри й підкреслення, першим має бути літера (3–41 символ). Унікальна в межах організації; end_call і take_message зарезервовано.
description
обов’язковий
тіло string Пояснює моделі, коли і як використовувати інструмент.
kind
обов’язковий
тіло "read" | "write" read виконується одразу; write спершу просить абонента підтвердити.
url
обов’язковий
тіло string Ваш ендпоінт. Лише https; локальні й приватні адреси відхиляються.
parameters тіло object Об’єкт JSON Schema: до 20 полів типів string, number, integer або boolean (можна enum).
timeout_s тіло integer Від 2 до 15 секунд.
enabled тіло boolean Вимкнені інструменти моделі не пропонуються.
secret тіло string Використовується для підпису запитів. Лише для запису: під час оновлення порожнє значення зберігає поточний секрет, а "-" видаляє його.

Запит

curl
curl -X PUT "https://hubvocal.com/v1/tools/tl_8f3a2c" \
  -H "Authorization: Bearer $VT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "check_order",
  "description": "Looks up the shipping status of an order by its number.",
  "kind": "read",
  "url": "https://crm.example.com/hooks/order",
  "parameters": {
    "type": "object",
    "properties": {
      "order_id": {
        "type": "string",
        "description": "Order number"
      }
    },
    "required": [
      "order_id"
    ]
  },
  "timeout_s": 10,
  "enabled": true,
  "secret": ""
}'

Відповідь · 200

JSON
{
  "id": "tl_8f3a2c",
  "name": "check_order",
  "description": "Looks up the shipping status of an order by its number.",
  "kind": "read",
  "url": "https://crm.example.com/hooks/order",
  "parameters": {
    "type": "object",
    "properties": {
      "order_id": {
        "type": "string",
        "description": "Order number"
      }
    },
    "required": [
      "order_id"
    ]
  },
  "timeout_s": 10,
  "enabled": true,
  "has_secret": true,
  "created_at": 1793830000,
  "updated_at": 1793833600
}

Помилки

  • 400 Поле порушує правила: формат назви, URL не https, приватна адреса, понад 20 параметрів або тайм-аут поза діапазоном.
  • 404 Інструмента з таким id немає.

Видалення інструмента

DELETE /v1/tools/{id}

Видаляє інструмент і прибирає його з усіх агентів, які ним користувалися.

НазваДеТипОпис
id
обов’язковий
шлях string Id інструмента.

Запит

curl
curl -X DELETE "https://hubvocal.com/v1/tools/tl_8f3a2c" \
  -H "Authorization: Bearer $VT_API_KEY"

Відповідь · 200

JSON
{
  "deleted": "tl_8f3a2c"
}

Помилки

  • 404 Інструмента з таким id немає.

Тест інструмента

POST /v1/tools/{id}/test

Надсилає справжній запит на URL інструмента з указаними аргументами й повертає статус, час виконання і до 4 КБ тіла відповіді.

НазваДеТипОпис
id
обов’язковий
шлях string Id інструмента.
arguments тіло object Тестові аргументи відповідно до parameters.

Запит

curl
curl -X POST "https://hubvocal.com/v1/tools/tl_8f3a2c/test" \
  -H "Authorization: Bearer $VT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "arguments": {
    "order_id": "A-10234"
  }
}'

Відповідь · 200

JSON
{
  "ok": true,
  "status": 200,
  "ms": 412,
  "body": "{\"order_id\":\"A-10234\",\"status\":\"shipped\",\"eta\":\"2026-11-07\"}"
}

Помилки

  • 404 Інструмента з таким id немає.

MCP-сервери

Список MCP-серверів

GET /v1/mcp-servers

MCP-сервери вашої організації з їхнім станом і синхронізованими інструментами. auth_set показує, чи збережено секрет; сам секрет ніколи не повертається.

Запит

curl
curl "https://hubvocal.com/v1/mcp-servers" \
  -H "Authorization: Bearer $VT_API_KEY"

Відповідь · 200

JSON
[
  {
    "id": "mcp_2b8e41",
    "name": "crm",
    "url": "https://mcp.example.com/mcp",
    "transport": "streamable_http",
    "auth": "bearer",
    "auth_set": true,
    "enabled": true,
    "status": "ok",
    "error": null,
    "tools_synced_at": 1793831000,
    "tools": [
      {
        "name": "find_customer",
        "description": "Find a customer by phone number.",
        "input_schema": {
          "type": "object",
          "properties": {
            "phone": {
              "type": "string"
            }
          },
          "required": [
            "phone"
          ]
        },
        "enabled": true,
        "access": "read"
      },
      {
        "name": "create_ticket",
        "description": "Open a support ticket.",
        "input_schema": {
          "type": "object",
          "properties": {
            "subject": {
              "type": "string"
            },
            "body": {
              "type": "string"
            }
          },
          "required": [
            "subject"
          ]
        },
        "enabled": false,
        "access": "write"
      }
    ]
  }
]

Додавання MCP-сервера

POST /v1/mcp-servers

Зберігає сервер і отримує список його інструментів. Нові інструменти вимкнені. До 10 серверів на організацію.

НазваДеТипОпис
name
обов’язковий
тіло string Коротка назва; слугує префіксом у назвах інструментів (<name>.<tool>).
url
обов’язковий
тіло string MCP-ендпоінт сервера. Лише https; локальні й приватні адреси відхиляються.
transport тіло string streamable_http (за замовчуванням) або sse.
auth тіло string none, bearer або header.
secret тіло string Токен або значення заголовка. Зберігається в зашифрованому вигляді й ніколи не повертається; "-" видаляє його.
header_name тіло string Назва заголовка, якщо auth — header.

Запит

curl
curl -X POST "https://hubvocal.com/v1/mcp-servers" \
  -H "Authorization: Bearer $VT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "crm",
  "url": "https://mcp.example.com/mcp",
  "auth": "bearer",
  "secret": "sk_live_…"
}'

Відповідь · 201

JSON
{
  "id": "mcp_2b8e41",
  "name": "crm",
  "url": "https://mcp.example.com/mcp",
  "transport": "streamable_http",
  "auth": "bearer",
  "auth_set": true,
  "enabled": true,
  "status": "ok",
  "error": null,
  "tools_synced_at": 1793831000,
  "tools": [
    {
      "name": "find_customer",
      "description": "Find a customer by phone number.",
      "input_schema": {
        "type": "object",
        "properties": {
          "phone": {
            "type": "string"
          }
        },
        "required": [
          "phone"
        ]
      },
      "enabled": false,
      "access": "write"
    },
    {
      "name": "create_ticket",
      "description": "Open a support ticket.",
      "input_schema": {
        "type": "object",
        "properties": {
          "subject": {
            "type": "string"
          },
          "body": {
            "type": "string"
          }
        },
        "required": [
          "subject"
        ]
      },
      "enabled": false,
      "access": "write"
    }
  ]
}

Помилки

  • 400 URL не https або вказує на приватну адресу, або не вдалося отримати список інструментів сервера.
  • 409 В організації вже є 10 MCP-серверів.

Оновлення MCP-сервера

PUT /v1/mcp-servers/{id}

Змінює назву, URL, автентифікацію чи стан (увімкнено/вимкнено), а також те, які інструменти ввімкнені і чи належать вони до read або write. Щоб видалити секрет, надішліть secret: "-".

НазваДеТипОпис
id
обов’язковий
шлях string Id MCP-сервера.
name тіло string Коротка назва; слугує префіксом у назвах інструментів (<name>.<tool>).
url тіло string MCP-ендпоінт сервера. Лише https; локальні й приватні адреси відхиляються.
enabled тіло boolean Вимкнений сервер агентам не пропонується.
auth тіло string none, bearer або header.
secret тіло string Токен або значення заголовка. Зберігається в зашифрованому вигляді й ніколи не повертається; "-" видаляє його.
tools тіло object[] [{name, enabled, access}] для кожного інструмента; access — read або write.

Запит

curl
curl -X PUT "https://hubvocal.com/v1/mcp-servers/mcp_2b8e41" \
  -H "Authorization: Bearer $VT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "tools": [
    {
      "name": "find_customer",
      "enabled": true,
      "access": "read"
    },
    {
      "name": "create_ticket",
      "enabled": true,
      "access": "write"
    }
  ]
}'

Відповідь · 200

JSON
{
  "id": "mcp_2b8e41",
  "name": "crm",
  "url": "https://mcp.example.com/mcp",
  "transport": "streamable_http",
  "auth": "bearer",
  "auth_set": true,
  "enabled": true,
  "status": "ok",
  "error": null,
  "tools_synced_at": 1793831000,
  "tools": [
    {
      "name": "find_customer",
      "description": "Find a customer by phone number.",
      "input_schema": {
        "type": "object",
        "properties": {
          "phone": {
            "type": "string"
          }
        },
        "required": [
          "phone"
        ]
      },
      "enabled": true,
      "access": "read"
    },
    {
      "name": "create_ticket",
      "description": "Open a support ticket.",
      "input_schema": {
        "type": "object",
        "properties": {
          "subject": {
            "type": "string"
          },
          "body": {
            "type": "string"
          }
        },
        "required": [
          "subject"
        ]
      },
      "enabled": true,
      "access": "write"
    }
  ]
}

Помилки

  • 400 URL не https або вказує на приватну адресу, або не вдалося отримати список інструментів сервера.
  • 404 MCP-сервера з таким id немає.

Видалення MCP-сервера

DELETE /v1/mcp-servers/{id}

Видаляє сервер і прибирає його інструменти з усіх агентів.

НазваДеТипОпис
id
обов’язковий
шлях string Id MCP-сервера.

Запит

curl
curl -X DELETE "https://hubvocal.com/v1/mcp-servers/mcp_2b8e41" \
  -H "Authorization: Bearer $VT_API_KEY"

Відповідь · 200

JSON
{
  "deleted": "mcp_2b8e41"
}

Помилки

  • 404 MCP-сервера з таким id немає.

Синхронізація інструментів

POST /v1/mcp-servers/{id}/sync

Ще раз отримує список інструментів. Нові інструменти з’являються вимкненими, з доступом write.

НазваДеТипОпис
id
обов’язковий
шлях string Id MCP-сервера.

Запит

curl
curl -X POST "https://hubvocal.com/v1/mcp-servers/mcp_2b8e41/sync" \
  -H "Authorization: Bearer $VT_API_KEY"

Відповідь · 200

JSON
{
  "id": "mcp_2b8e41",
  "name": "crm",
  "url": "https://mcp.example.com/mcp",
  "transport": "streamable_http",
  "auth": "bearer",
  "auth_set": true,
  "enabled": true,
  "status": "ok",
  "error": null,
  "tools_synced_at": 1793831000,
  "tools": [
    {
      "name": "find_customer",
      "description": "Find a customer by phone number.",
      "input_schema": {
        "type": "object",
        "properties": {
          "phone": {
            "type": "string"
          }
        },
        "required": [
          "phone"
        ]
      },
      "enabled": true,
      "access": "read"
    },
    {
      "name": "create_ticket",
      "description": "Open a support ticket.",
      "input_schema": {
        "type": "object",
        "properties": {
          "subject": {
            "type": "string"
          },
          "body": {
            "type": "string"
          }
        },
        "required": [
          "subject"
        ]
      },
      "enabled": false,
      "access": "write"
    }
  ]
}

Помилки

  • 400 URL не https або вказує на приватну адресу, або не вдалося отримати список інструментів сервера.
  • 404 MCP-сервера з таким id немає.

Тест інструмента

POST /v1/mcp-servers/{id}/test

Викликає один інструмент на сервері з указаними аргументами й повертає час виконання, до 4 КБ вмісту та ознаку того, чи повідомив інструмент про помилку.

НазваДеТипОпис
id
обов’язковий
шлях string Id MCP-сервера.
tool
обов’язковий
тіло string Назва інструмента, який треба викликати.
arguments тіло object Аргументи інструмента відповідно до його input_schema.

Запит

curl
curl -X POST "https://hubvocal.com/v1/mcp-servers/mcp_2b8e41/test" \
  -H "Authorization: Bearer $VT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "tool": "find_customer",
  "arguments": {
    "phone": "+905321234567"
  }
}'

Відповідь · 200

JSON
{
  "ok": true,
  "ms": 236,
  "content": "{\"customer_id\":\"C-1042\",\"name\":\"Ayşe Yılmaz\",\"open_tickets\":0}",
  "is_error": false
}

Помилки

  • 404 MCP-сервера з таким id немає.

Вебхуки

Список вебхуків

GET /v1/webhooks

Вебхуки вашої організації з результатом останньої доставки. Секрет тут ніколи не повертається; secret_set показує, чи його задано.

Запит

curl
curl "https://hubvocal.com/v1/webhooks" \
  -H "Authorization: Bearer $VT_API_KEY"

Відповідь · 200

JSON
[
  {
    "id": "wh_3c9d1e",
    "url": "https://crm.example.com/hooks/voice",
    "events": [
      "call.ended"
    ],
    "enabled": true,
    "secret_set": true,
    "created_at": 1793830000,
    "last_delivery": {
      "status": "ok",
      "at": 1793832440.2,
      "http_status": 200
    }
  }
]

Створення вебхука

POST /v1/webhooks

Підписує URL на події. Наразі подія лише одна — call.ended. До 5 вебхуків на організацію. Якщо не вказати secret, його буде згенеровано й повернуто лише в цій відповіді.

НазваДеТипОпис
url
обов’язковий
тіло string Ваш ендпоінт. Лише https; локальні й приватні адреси відхиляються.
events
обов’язковий
тіло string[] Події, які потрібно отримувати. Наразі ["call.ended"].
enabled тіло boolean Вимкнені вебхуки нічого не отримують.
secret тіло string Секрет для підпису. Якщо не вказано, генерується автоматично; повертається лише один раз.

Запит

curl
curl -X POST "https://hubvocal.com/v1/webhooks" \
  -H "Authorization: Bearer $VT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "url": "https://crm.example.com/hooks/voice",
  "events": [
    "call.ended"
  ]
}'

Відповідь · 201

JSON
{
  "id": "wh_3c9d1e",
  "url": "https://crm.example.com/hooks/voice",
  "events": [
    "call.ended"
  ],
  "enabled": true,
  "secret_set": true,
  "created_at": 1793830000,
  "last_delivery": null,
  "secret": "whsec_9QmZ…"
}

Помилки

  • 400 URL не https, вказує на приватну адресу, або подія невідома.
  • 409 В організації вже є 5 вебхуків.

Оновлення вебхука

PUT /v1/webhooks/{id}

Змінює URL, події або вмикає й вимикає вебхук. Надішліть secret: "-", щоб згенерувати новий секрет; його буде повернуто у відповіді.

НазваДеТипОпис
id
обов’язковий
шлях string Id вебхука.
url тіло string Ваш ендпоінт. Лише https; локальні й приватні адреси відхиляються.
events тіло string[] Події, які потрібно отримувати. Наразі ["call.ended"].
enabled тіло boolean Вимкнені вебхуки нічого не отримують.
secret тіло string "-" генерує новий секрет. Не передавайте поле, щоб зберегти поточний.

Запит

curl
curl -X PUT "https://hubvocal.com/v1/webhooks/wh_3c9d1e" \
  -H "Authorization: Bearer $VT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "enabled": false
}'

Відповідь · 200

JSON
{
  "id": "wh_3c9d1e",
  "url": "https://crm.example.com/hooks/voice",
  "events": [
    "call.ended"
  ],
  "enabled": false,
  "secret_set": true,
  "created_at": 1793830000,
  "last_delivery": {
    "status": "ok",
    "at": 1793832440.2,
    "http_status": 200
  }
}

Помилки

  • 400 URL не https, вказує на приватну адресу, або подія невідома.
  • 404 Вебхука з таким id немає.

Видалення вебхука

DELETE /v1/webhooks/{id}

Видаляє вебхук. Доставки, що очікують на надсилання, скасовуються.

НазваДеТипОпис
id
обов’язковий
шлях string Id вебхука.

Запит

curl
curl -X DELETE "https://hubvocal.com/v1/webhooks/wh_3c9d1e" \
  -H "Authorization: Bearer $VT_API_KEY"

Відповідь · 200

JSON
{
  "deleted": "wh_3c9d1e"
}

Помилки

  • 404 Вебхука з таким id немає.

Тест вебхука

POST /v1/webhooks/{id}/test

Надсилає на URL тестову подію call.ended і повертає статус, час виконання й тіло відповіді.

НазваДеТипОпис
id
обов’язковий
шлях string Id вебхука.

Запит

curl
curl -X POST "https://hubvocal.com/v1/webhooks/wh_3c9d1e/test" \
  -H "Authorization: Bearer $VT_API_KEY"

Відповідь · 200

JSON
{
  "ok": true,
  "http_status": 200,
  "ms": 184,
  "body": "{\"received\":true}"
}

Помилки

  • 404 Вебхука з таким id немає.

Список доставок

GET /v1/webhooks/{id}/deliveries

Останні 50 доставок вебхука, від найновіших: статус (pending, ok, failed), кількість спроб, HTTP-статус, помилка й час наступної спроби.

НазваДеТипОпис
id
обов’язковий
шлях string Id вебхука.

Запит

curl
curl "https://hubvocal.com/v1/webhooks/wh_3c9d1e/deliveries" \
  -H "Authorization: Bearer $VT_API_KEY"

Відповідь · 200

JSON
[
  {
    "id": "dl_51b7a9",
    "event": "call.ended",
    "call_id": "demo-8585522d",
    "status": "ok",
    "attempts": 1,
    "http_status": 200,
    "error": null,
    "created_at": 1793832440.2,
    "next_attempt_at": null
  },
  {
    "id": "dl_51a3c4",
    "event": "call.ended",
    "call_id": "tel-6b1f04d2",
    "status": "pending",
    "attempts": 2,
    "http_status": 503,
    "error": "HTTP 503",
    "created_at": 1793832101.7,
    "next_attempt_at": 1793833901.7
  }
]

Помилки

  • 404 Вебхука з таким id немає.

Повторення доставки

POST /v1/webhooks/deliveries/{id}/retry

Знову ставить невдалу доставку в чергу.

НазваДеТипОпис
id
обов’язковий
шлях string Id доставки зі списку доставок.

Запит

curl
curl -X POST "https://hubvocal.com/v1/webhooks/deliveries/dl_51a3c4/retry" \
  -H "Authorization: Bearer $VT_API_KEY"

Відповідь · 200

JSON
{
  "ok": true
}

Помилки

  • 404 Доставки з таким id немає, або вона не завершилася помилкою.

Голоси й рушії

Рушії, голоси й ліміти

GET /v1/voices

Усе, що потрібно для форми агента: назви рушіїв, допустимі голоси для кожного рушія, діапазони швидкості, мови, пресети тону, модель кожного рушія й ліміти довжини полів. Приклад нижче скорочено.

Запит

curl
curl "https://hubvocal.com/v1/voices" \
  -H "Authorization: Bearer $VT_API_KEY"

Відповідь · 200

JSON
{
  "engines": {
    "live": "GPT-Live 1 (OpenAI full-duplex ses modeli)",
    "gemini": "Gemini Live (Google ses-sese model)",
    "realtime": "Realtime (OpenAI ses-sese model)",
    "classic": "Klasik (Deepgram + OpenAI LLM + OpenAI TTS)"
  },
  "voices": {
    "live": [
      "marin",
      "cedar",
      "gleam",
      "meridian"
    ],
    "gemini": [
      "Kore",
      "Aoede",
      "Charon",
      "Puck"
    ],
    "realtime": [
      "marin",
      "cedar",
      "alloy"
    ],
    "classic": [
      "alloy",
      "coral",
      "sage"
    ]
  },
  "speed": {
    "live": {
      "min": 1,
      "max": 1
    },
    "gemini": {
      "min": 1,
      "max": 1
    },
    "realtime": {
      "min": 0.25,
      "max": 1.5
    },
    "classic": {
      "min": 0.25,
      "max": 4
    }
  },
  "langs": {
    "tr": "Türkçe",
    "en": "English"
  },
  "presets": [
    {
      "id": "calm",
      "label": "Sakin ve güven veren",
      "text": "Sakin, yumuşak ve güven veren bir tonla konuş."
    }
  ],
  "models": {
    "live": {
      "model": "gpt-live-1",
      "backend": "gpt-5.6-luna"
    },
    "gemini": {
      "model": "gemini-3.8-live",
      "ready": true
    },
    "realtime": {
      "model": "gpt-realtime-2.1-mini"
    },
    "classic": {
      "stt": "nova-3",
      "llm": "gpt-4.1-mini",
      "tts": "gpt-4o-mini-tts"
    }
  },
  "limits": {
    "tone": 600,
    "instructions": 8000,
    "greeting": 400
  }
}

Дзвінки

Строки зберігання налаштовуються для організації в панелі керування: recordings_days (за замовчуванням 30), transcripts_days (за замовчуванням 365) і pii_redaction. Щоденне завдання видаляє записи й розшифровки, строк зберігання яких минув; рядок дзвінка та його вартість залишаються.

Веб-віджет: публічні ключі (pk_…) створюються для кожного агента в панелі керування. Скрипт віджета викликає POST /api/public/web-calls; докладніше — у посібнику на сторінці «Розробникам».

Початок веб-дзвінка

POST /v1/web-calls

Відкриває кімнату для дзвінка з браузера й повертає короткочасний токен доступу. Передайте server_url і token у livekit-client у браузері; агент приєднається до кімнати сам. Викликайте цей ендпоінт зі свого сервера, щоб ключ API ніколи не потрапив у браузер. Замість agent_id можна надіслати повний об’єкт agent, щоб перевірити чернетку без збереження.

НазваДеТипОпис
agent_id тіло string Id збереженого агента. Обов’язковий, якщо не надіслано agent.
agent тіло object Повний об’єкт агента (ті самі поля, що й у POST /v1/agents) лише для цього дзвінка.
version тіло string | integer Яку версію використовувати: "live" (за замовчуванням), "draft" або номер версії.

Запит

curl
curl -X POST "https://hubvocal.com/v1/web-calls" \
  -H "Authorization: Bearer $VT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "agent_id": "front-desk"
}'

Відповідь · 200

JSON
{
  "server_url": "wss://hubvocal.com",
  "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9…",
  "room": "demo-3f9a1c2e",
  "max_seconds": 300
}

Помилки

  • 400 Не надіслано ні agent_id, ні agent.
  • 402 Організація досягла місячного ліміту витрат.
  • 403 Роботу організації призупинено.
  • 404 Агента з таким id немає.

Вихідний телефонний дзвінок

POST /v1/calls

Набирає номер з одного з номерів вашої організації й підключає агента, коли абонент відповість. Провайдер (DIDWW, Twilio або ваш SIP-транк) визначається за номером from.

НазваДеТипОпис
from
обов’язковий
тіло string Один із номерів вашої організації у форматі E.164 (+90…).
to
обов’язковий
тіло string Номер, на який треба зателефонувати, у форматі E.164.
agent_id тіло string Агент для дзвінка. Якщо не вказано, говорить агент, призначений номеру from.
version тіло string | integer Яку версію використовувати: "live" (за замовчуванням), "draft" або номер версії.

Запит

curl
curl -X POST "https://hubvocal.com/v1/calls" \
  -H "Authorization: Bearer $VT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "from": "+908501234567",
  "to": "+905321234567",
  "agent_id": "front-desk"
}'

Відповідь · 200

JSON
{
  "room": "tel-out-9c41e0b7",
  "provider": "didww",
  "sip_call_id": "SCL_7mVt2kQb9xRa"
}

Помилки

  • 400 Номер не в міжнародному форматі, або from не належить до ваших номерів.
  • 402 Організація досягла місячного ліміту витрат.
  • 502 Провайдер телефонії відхилив дзвінок.

Список дзвінків

GET /v1/calls

Дзвінки від найновіших до найстаріших, веб і телефонні. quality — зведення вимірювань на боці браузера; для телефонних дзвінків воно null. ended_by: caller, agent, max_call_seconds, caller_unresponsive, agent_unresponsive, no_answer або unknown. channel: web, phone_in або phone_out. Кожен рядок також містить outcome і summary_text (перші 160 символів підсумку). ended_by має значення supervisor, якщо дзвінок завершив супервізор із консолі реального часу.

НазваДеТипОпис
limit query integer За замовчуванням 50, максимум 500.
agent query string Лише дзвінки цього агента (назва агента).
outcome query string Лише дзвінки з цим результатом.

Запит

curl
curl "https://hubvocal.com/v1/calls?limit=20" \
  -H "Authorization: Bearer $VT_API_KEY"

Відповідь · 200

JSON
[
  {
    "room": "demo-8585522d",
    "org_id": "6f1c2a40-3b7e-4d0c-9a51-2f8e7c1d9b03",
    "org_name": "Example Clinic",
    "channel": "web",
    "profile": "Front desk",
    "engine": "live",
    "lang": "en",
    "voice": "marin",
    "started_at": 1793832409.1,
    "ended_at": 1793832434.2,
    "duration_s": 25.1,
    "total_usd": 0.021215,
    "ended_by": "caller",
    "outcome": "message_taken",
    "summary_text": "The caller asked for an appointment on Thursday afternoon; a message was taken for a callback.",
    "extracted": {
      "appointment_date": "2026-11-12",
      "callback": true
    },
    "first_audio_s": 2.43,
    "turns": 4,
    "source_gaps": {
      "count": 0,
      "total_ms": 0,
      "max_ms": 0
    },
    "quality": {
      "verdict": "Clean: no loss, no gaps.",
      "protocol": "UDP",
      "loss_pct": 0,
      "conceal_pct": 0,
      "jitter_ms": 4,
      "rtt_ms": 38
    }
  }
]

Отримання дзвінка

GET /v1/calls/{room}

Повна картка дзвінка: деталізація вартості за провайдерами, розшифровка, час до привітання, розриви на боці агента та шкала якості в браузері у 2-секундних вікнах. Поля вартості залежать від рушія (live, llm, stt, tts, realtime…); кожне містить usd. source_gaps.events — це пари [секунда, мс]. summary містить text, outcome (resolved, message_taken, transferred, unresolved, no_conversation, spam), sentiment, topics і action_items. supervisors показує, хто приєднувався до дзвінка з консолі реального часу й у яких режимах. recording містить available, duration_s і size_bytes. extracted містить значення post_call.fields агента (null, якщо про значення не йшлося).

НазваДеТипОпис
room
обов’язковий
шлях string Назва кімнати зі списку дзвінків або з POST /v1/web-calls.

Запит

curl
curl "https://hubvocal.com/v1/calls/demo-8585522d" \
  -H "Authorization: Bearer $VT_API_KEY"

Відповідь · 200

JSON
{
  "call": {
    "room": "demo-8585522d",
    "org_id": "6f1c2a40-3b7e-4d0c-9a51-2f8e7c1d9b03",
    "org_name": "Example Clinic",
    "channel": "web",
    "profile": "Front desk",
    "engine": "live",
    "lang": "en",
    "voice": "marin",
    "started_at": 1793832409.1,
    "ended_at": 1793832434.2,
    "duration_s": 25.1,
    "total_usd": 0.021215,
    "ended_by": "caller",
    "outcome": "message_taken",
    "summary_text": "The caller asked for an appointment on Thursday afternoon; a message was taken for a callback.",
    "extracted": {
      "appointment_date": "2026-11-12",
      "callback": true
    },
    "first_audio_s": 2.43,
    "turns": 4,
    "source_gaps": {
      "count": 2,
      "total_ms": 230,
      "max_ms": 141,
      "agent_audio_s": 31.2,
      "events": [
        [
          16.4,
          141
        ],
        [
          40.1,
          89
        ]
      ]
    },
    "quality": {
      "verdict": "Clean: no loss, no gaps.",
      "protocol": "UDP",
      "loss_pct": 0,
      "conceal_pct": 0,
      "jitter_ms": 4,
      "rtt_ms": 38
    },
    "cost": {
      "live": {
        "billed_s": 25.1,
        "reported": true,
        "voice_usd": 0.020917,
        "backend": {
          "in": 1840,
          "cached": 1024,
          "out": 96
        },
        "backend_usd": 0.000298
      },
      "llm": {
        "input_tokens": 1840,
        "cached_tokens": 1024,
        "output_tokens": 96,
        "usd": 0.000298
      },
      "tts": {
        "input_tokens": 0,
        "audio_tokens": 0,
        "audio_s": 25.1,
        "usd": 0.020917
      },
      "stt": {
        "audio_s": 0,
        "usd": 0
      }
    },
    "tools": [
      {
        "t": 14.2,
        "name": "check_order",
        "kind": "read",
        "ok": true,
        "ms": 412,
        "status": 200
      }
    ],
    "outcomes": [],
    "summary": {
      "text": "The caller asked for an appointment on Thursday afternoon; a message was taken for a callback.",
      "language": "en",
      "outcome": "message_taken",
      "sentiment": "neutral",
      "topics": [
        "appointment"
      ],
      "action_items": [
        "Call the caller back on Thursday morning"
      ]
    },
    "recording": {
      "available": true,
      "duration_s": 25.1,
      "size_bytes": 201344
    },
    "supervisors": [
      {
        "user": "ayse@example.com",
        "joined_at": 1793832420.4,
        "left_at": 1793832431,
        "modes": [
          "listen",
          "whisper"
        ]
      }
    ],
    "greeting": {
      "connect_s": 0.15,
      "session_started_s": 0.05,
      "reply_requested_s": 0.05,
      "first_audio_s": 2.4,
      "reply_done_s": 7.1
    },
    "transcript": [
      {
        "role": "assistant",
        "text": "Hello, thanks for calling the clinic. How can I help you today?",
        "t": 2.4,
        "interrupted": false
      },
      {
        "role": "user",
        "text": "I would like an appointment on Thursday afternoon.",
        "t": 9.8
      }
    ]
  },
  "quality": {
    "summary": {
      "verdict": "Clean: no loss, no gaps.",
      "protocol": "UDP",
      "rtt_ms": 38,
      "protocols_seen": [
        "UDP"
      ],
      "loss_pct": 0,
      "conceal_pct": 0,
      "jitter_ms": 4,
      "buffer_ms": 62
    },
    "timeline": [
      {
        "t": 2,
        "loss": 0,
        "conceal": 0,
        "jitter": 3,
        "buffer": 60,
        "proto": "UDP"
      },
      {
        "t": 4,
        "loss": 0,
        "conceal": 0,
        "jitter": 4,
        "buffer": 62,
        "proto": "UDP"
      }
    ]
  }
}

Помилки

  • 404 Дзвінок не знайдено.

Завантаження запису

GET /v1/calls/{room}/recording

Аудіо дзвінка у форматі OGG/Opus. Підтримуються Range-запити. 404, якщо дзвінок не записувався або строк зберігання запису минув.

НазваДеТипОпис
room
обов’язковий
шлях string Назва кімнати зі списку дзвінків або з POST /v1/web-calls.

Запит

curl
curl "https://hubvocal.com/v1/calls/demo-8585522d/recording" \
  -H "Authorization: Bearer $VT_API_KEY" \
  -o call.ogg

Відповідь · 200

audio/ogg
HTTP/1.1 200 OK
Content-Type: audio/ogg
Accept-Ranges: bytes
Content-Length: 201344

<OGG/Opus>

Помилки

  • 404 Дзвінок не записувався, або строк зберігання запису минув.

Видалення дзвінка

DELETE /v1/calls/{room}

Одразу видаляє запис, розшифровку й підсумок дзвінка, наприклад на запит згідно з KVKK або GDPR. Рядок дзвінка та його вартість залишаються.

НазваДеТипОпис
room
обов’язковий
шлях string Назва кімнати зі списку дзвінків або з POST /v1/web-calls.

Запит

curl
curl -X DELETE "https://hubvocal.com/v1/calls/demo-8585522d" \
  -H "Authorization: Bearer $VT_API_KEY"

Відповідь · 200

JSON
{
  "deleted": "demo-8585522d"
}

Помилки

  • 404 Дзвінок не знайдено.

Експорт дзвінків (CSV)

GET /v1/calls/export

Дзвінки за період у форматі CSV, один рядок на дзвінок; структуровані поля подано додатковими стовпцями.

НазваДеТипОпис
format
обов’язковий
query string Лише csv.
from query date YYYY-MM-DD, включно.
to query date YYYY-MM-DD, включно.
agent_id query string Лише дзвінки цього агента.

Запит

curl
curl "https://hubvocal.com/v1/calls/export?format=csv&from=2026-11-01&to=2026-11-05" \
  -H "Authorization: Bearer $VT_API_KEY" \
  -o calls.csv

Відповідь · 200

text/csv
room,started_at,agent,channel,duration_s,total_usd,outcome,appointment_date,callback
demo-8585522d,2026-11-05T09:46:49Z,front-desk,web,25.1,0.021215,message_taken,2026-11-12,true

Номери телефонів

Список номерів

GET /v1/numbers

Номери телефонів вашої організації та агент, який відповідає на кожному з них (profile_id), а також готовність кожного провайдера телефонії. Номери додає команда платформи, а агентів призначаєте ви.

Запит

curl
curl "https://hubvocal.com/v1/numbers" \
  -H "Authorization: Bearer $VT_API_KEY"

Відповідь · 200

JSON
{
  "numbers": [
    {
      "number": "+908501234567",
      "provider": "didww",
      "org_id": "6f1c2a40-3b7e-4d0c-9a51-2f8e7c1d9b03",
      "org_name": "Example Clinic",
      "profile_id": "front-desk",
      "label": "Main line"
    }
  ],
  "sip": {
    "enabled": true,
    "room_prefix": "tel-",
    "providers": {
      "didww": {
        "inbound_ips": "46.19.209.14,46.19.210.14",
        "inbound_auth": false,
        "outbound_host": "trunk.example.com",
        "outbound_auth": true,
        "outbound_ready": true,
        "inbound_ready": true
      }
    }
  }
}

Призначення агента номеру

PUT /v1/numbers/{number}

Визначає, який агент відповідатиме на вхідні дзвінки на цей номер. Щоб зняти призначення, надішліть agent_id: null. Знак + у номері кодуйте в шляху як %2B (префікс 00 теж працює).

НазваДеТипОпис
number
обов’язковий
шлях string Номер у форматі E.164, закодований для URL.
agent_id тіло string | null Агент, який відповідає на вхідні дзвінки.
label тіло string Примітка для вашої команди, до 60 символів.

Запит

curl
curl -X PUT "https://hubvocal.com/v1/numbers/%2B908501234567" \
  -H "Authorization: Bearer $VT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "agent_id": "front-desk",
  "label": "Main line"
}'

Відповідь · 200

JSON
{
  "ok": true
}

Помилки

  • 400 Такого агента не існує.
  • 404 Номер не належить вашій організації.

Використання

Використання

GET /v1/usage

Дзвінки, хвилини й витрати на провайдерів у вашій організації — за провайдерами й днями (Europe/Istanbul). За замовчуванням — поточний місяць. kind: llm, tts, stt або voice (рушії, що працюють безпосередньо з голосом).

НазваДеТипОпис
from query date YYYY-MM-DD, включно.
to query date YYYY-MM-DD, включно.

Запит

curl
curl "https://hubvocal.com/v1/usage?from=2026-11-01&to=2026-11-05" \
  -H "Authorization: Bearer $VT_API_KEY"

Відповідь · 200

JSON
{
  "from": "2026-11-01",
  "to": "2026-11-05",
  "totals": {
    "calls": 42,
    "minutes": 81.2,
    "usd": 3.94
  },
  "by_provider": [
    {
      "provider": "openai",
      "model": "gpt-live-1",
      "kind": "voice",
      "calls": 30,
      "input_tokens": 0,
      "cached_tokens": 0,
      "output_tokens": 0,
      "audio_s": 2900.1,
      "usd": 2.41
    }
  ],
  "by_day": [
    {
      "date": "2026-11-05",
      "usd": 1.2,
      "minutes": 20.5,
      "calls": 9
    }
  ],
  "by_org": [
    {
      "org_id": "6f1c2a40-3b7e-4d0c-9a51-2f8e7c1d9b03",
      "org_name": "Example Clinic",
      "usd": 3.94,
      "minutes": 81.2,
      "calls": 42
    }
  ]
}

Специфікація

Специфікація OpenAPI

GET /v1/openapi.json Ключ не потрібен

Документ OpenAPI 3.1 для цього API. Ключ не потрібен. Імпортуйте його в Postman, Insomnia або генератор клієнтів.

Запит

curl
curl "https://hubvocal.com/v1/openapi.json"

Відповідь · 200

JSON
{
  "openapi": "3.1.0",
  "info": {
    "title": "HubVocal API",
    "version": "1.0.0"
  },
  "servers": [
    {
      "url": "https://hubvocal.com/v1"
    }
  ],
  "paths": {}
}