Skip to main content

Documentation Index

Fetch the complete documentation index at: https://documentation.uponai.com/llms.txt

Use this file to discover all available pages before exploring further.

Webhooks push data to your application as events happen — no polling required.

Event Types

Voice Call Events

EventDescriptionPayload
call_startedNew call beginsBasic call information
call_endedCall completes, transfers, or errorsFull call object (excluding call_analysis)
call_analyzedCall analysis completeFull call data including call_analysis
transcript_updatedTurn-taking transcript updates + final update on call endFull call data + transcript_with_tool_calls
transfer_startedTransfer initiatedFull call data + transfer_destination and transfer_option
transfer_bridgedTransfer successfully bridgedFull call data + transfer_destination and transfer_option
transfer_cancelledTransfer cancelled or failedFull call data + transfer_destination and transfer_option
transfer_endedTransfer leg endsFull call data
If a call did not connect (e.g. dial_failed, dial_no_answer, dial_busy), call_started will NOT be triggered. call_ended and call_analyzed will still fire.

Chat Events

EventDescriptionPayload
chat_startedNew chat beginsBasic chat information
chat_endedChat completes or errorsFull chat object (excluding chat_analysis)
chat_analyzedChat analysis completeFull chat data including chat_analysis

Webhook Behavior

  • Timeout: 10 seconds. If no 2xx response is received, retried up to 3 times.
  • Ordering: Events fire in order but are non-blocking. A failed call_started won’t prevent call_ended from firing.
  • Expected response: Return a 2xx status code. No body required.

Event Filtering

Limit which events are delivered per agent using the webhook_events field when creating or updating an agent.
Agent typeDefault events
Voicecall_started, call_ended, call_analyzed
Chatchat_started, chat_ended, chat_analyzed

Webhook Types

TypeSetupScope
Account-levelDashboard → Webhooks tabAll agents under your account
Agent-levelwebhook_url field on agentThat agent only. When set, account-level webhook will NOT fire for that agent.

Sample Payloads

call_ended payload:
{
  "event": "call_ended",
  "call": {
    "call_type": "phone_call",
    "from_number": "+12137771234",
    "to_number": "+12137771235",
    "direction": "inbound",
    "call_id": "Jabr9TXYYJHfvl6Syypi88rdAHYHmcq6",
    "agent_id": "oBeDLoLOeuAbiuaMFXRtDOLriTJ5tSxD",
    "call_status": "registered",
    "start_timestamp": 1714608475945,
    "end_timestamp": 1714608491736,
    "disconnection_reason": "user_hangup",
    "transcript": "...",
    "retell_llm_dynamic_variables": {
      "customer_name": "John Doe"
    }
  }
}
transfer_started payload:
{
  "event": "transfer_started",
  "call": {
    "call_id": "Jabr9TXYYJHfvl6Syypi88rdAHYHmcq6"
  },
  "transfer_destination": {
    "number": "+12137771235",
    "extension": "1234"
  },
  "transfer_option": {
    "type": "warm_transfer",
    "showTransfereeAsCaller": true,
    "agentDetectionTimeoutMs": 15000
  }
}

Verify Webhooks

All requests include an x-retell-signature header (HMAC-SHA256). Verify using your UponAI API key:
Node
import { UponAI } from "uponai-sdk";
import express from "express";

const app = express();
// Use raw body — not JSON.stringify(req.body)
app.use(express.raw({ type: "application/json" }));

app.post("/webhook", (req, res) => {
  const rawBody = req.body.toString("utf-8");
  if (
    !UponAI.verify(
      rawBody,
      process.env.UPONAI_API_KEY,
      req.headers["x-retell-signature"],
    )
  ) {
    console.error("Invalid signature");
    return res.status(401).send();
  }

  const { event, call } = JSON.parse(rawBody);

  switch (event) {
    case "call_started":
      console.log("Call started", call.call_id);
      break;
    case "call_ended":
      console.log("Call ended", call.call_id);
      break;
    case "call_analyzed":
      console.log("Call analyzed", call.call_id);
      break;
    case "transcript_updated":
      console.log("Transcript updated", call.call_id);
      break;
    case "transfer_started":
    case "transfer_bridged":
    case "transfer_cancelled":
    case "transfer_ended":
      console.log("Transfer event", event, call.call_id);
      break;
    default:
      console.log("Unknown event:", event);
  }

  res.status(204).send();
});
You can also allowlist UponAI’s IP address: 100.20.5.228.

Local Testing

Use ngrok to expose a local endpoint for webhook testing during development.

Privacy

If you enable Opt-Out of Personal and Sensitive Data Storage, transcripts and recordings won’t be stored post-call. However, they remain accessible via webhooks for up to 10 minutes via the recording_url field.