Към съдържанието

Как да се обадите на клиент от n8n workflow

September 2, 2026 · 7 мин четене

От n8n можете да се обадите на клиент без нито един ред код: добавете към workflow възел HTTP Request, настройте го на POST https://volai.cz/v1/calls със заглавка Authorization: Bearer vk_... и тяло {to, agentId} - и Вашият гласов агент ще набере номера точно в момента, в който workflow-ът има нужда. По-долу е целият процес: как да прехвърлите данните от workflow-а в промпта на агента, как да върнете резултата от обаждането в n8n и как да се обадите и без агент, с директно свързване на два номера.

Какво ще Ви трябва

  • Инстанция на n8n - облачна или self-hosted, версията няма значение.
  • Акаунт във volai и API ключ от портала (Настройки -> API и MCP), във вид vk_.... В n8n го запазете като credential от тип Header Auth (заглавка Authorization, стойност Bearer vk_...) - така няма да се налага да пренаписвате ключа във всеки възел поотделно.
  • Собствен телефонен номер с гласов агент - създава се в портала или през /docs/agent. Без агент може да се обадите и с директно свързване на два номера (вариантът from по-долу).

1Добавете възел HTTP Request

Метод POST, URL https://volai.cz/v1/calls, автентикация чрез запазения credential, Body Content Type JSON. В тялото влизат to (номерът на клиента) и agentId (ID на агента от портала) - и двете са задължителни, като точно ЕДНО от agentId/from/systemPrompt е позволено, никога повече наведнъж.

json
{
  "to": "={{ $json.phone }}",
  "agentId": "ag_kx91fa2b",
  "variables": {
    "customer_name": "={{ $json.name }}",
    "order_number": "={{ $json.order }}"
  },
  "ringingTimeoutSecs": 30
}

Стойностите с ={{...}} са изрази на n8n - $json чете полетата от предходния възел на workflow-а (например webhook „нова поръчка“ или ред от таблица).

2Прехвърлете данните от workflow-а в промпта на агента

variables е обект низ-низ, който агентът получава като динамични променливи - в системния си промпт ги използвате със записа {{customer_name}}. Ограничения: най-много 20 ключа, ключ до 64 знака, стойност до 512 знака. Имената attempt_id, caller_number, called_number са запазени - добавя ги самият volai и стойностите със същото име от workflow-а биха били отхвърлени.

ringingTimeoutSecs (от 5 до 60 секунди, по подразбиране 25) определя колко дълго да звъни, преди невдигнатото обаждане да бъде приключено с endReason: "no_answer". По-дългото звънене увеличава шанса клиентът да успее да вдигне, но и по-дълго държи заето изходящия слот.

3Прочетете отговора и при нужда изчакайте резултата

Успешният отговор идва веднага, но обаждането в този момент едва започва - status е initiated, не краен статус:

json
{
  "id": "c_9d4e2b7f",
  "status": "initiated"
}

Ако искате в същия workflow да изчакате резултата вместо да ползвате отделен webhook, добавете веднага след възела HTTP Request втори, който извиква GET /v1/calls/{id} с параметър waitSecs (от 0 до 45 секунди) - сървърът отговаря, когато обаждането приключи или когато лимитът изтече, което настъпи първо:

bash
curl "https://volai.cz/v1/calls/c_9d4e2b7f?waitSecs=30" \
  -H "Authorization: Bearer vk_YOUR_KEY"

Резултатът обратно: webhook към n8n

За продукционни workflow-и е по-практично да не се чака резултатът в същото изпълнение, а да се получава отделно: добавете в n8n (спокойно в нов workflow) възел Webhook, копирайте неговия Production URL и го регистрирайте еднократно във volai:

bash
curl -X PUT https://volai.cz/v1/webhook \
  -H "Authorization: Bearer vk_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://your-instance.app.n8n.cloud/webhook/volai-calls",
    "events": ["call.completed", "call.failed", "call.no_answer"]
  }'

Отговорът съдържа secret (във вид whsec_...) - запазете го, ще Ви трябва за проверка на подписа на всяка входяща заявка. volai изпраща заглавка Volai-Signature във вида t=<unix>,v1=<hex> - пълният код за проверка на TypeScript и Python ще намерите на /docs/webhooky. Във възела Code на n8n не може да се пренесе без промяна: HMAC се изчислява върху СУРОВОТО тяло на заявката, така че във възела Webhook трябва да включите опцията Raw Body (без нея n8n предава вече разпарсиран JSON и подписът не съвпада), а модулът crypto импортирайте през require, не през import. Не обработвайте тялото, преди да сте проверили подписа.

Пример какво пристига на webhook-а след края на обаждането:

json
{
  "event": "call.completed",
  "ts": 1756111640000,
  "data": {
    "id": "c_9d4e2b7f",
    "direction": "out",
    "from": "+420601234567",
    "to": "+420777123456",
    "status": "completed",
    "durationSecs": 90,
    "priceHal": 513,
    "answeredBy": "human",
    "endReason": "completed",
    "transcript": [
      { "role": "agent", "message": "Добър ден, обаждам се във връзка с поръчка A-42." },
      { "role": "caller", "message": "Да, вече знам, благодаря за напомнянето." }
    ],
    "summary": "Клиентът потвърди получаването на поръчка A-42.",
    "data": {
      "order_confirmed": true
    }
  }
}

