Call history

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

ConceptWhat it isWhere
Call recordOne 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}
outcomeHow the call ended, in the Analytics taxonomy, read together with direction. missed is the Missed group.Call outcomes
Partiesexternal (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 accountsA 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
Recordingsrecordings, 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
TranscriptsOne 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
AnalysesAI 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
JourneyThe 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 logWho 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
permissionsWhat 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.

CallerSeesContent (recordings, transcripts, analyses)Journey
Your account's admins, the reporting role, API keysEvery call of the account, internal calls includedEvery callEvery call
A userThe 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 mailboxOnly 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 onlyNever

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 from and to, the last 30 days. A date (2026-10-01) is read in your account's time zone, and a date-only to runs through the end of that day; an instant with a zone (2026-10-01T13:00:00Z) is exact. meta.time_zone names 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) and transcript_q (what was said). direction, type, outcome, company_number, external_number, extension, recording and hour_of_day repeat for several values; send every other filter once. company_number takes a phone number in any format, or a code as a record's company_number.code shows it (*611).
  • Pages: limit records per page (1 to 200, default 50). A page may hold fewer rows than limit, even none, while next_cursor is not null: keep going until it is null. A cursor carries your filters, works only for you, and expires after 24 hours (400 cursor_invalid).
  • Totals: with_total=true adds meta.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: ids fetches 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, sort and with_total do not apply (400 parameter_conflict).
  • Previews: include=previews adds transcript.preview (the first ~200 characters) and each analysis' headline where you may read them. Never recorded in the access log.
  • One extension: with exactly one extension, each row also carries extension_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.total can 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 permissions and GET /me within a minute. Revoking a key, changing its role or disabling its account takes effect within a minute.