-
Calls Today
-
This Week
-
Avg Duration
-
Success Rate
Last 7 Days
Call Details
Default Agent
🤖
Loading agents...
📋
Loading leads...
LLM
0.7
Agent

Instructions given to the LLM for every call. Supports {variable} placeholders.

What the agent says when the call connects.

Speech-to-Text
Text-to-Speech (Cartesia)
Campaign / Lead Defaults

JSON array of questions the agent should ask during screening.

Webhooks

We POST call lifecycle events (initiated, ringing, in-progress, completed/failed) to this URL in real time. Leave blank to disable.

All changes apply immediately - no restart needed.
📭
Loading call history...

Calls

Place an Outbound Call

POST/api/calls
Initiate an outbound call via Plivo and connect the AI voice agent.
FieldTypeRequiredDescription
tostringYesDestination phone number (E.164 format)
fromstringNoCaller ID. Defaults to PLIVO_FROM_NUMBER
agent_idUUIDNoAgent profile to use. Defaults to DEFAULT_AGENT_ID
initial_greetingstringNoOverride the greeting message for this call
prompt_variablesobjectNoKey-value pairs injected as {variable} in the system prompt
prompt_contextobjectNoLegacy alias for prompt_variables (lower precedence)
curl -X POST /api/calls \
  -H "Content-Type: application/json" \
  -d '{
    "to": "+919876543210",
    "agent_id": "abc-123",
    "initial_greeting": "Hi John, this is Sarah from Acme!",
    "prompt_variables": {
      "lead_first_name": "John",
      "company_name": "Acme Corp"
    }
  }'
Response 201:
{ "api_id": "...", "request_uuid": "...", "message": "call fired" }

List Calls

GET/api/calls
Paginated call history. Requires Supabase.
Query ParamTypeDefaultDescription
limitint20Results per page (max 100)
offsetint0Pagination offset
tostringFilter by destination number
fromstringFilter by caller number
statusstringFilter by status
curl /api/calls?limit=10&status=completed

Agents

Named configuration profiles. Each agent can override LLM, STT, TTS, idle settings, and define custom prompt variables. Requires Supabase.

List Agents

GET/api/assistants?limit=20&offset=0

Get Agent

GET/api/assistants/:id

Create Agent

POST/api/assistants
FieldTypeRequiredDescription
namestringYesAgent display name
system_promptstringNoSystem prompt template with {variable} placeholders
initial_greetingstringNoFirst message the agent speaks
llm_providerstringNoopenai or groq
openai_modelstringNoe.g. gpt-4.1-mini
groq_modelstringNoe.g. llama-3.3-70b-versatile
temperaturefloatNo0.0 to 2.0
max_output_tokensintNoMax tokens per LLM response
stt_providerstringNodeepgram, cartesia, or whisper
cartesia_voice_idstringNoCartesia TTS voice UUID
cartesia_model_idstringNoCartesia TTS model ID
cartesia_languagestringNoTTS language code
idle_timeout_msintNoSilence timeout in ms
idle_timeout_enabledboolNoEnable idle detection
idle_max_promptsintNoMax idle prompts before hangup
idle_prompt_messagesarrayNoJSON array of idle prompt strings
idle_goodbye_messagestringNoFinal message before idle hangup
prompt_variablesobjectNoDefault values for prompt {variable} placeholders
curl -X POST /api/assistants \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Real Estate Agent",
    "system_prompt": "You are calling {lead_name} about {property_address}...",
    "initial_greeting": "Hi! I am calling about the property listing.",
    "llm_provider": "groq",
    "prompt_variables": {
      "lead_name": "",
      "property_address": "",
      "listing_price": "",
      "bedrooms": ""
    }
  }'
All fields except name are nullable. Null values inherit from server defaults. The prompt_variables keys are auto-detected from {placeholders} in the system prompt on the Make a Call page.

Update Agent

PATCH/api/assistants/:id
Same fields as create. Only provided fields are updated.

Delete Agent

DELETE/api/assistants/:id
Returns 204 No Content.

Default Agent

GET/api/config/default-agent
PATCH/api/config/default-agent
curl -X PATCH /api/config/default-agent \
  -H "Content-Type: application/json" \
  -d '{ "default_agent_id": "uuid-here" }'

Leads

Manage contacts for outbound calls. Requires Supabase.

List Leads

GET/api/leads?limit=20&offset=0

Create Lead

