---
title: "Video with its detected clips"
method: GET
path: "/api/videos/{id}"
tags: ["videos"]
---

# Video with its detected clips

`GET /api/videos/{id}`

## Request

- Base URL: `https://cliponit.app`
- URL: `https://cliponit.app/api/videos/{id}`
- Auth: one of:
  - HTTP bearer
  - API key in cookie `session`
  - OAuth 2 (authorization code, authorization URL `https://cliponit.app/oauth/authorize`, token URL `https://cliponit.app/oauth/token`, scopes: `clips`)

`state` (queued|running|ready|failed), `queue_position` and `eta_s` tell how long to wait (poll every ~10 s, or use the MCP `wait_video` tool). Clips are sorted chronologically (`position`). Pick by `score` (0-100, estimated viral potential) and read `reason`. `description`/`hashtags` are null until `describeClip` is called. `thumbnail_url` may be null while thumbnails are generated.

## Response `200`

Video + clips

- VideoDetail
  - `id` string, uuid, required
  - `title` string, required
  - `path` string: Server-side file path (informational)
  - `url` string, required: Source file, relative to the server, e.g. `/files/uploads/<id>.mp4`
  - `thumbnail_url` string, nullable
  - `thumbnail_path` string, nullable
  - `size_bytes` integer, required
  - `duration_s` number, nullable: Seconds, null until probed
  - `width` integer, nullable
  - `height` integer, nullable
  - `status` 'processing' | 'ready' | 'failed', required
  - `state` 'queued' | 'running' | 'ready' | 'failed', required: `processing` split by the job queue: `queued` (waiting behind other videos) or `running`; otherwise = `status`
  - `queue_position` integer, nullable: 1-based position in the processing queue while `state` is `queued`
  - `eta_s` number, nullable: Estimated seconds until `ready` (0.25 × (duration + durations of the videos ahead)); null when not processing
  - `progress` 'downloading' | 'probing' | 'transcribing' | 'detecting' | 'demo' | 'null', nullable: Current step while processing; null when ready/failed. `demo` = demo copy waiting for the master
  - `error` string, nullable: Why it failed
  - `is_demo` 0 | 1, required: 1 = the sample video seeded at signup (cannot be exported on the free plan)
  - `created_at` string, required
  - `clips_count` integer, required
  - `clips` Clip[], required
    - `id` string, uuid, required
    - `video_id` string, uuid, required
    - `position` integer, required: Chronological order
    - `title` string, required
    - `start_s` number, required: Absolute start in the source video (seconds)
    - `end_s` number, required: Absolute end (seconds)
    - `created_at` string, required
    - `score` integer, nullable: Estimated viral potential (AI)
    - `reason` string, nullable: One sentence explaining the score, in the transcript language
    - `description` string, nullable: Ready-to-post caption (null until `describeClip`)
    - `hashtags` string[], nullable: Without `#`
    - `thumbnail_url` string, nullable: `/files/thumbs/clips/<clip_id>.jpg`, 320 px frame at start_s + 1

## Other responses

- `404`: Resource not found or not owned by the user

---

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