Uploads
Upload a local image, video, or audio file to short-lived CDN storage and use the returned URL as a generation input.
POST /v2/uploads accepts a single multipart file and returns a public CDN URL you can drop into any image, video, or audio input field. Files live about 1–2 hours before they are deleted.
For media you will reuse across many jobs, use the Assets API instead — assets do not expire.
Upload a file
POST /v2/uploads
Send multipart/form-data with one file part. The API sniffs magic bytes and ignores the declared Content-Type.
Limits
| Kind | Max size | Allowed types |
|---|---|---|
| Image | 25 MB | PNG, JPEG, WebP, GIF |
| Audio | 25 MB | MP3, WAV, OGG, M4A |
| Video | 50 MB | MP4, WebM, MOV |
Response
Status: 201 Created
{
"id": "3f9d2a71-58f0-4f4e-9c6b-2f1f7d0a8b34",
"url": "https://cdn2.apiframe.ai/uploads/...",
"kind": "audio",
"contentType": "audio/mpeg",
"byteSize": 245123,
"expiresAt": "2026-08-14T16:00:00.000Z"
}Pass url as audioUrl, start_image, reference_images, or any other media URL field. After expiresAt the file is gone.
Code examples
curl -X POST https://api.apiframe.ai/v2/uploads \
-H "X-API-Key: afk_your_api_key_here" \
-F "file=@./demo.mp3"import requests
resp = requests.post(
"https://api.apiframe.ai/v2/uploads",
headers={"X-API-Key": "afk_your_api_key_here"},
files={"file": open("demo.mp3", "rb")},
)
url = resp.json()["url"]import { readFile } from "node:fs/promises";
const form = new FormData();
form.append("file", new Blob([await readFile("demo.mp3")]), "demo.mp3");
const resp = await fetch("https://api.apiframe.ai/v2/uploads", {
method: "POST",
headers: { "X-API-Key": "afk_your_api_key_here" },
body: form,
});
const { url } = await resp.json();