> ## Documentation Index
> Fetch the complete documentation index at: https://docs.nunchux.ai/llms.txt
> Use this file to discover all available pages before exploring further.

> ## Agent Instructions
> Authenticate every request with your API key in the `X-API-Key` header or `Authorization: Bearer`. Keys start with `sk-nunchux-`.
> Image generation is synchronous: the image is in the response.
> Video generation is asynchronous: submit the job, poll its task until it reaches a terminal status, then download the output promptly, because output URLs expire.

# Topaz Image Enhance

> Upscale and enhance images with Topaz Labs Wonder 4, Wonder 3.5, Bloom 2 and Gigapixel High Fidelity 3 through one asynchronous endpoint.

# Topaz Image Enhance

Topaz Labs makes image models that upscale and enhance a photo or a generated image. You send one source image and the output size you want. Topaz returns the image at that size. One route serves all four models. The request is asynchronous. You submit a job, poll it until the status is terminal, then download the image.

The route takes a JSON body. Topaz's own API takes a multipart form, so the field names here are ours where the two differ.

> [!NOTE]
>
> Best for
>
> * Low-resolution and compressed photos. Wonder 4 and Wonder 3.5 remove noise, blur and compression artifacts while they upscale.
> * Generated images. Bloom 2 adds new detail and texture to AI artwork, illustrations and renders.
> * Camera originals. Gigapixel High Fidelity 3 enlarges high-quality photos and keeps their look.
> * Large output. Each side can be up to 32,000 pixels.

## Models

| Model | Model ID | Best on | Character |
| - | - | - | - |
| Wonder 4 | `topaz-wonder-4` | Any photo, from damaged scans to high resolution | All-in-one enhancement and upscaling. Corrects each region of the image on its own. |
| Wonder 3.5 | `topaz-wonder-3.5` | Real-world photos, charts and documents | Generative upscaling with fine detail |
| Bloom 2 | `topaz-bloom-2` | AI artwork, illustrations, CG renders | Creative upscaling. Adds new detail. |
| Gigapixel High Fidelity 3 | `topaz-gigapixel-high-fidelity-3` | Professional and high-resolution photos | Precise upscaling. Keeps the original structure. |

Each model runs with Topaz's default settings. Wonder 3.5 enhances at its high strength. Bloom 2 runs at creativity 3 with its automatic prompt and color preservation on. High Fidelity 3 recovers detail at its default strength. Model settings cannot be changed on this route yet.

## Endpoints

| Step | Route |
| - | - |
| Submit | `POST /v1/topaz/image/enhance` |
| Poll | `GET /v1/topaz/image/{process_id}` |

## Request

