Calls
Call Logs
Call logs are the account's call history: one row per call leg with direction, numbers, extensions, queue, duration, cost, whether a recording exists, and the notes and tags attached to it. This group is the list itself; recordings, notes, tags and reports have their own groups and are described here because the portal always uses them together.
Workflow (what the portal does)
- The list:
GET /v2/call-logis the call history grid. Filters (all optional, comma-separated where several values are allowed):from_date/to_dateasY-m-dorY-m-d H:i:s, read in theX-Timezoneyou send (or the user's profile timezone). Send both; with only one, the last month is used.type:incoming,outgoing,missed,unanswered, plusinclude_voicemail,include_playback,include_internal,group_missed_calls.numbers,incoming_number,outgoing_number,extensions,queues,tags(tag ids),notes(substring),search_for(contact or extension name, or a number),duration_above/duration_under,billsec_above/billsec_under(seconds),has_transcriptions,transcription.page,per_page(default 25, no maximum),sort_by(call_date,from,from_ext,to,to_ext),sort_dir(DESCby default).- The response is
{"_embedded": [rows], "_links": {…}, "page_count": <current page>, "page_size", "total_items"}. Lists of selectable extensions, numbers and queues for the user come with it in_selectable.
- One call:
GET /v2/call-logs/{callId}bycall_id(orcall_unique_id) returns the legs of that call as an array. - Recording: build the URL yourself from the row,
GET /v3/call-recording/{callId}with the row'scall_id;formatpicks MP3 (default), OGG or WAV,start/endtrim it. Deleting is admin-only:DELETE /v2/call-recording/{callUniqueId}. - Notes and tags on a call: read them with
GET /v2/call-notes?callIDs[]=…andGET /v2/call-tags?callIDs[]=…, passing the row'scall_id,sip_call_idandoriginal_sip_call_idtogether. Add a note withPOST /v3/call-notes(callId,note), assign a tag withPOST /v2/add-call-tag(call_id,tag_info_id); the tag catalogue isGET /v3/call-tags. - Transcript:
GET /v2/speech-to-text/{callUniqueId}when the account has transcription enabled. - Export:
GET /v2/call-log-exporttakes the same filters as the list and answers204: the CSV is built in the background and emailed to the requesting user, normally within minutes. The job is allowed 15 minutes; past that it is abandoned, not retried, and the user receives a failure email instead, so request again with a narrower range. An export holds at most 100,000 rows: above that the request answers422with the row count and the limit inmessage, and nothing is queued. The six-month limit on the date range is a portal rule, not an API one. Dates in the file are in theX-Timezoneyou send, or the user's profile timezone without it. - Reports (their own group): missed calls (paginated, with an export), top callers, busy hours by hour, day or month, and extension usage by direction or duration. All take
from_date,to_dateand, where it applies,extensionsortype.
Reading a row
call_unique_idis the row's own id;call_idis the telephony id shared by every leg of the same call (transfers, queue legs). Key your data oncall_unique_id, look recordings up bycall_id.directionisinbound,outboundorinternal;typeaddsmissed,unanswered,voicemail,playback;statusisANSWERED,NO ANSWER,BUSYorFAILED.- Who is who depends on
direction. Every number comes twice,from/toas stored andfrom_local/to_localin local format; pick one and show it consistently.- inbound: the caller is
from(orfrom_local), named byfrom_name(from_contact_idis the matched phonebook contact,from_name_sourcesays where the name came from); the number they dialled isto(orto_local) withto_name; the extension that took the call isto_extwithto_ext_name. On a missed callto_extis empty. - outbound: the agent is
from_extwithfrom_ext_name; the caller ID presented to the other side isfrom(orfrom_local) withfrom_name; the person called isto(orto_local) withto_name(to_contact_id). - internal: both sides are extensions,
from_ext/from_ext_nameandto_ext/to_ext_name. - For one user, a row whose
from_extis their extension is a call they made and a row whoseto_extis their extension is a call they received.
- inbound: the caller is
billsecis the connected time,durationthe total time including ringing.recordingistrueonly when a recording exists and the user may listen to it.extra.call_tagsandextra.call_notesare included in the row;transferred_childlists the ids of the legs a transfer created (fetch them withcdr_id=<ids>).
Roles and access
- Any authenticated user. An account admin, or a user whose call-log permission is "all", sees every call; everyone else sees only calls on their own extension and on the numbers, extensions and queues granted to them. With no grants the list is simply empty, not
403. - Recording playback needs the same visibility and recording access (the account's recording add-on or subscription); otherwise
403. - Deleting a recording and the admin missed-call export are admin-only.
- The ISO dates option (per account) switches
call_dateand note timestamps to ISO 8601 in the requested timezone (UTC by default). Without it dates areY-m-d H:i:sin the user's timezone.
Pitfalls
- The generated reference does not list the list's filters, because they are read from the raw query string. Use the parameters described above.
call_idis not unique: transfer and queue legs share it. Usecall_unique_idas the row key, and pass all three ids when reading notes and tags.page_countis the current page, not the number of pages; paginate ontotal_itemsandpage_size.- Choosing a direction in
typeexcludes voicemail and playback rows unless you addinclude_voicemail/include_playback. - Send filters as comma-separated strings, not as
extensions[]arrays. - Dates: an unparsable value silently becomes 1970-01-01; a value with a UTC offset is shifted. Send wall-clock times and set
X-Timezone. - There is no server-side cap on the date range or
per_page; the portals cap the range at six months. Recordings are kept for six months by default (longer with a retention add-on), so an older row withrecording: truecan still answer404. - Exports are asynchronous and arrive by email; the request itself returns no job id.