---
title: "Step 2: finalize the uploaded file into a clippable video (auto-clips for active plans)"
method: POST
path: "/api/v1/videos/complete"
---

# Step 2: finalize the uploaded file into a clippable video (auto-clips for active plans)

`POST /api/v1/videos/complete`

## Request

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

rightsConfirmed must be the USER's attestation that they hold the rights — agents must ask, never assume. Pass linkSourceVideoId (a parked detected video from /videos) to attach the file to it: un-parks it and keeps its YouTube attribution. Idempotent per uploaded object. After an ambiguous PUT (timeout, dropped connection, or 412 on a retried PUT), call this with the same key first; cancel the slot only if it answers 400 (the bytes never landed).

## Request body

- object
  - `key` string, required
  - `title` string
  - `rightsConfirmed` unknown, required
  - `linkSourceVideoId` string
  - `renderMode` 'auto' | 'manual': auto: an account with automatic clipping on starts a render with its saved settings, and that render is this video's one monthly allowance. manual: no automatic render; pass it when you will call POST /api/v1/clip with your own options. The choice is durable — a retry that omits it keeps it.

## Response `200`

Idempotent adoption result. autoClipping=true means a render is already running; parked=quota means the file is safe but monthly videos are used up.

- FinalizeUploadEnvelope
  - `ok` unknown, required
  - `data` object, required
    - `videoId` string, required
    - `title` string, required
    - `existing` boolean, required
    - `linked` boolean, required
    - `autoClipping` boolean, required
    - `renderMode` 'manual': Present when this upload is held for a render the caller starts (renderMode manual).
    - `parked` 'quota'

## Other responses

- `400`: The uploaded object is missing or empty: the PUT never landed. PUT again while putUrl is valid, else cancel the slot and start a new upload.
- `401`: Missing, expired, or revoked API key.
- `402`: Subscription or plan does not allow API writes.
- `403`: Write scope, ownership, suspension, or the user's rights attestation blocks finalization.
- `409`: Account/video deletion fence, secure deletion, or upload_not_ready settlement fence. Retry only upload_not_ready with the same key.
- `413`: The stored object exceeds the 32 GB upload cap and is scheduled for secure cleanup.
- `422`: The request body, key, title, or linkSourceVideoId is invalid.
- `429`: Rate limit exceeded; replay the same key after Retry-After.
- `500`: Ambiguous service failure; replay the same key and never upload/cancel the bytes again.
- `503`: Ambiguous service failure; replay the same key and never upload/cancel the bytes again.

---

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