# headcast Talking-head videos from a script. You send words, a presenter and a photo; you get a finished mp4. Base URL: https://headcast.ai Docs for humans and agents: https://headcast.ai/docs Every word of those docs in one markdown file: https://headcast.ai/docs.md ## Auth Every call: `Authorization: Bearer ca_...`. Keys are made by the account owner at /app/api, one at a time. Accounts are invite-only right now: https://headcast.ai/login#invite ## Price Plans, each with minutes of finished video a month: Starter $99 for 114 min, Creator $299 for 391, Pro $699 for 977, Max $1,299 for 1,955 (23% cheaper a minute than Starter). More minutes come as packs of 100, 250, 500, 1000 or 2500 bought from the billing page at $1.00 each, the same rate on every plan; bought minutes never expire. Starter has no API access; every plan above it does. Plan minutes reset monthly. A video is only accepted when the balance covers its estimate (402 otherwise). Minutes are reserved when a video is accepted and settled to the real length when it finishes. A failed render costs nothing. Minimum charge one minute. ## Endpoints GET /api/v1/me account, minutes left, limits GET /api/v1/presenters your presenters, newest first POST /api/v1/presenters multipart: name, image, audio -> 202, poll until status is ready POST /api/v1/presenters//voice {rate, expressiveness} -> saves and measures; reply carries the new voice block POST /api/v1/presenters//voice/preview same body -> audio/mpeg of a fixed passage, pace in X-Words-Per-Minute POST /api/v1/presenters//portrait multipart: image -> a new face on an existing presenter, voice unchanged POST /api/v1/presenters//voice/sample multipart: audio -> a new voice on an existing presenter, face unchanged GET /api/v1/videos your last 100 videos POST /api/v1/videos json: script + presenter (both required), title, setting, callback_url, qr -> 202 POST /api/v1/videos multipart: same fields, plus ad_clip + ad_text (your clip over one passage) and qr_image (your own code) POST /api/v1/voiceovers multipart: audio (+ presenter) -> {voice_token, text, unsure}; your own narration, read, free POST /api/v1/videos json with voice_token + script (the transcript, misheard words fixed) -> rendered to your recording POST /api/v1/videos multipart with audio (script optional) -> read and rendered in one call GET /api/v1/videos/{id} one video; poll every 10 to 30 seconds GET /api/v1/videos/{id}/assets the working files kept from the render, once it is archived POST /api/ad-slot/match json: script, passage -> {ok, words, seconds}; check a passage before submitting ## Rules an agent needs - script: 30 to 6,000 words, plain prose. Markdown, headings, timestamps and beat lines are stripped before the words are counted. - presenter: one front-facing photo of one person, and 8 to 30 seconds of them speaking alone. Uploads up to 12 MB. Presenters per account come from the plan (3 on Starter up to 50 on Max); read max_presenters from /api/v1/me. - status moves queued -> rendering -> done, or failed. Poll; there is no long-polling. - videos rendering at once depend on the plan (no queue beyond that); read max_inflight from /api/v1/me. - POST /api/v1/videos/{id}/cancel while it is queued (always its first 20 s): full refund. Once rendering it cannot be cancelled (409 already_started). A failed one can be tried again and it gets a new id. - callbacks are signed: HMAC-SHA256 hex of the raw body, header X-Cheapavatar-Signature, User-Agent cheapavatar-webhook/1. Both names kept the old brand so live receivers keep working. - errors are {"error": "sentence"} with a normal HTTP status. Retry 5xx and timeouts, never retry 4xx. - 403 means the key is on a plan without API access. 402 means the balance is short; it carries code "no_minutes", needed, balance and the packs on offer, and it happens on every plan. - about 40 minutes for a 10 minute video. The presenter is rendered with HeyGen Avatar IV. - ad slot: multipart ad_clip (mp4/mov/webm up to 90s and 100 MB, or jpg/png) + ad_text, the passage of the script it plays over copied exactly, 6 words or more. Narration keeps running under it. Up to 6 passages: one per line in ad_text, or ad_passages as a JSON array. The same clip plays over each. - qr: {"url" or "source":"upload", "always"|"passage"|"every_min"+"hold_sec", "x", "y", "size_pct"}. x and y are fractions of the frame for the code's top-left; size_pct is 5 to 40, default 14. "position" (tr/tl/br/bl) still works instead of x/y. Your own code: multipart qr_image, png/jpg/webp under 10 MB. - the video object carries ad_slot and qr as booleans. - your own voiceover: one voice alone, no music, 20s to 35 min, up to 100 MB. The transcript is the script. A script sent with it must be the same words (typos fixed); otherwise 400 code voice_script_mismatch, nothing held. voice_token lasts a day (then 400 voice_expired). Held on the recording's real length.