---
title: "Get a video"
method: GET
path: "/api/v1/videos/{video_id}"
tags: ["videos"]
---

# Get a video

`GET /api/v1/videos/{video_id}`

## Request

- Base URL: `https://kinetune.com`
- URL: `https://kinetune.com/api/v1/videos/{video_id}`
- Auth: one of:
  - HTTP bearer
  - OAuth 2 (authorization code, authorization URL `https://kinetune.com/api/auth/oauth2/authorize`, token URL `https://kinetune.com/api/auth/oauth2/token`, scopes: `videos:read`)

Status, progress, credits and, when completed, the download links

status is queued, processing, completed, failed or cancelled. While it waits, queue says why: plan_limit (the organization already makes as many videos at once as its plan allows; position is its place in line) or render_capacity (every render machine is busy; estimated_wait_seconds is about how long). Completed videos have outputs with download_url (full quality), web_url (720p) and poster_url, signed for 7 days. A lyric video's poster is a frame with one whole lyric line on screen (the hook when it can be), ready to set as the thumbnail where you post it; a Canvas's is its first frame. poster_seconds says where in that file the poster was cut, for posts that take a cover frame offset instead of an image (TikTok); null on videos made before it was kept. Failed videos have error and error_code; AI_VIDEO_UNAVAILABLE means the AI video couldn’t be made for a reason on our side, so make it again later.

## Path parameters

- `video_id` string, required: The video id

## Response `200`

OK

- Video
  - `id` string, required
  - `type` 'lyric-video' | 'canvas', required
  - `variation` integer, required
  - `variation_count` integer, required
  - `quote_id` string, nullable, required
  - `status` 'queued' | 'processing' | 'completed' | 'failed' | 'cancelled', required
  - `stage` string, required: The step it is at while it is made
  - `progress` number, required: 0–100
  - `queue` object, nullable, required: Why the video is waiting, while it waits (its plan's limit, or every render machine busy); null otherwise
    - `reason` 'plan_limit' | 'render_capacity', required: plan_limit: the organization already makes as many videos at once as its plan allows, so this one starts when one of them finishes. render_capacity: every render machine is busy, so parts of this video wait their turn (higher plans get a larger share of the machines)
    - `position` integer, nullable, required: plan_limit: its place among the organization's waiting videos (1 starts next); null otherwise
    - `estimated_wait_seconds` integer, nullable, required: render_capacity: about how long until all of it is rendering, in seconds; null otherwise
  - `outputs` object[], required: One file per format, once delivered
    - `aspect_ratio` '9:16' | '16:9' | '1:1', required: The format of this file
    - `url` string: The full-quality file
    - `download_url` string: The full-quality file, saved under a readable name
    - `web_url` string: A 720p copy, for playback
    - `poster_url` string: A still of the video: for a lyric video one whole lyric line on screen (the hook when it can be), for a Canvas its first frame
    - `poster_seconds` number, nullable, required: Where poster_url was cut, in seconds from the start of this file (a trimmed clip counts from its own start): the cover frame offset for a post that takes one instead of an image (TikTok). Null for videos made before it was kept
    - `url_expires_in_seconds` integer: How long the links stay valid
    - `duration_seconds` number, nullable
    - `size_bytes` integer, nullable
    - `bitrate_kbps` integer, nullable
    - `web_size_bytes` integer, nullable
  - `song` object, required
    - `id` string, nullable, required
    - `title` string, nullable, required
    - `artist_name` string, nullable, required
  - `request` object, required: What the video was made from, with your metadata
  - `look_id` string, nullable, required
  - `look` object, nullable, required
  - `canvas` object, nullable: A Canvas: its design and, for stock, the credit to show
  - `quoted_credits` number, nullable, required
  - `charged_credits` number, nullable, required
  - `error` string, nullable, required
  - `error_code` string, nullable, required
  - `retry_of_job_id` string, nullable, required
  - `created_at` string, required
  - `updated_at` string, required

## Other responses

- `201`: Created
- `400`: Invalid request
- `401`: Missing or invalid credentials
- `402`: Not enough credits
- `403`: Missing scope
- `404`: Not found
- `409`: Conflict
- `422`: Unprocessable
- `503`: Temporarily unavailable (AI video): nothing was held; try again after Retry-After seconds

---

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