API Reference

The End of Line REST API lets you access your call intelligence data programmatically. All endpoints are available at https://api.endofline.ai/api/v1/.

Authentication

End of Line supports two authentication methods:

JWT Tokens (recommended for web apps)

Obtained via Stack Auth. Include the token in the Authorization header:

GET /api/v1/calls
Authorization: Bearer <jwt_token>
X-Tenant-ID: <tenant_uuid>

API Keys (recommended for server-to-server)

Create API keys in Settings → API Keys (Business plan and above). Include the key in the X-API-Key header:

GET /api/v1/calls
X-API-Key: eol_live_abc123...
X-Tenant-ID: <tenant_uuid>

Rate Limits

Rate limits vary by plan. All responses include rate limit headers:

X-RateLimit-Limit: 100
X-RateLimit-Remaining: 98
X-RateLimit-Reset: 1707900000
PlanRequests/minute
Free30
Pro100
Business300
EnterpriseCustom

Pagination

List endpoints support cursor-based pagination using page and per_page parameters:

GET /api/v1/calls?page=2&per_page=50

Response:
{
  "items": [...],
  "total": 1250,
  "page": 2,
  "per_page": 50,
  "pages": 25
}

Error Codes

Errors follow a consistent format:

{
  "detail": "Human-readable error message"
}
StatusMeaning
400Bad Request — invalid parameters
401Unauthorized — missing or invalid auth
403Forbidden — insufficient permissions or plan limit exceeded
404Not Found — resource does not exist
429Rate Limited — too many requests
500Server Error — contact support

Calls

List calls

GET /api/v1/calls?page=1&per_page=50&sort=-call_started_at

Query parameters:
  page        int    Page number (default: 1)
  per_page    int    Results per page (1-100, default: 50)
  sort        str    Sort field, prefix with - for descending
  status      str    Filter by status (pending, processing, completed, failed)
  date_from   int    Unix timestamp lower bound
  date_to     int    Unix timestamp upper bound
  agent       str    Filter by agent name
  campaign    str    Filter by campaign name

Response:
{
  "items": [
    {
      "call_id": "uuid",
      "inbound_number": "+15551234567",
      "caller_number": "+15559876543",
      "agent_name": "John Smith",
      "campaign_name": "Summer Promo",
      "call_started_at": 1707850000,
      "duration_seconds": 342,
      "status": "completed",
      "sentiment_score": 0.72,
      "summary": "Customer inquired about pricing..."
    }
  ],
  "total": 1250,
  "page": 1,
  "per_page": 50,
  "pages": 25
}

Get call detail

GET /api/v1/calls/{call_id}

Response:
{
  "call_id": "uuid",
  "inbound_number": "+15551234567",
  "caller_number": "+15559876543",
  "agent_name": "John Smith",
  "campaign_name": "Summer Promo",
  "call_started_at": 1707850000,
  "duration_seconds": 342,
  "status": "completed",
  "sentiment_score": 0.72,
  "summary": "Customer inquired about pricing...",
  "entities": ["Acme Corp", "Premium Plan"],
  "topics": ["pricing", "features"],
  "compliance_flags": [],
  "agent_score": {
    "overall": 8.5,
    "empathy": 9.0,
    "objection_handling": 7.5,
    "closing": 8.0
  }
}

Get call transcript

GET /api/v1/calls/{call_id}/transcript

Response:
{
  "call_id": "uuid",
  "segments": [
    {
      "speaker": "Agent",
      "text": "Hi, thanks for calling...",
      "start_time": 0.0,
      "end_time": 3.5
    },
    {
      "speaker": "Caller",
      "text": "Hi, I'm interested in...",
      "start_time": 3.8,
      "end_time": 8.2
    }
  ]
}

Get audio URL

GET /api/v1/calls/{call_id}/audio

Response:
{
  "url": "https://s3.amazonaws.com/...",
  "expires_in": 3600
}

Export calls (CSV)

GET /api/v1/calls/export?date_from=...&date_to=...&format=csv

Returns: CSV file download

Semantic search

POST /api/v1/search

Request:
{
  "query": "customer asked about refund policy",
  "limit": 10,
  "date_from": 1707000000,
  "date_to": 1707900000
}

Response:
{
  "results": [
    {
      "call_id": "uuid",
      "score": 0.92,
      "snippet": "...the customer then asked about our refund policy...",
      "agent_name": "Jane Doe",
      "call_started_at": 1707850000
    }
  ],
  "total": 42,
  "query": "customer asked about refund policy"
}

Analytics

Overview KPIs

GET /api/v1/analytics/overview?date_from=...&date_to=...

