KaiCalls API
Give your AI agent a phone. Make outbound calls, manage agents, and integrate AI phone assistants into your applications.
https://kaicalls.com/api/v1Quick Start
1. Get your API key
Go to Dashboard → Settings → API Keys and generate a key.
2. Make your first call
curl -X POST https://kaicalls.com/api/v1/calls \
-H "Authorization: Bearer kc_live_xxxxx" \
-H "Content-Type: application/json" \
-d '{
"agent_id": "your-agent-id",
"to": "+15125551234",
"name": "John Smith",
"context": "Confirm appointment for tomorrow at 2pm"
}'3. Check the result
curl "https://kaicalls.com/api/v1/calls?id=CALL_ID" \
-H "Authorization: Bearer kc_live_xxxxx"Authentication
All API requests require a Bearer token in the Authorization header.
Authorization: Bearer kc_live_xxxxxKey Prefixes
kc_live_— Production keyskc_test_— Sandbox keys (coming soon)
Scopes
Keys are created with scopes that control access. Default scopes are granted automatically.
| Parameter | Type | Description |
|---|---|---|
agents:read | scope | List and view agents |
numbers:read | scope | List phone numbers |
calls:read | scope | List and view call records |
calls:write | scope | Make outbound calls |
* | scope | Full access (all scopes) |
Agents
/api/v1/agentsList all agentsReturns all agents assigned to your businesses. Requires agents:read scope.
{
"agents": [
{
"id": "uuid-abc123",
"name": "Kai",
"business_id": "uuid-biz456",
"created_at": "2026-01-15T10:00:00Z"
}
]
}/api/v1/agents?id=AGENT_IDGet agent detailsReturns detailed info including Vapi assistant ID and assigned phone number.
{
"id": "uuid-abc123",
"name": "Kai",
"business_id": "uuid-biz456",
"vapi_assistant_id": "vapi-asst-789",
"phone_number": "+15125551234",
"created_at": "2026-01-15T10:00:00Z"
}Phone Numbers
/api/v1/numbersList phone numbersReturns all phone numbers registered to your businesses. Requires numbers:read scope.
{
"numbers": [
{
"id": "uuid-num789",
"phone_number": "+15125551234",
"agent_id": "uuid-abc123",
"business_id": "uuid-biz456",
"created_at": "2026-01-15T10:00:00Z"
}
]
}Calls
/api/v1/callsMake an outbound callInitiates an outbound call using your AI agent. The system automatically enriches the call with context from your CRM — the agent will know the caller's name, lead score, interaction history, and business details.
Required scope: calls:write
Parameters
| Parameter | Type | Description |
|---|---|---|
agent_idrequired | string | The agent to use for this call |
torequired | string | Phone number to call (E.164 format, e.g. +15125551234) |
name | string | Customer name. The agent greets them by name. Also accepts customer_name. |
context | string | Freeform context the agent can reference. Use for task instructions, appointment details, or notes. |
firstMessage | string | Override the agent's opening line for this call. Also accepts first_message. If omitted, uses the agent's configured outbound greeting. |
lead_id | string | Link this call to a lead in your CRM. Enables automatic enrichment with lead score, history, and source. |
webhook_url | string | URL to receive a webhook when the call completes |
max_duration | integer | Maximum call duration in seconds (default: 600) |
Automatic Context Enrichment
When you provide a lead_id or the to number matches an existing lead, the agent automatically receives these variables in its prompt:
| Variable | Description |
|---|---|
name | Lead's first name (from name param or CRM) |
lead_score | AI-assigned quality score (0-100) |
lead_status | Current lead status in your pipeline |
interaction_count | Number of previous calls with this lead |
days_since_first_contact | Days since the lead was first created |
lead_source | Where the lead came from (web form, referral, etc.) |
business_name | Your business name |
business_phone | Your office phone number |
time_of_day | "morning", "afternoon", or "evening" |
These are injected automatically — you don't need to pass them.
Minimal Example
curl -X POST https://kaicalls.com/api/v1/calls \
-H "Authorization: Bearer kc_live_xxxxx" \
-H "Content-Type: application/json" \
-d '{"agent_id": "uuid-abc123", "to": "+15125559876"}'Full Example (with context and lead)
curl -X POST https://kaicalls.com/api/v1/calls \
-H "Authorization: Bearer kc_live_xxxxx" \
-H "Content-Type: application/json" \
-d '{
"agent_id": "uuid-abc123",
"to": "+15125559876",
"name": "John Smith",
"lead_id": "uuid-lead123",
"context": "Following up on car accident case",
"firstMessage": "Hey John, this is Kai from Smith Law — do you have a minute?"
}'{
"id": "uuid-call789",
"conversation_id": "vapi-conv-xyz",
"status": "queued",
"agent_id": "uuid-abc123",
"to": "+15125559876",
"name": "John Smith",
"created_at": "2026-02-15T14:30:00Z"
}/api/v1/callsList callsReturns calls across all your businesses, ordered by most recent. Requires calls:read scope.
Query Parameters
| Parameter | Type | Description |
|---|---|---|
limit | integer | Max results per page (default: 50, max: 100) |
agent_id | string | Filter by agent ID |
status | string | Filter by call status |
after | string | Cursor-based pagination. Pass the created_at of the last result to get the next page. |
{
"calls": [
{
"id": "uuid-call789",
"conversation_id": "vapi-conv-xyz",
"status": "completed",
"duration": 127,
"agent_id": "uuid-abc123",
"agent_name": "Kai",
"created_at": "2026-02-15T14:30:00Z"
}
],
"has_more": true
}/api/v1/calls?id=CALL_IDGet call detailsReturns full details for a single call including summary, recording, and quality analysis.
{
"id": "uuid-call789",
"conversation_id": "vapi-conv-xyz",
"status": "completed",
"direction": "inbound",
"duration": 127,
"agent_id": "uuid-abc123",
"agent_name": "Kai",
"business_id": "uuid-biz456",
"lead_id": "uuid-lead123",
"summary": "Confirmed appointment with John for tomorrow at 2pm.",
"recording_url": "https://storage.example.com/recordings/call_xyz.mp3",
"quality_dimensions": {
"professionalism": 92,
"empathy": 88,
"information_gathering": 95,
"resolution": 90
},
"created_at": "2026-02-15T14:30:00Z"
}API Keys
Key management uses session authentication (dashboard login), not API key auth.
/api/v1/keysList your API keys{
"keys": [
{
"id": "uuid-key123",
"prefix": "kc_live_abc1",
"name": "Production Key",
"scopes": ["agents:read", "calls:read", "calls:write", "numbers:read"],
"business_id": null,
"created_at": "2026-01-15T10:00:00Z",
"last_used_at": "2026-02-15T14:30:00Z",
"expires_at": null,
"is_active": true
}
]
}/api/v1/keysCreate a new keyThe full key is returned only once — store it securely.
| Parameter | Type | Description |
|---|---|---|
name | string | Human-readable name (default: "Untitled Key") |
business_id | string | Scope key to a single business. If omitted, key accesses all your businesses. |
scopes | string[] | Permission scopes. Defaults to ["agents:read", "numbers:read", "calls:read", "calls:write"]. |
{
"key": "kc_live_abc123def456...",
"id": "uuid-key123",
"prefix": "kc_live_abc1",
"name": "My Integration Key",
"scopes": ["agents:read", "calls:read", "calls:write", "numbers:read"],
"business_id": "uuid-biz456",
"created_at": "2026-02-15T14:30:00Z"
}/api/v1/keys?id=KEY_IDRevoke a keyRevokes an API key. The key immediately stops working.
{ "success": true }Account
/api/v1/balanceGet subscription infoReturns usage and subscription status for each of your businesses.
{
"businesses": [
{
"business_id": "uuid-biz456",
"minutes_used": 412,
"phone_numbers": 2,
"subscription_status": "active"
}
]
}/api/v1/usageGet API usage logReturns your API call history.
| Parameter | Type | Description |
|---|---|---|
start | string | ISO 8601 start date filter |
end | string | ISO 8601 end date filter |
limit | integer | Max results (default: 100, max: 500) |
{
"usage": [
{
"id": "uuid-log123",
"endpoint": "/v1/calls",
"method": "POST",
"status_code": 201,
"call_id": "uuid-call789",
"cost_cents": 15,
"created_at": "2026-02-15T14:30:00Z"
}
],
"has_more": false
}Webhooks
Pass a webhook_url when making a call to receive events when the call completes or fails.
call.completed
{
"event": "call.completed",
"call_id": "uuid-call789",
"status": "completed",
"duration": 127,
"recording_url": "https://...",
"summary": "Confirmed appointment for tomorrow at 2pm.",
"timestamp": "2026-02-15T14:32:12Z"
}call.failed
{
"event": "call.failed",
"call_id": "uuid-call789",
"status": "failed",
"error": "no_answer",
"timestamp": "2026-02-15T14:31:00Z"
}Errors
All errors follow a consistent format:
{
"error": {
"code": "error_code",
"message": "Human-readable description"
}
}| Code | Status | Description |
|---|---|---|
unauthorized | 401 | Invalid, missing, expired, or revoked API key |
forbidden | 403 | Key doesn't have the required scope |
not_found | 404 | Agent, call, or resource not found |
invalid_request | 400 | Missing required fields or invalid JSON |
call_failed | 500 | Vapi failed to initiate the call |
internal_error | 500 | Unexpected server error |
rate_limited | 429 | Too many requests — slow down |
Rate Limits
| Endpoint | Limit |
|---|---|
| POST /v1/calls | 60 requests/minute |
| All GET endpoints | 300 requests/minute |
SDKs
Python
pip install kaicallsfrom kaicalls import KaiCalls
kai = KaiCalls(api_key="kc_live_xxx")
# Simple call — agent auto-enriches with CRM data
call = kai.calls.create(
agent_id="uuid-abc123",
to="+15125551234",
name="John Smith"
)
# Full call with lead linking and custom opening
call = kai.calls.create(
agent_id="uuid-abc123",
to="+15125551234",
name="John Smith",
lead_id="uuid-lead123",
context="Following up on car accident case",
first_message="Hey John, this is Kai — do you have a minute?"
)
result = kai.calls.wait(call.id)
print(result.summary)JavaScript / TypeScript
npm install kaicallsimport { KaiCalls } from 'kaicalls';
const kai = new KaiCalls({ apiKey: 'kc_live_xxx' });
// Simple call
const call = await kai.calls.create({
agentId: 'uuid-abc123',
to: '+15125551234',
name: 'John Smith',
});
// Full call with lead linking and custom opening
const call = await kai.calls.create({
agentId: 'uuid-abc123',
to: '+15125551234',
name: 'John Smith',
leadId: 'uuid-lead123',
context: 'Following up on car accident case',
firstMessage: 'Hey John, this is Kai — do you have a minute?',
});
const result = await kai.calls.get(call.id);
console.log(result.summary);Need help? support@kaicalls.com