Trigger Speaker Name Inference Suggestions Route
POST/v2/audios/{audio_id}/speaker-name-inference/suggestions
Trigger speaker-name inference in suggestions mode: same model pass and
evidence grounding as POST .../speaker-name-inference, same result rows, writes
nothing.
audios.speakers[].name is left byte-identical. No manual_name_inference_runs
audit append and no Deal-Person linking fire. The client reviews results and
commits accepted names through existing rename endpoints that do not charge:
PUT /v1/audios/{audio_id}/speakers/names— names only, including speakers with no matched face. Unlike the committing inference POST, a commit here may overwrite an OCR-derived face name on a completed parent video. Unknownspeaker_ids are skipped with a 200; there is noaudio.status == "completed"check and no parent-video check. A suggestion committed after a speaker merge/delete can silently no-op. A name committed while the parent video is still processing can be overwritten withFace {id}when speaker-face matching writes back. This is the primary commit path for both audio-only media and video-backed audio.PUT /v2/videos/{video_id}/speaker-face-match(namefield; requiresface_id) — updates both face and speaker. Only available when this audio has a parent video. Speakers with no matched face are out of scope. Unknownspeaker_id/face_idraiseInvalidSpeaker/InvalidFace; the video must becompleted. A stale id is a 4xx, not a silent skip.
Neither PUT re-runs this endpoint's validation (no synthetic-track refusal, no
duplicate-name guard). They also do not restore the Deal-Person linking or
manual_name_inference_runs stamp that the committing POST performs
(follow-up: #1375). Identify-people Save via this route then a PUT is a smaller
feature than the committing POST.
Duplicate-name grounding is per call against persisted speaker names. Because
this path writes nothing, two sequential per-speaker suggestion calls can both
accept the same name (e.g. "Alice"), and neither PUT dedupes.
Every successful call is billed. The amount is not quoted on the request; it is recorded after the run. A 502 (model failure or unparseable response) is not billed. The call is not idempotent: a double click is two model calls and two charges. The client must disable the control while in flight and must not blindly retry a gateway timeout — the request may still complete and charge after the client has given up.
Body and auth match the sibling POST. Audio must be completed; unlike the committing POST, an in-flight parent is not a 409. Synchronous: holds the connection for the model call. An all-rejected result is a successful billed run.
Request Body (required)
target_speaker_ids: required, non-empty list of speaker ids to (re-)name.infer_roles: optional, default false. When true, the same model pass also proposesagentorcustomerper targeted speaker, grounded in a quote from that speaker's own words. Independent of the name verdict. Roles are never written; commit them viaPUT /v1/audios/{audio_id}/speakers/roles. A speaker whose stored role is alreadyagentorcustomeris not offered a new role (role_already_set); clear the role and re-run to get a fresh proposal. Omitted and false are the same request. This is the path for a role proposal without a possible rename.
Prerequisites
- User must be the audio owner or hold
MEDIA_WRITE - Audio must be in 'completed' status. An in-flight parent video does not 409 this path: this call writes nothing. Committing a suggestion via PUT while the parent is still processing is a documented race (see the commit-path bullet above)
- The audio must be eligible for transcript-based name inference (non-meeting
upload with no provider-supplied transcript/diarization and no
speech_segmentspointer) and its transcript must already be available. A supplied or replaced transcript is a permanent 400, not a retryable state - Caller must have a positive credit balance. This call is billed on success; the amount is not quoted here. A 402 is returned before the model runs when admission is refused
Response
Returns at least one result row per requested target_speaker_id, each either an
accepted proposal (name, quote, pattern) or a rejection (reason) — including
a row for any targeted speaker the model could not resolve. Duplicate model rows for
the same id, if any, are not collapsed. When infer_roles is true, each row also
carries an independent role verdict (role_accepted, and on accept role plus
role_quote). Roles are not mutually exclusive across speakers. video_id is set
when this audio has a parent video; it is null for audio-only media.
Error Responses
- 401 Unauthorized: User is not authenticated or not authorized to access this audio
- 404 Not Found: Audio not found
- 409 Conflict: Audio processing not completed
- 400 Bad Request: Transcript not ready,
target_speaker_idsis empty, contains a speaker ID not present in the audio or naming a synthetic track, the audio (or its parent video) is not eligible for this feature, orvideo_idpoints at a missing video - 402 Payment Required: Admission refused. Detail is the admission
refusal_message. The wording differs for a zero vs. negative balance vs. a window refusal (buying credits does not fix the latter) - 422 Unprocessable Entity:
target_speaker_idsis missing/null, or contains a non-integer entry; orinfer_rolesis null or not a boolean - 502 Bad Gateway: The model call failed or returned an unparseable response. No charge is applied
Request
Responses
- 200
- 422
Successful Response
Validation Error