Calls
Read call activity
Read call activity: filtered lists, statuses, per-assistant summaries, bulk export, full single-call payloads, and per-call session insights.
The calls API is your read-only window into everything your assistants have handled on the phone: transcripts, summaries, analysis, cost, and recording links.
Read-only
There is no API to place calls. Calls are created by the platform when someone dials one of your phone numbers; these endpoints only read the results.
| Method | Path | Purpose |
|---|---|---|
| GET | /calls | List calls with filters and pagination |
| GET | /calls/statuses | Distinct call statuses seen in your tenant |
| GET | /calls/summary-by-assistant | Per-assistant call summaries |
| GET | /calls/export | Bulk export (up to 10,000 rows, lean fields) |
| GET | /calls/{id} | One call with the full payload |
| GET | /calls/{id}/insights | Session insights for one call: models, per-turn latency, tool timeline |
| GET | /calls/insights | Session insights for up to 25 calls in one request |
List calls#
GET /calls
| Query param | Type | Required | Description |
|---|---|---|---|
limit | number | No | Page size. Default 50, maximum 500. |
offset | number | No | Items to skip. Default 0. |
assistantId | UUID | No | Only calls handled by this assistant |
status | string | No | Filter by status (values from /calls/statuses) |
dateFrom / dateTo | ISO 8601 datetime (with offset) | No | Time window, e.g. 2026-07-01T00:00:00+00:00 |
durationMin / durationMax | number | No | Call duration bounds |
sortBy | startedAt | createdAt | No | Sort key (default startedAt) |
search | string | No | Free-text search |
curl "https://core-api.heysadie.ai/calls?assistantId=ASSISTANT_ID&dateFrom=2026-07-01T00:00:00%2B00:00&limit=100" \
-H "Authorization: ApiKey YOUR_API_KEY"Discover statuses#
GET /calls/statuses returns the distinct status strings that actually occur in your tenant's call history. Use it to build filter dropdowns rather than hard-coding values.
curl https://core-api.heysadie.ai/calls/statuses \
-H "Authorization: ApiKey YOUR_API_KEY"Per-assistant summaries#
GET /calls/summary-by-assistant returns one row per assistant:
| Field | Description |
|---|---|
assistantId / assistantName | Which assistant |
totalCalls | Total call count |
avgDuration | Average duration (nullable) |
successRate | Success rate |
curl https://core-api.heysadie.ai/calls/summary-by-assistant \
-H "Authorization: ApiKey YOUR_API_KEY"Export calls in bulk#
GET /calls/export returns up to 10,000 calls as JSON in one response. It accepts the same filters as the list endpoint (assistantId, status, dateFrom, dateTo, durationMin, durationMax, search) but no pagination params.
Lean rows only
Export rows exclude the heavy fields: no transcript, messages, analysis, summary, or recording URL. You get identifiers, timing, status, cost, and duration. Fetch GET /calls/{id} for the full payload of any call you need in depth. Use date-range filters to stay under the 10,000-row cap on busy tenants.
curl "https://core-api.heysadie.ai/calls/export?dateFrom=2026-07-01T00:00:00%2B00:00&dateTo=2026-08-01T00:00:00%2B00:00" \
-H "Authorization: ApiKey YOUR_API_KEY"Get one call#
GET /calls/{id} returns the full call record:
| Field | Description |
|---|---|
id, cid | Call identifiers |
type, status, endedReason | What kind of call, how it ended |
startedAt, endedAt, callDuration | Timing |
transcript, messages | Full transcript and message log |
summary, analysis | AI-generated summary and structured analysis |
recordingUrl | Recording link (when recording is enabled) |
cost, costBreakdown | Billing detail |
customerNumber | The caller's number |
assistantId, assistantName | Which assistant handled it |
supervisorAnswered | Whether a human supervisor answered (transfers) |
createdAt, updatedAt | Record timestamps |
curl https://core-api.heysadie.ai/calls/CALL_ID \
-H "Authorization: ApiKey YOUR_API_KEY"Read session insights#
GET /calls/{id}/insights returns how one call actually ran. It joins the call record with the performance metrics the voice pipeline recorded during the call. id is the same call id GET /calls/{id} takes.
| Field | Description |
|---|---|
id | The call id, the same value the call record carries |
startedAt, endedAt, callDuration | Timing |
hasRecording | Whether a recording exists. The URL itself is on GET /calls/{id} |
pipeline | One entry each for eou, llm and tts: the model that ran that stage and its avgMs over the call (end-of-utterance delay, LLM time to first token, TTS time to first byte) |
summary | Turn counts, tool call and tool failure counts, interruptions, the average latencies in milliseconds, and agentProcessingMs, the average latency multiplied by the agent turn count |
performance | One entry per assistant turn: e2eLatencyMs, llmTtftMs, ttsTtfbMs, transcriptionDelayMs, endOfUtteranceDelayMs, interrupted, token counts and cache status |
timeline | Events in call order, each with offsetMs from the start of the call: user_speech, agent_response, tool_call and tool_result |
Every latency is in milliseconds. A value the pipeline did not measure is null, never 0, and the averages in summary are null when no turn carried the value. agent_response.latencyMs is that turn's end-to-end latency. tool_result.result is the raw body your server returned, as a string, and tool_result.error is set when the call failed.
Metrics land a short while after the call ends. Until they do, this endpoint answers 404 with the message Call insights not found, even though GET /calls/{id} already returns the call. Retry after a minute rather than treating that first 404 as final. A 404 with Call not found is different: the id is not a call in your tenant.
curl https://core-api.heysadie.ai/calls/CALL_ID/insights \
-H "Authorization: ApiKey YOUR_API_KEY"Read insights for several calls#
GET /calls/insights?ids=... returns the same insights for up to 25 calls in one request.
| Query param | Type | Required | Description |
|---|---|---|---|
ids | comma-separated UUIDs | Yes | 1 to 25 call ids, no duplicates. Spaces around the commas are ignored |
The response has two arrays. insights holds one entry per call that produced insights, in the order you sent the ids. missing names every id that produced nothing, with a reason: call_not_found when the id is not a call in your tenant, metrics_not_found when the call exists but has no metrics yet. One unknown id never fails the request, and a request where every id is missing is still a 200.
curl "https://core-api.heysadie.ai/calls/insights?ids=0195f1e2-0000-0000-0000-000000000000,0195f1e2-0000-0000-0000-000000000001" \
-H "Authorization: ApiKey YOUR_API_KEY"Both insights endpoints answer 503 with code PERFORMANCE_SERVICE_UNREACHABLE if the metrics store cannot be reached. Retry with backoff; the call record itself stays available on GET /calls/{id}.
Next steps#
- Calls reference: every field and response shape, generated from the public specification.
- Live monitoring: watch a call while it is happening, rather than after it has ended.
- Conversations: the same activity view for messaging channels.
- End-of-call report webhook: get results pushed to your
serverUrlinstead of polling.