# clipsdk > Long video in, short clips out. Send a podcast, interview, webinar or stream VOD; get back its best moments as captioned, reframed vertical MP4s with titles and ready-to-post captions. Base URL: https://api.clipsdk.com Auth: `Authorization: Bearer csdk_live_...` on every /v1 call. File URLs need no auth. Docs: https://clipsdk.com/docs OpenAPI 3.1: https://api.clipsdk.com/openapi.json ## POST /v1/clips {"video_url": "https://example.com/podcast.mp4", "clips": 5, "aspect": "9:16"} - video_url (required): direct link to the video file (MP4, MOV, WebM or MKV, up to 3 h and 5 GB) or the video_url from POST /v1/uploads. Page links such as YouTube or TikTok are 400. - clips: 1-20, default 5. Fewer come back when the video has fewer good moments. - min_seconds, max_seconds: 10-90, default 20 and 60; max_seconds at least min_seconds + 5. - aspect: 9:16 (default), 1:1, 4:5, 16:9. - reframe: auto (follows the speaker, default), center, none (whole frame over a blurred copy). - captions: bold (default), karaoke, minimal or false. srt and vtt come back either way. - language: ISO 639-1 code like en; detected when absent. - prompt: up to 500 chars on what to look for, e.g. "moments about pricing". - webhook_url: HTTPS URL that gets the finished job. The call waits up to 60 s; change it with `?wait=0..300`, `Prefer: wait=N` or `Prefer: respond-async`. Clipping takes minutes, so expect 202 and poll, or pass webhook_url. ## GET /v1/jobs/{id} `?wait=0..300` holds the request until the job finishes (default 0). - 200 `{ "job": {...} }`: finished, succeeded or failed. - 202 `{ "job": {...} }` with `Location` and `Retry-After: 5`: queued or running. job: { id, op: "clips", status: queued|running|succeeded|failed, stage: fetching|transcribing|ranking|reframing|rendering (null while queued and once finished), created_at, finished_at, result, usage: { source_minutes, clips, output_seconds }, error: { code, message } | null, poll_url } result, only once succeeded: { source: { duration_s, language, speakers }, clips: [{ rank, score, title, reason, start_s, end_s, duration_s, transcript, post_caption, video, poster, srt, vtt }] }, best first (rank 1, score 0-100). video, poster, srt and vtt are file URLs. usage is zero unless the job succeeded; failed jobs cost nothing. ## POST /v1/uploads For files that have no public URL. {"filename": "talk.mp4", "size": 734003200} returns 201 { upload_url, video_url, expires_at }. PUT the raw bytes to upload_url with Content-Length and no Authorization header within 1 h, then pass video_url to POST /v1/clips. Up to 5 GB, kept 7 days. ## Files File URLs (outputs and uploads) work for 7 days, support Range requests and need no auth. ## Webhooks webhook_url gets a POST when the job finishes: { "event": "job.succeeded" | "job.failed", "job": {...same as GET...} }. Headers: `Clipsdk-Signature: t=,v1=." keyed with your webhook secret>`, `Clipsdk-Job-Id`, `Clipsdk-Attempt` (1-3), `Idempotency-Key: :`, `User-Agent: clipsdk-webhooks/1`. 3 attempts (now, +2 s, +8 s), 15 s timeout each; any 2xx counts as delivered. Reject signatures older than 5 minutes. ## Limits Sources up to 3 h and 5 GB (MP4, MOV, WebM, MKV). 1-20 clips of 10-90 s. Per key: 3 jobs running at once and 200 jobs per UTC day; over a limit you get 429 RATE_LIMITED with Retry-After (seconds). Files are kept 7 days. ## Errors Body: { "error": { "code", "message", "issues"? } } - 400 INVALID_REQUEST (issues lists { path, message }), INVALID_JSON - 401 UNAUTHORIZED, 404 NOT_FOUND, 413 PAYLOAD_TOO_LARGE, 429 RATE_LIMITED, 500 INTERNAL A failed job answers 200 with job.error.code: INPUT_FETCH_FAILED, INPUT_UNSUPPORTED, INPUT_TOO_LONG, INPUT_TOO_LARGE, NO_SPEECH, INSUFFICIENT_CREDIT (the video costs more than your credit covers, top up and retry) or INTERNAL (ours, safe to retry).