Skip to main content

Webhooks

Set webhook_url when you create a job, and the API sends one POST request, a callback, to that URL when the job ends. Use a webhook when you don't want to poll. This page covers jobs created with an API key. x402 jobs have their own webhooks.

Delivery​

  • The API makes one attempt and doesn't retry. If your endpoint is down or returns an error, that webhook is lost. Get the job to recover its status and output.
  • The request has no signature, and its only header is Content-Type. Anyone who knows your webhook URL can send it requests. Treat a webhook as a notification and confirm the result by getting the job. You can add a secret to your webhook_url, such as https://your-domain.com/webhook?token=SOME_SECRET, and check it.
  • The API sends final results only. It doesn't send progress. To receive progress and segments as they're transcribed, use can_stream_output.
  • A job that completes or fails sends a webhook. A job you cancel may also send one.
  • Make your handler safe to run twice for the same job id. The API makes one attempt, but a canceled job can send a webhook after its result, and anyone who knows the URL can repeat a request.

Payloads​

Completed​

The body is the same JSON as the completed job response, shortened here:

{
"id": "00000000-1111-7222-b333-444444444444-sic",
"output": {
"duration": 1246.679375,
"request": { "input_url": "https://example.com/audio-file.m4a" },
"segments": [
{
"confidence": 0.988,
"end": 7.296,
"id": 1,
"language": "en (99.60%)",
"processing_duration_in_s": 0.029,
"start": 0,
"text": "Imagine staring at um just a massive hard drive filled with gigabytes of raw video files.",
"words": []
}
]
},
"status": "COMPLETED"
}

If you created the job with an output_format, the body is the transcript in that format instead, with Content-Type: application/x-subrip for SRT or text/vtt for VTT. That body doesn't contain the job ID. To tell jobs apart, add your own identifier to each job's webhook_url, for example https://your-domain.com/webhook?ref=episode-42. Failed and canceled jobs always send JSON.

The webhook carries the full transcript even for a job created with is_private. Only request.input_url is redacted. See Private Jobs.

Failed​

{
"id": "00000000-1111-7222-b333-444444444444-sic",
"output": {
"error": "Expected at least 6 seconds; got 2.5 seconds"
},
"status": "FAILED"
}

output.error is a human-readable message, not a code. The webhook is the only place to get it, because getting a failed job returns an empty output. See Failures After a Job Is Accepted for the common messages.

Two failures happen while you create the job. The create request returns 400 Bad Request when the input_url isn't reachable, and 500 Internal Server Error with Failed to start a new transcribe job when the API can't start the job. In both cases the webhook also receives a FAILED payload with the same message, such as Input URL is not reachable: https://example.com/audio-file.mp3 (HTTP 403). The API doesn't save that job ID, so getting it returns 404 Not Found.

Canceled​

{
"id": "00000000-1111-7222-b333-444444444444-sic",
"output": {},
"status": "CANCELED"
}

The API sends this when a job you canceled stops. output can contain an error message that describes the cancellation.

Compared With x402 Webhooks​

Jobs APIx402 API
AttemptsOneUp to 12 within 24 hours
Signature and headersNo signature. Content-Type onlyNo signature. Content-Type, X-SiC-Event-ID, and X-SiC-Event-Type
Event typesNone. Every webhook is a job resultx402.outcome for a job result and x402.payment for a refund update