GET https://api.emaktalk.com/api/v2/call_records lists the calls on your account, one record per call. This guide gets you to a working paged request, then covers dates, paging, freshness, errors and recordings. The full parameter and field lists live on the endpoint pages: [List call records](ref:g
Call History gives you one record per call on your account: who called, who answered, how the call ended, whether it reached a mailbox, and the call's recordings, transcripts and analyses. Every Call History endpoint lives under https://api.emaktalk.com/api/v2/call_records; GET /me is at https://api.emaktalk.com/api/v2/me. This page is the overview; each endpoint page has the fields, parameters and errors.
Quickstart
Send your account API key as a bearer token. Call History needs a key with All permissions; a Scoped key is refused with 403 forbidden. See Authentication.
1. Who am I? GET /me says who you are, which account your requests read, and what you may do there.
curl https://api.emaktalk.com/api/v2/me \
-H "Authorization: Bearer $EMAK_API_KEY"2. List calls. GET /call_records returns the last 30 days, newest first, in pages. Follow next_cursor until it is null, sending it alone as cursor.
curl -G https://api.emaktalk.com/api/v2/call_records \
-H "Authorization: Bearer $EMAK_API_KEY" \
--data-urlencode "from=2026-10-01" \
--data-urlencode "to=2026-10-07" \
--data-urlencode "direction=inbound" \
--data-urlencode "missed=true"3. Read one call. GET /call_records/{id} returns the record complete. Name parts with include to get exactly those parts, in full.
curl -G https://api.emaktalk.com/api/v2/call_records/$CALL_RECORD_ID \
-H "Authorization: Bearer $EMAK_API_KEY" \
--data-urlencode "include=journey,recordings"4. Play a recording. Request a recording's media_url (GET …/recordings/{recording_id}) without following the redirect, and give the Location link to your player. The link works for one hour and must be fetched without your Authorization header.
curl -s -o /dev/null -w "%{redirect_url}\n" \
https://api.emaktalk.com/api/v2/call_records/$CALL_RECORD_ID/recordings/$RECORDING_ID \
-H "Authorization: Bearer $EMAK_API_KEY"5. Search what was said. transcript_q searches the transcripts; sort=relevance orders by match.score.
curl -G https://api.emaktalk.com/api/v2/call_records \
-H "Authorization: Bearer $EMAK_API_KEY" \
--data-urlencode 'transcript_q="cancel my order"' \
--data-urlencode "sort=relevance"Concepts
| Concept | What it is | Where |
|---|---|---|
| Call record | One call, whatever happened on it: ring-group fan-out, transfers, queue offers and forwards are part of the same call. Appears about 20 seconds after the call ends. History starts on May 1, 2026. Call records are never deleted. | GET /call_records, GET /call_records/{id} |
outcome | How the call ended, in the Analytics taxonomy, read together with direction. missed is the Missed group. | Call outcomes |
| Parties | external (the outside party), company_number (your number on the call), placed_by, answered_by. Numbers are E.164 (+15145551234). company_number is tagged by type: number (a phone number) or code (a code another account's phone dialed to reach you, such as 92205 or *611, with its label as of the call). An outside caller known only by name has number_e164: null. On an internal call, called is who the call was for (the extension, AI agent, number or code dialed), whether or not anyone answered; it is null on inbound and outbound calls. | the record |
| Calls between accounts | A call from another account's phone is inbound for the account it reaches, from an outside party, with its real outcome. The account that placed it has its own outbound record. Each account sees only its own record, recordings and transcripts. | Call outcomes |
| Recordings | recordings, in call order; usually one. Each has an id, a state (available, pending, deleted) and, when you may play it, a media_url and a download_url. | Play or download |
| Transcripts | One per recording, turn by turn with a speaker table. The record carries a transcript summary; fetch the text when its state is done. | Get a call transcript, Get a recording's transcript |
| Analyses | AI analyses of the call, keyed by kind. No kind is available yet: analyses is {} until one is turned on for your account. | Get a call analysis |
| Journey | The call flow, step by step: menus, ring groups, queues, who answered, transfers, who hung up. Admins, the reporting role and API keys only. | include=journey |
| Access log | Who played, downloaded, deleted or restored a recording, when a deleted recording was purged, and who read a transcript without being a participant on the call. The account's admins and API keys only. Deletions made in the older portal, and their purges, are not in it; purges are recorded from 21 October 2026. | include=access_log |
permissions | What you may do with this record's content: play_recording, read_transcript, read_analyses, delete_recording. | every record |
Who sees what
Every request reads exactly one account: the one you belong to. A reseller's access to its customers' accounts reads nothing here.
| Caller | Sees | Content (recordings, transcripts, analyses) | Journey |
|---|---|---|---|
| Your account's admins, the reporting role, API keys | Every call of the account, internal calls included | Every call | Every call |
| A user | The calls that touched their assigned extensions: placed, answered, forwarded from, picked up, dialed, rang in a ring group, offered by a queue, or reached their mailbox | Only calls they spoke on (answered or picked up, or placed and it connected) or that left a message in their mailbox; a call that reached the greeting and hung up gives the facts only | Never |
A caller whose recording access is off may play and read nothing. Assigned company numbers and chat-room membership grant no access. Asking for a part you may not see (include) is refused with 403 forbidden, never silently dropped.
Listing and paging
- Window: without
fromandto, the last 30 days. A date (2026-10-01) is read in your account's time zone, and a date-onlytoruns through the end of that day; an instant with a zone (2026-10-01T13:00:00Z) is exact.meta.time_zonenames the zone used. - Filters:
direction,type,outcome,missed,voicemail_left,company_number,external_number,extension,recording,duration_min,duration_max,hour_of_day,q(parties' names, including a contact's current name, or number digits) andtranscript_q(what was said).direction,type,outcome,company_number,external_number,extension,recordingandhour_of_dayrepeat for several values; send every other filter once.company_numbertakes a phone number in any format, or a code as a record'scompany_number.codeshows it (*611). - Pages:
limitrecords per page (1 to 200, default 50). A page may hold fewer rows thanlimit, even none, whilenext_cursoris notnull: keep going until it isnull. A cursor carries your filters, works only for you, and expires after 24 hours (400cursor_invalid). - Totals:
with_total=trueaddsmeta.total({ value, exact }), exact up to 10,000. Ask for it on the first page only; counting costs more than listing and is limited more tightly. - Known records:
idsfetches up to 100 records you already know, in the order given, whatever their date. An id you may not see is simply absent.limit,cursor,sortandwith_totaldo not apply (400parameter_conflict). - Previews:
include=previewsaddstranscript.preview(the first ~200 characters) and each analysis'headlinewhere you may read them. Never recorded in the access log. - One extension: with exactly one
extension, each row also carriesextension_outcome, that extension's own outcome. See Call outcomes.
Searching transcripts
transcript_q takes keywords or a short phrase, up to 200 characters, matched in English and French, word forms included. Web-search syntax: every word must appear, "a quoted phrase" matches in that order, -word excludes, or separates alternatives. Each matching row carries match: a score and up to three snippets with the matched words in **double asterisks**. Only calls whose transcript you may read match, and a deleted recording's transcript never does. A transcript becomes searchable a few minutes after the call. A search over a long window that runs too long is refused with 400 query_too_broad: narrow the window or add filters.
Recordings
Play or download. Each available recording you may play has a media_url and a download_url. Requesting either with your Authorization header answers a 302 redirect to a signed link that works for one hour; download=true serves the file as an attachment named for the call. Your player must fetch the link without your Authorization header. Store the record's and the recording's ids, never the link, and request the endpoint again when the hour is up. Apps may cache call metadata (the list, numbers, times) on devices, never recordings or transcripts: fetch content fresh each time, as Cache-Control: private, no-store on every answer says. Every GET is recorded in the call's access log as play or download; HEAD answers the same redirect to a link that answers HEAD only, and is never recorded.
Delete and restore. DELETE …/recordings/{recording_id} deletes one recording: at once, everywhere, it stops playing, links handed out before stop working, and its transcript is hidden. The call's analyses are kept and the call record stays. Until the recording's purge_at (30 days), POST …/undelete restores it; after that, the deletion is permanent. A purged recording stays deleted, with purge_at in the past, and its transcript is removed for good once no other recording of the call can still play, be restored or is on legal hold (until then it reads none). A recording placed on legal hold after its deletion is not purged until the hold is lifted. A legal hold blocks a deletion, never a restore. Batch delete takes up to 100 recording ids with a result per id.
Who may delete: your account's admins and EMAK support; an API key only when its "Can delete recordings" switch on the API keys page is on; users never. Each record's permissions.delete_recording says whether you may. A recording on legal hold can't be deleted by anyone until the hold is lifted (409 recording_not_deletable, details.reason legal_hold).
curl -X DELETE \
https://api.emaktalk.com/api/v2/call_records/$CALL_RECORD_ID/recordings/$RECORDING_ID \
-H "Authorization: Bearer $EMAK_API_KEY"Transcripts and analyses
Read the record's transcript summary first and fetch when its state is done. GET …/transcript returns every recording's transcript, whole, in call order; GET …/recordings/{recording_id}/transcript returns one. format=text returns plain text, one [m:ss] Speaker: text line per turn. Once at least one transcript exists and every one is done, the answer carries an ETag: send it back as If-None-Match, and a transcript you already hold answers 304.
curl -G https://api.emaktalk.com/api/v2/call_records/$CALL_RECORD_ID/transcript \
-H "Authorization: Bearer $EMAK_API_KEY" \
--data-urlencode "format=text"A transcript read is recorded in the call's access log as transcript_read unless the reader was a participant on the call; an API key is never a participant. Transcript times (start_sec, end_sec) count from the start of the recording; add the recording's offset_sec for seconds from the start of the call (offset_source says whether that offset is recorded or estimated).
GET …/analyses/{kind} returns one analysis of a call by its kind. Analyses are never recorded in the access log.
Errors and retries
Every error has one shape, with a code to branch on; see Errors. Page sequentially. On 429 and 503, wait the Retry-After seconds before retrying. Quote the X-Request-Id of any response when you report a problem.
Freshness
- Every read can lag a change by a few seconds: right after a recording is deleted or restored, a read can still show it as it was. The answer to the change itself is always current.
- With
transcript_q, for a few seconds after a recording is deleted or a permission changes,meta.totalcan count a call the list no longer returns. - A change to a key's "Can delete recordings" switch is enforced at once and shows in
permissionsandGET /mewithin a minute. Revoking a key, changing its role or disabling its account takes effect within a minute.
