API Reference / Deepfake detection
Detect AI-generated speech
POST/v1/deepfake/detect
Checks whether a recording contains AI-generated speech. Send one audio file longer than 4 seconds and at most 120 seconds. Use the result's verdict: real, fake, or not_sure when the recording cannot be judged reliably (try a longer or cleaner recording). score (0 to 1, higher means more likely AI-generated) is kept for older clients together with label and is_synthetic. A not_sure verdict uses credits like any result, except when the check could not run completely: then credits.charged is 0. Main failures: the file is not audio or is damaged (415/422), 4 seconds or shorter or longer than 120 seconds (422), not enough credits (402), the service is busy (503, retry later). Requires scope deepfake:detect.
Authentication
Send your API key as Authorization: Bearer <your API key>.
Headers
| Name | Type | Details |
|---|---|---|
Authorizationrequired | string |
|
Idempotency-Keyoptional | string 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.
filefilerequiredThe audio file: WAV, MP3, FLAC, OGG/Opus, WebM, M4A/AAC or AIFF, at most 100 MB.
Response
200 The check completed.
request_idstringrequiredoperation_idstringrequiredobjectstringrequiredalways
"deepfake.detection"resultobjectrequired8 fields in
resultverdictstringrequiredThe decision:
real,fake(AI-generated), ornot_sure(try a longer or cleaner recording).One of:
real,fake,not_surelabelstringrequiredThe same decision in the older wording:
synthetic(fake),genuine(real),uncertain(not sure).One of:
synthetic,genuine,uncertainis_syntheticbooleanrequiredtrue only when the verdict is
fake.scorenumberrequiredHow likely the recording is AI-generated, from 0 to 1.
0 to 1
thresholdnumberrequiredThe main model's threshold (0.62). Informational: decide with
verdict.score_semanticsstringrequiredA short reminder of what
scoremeans.duration_secondsnumberrequiredLength of the checked audio, in seconds.
segmentsarray of objectrequiredScores for consecutive, overlapping parts of the recording.
3 fields in
segmentsstartnumberrequiredStart of this part of the recording, in seconds.
endnumberrequiredEnd of this part of the recording, in seconds.
scorenumberrequiredHow likely this part is synthetic (0 to 1).
0 to 1
modelobjectrequired2 fields in
modelnamestringrequiredModel family:
aletheia(deepfake detection) oreidos(speaker verification).versionstringrequiredOpaque model version; it changes whenever the model is updated.
creditsobjectrequired4 fields in
creditschargedintegerrequiredCredits 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 nullrequiredYour available credits after this request; null on the unlimited plan.
original_chargeinteger or nullOnly on repeated requests (
chargedis then 0): the credits the original request used.unlimitedboolean or nullPresent (true) only for accounts on the unlimited plan, where checks use no credits.
latency_msnumberrequiredidempotent_replaybooleanrequired
Example response
{
"request_id": "req_8f14e45fceea167a5a36dedd",
"operation_id": "op_6f1ed002ab5595859014ebf0951522d9",
"object": "deepfake.detection",
"idempotent_replay": false,
"result": {
"threshold": 0.62,
"score_semantics": "Higher means more likely AI-generated. Decide with the verdict, not the score alone.",
"verdict": "real",
"label": "genuine",
"is_synthetic": false,
"score": 0.0731,
"duration_seconds": 6.4,
"segments": [
{
"start": 0,
"end": 4,
"score": 0.061
},
{
"start": 2,
"end": 6.4,
"score": 0.085
}
]
}
}Errors
| Status | Meaning |
|---|---|
| 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 "https://platform.detectif.ai/v1/deepfake/detect" \
-H "Authorization: Bearer $DETECTIF_API_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-F "file=@clip.wav"import os
import uuid
import requests
with open("clip.wav", "rb") as f:
resp = requests.post(
"https://platform.detectif.ai/v1/deepfake/detect",
headers={"Authorization": f"Bearer {os.environ['DETECTIF_API_KEY']}", "Idempotency-Key": str(uuid.uuid4())},
files={"file": f},
timeout=300,
)
print(resp.status_code, resp.json())import { readFile } from "node:fs/promises";
import { randomUUID } from "node:crypto";
const form = new FormData();
form.append("file", new Blob([await readFile("clip.wav")]), "clip.wav");
const res = await fetch("https://platform.detectif.ai/v1/deepfake/detect", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.DETECTIF_API_KEY}`,
"Idempotency-Key": randomUUID(),
},
body: form,
});
console.log(res.status, await res.json());