PodcastsToText
Sources

File uploads

Presigned uploads for files you hold yourself, checked against your plan before they transfer.

POST/api/v1/uploadsscope: transcriptions:write

For audio you already hold. Ask for a presigned URL, PUT the bytes straight to storage, then transcribe the resulting link: the file never passes through the API.

Request body

FieldTypeRequiredDescription
filenamestringYesThe original name. Used for the stored key and the default title.
content_typestringYesThe file’s MIME type, e.g. audio/mpeg.
size_bytesnumberYesSize in bytes.

All three are required so the file is checked against your plan before you spend bandwidth uploading it.

The three steps

Ask, upload, transcribe
# 1. ask for somewhere to put it
RESP=$(curl -sS -X POST https://podcaststotext.com/api/v1/uploads \
  -H "Authorization: Bearer $PTT_KEY" -H 'Content-Type: application/json' \
  -d '{"filename":"episode.mp3","content_type":"audio/mpeg","size_bytes":82312904}')

UPLOAD_URL=$(echo "$RESP" | jq -r .upload_url)
AUDIO_URL=$(echo "$RESP" | jq -r .audio_url)

# 2. PUT the bytes; the Content-Type must match exactly
curl -X PUT "$UPLOAD_URL" \
  -H "Content-Type: audio/mpeg" \
  --data-binary @episode.mp3

# 3. transcribe it
curl -X POST https://podcaststotext.com/api/v1/transcriptions \
  -H "Authorization: Bearer $PTT_KEY" -H 'Content-Type: application/json' \
  -d "{\"audio_url\": \"$AUDIO_URL\"}"
200 OK
{
  "upload_url": "https://….r2.cloudflarestorage.com/…?X-Amz-Signature=…",
  "audio_url": "https://cdn.podcaststotext.com/uploads/{user_id}/{uuid}-episode.mp3",
  "key": "uploads/{user_id}/{uuid}-episode.mp3",
  "expires_in_seconds": 3600,
  "method": "PUT",
  "headers": { "Content-Type": "audio/mpeg" },
  "message": "PUT the file to upload_url, then create a transcription with audio_url."
}

The Content-Type must match. The presigned URL is signed against the content_type you declared. PUT with a different one and storage rejects it with a signature error that does not obviously say so. The URL expires after an hour, ask for a new one rather than storing it.

Accepted types and sizes

FreeCreatorProStudioPodmaxxing
Maximum file size10 MB1 GB1 GB1 GB1 GB
Maximum episode length30 minUncappedUncappedUncappedUncapped

Accepted containers: mp3, m4a, wav, aac, ogg, opus, flac, webm, mp4, mov. Rejections happen at step 1, before the transfer, with the limit or the accepted list in how_to_fix.