2026-11-01 · 6 min read
A Caption API for Agencies: Caption Every Client Video Without Adding an Editor
Agency math is unforgiving: every client expects more video, every platform defaults to muted autoplay, and every hour of manual captioning is an hour that cannot be billed twice. Captions are exactly the kind of high-value, low-judgment task that belongs in a pipeline instead of on an editor's plate.
caption.sh gives an agency that pipeline. Wherever final cuts land, a folder, a DAM, a client portal, a small script POSTs each one to the API and collects a captioned MP4 with word-timed, styled captions burned in. The client gets captioned deliverables as the default, and the agency stops choosing between quality and margin.
One function, every client
import time, requests, sys
KEY = "YOUR_CAPTION_API_KEY"
HEADERS = {"Authorization": f"Bearer {KEY}"}
API = "https://api.caption.sh/v1"
def caption_cut(video_url: str, font: str = "inter") -> str:
r = requests.post(
f"{API}/videos",
headers=HEADERS,
json={"source_url": video_url, "options": {"font": font}},
timeout=30,
)
job_id = r.json().get("job_id")
if not job_id:
sys.exit(f"submit failed: {r.status_code} {r.text}")
deadline = time.time() + 15 * 60
while time.time() < deadline:
job = requests.get(f"{API}/jobs/{job_id}", headers=HEADERS, timeout=30).json()
if job.get("status") == "done":
r = requests.get(
f"https://api.caption.sh/v1/jobs/{job_id}/result",
headers=HEADERS, allow_redirects=False, timeout=30,
)
return r.headers["Location"]
if job.get("status") == "error":
sys.exit(f"caption job failed: {job}")
time.sleep(5)
sys.exit("timed out waiting for caption job")Keep a small config per client, font and animation choices, and the same function serves the whole roster while each account keeps its own look. Results are stored for 24 hours and then deleted, so download into the client's delivery folder as soon as each job completes. Per-key rate limits mean a big multi-client batch should tolerate a 429 with a short wait and retry rather than erroring out.
Where the economics land
- Cost is a known number at $0.10 per minute, so captions can be priced into retainers instead of absorbed as unbilled editing time.
- Turnaround stops depending on editor availability; a cut exported at 6pm is captioned by 6:20, not tomorrow.
- Quality is uniform across junior and senior staff because the style is configured once per client.
Agencies win on reliability, and reliable captioning is a small, visible promise kept on every deliverable. Get an API key at caption.sh and run one client's latest batch through it.