API Reference / Speakers

Enroll a voice sample

POST/v1/speakers/enroll

Saves a voice sample for a speaker so that later recordings can be verified against it. The speaker is created on first use. Send a recording of 15-60 seconds with at least 10 seconds of clear speech from that one person. Up to 5 samples per speaker; 2-3 samples from different sessions make verification more reliable. Main failures: too short, too long or too little speech (422, the message says what is needed), the speaker already has 5 samples (409), not enough credits (402). Requires scope speakers:enroll.

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}$

  • display_namestring

    Optional label for the speaker, shown in the dashboard.

    at most 128 characters

Response

200 The sample was saved.

  • request_idstringrequired
  • operation_idstringrequired
  • objectstringrequired

    always "speaker.enrollment"

  • speakerobjectrequired
    5 fields in speaker
    • speaker_idstringrequired

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

    • display_namestring or nullrequired
    • samplesintegerrequired

      Active enrollment samples for the current speaker model (max 5).

    • created_atstringrequired
    • updated_atstringrequired
  • qualityobjectrequired
    2 fields in quality
    • speech_secondsnumberrequired
    • duration_secondsnumberrequired
  • 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.enrollment",
  "speaker": {
    "speaker_id": "customer-4711",
    "display_name": "Ada Lovelace",
    "samples": 1,
    "created_at": "2026-10-13T09:30:00Z",
    "updated_at": "2026-10-13T09:30:00Z"
  },
  "quality": {
    "speech_seconds": 17.9,
    "duration_seconds": 19.2
  },
  "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.

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/enroll" \
  -H "Authorization: Bearer $DETECTIF_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -F "speaker_id=alice" \
  -F "file=@clip.wav"