API Reference / Speakers

POST/v1/speakers/verify

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.

Authentication

Send your API key as Authorization: Bearer <your API key>.

Headers

NameTypeDetails
Authorizationrequiredstring

Bearer <your API key>. Keys are created in the dashboard; see Authentication.

Idempotency-Keyoptionalstring or null

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.

1 to 128 characters

Request body

Send the request as multipart/form-data. Upload the audio file in the file field (up to 100 MB) and send the other fields as form fields. See Audio and limits.

  • filefilerequired

    The audio file: WAV, MP3, FLAC, OGG/Opus, WebM, M4A/AAC or AIFF, at most 100 MB.

  • speaker_idstringrequired

    Your identifier for the speaker (1-64 characters: letters, digits, _ . : -).

    1 to 64 characterspattern ^[A-Za-z0-9_.:-]{1,64}$

  • detect_deepfakeboolean

    Also check the same recording for AI-generated speech (needs scope deepfake:detect).

    default false

Response

200 The check completed.

  • request_idstringrequired
  • operation_idstringrequired
  • objectstringrequired

    always "speaker.verification"

  • speaker_idstringrequired
  • resultobjectrequired
    5 fields in result
    • decisionstringrequired

      match when similarity is at or above threshold.

      One of: match, no_match

    • similaritynumberrequired

      How alike the two voices are, from -1 to 1 (higher is more alike).

      -1 to 1

    • thresholdnumberrequired

      The similarity from which the decision is match.

    • similarity_semanticsstringrequired

      A short reminder of what similarity means.

    • duration_secondsnumberrequired

      Length of the checked audio, in seconds.

  • deepfakeobject or nullrequired

    null unless detect_deepfake=true; then either the synthetic-speech result or its error.

    2 fields in deepfake
    • option 1 (EmbeddedDeepfake)object
      11 fields in this option
      • verdictstringrequired

        The decision: real, fake (AI-generated), or not_sure (try a longer or cleaner recording).

        One of: real, fake, not_sure

      • labelstringrequired

        The same decision in the older wording: synthetic (fake), genuine (real), uncertain (not sure).

        One of: synthetic, genuine, uncertain

      • is_syntheticbooleanrequired

        true only when the verdict is fake.

      • scorenumberrequired

        How likely the recording is AI-generated, from 0 to 1.

        0 to 1

      • thresholdnumberrequired

        The main model's threshold (0.62). Informational: decide with verdict.

      • score_semanticsstringrequired

        A short reminder of what score means.

      • duration_secondsnumberrequired

        Length of the checked audio, in seconds.

      • segmentsarray of objectrequired

        Scores for consecutive, overlapping parts of the recording.

        3 fields in segments
        • startnumberrequired

          Start of this part of the recording, in seconds.

        • endnumberrequired

          End of this part of the recording, in seconds.

        • scorenumberrequired

          How likely this part is synthetic (0 to 1).

          0 to 1

      • operation_idstringrequired
      • credits_chargedintegerrequired
      • modelobjectrequired
        2 fields in model
        • namestringrequired

          Model family: aletheia (deepfake detection) or eidos (speaker verification).

        • versionstringrequired

          Opaque model version; it changes whenever the model is updated.

    • option 2 (EmbeddedDeepfakeError)object
      3 fields in this option
      • errorobjectrequired
        4 fields in error
        • typestringrequired

          One of: invalid_request, authentication, permission, not_found, conflict, rate_limited, insufficient_credits, payload_too_large, unsupported_media, unprocessable_audio, overloaded, internal

        • codestringrequired

          Stable snake_case error code.

        • messagestringrequired

          Human-readable explanation. Do not parse.

        • paramstring or null

          The request field the error refers to, if any.

      • operation_idstringrequired
      • credits_chargedinteger

        default 0

  • modelobjectrequired
    2 fields in model
    • namestringrequired

      Model family: aletheia (deepfake detection) or eidos (speaker verification).

    • versionstringrequired

      Opaque model version; it changes whenever the model is updated.

  • creditsobjectrequired
    4 fields in credits
    • chargedintegerrequired

      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.

    • balanceinteger or nullrequired

      Your available credits after this request; null on the unlimited plan.

    • original_chargeinteger or null

      Only on repeated requests (charged is then 0): the credits the original request used.

    • unlimitedboolean or null

      Present (true) only for accounts on the unlimited plan, where checks use no credits.

  • latency_msnumberrequired
  • idempotent_replaybooleanrequired

Example response

JSON
{
  "request_id": "req_8f14e45fceea167a5a36dedd",
  "operation_id": "op_6f1ed002ab5595859014ebf0951522d9",
  "object": "speaker.verification",
  "speaker_id": "customer-4711",
  "result": {
    "decision": "match",
    "similarity": 0.7412,
    "threshold": 0.53,
    "similarity_semantics": "Higher means the two voices are more alike. Not a percentage.",
    "duration_seconds": 4.1
  },
  "idempotent_replay": false
}

Errors

StatusMeaning
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.

Error bodies share one shape with a stable error.code; see Errors for every code and how to fix it.

Code samples

cURL
curl "https://platform.detectif.ai/v1/speakers/verify" \
  -H "Authorization: Bearer $DETECTIF_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -F "speaker_id=alice" \
  -F "file=@clip.wav"