---
title: "A video is finished"
method: POST
path: "video"
tags: ["videos"]
---

# A video is finished

`POST video` (webhook)

POSTed to the request's callback_url once the video is completed, failed or cancelled: the video as get_video returns it. Kinetune-Signature is t=<unix seconds>,v1=<hex HMAC-SHA256 of "<t>.<body>"> with your callback secret. Answer with any 2xx within 10 seconds; anything else is retried after 30 s, 2 min, 10 min, 30 min and 2 h.

## Headers

- `Kinetune-Event` 'video.completed' | 'video.failed' | 'video.cancelled', required
- `Kinetune-Delivery` string, uuid, required
- `Kinetune-Signature` string, required

## Payload

- 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

## Acknowledgement `2XX`

Received

---

[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)
