Calls API
List Calls
Retrieve a paginated list of calls with advanced filtering and sorting
List Calls
Retrieve a paginated list of calls with advanced filtering, sorting, and search capabilities.
Endpoint
GET /api/v1/callsAuthentication
Requires API key in request headers:
x-api-key: YOUR_API_KEYQuery Parameters
All query parameters are optional:
| Parameter | Type | Default | Description |
|---|---|---|---|
agentId | string | - | Filter by specific agent UUID |
status | string | - | Filter by call status (initiated, connecting, ringing, active, completed, failed, cancelled, no_answer, busy) |
direction | string | - | Filter by direction: inbound or outbound |
phoneNumber | string | - | Filter by phone number (matches both contact phone and agent phone) |
startDate | string | - | Filter calls after this date (ISO 8601 format) |
endDate | string | - | Filter calls before this date (ISO 8601 format) |
limit | integer | 50 | Number of results per page (max: 100) |
offset | integer | 0 | Number of results to skip for pagination |
sortBy | string | createdAt | Sort field: createdAt or scheduledAt |
sortOrder | string | desc | Sort order: asc or desc |
Response
Returns a paginated list of calls with metadata.
Response Schema
{
"data": {
"calls": [
{
"id": "string",
"status": "string",
"direction": "inbound|outbound",
"scheduledAt": "string|null",
"duration": "integer|null",
"outcome": "string|null",
"twilioCallSid": "string|null",
"agent": {
"id": "string",
"name": "string"
},
"contact": {
"phone": "string",
"name": "string|null",
"email": "string|null"
},
"phoneNumber": "string",
"createdAt": "string"
}
],
"pagination": {
"total": "integer",
"limit": "integer",
"offset": "integer",
"hasMore": "boolean"
}
}
}Field Descriptions
id: Unique call identifierstatus: Current call statusdirection: Call direction (inbound/outbound)scheduledAt: When call was/is scheduled (null for immediate calls)duration: Call duration in seconds (null if not completed)outcome: Call outcome/resulttwilioCallSid: Twilio call SID (if applicable)agent: Agent informationcontact: Contact detailsphoneNumber: Agent's phone number usedcreatedAt: Call creation timestamp (ISO 8601)
Examples
Basic Request
curl -X GET "https://v2.heppu.ai/api/v1/calls?limit=10" \
-H "x-api-key: YOUR_API_KEY"const response = await fetch('https://v2.heppu.ai/api/v1/calls?limit=10', {
method: 'GET',
headers: {
'x-api-key': 'YOUR_API_KEY'
}
});
const data = await response.json();
console.log('Calls:', data.data.calls);
console.log('Total:', data.data.pagination.total);import requests
response = requests.get(
'https://v2.heppu.ai/api/v1/calls',
headers={'x-api-key': 'YOUR_API_KEY'},
params={'limit': 10}
)
data = response.json()
print(f"Calls: {data['data']['calls']}")
print(f"Total: {data['data']['pagination']['total']}")Filter by Agent and Status
curl -X GET "https://v2.heppu.ai/api/v1/calls?agentId=550e8400-e29b-41d4-a716-446655440000&status=completed&limit=20" \
-H "x-api-key: YOUR_API_KEY"const agentId = '550e8400-e29b-41d4-a716-446655440000';
const params = new URLSearchParams({
agentId: agentId,
status: 'completed',
limit: '20'
});
const response = await fetch(`https://v2.heppu.ai/api/v1/calls?${params}`, {
headers: { 'x-api-key': 'YOUR_API_KEY' }
});
const data = await response.json();params = {
'agentId': '550e8400-e29b-41d4-a716-446655440000',
'status': 'completed',
'limit': 20
}
response = requests.get(
'https://v2.heppu.ai/api/v1/calls',
headers={'x-api-key': 'YOUR_API_KEY'},
params=params
)Filter by Date Range
curl -X GET "https://v2.heppu.ai/api/v1/calls?startDate=2025-12-01T00:00:00Z&endDate=2025-12-31T23:59:59Z" \
-H "x-api-key: YOUR_API_KEY"const params = new URLSearchParams({
startDate: '2025-12-01T00:00:00Z',
endDate: '2025-12-31T23:59:59Z',
sortBy: 'createdAt',
sortOrder: 'desc'
});
const response = await fetch(`https://v2.heppu.ai/api/v1/calls?${params}`, {
headers: { 'x-api-key': 'YOUR_API_KEY' }
});from datetime import datetime
params = {
'startDate': '2025-12-01T00:00:00Z',
'endDate': '2025-12-31T23:59:59Z',
'sortBy': 'createdAt',
'sortOrder': 'desc'
}
response = requests.get(
'https://v2.heppu.ai/api/v1/calls',
headers={'x-api-key': 'YOUR_API_KEY'},
params=params
)Pagination Example
# Get first page
curl -X GET "https://v2.heppu.ai/api/v1/calls?limit=50&offset=0" \
-H "x-api-key: YOUR_API_KEY"
# Get second page
curl -X GET "https://v2.heppu.ai/api/v1/calls?limit=50&offset=50" \
-H "x-api-key: YOUR_API_KEY"async function getAllCalls() {
let allCalls = [];
let offset = 0;
const limit = 50;
let hasMore = true;
while (hasMore) {
const response = await fetch(
`https://v2.heppu.ai/api/v1/calls?limit=${limit}&offset=${offset}`,
{ headers: { 'x-api-key': 'YOUR_API_KEY' } }
);
const data = await response.json();
allCalls = allCalls.concat(data.data.calls);
hasMore = data.data.pagination.hasMore;
offset += limit;
}
return allCalls;
}def get_all_calls():
all_calls = []
offset = 0
limit = 50
has_more = True
while has_more:
response = requests.get(
'https://v2.heppu.ai/api/v1/calls',
headers={'x-api-key': 'YOUR_API_KEY'},
params={'limit': limit, 'offset': offset}
)
data = response.json()
all_calls.extend(data['data']['calls'])
has_more = data['data']['pagination']['hasMore']
offset += limit
return all_callsFilter Outbound Calls by Phone Number
curl -X GET "https://v2.heppu.ai/api/v1/calls?direction=outbound&phoneNumber=%2B14155552671" \
-H "x-api-key: YOUR_API_KEY"const params = new URLSearchParams({
direction: 'outbound',
phoneNumber: '+14155552671'
});
const response = await fetch(`https://v2.heppu.ai/api/v1/calls?${params}`, {
headers: { 'x-api-key': 'YOUR_API_KEY' }
});params = {
'direction': 'outbound',
'phoneNumber': '+14155552671'
}
response = requests.get(
'https://v2.heppu.ai/api/v1/calls',
headers={'x-api-key': 'YOUR_API_KEY'},
params=params
)Response Examples
Success Response
{
"data": {
"calls": [
{
"id": "call_abc123",
"status": "completed",
"direction": "outbound",
"scheduledAt": "2025-12-01T14:00:00Z",
"duration": 180,
"outcome": "successful",
"twilioCallSid": "CA1234567890abcdef",
"agent": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "Customer Support Agent"
},
"contact": {
"phone": "+14155552671",
"name": "John Doe",
"email": "john.doe@example.com"
},
"phoneNumber": "+14155551234",
"createdAt": "2025-12-01T13:55:00Z"
},
{
"id": "call_def456",
"status": "no_answer",
"direction": "outbound",
"scheduledAt": null,
"duration": null,
"outcome": "no_answer",
"twilioCallSid": "CA0987654321fedcba",
"agent": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "Customer Support Agent"
},
"contact": {
"phone": "+14155552672",
"name": "Jane Smith",
"email": null
},
"phoneNumber": "+14155551234",
"createdAt": "2025-12-01T13:30:00Z"
}
],
"pagination": {
"total": 125,
"limit": 50,
"offset": 0,
"hasMore": true
}
}
}Empty Results
{
"data": {
"calls": [],
"pagination": {
"total": 0,
"limit": 50,
"offset": 0,
"hasMore": false
}
}
}Error Responses
Invalid API Key
{
"error": {
"message": "Unauthorized",
"code": 401
}
}Invalid Status Filter
{
"error": {
"message": "Invalid status value",
"code": 400
}
}Invalid Date Format
{
"error": {
"message": "Invalid date format. Use ISO 8601 format",
"code": 400
}
}Use Cases
Call Analytics Dashboard
Retrieve call statistics for a specific agent over the last 30 days:
const thirtyDaysAgo = new Date();
thirtyDaysAgo.setDate(thirtyDaysAgo.getDate() - 30);
const params = new URLSearchParams({
agentId: 'your-agent-id',
startDate: thirtyDaysAgo.toISOString(),
limit: '100',
sortBy: 'createdAt',
sortOrder: 'desc'
});
const response = await fetch(`https://v2.heppu.ai/api/v1/calls?${params}`, {
headers: { 'x-api-key': 'YOUR_API_KEY' }
});
const data = await response.json();
// Calculate statistics
const stats = {
total: data.data.pagination.total,
completed: data.data.calls.filter(c => c.status === 'completed').length,
failed: data.data.calls.filter(c => c.status === 'failed').length,
avgDuration: data.data.calls
.filter(c => c.duration)
.reduce((sum, c) => sum + c.duration, 0) / data.data.calls.length
};Export Call History
Export all calls for compliance or reporting:
import csv
from datetime import datetime, timedelta
def export_calls_to_csv(start_date, end_date, filename='calls.csv'):
all_calls = []
offset = 0
limit = 100
params = {
'startDate': start_date.isoformat(),
'endDate': end_date.isoformat(),
'limit': limit,
'sortBy': 'createdAt',
'sortOrder': 'asc'
}
while True:
params['offset'] = offset
response = requests.get(
'https://v2.heppu.ai/api/v1/calls',
headers={'x-api-key': 'YOUR_API_KEY'},
params=params
)
data = response.json()
calls = data['data']['calls']
all_calls.extend(calls)
if not data['data']['pagination']['hasMore']:
break
offset += limit
# Write to CSV
with open(filename, 'w', newline='') as csvfile:
fieldnames = ['id', 'agent_name', 'contact_phone', 'contact_name',
'status', 'direction', 'duration', 'createdAt']
writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
writer.writeheader()
for call in all_calls:
writer.writerow({
'id': call['id'],
'agent_name': call['agent']['name'],
'contact_phone': call['contact']['phone'],
'contact_name': call['contact']['name'] or '',
'status': call['status'],
'direction': call['direction'],
'duration': call['duration'] or 0,
'createdAt': call['createdAt']
})
return len(all_calls)Best Practices
- Use pagination - Always implement pagination for large result sets
- Filter early - Use query parameters to reduce data transfer
- Cache results - Cache frequently accessed data to reduce API calls
- Handle errors - Always check response status and handle errors gracefully
- Date ranges - Use date filters for better performance on large datasets
- Sort efficiently - Choose appropriate sort fields for your use case
Related Endpoints
- Get Call Details - Get detailed information about a specific call
- Schedule Call - Schedule a new call
- Batch Schedule - Schedule multiple calls