POST/api/leads
FieldTypeRequiredDescription
numberstringYesPhone number
namestringNoContact name
emailstringNoEmail address
curl -X POST /api/leads \
  -H "Content-Type: application/json" \
  -d '{ "number": "+919876543210", "name": "John Doe", "email": "john@example.com" }'

Upload CSV

POST/api/leads/upload
Bulk import leads from CSV. Send the file contents as the raw request body.
curl -X POST /api/leads/upload \
  -H "Content-Type: text/csv" \
  --data-binary @leads.csv
CSV format (header row auto-detected):
name,number,email
John Doe,+919876543210,john@example.com
Jane Smith,+919876543211,jane@example.com
Accepted phone column names: number, phone, phone_number. Without headers, columns are assumed as: number, name, email.

Get / Update / Delete Lead

GET/api/leads/:id
PATCH/api/leads/:id
DELETE/api/leads/:id

Configuration

Get Config

GET/api/config
Returns current server configuration including LLM, STT, TTS, and campaign defaults.

Update Config (Hot-Reload)

PATCH/api/config
Apply changes immediately. Saved to .env. LLM/STT clients are recreated if their settings change. Only provided fields are updated.
curl -X PATCH /api/config \
  -H "Content-Type: application/json" \
  -d '{
    "llmProvider": "groq",
    "temperature": 0.8,
    "initialGreeting": "Hello! How can I help?",
    "systemPrompt": "You are a helpful assistant..."
  }'
KeyDescription
llmProvideropenai or groq
sttProviderdeepgram, cartesia, or whisper
groqModel, openaiModelModel name strings
temperature0.0 to 2.0
maxOutputTokensMax tokens per response
systemPromptSystem prompt template
initialGreetingDefault greeting message
cartesiaModelId, cartesiaVoiceId, cartesiaLanguageTTS settings
webhookUrlEvent webhook endpoint
leadFirstName, companyName, jobTitle, etc.Campaign defaults for prompts

Real-Time Events

SSE Stream

GET/api/events
Server-Sent Events stream. Receives call lifecycle events in real time. Includes a heartbeat every 30s.
curl -N /api/events

// Events received:
data: {"event":"call.initiated","request_uuid":"...","to_number":"+91...","from_number":"+1..."}
data: {"event":"call.ringing","call_uuid":"..."}
data: {"event":"call.in-progress","call_uuid":"..."}
data: {"event":"call.completed","call_uuid":"...","duration_seconds":45}
EventDescription
call.initiatedOutbound call queued with Plivo
call.ringingPhone is ringing
call.in-progressCall answered, media stream connected
call.completedCall ended normally
call.failedCall failed or rejected
Events are also sent to the configured webhookUrl (POST) and Kafka topic if enabled.

Health Check

GET/health
{ "ok": true, "ready": true, "activeCalls": 0 }

Prompt Variables

The system prompt template supports {variable_name} placeholders. Values are resolved in this priority order (highest wins):
PrioritySourceDescription
1 (lowest)Server defaultsCampaign fields from Settings page / env vars
2Agent prompt_variablesPer-agent defaults stored in the agent profile
3 (highest)Per-call prompt_variablesPassed in POST /api/calls request
Built-in variables (always available, no configuration needed):
VariableValue
{current_date}Today's date (YYYY-MM-DD)
{current_time}Current time (HH:MM)
{current_datetime}Full ISO datetime
Example: An agent with this system prompt:
You are calling {lead_name} about a property at {property_address}.
The listing price is {listing_price}. Today is {current_date}.
Called with:
curl -X POST /api/calls -H "Content-Type: application/json" \
  -d '{
    "to": "+919876543210",
    "agent_id": "real-estate-agent-uuid",
    "prompt_variables": {
      "lead_name": "Rahul",
      "property_address": "42 Marina Bay, Chennai",
      "listing_price": "1.2 Cr"
    }
  }'
Latency Metrics
Calls Analysed
E2E Latency
p50 ms
p90 ms
STT EoU Delay
p50 ms
p90 ms
Pre-LLM Gap
p50 ms
p90 ms
LLM Buffer
p50 ms
p90 ms
LLM TTFT
p50 ms
p90 ms
TTS TTFB
p50 ms
p90 ms
Avg E2E Breakdown — Pre-LLM · LLM TTFT · LLM Buffer · TTS TTFB
Cost Metrics
Avg Cost / Call
Cost / Min
Avg Cost Breakdown — STT · LLM · TTS
i TTS priced on the Cartesia Scale plan