🔌 Integrations & Telephony

Webhooks 101 for Voice Agents

Webhooks are the backbone of voice agent integrations. When your voice agent needs to call a CRM, update a ticket, send an SMS, or trigger any external action, it does so via HTTP — and most of those HTTP calls are structured as webhooks or webhook-like REST operations.

Tyler Weitzman
Tyler Weitzman
March 25, 2026 · 7 min read
Speechify

Webhooks are the backbone of voice agent integrations. When your voice agent needs to call a CRM, update a ticket, send an SMS, or trigger any external action, it does so via HTTP — and most of those HTTP calls are structured as webhooks or webhook-like REST operations. Understanding how to design, secure, operate, and debug webhooks is foundational to building reliable voice agent systems. This isn't theoretical — a broken webhook is a broken voice agent.

This piece covers the practical side of webhooks for voice agent engineers: patterns, security, retries, observability, and the pitfalls that kill reliability.

TL;DR

  • Webhooks are HTTP POST requests triggered by events — in voice agents, typically outbound from the agent to external systems.
  • Design for idempotency, retries, and failure modes from day one.
  • Secure with signatures (HMAC) or OAuth; never just a shared secret in a URL.
  • Treat webhook delivery as a distributed systems problem: retries, queues, dead letters.
  • Observability is critical: log every request/response, monitor success rates.

What's a webhook

A webhook is an HTTP request triggered by an event. For voice agents:

  • Outbound webhook: your voice agent → external system ("create this ticket", "log this call").
  • Inbound webhook: external system → your voice agent ("this customer just signed up — call them").

Most voice agent integrations have both. The patterns are similar but the security and reliability considerations differ.

Outbound webhook patterns

Voice agent calls external APIs:

  • CRM actions — create contact, log call, update deal.
  • Messaging — send SMS or email follow-up.
  • Calendar — book, reschedule, cancel appointments.
  • Payment — initiate refunds, take payments (tokenized).
  • Ticketing — create or update tickets.
  • Analytics — log events to BI or data warehouse.
  • Notifications — Slack or Teams alerts for escalations.

Each is an HTTP POST (or sometimes PUT/PATCH/GET) from your voice agent infrastructure to the external service.

The function-calling bridge

In modern voice AI, webhooks are often triggered via LLM function calling:

  1. User says something.
  2. LLM decides a function should be called (e.g., book_appointment).
  3. Your code receives the function call, translates to HTTP request.
  4. HTTP request goes to external API.
  5. Response comes back.
  6. LLM incorporates the result into its next response.

The function definition and the webhook target are connected but not the same thing. The LLM doesn't know about HTTP directly — it calls a function that your code maps to an HTTP request.

See function calling for voice agents: a practical guide.

Idempotency

If a webhook fails, you retry. If the first attempt actually succeeded but you didn't see the response, retrying creates duplicates. Prevent with idempotency keys:

POST /crm/tickets
Idempotency-Key: call_4827_create_ticket_v1
{...}

Server-side: if an operation with the same idempotency key has already been processed, return the cached response instead of re-executing.

Not all APIs support idempotency keys natively. For those that don't, build application-level idempotency (e.g., check if a ticket with this external reference already exists).

Retry strategy

Webhooks fail for various reasons:

  • Network timeout.
  • Rate limit hit.
  • Server error (5xx).
  • Transient downstream issue.

Standard retry: exponential backoff with jitter.

  • 1st retry: 1 second.
  • 2nd retry: 3 seconds.
  • 3rd retry: 10 seconds.
  • 4th retry: 30 seconds.
  • 5th retry: 2 minutes.

Beyond 5 retries, give up or send to a dead-letter queue for manual review.

Don't retry on 4xx responses (except 429 rate limits) — these are client errors that won't succeed on retry.

Queue-based architecture

For reliability, voice agents should queue webhook operations rather than fire them inline:

Voice agent → queue → webhook worker → external API

Benefits:

  • Voice agent not blocked on webhook latency.
  • Retries happen async.
  • Queue provides backpressure on downstream rate limits.
  • Dead-letter queue handles permanent failures.

Common queue systems: SQS, RabbitMQ, Google Pub/Sub, Kafka.

Timing and latency

Voice agents are real-time. Webhooks with user-facing impact (e.g., "did this appointment book?") need fast response. Strategies:

  • Fast path webhooks — must respond in under 500ms for the caller to hear a confirmation.
  • Slow path webhooks — can be async (queue + worker); caller doesn't wait.
  • Optimistic responses — agent confirms, webhook runs; agent handles failure via follow-up call if needed.

Design each webhook for its latency profile.

Security: signatures

