RSS transcription API

Automatically transcribe a podcast RSS feed

Read the feed, post each new episode enclosure, keep your own id, poll the job until it completes, store the transcript. About a hundred lines.

request
# Cron / GitHub Actions, every 5 minutes

# 1. New episode spotted in the feed → create the job
JOB=$(curl -s -X POST https://api.techtuel.com/v1/transcriptions \
  -H "Authorization: Bearer $TECHTUEL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "audio_url": "https://media.example.com/ep-143.mp3" }' \
  | jq -r .id)
# 2. Store $JOB next to the RSS item guid, then exit.

# 3. Next run: re-read the pending jobs
curl -s https://api.techtuel.com/v1/transcriptions/$JOB \
  -H "Authorization: Bearer $TECHTUEL_API_KEY" | jq '.status, .transcript'

# 4. On failure, re-run without creating a new job
curl -X POST https://api.techtuel.com/v1/transcriptions/$JOB/retry \
  -H "Authorization: Bearer $TECHTUEL_API_KEY"
response
{
  "id": "job_5ab7",
  "status": "completed",
  "title": "The Podcast — #143",
  "language": "en",
  "minutes": 48.9,
  "created_at": "2026-07-21T09:30:00Z",
  "transcript": "Episode 143, here we go…",
  "segments": [
    { "start_seconds": 0, "text": "Episode 143, here we go" }
  ],
  "error": ""
}

A podcast RSS feed makes an excellent trigger: it is public, ordered, and every item already carries the audio file URL in its enclosure. The whole pipeline fits in five steps, and none of them is hard — as long as you do not confuse "asynchronous" with "complicated".

Step 1 reads the feed and picks out the items you have not processed yet, keyed on the item guid. Step 2 posts the enclosure URL to POST /v1/transcriptions using the audio_url field; the 202 response gives you a job id. Step 3 is the one people skip: store that job id in your table next to your own episode identifier. That is what makes the whole process resumable if your worker restarts.

Step 4 is tracking: you poll GET /v1/transcriptions/{id} until status reads completed or failed. This writes very naturally as a loop that sweeps pending jobs on every run — a cron every five minutes, or a scheduled GitHub Actions workflow, is plenty for a show that publishes weekly. Step 5 stores transcript and segments, then marks the episode as done. A failed job can be re-run with POST /v1/transcriptions/{id}/retry.

The job model described here stays the right tool for a batch of episodes: submission is decoupled from tracking, and a restarting worker picks up where it left off. If you process episodes one at a time in a script, POST /v1/transcribe is shorter to write — it waits for the transcription and hands it straight back, with no job id to store and no loop to maintain.

Why this API

Resumable by design

The job id is durable: your worker can die between the POST and the end of processing, and recovery is just polling the job again.

Polling, on purpose

No webhooks means no public endpoint to expose, no signature to verify, no replays to deduplicate. A cron sweeping pending jobs is enough.

Explicit retry

A failed episode — a momentarily unreachable file — is re-run with POST /v1/transcriptions/{id}/retry, without creating a new job.

Pricing you can read

Free100 credits/month (~50 min) to validate the pipeline
Pro2000 credits/month (~1000 min), 120 req/min for a bulk backfill

Frequently asked questions

Are there webhooks to notify me when a job finishes?+

No, and for an RSS feed you do not need them. Two options: POST /v1/transcribe waits for the transcription and hands it back directly, which suits a script processing episodes one at a time; or keep the job model and sweep GET /v1/transcriptions/{id} periodically until completed or failed, which remains the most robust pattern for a batch of episodes driven by cron.

How often should I poll a job?+

Every five to ten seconds while a job is actively running, or once per cron run if you work in batches. The rate limit is 120 requests per minute per key on the Pro plan.

How do I avoid transcribing the same episode twice?+

Keep a table mapping the RSS item guid to the returned job id, and only create a job for unknown guids. On an already-transcribed public source the cache prevents double billing anyway.

How do I list my in-flight jobs?+

GET /v1/transcriptions accepts page, per_page and api_key_id. Handy for reconciling after an incident, or for dedicating one key to this pipeline and only seeing its jobs.

What if an episode fails?+

The job ends in status failed with an error field. POST /v1/transcriptions/{id}/retry re-runs the same job, so the reference stored in your database stays valid.

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