Webhooks

Webhooks are the rawest integration Foan offers. We POST a JSON payload to a URL you provide, every time an event happens. You write the receiving code.

If you can't find a Foan integration that does what you need, webhooks are the escape hatch.

What it does

Same event stream as Zapier and Make, but delivered as raw HTTP POST instead of via a third-party automation platform.

Events you can subscribe to:

  • call.completed — every call (inbound + outbound)
  • call.inbound.completed
  • call.outbound.completed
  • complaint.flagged
  • booking.made
  • payment.completed
  • callback.requested

Each event POSTs JSON like:

{
  "event": "call.completed",
  "call_id": "01HXXX…",
  "direction": "inbound",
  "agent_id": "agent_abc",
  "caller": { "phone": "+447700900123", "name": "Sarah W" },
  "duration_seconds": 134,
  "intent": "booking",
  "summary": "Sarah booked the 9am Wednesday slot…",
  "transcript_url": "https://foan.me/api/calls/01HXXX/transcript",
  "completed_at": "2026-05-07T14:23:11Z"
}

Setting it up

  1. Pick a URL — your server, a Cloudflare Worker, an AWS Lambda, anything that accepts POST and returns 2xx.
  2. In /dashboard/integrations → Webhooks, paste the URL and pick the events to subscribe to.
  3. Foan signs every payload with HMAC-SHA256 — the secret is shown once at setup. Verify the signature on your end (X-Foan-Signature header).
  4. Test fires immediately so you know it's wired.

Multiple URLs are fine — one per environment, one per team, etc.

Verifying signatures

import crypto from 'crypto';

const expected = crypto
  .createHmac('sha256', process.env.FOAN_WEBHOOK_SECRET)
  .update(rawBody)
  .digest('hex');

const provided = req.headers['x-foan-signature'];
if (!crypto.timingSafeEqual(Buffer.from(provided), Buffer.from(expected))) {
  return res.status(401).end();
}

Retries

If your endpoint returns non-2xx or times out, we retry with exponential backoff: 1m, 5m, 30m, 2h, 6h. After 6 hours we give up and the event is permanently failed (visible in the dashboard).

Pricing

Webhooks are free — included in every Foan plan, no per-event charge.

Common questions

Latency? Within a few seconds of the event.

Order guarantee? We don't guarantee strict ordering across events. Within a single call, events are emitted in order; across calls, races are possible.

Idempotency? Each event has a unique ID — dedupe on that if your handler isn't naturally idempotent.

Replay? Coming soon. For now, contact us to replay a specific event.

TLS? HTTPS required. We won't POST to plain HTTP.

Last updated 7 May 2026