Skip to main content
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:
Without 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

Scheduling Constraint: The scheduleTime must be a valid ISO 8601 date-time string and cannot exceed 30 days in the future. Attempts to schedule beyond this limit will result in a 400 Bad Request error.
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 to SCHEDULED 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.
If you stop polling when a conversation goes terminal, subscribe to conversation.rescheduled and resume when it fires. It is emitted on every reopen, so a poller that ignores it will never see the outcome of the new call. Until 28 August 2026 a terminal status was documented as never changing again — see the August 2026 changelog.

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.
Reading it:
  • The key on each field, outcome and tag is the one configured on the agent, so you can switch on it directly.
  • value: null means the call did not surface it — distinct from a false or empty value that was surfaced. A contact who declines to answer gives you null; one who says “no” gives you false. confidence and evidence are omitted entirely when the value is null.
  • weightPercent is 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 raw 50 tells a consumer nothing on its own.
  • In scoring.items, an entry with kind: "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.
  • matchScore is always present, and null when scoring has not run yet.
  • In qa, answered: false means the call never reached the question — not that it was answered with nothing. answer is an empty string in both cases, so switch on answered, not on the string.
  • evaluation is 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 outcomes or sentiment means “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.
The analysis object is the hiring assessment. It contains a 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.
Education Level Values: 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 in specific depends on the agent’s focus. There are four hiring focuses; a custom agent has none of them and produces analytics instead.
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