By area
Calls
Read from the API’s own reference file every hour.
Your call history. Each call carries its journey through menus, groups and people, with AI summaries, transcripts and recording links.
List calls
GET/v1/
Your calls in a date window, newest first, one entry per call. Each call carries its journey: every leg it took through menus, groups, queues and people, with the AI summary, the transcript and a recording link when the leg was recorded.
Dates. Send start_date and end_date together, as local days in timezone. Send neither for today. A single date is ignored and you get today. At most 366 days per request; for more history, walk it a year at a time.
Paging. limit is 500 by default and at most 500. Calls that tie on the sort key keep a stable order, so paging is safe.
Filters. status, extension and type match single legs. A call is listed when one of its legs matches, and its journey then shows only the legs that match. search looks in the call id, the other party's name and number, your number and the extensions.
Fields to know. status is the status of the first leg in journey, not the call's final outcome: a call a menu answered and a person then missed reads answered. extension and extension_name name the last person who held the call. recording_url points at GET /v1/media/rec_<n>, which returns a signed link.
Recordings in parts. A call that is parked and picked up again is recorded in parts: part 1 up to the park, part 2 after the pick-up, rarely a part 3. Each leg lists its recordings in recordings, oldest first, each with its own url (GET /v1/media/rec_<n>?part=N) and its own start time and length. recording_url, summary and transcription are the latest part's. Nearly every leg has one part. The transcript of each part also comes by webhook (call.transcription, one event per part).
A search that runs longer than 30 seconds is stopped with 500. Narrow the window or add filters.
Each request is written to your account's HIPAA access log.
Request
curl -G https://api.vocatech.com/v1/calls \
-H "Authorization: Bearer YOUR_API_KEY" \
--data-urlencode "start_date=2026-09-21" \
--data-urlencode "end_date=2026-09-22" \
--data-urlencode "timezone=America/New_York"const params = new URLSearchParams({
start_date: "2026-09-21",
end_date: "2026-09-22",
timezone: "America/New_York",
});
const res = await fetch(`https://api.vocatech.com/v1/calls?${params}`, {
headers: { Authorization: "Bearer YOUR_API_KEY" },
});
console.log(res.status, await res.json());import requests
r = requests.get(
"https://api.vocatech.com/v1/calls",
headers={"Authorization": "Bearer YOUR_API_KEY"},
params={
"start_date": "2026-09-21",
"end_date": "2026-09-22",
"timezone": "America/New_York",
},
timeout=30,
)
print(r.status_code, r.json())<?php
require 'vendor/autoload.php';
$client = new GuzzleHttp\Client([
'base_uri' => 'https://api.vocatech.com',
'headers' => ['Authorization' => 'Bearer YOUR_API_KEY'],
'http_errors' => false,
]);
$res = $client->get('/v1/calls', [
'query' => [
'start_date' => '2026-09-21',
'end_date' => '2026-09-22',
'timezone' => 'America/New_York',
],
]);
echo $res->getStatusCode(), PHP_EOL, $res->getBody(), PHP_EOL;Parameters
| Name | In | Type | Description |
|---|---|---|---|
start_date | query | string (date) | First local day of the window, YYYY-MM-DD, in timezone. Send it with end_date. Send neither for today. A single date is ignored and you get today. For example 2026-09-01. |
end_date | query | string (date) | Last local day of the window, YYYY-MM-DD, included in full. At most 366 days after start_date. For example 2026-09-07. |
timezone | query | string | IANA time zone for the dates, for example America/Chicago. An unknown zone falls back to America/New_York. The response echoes the zone used. Default America/New_York. |
direction | query | string | incoming or outgoing, as each call's direction reads. voicemail matches the rare calls stored that way. One of any, incoming, outgoing or voicemail. Default any. |
status | query | string | Only calls with a leg in this status, for example answered or missed. missed never returns an outgoing call. Default any. For example missed. |
extension | query | string | Only calls with a leg on this extension (exact match). For example 104. |
type | query | string | Only calls with a leg of this type, for example user, auto_attendant, hunt_group or call_center. Default any. |
search | query | string | Text to find in the call id, the other party's name or number, your number, or an extension. |
sort | query | string | Order by start time or by duration. Calls that tie keep a stable order, so paging is safe. One of day_desc, day_asc, duration_desc or duration_asc. Default day_desc. |
page | query | integer | Page number, from 1. Default 1. At least 1. |
limit | query | integer | Rows per page, 1 to 500. A value outside that range is brought inside it. Default 500. From 1 to 500. |
company_id | query | integer | Optional. If you send it, it must be your own company id, or the request is refused with 403. The key already decides the company. |
Answers
| Field | Type | Description |
|---|---|---|
query required | object | The filters that were applied, echoed back. extension and type are applied but not echoed. |
query. | integer | |
query. | string (date) | The first local day used. |
query. | string (date) | The last local day used. |
query. | string | |
query. | string | |
query. | string | |
query. | string | The time zone used. |
calls required | array of objects | |
calls[]. required | string | The call's id. |
calls[]. required | string | incoming or outgoing. A call your staff placed through the dial-out portal reads outgoing. A few calls read voicemail. |
calls[]. required | string | The status of the first leg in journey, for example answered or missed. It is not the call's final outcome: a call a menu answered and a person then missed reads answered. Read the legs to see who answered. |
calls[]. required | string or null | The last person who held the call. When no person did, the first extension on it. |
calls[]. required | string or null | That extension's name, written First Last. |
calls[]. required | string | The other party's name from caller ID, written First Last. Can be empty. |
calls[]. required | string | The other party's number, digits without the leading 1. Can be empty. |
calls[]. required | string | Your number on the call, digits without the leading 1. Can be empty. |
calls[]. required | string (date-time) or null | UTC, ISO 8601 with milliseconds. |
calls[]. required | string (date-time) or null | UTC, ISO 8601 with milliseconds. |
calls[]. required | integer | The call's length in seconds. |
calls[]. required | array of objects | Every leg, in order. When you filter by status, extension or type, only the matching legs are listed. |
calls[]. required | integer | Position in the journey, from 1. |
calls[]. required | string | What handled this leg, as the phone system wrote it. For example user (a person), auto_attendant, hunt_group or call_center. |
calls[]. required | string or null | The name of the person or feature on this leg, as set in the portal, written First Last. |
calls[]. required | string or null | The extension on this leg. |
calls[]. required | string (date-time) or null | UTC, ISO 8601 with milliseconds. |
calls[]. required | string (date-time) or null | UTC, ISO 8601 with milliseconds. |
calls[]. required | integer | Seconds on this leg. |
calls[]. required | string or null | The AI summary of this leg's recording (its latest part). Null when there is none, and when the leg's only recording belongs to another call leg. |
calls[]. required | string or null | The transcript of this leg's recording (its latest part), with speaker labels. Null when there is none, and when the leg's only recording belongs to another call leg. |
calls[]. required | string (uri) or null | Where to fetch this leg's recording (its latest part). Call it with your key (GET /v1/media/rec_<n>) to get a signed link. Null when the leg was not recorded. |
calls[]. required | array of objects | Every recording of this leg, oldest first. A call parked and picked up again has two parts (rarely three). Nearly every recorded leg has one. Empty when the leg was not recorded. |
calls[]. required | integer | This part's place, from 1, oldest first. |
calls[]. required | integer | How many parts the leg's recording has. |
calls[]. required | integer | The recording's id. The call.transcription event of this part carries the same id. |
calls[]. required | string (date-time) or null | When this part started. UTC, ISO 8601 with milliseconds. |
calls[]. required | integer or null | Seconds. |
calls[]. required | string (uri) or null | Where to fetch this part (GET /v1/media/rec_<n>?part=N) with your key. Null while the part's file is not stored yet. |
meta required | object | Paging for list routes. Each list adds its own total. |
meta. required | integer | This page, from 1. |
meta. required | integer | Rows per page, after limits were applied. |
meta. required | integer | How many pages there are. |
meta. required | integer | Calls that match, across all pages. |
{
"query": {
"company_id": 1234567890,
"start_date": "2026-09-21",
"end_date": "2026-09-22",
"direction": "any",
"status": "any",
"search": "",
"timezone": "America/New_York"
},
"calls": [
{
"call_id": "3c9d7e1f-2a4b-4c6d-8e0f-1a2b3c4d5e6f",
"direction": "outgoing",
"status": "answered",
"extension": "104",
"extension_name": "Maya Chen",
"remote_name": "",
"remote_number": "7185550142",
"group_number": "7185550100",
"start_time": "2026-09-22T15:40:02.000Z",
"end_time": "2026-09-22T15:41:10.000Z",
"duration": 68,
"journey": [
{
"order": 1,
"type": "user",
"extension_name": "Maya Chen",
"extension": "104",
"start_time": "2026-09-22T15:40:02.000Z",
"end_time": "2026-09-22T15:41:10.000Z",
"duration": 68,
"summary": null,
"transcription": null,
"recording_url": null,
"recordings": []
}
]
},
{
"call_id": "8a1f3c2e-5b7d-4e9a-9c1b-2d4e6f8a0b1c",
"direction": "incoming",
"status": "answered",
"extension": "104",
"extension_name": "Maya Chen",
"remote_name": "Jordan Reyes",
"remote_number": "7185550142",
"group_number": "7185550100",
"start_time": "2026-09-21T14:03:12.000Z",
"end_time": "2026-09-21T14:09:40.000Z",
"duration": 388,
"journey": [
{
"order": 1,
"type": "auto_attendant",
"extension_name": "Main Menu",
"extension": "100",
"start_time": "2026-09-21T14:03:12.000Z",
"end_time": "2026-09-21T14:03:31.000Z",
"duration": 19,
"summary": null,
"transcription": null,
"recording_url": null,
"recordings": []
},
{
"order": 2,
"type": "user",
"extension_name": "Maya Chen",
"extension": "104",
"start_time": "2026-09-21T14:03:31.000Z",
"end_time": "2026-09-21T14:09:40.000Z",
"duration": 369,
"summary": "Jordan Reyes asked to move the Thursday appointment to Friday at 10 AM. Maya Chen confirmed the new time and said a reminder text will follow.",
"transcription": "Speaker 1: Good morning, thanks for calling. This is Maya.\nSpeaker 2: Hi Maya, this is Jordan Reyes. I need to move my Thursday appointment.\nSpeaker 1: No problem. Would Friday at 10 AM work?\nSpeaker 2: Friday at 10 is perfect. Thank you.",
"recording_url": "https://api.vocatech.com/v1/media/rec_48213907",
"recordings": [
{
"part": 1,
"parts": 2,
"recording_id": 10577640,
"start_time": "2026-09-21T14:03:32.000Z",
"duration": 41,
"url": "https://api.vocatech.com/v1/media/rec_48213907?part=1"
},
{
"part": 2,
"parts": 2,
"recording_id": 10577702,
"start_time": "2026-09-21T14:04:31.000Z",
"duration": 309,
"url": "https://api.vocatech.com/v1/media/rec_48213907?part=2"
}
]
}
]
}
],
"meta": {
"page": 1,
"limit": 500,
"total_pages": 1,
"total_calls": 2
}
}YYYY-MM-DD, an end before the start, or a window over 366 days.Example bodies
{
"error": {
"code": 400,
"type": "BAD_REQUEST",
"message": "Invalid date format or timezone. Use YYYY-MM-DD and a valid IANA timezone."
}
}{
"error": {
"code": 400,
"type": "BAD_REQUEST",
"message": "end_date is before start_date."
}
}{
"error": {
"code": 400,
"type": "BAD_REQUEST",
"message": "Ask for at most 366 days at a time (this request covers 400). For more history, walk it a year at a time."
}
}Retry-After seconds. The body names the counter, the window and the limit.| Header | Type | Description |
|---|---|---|
Retry-After | integer | Seconds to wait before you try again. |
Retry-After: 5), or a service this route needs could not be reached.| Header | Type | Description |
|---|---|---|
Retry-After | integer | Seconds to wait before you try again. |
