---
title: "Upload a media file"
method: POST
path: "/uploads"
tags: ["Uploads"]
---

# Upload a media file

`POST /uploads`

Gets a media file into your AITuber library and returns an `assetId` you can pass to other endpoints. Every upload has a `purpose` that says what the file is for; the purpose decides the validation rules and where the asset can be used.

**Two ways to upload:**

**1. From a URL** (easiest, works from AI agents): pass `sourceUrl` and we download the file for you. Only available for small image purposes (not video).

**2. Direct upload** (for local files): pass `contentType` and `fileSizeBytes` and you get back an `uploadUrl`. PUT your file bytes to that URL within 1 hour (set the same Content-Type header), then use the `assetId`.

**Supported purposes:**
- `clip-reference-image`, `clip-reference-video`, `clip-reference-audio`: input files for standalone clip generation. Images allow JPEG, PNG, or WebP up to 25MB. Videos allow MP4, MOV, or WebM up to 200MB. Audio allows MP3, WAV, M4A, AAC, OGG, or WebM up to 50MB. Direct upload only.
- `element-image`: a reference photo for an element (a person, product, or place). JPEG, PNG, or WebP, max 25MB. URL upload allowed. Use the `assetId` in `POST /elements`.
- `ugc-demo`: a product demo video for a UGC hook video. MP4, MOV, or WebM, max 200MB, up to 3 minutes. Direct upload only. Use the `assetId` as `demoVideoAssetId` in `POST /ugc/videos`.
- `music`: an audio track to score a music video. MP3, WAV, M4A, or AAC, max 50MB. Direct upload only, and `durationSeconds` is REQUIRED. Use the `assetId` as `musicAssetId` in `POST /music-videos`.
- `voice-sample`: an audio sample for voice cloning. MP3, WAV, M4A, AAC, OGG, or WebM, max 11MB. Direct upload only. Pass the `assetId` to the voice clone endpoint.

Uploads that are never attached to anything are deleted after 7 days.

## Request body

- object
  - `purpose` 'clip-reference-image' | 'clip-reference-video' | 'clip-reference-audio' | 'element-image' | 'ugc-demo' | 'music' | 'voice-sample' | 'agent-attachment', required — What this file is for. Only listed purposes are accepted; each unlocks specific endpoints (see the endpoint description).
  - `sourceUrl` string — A public URL to download the file from (image purposes only). Use this OR contentType+fileSizeBytes, not both.
  - `contentType` 'image/jpeg' | 'image/png' | 'image/webp' | 'video/mp4' | 'video/quicktime' | 'video/webm' | 'audio/mpeg' | 'audio/wav' | 'audio/mp4' | 'audio/x-m4a' | 'audio/aac' | 'audio/mp3' | 'audio/wave' | 'audio/x-wav' | 'audio/ogg' | 'audio/webm' — The file type for a direct upload. Returns an `uploadUrl` to PUT the bytes to. Must match the purpose (image, video, or audio).
  - `fileSizeBytes` integer — The file size in bytes for a direct upload. Max depends on the purpose (25MB images, 200MB video, 50MB audio).
  - `durationSeconds` number — For video (ugc-demo, 1-180) and audio (music, 1-600) uploads: REQUIRED. The clip or track length in seconds. Used to time the segment.
  - `videoWidth` integer — For video uploads (ugc-demo): the pixel width. Recommended so the demo is framed correctly.
  - `videoHeight` integer — For video uploads (ugc-demo): the pixel height. Recommended so the demo is framed correctly.

## Response `200`

OK

- object
  - `assetId` string, uuid, required — Pass this to the endpoint that consumes this purpose.
  - `url` string, required — The public URL the file will be served from.
  - `uploadUrl` string, nullable, required — Only for direct uploads: PUT your file bytes here within 1 hour, with the same Content-Type you declared. `null` for URL uploads (already stored).
  - `status` 'ready' | 'awaiting_file', required — `ready`: the file is stored and the assetId is usable now. `awaiting_file`: PUT your file to `uploadUrl` first.

## Other responses

- `401` — 401
- `402` — 402
- `403` — 403

---

[API](https://skmtc.net/aituber/apis/aituber-api.md) · [All operations](https://skmtc.net/aituber/apis/aituber-api/llms.txt) · [OpenAPI document](https://skmtc-service-staging.skmtc.workers.dev/v1/apis/aituber/aituber-api/revisions/35448566f143/schema)
