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

# Image Rate Request

> Reference for the request body and response shape of POST /image/rate.

Endpoint:

```text theme={"theme":"kanagawa-dragon"}
POST https://api.mynth.io/image/rate
```

Authentication: API key or OAuth access token required. Public Access Tokens are not accepted.

By default the endpoint is **synchronous** — results are returned in the response body as a `200`. Set `"sync": false` to queue the task and receive a `202` with a task ID for polling instead. In sync mode, if the task does not finish within the sync timeout the endpoint returns a `202` pending response, and if the task fails it returns a `500`.

## Request body

```json theme={"theme":"kanagawa-dragon"}
{
  "mode": "custom",
  "urls": ["https://example.com/photo-1.webp", "https://example.com/photo-2.webp"],
  "levels": [
    { "value": "safe", "description": "Safe for all audiences" },
    { "value": "sensitive", "description": "Contains mature or suggestive content" },
    { "value": "explicit", "description": "Explicit adult content" }
  ],
  "sync": true
}
```

## Fields

| Field    | Type      | Default    | Notes                                                                                            |
| -------- | --------- | ---------- | ------------------------------------------------------------------------------------------------ |
| `mode`   | `string`  | *required* | `nsfw_sfw` for the built-in scale, or `custom`.                                                  |
| `urls`   | `array`   | *required* | Image URLs to rate. Minimum `1`, maximum `10`.                                                   |
| `levels` | `array`   | —          | Required when `mode` is `custom`. Defines the rating scale.                                      |
| `sync`   | `boolean` | `true`     | When `true`, wait for results and return them inline. When `false`, return a `202` pending task. |

### `levels` items

Each item in the `levels` array must have:

| Field         | Type     | Constraints      | Notes                                                       |
| ------------- | -------- | ---------------- | ----------------------------------------------------------- |
| `value`       | `string` | 1–24 characters  | The string returned in the result for images at this level. |
| `description` | `string` | 1–150 characters | Natural-language description used by the rating model.      |

Constraints for the `levels` array:

* Minimum `2` items
* Maximum `7` items

**How the rating model uses levels**

The `description` of each level is passed directly to a vision language model (LLM), which selects the best match for each image. Because LLM inference is non-deterministic, results for borderline images may occasionally vary between requests.

This endpoint is optimised for speed and accuracy at a high level of abstraction. Broad, clearly separated scales such as `safe` / `suggestive` / `explicit` or `safe-for-children` / `safe-for-adults` / `nsfw` perform reliably. Scales that depend on subtle visual distinctions — for example distinguishing between artistic and explicit nudity — are outside the intended scope and may produce inconsistent results. Test thoroughly before using such scales in production.

## Response body

### `200` — completed

Returned when `sync` is `true` (the default) and the task finishes within the sync timeout.

```json theme={"theme":"kanagawa-dragon"}
{
  "data": {
    "task": {
      "id": "tsk_01KE7XWWEQ4MCGWKBQKJ1G47RP",
      "status": "completed",
      "cost": "0.00020000"
    },
    "results": [
      { "status": "success", "url": "https://example.com/photo-1.webp", "level": "safe" },
      {
        "status": "failed",
        "url": "https://example.com/photo-2.webp",
        "error": { "code": "RATING_FAILED" }
      }
    ]
  }
}
```

| Field          | Type     | Notes                                                                                    |
| -------------- | -------- | ---------------------------------------------------------------------------------------- |
| `data.task`    | `object` | Task record created for this request.                                                    |
| `data.results` | `array`  | One entry per submitted URL, in the same order. Each entry is a success or failure item. |

### `202` — pending

Returned when `sync` is `false`, or when `sync` is `true` but the task did not finish within the sync timeout. Use the task `id` to poll for completion.

```json theme={"theme":"kanagawa-dragon"}
{
  "data": {
    "task": {
      "id": "tsk_01KE7XWWEQ4MCGWKBQKJ1G47RP",
      "status": "pending"
    }
  }
}
```

### Success item

```json theme={"theme":"kanagawa-dragon"}
{ "status": "success", "url": "https://example.com/photo-1.webp", "level": "sfw" }
```

| Field    | Type     | Notes                                            |
| -------- | -------- | ------------------------------------------------ |
| `status` | `string` | Always `success`.                                |
| `url`    | `string` | The submitted image URL.                         |
| `level`  | `string` | The assigned rating value from the active scale. |

When using the default scale, `level` is one of `sfw` or `nsfw`.
When using custom levels, `level` is the `value` of the chosen level.

### Failure item

```json theme={"theme":"kanagawa-dragon"}
{
  "status": "failed",
  "url": "https://example.com/photo-2.webp",
  "error": { "code": "RATING_FAILED" }
}
```

A failure item means that one image could not be rated. Other images in the same request are unaffected.

| Code            | Cause                                                                              |
| --------------- | ---------------------------------------------------------------------------------- |
| `FETCH_FAILED`  | The image could not be downloaded from the provided URL.                           |
| `RATING_FAILED` | The image was downloaded but the rating operation failed.                          |
| `UNKNOWN_ERROR` | An unexpected error occurred. Should not normally occur; treat as a bug and retry. |

## Limits

| Constraint          | Value            |
| ------------------- | ---------------- |
| URLs per request    | 1–10             |
| Custom levels       | 2–7              |
| Level `value`       | 1–24 characters  |
| Level `description` | 1–150 characters |

## Pricing

Each URL is priced at \*\*$0.0002**. The full amount (`urls` × $0.0002) is reserved from your account balance before processing begins. You are charged only for URLs that are successfully rated — the reserved balance for any failed ratings is released. If your balance is insufficient to reserve the full amount, the request returns `422 INSUFFICIENT_BALANCE`.

## Error responses

| Status | Body                                | Cause                                                                                  |
| ------ | ----------------------------------- | -------------------------------------------------------------------------------------- |
| `400`  | `{ success: false, errors: [...] }` | Request body fails schema validation.                                                  |
| `401`  | `{ code: "UNAUTHORIZED", ... }`     | Missing or invalid API key or OAuth access token.                                      |
| `422`  | `{ code: "INSUFFICIENT_BALANCE" }`  | Account balance is too low to reserve the full cost.                                   |
| `500`  | `{ code: "UNKNOWN_ERROR" }`         | `sync` is `true` and the rating task failed. Use async mode or retry to poll the task. |

See [Errors and Limits](/reference/errors-and-limits) for the full error reference.
