Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.sailresearch.com/llms.txt

Use this file to discover all available pages before exploring further.

Sail accepts image inputs on multimodal base models. Images can be supplied as base64 data URIs or as HTTP(S) URLs.

Supported models

Multimodal support is per-model. The Models page is the canonical list — any row with a check in the Image column accepts the content blocks shown below. Requesting image input on a non-multimodal model returns 400 with model '<id>' does not support image input.

Limits

  • Max 20 images per request.
  • Max 20 MB per image. This is the size of the image bytes, not the base64-encoded length.
  • Formats: JPEG, PNG, WebP, GIF.
  • No pixel-dimension limit. The 20 MB byte cap is the effective bound; very large dimensions may be resized or tiled by the model before decoding.
  • URL images must be on http:// or https:// and must be reachable from the public internet. If Sail can’t fetch a URL within 10 s, the request fails with 400.

Responses API

Pass an input_image block inside a message’s content array. The image_url value can be a data URI or a public URL.
from openai import OpenAI

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

response = client.responses.create(
    model="moonshotai/Kimi-K2.5",
    input=[
        {
            "role": "user",
            "content": [
                {"type": "input_text", "text": "What's in this image?"},
                {
                    "type": "input_image",
                    "image_url": "https://example.com/cat.jpg",
                },
            ],
        }
    ],
    background=True,
)
Equivalent with a base64 data URI:
import base64, pathlib

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

response = client.responses.create(
    model="moonshotai/Kimi-K2.5",
    input=[
        {
            "role": "user",
            "content": [
                {"type": "input_text", "text": "What's in this image?"},
                {"type": "input_image", "image_url": data_uri},
            ],
        }
    ],
    background=True,
)
detail ("auto", "low", "high") is supported.

Chat Completions API

Use OpenAI’s standard image_url content part.
response = client.chat.completions.create(
    model="moonshotai/Kimi-K2.5",
    messages=[
        {
            "role": "user",
            "content": [
                {"type": "text", "text": "What's in this image?"},
                {
                    "type": "image_url",
                    "image_url": {
                        "url": "https://example.com/cat.jpg",
                        "detail": "auto",
                    },
                },
            ],
        }
    ],
)
Data URIs are accepted in the same url field:
"image_url": {"url": f"data:image/jpeg;base64,{b64}"}

Messages API (Anthropic)

Use the Anthropic image content block. Both base64 and url source types are supported.
import anthropic

client = anthropic.Anthropic(
    base_url="https://api.sailresearch.com",
    api_key="YOUR_KEY",
)

# URL source
response = client.messages.create(
    model="moonshotai/Kimi-K2.5",
    max_tokens=1024,
    messages=[
        {
            "role": "user",
            "content": [
                {
                    "type": "image",
                    "source": {"type": "url", "url": "https://example.com/cat.jpg"},
                },
                {"type": "text", "text": "What's in this image?"},
            ],
        }
    ],
)

# Base64 source
response = client.messages.create(
    model="moonshotai/Kimi-K2.5",
    max_tokens=1024,
    messages=[
        {
            "role": "user",
            "content": [
                {
                    "type": "image",
                    "source": {
                        "type": "base64",
                        "media_type": "image/jpeg",
                        "data": b64,  # raw base64 string, no data: prefix
                    },
                },
                {"type": "text", "text": "What's in this image?"},
            ],
        }
    ],
)

Error cases

ConditionStatusMessage
model is not multimodal400model '<id>' does not support image input
More than 20 images in one request400too many images: maximum 20 images per request
Image larger than 20 MB decoded400image too large: exceeds maximum of ... bytes
Unsupported MIME type400unsupported image type ...
URL scheme not http/https400unsupported URL scheme ...
URL not reachable from the public internet400blocked: ...
URL returns non-200 or times out (10 s)400failed to download image: ...
Data URI declared MIME does not match actual bytes400declared type ... does not match detected type ...

Notes

  • If you already have the image bytes, sending them as a base64 data URI is typically faster than a URL.
  • Image bytes are not cached across requests.
  • LoRAs and image inputs can be combined on a multimodal base model that also supports LoRA (see LoRAs).