This resource is also
/conversations. /interviews is a permanent alias that keeps working unchanged; the newer name is the one to reach for in new code. See Resource names.Overview
A conversation is one AI-run call to one contact, by phone or on the web. Each is run by an agent and leaves behind a transcript, a recording, and either an analysis or the analytics the agent was configured to extract.Resource Structure
runId is null on a conversation created on its own, and carries the run’s id on one a
run produced — a run mints one conversation per contact. The
conversation.* and analysis.* webhook payloads carry
it too, so a batch can be attributed without reading the conversation back.The
analysis above is the recruiting pipeline’s output. A conversation run by a custom
agent instead carries an
analytics object beside it — usually without an analysis,
since none of the hiring jobs apply to it.Required Scopes
The legacy aliases (
read:interviews, write:interviews, delete:interviews) work identically and stay valid on keys that already carry them — see
Scopes and Permissions.
Creating Conversations
With an Existing Contact and Agent
Job selection: with an existing
contactId you may name a jobId to record which job
the conversation is for. It is required when the contact is associated with several jobs.
The job must belong to your API key’s company, but it need not be one the contact already
holds: if they are not assigned to it, creating the conversation assigns them.With an Inline Contact
Create a conversation with a contact that does not exist yet. A job is optional: With Job Association:Inline contact fields:
gdprExpiryDate is required, and must be a valid ISO 8601 date —
it is when this person’s data stops being yours to keep. jobId is optional; omit it to
create the contact with no job assignment and attach jobs later through the update contact
endpoint.With an Inline Job (Existing Contact)
Create a conversation for a contact you already hold while defining the job inline — useful when you know the job but do not want to create it as a separate request first.Inline Job Fields: -
jobTitle is required and must be between 5–200
characters. - Arrays like requiredSkills and niceToHaveSkills accept up to
10 skills each; each skill is a non-empty string up to 128 characters.
Combined total cannot exceed 10 skills. - Enum fields (such as languages,
education, experience, contractType) use the same values as the Jobs
API. - Nested objects location and salary reuse the core Job DTOs, so data
stored is identical to jobs created via the Jobs API. The inline job is
persisted as a regular Job during creation, and the conversation is
linked to it.XOR with
jobId: - Use jobId when you already have a job created. - Use
job when you want to define the job inline. - You must not send both jobId
and job in the same request (XOR behavior).With an Inline Contact and an Inline Job
Define both inline in a single request, when you already hold everything you need:Complete inline workflow: combining
contact with job - creates a new Job for your
company - creates a new Contact, automatically linked to that job - associates the
Conversation with both - and leaves all three as permanent resources. Nothing has to be
created in an earlier request.Ways to name the job: 1. Inline:
job at the top level defines and creates it in one
request 2. By reference: jobId at the top level, for a job that exists 3. Compact:
jobId inside contact, when creating the contact in the same request. Priority: if
several are sent, job > top-level jobId > contact.jobId. Do not combine
contact.jobId with a top-level jobId or job — which job you meant would be a guess.Scheduling
scheduleTime is optional. Omit it to place the call as soon as the agent’s calling hours allow, or send a future timestamp to pin it.
Deleting Conversations
Deleting a conversation removes it permanently, along with its transcript, recording and analysis.The conversation row itself is deleted outright, and its transcripts, recordings and analyses
go with it — a deleted conversation is gone from list and get, and no endpoint returns it
again. See Delete Conversation for what
happens to a call that is in progress at the time.
Conversation Status
status moves through the non-terminal values and settles on one of four terminal values. A terminal status holds until the conversation is deliberately reopened — see Reopening a terminal conversation below.
UNREACHABLE is new as of August 2026. It splits the “we could not reach them”
cohort out of FAILED and CANCELLED, which previously carried it
inconsistently depending on where the retry budget ran out. If you filter or report on
either of those, add UNREACHABLE — see the August 2026 changelog.Reopening a terminal conversation
Rescheduling a conversation that has already settled returns it toSCHEDULED and clears finishedDate. This applies to every terminal status — FAILED, UNREACHABLE, CANCELLED and COMPLETED alike. It keeps the same id and runs to an outcome as normal, so a terminal status is better read as terminal until somebody asks for another call than as final.
Only a deliberate action reopens one — a reschedule, an automatic retry, or an explicitly invoked attempt. Nothing reopens on its own. A reopened COMPLETED conversation keeps every transcript, recording and analysis it already has: those belong to the attempts that produced them, not to the conversation’s current status, so calling again adds to the record rather than replacing it.
Retrieving Results
Get a Conversation with its Analysis
List a Contact’s Conversations
Custom Agent Analytics
A conversation run by a custom agent carries a second, separate object:analytics, holding whatever that agent’s analyticsConfig asked for.
It is a sibling of analysis, not a variant of it. analysis is the recruiting pipeline’s output and is typically absent on a custom call — there is no analysisPdfBase64 either, since the PDF report is a recruiting artefact. analytics is the agent’s own design, and it is the only one of the two that appears outside hiring.
- The
keyon each field, outcome and tag is the one configured on the agent, so you can switch on it directly. value: nullmeans the call did not surface it — distinct from afalseor empty value that was surfaced. A contact who declines to answer gives younull; one who says “no” gives youfalse.confidenceandevidenceare omitted entirely when the value isnull.weightPercentis each item’s share of the match score, and the shares sum to exactly 100. The weights you configured are relative, not percentages, so a raw50tells a consumer nothing on its own.- In
scoring.items, an entry withkind: "question"carries the flow question’s id rather than a configured key — a question has none, which is why its scoring is set inline on the question.kind: "field"and"criterion"carry the configured keys. matchScoreis always present, andnullwhen scoring has not run yet.- In
qa,answered: falsemeans the call never reached the question — not that it was answered with nothing.answeris an empty string in both cases, so switch onanswered, not on the string. evaluationis four independent arrays of lines (strengths,concerns,objections,assessment). Any one of them can be empty while the others are populated, so check each rather than the object.- Each slice comes from its own after-call job, and each runs only when the agent asked for it — so an absent
outcomesorsentimentmeans “not configured, or not run yet”.
The same object is pushed to your
analysis.completed
webhook, so you do not have to poll for it. It
also appears on every row of GET /conversations.Analysis Structure
This section describes
analysis — the recruiting pipeline’s output, produced for
agents with a hiring focus. For a custom agent, see Custom Agent
Analytics above.general object holding the overall verdict and an optional specific object carrying whatever the agent’s focus produces.
General Analysis Fields
When there is no rating
overallRating comes back null when the model that scores the conversation could not be reached.
It is not zero and not a low score: no rating was produced. scoringIncompleteReason says why, and it
is the field to branch on rather than treating a missing rating as a bad one. A conversation that was
never analysed also has a null rating, and no scoringIncompleteReason.
The rest of the analysis is unaffected —
strongPoints, weakPoints, evaluation and the
specific data are produced by different calls and are present as usual. On a model_unavailable
run that recovers, the rating appears and the reason disappears; the
analysis.completed webhook fires again with the
filled-in analysis.
UNDEFINED, PRIMARY_EDUCATION, SECONDARY_SCHOOL_STUDENT, SECONDARY_WITHOUT_DIPLOMA, SECONDARY_WITH_DIPLOMA, POST_SECONDARY_VOCATIONAL, UNIVERSITY_STUDENT, BACHELOR_LEVEL, MASTER_LEVEL, POSTGRADUATE
Experience Level Values: UNDEFINED, NO_EXPERIENCE, LESS_THAN_1_YEAR, ONE_TO_3_YEARS, THREE_TO_5_YEARS, FIVE_TO_10_YEARS, TEN_TO_15_YEARS, MORE_THAN_15_YEARS
Conversation Types & Analysis
What lands inspecific depends on the agent’s focus. There are four hiring focuses; a custom agent has none of them and produces analytics instead.
- SCREENING
- OUTREACH
- GENERIC
- LANGUAGE_TEST
Standard hiring screenEvaluates the contact against the job’s requirements. The analysis uses only the
general fields — there is no specific data.Best Practices
Check Billing
Verify billing limits before bulk scheduling
Set Realistic Times
Leave buffer time, and let the calling window pick the hour
Monitor Status
Poll status, or take the webhook instead
Store Analysis
Save analysis data to your database
Next Steps
Agents
Create and configure the agents that run the calls
Contacts
Learn about managing contacts
Delete Conversation
What deletion removes, and what it cannot undo
Billing
Understand call costs and limits