Asynchronous transcription for long audio and video
An honest job model: an instant 202, an id to keep, explicit statuses, polling, typed 402 refusals and a retry on the same job. The right tool as soon as the media is long.
# 1. Create the job — instant response, even for 2 h of audio
curl -i -X POST https://api.techtuel.com/v1/transcriptions \
-H "Authorization: Bearer $TECHTUEL_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "audio_url": "https://cdn.example.com/full-conference.mp3" }'
# HTTP/1.1 202 Accepted
# { "id": "job_1f88", "status": "processing", "minutes": 0 }
# 2. Poll until a terminal state
until curl -s https://api.techtuel.com/v1/transcriptions/job_1f88 \
-H "Authorization: Bearer $TECHTUEL_API_KEY" \
| jq -e '.status == "completed" or .status == "failed"' > /dev/null; do
sleep 10
done
# 3. Check the remaining allowance before a batch
curl https://api.techtuel.com/v1/usage \
-H "Authorization: Bearer $TECHTUEL_API_KEY"{
"id": "job_1f88",
"status": "completed",
"title": "Full conference — May 12",
"language": "en",
"minutes": 118.3,
"created_at": "2026-07-21T09:30:00Z",
"transcript": "Good morning everyone…",
"segments": [
{ "start_seconds": 0, "text": "Good morning everyone" }
],
"error": ""
}
// Quota refusal, on the POST:
// HTTP/1.1 402
// { "message": "monthly credits exhausted", "reason": "quota_exceeded" }Transcribing two hours of audio cannot fit inside one HTTP request: load balancer timeouts, connections dropped at 95% of the work, retries that are impossible because the only state lived in a socket. That is exactly where the job model is the right tool — and why POST /v1/transcribe, the synchronous endpoint that hands the transcript straight back, falls back to a 202 with a job id as soon as the wait window elapses. Short: one request is enough. Long: the job takes over.
The cycle. POST /v1/transcriptions returns 202 with an id and status processing. The job then moves to claimed when a worker picks it up, and finishes as completed or failed — only those last two are terminal. You read the status with GET /v1/transcriptions/{id}; on a completed job that same response already carries transcript and segments. A sensible cadence is every five to ten seconds on an active job, wider for background work, within the 120 requests per minute per key limit.
To be explicit about the mechanism: there are no webhooks. Tracking is done by polling, or by the wait POST /v1/transcribe performs for you server side. That is a constraint, but it comes with a real upside — no public endpoint to expose, no signature to verify, no replays to deduplicate, and a restarting worker simply picks up where it left off because the job id is durable.
Refusals are typed. When your quota is exhausted or a payment has failed, the API answers 402 with a { message, reason } body, where reason is quota_exceeded or payment_failed. That discriminator is what lets you pause your queue in one case and alert billing in the other, without parsing a message. GET /v1/usage gives you the picture up front — credits_used, credits_limit, rate_per_min, renews_at, billing_state — so you can check the remaining allowance before launching a batch. Finally, a failed job is re-run with POST /v1/transcriptions/{id}/retry, on the same id.
Why this API
No timeouts to manage
The 202 is immediate regardless of media length. Your HTTP request is never held open while the work runs.
Actionable 402 refusals
reason is quota_exceeded or payment_failed. Your queue can tell "wait for the renewal" apart from "alert billing".
Retry and inventory
POST /{id}/retry replays a failed job under the same id, and GET /v1/transcriptions paginates your jobs so you can reconcile after an incident.
Pricing you can read
Frequently asked questions
Are there completion webhooks?+
No. Tracking is done by polling GET /v1/transcriptions/{id}, or by letting POST /v1/transcribe wait for you server side. In exchange you have no public endpoint to expose, no signature to verify and no replays to deduplicate.
What are the possible job statuses?+
processing on creation, claimed once a worker picks it up, then completed or failed. On a failure the error field carries the reason.
How often should I poll?+
Every five to ten seconds on an active job is plenty; go wider for background work. The limit is 120 requests per minute per key on the Pro plan.
How should I react to a 402 response?+
Read the reason field. quota_exceeded means the monthly allowance is exhausted: pause the queue until renews_at. payment_failed is a billing matter and needs action on the payment method.
Can I process several media in parallel?+
Yes. Create as many jobs as the rate limit allows, keep their ids, then sweep the ones still running. GET /v1/transcriptions paginates them with page, per_page and api_key_id.
Other ways to use the API
Free trial, no credit card
Generate an API key and transcribe your first source in under a minute. A free monthly quota lets you test under real conditions.
Start with the API