Agent Native

setup-webhook

This skill configures webhook endpoints to receive real-time events from Vapi during calls, including transcripts, tool calls, and call summaries.

by VapiOfficial publisherNot reviewed

Identity proven by GitHub's verified organisation badge (VapiAI)

Agents
Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode
License
MIT (permissive)
Pin
ecd56bdpinned Oct 9, 2026
Context cost
about 2,000 tokenswhen the skill loads
GitHub stars
66on vapiai/skills
Scripts
None found

What it does

“Configure Vapi server URLs and webhooks to receive real-time call events, transcripts, tool calls, and end-of-call reports. Use when setting up webhook endpoints, building tool servers, or integrating Vapi events into your application.”
The author's description, from SKILL.md

Generated summary from the skill's own text

This skill configures webhook endpoints to receive real-time events from Vapi during calls, including transcripts, tool calls, and call summaries. It provides setup instructions for assistants, phone numbers, and organization-level URLs, along with example webhook servers in Express.js and Python that handle different event types. The skill also covers webhook authentication using Vapi credentials and local development techniques for testing.

When to use it

  • Building a webhook server to receive Vapi call events and transcripts
  • Implementing dynamic assistant configuration based on caller information
  • Handling tool calls from Vapi assistants and returning results
  • Processing end-of-call reports and call analytics

When not to

  • Creating Vapi assistants or phone numbers without webhooks
  • Integrating with services that do not support HTTP webhooks

Install

These commands install from the publisher's repository and need no account.

skills CLI

npx skills add vapiai/skills --skill setup-webhook

Installs from the repository's default branch, which may have changed since the commit we checked.

GitHub CLI 2.90 or later

gh skill install vapiai/skills setup-webhook@ecd56bd32688be8ea6fe54029445b536333d8d9c

Installs the commit we checked (ecd56bd).

Copy by hand

Download the folder at ecd56bd and put it in .claude/skills/setup-webhook for Claude Code and in .agents/skills/setup-webhook for Codex, Cursor, Gemini CLI, GitHub Copilot and OpenCode.

Skill folder on GitHub at ecd56bd

Copy for your agent

A prompt for any coding agent. It installs this skill from GitHub at the pinned commit, copies the files as they are, and runs nothing unless you ask.

Prompt

Install the agent skill "setup-webhook" by Vapi.

Source, pinned to commit ecd56bd32688be8ea6fe54029445b536333d8d9c:
https://github.com/vapiai/skills/tree/ecd56bd32688be8ea6fe54029445b536333d8d9c/setup-webhook

1. Download that folder at exactly this commit. Do not use the default branch.
2. Copy every file unchanged, keeping the folder structure, into .claude/skills/setup-webhook/ for Claude Code and .agents/skills/setup-webhook/ for Codex, Cursor, Gemini CLI, GitHub Copilot and OpenCode. Create the folders if they do not exist.
3. Do not edit the files, and do not run any script in the folder unless I ask you to.
4. When you are done, list the files you copied and where you put them.

Listing and checks: https://www.agentnative.dev/skills/vapi/setup-webhook-skills

SKILL.md at the pin

---
name: setup-webhook
description: Configure Vapi server URLs and webhooks to receive real-time call events, transcripts, tool calls, and end-of-call reports. Use when setting up webhook endpoints, building tool servers, or integrating Vapi events into your application.
license: MIT
compatibility: Requires internet access and a Vapi API key (VAPI_API_KEY).
metadata:
  author: vapi
  version: "1.0"
---

# Vapi Webhook / Server URL Setup

Configure server URLs to receive real-time events from Vapi during calls — transcripts, tool calls, status changes, and end-of-call reports.

> **Setup:** Ensure `VAPI_API_KEY` is set. See the `setup-api-key` skill if needed.

## Overview

Vapi uses "Server URLs" (webhooks) to communicate with your application. Unlike traditional one-way webhooks, Vapi server URLs support bidirectional communication — your server can respond with data that affects the call.

## Where to Set Server URLs

### On an Assistant

```bash
curl -X PATCH https://api.vapi.ai/assistant/{id} \
  -H "Authorization: Bearer $VAPI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "server": {
      "url": "https://your-server.com/vapi/webhook",
      "credentialId": "cred_abc123"
    }
  }'
```

Create the optional `credentialId` in **Dashboard > Custom Credentials**. Omit it only for a deliberately public endpoint.

### On a Phone Number

Phone-number updates also use a `server` object with `url` and optional `credentialId`. When updating through the API, first retrieve the number and preserve its existing `provider` discriminator in the PATCH body. The dashboard is the safest choice when the provider is unknown.

### At the Organization Level

Set a default server URL in the Vapi Dashboard under **Settings > Server URL**.

Priority order: Tool server URL > Assistant server URL > Phone Number server URL > Organization server URL.

## Event Types

