Poll analysis status
GET/api/v1/speech/analyze/:requestId
Returns the current status of a previously submitted analysis.
Safe to poll repeatedly. The minimum enforced interval is 10
seconds for non-terminal statuses; faster polls return 429.
Response shape varies by status:
queued/processing: lightweight status payload,Retry-Afterheader setsuccess/partial: full result payload with scores, analysis, transcriptfailed: terminal witherror.codeanderror.message
The id does not expire — you can stop and resume polling
later. (The path parameter accepts the same value returned as id
on submit.)
Webhook delivery (push instead of poll)
If you register one or more webhook endpoints for your account, every
terminal Speech run is also delivered to them as a signed POST — so
you can react to results push-style instead of polling. Register and
test endpoints from the webhooks console in your dashboard.
- Events:
speech.completed(asuccessorpartialrun) andspeech.failed(a failed run). There is no separatepartialevent — a degraded run arrives asspeech.completedwithstatus: "partial"and a non-emptywarnings[]array naming what degraded. - Body: the same result fields the poll endpoint returns for that
run (scores, analysis, transcript for a completed run;
errorfor a failed one), wrapped with aneventname. It never contains fields the poll response omits. - Signature: each delivery carries an
X-CVDM-Signatureheader of the formt=<unix-ts>,v1=<hex-hmac-sha256>. Recompute the HMAC over<t>.<raw-body>with your signing secret and compare in constant time before trusting the payload. - Retries: a non-2xx or timeout is retried up to 3 times with exponential backoff. Delivery is best-effort — the poll endpoint remains the source of truth if every attempt fails.
Example speech.completed (partial) body:
{
"event": "speech.completed",
"id": "req_1705412345678_abc123",
"status": "partial",
"timestamp": "2026-04-20T10:06:15.015Z",
"processingTimeMs": 62473,
"scoringMethod": "ml_hybrid",
"audio": { "durationMs": 180000, "languageCode": "eng", "requestedLanguage": "en", "speakerCount": 2 },
"scores": { "vocabulary": 4.37, "fluency": 4.63, "accent": null, "overall": 4.42, "cefrLevel": "C2" },
"warnings": [ { "code": "ACCENT_SCORE_UNAVAILABLE", "message": "Accent analysis was unavailable for this run." } ],
"degraded": ["ACCENT_SCORE_UNAVAILABLE"]
}
Example speech.failed body:
{
"event": "speech.failed",
"id": "req_1705412345678_abc123",
"status": "failed",
"timestamp": "2026-04-20T10:06:15.015Z",
"processingTimeMs": 42100,
"error": { "code": "TRANSCRIPTION_FAILED", "message": "Transcription failed: audio appears corrupted." }
}
Request
Responses
- 200
- 404
- 429
Current state of the run.
Request id not found (or belongs to another client).
Polled faster than the minimum 10s interval.