Upload media
Store an image, video or audio file to use as a generation input, and list the files you have.
POST/api/v1/uploads
Every image, video and audio input of a generation must be a file stored on this service. Upload it here first, then pass the returned url in the model's input field. The URL of a previous task's output works too, and listing your files finds both.
Uploaded files go through the same checks as the studio: content moderation for images and video, your storage quota, and your plan's retention period (expires_at). On the free plan an upload is first kept for a few days; if it has been used as a generation input by then, it is kept for the plan's full retention period instead (the listing below shows the extended expires_at once that check has run). After several rejected files, uploads are paused for a while (upload_suspended). For audio and video, the server measures the duration itself — models priced by input length bill by that measurement.
Request
Send the raw file bytes as the body (not multipart form data).
| Part | Description |
|---|---|
Content-Type header · required | The file's MIME type, e.g. image/png, video/mp4, audio/mpeg. Only image, video and audio types are accepted, and not SVG. |
Content-Length header · required | The file size in bytes (most HTTP clients set it for you). |
filename query | Optional name, for your own bookkeeping. |
digest query | Optional SHA-256 of the file as 64 lowercase hex characters. Uploading the same bytes again with the same digest returns the existing URL instead of storing a copy — useful in batch jobs. |
curl "https://vidocraft.com/api/v1/uploads?filename=product.png" \
-X POST \
-H "Authorization: Bearer sk_test_xxxxxxxx" \
-H "Content-Type: image/png" \
--data-binary @product.pngResponse
201 Created
{
"url": "https://cdn.example.com/…/upload/image/9f86d08….png",
"mime_type": "image/png",
"size": 204813,
"duration": null,
"expires_at": "2026-10-22T10:36:31.248Z",
"deduplicated": false
}durationis the length in seconds for audio and video (nullfor images). If it isnullfor an audio or video file, the format could not be read; a model that prices by input length will refuse that file withmedia_unreadable— convert it to MP4, MOV, M4A, MP3, WAV, FLAC or OGG and upload again.- Check each model's limits before uploading:
GET /api/v1/modelslists, for every media parameter, the accepted MIME types, maximum file size, maximum count and duration bounds undermedia. - Test keys store files for real (a sandbox generation still validates its inputs), so uploads count against your storage quota in both modes.
Using the URL
Pass the URL in the model's media parameter. A parameter with media.multiple: true takes a list of URLs; one with media.frames: true takes a single URL (the first frame) or a two-item list [first frame, last frame].
{
"model": "image-to-video:wzkmnjbjb3av",
"input": {
"image_urls": ["https://cdn.example.com/…/first.png", "https://cdn.example.com/…/last.png"],
"multi_prompt": [{ "prompt": "the camera slowly pulls back", "duration": 5 }]
}
}A URL that is not a file on this service is refused with media_not_uploaded. The one exception is a domain the service operator has approved for direct links: its https URLs are accepted without uploading, and images and videos from it are moderated when the generation is submitted (moderation_blocked if rejected).
List your files
GET/api/v1/uploads
Lists the files you can pass as generation inputs — your uploads and your previous tasks' outputs — newest first. Deleted and expired files are left out, and only the API key owner's own files are ever returned.
| Query | Description |
|---|---|
type | image, video or audio. Omit for all three. |
source | upload (files you uploaded) or generation (task outputs). Omit for both. |
limit | Page size, 1–100. Default 20. |
cursor | The next_cursor of the previous page. Pages are stable: files added while you page through show up at the start, not in the middle. |
curl "https://vidocraft.com/api/v1/uploads?type=image&limit=2" \
-H "Authorization: Bearer sk_test_xxxxxxxx"{
"files": [
{
"url": "https://cdn.example.com/…/upload/image/9f86d08….png",
"type": "image",
"source": "upload",
"mime_type": "image/png",
"size": 204813,
"duration": null,
"filename": "product.png",
"task_id": null,
"created_at": "2026-09-22T10:36:31.248Z",
"expires_at": "2026-10-22T10:36:31.248Z"
},
{
"url": "https://cdn.example.com/…/image/1b4f0e9….png",
"type": "image",
"source": "generation",
"mime_type": "image/png",
"size": 1830042,
"duration": null,
"filename": null,
"task_id": "01J8Z…",
"created_at": "2026-09-21T08:12:05.004Z",
"expires_at": "2026-10-21T08:12:05.004Z"
}
],
"next_cursor": "MTc1ODQ0MjMyNTAwNDowMUo4Wi4uLg"
}next_cursor is null on the last page. task_id links an output to the task that produced it.