# Image generation and editing (/en/docs/developers/model/guides/images)



Use `gpt-image-2` through the OpenAI Images API for both generation and editing. Check `GET /openai/v1/models?api=images` before calling; the native catalog declares `openai.images.generations` and `openai.images.edits` separately.

## 1. Prepare your terminal [#1-prepare-your-terminal]

Use Python 3.10+ and [uv](https://docs.astral.sh/uv/getting-started/installation/). Put your [Praxis cloud API Key](/en/docs/developers/account/api-keys) in `PRAXIS_API_KEY`; do not put it in source code or logs.

```bash
test -n "$PRAXIS_API_KEY"
```

Expected: exit code 0. Exit code 1 means the variable is missing. Examples default to `https://api.deepraxis.com`. To switch environments, set `PRAXIS_API_BASE` to the API origin without a trailing slash or API path.

## 2. Generate and edit [#2-generate-and-edit]

Run in a writable directory. This example makes two billable image requests: one generation and one edit. It saves `circle.png` and `circle-edited.png`; use a fresh directory to avoid overwriting existing files. Automatic retries are disabled.

Save as `images.py` and run `uv run -q --no-project --with openai --with anthropic --with google-genai python images.py`.

```python
import base64
import os
from pathlib import Path
from openai import OpenAI

client = OpenAI(api_key=os.environ['PRAXIS_API_KEY'],
    base_url=os.environ.get('PRAXIS_API_BASE', 'https://api.deepraxis.com') + '/openai/v1',
    timeout=180, max_retries=0)
models = client.models.list(extra_query={'api': 'images'})
print('X-Request-Id:', models._request_id)
assert 'gpt-image-2' in [model.id for model in models]

def save(response, filename):
    print('X-Request-Id:', response._request_id)
    assert len(response.data) == 1 and response.data[0].b64_json
    image = base64.b64decode(response.data[0].b64_json, validate=True)
    assert image.startswith(b'\x89PNG\r\n\x1a\n'), 'Expected PNG output'
    Path(filename).write_bytes(image)
    assert response.usage is not None, 'Usage was not reported'
    print(filename, len(image), 'bytes; usage:', response.usage.model_dump())

save(client.images.generate(model='gpt-image-2',
    prompt='A single blue circle centered on a plain white background.',
    n=1, size='1024x1024', quality='low'), 'circle.png')
with open('circle.png', 'rb') as image:
    save(client.images.edit(model='gpt-image-2', image=image,
        prompt='Change the blue circle to a red circle. Keep the white background.',
        n=1, size='1024x1024', quality='low'), 'circle-edited.png')
```

Expected: both files are nonempty PNGs; each response contains one image and token usage. Exit code 0. Open the files: the first should show a blue circle, the second a red circle on white. The signature check proves file format, not visual accuracy.

## 3. Read image costs [#3-read-image-costs]

`gpt-image-2` is billed by tokens, not a fixed price per image. Text input, image input, and image output have separate rates. Editing includes input image tokens. Read the returned usage and the current prices in [the model catalog](https://console.deepraxis.ai/models/gpt-image-2); see [usage and billing](/en/docs/developers/account/billing) for account totals.

If the catalog assertion fails, stop before generating and choose a currently available image model. If an output assertion fails, retain the request ID and response error; do not repeatedly regenerate to diagnose a file problem.

Operation details: [generate](/en/docs/api/compatible/openai/createImage) and [edit](/en/docs/api/compatible/openai).

[API reference →](/en/docs/api/compatible/openai) · [Cookbook →](/en/docs/cookbook)
