Skip to main content
Webhooks allow your application to receive real-time notifications about events that occur in your Retell AI account. Instead of continuously polling our API, webhooks push data to your application as events happen, making your integrations more efficient and responsive.

Event Types

Retell AI supports the following webhook events for voice calls:
If the call did not connect (like dial failed), the call_started webhook event will not be triggered.
Event TypeDescriptionPayload
call_startedTriggered when a new call beginsBasic call information
call_endedTriggered when a call completes, transfers, or encounters an errorall fields from the call object except call_analysis.
call_analyzedTriggered when call analysis is completeFull call data including call_analysis object
transcript_updatedTriggered on turn-taking transcript updates, plus a final update when the call endsFull call data plus transcript_with_tool_calls
transfer_startedTriggered when a transfer is initiatedFull call data plus transfer_destination and transfer_option (if available)
transfer_bridgedTriggered when a transfer successfully bridgesFull call data plus transfer_destination and transfer_option (if available)
transfer_cancelledTriggered when a transfer is cancelled or fails to connectFull call data plus transfer_destination and transfer_option (if available)
transfer_endedTriggered when the transfer leg endsFull call data
Retell AI supports the following webhook events for chat:
Event TypeDescriptionPayload
chat_startedTriggered when a new chat beginsBasic chat information
chat_endedTriggered when a chat completes or errors outAll fields from the chat object except chat_analysis.
chat_analyzedTriggered when chat analysis is completeFull chat data including chat_analysis object

Common Use Cases

  1. Real-time Analytics
    • Track call statistics and performance metrics
    • Monitor call volumes and patterns
    • Trigger alerts for specific call outcomes
  2. System Integration
    • Update CRM records when calls complete
    • Trigger workflow automations based on call analysis
    • Archive call transcripts in your data warehouse
  3. Call Monitoring
    • Get notified of failed or transferred calls
    • Track call duration and completion status
    • Monitor agent performance in real-time

Webhook Spec

The webhook will POST the payload to your endpoint. The webhook has a timeout of 10 seconds. If within 10 seconds no success status (2xx) is received, the webhook will be retried, up to 3 times. The webhook will be triggered in order, but is not blocking. For example, if the webhook for call_started is not successful, we can still trigger call_ended webhook. When the call did not connect (like calls with dial_failed, dial_no_answer, dial_busy disconnection reason), it will not have its call_started webhook triggered. It will still have its call_ended and call_analyzed webhook triggered.

Request payload

The webhook will contain the event type and the call object. See a sample payload in the “Handle Webhook” section below.

Event filtering

You can limit which events are delivered per agent using the webhook_events field when creating or updating an agent.
  • Voice agent default: call_started, call_ended, call_analyzed
  • Chat agent default: chat_started, chat_ended, chat_analyzed
This is useful when you only need high-signal events and want to reduce webhook traffic.

Register Webhook

We offer two types of webhooks: Agent-Level and Account-Level, designed to streamline your event notification process. Here’s a brief on each:

Account-level webhooks

Set up through the dashboard’s webhooks tab, these webhooks notify you of events related to any agent under your account. Specify your webhook URL in the dashboard’s webhooks tab to activate.

Agent-level webhooks

When you create the agent, you can set webhook_url field. Any event associated with that agent will be pushed to the agent webhooks url. If set, account level webhooks url will not be triggered for that agent.

Handle Webhook

After registering the webhook, you would want to verify the webhook is from Retell and handle it.

Webhook Payload

The webhook will be POST to the URL you provided with a JSON payload. The payload will contain the event type and the call detail associated with the event. It will contain a x-retell-signature header to help you verify the webhook comes from Retell.

Sample Payload

The call field in the webhook payload contains the call details. It’s the same content you would receive when you fetch the call details using the get-call API.
{
  "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",
    "metadata": {},
    "retell_llm_dynamic_variables": {
      "customer_name": "John Doe"
    },
    "start_timestamp": 1714608475945,
    "end_timestamp": 1714608491736,
    "disconnection_reason": "user_hangup",
    "transcript": "...",
    "transcript_object": [ [Object], [Object], [Object], [Object] ],
    "transcript_with_tool_calls": [ [Object], [Object], [Object], [Object] ],
    "opt_out_sensitive_data_storage": false
  }
}
If metadata and retell_llm_dynamic_variables are not provided, they will be omitted from the webhook event payload. For transcript_updated events, the payload also includes transcript_with_tool_calls. For transfer events, the payload includes transfer_destination and (when available) transfer_option.

Sample Transfer event payload

Here is a compact example of a transfer webhook payload (fields may vary by transfer type):
{
  "event": "transfer_started",
  "call": {
    "call_id": "Jabr9TXYYJHfvl6Syypi88rdAHYHmcq6"
  },
  "transfer_destination": {
    "number": "+12137771235",
    "extension": "1234"
  },
  "transfer_option": {
    "type": "warm_transfer",
    "showTransfereeAsCaller": true,
    "publicHandoffOption": {
      "type": "static_message",
      "message": "Hi, I am transferring the caller now."
    },
    "agentDetectionTimeoutMs": 15000,
    "onHoldMusic": {
      "type": "default"
    },
    "enableBridgeAudioCue": true
  }
}

Verifying Webhook

You can use the x-retell-signature header together with your Retell API Key to verify the webhook. We have provided verify function in our SDKs to help you with this. You can also check and allowlist Retell IP addresses: 100.20.5.228. The following code snippets demonstrate how to verify and handle the webhook in Node.js and Python.

Sample Code

// install the sdk: https://docs.retellai.com/get-started/sdk
import { Retell } from "retell-sdk";
import express, { Request, Response } from "express";

const app = express();
app.use(express.json());

app.post("/webhook", (req: Request, res: Response) => {
  if (
    !Retell.verify(
      JSON.stringify(req.body),
      process.env.RETELL_API_KEY,
      req.headers["x-retell-signature"] as string,
    )
  ) {
    console.error("Invalid signature");
    return;
  }
  const {event, call} = req.body;
  switch (event) {
    case "call_started":
      console.log("Call started event received", call.call_id);
      break;
    case "call_ended":
      console.log("Call ended event received", call.call_id);
      break;
    case "call_analyzed":
      console.log("Call analyzed event received", call.call_id);
      break;
    case "transcript_updated":
      console.log("Transcript updated event received", call.call_id);
      break;
    case "transfer_started":
    case "transfer_bridged":
    case "transfer_cancelled":
    case "transfer_ended":
      console.log("Transfer event received", event, call.call_id);
      break;
    default:
      console.log("Received an unknown event:", event);
  }
  // Acknowledge the receipt of the event
  res.status(204).send();
});

Testing Locally

To test webhooks on your local machine, you can use ngrok to generate a production url forwarding requests to your local endpoints.

Privacy

Choosing to “Opt-Out of Personal and Sensitive Data Storage” means transcripts and recordings post-call won’t be stored. However, transcripts and recording remain accessible via webhooks, allowing for alternative storage solutions on your end. The recording will also be available in the recording_url field. The link will be accessible for 10 minutes and will be deleted and become inaccessible after 10 minutes.

Response

We expect a successful status code (2xx) to be returned. No body is expected.

Video Tutorial

See community templates in docs