Skip to content

Vision inputs

Vision-capable chat models accept images inside the message content array. Images are billed as tokens — each image adds input tokens to the request, proportional to its resolution.

To send images you need:

  • An API key — one key works across all three protocols (Authorization: Bearer for OpenAI, x-api-key or Authorization: Bearer for Anthropic, x-goog-api-key or ?key= for Gemini).
  • A model with the vision capability — check the capability flags in the catalogue. The examples below use deepseek-chat as a placeholder; swap in any vision-capable model.
  • The right base URL per protocol:
    • OpenAI-compatible: https://api.mirapi.ai/v1
    • Anthropic: https://api.mirapi.ai
    • Gemini: https://api.mirapi.ai or https://api.mirapi.ai/v1beta

OpenAI-style requests place images in the message content array as image_url parts. The url can be an HTTP(S) URL or a base64 data URI.

import os
from openai import OpenAI
client = OpenAI(base_url="https://api.mirapi.ai/v1", api_key=os.environ["MIRAPI_API_KEY"])
response = client.chat.completions.create(
model="deepseek-chat",
messages=[{
"role": "user",
"content": [
{"type": "text", "text": "What is in this photo?"},
{"type": "image_url", "image_url": {"url": "https://example.com/photo.jpg"}},
],
}],
)
print(response.choices[0].message.content)

Send the text part first, then the images — this ordering is parsed most reliably across models.

For local or private images, encode the file as a data URI:

import base64
def data_uri(path: str) -> str:
with open(path, "rb") as f:
encoded = base64.b64encode(f.read()).decode()
return f"data:image/jpeg;base64,{encoded}"

Pass the result as image_url.url. Base64 is required for files that are not publicly reachable.

Anthropic-format requests go to POST /v1/messages and carry the image as an image part with a base64 source. Base URL: https://api.mirapi.ai (no /v1).

{
"model": "deepseek-chat",
"max_tokens": 1024,
"messages": [
{
"role": "user",
"content": [
{"type": "text", "text": "Describe this image"},
{
"type": "image",
"source": {
"type": "base64",
"media_type": "image/jpeg",
"data": "<base64>"
}
}
]
}
]
}

Gemini-format requests go to POST /v1beta/models/{model}:generateContent and place images in contents[].parts using inlineData (base64) or fileData (a file URI). Base URL: https://api.mirapi.ai or https://api.mirapi.ai/v1beta.

{
"contents": [
{
"role": "user",
"parts": [
{"text": "Describe this image"},
{
"inlineData": {
"mimeType": "image/jpeg",
"data": "<base64>"
}
}
]
}
]
}
Parameter Required Description
model yes Model id; must support vision.
messages / contents yes The conversation; image parts go inside content / parts.
type yes image_url (OpenAI), image (Anthropic), inlineData / fileData (Gemini).
url (OpenAI) yes HTTP(S) URL or base64 data URI.
source (Anthropic) yes Base64 source with media_type and data.
mimeType (Gemini) yes MIME type for inlineData.
max_tokens (Anthropic) yes Required by the Anthropic protocol.

Commonly supported formats are PNG, JPEG, WebP, and GIF; the exact set depends on the model, so check the catalogue.

  • 401 — the key is missing, invalid, or unknown. Fix your credentials.
  • 403 — the key is valid but the request was rejected: insufficient balance, a model-whitelist miss, quota, or IP restrictions. Top up or adjust the key’s constraints, then retry.
  • 413 — the request is too large. Downscale or compress the image and retry.
  • 429 — rate limited. Retry with jittered exponential backoff (no Retry-After header is returned).
  • 500 — an upstream failure. Idempotent requests are safe to retry.

Every error message ends with a request ID — include it when you open a support ticket.

  • Images are billed as input tokens; a single high-resolution image can cost thousands of tokens. Check per-token pricing in the catalogue before batch runs.
  • Non-streaming responses report token counts in usage, not dollar amounts — reconcile costs in the console billing log or via GET /api/log/token.
  • MirAPI runs on a prepaid USD balance with no monthly fee. When the balance is exhausted, requests return 403; topping up restores the same key immediately.
  • Model rejects the image — the model lacks the vision capability; pick a vision-capable model from the catalogue.
  • 403 on a vision model — this is a balance/whitelist/quota issue, not an image-format problem.
  • 413 on a large image — downscale or re-encode the image before retrying.
  • URL images fail — the URL must be publicly reachable; use a base64 data URI for private files.
  • Multiple images in the wrong order — put the text prompt first, then the images.