Vapi Voice Agent
Programmable voice AI calls with pluggable LLM models and voice providers via Vapi REST API
Vapi Voice Agent
The Vapi page at /admin/vapi provides programmable AI voice calls with pluggable LLM models and voice providers. Where Bland AI uses its own internal models, Vapi lets you choose the LLM (OpenAI, Anthropic, Groq, Google) and the voice provider (ElevenLabs, PlayHT, Deepgram) for each call.
Architecture
Admin UI → /api/admin/vapi-manage → Vapi REST API
├── POST /call (create call with transient assistant)
├── GET /call (list calls)
├── GET /call/:id (call detail + transcript)
└── GET /phone-number (list Vapi phone numbers)
Calls use a “transient assistant” — the system prompt, model, and voice are defined inline per call rather than referencing a saved assistant. This keeps configuration self-contained in the admin UI.
Page Layout
Stats Row
Four stat cards:
- API Status — connection health (OK/Error)
- Total Calls — number of calls made
- Active — calls currently in progress
- Phone Numbers — Vapi phone numbers available for caller ID
Make Call Tab
Form card with:
- Customer Phone Number — E.164 format
- System Prompt — instructions for the AI assistant (what to say, how to behave)
- Model Provider — dropdown: OpenAI, Anthropic, Groq, Google
- Model — dynamically filtered by provider selection
- Voice Provider — optional: ElevenLabs, PlayHT, Deepgram (or Default)
- Voice ID — provider-specific voice identifier
- Phone Number ID — optional Vapi phone number for outbound caller ID
- Call button with spinner feedback
The model dropdown updates automatically when the provider changes.
Call History Tab
Table of recent calls showing Customer number, Status (badge), Duration, Created date, Cost, and View button.
Call Detail Tab
Full call information:
- Customer number, status, duration, timestamps, end reason
- Transcript timeline with role-colored message bubbles (amber for assistant, blue for user)
- Cost breakdown
API Route
Route: /api/admin/vapi-manage
Auth: Admin-only (CF Access JWT validation)
GET
Health check — verifies Vapi API connectivity.
POST Actions
| Action | Parameters | Returns |
|---|---|---|
get-status | none | { status } |
make-call | customerNumber, systemPrompt, modelProvider, model, voiceProvider, voiceId, phoneNumberId | { success, callId, status } |
list-calls | limit (max 100, default 50) | { calls[], total } |
get-call | callId | { call } (includes transcript, cost, messages) |
list-phone-numbers | none | { phoneNumbers[] } |
Environment Variables
| Variable | Required | Description |
|---|---|---|
VAPI_API_KEY | Yes | Vapi API key (from dashboard.vapi.ai) |
Model Provider Reference
| Provider | Models | Notes |
|---|---|---|
| OpenAI | gpt-4o, gpt-4o-mini | Default provider |
| Anthropic | claude-sonnet-4-5-20250929 | Claude Sonnet 4.5 |
| Groq | llama-3.1-70b-versatile | Fast inference |
gemini-2.0-flash | Gemini Flash |
Voice Provider Reference
| Provider | Voice ID Format | Notes |
|---|---|---|
| ElevenLabs | pNInz6obpgDQGcFmaJgB (voice hash) | Same voices as ElevenLabs admin page |
| PlayHT | Provider-specific ID | Alternative TTS |
| Deepgram | Provider-specific ID | Low-latency TTS |
If no voice provider is specified, Vapi uses its default voice.
Vapi Phone Numbers
Outbound calls require a phoneNumberId — a phone number purchased through Vapi’s dashboard. Without one, calls will fail. Check the Phone Numbers stat card or visit dashboard.vapi.ai to purchase a number.
Setup
- Create an account at dashboard.vapi.ai
- Navigate to Organization → API Keys and copy your key
- Set the environment variable:
- Local: add
VAPI_API_KEY=your-keyto.env - Production:
npx wrangler pages secret put VAPI_API_KEY
- Local: add
- Purchase a phone number in Phone Numbers tab ($2/month — required for outbound calls)
- Restart the dev server or redeploy
Vapi offers $10 trial credit. Outbound calls cost varies by model and voice provider.
Troubleshooting
API Status shows Error
Symptom: Stats row shows “Error”, all calls fail with 401.
Fix: The VAPI_API_KEY is missing or invalid. Check .env (local) or CF Pages secrets (production). Get your key from dashboard.vapi.ai → Organization → API Keys.
Call fails with “phone number required”
Symptom: Making a call returns an error or never connects.
Fix: Vapi outbound calls require a phoneNumberId — a number purchased through Vapi’s dashboard. Go to dashboard.vapi.ai → Phone Numbers, purchase one ($2/mo), and paste the ID into the “Phone Number ID” field.
AI uses wrong voice or model
Symptom: Call connects but uses unexpected voice/model, or responses seem generic.
Fix: Vapi uses transient (inline) assistant config per call. If Voice Provider is set but Voice ID is blank, Vapi uses its default voice. Get ElevenLabs voice IDs from /admin/elevenlabs or elevenlabs.Izar-Host. Ensure Model Provider matches the Model selected (e.g., OpenAI → gpt-4o).
Cost seems high
Symptom: Individual calls cost more than expected.
Fix: Cost depends on the model and voice provider selected. gpt-4o-mini is cheaper than gpt-4o. ElevenLabs voices add TTS cost on top of the base call cost. Check Call Detail for the cost breakdown. Use the Vapi dashboard for detailed billing.
Related
- Twilio Dashboard (
/admin/twilio) — manual SMS and voice calls with pre-written text - Bland AI Phone Agent (
/admin/bland) — AI calls with Bland’s internal models and voices - ElevenLabs (
/admin/elevenlabs) — voice library (ElevenLabs voices can be used as Vapi voice provider)