Heppu AI
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/calls

Authentication

Requires API key in request headers:

x-api-key: YOUR_API_KEY

Query Parameters

All query parameters are optional:

ParameterTypeDefaultDescription
agentIdstring-Filter by specific agent UUID
statusstring-Filter by call status (initiated, connecting, ringing, active, completed, failed, cancelled, no_answer, busy)
directionstring-Filter by direction: inbound or outbound
phoneNumberstring-Filter by phone number (matches both contact phone and agent phone)
startDatestring-Filter calls after this date (ISO 8601 format)
endDatestring-Filter calls before this date (ISO 8601 format)
limitinteger50Number of results per page (max: 100)
offsetinteger0Number of results to skip for pagination
sortBystringcreatedAtSort field: createdAt or scheduledAt
sortOrderstringdescSort 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 identifier
  • status: Current call status
  • direction: 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/result
  • twilioCallSid: Twilio call SID (if applicable)
  • agent: Agent information
  • contact: Contact details
  • phoneNumber: Agent's phone number used
  • createdAt: 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_calls

Filter 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

  1. Use pagination - Always implement pagination for large result sets
  2. Filter early - Use query parameters to reduce data transfer
  3. Cache results - Cache frequently accessed data to reduce API calls
  4. Handle errors - Always check response status and handle errors gracefully
  5. Date ranges - Use date filters for better performance on large datasets
  6. Sort efficiently - Choose appropriate sort fields for your use case

On this page