Windpaint
Generation

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:

ReferenceExampleWhat happens
Asset id8e1f2a3b-4c5d-4e6f-9a0b-1c2d3e4f5a6bThe asset is used as is.
Asset URL from this APIhttps://api.windpaint.ai/v1/generation/assets/{id}/contentSame as the id.
Public https:// URLhttps://example.com/frame.jpgFetched at submit and stored as a new asset with source: "url".
data: URIdata: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.

KindFormatsMax sizeOther limits
ImagePNG, JPEG, WebP20 MiBLong edge at most 8192 px, short edge at least 64 px
VideoMP4, MOV, WebM200 MiBAt most 60 seconds
AudioMP3, WAV, M4A, OGG25 MiBAt 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_frame returns 422.

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 be https://. 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 ,....

codeWhendetails
input.invalidAn 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_formatThe bytes aren’t a supported format, or can’t be read as the detected kind.detected (such as "GIF", or null), allowed
input.too_largeOver 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.dimensionsAn image’s long edge is over 8192 px or its short edge under 64 px.width, height, max_long_edge, min_short_edge
input.durationA video over 60 seconds or audio over 5 minutes.kind, duration_s, max_duration_s
input.fetch_failedThe 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.