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.
Prerequisites
Section titled “Prerequisites”To send images you need:
- An API key — one key works across all three protocols (
Authorization: Bearerfor OpenAI,x-api-keyorAuthorization: Bearerfor Anthropic,x-goog-api-keyor?key=for Gemini). - A model with the vision capability — check the capability flags in the catalogue. The examples below use
deepseek-chatas 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.aiorhttps://api.mirapi.ai/v1beta
- OpenAI-compatible:
OpenAI-compatible format
Section titled “OpenAI-compatible format”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.
Using an image URL
Section titled “Using an image URL”import osfrom 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.
Using a base64 data URI
Section titled “Using a base64 data URI”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 protocol
Section titled “Anthropic protocol”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 protocol
Section titled “Gemini protocol”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>" } } ] } ]}Parameters
Section titled “Parameters”| 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.
Errors
Section titled “Errors”- 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-Afterheader 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.
Billing
Section titled “Billing”- 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 viaGET /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.
Troubleshooting
Section titled “Troubleshooting”- 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.