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

# Trigger Speaker Name Inference Route

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

## 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`
- Auth: one of:
  - API key in header `X-API-Key`
  - HTTP bearer

Trigger a manual, credit-billed, speaker-scoped re-run of transcript-based
speaker-name inference for an audio.

The name signal itself is face-independent: a quote-grounded model pass over the
diarized transcript that proposes a name per targeted speaker from self-intros
("Hi, I'm Mark") or third-person mentions ("Thanks, Priya"), each verified
deterministically against the real transcript text before being persisted onto
the speaker row and transcript sentences. For audio that belongs to a completed
video, a face already matched to that `speaker_id` is updated only when it does
not already carry an OCR-derived name. Interactive rename and a suggestion
commit via `PUT /v1/audios/{audio_id}/speakers/names` may overwrite an OCR-derived
face name; this persist path does not.

This endpoint mirrors the automatic, free, one-shot webhook hook, but without
either of its restrictions: it does not require the audio to be freshly unnamed
(targeting an already-named speaker is a legitimate, billed re-run — e.g. the name
was wrong, or wiped), and it never touches a speaker outside
`target_speaker_ids`, named or not.

This call is synchronous: it runs in-request (bounded by an internal timeout) and
returns the final result rather than a processing/queued status, unlike
`speaker-face-match`. A caller must be prepared to hold the connection open for
the duration of the model call.

## Request Body (required)

- `target_speaker_ids`: required, non-empty list of speaker ids to (re-)name. Every
  speaker not in this list is left byte-for-byte untouched, even if the model's
  transcript reasoning would otherwise have proposed something for them.
- `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`. Targeting
  a speaker for a role also targets them for a rename; callers who want a role
  proposal without a possible rename should use
  `.../speaker-name-inference/suggestions`. 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.

## Prerequisites

- User must be the audio owner or hold `MEDIA_WRITE`
- Audio must be in 'completed' status. If the audio has a parent video, that video
  must also be completed (a paid name can otherwise be overwritten with
  `Face {id}` when speaker-face matching writes back)
- The audio must be eligible for transcript-based name inference: not a
  meeting-platform ingest, no provider-supplied transcript/diarization, and no
  `speech_segments` pointer. A supplied or replaced transcript
  (`PUT /v1/audios/{audio_id}/transcript/replace`, or a URL+transcript upload)
  writes that pointer permanently, so Identify-people Suggest-names returns 400
  for those items rather than running. The transcript itself must already be
  available
- 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 rename (`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, or parent video 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/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)