Send your API key in the `X-API-Key` header. See [Authentication](https://docs.nunchux.ai/authentication.md). Set `Content-Type: application/json`. The examples also send a `User-Agent` header that names your application.

**model** `string` *required*

The model ID: `topaz-wonder-4`, `topaz-wonder-3.5`, `topaz-bloom-2` or `topaz-gigapixel-high-fidelity-3`.

**image** `string` *required*

The source image. Either a public `https` URL, or a `data:` URI with base64 data of type `image/jpeg`, `image/png` or `image/tiff`. An `http` URL is rejected.

**output\_width** `integer` *required*

The output width in pixels, 1 to 32,000. Required, together with `output_height`. The price follows the output canvas, so the route takes no scale factor and does not derive one side from the other.

**output\_height** `integer` *required*

The output height in pixels, 1 to 32,000. Required, together with `output_width`.

**output\_format** `string` (default: jpeg)

The format of the output image: `jpeg`, `png` or `tiff`.

**crop\_to\_fill** `boolean` (default: false)

When the output shape differs from the source shape, `true` crops the output to fill the canvas. `false` letterboxes it.

## Response

### Submit

A 200 status means that Topaz accepted the job. It does not mean that the image is ready.

**process\_id** `string` *required*

The job ID. Poll `GET /v1/topaz/image/{process_id}` with it. There is no `handle` field: `process_id` is the value to poll. It works for 7 days.

### Poll

**status** `string` *required*

`Processing` while the job runs. `Completed`, `Failed` or `Cancelled` when it ends. Poll until you read one of the three terminal values.

**download\_url** `string`

The URL of the output image. Present only when `status` is `Completed`. The URL is time-limited. A later poll returns a fresh URL.

**output\_width** `integer` *required*

The output width you requested.

**output\_height** `integer` *required*

The output height you requested.

**output\_format** `string` *required*

The file type of the output: `jpg`, `png` or `tif`.

**credits** `integer`

The Topaz credits that the job used. Present once the job is billed.

**error** `object`

Present when the job did not complete. `error.message` explains why. Read it before you resubmit.

## Example

Submit, poll, download. The submit and the poll use different paths.

```bash cURL theme={"system"}
BASE=https://api.nunchux.com

# 1. Submit
SUBMIT=$(curl -sS --fail-with-body "$BASE/v1/topaz/image/enhance" \
  -H "X-API-Key: $NUNCHUX_API_KEY" \
  -H "Content-Type: application/json" \
  -H "User-Agent: YourApp/1.0" \
  -d '{
    "model": "topaz-wonder-4",
    "image": "https://example.com/photo.jpg",
    "output_width": 3840,
    "output_height": 2160,
    "output_format": "png"
  }') || { echo "submit failed: $SUBMIT" >&2; exit 1; }
JOB=$(jq -er '.process_id' <<<"$SUBMIT") || { echo "no process_id in: $SUBMIT" >&2; exit 1; }

# 2. Poll until the status is terminal
DELAY=3
for _ in $(seq 1 90); do
  RESP=$(curl -sS "$BASE/v1/topaz/image/$JOB" \
    -H "X-API-Key: $NUNCHUX_API_KEY" \
    -H "User-Agent: YourApp/1.0")
  STATUS=$(jq -r '.status // ""' <<<"$RESP")
  case "$STATUS" in Completed|Failed|Cancelled) break ;; esac
  sleep "$DELAY"; DELAY=$(( DELAY * 2 > 30 ? 30 : DELAY * 2 ))
done

# 3. Check for failure
[ "$STATUS" = "Completed" ] || { echo "job $STATUS: $(jq -r '.error.message // "no error"' <<<"$RESP")" >&2; exit 1; }

# 4. Download
curl -sSL -o topaz.png "$(jq -r '.download_url' <<<"$RESP")"
```

```python Python theme={"system"}
# pip install requests
import os, time, requests

BASE = "https://api.nunchux.com"
HEADERS = {
    "X-API-Key": os.environ["NUNCHUX_API_KEY"],
    "User-Agent": "YourApp/1.0",
}

# 1. Submit
submit = requests.post(
    f"{BASE}/v1/topaz/image/enhance",
    headers=HEADERS,
    json={
        "model": "topaz-wonder-4",
        "image": "https://example.com/photo.jpg",
        "output_width": 3840,
        "output_height": 2160,
        "output_format": "png",
    },
)
if not submit.ok:
    raise RuntimeError(f"submit failed: HTTP {submit.status_code} {submit.text}")
job = submit.json()["process_id"]

# 2. Poll until the status is terminal
delay = 3
for _ in range(90):
    data = requests.get(f"{BASE}/v1/topaz/image/{job}", headers=HEADERS).json()
    status = data.get("status", "")
    if status in ("Completed", "Failed", "Cancelled"):
        break
    time.sleep(delay)
    delay = min(delay * 2, 30)
else:
    raise TimeoutError("Topaz job did not reach a terminal status")

# 3. Check for failure
if status != "Completed":
    raise RuntimeError(f"Topaz job {status}: {data.get('error')}")

# 4. Download
with requests.get(data["download_url"], stream=True, timeout=300) as r:
    r.raise_for_status()
    with open("topaz.png", "wb") as f:
        for chunk in r.iter_content(1 << 14):
            f.write(chunk)
```

## Tips

* Keep the output shape equal to the source shape. A different shape is letterboxed, or cropped with `crop_to_fill`.
* Pick the canvas you need, not the largest one. The price grows with the output megapixels.
* Use Wonder 4 when you are unsure. Use Bloom 2 only on generated images, because it invents detail. Use High Fidelity 3 on sources that are already sharp.
* Poll every 3 seconds at first, then back off to 30 seconds. Polls are free and never use a concurrency slot.

## Errors and limits

A 200 status on submit means that Topaz accepted the job. It does not mean that the job succeeded. A job that fails later ends with `status` set to `Failed` or `Cancelled`, and `error.message` explains why. Read it before you resubmit.

A failed submit returns an HTTP error status. See [Error codes](https://docs.nunchux.ai/errors.md). These request shapes are rejected with 400 before any charge:

| Code | Cause |
| - | - |
| `invalid_output_width`, `invalid_output_height` | A side is missing, is not an integer, or is outside 1 to 32,000. |
| `invalid_image` | The image is missing, is an `http` URL, or is a `data:` URI that is not base64 JPEG, PNG or TIFF. |
| `invalid_output_format` | The format is not `jpeg`, `png` or `tiff`. |
| `webhook_url_not_supported` | The body carries `webhook_url`. Poll the job instead. |
| `invalid_settings` | The body carries a `settings` map with a Topaz model setting, which Topaz names in camelCase. A snake\_case name passes this check but has no effect. See [Models](#models). |

Topaz can refuse an output size that its model does not support. Wonder 4 takes an output from 1 to 6 times the source size. The refusal comes back as a 4xx on submit with Topaz's own message, or as a `Failed` job. Neither is charged.

A 5xx status or a timeout on submit does not tell you whether the job was created. Never resubmit blindly. If the submit returned a `process_id`, poll it. If it returned nothing, check your credits before you try again.

Topaz bills in whole credits, by output megapixels. Each model turns a different number of megapixels into one credit, so the same canvas costs more on Bloom 2 than on High Fidelity 3. Nunchux holds the charge for your canvas at submit and settles it to the credits that Topaz reports when the job ends. A failed job is refunded. See the [pricing page](https://nunchux.ai/pricing) for the rates.

Every submit counts toward the simultaneous-jobs cap of your plan for six minutes, however fast the job finishes. A job that ends sooner does not give its slot back early, so a burst of short jobs can return 429 `concurrent_limit_exceeded`. Wait and retry with backoff. Separately, at most five Topaz jobs per account can be in progress at once. A sixth returns 429 with the code `too_many_open_tasks`. A job stops counting toward the five when Nunchux settles it, which can be a few seconds after the poll first shows a terminal status, so a submit sent at once can still return 429. See [Rate limits](https://docs.nunchux.ai/rate-limits.md), [Credits & pricing](https://docs.nunchux.ai/credits-pricing.md) and the [Partner models overview](https://docs.nunchux.ai/partner-models/overview.md).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.