~/docs cat detect-audio.md
Detect audio
Checks a recording for synthetic or cloned voice, and answers with one verdict for the recording plus a timeline with a value for every window of speech.
Send the file
curl
curl -X POST "https://api.scam.ai/v1/detections" \ -H "x-api-key: <YOUR_API_KEY>" \ -F "file=@/path/to/voicemail.mp3"
Recordings are sent as a file. Links are fetched for video only; see Detect from a link.
Parameters
| Field | Type | Meaning |
|---|---|---|
file | binary | The media file. MP3, WAV, FLAC, M4A, AAC or OGG, at most 50 MB. |
save | "true" | "false" | Keep a history row and the file. Default "true". With "false" nothing is stored and the run cannot be retrieved later. |
The response
- idstring
- The detection id. Pass it to GET /v1/detections/{id} to read the run back.
- statusstring
- Always
"completed". The answer arrives in the same request. - created_atstring
- When the run finished. RFC 3339, millisecond precision, always Z.
- mediaobject
- What was checked:
type(image, video, audio or document),filename,mime_typeandbytes. The last three can be null when they were not known.mime_typeis what the upload declared, so a client that sends no content type seesapplication/octet-streamhere;typecomes from the bytes themselves. - modelstring
- The model that answered,
"Eva V1.6". - verdictstring
LIKELY_REAL,ALERTorLIKELY_AI. Branch on this.- scorenumber | null
- 0 to 1, the probability the media is AI-made or manipulated. null when nothing could be scored.
- summarystring
- One sentence a person can read, matching the verdict.
- credits_usednumber
- What this run cost, an integer. 0 on a sandbox key, or when the same file was sent byte for byte from this account within 30 days.
- zero_charge_reasonstring
- Only when
credits_usedis 0:"sandbox"or"duplicate". - duration_msnumber
- The end of the last window in milliseconds, scored or not. Audio is billed by length.
- segmentsarray
- One entry per window:
start_ms,end_msandvalue(0 to 1, the probability that window is synthetic, or null when the window was not scored). - segments[].statusstring
scoredwhen the window has a value,abstainedwhen it does not.- segments[].reason_codesstring[]
- Only on an abstained window: why it was not scored, for example
no_voice_content.
response · 200
{
"id": "c3a9e1d0-7f24-4b6a-8e15-9d0c2b7a4f61",
"status": "completed",
"created_at": "2026-09-15T10:21:40.088Z",
"media": {
"type": "audio",
"filename": "voicemail.mp3",
"mime_type": "audio/mpeg",
"bytes": 131072
},
"model": "Eva V1.6",
"verdict": "LIKELY_AI",
"score": 0.96,
"summary": "This recording shows strong signs of synthetic or cloned voice.",
"credits_used": 1,
"duration_ms": 8000,
"segments": [
{ "start_ms": 0, "end_ms": 4000, "value": 0.9612, "status": "scored" },
{
"start_ms": 4000,
"end_ms": 8000,
"value": null,
"status": "abstained",
"reason_codes": ["no_voice_content"]
}
]
}Questions
- What is a window?
- The recording is scored in fixed-length windows. Each entry in
segments[]is one window, with its start and end in milliseconds and its ownvalue. Thescoreat the top of the response is the verdict for the whole recording. - Why is a window's value null?
- Nothing was scored there:
statusisabstainedandreason_codessays why, for exampleno_voice_contentwhen the window holds no speech. A null is never a 0. - Why does audio never answer ALERT?
- A recording is judged on one line, so it answers
LIKELY_REALorLIKELY_AI. Your code should still handle all three words, because the same integration will seeALERTon images and videos.