Implement Retell AI webhook signature validation and event handling. Use when setting up webhook endpoints, implementing signature verification, or handling Retell AI event notifications securely. Trigger with phrases like "retellai webhook", "retellai events", "retellai webhook signature", "handle retellai events", "retellai notifications".
Scanned 9/10/2026
Install to Claude Code
npx -y skills add micsapp/micstec-skills --skill retellai-webhooks-events --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Retellai Webhooks Events?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/micsapp-retellai-webhooks-events)More formats (shields.io, HTML) on the badges page.
---
name: retellai-webhooks-events
description: |
Implement Retell AI webhook signature validation and event handling.
Use when setting up webhook endpoints, implementing signature verification,
or handling Retell AI event notifications securely.
Trigger with phrases like "retellai webhook", "retellai events",
"retellai webhook signature", "handle retellai events", "retellai notifications".
allowed-tools: Read, Write, Edit, Bash(curl:*)
version: 1.0.0
license: MIT
author: Jeremy Longshore <jeremy@intentsolutions.io>
compatible-with: claude-code, codex, openclaw
---
# Retell AI Webhooks & Events
## Overview
Handle Retell AI webhooks for real-time voice call lifecycle events. Retell AI fires webhooks when calls start, end, or encounter events during conversation.
## Prerequisites
- Retell AI account with API access
- Retell AI API key stored in `RETELL_API_KEY` environment variable
- HTTPS endpoint for receiving webhook deliveries
- Voice agent configured in Retell AI dashboard
## Webhook Event Types
| Event | Trigger | Payload |
|-------|---------|---------|
| `call_started` | AI agent picks up | Call ID, agent ID, from/to numbers |
| `call_ended` | Call completes | Call ID, duration, end reason, transcript |
| `call_analyzed` | Post-call analysis done | Sentiment, summary, custom data |
| `agent_transfer` | Transfer to human | Call ID, transfer number, context |
| `voicemail_detected` | Voicemail reached | Call ID, voicemail status |
| `call_error` | Call fails | Error code, error message |
## Instructions
### Step 1: Configure Webhook Endpoint
```typescript
import express from "express";
import crypto from "crypto";
const app = express();
app.post("/webhooks/retellai",
express.raw({ type: "application/json" }),
async (req, res) => {
const signature = req.headers["x-retell-signature"] as string;
const secret = process.env.RETELL_WEBHOOK_SECRET!;
const expected = crypto
.createHmac("sha256", secret)
.update(req.body)
.digest("hex");
if (!crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected))) {
return res.status(401).json({ error: "Invalid signature" }); # HTTP 401 Unauthorized
}
const event = JSON.parse(req.body.toString());
res.status(200).json({ received: true }); # HTTP 200 OK
await handleRetellEvent(event);
}
);
```
### Step 2: Route Call Events
```typescript
interface RetellWebhookPayload {
event: string;
call: {
call_id: string;
agent_id: string;
call_status: string;
from_number: string;
to_number: string;
duration_ms?: number;
transcript?: string;
call_analysis?: {
sentiment: string;
summary: string;
custom_analysis_data: Record<string, any>;
};
};
}
async function handleRetellEvent(payload: RetellWebhookPayload) {
switch (payload.event) {
case "call_started":
await handleCallStarted(payload.call);
break;
case "call_ended":
await handleCallEnded(payload.call);
break;
case "call_analyzed":
await handleCallAnalyzed(payload.call);
break;
case "agent_transfer":
await handleAgentTransfer(payload.call);
break;
}
}
```
### Step 3: Process Call Results
```typescript
async function handleCallEnded(call: any) {
const { call_id, duration_ms, transcript, from_number } = call;
const durationMin = Math.round(duration_ms / 60000); # 60000: 1 minute in ms
console.log(`Call ${call_id} ended: ${durationMin}min`);
await db.calls.create({
callId: call_id,
fromNumber: from_number,
duration: duration_ms,
transcript,
completedAt: new Date(),
});
if (transcript) {
await extractActionItems(call_id, transcript);
}
}
async function handleCallAnalyzed(call: any) {
const { call_id, call_analysis } = call;
const { sentiment, summary } = call_analysis;
if (sentiment === "negative") {
await alerting.send({
channel: "#customer-escalations",
message: `Negative call: ${call_id}\nSummary: ${summary}`,
});
}
await crmClient.logActivity({
callId: call_id,
sentiment,
summary,
});
}
```
### Step 4: Create Outbound Call via API
```bash
set -euo pipefail
curl -X POST https://api.retellai.com/v2/create-phone-call \
-H "Authorization: Bearer $RETELL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"from_number": "+11234567890", # 11234567890 = configured value
"to_number": "+10987654321", # 10987654321 = configured value
"agent_id": "agt_abc123",
"webhook_url": "https://api.yourapp.com/webhooks/retellai"
}'
```
## Error Handling
| Issue | Cause | Solution |
|-------|-------|----------|
| Invalid signature | Wrong webhook secret | Verify secret in Retell AI dashboard |
| No transcript | Short call or error | Check `end_reason` for early termination |
| Transfer failed | Invalid transfer number | Verify transfer number is active |
| Missing analysis | Analysis not configured | Enable post-call analysis in agent settings |
## Examples
### Post-Call Action Items
```typescript
async function extractActionItems(callId: string, transcript: string) {
const items = await llm.extract(transcript, "action_items");
for (const item of items) {
await taskManager.createTask({
title: item,
source: `Call: ${callId}`,
});
}
}
```
## Resources
- [Retell AI API Documentation](https://docs.retellai.com)
- [Retell AI Webhooks](https://docs.retellai.com/webhooks)
## Next Steps
For deployment setup, see `retellai-deploy-integration`.
## Output
- Configuration files or code changes applied to the project
- Validation report confirming correct implementation
- Summary of changes made and their rationaleIs this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!