Automation API
Turn any video into a captioned MP4 with one request. Jobs run on CaptionTik’s render workers with the same engine and templates as the editor. Available on the Pro and Business plans; API render minutes are metered against your plan.
Base URL: https://captiontik.cyou/api/v1
Authentication
Create a key in Dashboard → API & jobs. Send it as a bearer token. Keys are shown once; revoke them at any time.
curl https://captiontik.cyou/api/v1/me \
-H "Authorization: Bearer csk_live_XXXXXXXX"Uploads (optional)
If your video is not publicly reachable, request a presigned upload URL, PUT the file to it, then reference the returned uploadKey.
curl -X POST https://captiontik.cyou/api/v1/uploads \
-H "Authorization: Bearer $CAPTIONTIK_KEY" -H "Content-Type: application/json" \
-d '{"filename":"talk.mp4","contentType":"video/mp4","size":48211200}'
# → { "uploadKey": "uploads/usr_…/talk.mp4", "uploadUrl": "https://…", "expiresIn": 3600 }
curl -X PUT --upload-file talk.mp4 -H "Content-Type: video/mp4" "<uploadUrl>"Create a job
POST /jobs
curl -X POST https://captiontik.cyou/api/v1/jobs \
-H "Authorization: Bearer $CAPTIONTIK_KEY" -H "Content-Type: application/json" \
-d '{
"videoUrl": "https://example.com/talk.mp4",
"template": "juno",
"variant": 1,
"controls": { "highlight-color": "#D9A85B" },
"language": "en",
"aiStyling": true,
"autoCutSilences": false,
"resolution": "1080p",
"subtitleFormats": ["srt", "vtt"],
"wordLevel": false,
"webhookUrl": "https://your.app/hooks/captiontik"
}'
# → 202 { "id": "cm3…", "status": "queued", … }| Field | Type | Description |
|---|---|---|
videoUrl / uploadKey | string | One is required. Public http(s) URL or a key from /uploads. |
template | string | Template id from GET /templates. Default juno. |
variant | integer | Colour preset index of the template. |
controls | object | Overrides for the template’s style controls (ids from GET /templates/:id). |
language | string | ISO code; omit to auto-detect. |
subtitles | string | SRT or WebVTT text to use instead of transcribing. |
aiStyling | boolean | Tag hook, emphasis words, entities and emoji with AI (counts one AI run). |
diarize | boolean | Label speakers when the transcription provider supports it; each speaker gets the template’s next colour preset. |
autoCutSilences | boolean | Remove pauses longer than 0.6 s. |
resolution | source | 720p | 1080p | 4k | Clamped to your plan’s maximum. |
format | mp4 | webm | Output container. Default mp4. |
subtitleFormats | array | Any of srt, vtt, ass, sbv, txt. |
wordLevel | boolean | Per-word timing in subtitle files where the format allows. |
webhookUrl | string | Receives the job JSON when it completes or fails. |
metadata | object | Your own string key/values, echoed back. |
Job status
GET /jobs/:id — poll every few seconds. GET /jobs lists your recent jobs. DELETE /jobs/:id cancels a queued job.
{
"id": "cm3…",
"status": "completed", // queued | downloading | transcribing | styling | rendering | uploading | completed | failed | cancelled
"progress": 1,
"durationSec": 42.3,
"output": { "url": "https://…/captioned.mp4", "expiresIn": 86400 },
"subtitles": { "srt": "https://…", "vtt": "https://…" },
"error": null,
"createdAt": "2026-10-30T09:12:00.000Z",
"completedAt": "2026-10-30T09:13:10.000Z"
}Webhooks
When a job finishes, CaptionTik POSTs the job JSON to your webhookUrl with headers X-CaptionTik-Timestamp and X-CaptionTik-Signature = hex HMAC-SHA256 of `${timestamp}.${rawBody}` using your webhook secret (Dashboard → API). Reject requests older than 5 minutes.
import crypto from 'node:crypto';
function verify(rawBody, ts, sig, secret) {
const expected = crypto.createHmac('sha256', secret).update(`${ts}.${rawBody}`).digest('hex');
return Math.abs(Date.now() / 1000 - Number(ts)) < 300 &&
crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(sig));
}Templates
GET /templates lists every template (id, name, category, description, colour presets). GET /templates/:id returns its style controls with types, defaults and bounds.
Errors & limits
| Status | Meaning |
|---|---|
| 400 | Invalid request body (details in issues). |
| 401 | Missing or invalid API key. |
| 402 | Monthly limit reached for your plan. |
| 403 | Plan does not include the API, or account suspended. |
| 404 | Job not found. |
| 429 | Too many concurrent jobs (Pro 3, Business 10). |
Outputs are kept for 7 days. Max input duration: 30 minutes per job.