Ключът data вътре в data е по избор и съдържа точно полетата, които сте задали на агента в неговите dataFields - примерът по-горе (order_confirmed) е само илюстративен, при Вас ще са други. Следващият възел на n8n може по тези полета да реши например дали да обнови CRM, или да насрочи обаждането наново.

Как да се обадите без агент?

Ако нямате нужда от гласов агент и искате само да свържете два номера (например търговец с клиент), изпратете вместо agentId полето from:

json
{
  "to": "+420777123456",
  "from": "+420601234567"
}

volai първо се обажда на from и щом някой вдигне, набира to. Двете страни на обаждането се таксуват поотделно по 0,92 kr за минута (без надбавка за агент). from е номерът, на който Вие вдигате - обикновено Вашият мобилен - и може да е произволен чешки или словашки номер, дори извън Вашия акаунт във volai. Условието е друго: в акаунта трябва да имате поне един СОБСТВЕН номер във volai, защото от него се таксува обаждането и това е номерът, който се показва на дисплея и на двете страни (без него volai връща грешка bridge_needs_number). Само внимавайте да не е номер във volai, насочен към агент или към SIP - мрежата би свързала първата страна с него, не с Вас, и обаждането никога нямаше да Ви достигне.

Колко струва такова обаждане?

Изходящо обаждане през агент се таксува като сбор от две тарифи: изходяща минута (0,92 kr) и надбавка за агент ОТГОРЕ на нея (2,50 kr), и двете от ценовата листа, валидна към 2.9.2026 г. Обаждане с продължителност минута и половина така излиза 5,13 kr:

ПозицияТарифа90 с разговор
Изходяща минута0,92 kr/мин1,38 kr
Надбавка за агент2,50 kr/мин3,75 kr
Общо5,13 kr

Таксува се по секунди, не по цели минути - по-кратко обаждане струва пропорционално по-малко. Точната ценова листа на всички позиции (номера, агент, SMS) е на /cenik.

Безопасно повтаряне при retry (Idempotency-Key)

n8n може да повтори възела автоматично при грешка (Retry On Fail) - без предпазна мярка при телефонно обаждане това би означавало две реални обаждания към един и същ клиент. Добавете заглавка Idempotency-Key със стабилна стойност за едно изпълнение на workflow-а (n8n я предлага като {{ $execution.id }}, или използвайте собствено ID на поръчката) - със същия ключ в рамките на 24 часа получавате обратно отговора от първия опит и обаждането не се създава втори път:

bash
curl -X POST https://volai.cz/v1/calls \
  -H "Authorization: Bearer vk_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: reminder-order-A-42" \
  -d '{"to": "+420777123456", "agentId": "ag_kx91fa2b"}'

Какво да направите, когато API върне грешка?

Тази таблица обхваща варианта с agentId и from - състоянията, специфични за пробно обаждане без номер (systemPrompt), тук нарочно липсват, за тях важи друг процес.

СтатусКодКакво означава
400invalid_numberПолето не е валиден телефонен номер.
400validationЛипсва или са повече от едно от agentId/from; евентуално variables извън лимита или ringingTimeoutSecs извън обхвата от 5 до 60.
400on_dncНомерът е във Вашия списък „не звънете“ (/v1/dnc).
400destination_auto_blockedДестинацията е автоматично блокирана за 30 дни след многократни неуспехи.
400cannot_call_own_numberЗащита срещу цикъл - на собствен номер във volai не може да се звъни.
404agent_not_foundagentId не съществува или не принадлежи на Вашия акаунт.
404agent_no_numberАгентът няма присвоен телефонен номер.
404bridge_needs_numberПри варианта from: в акаунта Ви трябва поне един собствен номер във volai.
409destination_busyКъм същия номер в момента тече друго Ваше обаждане.
402insufficient_creditБалансът не покрива минимума за започване на обаждане.
503capacity_busyВсички изходящи линии в момента са заети, опитайте след минута.

Общ лимит на API

Освен таблицата по-горе важи още един общ лимит за цялото API: най-много 60 заявки в минута на един API ключ (HTTP 429, rate_limited). При workflow-и, които звънят на десетки номера бързо един след друг, имайте го предвид - същият лимит важи за POST /v1/messages и останалите endpoint-и под същия ключ.

Какво следва

Пълният преглед на всичко, което може да се извика от n8n (SMS, номера, DNC), е в интеграцията с n8n. Пълната REST референция е на /docs/api, пълното описание на събитията на webhook-а и проверката на подписа - на /docs/webhooky.

Изпробвайте volai - първите 50 kr са от нас

Създавате акаунт за минута и в него вече има начален баланс за обаждания и номер - SMS изпращате след първото зареждане.

Изпробвайте безплатно