---
title: "Trigger Speaker Name Inference Suggestions Route"
method: POST
path: "/v2/audios/{audio_id}/speaker-name-inference/suggestions"
tags: ["Audio Emotion API"]
---

# Trigger Speaker Name Inference Suggestions Route

`POST /v2/audios/{audio_id}/speaker-name-inference/suggestions`

## Request

- Base URL: `https://api.imentiv.ai` (the document declares no server; this is the origin it was published from)
- URL: `https://api.imentiv.ai/v2/audios/{audio_id}/speaker-name-inference/suggestions`
- Auth: one of:
  - API key in header `X-API-Key`
  - HTTP bearer

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. Unknown
  `speaker_id`s are skipped with a 200; there is no `audio.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 with `Face {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` (`name` field; requires `face_id`)
  — updates both face and speaker. Only available when this audio has a parent
  video. Speakers with no matched face are out of scope. Unknown `speaker_id` /
  `face_id` raise `InvalidSpeaker` / `InvalidFace`; the video must be
  `completed`. 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
  proposes `agent` or `customer` per targeted speaker, grounded in a quote from
  that speaker's own words. Independent of the name verdict. Roles are never
  written; commit them via `PUT /v1/audios/{audio_id}/speakers/roles`. A speaker
  whose stored role is already `agent` or `customer` is 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_segments`
  pointer) 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_ids` is 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, or `video_id` points 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_ids` is missing/null, or contains a
  non-integer entry; or `infer_roles` is null or not a boolean
- **502 Bad Gateway**: The model call failed or returned an unparseable response.
  No charge is applied

## Path parameters

- `audio_id` string, required: Unique identifier of the audio. Audio must be in 'completed' status.

## Request body

- SpeakerNameInferenceRequest: Manual, speaker-scoped re-run of transcript-based speaker-name inference. ``target_speaker_ids`` is required and non-empty. ``infer_roles`` defaults to false; omitted and false are the same request.
  - `target_speaker_ids` integer[], required
  - `infer_roles` boolean: When true, the same model pass also proposes agent or customer per targeted speaker, grounded in a quote from that speaker's own words. Independent of the name verdict. Roles are never written; commit them via PUT /v1/audios/{audio_id}/speakers/roles. Default false; omitted and false are the same request.

## Response `200`

Successful Response

- SpeakerNameInferenceResponse: Response for a manual speaker-name-inference trigger. ``results`` has at least one row per requested target. Duplicate model rows for the same id, if any, are not collapsed. ``video_id`` is the parent video when this audio has one; ``None`` for audio-only media (standalone uploads store ``video_id: ""``, which is normalized to ``None`` rather than published as an empty string).
  - `video_id` string, nullable
  - `audio_id` string, required
  - `results` SpeakerNameInferenceResult[], required
    - `speaker_id` integer, required
    - `accepted` boolean, required
    - `name` string, nullable
    - `reason` string, nullable
    - `quote` string, nullable
    - `pattern` string, nullable
    - `role` 'agent' | 'customer', nullable: Proposed role. Present only when a role was accepted.
    - `role_accepted` boolean, nullable: True when the cited quote was found verbatim in a line this speaker spoke. The role itself is the model's judgement and is not verified.
    - `role_reason` string, nullable: Why the role was rejected. Omitted on accept. One of, checked in this order: role_already_set, insufficient_evidence, invalid_role, quote_too_short, quote_mismatch, wrong_speaker.
    - `role_quote` string, nullable: A quote from that speaker's own words that the model cited for the role. Present only when a role was accepted.

## Other responses

- `422`: Validation Error

## Changes

- **2026-09-08** `b10651168511`: 1 info
  - endpoint added

[Operation history](https://skmtc.dev/imentiv/apis/welcome-to-imentiv-ai/changes/v2/audios/:audio_id/speaker-name-inference/suggestions/post.md)

---

[API](https://skmtc.dev/imentiv/apis/welcome-to-imentiv-ai.md) - [All operations](https://skmtc.dev/imentiv/apis/welcome-to-imentiv-ai/llms.txt) - [OpenAPI document](https://skmtc.dev/imentiv/apis/welcome-to-imentiv-ai/revisions/bc15cec7e794?raw)
