---
title: "Verify a speaker"
method: POST
path: "/v1/speakers/verify"
tags: ["Speakers"]
---

# Verify a speaker

`POST /v1/speakers/verify`

## Request

- Base URL: `https://platform.detectif.ai`
- URL: `https://platform.detectif.ai/v1/speakers/verify`
- Auth: HTTP bearer

Checks whether a recording is the voice of an enrolled speaker. Send a recording of 3-60 seconds with at least 2 seconds of speech. The result has a `decision` (`match` or `no_match`), a `similarity` from -1 to 1 (higher means more alike) and the `threshold` used for the decision. Main failures: unknown speaker (404), too short or too little speech (422), not enough credits (402). Requires scope `speakers:verify`.

With `detect_deepfake=true` the same recording is also checked for AI-generated speech (needs scope `deepfake:detect`; that check needs a recording longer than 4 seconds, otherwise only it fails). The two checks are counted separately, and only completed checks use credits:
* if the synthetic-speech check fails, you still get the verification, with `deepfake.error`;
* if the verification fails but the synthetic-speech check completed, you get the verification's error together with `partial` (the synthetic-speech result);
* if both fail, you get the error and no credits are used.

A retry with the same `Idempotency-Key` returns the same outcome again without running or counting the checks twice.

## Headers

- `Idempotency-Key` string, nullable: Optional (recommended) key that makes retries safe for 24 h: a retry with the same key and the same request returns the stored response without charging again.

## Response `200`

The check completed.

- VerifyResponse
  - `request_id` string, required
  - `operation_id` string, required
  - `object` 'speaker.verification', required
  - `speaker_id` string, required
  - `result` VerifyResult, required
    - `decision` 'match' | 'no_match', required: `match` when `similarity` is at or above `threshold`.
    - `similarity` number, required: How alike the two voices are, from -1 to 1 (higher is more alike).
    - `threshold` number, required: The similarity from which the decision is `match`.
    - `similarity_semantics` string, required: A short reminder of what `similarity` means.
    - `duration_seconds` number, required: Length of the checked audio, in seconds.
  - `deepfake` union, required: null unless detect_deepfake=true; then either the synthetic-speech result or its error.
    - EmbeddedDeepfake
      - `verdict` 'real' | 'fake' | 'not_sure', required: The decision: `real`, `fake` (AI-generated), or `not_sure` (try a longer or cleaner recording).
      - `label` 'synthetic' | 'genuine' | 'uncertain', required: The same decision in the older wording: `synthetic` (fake), `genuine` (real), `uncertain` (not sure).
      - `is_synthetic` boolean, required: true only when the verdict is `fake`.
      - `score` number, required: How likely the recording is AI-generated, from 0 to 1.
      - `threshold` number, required: The main model's threshold (0.62). Informational: decide with `verdict`.
      - `score_semantics` string, required: A short reminder of what `score` means.
      - `duration_seconds` number, required: Length of the checked audio, in seconds.
      - `segments` Segment[], required: Scores for consecutive, overlapping parts of the recording.
        - `start` number, required: Start of this part of the recording, in seconds.
        - `end` number, required: End of this part of the recording, in seconds.
        - `score` number, required: How likely this part is synthetic (0 to 1).
      - `operation_id` string, required
      - `credits_charged` integer, required
      - `model` ModelInfo, required
        - `name` string, required: Model family: `aletheia` (deepfake detection) or `eidos` (speaker verification).
        - `version` string, required: Opaque model version; it changes whenever the model is updated.
    - EmbeddedDeepfakeError
      - `error` ErrorDetail, required
        - `type` 'invalid_request' | 'authentication' | 'permission' | 'not_found' | 'conflict' | 'rate_limited' | 'insufficient_credits' | 'payload_too_large' | 'unsupported_media' | 'unprocessable_audio' | 'overloaded' | 'internal', required
        - `code` string, required: Stable snake_case error code.
        - `message` string, required: Human-readable explanation. Do not parse.
        - `param` string, nullable: The request field the error refers to, if any.
      - `operation_id` string, required
      - `credits_charged` integer
  - `model` ModelInfo, required
    - `name` string, required: Model family: `aletheia` (deepfake detection) or `eidos` (speaker verification).
    - `version` string, required: Opaque model version; it changes whenever the model is updated.
  - `credits` CreditsCharged, required
    - `charged` integer, required: Credits used by this request. A repeated request with the same Idempotency-Key uses none: it reports 0 here and what the original request used in `original_charge`.
    - `balance` integer, nullable, required: Your available credits after this request; null on the unlimited plan.
    - `original_charge` integer, nullable: Only on repeated requests (`charged` is then 0): the credits the original request used.
    - `unlimited` boolean, nullable: Present (true) only for accounts on the unlimited plan, where checks use no credits.
  - `latency_ms` number, required
  - `idempotent_replay` boolean, required

## Other responses

- `400`: The request is invalid, for example a missing or malformed field.
- `401`: The API key is missing, invalid or revoked.
- `402`: Not enough credits are available for this operation.
- `403`: The key lacks the required scope, the email address is not verified, or the account is suspended.
- `404`: Not found. Also returned for resources that belong to another account.
- `408`: The upload did not arrive in time (the whole file within 120 seconds, at least 64 KB per second).
- `409`: Conflict, for example a request with the same Idempotency-Key is still running, or the speaker already has the maximum number of samples.
- `413`: The upload is larger than 100 MB.
- `415`: Not a supported audio format, or the request is not multipart/form-data.
- `422`: The audio cannot be used (damaged, too short, too long, silent or too little speech; the message says what is needed), or the Idempotency-Key was already used for a different request.
- `429`: Too many requests or too many operations at the same time. Wait for the number of seconds in Retry-After.
- `500`: Something went wrong on our side. No credits were used.
- `502`: The check failed on our side. No credits were used; retry later.
- `503`: The service is busy, for example with many large uploads. Retry after the Retry-After seconds.
- `504`: The check took too long. No credits were used; retry later.

---

[API](https://skmtc.dev/detectif/apis/detectifai-developer-api.md) · [All operations](https://skmtc.dev/detectif/apis/detectifai-developer-api/llms.txt) · [OpenAPI document](https://skmtc.dev/detectif/apis/detectifai-developer-api/revisions/24295482ed77?raw)