| Event | Description | Expects Response? |
|-------|-------------|-------------------|
| `assistant-request` | Request for dynamic assistant config | Yes — return assistant config |
| `tool-calls` | Assistant is calling a tool | Yes — return tool results |
| `status-update` | Call status changed | No |
| `transcript` | Real-time transcript update | No |
| `end-of-call-report` | Call completed with summary | No |
| `hang` | Assistant failed to respond | No |
| `speech-update` | Speech activity detected | No |

## Webhook Server Example (Express.js)

```typescript
import express from "express";
const app = express();
app.use(express.json());

app.post("/vapi/webhook", (req, res) => {
  const { message } = req.body;

  switch (message.type) {
    case "assistant-request":
      // Dynamically configure the assistant based on the caller
      res.json({
        assistant: {
          name: "Dynamic Assistant",
          firstMessage: `Hello ${message.call.customer?.name || "there"}!`,
          model: {
            provider: "openai",
            model: "gpt-4.1",
            messages: [
              { role: "system", content: "You are a helpful assistant." },
            ],
          },
          voice: { provider: "vapi", voiceId: "Elliot", version: 2 },
          transcriber: { provider: "deepgram", model: "nova-3", language: "en" },
        },
      });
      break;

    case "tool-calls":
      // Handle tool calls from the assistant
      const results = (message.toolCallList || []).map((toolCall: any) => ({
        toolCallId: toolCall.id,
        result: handleToolCall(
          toolCall.name,
          toolCall.parameters || toolCall.arguments
        ),
      }));
      res.json({ results });
      break;

    case "end-of-call-report":
      // Process the call report
      console.log("Call ended:", {
        callId: message.call.id,
        endedReason: message.endedReason,
        cost: message.cost,
        analysis: message.analysis,
        artifact: message.artifact,
      });
      res.json({});
      break;

    case "status-update":
      console.log("Call status:", message.status);
      res.json({});
      break;

    case "transcript":
      console.log(`[${message.role}]: ${message.transcript}`);
      res.json({});
      break;

    default:
      res.json({});
  }
});

function handleToolCall(name: string, args: any): string {
  // Implement your tool logic here
  return `Result for ${name}`;
}

app.listen(3000, () => console.log("Webhook server running on port 3000"));
```

## Webhook Server Example (Python / Flask)

```python
from flask import Flask, request, jsonify

app = Flask(__name__)

@app.route("/vapi/webhook", methods=["POST"])
def vapi_webhook():
    data = request.json
    message = data.get("message", {})
    msg_type = message.get("type")

    if msg_type == "assistant-request":
        return jsonify({
            "assistant": {
                "name": "Dynamic Assistant",
                "firstMessage": "Hello! How can I help?",
                "model": {
                    "provider": "openai",
                    "model": "gpt-4.1",
                    "messages": [
                        {"role": "system", "content": "You are a helpful assistant."}
                    ],
                },
                "voice": {"provider": "vapi", "voiceId": "Elliot", "version": 2},
                "transcriber": {"provider": "deepgram", "model": "nova-3", "language": "en"},
            }
        })

    elif msg_type == "tool-calls":
        results = []
        for tool_call in message.get("toolCallList", []):
            results.append({
                "toolCallId": tool_call["id"],
                "result": f"Handled {tool_call['name']}",
            })
        return jsonify({"results": results})

    elif msg_type == "end-of-call-report":
        print(f"Call ended: {message['call']['id']}")
        print(f"Summary: {message.get('analysis', {}).get('summary')}")

    return jsonify({})

if __name__ == "__main__":
    app.run(port=3000)
```

## Webhook Authentication

Use a Vapi Custom Credential and place its ID in `server.credentialId`. Vapi supports Bearer Token, OAuth 2.0 client credentials, and HMAC credentials. Verify requests according to the credential you configured; HMAC header names, algorithms, timestamps, and payload formats are configurable, so do not assume a fixed `x-vapi-signature` format.

For a bearer credential, compare the incoming `Authorization: Bearer <token>` value with the token stored securely by your server. Never put the secret itself in an assistant or phone-number payload.

## Local Development

Use the Vapi CLI with a public tunnel. The CLI forwards from port 4242 to your app, but it does not create the public URL itself:

```bash
# Install the CLI
curl -sSL https://vapi.ai/install.sh | bash

# Terminal 1: expose the CLI listener
ngrok http 4242

# Terminal 2: forward events from the CLI to your app
vapi listen --forward-to localhost:3000/vapi/webhook
```

Set the Vapi server URL to the public ngrok URL. To skip the CLI and tunnel directly to the Express or Flask server instead:

```bash
ngrok http 3000
# Copy the ngrok URL and set it as your server URL
```

## End-of-Call Report Fields

The `end-of-call-report` event includes:

| Field | Description |
|-------|-------------|
| `call` | Full call object with metadata |
| `endedReason` | Why the call ended |
| `artifact` | Recording, transcript, messages, and other enabled artifacts |
| `analysis` | Configured summaries, structured data, and success evaluation |
| `cost` | Total call cost |
| `startedAt` / `endedAt` | Call timing, when included |

