---
title: "Clip the best moments from one of the user's videos into vertical Shorts"
method: POST
path: "/api/v1/clip"
---

# Clip the best moments from one of the user's videos into vertical Shorts

`POST /api/v1/clip`

## Request

- Base URL: `https://everpop.app`
- URL: `https://everpop.app/api/v1/clip`
- Auth: HTTP bearer

## Headers

- `Idempotency-Key` string

## Request body

- object
  - `sourceVideoId` string, required: A video from GET /api/v1/videos with clippable: true.
  - `prompt` string: Optional steer, e.g. 'the most surprising moment' — omit and the AI picks
  - `clipCount` integer: How many clips. Omit for the account's saved clip count (3 if unset). Capped by the plan's clips per video (Starter 3, Pro 10, Scale 15); the response's clipCountApplied says what the job runs with.
  - `captionStyle` 'pop' | 'boxed' | 'minimal' | 'clean' | 'hormozi'
  - `language` string, nullable: Omit to use the saved language choice (English text by default). Null explicitly selects English captions, headlines and hooks with auto-detected speech (non-English speech is translated). A lowercase ISO-639-1 code such as bg pins that spoken language and keeps text native — so en means the speech IS English; never send en for non-English speech. Original audio is retained.
  - `archetype` 'top_moments' | 'summary' | 'punch' | 'action' | 'all': Editorial cut; all = a Summary, a Top-moment and a Punch from one pass. Omit for the normal best-moments pick.
  - `targetSeconds` integer
  - `aspectRatio` '9:16' | '1:1' | '16:9' | '4:5': The rendered frame. Omit for the account's saved setting (9:16 if unset). The response's aspectRatio says what the job renders at.
  - `captionsEnabled` boolean: Burn captions into the clips. Omit for the account's saved setting (on if unset). The response's captionsEnabled says what the job applied.

## Response `200`

Render started — poll the returned job. clipCountApplied, aspectRatio and captionsEnabled are the values the job runs with.

- ClipJobRefEnvelope
  - `ok` unknown, required
  - `data` ClipJobRef, required
    - `jobId` string, required
    - `status` 'PENDING' | 'PROCESSING' | 'COMPLETED' | 'FAILED' | 'CANCELED', required
    - `poll` string, required: Relative URL to poll, e.g. /api/v1/jobs/{id}
    - `clipCountApplied` integer, nullable, required: The clip count the job runs with after the plan's per-video cap (1 for a Summary or Punch, which deliver one video).
    - `aspectRatio` '9:16' | '1:1' | '16:9' | '4:5' | 'null', nullable, required: The aspect ratio the job renders at: the request's aspectRatio, or the account's saved setting when it was omitted.
    - `captionsEnabled` boolean, nullable, required: Whether the job burns captions in: the request's captionsEnabled, or the account's saved setting when it was omitted.

## Other responses

- `401`: The API key did not authenticate. code=key_missing: no Authorization: Bearer epk_... header. code=key_invalid: the key is unknown or revoked. code=key_expired: the key passed its expiry; the user creates a new one in Dashboard → API.
- `402`: REST and MCP need the Pro or Scale plan. reason=subscription: the account has no active subscription (subscribe, or redeem an invite code). reason=plan: the account's plan doesn't include this (API and agent access need Pro or Scale).
- `403`: code=scope (also reason=scope): the API key is read-only and this is a write. code=suspended: the account is suspended. Endpoint-specific refusals document their own reason.
- `404`: Source video not found for this account.
- `409`: code=idempotency_conflict — the Idempotency-Key was already used with different options.
- `422`: 422 with body.code: upload_required — this video's source is a YouTube URL and Everpop never downloads from YouTube; upload the file via POST /api/v1/videos/upload (+ /complete with linkSourceVideoId to attach it to this video), then clip. The body also carries uploadUrl, the sign-in-gated page where the user can upload the file themselves (for agents that can't send bytes). generated_source — a generated short's synthetic source (use /api/v1/generate). demo_source — Everpop's sample. validation_failed — the body did not validate. GET /api/v1/videos reports the first three ahead of time as clippable: false + notClippableReason.
- `429`: code=rate_limited (Retry-After 60); code=quota_exhausted (monthly videos used up; retryable: false, Retry-After = seconds until resetsAt — tell the user); or code=queue_capacity (render queue full; retryable: true, Retry-After 180).
- `503`: code=engine_offline — the clipping service is briefly unavailable; nothing was charged and the attempt is recorded as a failed job. Retry the same request in a few minutes.

---

[API](https://skmtc.dev/everpop/apis/everpop-api.md) · [All operations](https://skmtc.dev/everpop/apis/everpop-api/llms.txt) · [OpenAPI document](https://skmtc.dev/everpop/apis/everpop-api/revisions/1a9fb20867f5?raw)
