---
title: Images and voice
description: Send images to chat models, generate images, transcribe audio and turn text into speech through the AI Gateway, with the same key, rules and logs as chat.
section: AI
order: 1.5
updated: 2026-11-04
---

The AI Gateway takes OpenAI's requests for images and audio as well as chat. You use the same gateway key and the same SDK, and every request goes through the project's [routing rules](/docs/ai-routing), its spend cap and the request log, just as a chat completion does. Each model has a `kind` that decides which endpoint serves it, and the [model catalogue](/docs/ai-models#what-can-each-model-do) lists them.

| What you want | Endpoint | Models, for example |
| --- | --- | --- |
| A chat model to read an image | `POST /v1/ai/chat/completions` | `openai/gpt-4.1-mini`, `anthropic/claude-sonnet-5-5`, `google/gemini-3.8-flash` |
| Generate an image | `POST /v1/ai/images/generations` | `openai/gpt-image-2`, `openai/gpt-image-1-mini` |
| Transcribe audio | `POST /v1/ai/audio/transcriptions` | `openai/gpt-4o-mini-transcribe`, `openai/gpt-4o-transcribe` |
| Turn text into speech | `POST /v1/ai/audio/speech` | `openai/gpt-4o-mini-tts`, `openai/tts-1` |

Images and audio pass through the gateway to the provider and are never stored. The request log keeps the kind of request, the model, usage, timing and cost.

> [!WARNING]
> Veil, which is in development, finds personal details in text. It doesn't yet remove them from images or audio, so a photo of an ID card or a recording of a phone call reaches the provider as it is. Keep that kind of material to providers you've approved for it.

## Send an image in a chat

Add an `image_url` part to a user message. The URL can be an `https` address the provider can fetch, or a base64 data URL of a PNG, JPEG, WebP or GIF image of up to 10 MB. A request can carry up to 20 images, and `detail` (`auto`, `low` or `high`) is passed on to providers that read it.

```python tab="Python"
import base64
import os
from openai import OpenAI

client = OpenAI(base_url="https://api.dekka.cloud/v1/ai", api_key=os.environ["DEKKA_AI_KEY"])

with open("receipt.jpg", "rb") as f:
    receipt = base64.b64encode(f.read()).decode()

reply = client.chat.completions.create(
    model="openai/gpt-4.1-mini",
    messages=[{
        "role": "user",
        "content": [
            {"type": "text", "text": "What does this receipt total?"},
            {"type": "image_url", "image_url": {"url": f"data:image/jpeg;base64,{receipt}"}},
        ],
    }],
)
print(reply.choices[0].message.content)
```

```bash tab="cURL"
curl https://api.dekka.cloud/v1/ai/chat/completions \
  -H "Authorization: Bearer $DEKKA_AI_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "anthropic/claude-sonnet-5-5",
    "messages": [{
      "role": "user",
      "content": [
        {"type": "text", "text": "Describe this photo in one sentence."},
        {"type": "image_url", "image_url": {"url": "https://example.com/market.jpg"}}
      ]
    }]
  }'
```

The gateway passes the parts on unchanged to OpenAI-compatible providers and turns them into image blocks for Anthropic. Images count toward the request's input tokens at the provider's own rate. A model whose `input_modalities` doesn't include `image` answers 422 `modality_not_supported`, and a fallback only moves to models that take images too.

## Generate an image

Send a prompt to an image model. The response has each image as base64 in `b64_json`, because the gateway never stores images and so has no URL to give, and `response_format: "url"` answers 422 `unsupported_feature`. You can ask for up to four images, a `size` of `1024x1024`, `1536x1024`, `1024x1536` or `auto`, a `quality` of `low`, `medium`, `high` or `auto`, an `output_format` of `png`, `jpeg` or `webp`, and a `background` of `transparent`, `opaque` or `auto`.

```python tab="Python"
image = client.images.generate(
    model="openai/gpt-image-2",
    prompt="A poster for a farmers' market in Kumasi, in warm colours",
    size="1024x1536",
    quality="medium",
)
with open("poster.png", "wb") as f:
    f.write(base64.b64decode(image.data[0].b64_json))
```

```bash tab="cURL"
curl https://api.dekka.cloud/v1/ai/images/generations \
  -H "Authorization: Bearer $DEKKA_AI_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model": "openai/gpt-image-1-mini", "prompt": "A simple logo of a cocoa pod", "size": "1024x1024"}' \
  | jq -r '.data[0].b64_json' | base64 --decode > logo.png
```

The response's `usage` gives the prompt's text tokens and the image tokens the provider reports. A larger or higher-quality image uses more image tokens, so it costs more.

## Transcribe audio

Send the audio as multipart form data with a transcription model. The file can be up to 25 MB, and its name must end in one of `flac`, `m4a`, `mp3`, `mp4`, `mpeg`, `mpga`, `oga`, `ogg`, `wav` or `webm`. You can add a `language` such as `en`, a `prompt` with names or terms to listen for, and a `temperature`. The answer is `{"text": ..., "usage": ...}` as JSON, or the text alone with `response_format=text`.

```python tab="Python"
with open("voice-note.m4a", "rb") as audio:
    transcript = client.audio.transcriptions.create(
        model="openai/gpt-4o-mini-transcribe",
        file=audio,
        language="en",
    )
print(transcript.text)
```

```bash tab="cURL"
curl https://api.dekka.cloud/v1/ai/audio/transcriptions \
  -H "Authorization: Bearer $DEKKA_AI_KEY" \
  -F model=openai/gpt-4o-transcribe \
  -F file=@meeting.mp3 \
  -F response_format=text
```

Transcription models are priced per audio token in and text token out, which the provider reports. OpenAI estimates that comes to about $0.003 a minute for `gpt-4o-mini-transcribe` and $0.006 a minute for `gpt-4o-transcribe`.

## Turn text into speech

Send up to 4,096 characters of text, a `voice` such as `alloy`, `coral`, `nova` or `sage`, and a `response_format` of `mp3` (the default), `opus`, `aac`, `flac`, `wav` or `pcm`. The reply's body is the audio itself. `gpt-4o-mini-tts` also takes `instructions` about the delivery, such as "speak calmly", and `tts-1` takes a `speed` from 0.25 to 4.

```python tab="Python"
speech = client.audio.speech.create(
    model="openai/gpt-4o-mini-tts",
    voice="coral",
    input="Your order is on its way and should arrive by noon.",
    instructions="Warm and unhurried.",
)
speech.write_to_file("update.mp3")
```

```bash tab="cURL"
curl https://api.dekka.cloud/v1/ai/audio/speech \
  -H "Authorization: Bearer $DEKKA_AI_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model": "openai/tts-1", "voice": "nova", "input": "Akwaaba, and thank you for calling."}' \
  --output greeting.mp3
```

`tts-1` is priced per character of input text, so its cost is exact. OpenAI doesn't report usage for `gpt-4o-mini-tts`, so the gateway estimates it from the text at about 1,250 audio tokens for each minute of speech, and the cost it logs for that model is an estimate.

## What every endpoint shares

- The response headers `X-Dekka-Provider` and `X-Dekka-Model` say what answered.
- Routing rules, the monthly spend cap and the plan's AI token allowance apply, and a refusal has the same codes as chat, which [the order of checks](/docs/ai-routing#in-what-order-are-requests-checked) lists.
- When a model fails with a server error, a rate limit or a timeout, the gateway tries the next model of the same kind in the project's fallback order.
- Usage counts toward the plan's AI tokens. Speech priced per character counts at about four characters a token.

## Without a provider key

Outside production, a request whose provider has no key gets a simulated answer, marked with `"simulated": true` or the `X-Dekka-Simulated: true` header, so you can build before adding a key. Image generation returns a 1×1 PNG, transcription returns placeholder text, and speech returns half a second of silence as MP3, WAV or raw PCM, and as WAV for the other formats. Simulated requests cost nothing. In production a request with no key answers 503 `provider_unavailable`.

## Not supported yet

Audio inside a chat message, image editing and variations, streamed speech, and transcription formats other than JSON and text. Google's Gemini models read images in chat, but Gemini image generation, speech and transcription aren't offered through the gateway yet.
