---
title: Images
path: api-guides/images
status: published
---

# Images

Generate images from text prompts. Supports multiple providers (DALL-E 3, Stable Diffusion, Imagen) through a single endpoint.

**Endpoint:** `POST /v1/inference/images/generate`

## Basic request

```bash
curl -X POST https://scaigrid.scailabs.ai/v1/inference/images/generate \
  -H "Authorization: Bearer $SCAIGRID_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "openai/dall-e-3",
    "prompt": "A cozy reading nook with warm lighting, studio ghibli style",
    "size": "1024x1024",
    "quality": "standard",
    "n": 1
  }'
```

```python
import httpx, os

resp = httpx.post(
    "https://scaigrid.scailabs.ai/v1/inference/images/generate",
    headers={"Authorization": f"Bearer {os.environ['SCAIGRID_API_KEY']}"},
    json={
        "model": "openai/dall-e-3",
        "prompt": "A cozy reading nook with warm lighting, studio ghibli style",
        "size": "1024x1024",
        "quality": "standard",
        "n": 1,
    },
    timeout=120,
)
data = resp.json()["data"]
print(data["data"][0]["url"])
```

```typescript
const resp = await fetch("https://scaigrid.scailabs.ai/v1/inference/images/generate", {
  method: "POST",
  headers: {
    "Authorization": `Bearer ${process.env.SCAIGRID_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    model: "openai/dall-e-3",
    prompt: "A cozy reading nook with warm lighting, studio ghibli style",
    size: "1024x1024",
    quality: "standard",
    n: 1,
  }),
});
const { data } = await resp.json();
console.log(data.data[0].url);
```

## Parameters

| Field | Type | Notes |
|-------|------|-------|
| `model` | string (required) | Image model slug |
| `prompt` | string (required) | Text description |
| `n` | integer | Number of images to generate (typically 1–10) |
| `size` | string | `"1024x1024"`, `"1792x1024"`, `"1024x1792"`, model-dependent |
| `quality` | string | `"standard"` or `"hd"` for DALL-E 3 |
| `style` | string | `"vivid"` or `"natural"` for DALL-E 3 |
| `response_format` | string | `"url"` (default, short-lived proxy URL) or `"b64_json"` (inline base64) |
| `metadata` | object | Passed through to the provider |

## Response shape

```json
{
  "status": "ok",
  "data": {
    "created": 1713888000,
    "data": [
      {
        "url": "https://scaigrid.scailabs.ai/v1/media/tok_abc123",
        "b64_json": null,
        "revised_prompt": "A cozy reading nook..."
      }
    ]
  }
}
```

When `response_format` is `"url"`, the URL points at ScaiGrid's media proxy — the image is stored in our object storage and served through a short-lived token. URLs expire after 1 hour by default; download the image or re-encode it if you need longer retention.

When `response_format` is `"b64_json"`, the response contains inline base64 instead. Useful when your client can't make a second HTTP request to fetch the image.

## Downloading and saving

```python
import httpx, base64

# If URL format
img_resp = httpx.get(data["data"][0]["url"])
with open("output.png", "wb") as f:
    f.write(img_resp.content)

# If b64_json format
b64 = data["data"][0]["b64_json"]
with open("output.png", "wb") as f:
    f.write(base64.b64decode(b64))
```

```typescript
import { writeFileSync } from "node:fs";

const url = data.data[0].url;
const img = await fetch(url);
writeFileSync("output.png", Buffer.from(await img.arrayBuffer()));
```

## Available image models

```bash
curl "https://scaigrid.scailabs.ai/v1/models?modality=image" \
  -H "Authorization: Bearer $SCAIGRID_API_KEY"
```

Common options:

| Model | Size options | Notes |
|-------|--------------|-------|
| `openai/dall-e-3` | 1024x1024, 1792x1024, 1024x1792 | High quality, style/quality parameters |
| `openai/dall-e-2` | 256x256, 512x512, 1024x1024 | Older, cheaper |
| `stability/sd-xl` | 1024x1024 | Self-hosted via ScaiInfer |

Availability depends on which providers your tenant has configured.

## Revised prompts

DALL-E 3 rewrites prompts for better results. The rewritten version comes back in `revised_prompt`:

```python
data = resp.json()["data"]
item = data["data"][0]
print("You asked for:", "A cozy reading nook...")
print("Model generated:", item["revised_prompt"])
```

This is useful for debugging ("why did I get a cartoon when I asked for a photo?"). You can disable prompt rewriting by prefixing your prompt with `I NEED to test how the tool works with extremely simple prompts. DO NOT add any detail, just use it AS-IS:` — this is OpenAI's documented escape hatch.

## Error cases

| Code | Meaning |
|------|---------|
| `VALIDATION_ERROR` | Missing prompt or invalid size |
| `MODEL_ACCESS_DENIED` | Image model not enabled for your tenant |
| `BACKEND_ERROR` | Safety filter triggered, or upstream rejected the prompt |
| `BUDGET_EXCEEDED` | Image generation often has its own budget cap (expensive) |

## What's next

- [Audio](./04-audio.md) — speech synthesis and transcription.
- [Chat Completions](./01-chat-completions.md) — send generated images back to a vision model.
- [OpenAI Compatibility](./07-openai-compatibility.md) — `/oai/v1/images/generations` works identically.
