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.oggThen 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
| Method | Path | Does |
|---|---|---|
| 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=20 | Your jobs, newest first (no transcript text) |
| GET | /jobs/{id} | status, progress, error, duration_seconds |
| GET | /jobs/{id}/transcript?format=txt|srt|json | The transcript |
| DELETE | /jobs/{id} | Deletes the job and its transcript → 204 |
| GET | /usage | plan, remaining_seconds, monthly_seconds, bonus_seconds, period_end |
Errors and limits
Errors look like { "error": { "code": "...", "message": "..." } }.
| Status | Meaning |
|---|---|
| 401 | Missing or invalid API key |
| 402 | Plan isn't active, or not enough minutes left |
| 404 | Job or upload not found (or not yours) |
| 409 | Transcript not ready yet |
| 413 | File larger than your limit |
| 429 | Over 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.