SMS and calls straight from your n8n workflow
n8n calls the volai REST API through its HTTP Request node - no code required to send an SMS, place a call through a voice agent, and get the result back as a webhook.
1Save your key as a credential
In n8n, create a new HTTP Header Auth credential: header name Authorization, value Bearer vk_YOUR_KEY (find the key in the portal under API and MCP). Attach it to every HTTP Request node that calls volai.cz/v1/* - the same key covers SMS, calls, and the webhook.
2Send an SMS from the workflow
Add an HTTP Request node: method POST, URL https://volai.cz/v1/messages, JSON body with to and body. The response includes priceHal (the price in CZK cents, 1/100 CZK, for all segments) and segments - a message with non-ASCII characters uses more segments than a plain ASCII one. The example below leaves the message text without accents on purpose, to stay within a single segment - it works exactly the same with accents, just at the cost of an extra segment.
curl -X POST https://volai.cz/v1/messages \
-H "Authorization: Bearer vk_TVUJ_KLIC" \
-H "Content-Type: application/json" \
-d '{"to": "+420777123456", "body": "Objednavka je pripravena k vyzvednuti."}'3Call a customer through your agent
A second HTTP Request node: POST https://volai.cz/v1/calls with to and the agentId of an existing voice agent (create one in the portal or via POST /v1/agents) - the agent must have a phone number assigned, otherwise the request fails with agent_no_number. The request only starts the call and returns its id - the actual outcome (completed, no answer, failed) comes from the webhook in the next step.
curl -X POST https://volai.cz/v1/calls \
-H "Authorization: Bearer vk_TVUJ_KLIC" \
-H "Content-Type: application/json" \
-d '{"to": "+420777123456", "agentId": "ag_kx91fa2b"}'4Set a webhook so the workflow gets a reply
Add a Webhook trigger (n8n generates a URL for you) and save that same address with PUT /v1/webhook, along with the list of events you care about. Watch out: an empty events array doesn't mean none - it means all of them. List the ones you want. The response also returns a secret - save it right away, GET /v1/webhook never returns it.
curl -X PUT https://volai.cz/v1/webhook \
-H "Authorization: Bearer vk_TVUJ_KLIC" \
-H "Content-Type: application/json" \
-d '{"url": "https://tvuj-n8n.app.n8n.cloud/webhook/volai", "events": ["call.completed", "message.sent"]}'5Verify the signature before processing the body
Every request carries a Volai-Signature header shaped like t=<unix>,v1=<hex>. In a Code node, compute HMAC-SHA256 over {t}.{rawBody} with your secret and compare it to v1 - only process the body once they match. In the Webhook node, turn on the Raw Body option under Add Options - without it, n8n parses the body for you and the exact bytes the signature was computed over are gone. With it on, the body arrives as binary data instead (property data), not in json.body - the code below reads it through getBinaryDataBuffer, which works whether n8n stores binary data in memory, on disk, or in S3. The built-in crypto module works in the Code node only on self-hosted n8n with NODE_FUNCTION_ALLOW_BUILTIN=crypto enabled - n8n Cloud doesn't support module imports at all, so verification there doesn't fit in a single node. On Cloud, extend the chain with an Extract From File node (the Extract From Text File operation) - it converts the binary to text in a field of your choice (say, rawBody) - and only then a Crypto node (the Hmac action, type SHA256, HEX encoding, value an expression joining the timestamp from the header with the rawBody field, the secret entered through a Crypto credential rather than a plain text field) computes the digest with no code; an IF node finishes the comparison against v1.
// Vstup z uzlu Webhook se zapnutou volbou Raw Body: header je hodnota
// "Volai-Signature", např. "t=1756111640,v1=8f2ac1d4..."; syrové tělo
// dorazí jako binární data (výchozí název vlastnosti "data"), ne v json.body.
const header = $input.first().json.headers['volai-signature'];
// getBinaryDataBuffer funguje ve všech režimech ukládání binárek n8n
// (výchozí v paměti i filesystem/S3) - přímé čtení
// $input.first().binary.data.data by fungovalo jen v paměťovém režimu.
const rawBody = (await this.helpers.getBinaryDataBuffer(0, 'data')).toString('utf8');
// secret je hodnota z kroku 4 (PUT /v1/webhook) - v produkci ji čti
// z n8n credentialu nebo proměnné prostředí, nikdy nepiš natvrdo
const secret = 'whsec_nahrad_svym';
const crypto = require('crypto'); // jen self-hosted n8n, viz text 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('Neplatný podpis Volai-Signature');
}What you can do with it
Order confirmation by SMS
Your store or booking system sends a webhook to n8n on a new order - the workflow immediately sends a confirmation SMS with the estimated pickup time.
Outbound calls from a scheduler or spreadsheet
A row in Google Sheets, Airtable, or your CRM triggers an HTTP Request node that calls the customer through your voice agent - an appointment reminder, an abandoned-cart nudge, a short survey.
Writing call results back into your system
The call.completed webhook carries the transcript, summary, and any data the agent captured (data) - the workflow writes it into your CRM, a spreadsheet, or Slack, with no one listening to the recording by hand.
Frequently asked questions
- Is there an official n8n node for volai?
- Not yet - the generic HTTP Request and Webhook nodes, always built into n8n, are enough today. A verified community node would need to go through n8n's Creator Portal review - we are not preparing one yet.
- How do I know a webhook really came from volai, not someone else?
- Check the
Volai-Signatureheader - an HMAC-SHA256 signature using thesecretthat comes back on everyPUT /v1/webhookcall (save it right away,GETnever returns it). The full formula, with Python and TypeScript examples, is on/en/docs/webhooks. - What if the HTTP Request node times out and n8n retries it?
- Add an
Idempotency-Keyheader with any stable value, such as your order ID. Within 24 hours, a repeated request with the same key returns the exact same response - no second SMS, no second call. - Does automating this through n8n cost extra?
- No - there's no surcharge for using n8n. The same pricing applies as on the pricing page: SMS 1.36 CZK (~EUR 0.06), outbound calls 0.92 CZK/min (~EUR 0.04), the built-in voice agent adds 2.50 CZK/min (~EUR 0.10). Full pricing is at
/en/pricing.