# Receiving voice call webhooks reliably · Vaakyo

> How to receive Vaakyo call webhooks: verifying HMAC signatures, handling retries, idempotent processing and what to do with each event.

Source: https://vaakyo.com/blog/reliable-call-webhooks

[← Blog](https://vaakyo.com/blog)

# Webhooks for call results: signatures, retries and idempotency

Every finished call can update your CRM, order system or sheet. Here is how to receive call webhooks safely and reliably.

The Vaakyo team 28 September 2026 2 min read

-   Webhooks
-   Engineering

A voice agent is only as useful as what happens after the call. Webhooks deliver each call's outcome to your systems the moment it ends: the status, duration, transcript, summary, extracted fields and cost.

## Verify the signature

Anyone can send a POST to your endpoint, so check that each request really comes from Vaakyo. Every webhook carries an `X-Voxa-Signature` header of the form `t=<unix seconds>,v1=<hex HMAC-SHA256>`. The signature is an HMAC-SHA256 of `<t>.<raw request body>`, keyed with your webhook secret:

 `import hashlib, hmac, time   def verify(raw_body: bytes, header: str, secret: str, tolerance: int = 300) -> bool:     parts = dict(p.split("=", 1) for p in header.split(","))     timestamp, signature = parts.get("t", ""), parts.get("v1", "")     if not timestamp.isdigit() or abs(time.time() - int(timestamp)) > tolerance:         return False  # too old: a replay     expected = hmac.new(secret.encode(), f"{timestamp}.".encode() + raw_body, hashlib.sha256).hexdigest()     return hmac.compare_digest(expected, signature)`

Compute it over the raw body exactly as received, before parsing JSON.

## Answer fast, work later

Return a 2xx within a few seconds, then do the work in the background (a queue, a job). If your endpoint is slow or failing, Vaakyo retries, so a long-running handler risks receiving the same event again while it's still processing.

## Expect duplicates

Retries mean you may receive an event more than once. Make processing idempotent: use the call id (and the event type) as a key, and skip work you've already done.

## Choose the events you need

You don't need every event. For most integrations, the end-of-call event with the results is enough; add live events (call started, transfer, tool calls) only if you show them in real time somewhere.

## Map results to actions

Decide in advance what each outcome does:

-   A confirmed COD order is released for shipping.
-   A booked appointment is written to the calendar and an SMS goes out.
-   A hot lead is assigned to a salesperson.
-   A failed call is retried, or flagged for a person.

## Watch the delivery log

The console's webhook log shows every delivery with its response code and timing, and lets you resend one. When an integration breaks, start there.

[Read next Running outbound campaigns from a CSV: pacing, retries and calling hours](https://vaakyo.com/blog/outbound-campaigns-from-csv)

## Get started **today**

### Talk to an expert

Tell us about your calls. We'll help you plan the agent, the numbers and the rollout for your team.

[Contact sales](https://vaakyo.com/contact#sales)

### Start building

Build an agent and talk to it in your browser in minutes. New workspaces start with ₹250 of free credits.

[Start free](https://console.vaakyo.com/signup)

---

More for agents: https://vaakyo.com/llms.txt · Docs: https://docs.vaakyo.com · Sitemap: https://vaakyo.com/sitemap-index.xml
