Przejdź do treści
REST API

SMS i połączenia prosto z workflow w n8n

n8n wywołuje REST API volai przez węzeł HTTP Request - bez pisania kodu wyślą Państwo SMS, uruchomią połączenie przez agenta głosowego i otrzymają wynik z powrotem webhookiem.

1Zapisanie klucza jako credential

W n8n należy utworzyć nowy credential typu HTTP Header Auth: nazwa headera Authorization, wartość Bearer vk_TWOJ_KLUCZ (klucz znajdą Państwo w portalu w sekcji Asystent AI). Trzeba go przypisać każdemu węzłowi HTTP Request, który wywołuje volai.cz/v1/* - ten sam klucz obowiązuje dla SMS, połączeń i webhooka.

2Wysłanie SMS z workflow

Należy dodać węzeł HTTP Request: metoda POST, adres https://volai.cz/v1/messages, treść JSON z polami to i body. Odpowiedź zawiera priceHal (cenę w setnych częściach waluty rozliczeniowej za wszystkie segmenty wiadomości) oraz segments - tekst z polskimi znakami zajmuje więcej segmentów niż wiadomość w samym ASCII. Dlatego w poniższym przykładzie treść wiadomości celowo nie ma znaków diakrytycznych, by mieściła się w jednym segmencie - ze znakami diakrytycznymi działa tak samo, tylko zużywa więcej segmentów.

bash
curl -X POST https://volai.cz/v1/messages \
  -H "Authorization: Bearer vk_TWOJ_KLUCZ" \
  -H "Content-Type: application/json" \
  -d '{"to": "+420777123456", "body": "Zamowienie jest gotowe do odbioru."}'

3Połączenie z klientem przez własnego agenta

Drugi węzeł HTTP Request: POST https://volai.cz/v1/calls z polami to i agentId istniejącego agenta głosowego (można go utworzyć w portalu lub przez POST /v1/agents) - agent musi mieć przypisany własny numer, w przeciwnym razie żądanie zakończy się błędem agent_no_number. Żądanie tylko uruchamia połączenie i zwraca jego id - o faktycznym wyniku (zakończone, nieodebrane, nieudane) dowiedzą się Państwo z webhooka w następnym kroku.

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

4Ustawienie webhooka, by workflow dostał odpowiedź

Należy dodać trigger Webhook (n8n wygeneruje adres URL) i zapisać ten sam adres przez PUT /v1/webhook wraz z listą interesujących Państwa zdarzeń. Uwaga: pusta tablica events nie oznacza braku zdarzeń, tylko wszystkie - lepiej zawsze je wymienić. Odpowiedź zwraca też secret - należy go zapisać od razu, GET /v1/webhook już go nie zwróci.

bash
curl -X PUT https://volai.cz/v1/webhook \
  -H "Authorization: Bearer vk_TWOJ_KLUCZ" \
  -H "Content-Type: application/json" \
  -d '{"url": "https://twoj-n8n.app.n8n.cloud/webhook/volai", "events": ["call.completed", "message.sent"]}'

5Weryfikacja podpisu przed przetworzeniem treści

Każde żądanie niesie header Volai-Signature w postaci t=<unix>,v1=<hex>. W węźle Code należy obliczyć HMAC-SHA256 z {t}.{rawBody} przy użyciu własnego secret i porównać wynik z v1 - treść wolno przetwarzać dopiero wtedy, gdy się zgadzają. W węźle Webhook trzeba włączyć w sekcji Add Options opcję Raw Body - bez niej n8n od razu parsuje treść i bajty, z których liczono podpis, przepadają. Przy włączonej opcji treść dociera jednak jako dane binarne (właściwość data), a nie w json.body - dlatego poniższy kod czyta ją przez getBinaryDataBuffer, co działa niezależnie od tego, czy n8n trzyma dane binarne w pamięci, na dysku czy w S3. Wbudowany crypto można w węźle Code użyć tylko w self-hosted n8n z włączonym NODE_FUNCTION_ALLOW_BUILTIN=crypto - n8n Cloud w ogóle nie obsługuje importu modułów, więc weryfikacja nie zmieści się tam w jednym węźle. W Cloud należy więc wydłużyć łańcuch o węzeł Extract From File (operacja Extract From Text File) - zamieni dane binarne na tekst w wybranym polu (np. rawBody) - a dopiero potem węzeł Crypto (akcja Hmac, typ SHA256, kodowanie HEX, wartość jako wyrażenie łączące znacznik czasu z headera z polem rawBody, secret podany przez credential Crypto, a nie zwykłe pole tekstowe) policzy skrót bez pisania kodu; porównanie z v1 zakończy węzeł IF.

javascript
// Wejście z węzła Webhook z włączoną opcją Raw Body: header to wartość
// "Volai-Signature", np. "t=1756111640,v1=8f2ac1d4..."; surowa treść
// dociera jako dane binarne (domyślna nazwa właściwości "data"), a nie w json.body.
const header = $input.first().json.headers['volai-signature'];

// getBinaryDataBuffer działa we wszystkich trybach przechowywania danych binarnych n8n
// (domyślnie w pamięci, a także filesystem/S3) - bezpośredni odczyt
// $input.first().binary.data.data działałby tylko w trybie pamięciowym.
const rawBody = (await this.helpers.getBinaryDataBuffer(0, 'data')).toString('utf8');

// secret to wartość z kroku 4 (PUT /v1/webhook) - w produkcji należy ją czytać
// z credentiala n8n lub zmiennej środowiskowej, nigdy nie wpisywać na stałe
const secret = 'whsec_zastap_swoim';

const crypto = require('crypto'); // tylko self-hosted n8n, patrz tekst kroku

const [tPart, v1Part] = header.split(',');
const t = tPart.replace('t=', '');
const v1 = v1Part.replace('v1=', '');

const expected = crypto
  .createHmac('sha256', secret)
  .update(`${t}.${rawBody}`)
  .digest('hex');

if (expected !== v1) {
  throw new Error('Nieprawidłowy podpis Volai-Signature');
}

Co Państwo z tym zrobią

Potwierdzenie zamówienia przez SMS

Sklep internetowy lub system rezerwacji wysyła do n8n webhook o nowym zamówieniu - workflow od razu wysyła SMS z potwierdzeniem i szacowanym czasem odbioru.

Połączenie wychodzące z harmonogramu lub arkusza

Wiersz w Google Sheets, Airtable albo CRM uruchamia węzeł HTTP Request, który dzwoni do klienta przez Państwa agenta głosowego - przypomnienie o terminie, zachęta do dokończenia zamówienia, krótka ankieta.

Zapis wyniku połączenia z powrotem do systemu

Webhook call.completed przekazuje transkrypcję, podsumowanie i dane zebrane w trakcie rozmowy (data) - workflow zapisuje je w CRM, arkuszu albo wysyła na Slack, bez ręcznego odsłuchiwania nagrania.

Często zadawane pytania

Czy istnieje oficjalny węzeł n8n dla volai?
Jeszcze nie - na dziś wystarczą ogólne węzły HTTP Request i Webhook, które n8n zawsze ma pod ręką. Zweryfikowany węzeł społecznościowy musiałby przejść review w n8n Creator Portal - na razie go nie przygotowujemy.
Skąd mam wiedzieć, że webhook faktycznie wysłało volai, a nie ktoś obcy?
Po headerze Volai-Signature - to podpis HMAC-SHA256 z użyciem secret, który zwraca każde PUT /v1/webhook (należy go zapisać od razu, GET już go nie zwróci). Dokładny wzór wraz z przykładami w Pythonie i TypeScripcie jest pod adresem /docs/webhooky.
Co, jeśli HTTP Request zakończy się timeoutem i n8n ponowi żądanie?
Należy dodać header Idempotency-Key z dowolną stałą wartością (np. numerem zamówienia). W ciągu 24 godzin na powtórzone żądanie z tym samym kluczem otrzymają Państwo dokładnie tę samą odpowiedź - SMS ani połączenie nie zostaną wysłane po raz drugi.
Ile kosztuje automatyzacja w porównaniu z ręcznym wywoływaniem API?
Nic - za n8n nie ma żadnej dopłaty. Obowiązują te same stawki co w cenniku: SMS 1,36 kr (≈ 0,24 PLN), połączenie wychodzące 0,92 kr/min (≈ 0,16 PLN), agent głosowy dodatkowo 2,50 kr/min (≈ 0,45 PLN). Dokładny cennik jest pod adresem /cenik.

Proszę wypróbować od razu

Proszę się zarejestrować, a pierwsze 50 kr salda dostają Państwo od nas.