Skip to main content
Multimodal models on Valar read images mixed in with your text. You attach each image one of two ways - a public URL that Valar fetches, or a base64 data URI you embed directly - and the model treats it as part of the prompt. Two things decide whether a request works: the model has to be multimodal, and each image has to fall inside the size and format limits below.

Check the model supports images

Vision is a per-model capability. Look for a check in the Image column on the Models page, or call GET /v1/models to confirm at runtime. Sending image content to a text-only model fails fast:
A non-multimodal model returns 400 with this model does not support image input. No tokens are charged.

Attach an image

The content block is shaped to match whichever API you’re already calling. Each tab shows the URL form first, then the inline base64 form.
Add an input_image part to the message content. Its image_url takes either a public URL or a data: URI, and the optional detail field accepts "auto", "low", or "high".
To send the bytes yourself, base64-encode the file into a data URI and pass it in the same field:

Limits

When an image is rejected

Most problems come back as a 400 with a JSON error whose message names the failing check: Two fetch failures happen below the JSON layer, so branch on the HTTP status rather than the body:
  • 403 Forbidden - a referenced URL blocked at the edge comes back as an HTML page from the WAF, not a JSON error.
  • Upstream fetch error - when Valar can’t retrieve a referenced image (unreachable host, timeout, or a non-200 response), the request fails with a generic provider error, sometimes a 503.

URL or base64?

Either works - pick based on where the bytes already are:
  • Base64 when you already hold the file (uploads, generated images). It skips a fetch and avoids exposing a URL, at the cost of a larger request body.
  • URL when the image is already hosted somewhere public. Smaller payload, but Valar has to reach it within 10 seconds.
Either way, image bytes are never cached between requests - every call re-sends or re-fetches its images, so reusing the same image across turns pays the transfer each time.