Inputs
What you can pass as an input to a job: asset ids, https URLs and data URIs, the supported formats and size limits, and the errors you get when an input doesn't fit.
Jobs and workflow runs take media inputs, such as the start_frame of a video. An input can be any of these:
| Reference | Example | What happens |
|---|---|---|
| Asset id | 8e1f2a3b-4c5d-4e6f-9a0b-1c2d3e4f5a6b | The asset is used as is. |
| Asset URL from this API | https://api.windpaint.ai/v1/generation/assets/{id}/content | Same as the id. |
Public https:// URL | https://example.com/frame.jpg | Fetched at submit and stored as a new asset with source: "url". |
data: URI | data:image/png;base64,iVBORw0... | Decoded at submit and stored as a new asset with source: "data_uri". |
They work everywhere an input is accepted: inputs on POST /v1/generation/capabilities/{capability}, image_urls on POST /v1/generation/models/{model}, and media inputs on workflow runs.
curl -X POST https://api.windpaint.ai/v1/generation/capabilities/video.generate \
-H "Authorization: Bearer $WINDPAINT_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"prompt": "slow dolly in, steam rising from the cup",
"inputs": {"start_frame": ["https://example.com/cup.jpg"]}
}'
An asset stored from a URL or data URI belongs to the job’s project and behaves like an upload afterwards: it appears in GET /v1/generation/assets, has its own id and url, and can be reused by id, so you only need to send the URL once. source_url holds the URL as you sent it; it’s null for data URIs. Estimate endpoints check prices without fetching URLs or storing anything.
Formats and limits
The same rules apply to uploads, URLs and data URIs. The format is detected from the file’s bytes; the extension and any declared content type are ignored, including the media type written in a data URI.
| Kind | Formats | Max size | Other limits |
|---|---|---|---|
| Image | PNG, JPEG, WebP | 20 MiB | Long edge at most 8192 px, short edge at least 64 px |
| Video | MP4, MOV, WebM | 200 MiB | At most 60 seconds |
| Audio | MP3, WAV, M4A, OGG | 25 MiB | At most 5 minutes |
- GIF, HEIC, HEIF and AVIF images are rejected. Convert them to PNG, JPEG or WebP first.
- An MP4 or M4A file with only audio streams is treated as audio (
audio/mp4) and gets the audio limits. - A
data:URI can be at most 5 MiB once decoded, and then the per-kind limits apply. Base64 and percent-encoded data URIs both work. - A submit body can be up to 32 MiB, enough for a few data URIs. For larger files, use a URL or upload first.
- The input must also be a kind the slot accepts: an audio file in
start_framereturns422.
Fetching URLs
Windpaint downloads a URL input when you submit, before the job is queued:
- Only
https://URLs are fetched, and every redirect must also behttps://. At most 5 redirects. - The whole fetch has 30 seconds. A submit that fetches URLs can take up to that much longer to answer.
- The final response must be HTTP
200. The size limit is enforced while downloading. - Hosts that resolve to private, loopback, link-local, CGNAT, multicast, reserved or cloud metadata addresses are refused.
- Requests come with
User-Agent: Windpaint-Fetcher/1.0.
The URL must be reachable without credentials. For files behind auth, pass a pre-signed URL or upload the file. Windpaint checks your balance and the model’s availability before downloading anything, so a submit that fails with 402 or 503 fetches nothing.
Errors
Input errors return 422 in the standard error envelope. For URL and data-URI inputs, details.input echoes the reference; data URIs are cut to their header plus ,....
code | When | details |
|---|---|---|
input.invalid | An empty file, a malformed data URI (no comma, bad base64, empty), a URL that isn’t https://, or a value that isn’t an id, asset URL, https:// URL or data URI. | value for bad references |
input.unsupported_format | The bytes aren’t a supported format, or can’t be read as the detected kind. | detected (such as "GIF", or null), allowed |
input.too_large | Over the size limit for its kind, or over 5 MiB for a data URI. | kind, size_bytes (null when the limit was hit while downloading), max_bytes |
input.dimensions | An image’s long edge is over 8192 px or its short edge under 64 px. | width, height, max_long_edge, min_short_edge |
input.duration | A video over 60 seconds or audio over 5 minutes. | kind, duration_s, max_duration_s |
input.fetch_failed | The URL couldn’t be fetched. The message is Could not fetch input URL: <reason>. | url, reason |
Typical reason values: the server answered HTTP 404., Host '<host>' resolves to a non-public address., only https URLs are fetched., timed out after 30 seconds, more than 5 redirects.
A fetched input whose kind doesn’t fit the slot returns 422 with code request.validation_failed and details {slot, input, kind} ({input, kind} for workflow runs, where input is the input’s name).
In the CLI and MCP server
The CLI’s -i slot=<value> accepts a local file, an asset id, an asset URL, an https:// URL or a data: URI; local files are uploaded first. In the MCP server, the generate, run_workflow and estimate_workflow tools accept https:// URLs and data URIs as inputs.