๐ฑOutbound Calls
The Outbound Calls API allows you to programmatically initiate phone calls from your AI agents to any phone number.
Base URL: https://api.krosai.com/v1/outbound-calls
Initiate Outbound Call
Start a new outbound call from your KrosAI phone number to a destination.
Endpoint
POST /outbound-calls
Request Body
| string | Yes | Your KrosAI phone number (E.164 format) |
| string | Yes | Destination phone number (E.164 format) |
| string | Yes | The endpoint (AI agent) to handle the call |
| object | No | Custom metadata to attach to the call |
| string | No | Override webhook URL for this call |
| integer | No | Maximum call duration in seconds |
Request
curl -X POST "https://api.krosai.com/v1/outbound-calls" \
-H "x-api-key: kros_live_your_key" \
-H "Content-Type: application/json" \
-d '{
"from_number": "+2348012345678",
"to_number": "+14155551234",
"endpoint_id": "ep_abc123",
"metadata": {
"customer_id": "cust_xyz",
"campaign": "follow-up-q1"
}
}'
Response
{
"call_id": "call_xyz789",
"status": "initiated",
"from_number": "+2348012345678",
"to_number": "+14155551234",
"endpoint_id": "ep_abc123",
"created_at": "2025-01-10T12:00:00Z"
}
Phone Number Format
All phone numbers must be in E.164 format:
Format | Example | Valid |
E.164 |
| โ |
E.164 |
| โ |
Local |
| โ |
Formatted |
| โ |
Note: The from_number must be a phone number owned by your organization.
Call Lifecycle
When you initiate an outbound call, it goes through these stages:
initiated โ ringing โ answered โ in_progress โ completed
Possible failure outcomes include failed, no_answer, and busy.
Status Values
| Call request accepted, setting up |
| Destination phone is ringing |
| Destination answered |
| Call is active with AI agent |
| Call ended normally |
| Call failed to connect |
| Destination didn't answer |
| Destination was busy |
Metadata
Attach custom metadata to calls for tracking and analytics:
Metadata is:
{
"from_number": "+2348012345678",
"to_number": "+14155551234",
"endpoint_id": "ep_abc123",
"metadata": {
"customer_id": "cust_123",
"campaign_id": "camp_456",
"lead_source": "website",
"custom_field": "any value"
}
}
Metadata is:
- Included in webhook payloads
- Searchable in call logs
- Available in analytics exports
Maximum Duration
Set a maximum call duration to prevent unexpectedly long calls:
{
"from_number": "+2348012345678",
"to_number": "+14155551234",
"endpoint_id": "ep_abc123",
"max_duration": 600
}
When the limit is reached, the call is automatically terminated.
Error Responses
400 |
| Invalid E.164 format |
400 |
|
|
400 |
| Outbound calls disabled for this number |
400 |
| Not enough credits |
404 |
| Invalid |
429 |
| Too many concurrent calls |
Error Response Format
{
"from_number": "+2348012345678",
"to_number": "+14155551234",
"endpoint_id": "ep_abc123",
"metadata": {
"customer_id": "cust_123",
"campaign_id": "camp_456",
"lead_source": "website",
"custom_field": "any value"
}
}
Concurrent Call Limits
'
Free | 1 |
Pro | 10 |
Business | 15 |
Enterprise | Unlimited |
Code Examples
interface OutboundCallOptions {
fromNumber: string;
toNumber: string;
endpointId: string;
metadata?: Record<string, string>;
maxDuration?: number;
}
async function initiateOutboundCall(options: OutboundCallOptions) {
const response = await fetch('https://api.krosai.com/v1/outbound-calls', {
method: 'POST',
headers: {
'x-api-key': process.env.KROSAI_API_KEY!,
'Content-Type': 'application/json',
},
body: JSON.stringify({
from_number: options.fromNumber,
to_number: options.toNumber,
endpoint_id: options.endpointId,
metadata: options.metadata,
max_duration: options.maxDuration,
}),
});
if (!response.ok) {
const error = await response.json();
throw new Error(`Call failed: ${error.code} - ${error.error}`);
}
return response.json();
}
// Usage
const call = await initiateOutboundCall({
fromNumber: '+2348012345678',
toNumber: '+14155551234',
endpointId: 'ep_abc123',
metadata: {
customer_id: 'cust_123',
campaign: 'welcome-series',
},
maxDuration: 300, // 5 minutes max
});
console.log(`Call initiated: ${call.call_id}`);
import requests
import os
def initiate_outbound_call(
from_number: str,
to_number: str,
endpoint_id: str,
metadata: dict = None,
max_duration: int = None
):
payload = {
'from_number': from_number,
'to_number': to_number,
'endpoint_id': endpoint_id
}
if metadata:
payload['metadata'] = metadata
if max_duration:
payload['max_duration'] = max_duration
response = requests.post(
'https://api.krosai.com/v1/outbound-calls',
headers={
'x-api-key': os.environ['KROSAI_API_KEY'],
'Content-Type': 'application/json'
},
json=payload
)
if not response.ok:
error = response.json()
raise Exception(f"Call failed: {error['code']} - {error['error']}")
return response.json()
# Usage
call = initiate_outbound_call(
from_number='+2348012345678',
to_number='+14155551234',
endpoint_id='ep_abc123',
metadata={
'customer_id': 'cust_123',
'campaign': 'welcome-series'
}
)
print(f"Call initiated: {call['call_id']}")
interface Contact {
phone: string;
customerId: string;
}
async function runCampaign(
contacts: Contact[],
fromNumber: string,
endpointId: string
) {
const results = [];
for (const contact of contacts) {
try {
const call = await initiateOutboundCall({
fromNumber,
toNumber: contact.phone,
endpointId,
metadata: {
customer_id: contact.customerId,
campaign: 'batch-outreach',
},
});
results.push({ success: true, callId: call.call_id, contact });
// Respect rate limits - wait between calls
await new Promise(r => setTimeout(r, 1000));
} catch (error) {
results.push({ success: false, error: error.message, contact });
}
}
return results;
}
Webhook Integration
Receive real-time updates about your outbound calls:
{
"error": "Phone number format is invalid. Use E.164 format (+14155551234)",
"code": "INVALID_PHONE_NUMBER",
"details": {
"field": "to_number",
"value": "4155551234"
}
}
โ Set up Webhooks
Best Practices
Do's โ
- Validate phone numbers before calling
- Use metadata to track campaign performance
- Set max_duration to prevent runaway calls
- Handle errors gracefully
- Respect rate limits in batch operations
- Test with small batches first
Don'ts โ
- Don't hardcode phone numbers in source code
- Don't exceed concurrent limits โ queue calls instead
- Don't ignore webhook failures โ implement retries
- Don't call without consent โ follow local regulations
Compliance Notes
When making outbound calls, ensure compliance with:
- TCPA (US) - Prior consent required
- GDPR (EU) - Data protection requirements
- Local regulations - Check destination country laws
KrosAI provides the infrastructure; you're responsible for compliance.
On this page
- ๐ฑOutbound Calls