Response:
{
  "total_calls": 1250,
  "avg_duration": 245.5,
  "avg_sentiment": 0.68,
  "conversion_rate": 0.32,
  "trend": {
    "total_calls_change": 12.5,
    "avg_sentiment_change": -2.1
  }
}

Trends

GET /api/v1/analytics/trends?date_from=...&date_to=...&granularity=day

Response:
{
  "points": [
    {
      "date": "2025-02-01",
      "total_calls": 42,
      "avg_sentiment": 0.71,
      "avg_duration": 230.5
    }
  ]
}

Agent rankings

GET /api/v1/analytics/agents?date_from=...&date_to=...

Response:
{
  "agents": [
    {
      "agent_name": "John Smith",
      "total_calls": 150,
      "avg_score": 8.5,
      "avg_sentiment": 0.75,
      "conversion_rate": 0.38
    }
  ]
}

Campaign performance

GET /api/v1/analytics/campaigns?date_from=...&date_to=...

Response:
{
  "campaigns": [
    {
      "campaign_name": "Summer Promo",
      "total_calls": 320,
      "avg_duration": 210.3,
      "avg_sentiment": 0.69,
      "conversion_rate": 0.28
    }
  ]
}

Conversions

List conversions

GET /api/v1/conversions

Response:
{
  "items": [
    {
      "id": "uuid",
      "name": "Appointment Set",
      "rules": {"field": "summary", "operator": "contains", "value": "appointment"},
      "created_at": "2025-02-01T00:00:00Z",
      "match_count": 145
    }
  ],
  "total": 5
}

Create conversion

POST /api/v1/conversions

Request:
{
  "name": "Sale Closed",
  "rules": {
    "field": "summary",
    "operator": "contains",
    "value": "sale completed"
  }
}

Response: 201 Created
{
  "id": "uuid",
  "name": "Sale Closed",
  "rules": {...},
  "created_at": "2025-02-14T00:00:00Z",
  "match_count": 0
}

Get conversion stats

GET /api/v1/conversions/{id}/stats?date_from=...&date_to=...

Response:
{
  "conversion_id": "uuid",
  "name": "Sale Closed",
  "total_matches": 145,
  "rate": 0.32,
  "trend": [
    {"date": "2025-02-01", "matches": 12, "total": 42, "rate": 0.286}
  ]
}

Integrations

List integrations

GET /api/v1/integrations

Response:
{
  "items": [
    {
      "id": "uuid",
      "platform": "ringba",
      "status": "active",
      "last_sync_at": "2025-02-14T12:00:00Z",
      "calls_synced": 1250
    }
  ]
}

Create integration

POST /api/v1/integrations

Request:
{
  "platform": "ringba",
  "credentials": {
    "account_id": "...",
    "api_token": "..."
  }
}

Response: 201 Created
{
  "id": "uuid",
  "platform": "ringba",
  "status": "active",
  "created_at": "2025-02-14T00:00:00Z"
}

Webhooks

List webhooks

GET /api/v1/webhooks

Response:
{
  "items": [
    {
      "id": "uuid",
      "url": "https://your-app.com/webhook",
      "events": ["call.completed", "conversion.matched"],
      "active": true
    }
  ]
}

Create webhook

POST /api/v1/webhooks

Request:
{
  "url": "https://your-app.com/webhook",
  "events": ["call.completed"],
  "secret": "your_webhook_secret"
}

Response: 201 Created
{
  "id": "uuid",
  "url": "https://your-app.com/webhook",
  "events": ["call.completed"],
  "active": true,
  "created_at": "2025-02-14T00:00:00Z"
}

Webhook payload

Webhook payloads are sent as POST requests with a X-Webhook-Signature header for verification:

POST https://your-app.com/webhook
Content-Type: application/json
X-Webhook-Signature: sha256=...

{
  "event": "call.completed",
  "timestamp": "2025-02-14T12:00:00Z",
  "data": {
    "call_id": "uuid",
    "status": "completed",
    "agent_name": "John Smith",
    "duration_seconds": 342,
    "sentiment_score": 0.72,
    "summary": "..."
  }
}

Knowledge Graph

Query graph

POST /api/v1/graph/query

Request:
{
  "query": "MATCH (a:Agent)-[:HANDLED]->(c:Call) RETURN a, count(c)",
  "limit": 100
}

Response:
{
  "nodes": [...],
  "edges": [...],
  "total": 42
}

Get entity relationships

GET /api/v1/graph/entities/{entity_name}

Response:
{
  "entity": "Acme Corp",
  "type": "Company",
  "relationships": [
    {"type": "MENTIONED_IN", "target": "call_uuid", "count": 15},
    {"type": "ASSOCIATED_WITH", "target": "Premium Plan", "count": 8}
  ]
}