## Image analysis

Models with image support accept graphics through the `content` array with a `type: "image_url"` element. The image address is either a `data:` URI with base64 data or an `https` link. In the [`GET /v1/models`](/docs/ai/models/list) catalog such models carry the `capabilities.vision: true` flag.

Images are processed for free by `bitrix/bitrixgpt-5.5` and `bitrix/bitrixgpt-5.5-thinking`. With your own provider key (BYOK), Anthropic Claude models are available: `anthropic/claude-opus-4-6`, `anthropic/claude-sonnet-4-6`, `anthropic/claude-haiku-4-5-20251001`. For these models, the platform automatically converts the `image_url` element to the Anthropic format — nothing needs to change on the client side.

## Request example

```bash
curl -X POST https://vibecode.bitrix24.com/v1/chat/completions \
  -H "X-Api-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "bitrix/bitrixgpt-5.5",
    "messages": [
      {
        "role": "user",
        "content": [
          {"type": "text", "text": "Describe what is in the image"},
          {"type": "image_url", "image_url": {"url": "data:image/jpeg;base64,/9j/4AAQSkZJRg..."}}
        ]
      }
    ],
    "max_tokens": 500
  }'
```

## Limits

| Parameter | Value |
|----------|----------|
| MIME types | `image/png`, `image/jpeg`, `image/gif`, `image/webp` |
| Maximum per image, decoded size | 20 MiB for any model |
| Maximum `image_url.url` in a request | 30 MiB — allowing for base64 encoding, that is 22 MiB of payload |
| `url` format | `data:<mime>[;parameter=value]*;base64,<data>` or `https://<host>/<path>`. Parameters between the type and `;base64` (for example `data:image/jpeg;name=photo.jpg;base64,…`) are accepted and discarded |
| `http://` links | not accepted, only `https` or `data:` |
| Maximum `content` elements per message | 64 |
| Maximum request body | `bitrix/*` models: the limit is set by the model cluster and is lower for a body with images than for text. The platform downscales `data:` images in a body over the limit — see "Known specifics". The message of a `413` response states the limit in effect. Models on your own provider key: 30 MiB |

**MiB** is a mebibyte, a binary unit per the IEC 80000-13 standard: `1 MiB = 2²⁰ = 1 048 576 bytes ≈ 1.05 MB`. Limits are checked as `N × 1024 × 1024`, so the error message also states the size in `MiB` — for example, `decoded size 21.3 MiB exceeds limit 20 MiB`.

## Content check

Before the request is sent to the model, the content of every `image_url` element passed as a `data:` URI is inspected by its actual bytes rather than its declared MIME type. If the content is not an image — for example an HTML page or an error response encoded in base64 and declared as `image/png` — the element is not dropped but **replaced in place** with the text placeholder `[image unavailable: <reason>]`. The remaining images are processed normally and the request succeeds.

The content check applies to `data:` URIs only. A candidate passed as an `https://` link is forwarded to the model as is, without fetching or inspecting its bytes — validate such links on your side.

Positions are preserved: the length of the `content` array does not change, so any candidate numbering on your side stays correct.

The substitution is visible in the response:

- the `X-Image-Parts-Rejected` header carries the number of replaced elements — this is the single signal available in every response mode; for streaming responses it arrives with the start of the stream;
- in a regular (non-streaming) response the `warnings` field additionally carries an entry with the code `IMAGE_CONTENT_REJECTED` and the substitution details. A streaming response has no `warnings` field — rely on the header.

## Errors

| HTTP | Code | Description |
|------|-----|---------|
| 400 | `invalid_image_payload` | A structural request error: the `url` field is missing, the string is neither a URL nor a data URI, a malformed data URI (no `;base64,`), an unsupported scheme, or `http://` in production. The message contains the `content` element index and the specific reason |
| 413 | `ai_payload_too_large` | A request body with images for a `bitrix/*` model exceeds the model cluster limit even after image downscaling. The request is not sent to the model and nothing is charged. The message states the request size and the limit in effect |
| 413 | `ai_payload_too_large` | The model cluster itself, or the provider of a model on your own key, refused the request because of the body size. The response body carries `providerStatusCode: 413` |
| 429 | `ai_image_resize_busy` | The platform is already downscaling many images at once. Retry after the interval in the `Retry-After` header, or downscale the images before sending |

Content errors (not an image, corrupted base64, unsupported MIME type, over 20 MiB) **no longer fail the request** — such an element is replaced with a placeholder (see "Content check").

For the full list of common API errors, see [Errors](/docs/errors).

## Known specifics

**The `content` array is only needed for images.** For text requests pass `content` as a string. An array with a single `text` element also works but is redundant.

**For `bitrix/*` models, the platform downscales large images itself.** When the request body contains images and exceeds the limit, the platform downscales its `data:` images, starting with the largest, to 1536 pixels on the long side and saves them as JPEG at quality 80. If that is not enough, it downscales them to 1024 pixels at quality 70. An image with transparent pixels is downscaled as PNG with its transparency kept, and only if that does not fit the limit is it saved as JPEG on a white background. A GIF keeps only its first frame; images passed as an `https` link are left unchanged. A body that is still over the limit gets a `413`. With `stream: true`, the `ai_payload_too_large` and `ai_image_resize_busy` refusals arrive as an error frame inside a `200` response, and the retry delay comes in the frame's `retryAfter` field rather than in a header. An image over 20 MiB after decoding is not downscaled: it is replaced with a placeholder, as described in "Content check".

**To control the quality, downscale images yourself.** A 12 MP JPEG photo takes 4–5 MB. Downscaled to 1500 pixels on the long side and saved as JPEG or WebP at quality 80–85, it takes 0.2–1 MB and reaches the model unchanged.

**Image size is checked after decoding.** The 20 MiB limit applies to the image itself, not to the base64 string. The string is roughly a third longer, so the request body for models on your own provider key is limited to 30 MiB.

## See also

- [Create a chat completion](./completions.md)
- [List of models](/docs/ai/models/list)
- [Your own keys (BYOK)](/docs/ai/credentials)
