Skip to main content
Multimodal base models on Valar accept images mixed into the text of a request. Each image travels one of two ways: inline as a base64 data URI, or by reference as an HTTP(S) URL that Valar fetches on your behalf. Before you wire up a request, confirm three things: the model accepts images, your images fall inside the size and format limits, and the URLs you reference are publicly reachable.

Confirm the model is multimodal

Image support is per model. The Models page is the source of truth — a checkmark in the Image column means the model accepts the content blocks shown below.
Sending image content to a model that is not multimodal returns 400 with model '<id>' does not support image input.

Stay inside the limits

images per request
integer
At most 20 images in a single request.
bytes per image
integer
At most 20 MB per image, measured against the raw decoded bytes rather than the length of the base64 string.
format
string
JPEG, PNG, WebP, or GIF.
pixel dimensions
any
No dimension cap. The 20 MB byte ceiling is the real bound; the model may resize or tile oversized images before decoding.
URL fetch
string
URLs must be http:// or https:// and reachable on the public internet. Valar gives up after 10 s and returns 400.

Pass an image per API

The content block differs by API surface. Each tab below shows the URL form first, then the base64 form, so you can match whichever client you already use.
Drop an input_image block into the message content array. Its image_url holds either a public URL or a data URI.
from openai import OpenAI

client = OpenAI(base_url="https://api.valarhq.ai/v1", api_key="YOUR_KEY")

response = client.responses.create(
    model="moonshotai/Kimi-K2.6",
    input=[
        {
            "role": "user",
            "content": [
                {"type": "input_text", "text": "Describe this photo."},
                {
                    "type": "input_image",
                    "image_url": "https://example.com/storefront.jpg",
                },
            ],
        }
    ],
    background=True,
)
To send the bytes inline, build a data URI and pass it in the same image_url field:
import base64, pathlib

raw = pathlib.Path("storefront.jpg").read_bytes()
b64 = base64.b64encode(raw).decode()
data_uri = f"data:image/jpeg;base64,{b64}"

response = client.responses.create(
    model="moonshotai/Kimi-K2.6",
    input=[
        {
            "role": "user",
            "content": [
                {"type": "input_text", "text": "Describe this photo."},
                {"type": "input_image", "image_url": data_uri},
            ],
        }
    ],
    background=True,
)
The optional detail field takes "auto", "low", or "high".

When a request is rejected

Every image problem surfaces as a 400. The message tells you which check failed:
StatusMessageCause
400model '<id>' does not support image inputThe model is not multimodal.
400too many images: maximum 20 images per requestThe request carried more than 20 images.
400image too large: exceeds maximum of ... bytesAn image was larger than 20 MB once decoded.
400unsupported image type ...The MIME type is outside JPEG, PNG, WebP, GIF.
400unsupported URL scheme ...A URL used a scheme other than http or https.
400blocked: ...A URL was not reachable from the public internet.
400failed to download image: ...A URL returned non-200 or timed out after 10 s.
400declared type ... does not match detected type ...A data URI’s declared MIME did not match the actual bytes.

Choosing between URL and base64

When the bytes are already on hand, a base64 data URI usually beats handing Valar a URL to fetch. Note that image bytes are never cached between requests, so each request re-sends or re-fetches its images.