Webhooks should be authenticated. For outbound (voice agent → external), the external service usually provides auth (API key, OAuth). For inbound (external → voice agent), you authenticate them.

HMAC signatures. Incoming webhook includes a signature header:

X-Signature: sha256=abcdef1234567890...

Server computes: HMAC-SHA256(secret, request body). Compare to the provided signature. If match, authentic. If not, reject.

Most major webhook senders (Stripe, Twilio, Shopify, GitHub) use some variant of this.

Security: other patterns

  • IP allowlisting. Only accept webhooks from known sender IPs.
  • Shared secret in header. Simpler than HMAC, less secure.
  • OAuth. Heavier but strongest.
  • mTLS. For very sensitive integrations.

Use HMAC at minimum for any webhook that triggers meaningful actions.

Never trust incoming data

Even with authentication, validate incoming webhook payloads:

  • Schema validation.
  • Sanity checks (timestamps not in the future, amounts not negative, IDs reference real records).
  • Business-rule validation (operation allowed for this sender).

Attackers can sometimes forge webhooks even past basic auth. Validate.

Logging

Log every webhook operation:

  • Timestamp.
  • Direction (in/out).
  • Source or destination.
  • Event type.
  • Request body (sanitized of PII).
  • Response status.
  • Response time.
  • Error (if any).

Logs are how you debug when things go wrong.

Observability

Monitor:

  • Success rate per endpoint / event type.
  • Latency (p50, p95, p99).
  • Error rate with breakdown by error type.
  • Retry counts.
  • Dead-letter queue depth.

Set alerts on:

  • Success rate drops below threshold.
  • Latency p95 exceeds threshold.
  • Dead-letter queue has items > N.

Webhook debugging tips

When a webhook fails:

  1. Check your logs for the request and response.
  2. Verify the request payload matches expected schema.
  3. Check the destination API's logs (if accessible).
  4. Verify auth credentials are current.
  5. Try the request manually (cURL, Postman) to isolate.
  6. Check rate limit headers.
  7. Review recent changes on either side.

Webhook issues are usually one of: auth, schema, rate limit, or destination-side bug.

Versioning

Webhook schemas evolve. Version your outbound webhooks:

POST /hook/voice-events/v2

Or include a version header. Allow multiple versions in parallel during migration.

Don't break existing consumers with silent schema changes.

Testing webhooks

Development and testing tools:

  • ngrok or localtunnel — expose local dev server to internet for testing inbound webhooks.
  • Webhook.site — inspect webhook payloads during development.
  • Recorded replay — capture real webhook traffic, replay in tests.
  • Mock servers — simulate destination APIs for testing.

Common pitfalls

Synchronous fire-and-hope. No retries, no queue, no durability. Works in demos, fails in production.

No idempotency. Duplicate records, duplicate charges, duplicate messages.

Secrets in URLs. Shared secret in the URL path. Leaks in logs. Use headers.

Ignoring 429. Not respecting rate limits → rate limit worsens → cascade failure.

Silent failures. Webhook errors swallowed; no alerts. Fail loud, not silent.

Schema drift. External API adds required field; your webhook breaks silently.

Over-aggressive retries. Tight retry loops hammer the destination. Use exponential backoff.

Voice-agent-specific considerations

  • Low-latency calls need fast webhooks. Use dedicated fast-path infrastructure.
  • Caller-facing confirmations need reliable webhooks. Optimistic response + fallback.
  • Compliance events can't be lost. SMS sent, payment processed, PII disclosed — these need durability.
  • Observability in real-time. Not end-of-day batch — operations team needs minute-level visibility.

FAQ

What HTTP methods should webhooks use? POST for events (create). PUT/PATCH for updates. Rarely GET for queries.

How do we handle webhooks when the destination is down? Queue with exponential backoff. Dead-letter after N retries. Alert operations.

Should webhooks be synchronous or async? Async for most. Sync only when the caller needs immediate confirmation.

How do we version webhook schemas? URL path (/v1/, /v2/) or version header. Maintain both during migration periods.

What about webhook replay? Useful for recovery after incidents. Design idempotent consumers so replay is safe.

Tyler Weitzman
Tyler Weitzman
Co-Founder & Head of AI, Speechify

Tyler Weitzman is co-founder and Head of AI at Speechify. He has spent the past decade building the speech-synthesis stack that powers millions of users. Tyler writes about the engineering of real-time conversational systems — text-to-speech, speech recognition, latency budgets, model serving, and the architectural choices that separate prototypes from production-grade voice agents.

More from Tyler Weitzman

View all →

Related reading

Voice AI, twice a month.

Get the best of the SIMBA resources hub — new articles, trend notes, and operator guides. No spam.