---
title: "Init Direct Upload"
method: POST
path: "/api/v1/uploads/init"
---

# Init Direct Upload

`POST /api/v1/uploads/init`

## Request

- Base URL: `https://api.clipmaster.app` (the document declares no server; this is the origin it was published from)
- URL: `https://api.clipmaster.app/api/v1/uploads/init`
- Auth: HTTP bearer

Start a direct-to-S3 upload: validate, dedup, reserve tokens, and hand the
browser a presigned POST it uploads the file with.

Security model: the presigned POST policy carries a content-length-range
condition capped at the declared size_bytes — S3 itself rejects a larger
body at the wire. No server-side re-verification of the file happens; a
garbage upload fails in the pipeline exactly like a corrupt file on the
legacy path (task FAILED, tokens refunded).

The browser must call POST /uploads/{project_id}/complete after S3
returns 204 — that's what dispatches the processing pipeline.

## Request body

- DirectUploadInitRequest: Request body for POST /api/v1/uploads/init. The upload options mirror VideoUploadFromUrlRequest / the Form params of POST /api/v1/upload so the frontend reuses the same option set on every upload path. The first five fields describe the file the browser is about to PUT to S3 — size_bytes becomes the hard content-length-range ceiling on the presigned POST policy.
  - `filename` string, required
  - `size_bytes` integer, required
  - `sha256` string, required
  - `duration_sec` number, required
  - `content_type` string, required
  - `tags` string, nullable
  - `query` string, nullable
  - `min_duration` number, nullable
  - `include_captions` boolean, nullable
  - `karaoke_captions` boolean, nullable
  - `karaoke_color` string, nullable
  - `orientation` string, nullable
  - `processing_mode` string, nullable
  - `smart_crop_enabled` boolean, nullable
  - `gemini_analysis` boolean, nullable
  - `compilation_format` string, nullable

## Response `200`

Successful Response

- DirectUploadInitResponse
  - `project_id` integer, required
  - `upload` DirectUploadTarget, required: Presigned POST payload — browser POSTs `fields` + the file to `url`.
    - `url` string, required
    - `fields` object, required
  - `expires_at` string, required

## Other responses

- `422`: Validation Error

---

[API](https://skmtc.dev/clipmaster/apis/semantic-video-clip-ai-agent.md) · [All operations](https://skmtc.dev/clipmaster/apis/semantic-video-clip-ai-agent/llms.txt) · [OpenAPI document](https://skmtc.dev/clipmaster/apis/semantic-video-clip-ai-agent/revisions/c9b8333cd22b?raw)
