Skip to main content
A webhook lets Vook tell your server when a job is done, so you do not need to poll. You pass a callback_url when you create the job, and Vook sends one signed request to that endpoint when the job reaches completed or failed.

Subscribe a job

Add callback_url to the body of POST /api/v1/transcription-jobs, whether you transcribe from a file or from a URL.
The endpoint must be public https on a standard port, up to 2048 characters. The job echoes it back as callback_url when you read the job, and returns null there for jobs created without one.

When it fires

Vook notifies the endpoint once per job, when the job reaches a terminal status (completed or failed). The event is transcription_job.resolved.

What your endpoint receives

Vook sends a POST request with a JSON body:
The body does not include the transcript itself. When data.status is completed, fetch it with GET /api/v1/transcription-jobs/{id}/transcript using your API key. The request carries these headers:

Verify the signature

Check the signature on every request before you trust its body. It proves the request comes from Vook and that the body was not changed on the way. Each API key has its own webhook signing secret, shown once when you create the key (see Authentication). Deliveries for a job are signed with the secret of the key that created the job. To verify a request:
  1. Read the raw request body as bytes, before any JSON parsing. Parsing and re-serializing changes the bytes and breaks the signature.
  2. Build the signed string: the X-Vook-Timestamp value, a period (.), then the raw body.
  3. Compute an HMAC-SHA256 of that string, using your signing secret as the key, and encode the result as lowercase hex.
  4. Split X-Vook-Signature on commas. Each part has the form v1=<hex>. Accept the request if any v1 value matches your result. The header can carry more than one value while Vook rotates its signing keys.
  5. Compare the timestamp to your clock and reject requests older than a tolerance you choose, such as five minutes. The timestamp is part of the signed string, so this blocks replays of a captured request.
Python
Use a constant-time comparison such as hmac.compare_digest, as above. Answer 400 or 401 when verification fails, and do not act on the body.
POST /api/v1/webhooks/test sends a sample signed with the same secret, so you can check your verification code before you send any audio. See Test your endpoint.

Respond and retries

Answer with any 2xx status within 10 seconds to acknowledge the delivery. Vook does not follow redirects, so a 3xx answer counts as not delivered. If the delivery does not succeed, Vook tries again. There are three attempts in total: when the job finishes, 10 minutes later, and one hour after that. After the third attempt, no further requests are sent for that job. Polling stays the source of truth. If your endpoint missed every attempt, read the job with GET /api/v1/transcription-jobs/{id} to get its final status.

Test your endpoint

Before you send any audio, check that your endpoint receives and accepts a request. POST /api/v1/webhooks/test runs the same callback_url checks as job creation, delivers a signed sample transcription_job.resolved payload, and returns the outcome. It starts no work and costs nothing.
A callback_url that is not public https on a standard port returns 400 with the error code invalid_callback_url.

Next steps

Transcribe from a file

Upload a file and create a job with a callback_url.

Transcribe from a URL

Create a job from a hosted file in one call.