# images.nineonefour.org — how to use the image API

Text-to-image with Iris-3B on this server's GPUs. Every request (except this page) needs an API
key with the `images` grant. Only HTTPS is accepted.

## 1. Get a key

The operator of this server gives you a key. It looks like `mfk_<id>_<secret>`. The same key can
also have grants for files (files.nineonefour.org) and speech (speech.nineonefour.org). A key
without the `images` grant gets `403`. An expired or revoked key gets `401`.

Keep the key secret. Do not put it in a URL or in a git repository.

## 2. Send the key

```
Authorization: Bearer mfk_...
X-Api-Key: mfk_...
```

## 3. Requests

| Request | Does |
|---|---|
| `POST /v1/generate` | make one image and send it back (the connection stays open until it is done) |
| `POST /v1/jobs` | queue one image and get a job id at once (`202`) |
| `GET /v1/jobs/{id}` | the job status: `queued` (with `position`), `running`, `done` or `error` |
| `GET /v1/jobs/{id}/image` | the image of a finished job (`409` until it is done) |
| `GET /v1/sizes` | the trained sizes |
| `GET /v1/status` | the service status (`loaded` tells if the models are in memory) |

Only the key that made a job can see it. A finished job is kept for one hour.

**Cold start:** the models are not kept in memory when nobody uses them. The first request
after 5 minutes with no work loads them first (1 to 6 minutes, longer when the server is busy),
then it makes the image. Use a job if your client cannot wait that long.

## 4. Body of `/v1/generate` and `/v1/jobs`

| Field | Default | Notes |
|---|---|---|
| `prompt` | required | plain descriptive English, up to 4000 characters |
| `model` | `turbo` | `turbo`: 4 steps, about 10 seconds. `base`: 100 steps, about 10 minutes, better detail |
| `negative_prompt` | none | `base` only |
| `aspect_ratio` | none | `W:H`, for example `16:9`. Snaps to the nearest trained size. Do not use with `width`/`height` |
| `width`, `height` | 1024 | multiples of 16, area up to 1344×1024 |
| `steps` | 100 | `base` only, 1–250 |
| `cfg_scale` | 3.0 | `base` only |
| `seed` | random | the seed used is always sent back |
| `format` | `png` | `png`, `jpeg` or `webp` |
| `quality` | 95 | `jpeg` and `webp` |
| `response` | `image` | `image`: the image bytes, with the settings in `X-Imagen-*` headers. `json`: `{"image": "<base64>", "seed": …, "seconds": …}` |

With `turbo`, do not send `steps`, `cfg_scale` or `negative_prompt` (`422`). The server makes one
image at a time; other requests wait.

## 5. Examples

```sh
KEY=mfk_...
API=https://images.nineonefour.org/v1

# Quick image (turbo)
curl -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
     -d '{"prompt":"a red fox in fresh snow, morning light","aspect_ratio":"16:9"}' \
     -o fox.png $API/generate

# Slow image (base): use a job
curl -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
     -d '{"prompt":"a lighthouse in a storm, oil painting","model":"base"}' $API/jobs
# -> {"id":"3353…","status":"queued","position":0,…}
curl -H "Authorization: Bearer $KEY" $API/jobs/3353…
# -> {"status":"done",…,"image_url":"/v1/jobs/3353…/image"}
curl -H "Authorization: Bearer $KEY" -o lighthouse.png $API/jobs/3353…/image
```

Python:

```python
import time, requests
api = "https://images.nineonefour.org/v1"
h = {"Authorization": f"Bearer {key}"}
job = requests.post(f"{api}/jobs", headers=h, json={"prompt": "a lighthouse in a storm", "model": "base"}).json()
while (s := requests.get(f"{api}/jobs/{job['id']}", headers=h).json())["status"] in ("queued", "running"):
    time.sleep(10)
open("lighthouse.png", "wb").write(requests.get(f"{api}/jobs/{job['id']}/image", headers=h).content)
```

## 6. Errors

Errors are JSON with a `detail` text.

| Code | Meaning |
|---|---|
| `400` | Bad request, or plain HTTP was used |
| `401` | No key, or the key is unknown, expired or revoked |
| `403` | Your key does not have the `images` grant |
| `404` | Unknown job, or the job expired |
| `409` | The job is not done |
| `413` | The body is larger than 64 KB |
| `422` | A field is not correct (the `detail` tells which) |
| `429` | Too many jobs wait; try again later |
| `502` | The image service did not answer |