## References

- [Common Server URL Events](references/webhook-events.md) — Common event payloads and responses
- [Setting Server URLs](https://docs.vapi.ai/server-url/setting-server-urls) — Placement and priority
- [Server Authentication](https://docs.vapi.ai/server-url/server-authentication) — Custom Credentials
- [Local Development](https://docs.vapi.ai/server-url/developing-locally) — Testing webhooks locally

## Additional Resources

Vapi provides a **documentation MCP server** that gives compatible AI agents access to the Vapi knowledge base. Use its documentation search for advanced configuration, troubleshooting, SDK details, and anything beyond this skill.

To add the Vapi documentation MCP server manually in Claude Code, run:
```bash
claude mcp add vapi-docs -- npx -y mcp-remote https://docs.vapi.ai/_mcp/server
```

See the [Vapi MCP integration guide](https://docs.vapi.ai/cli/mcp) for setup instructions across supported agents.

From vapiai/skills at ecd56bd, shown as plain text under its license: MIT (permissive). The license text is in setup-webhook/SKILL.md.

View SKILL.md on GitHub at ecd56bd

Files

2 files, 12 KB in total. Each file has a sha256 in the pin's manifest; the first 12 characters are shown.

Skill folder on GitHub at ecd56bd
All 24 skills from Vapi

More from Vapi

  • create-assistant

    Designs and creates Vapi voice assistants for phone and web by managing system prompts, provider selection, tool integration, and API validation.

    Claude Code, Codex, Cursor +4 · about 2.3K tokens · pinned 6 days ago

  • create-assistant

    This skill designs and creates Vapi voice assistants for phone and web calls.

    Claude Code, Codex, Cursor +4 · about 2.3K tokens · pinned 6 days ago

  • create-call

    This skill creates one-off outbound phone calls, web calls, and batch calls via the Vapi API.

    Claude Code, Codex, Cursor +4 · about 1.5K tokens · pinned 6 days ago

  • create-call

    This skill enables agents to create outbound phone calls, web calls, and batch calls via the Vapi API.

    Claude Code, Codex, Cursor +4 · about 1.5K tokens · pinned 6 days ago

  • create-campaign

    This skill enables agents to create, manage, and diagnose Vapi outbound campaigns for reaching multiple contacts with personalized calls using the…

    Claude Code, Codex, Cursor +4 · about 3.1K tokens · pinned 6 days ago

  • create-campaign

    This skill creates, manages, and monitors Vapi outbound calling campaigns for multi-contact operations.

    Claude Code, Codex, Cursor +4 · about 3.1K tokens · pinned 6 days ago

All Backend and APIs skills
  • databricks-apps-python

    Enables agents to build Python backends for Databricks Apps using FastAPI, Flask, Dash, Streamlit, Gradio, or Reflex.

    by DatabricksOfficial publisher

    Contains scripts

    Claude Code, Codex, Cursor +3 · about 2.9K tokens · pinned 6 days ago

  • setup-webhook

    This skill configures Vapi server URLs and webhooks to receive real-time events from voice calls, including transcripts, tool calls, and end-of-call reports.

    by VapiOfficial publisher

    Contains scripts

    Claude Code, Codex, Cursor +3 · about 2K tokens · pinned 6 days ago

  • speech-engine

    This skill integrates ElevenLabs Speech Engine to add real-time voice conversations to custom agent runtimes.

    by ElevenLabsOfficial publisher

    Claude Code, Codex, Cursor +4 · about 2.4K tokens · pinned 6 days ago

  • airflow-plugins

    Builds Airflow 3.1+ plugins that embed FastAPI apps, custom UI pages, React components, middleware, macros, and operator links directly into the Airflow UI…

    by AstronomerOfficial publisher

    Claude Code, Codex, Cursor +4 · about 5.8K tokens · pinned 6 days ago

  • authoring-go-sdk-tasks

    Enables writing Airflow task logic in Go by implementing the Go SDK's native API.

    by AstronomerOfficial publisher

    Claude Code, Codex, Cursor +4 · about 2K tokens · pinned 6 days ago

  • authoring-java-sdk-tasks

    This skill teaches how to write Airflow task logic in Java, Kotlin, or other JVM languages using the Airflow Java SDK.

    by AstronomerOfficial publisher

    Claude Code, Codex, Cursor +4 · about 2.4K tokens · pinned 6 days ago

Open roles at Vapi

5 of 11 open roles on the jobs board

The skills listed here are third-party software, collected from public GitHub repositories as a catalog of recent skills and provided as is. Agent Native does not write or control them and is not responsible for any harm, loss or damage caused by installing or using them. Labels and checks describe what we saw at one commit and are not a guarantee. Read a skill's files before you run it. Terms of use