REST API quickstart

Upload audio, start a job, poll, download the transcript. Base URL: https://gimmetext.com/api/v1. Every request needs Authorization: Bearer gt_live_XXXX.

Tip (optional): The REST API takes audio. The upload page and AI links take any video. To send a video through the API, pull the sound out first:

ffmpeg -i input.mp4 -vn -ac 1 -c:a libopus -b:a 32k output.ogg

Then upload output.ogg. It's faster, much smaller, and your video stays on your computer.

curl

KEY=gt_live_XXXX
API=https://gimmetext.com/api/v1

# 1. Create an upload
curl -s -X POST $API/uploads -H "Authorization: Bearer $KEY" \
  -H "Content-Type: application/json" \
  -d '{"content_type":"audio/ogg","size_bytes":'$(wc -c < file.ogg)'}'
# → {"upload_id":"<uuid>.ogg","upload_url":"https://…","expires_at":"…"}

# 2. PUT the file
curl -s -X PUT "$UPLOAD_URL" -H "Content-Type: audio/ogg" --data-binary @file.ogg

# 3. Create a job (duration in seconds)
curl -s -X POST $API/jobs -H "Authorization: Bearer $KEY" \
  -H "Content-Type: application/json" \
  -d '{"upload_id":"'$UPLOAD_ID'","duration_seconds":600,"language":"en"}'
# → 202 {"id":"<job-id>","status":"queued"}

# 4. Poll until "done"
curl -s $API/jobs/$JOB_ID -H "Authorization: Bearer $KEY"

# 5. Download the transcript (txt, srt or json)
curl -s "$API/jobs/$JOB_ID/transcript?format=txt" -H "Authorization: Bearer $KEY"

Python

import os, time, requests

API = "https://gimmetext.com/api/v1"
H = {"Authorization": "Bearer gt_live_XXXX"}
path = "file.ogg"

up = requests.post(f"{API}/uploads", headers=H, json={
    "content_type": "audio/ogg", "size_bytes": os.path.getsize(path)}).json()
with open(path, "rb") as f:
    requests.put(up["upload_url"], data=f, headers={"Content-Type": "audio/ogg"}).raise_for_status()

job = requests.post(f"{API}/jobs", headers=H, json={
    "upload_id": up["upload_id"], "duration_seconds": 600}).json()

while True:
    s = requests.get(f"{API}/jobs/{job['id']}", headers=H).json()
    if s["status"] in ("done", "failed"):
        break
    time.sleep(5)

print(requests.get(f"{API}/jobs/{job['id']}/transcript?format=txt", headers=H).text)

JavaScript (Node 18+)

import { readFile } from "node:fs/promises";

const API = "https://gimmetext.com/api/v1";
const H = { Authorization: "Bearer gt_live_XXXX", "Content-Type": "application/json" };
const file = await readFile("file.ogg");

const up = await (await fetch(`${API}/uploads`, {
  method: "POST", headers: H,
  body: JSON.stringify({ content_type: "audio/ogg", size_bytes: file.length }),
})).json();
await fetch(up.upload_url, { method: "PUT", headers: { "Content-Type": "audio/ogg" }, body: file });

const job = await (await fetch(`${API}/jobs`, {
  method: "POST", headers: H,
  body: JSON.stringify({ upload_id: up.upload_id, duration_seconds: 600 }),
})).json();

let s;
do {
  await new Promise((r) => setTimeout(r, 5000));
  s = await (await fetch(`${API}/jobs/${job.id}`, { headers: H })).json();
} while (s.status !== "done" && s.status !== "failed");

console.log(await (await fetch(`${API}/jobs/${job.id}/transcript?format=txt`, { headers: H })).text());

duration_seconds is the audio length; it is checked against your remaining minutes. Get it with ffprobe -v error -show_entries format=duration -of csv=p=0 file.ogg.

Endpoints

MethodPathDoes
POST/uploads{ content_type, size_bytes } → { upload_id, upload_url, expires_at }
POST/jobs{ upload_id, duration_seconds, language? } → 202 { id, status }
GET/jobs?limit=20Your jobs, newest first (no transcript text)
GET/jobs/{id}status, progress, error, duration_seconds
GET/jobs/{id}/transcript?format=txt|srt|jsonThe transcript
DELETE/jobs/{id}Deletes the job and its transcript → 204
GET/usageplan, remaining_seconds, monthly_seconds, bonus_seconds, period_end

Errors and limits

Errors look like { "error": { "code": "...", "message": "..." } }.

StatusMeaning
401Missing or invalid API key
402Plan isn't active, or not enough minutes left
404Job or upload not found (or not yours)
409Transcript not ready yet
413File larger than your limit
429Over the per-minute request limit (free 10, paid 60) (wait Retry-After seconds) or too many jobs running

Full description: /openapi.json. See also Limits.

Questions? Start with the docs home or the machine-readable llms.txt.