Phone Call Records
Every phone conversation your voice agent has is kept: the calls it places for you, and — once the agent has its own phone number — the calls people place to it. Each record holds who was on the line, when the call happened, how long it lasted, a short summary, and the full transcript.Inbound calls used to be answered but not kept. If someone called your agent’s
number, the conversation happened and then vanished. It is now recorded the same
way an outbound call is, so a call that comes in at 9pm is still there in the
morning.
What a record contains
Calls come from two places: your voice agent places and answers them,
and your team can call a lead from your organization’s
number with Erdo ringing their own phone first. Both land
in the same records.
Ask in chat
The simplest way in. Ask for the calls themselves, or for one call’s transcript:“Has anyone called my Sofia number this week?”
“What did the caller say on that last call?”Erdo lists the calls — newest first, with direction, both numbers, duration and a summary — and reads back the full transcript of whichever one you pick. You can narrow to one agent or to inbound calls only just by saying so.
Your agent asks callers who they are
On an inbound call the person on the line is a stranger — Erdo has no other way to reach them. So the agent asks, naturally and at most twice, for their name and the best email or phone to follow up on, spells an email back to confirm it, and accepts a “no thanks” gracefully. What they share lands in the transcript and the summary. On an outbound call it does the opposite: you already told Erdo who to call, so the agent never asks the recipient for their own contact details.An inbound caller becomes a lead
Someone who dials your number is a stranger who wants something, which is what a lead is — so an inbound call that arrives with a caller ID is saved as one, whether or not the caller gave a name or an email. The number itself is enough to follow up on, and the carrier verified it, so it is the lead’s phone. A name and an email join the row when the caller gave them; the call’s summary rides along, so the row says why they rang. Two kinds of call produce no lead: one from a withheld number where the caller stated no way to reach them, and one whose details could not be tied to a single lead — the refused outcome described below. Outbound calls are not leads — you already knew who you were calling. The lead carriessource = phone_incoming_call, which is how you tell callers
apart from the leads your landing pages and website widget capture in the same
table — and from sms_incoming, the text conversations
that arrive on the same number and are governed by the same setting. Where the row lands is a setting on the phone deployment (Agents →
Deployments → the phone runtime → Save leads), resolved the same way a
widget’s is: a dataset you pick, else your organization’s leads dataset when you
have exactly one, else a “Widget leads” dataset Erdo creates for you (the name
is historical — it is the catch-all for leads with nowhere else to go). Untick the
setting and calls are still recorded — they just stop producing leads.
Someone who calls a second time from the same number is recognised: the call
merges into the lead their first call created rather than starting a second row,
and anything new they said — an email they didn’t give last time — fills in what
was blank. Identity is the email address where there is one and the phone number
otherwise, so a caller who leaves an email on one call and not on the next can
still land as two rows — the same limit a landing page has. Where the number
they rang from is already on more than one lead — a shared office or family
line, each person captured separately — Erdo writes nothing rather than guess
which of them called, and the record reads refused.
Each call record says what happened to its lead, so you never have to guess:
the contact Erdo read out of the call, and the outcome — created (a new
lead), existing (merged into a lead already in the table), disabled
(lead saving is off for this deployment), refused (the details could not be
tied to a single lead, so no row was written), or test (a preview or
automated check, never written).
A lead is not instant. The contact details are read out of the call after it
ends, so the row appears within roughly 15 to 30 minutes of hang-up — the same
pass that fills in the summary.
When someone spells their email
Speech recognition often mishears an unusual name, so a caller who says their email out loud will often spell it straight after. Erdo saves the spelled address, not the one it heard. Spellings in Spanish and Portuguese count too (“eme, a, erre…”, “arroba”, “ponto”). When the assistant reads a spelling back and the caller says yes, Erdo saves that confirmed spelling, and the assistant uses it for the rest of the call, goodbye included.contact records how the email and the name were given:
A
conflict is the case to look at before you write to someone: Erdo keeps the
address they spelled and shows you the other one rather than picking between
them without telling you. The follow-up engine reads these
fields too. The fields are missing on conversations read before Erdo started
recording them.
Read them programmatically
The same list-and-read surface is available over the REST API, the CLI, and to MCP clients, so a scheduled automation or an external dashboard can pull calls without going through chat. All of them are scoped to your organization by your credentials.- List —
GET /v1/voice/calls(or aPOSTwith a JSON body) returns each call’s id, direction, both numbers, status, timing, duration, summary, and the lead it produced, newest first and paginated. Narrow withagent(a voice agent’s slug),direction(inboundoroutbound) andcanonical_lead_id(one lead’s calls — see below); filters combine. Bound a reporting period withsinceanduntil— RFC3339 timestamps on when the call started, withsinceinclusive anduntilexclusive, so back-to-back periods such as two calendar months never count a call twice. Either bound can be left off, and asincethat is not beforeuntilis refused rather than answered with an empty list. The response’stotalis how many calls match the filters and the period at the moment of that request, whatever the page size — so a dashboard tile can show “37 calls this month” from one request;countis the number on this page.totalis live: a call that comes in while you page through can change it from one page to the next, so a multi-page read is finished when a response has nonext_cursor, not when the rows you have collected reachtotal. When a response includesnext_cursor, pass it back ascursorto read the next stable page, keeping the same filters and period — this avoids skips when a call comes in during a multi-page scan. MCP tool:erdo_voice_call_list. - Read one —
GET /v1/voice/calls/{call_id}, using acall_idfrom the list, returnstranscript_turns— the conversation ready to display, as[{role, text, at}], whereroleis who spoke (userfor the caller,agentfor your agent),textis what they said, andatis when (the call’s start plus how far into the call the turn came).atis set on inbound calls; outbound calls leave it off because the call record starts before the call is answered, and any turn whose timing is not known leaves it off too — along with the same conversation as plaintranscript_text, the raw transcript, a structuredturnsarray with per-turn model latency and token usage, and the same lead fields the list carries.transcript_turnsis an empty list when no transcript was captured. MCP tool:erdo_voice_call_get.
contact is the
{first_name, last_name, email, phone} Erdo read out of the call, lead_status
is created | existing | disabled | refused | test | no_booking, and
lead_saved_at is when that outcome was recorded. no_booking is on a call Erdo
placed to a lead on a booking phone line that ended without
a meeting booked — there was nothing to add to the lead. refused means the details could not be tied
to a single lead — they matched more than one, or the email and phone pointed at
different leads, or the call left nothing in the columns your leads dataset
identifies people by — so no row was written and the call was closed out rather
than retried. A first-time caller is not refused: their details match no
existing lead, so a new one is written and the call reads created. See
lead identity. Two
absences mean different things and are worth keeping apart if you are counting: contact is null while the call has not been read
yet and an object with blank fields once it has been read and nobody was
reachable, and lead_status is an empty string while the lead writer has not
reached the call rather than meaning no lead.
When your leads dataset uses lead identity, each call also
names the lead it became: canonical_lead_id is that lead’s permanent UUID and
lead_reference is the same id in the 22-character form a link or a text
message carries. This is the field to join on when you show a lead’s calls — the
caller’s number is only evidence, and the same person can reach you from two
numbers or leave an email on a second call. Pass either form as
canonical_lead_id on the list (GET /v1/voice/calls?canonical_lead_id=...) to
read one lead’s calls; it narrows your organization’s calls and never reaches
anyone else’s. The same filter works on text
conversations and widget
conversations, so one lead’s
whole history is three reads keyed on one id.
Both fields are empty in three cases, and none of them means “not a lead”: the
call is still waiting for its lead to be written, its leads dataset is not
enrolled in lead identity, or the call was recorded before calls carried the
lead’s identity — those older calls keep empty fields rather than being matched
to a lead after the fact. A call keeps the id its lead was written under, so
after two leads are merged the absorbed
lead’s calls still carry its id; reading the surviving lead lists the ids merged
into it, and filtering by each of those covers the whole history.
From the CLI:
Website chat widget conversations are a separate surface — they belong to a
widget rather than to a phone number. See Website
Concierge for those.
Good to know
- Voicemail is detected, not left. When the AI agent’s call reaches a
voicemail greeting or a carrier’s recording — in English, Spanish or
Portuguese, including a short fragment such as “después del tono” or a
“press 1” menu — it hangs up straight away without leaving a message, and
the record’s dial outcome is
voicemail. A call on which everything the other side said was such a recording isvoicemailtoo, even if the agent kept talking. A call where the other side said one short thing and then nothing until the agent hung up isno_answer. A call that connects but on which nobody says anything isno_answer. The follow-up engine treats both like a call nobody answered. Calls made before 9 October 2026 have no outcome on the AI agent’s calls that connected; read the summary for those. - Summaries fill in on their own. A call is summarized shortly after it ends, so a record read moments after hang-up may show a transcript before its summary.
- Records follow the agent, not the person. An inbound caller is not an Erdo user, so the record belongs to your organization and the agent that answered.
- Retention matches your other conversation data. Transcripts are visible to your workspace members through Erdo — treat them like any other customer communication.

