Windpaint
Generation

Uploads

Upload an image, video or audio file as an asset you can pass to a generation job.

POST /v1/generation/uploads

Stores a file as an asset in the current project and returns it. Use the asset’s id (or url) in a job’s inputs, for example as the start_frame of a wan-2.2-i2v clip. Uploads are free.

Scope: generation:write

Body

Send multipart/form-data with a single file part.

datafilerequired

The file. The part’s Content-Type decides the asset kind; when it’s missing, the type is guessed from the filename. The filename is kept as the asset’s filename.

X-Windpaint-Projectstring

The project to upload into, by id or slug. Defaults to your organization’s default project. A multipart body has no project_id field, so the header is the only way to pick a project here.

Accepted types, up to 50 MiB:

Content typeAsset kind
image/pngimage
image/jpeg (image/jpg is accepted as an alias)image
image/webpimage
video/mp4video
audio/mpeg (MP3)audio
audio/wavaudio

Images must decode; their width and height are read from the file. Video and audio uploads are stored as-is, with width, height and duration_s left null.

Response

201 Created with {"data": Asset}. See the Asset object for every field. Uploaded assets have source: "upload" and job_id: null.

Errors

StatusMessageCause
422Unsupported content type '<type>'.Not one of the types above. details.allowed lists them.
422Empty file.The part has no bytes.
422File exceeds 50 MiB.The file is larger than 50 MiB.
422File is not a readable image.An image type whose bytes don’t decode.
409The project is archived.
413Request Entity Too LargeThe request body is over 51 MiB (the 50 MiB file limit plus room for multipart framing).
408Request took longer than 120 seconds to processThe upload didn’t finish streaming within 120 seconds. Uses the timeout body, not the error envelope.