Webhooks

Webhooks

Webhooks let Daffy Voice talk to your systems during and after calls: push each call's result to your server, receive the transcript when a call ends, or hand your AI employee what you know about a caller before it says hello.

Three webhooks

Each one is set up in a different place and behaves differently. Pick the one that fits.

At a glance

Send resultsPOST · call.result
A step in a workflow. One structured result per contact called: outcome, notes, captured details, summary. Signed if you set a secret. Up to 3 attempts.
End-of-callPOST
Set on an AI employee. Fires after every call that AI employee handles, with the transcript and a sentiment-based outcome. Not signed. Up to 4 attempts.
Prefetch dataGET
Set on an AI employee. Called before each conversation starts; the JSON you return is given to the AI employee as context about the caller. Not signed. One attempt, 5-second timeout.

Which should I use?

For CRM updates and reporting on outbound calling, use Send results — it has the richest data and is the only one you can verify with a signature. Use end-of-call when you need the transcript, or for inbound calls that aren't part of a workflow.

Send results (call.result)

Add a Send results step to a workflow and paste your URL. Setup, Google Sheets and examples are in Send results to your tools; the payload is in Events & payloads.

AI employee webhooks

  1. Open the AI employee

    Go to AI employees, open one, and stay on the Identity tab.

  2. Fill in Webhook settings

    Paste a URL into Prefetch Data Webhook, End-of-Call Webhook, or both. Leave a field empty to turn that webhook off.

  3. Save

    The webhooks apply from the next call. They fire for phone calls (Twilio, Plivo, SIP) and website widget calls.

Prefetch data

Before the conversation starts, Daffy Voice sends a GET to your URL with the other party's number in caller_id (international format, URL-encoded). When the number isn't known it is unknown; for website widget calls it is web.

Request
GET https://crm.example.com/ubiq/prefetch?caller_id=%2B919876543210

Return any JSON with status 2xx. Daffy Voice adds it, pretty-printed, to the AI employee's instructions for this call inside a <caller_context> block, so it can greet the caller by name or mention their booking.

Your response
{
  "name": "Rahul Sharma",
  "customer_since": "2022",
  "plan": "Gold",
  "last_appointment": "2026-09-28, cleaning with Dr. Mehta",
  "balance_due": "₹1,200"
}
prefetch.mjs
import express from "express";

const app = express();

app.get("/ubiq/prefetch", async (req, res) => {
  const phone = req.query.caller_id; // "+9198…", "unknown" or "web"
  const customer = await findCustomerByPhone(phone); // your lookup
  if (!customer) return res.json({ known_customer: false });
  res.json({
    known_customer: true,
    name: customer.name,
    plan: customer.plan,
    balance_due: customer.balanceDue,
  });
});
  • You have 5 seconds. The caller is waiting while Daffy Voice asks, so answer fast — ideally well under a second.
  • There are no retries. On a timeout, error, non-2xx status or a body that isn't JSON, the call goes ahead without context.
  • Redirects aren't followed — use the final URL.
  • Keep it short and relevant. Everything you return is read by the AI employee on every turn of the call.

End-of-call

After a call ends, Daffy Voice sends a POST with the call ID, duration, transcript and an outcome. The fields are described in Events & payloads.

AI employee webhooks are not signed

Prefetch and end-of-call requests carry no signature header, so your server can't prove they came from Daffy Voice. Use a long, unguessable URL path (for example one containing a random token), serve it over HTTPS, and don't return sensitive data from a prefetch URL that someone else could call. If you need verified delivery, use Send results with a signing secret.

Delivery basics

  • Bodies are JSON, sent with Content-Type: application/json.
  • Any 2xx status counts as delivered. Respond quickly and do slow work afterwards.
  • Deliveries are not de-duplicated by an ID, so make your handler safe to run twice for the same call.
  • Your URL must be reachable from the public internet. For Send results, private and internal addresses are refused.

Next steps