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

# Error Codes

> HTTP error codes and error response format

## Error response format

All error responses follow this structure:

```json theme={null}
{
  "code": 400,
  "message": "Missing required fields: model, task_type, input"
}
```

| Field     | Type     | Description                               |
| --------- | -------- | ----------------------------------------- |
| `code`    | `number` | The HTTP status code                      |
| `message` | `string` | A human-readable description of the error |

***

## Error codes

### 400 — Bad Request

The request body is malformed or missing required fields.

**Common causes**:

* Missing `model`, `task_type`, or `input` in the request body
* Unknown or unsupported `task_type`
* Invalid input parameters for the selected task type

```json theme={null}
{
  "code": 400,
  "message": "Missing required fields: model, task_type, input"
}
```

### 401 — Unauthorized

The API key is missing, invalid, or has been revoked.

**Common causes**:

* No `x-api-key` header in the request
* API key does not exist or has been deleted
* API key has been disabled

```json theme={null}
{
  "code": 401,
  "message": "Invalid API key"
}
```

### 402 — Payment Required

Your account does not have enough available credits to cover the task cost.

**How to fix**: [Top up credits](https://sunor.cc/dashboard/billing) in your dashboard.

```json theme={null}
{
  "code": 402,
  "message": "Insufficient credits: available 3, required 10"
}
```

### 404 — Not Found

The requested resource does not exist.

**Common causes**:

* Invalid task ID
* Task belongs to a different user

```json theme={null}
{
  "code": 404,
  "message": "Task not found"
}
```

### 429 — Too Many Requests

You have exceeded the [rate limit](/rate-limits).

**How to fix**: Wait for the duration in `retry_after_seconds` (or the `Retry-After` header) before retrying.

```json theme={null}
{
  "code": 429,
  "message": "Rate limit exceeded.",
  "retry_after_seconds": 60
}
```

### 500 — Internal Server Error

An unexpected error occurred on the server.

**What to do**: For read-only requests, retry after a short delay. For
`POST /api/v1/task`, do not automatically submit the same task again when the
result is unknown; the current endpoint does not yet accept an
`Idempotency-Key`. If you already received a `task_id`, poll that task instead.

```json theme={null}
{
  "code": 500,
  "message": "Internal server error"
}
```

### 502 — Bad Gateway

The upstream AI provider returned an error or is temporarily unavailable.

**What to do**: If the provider failure is explicit, the failed task follows
the normal refund path. For an uncertain network or gateway result from
`POST /api/v1/task`, do not blindly create another task. If you already
received a `task_id`, poll that task instead.

```json theme={null}
{
  "code": 502,
  "message": "Upstream provider error"
}
```

***

## Handling errors

<Tip>
  Always check the HTTP status code before parsing the body. Follow
  `Retry-After` for `429` responses. Exponential backoff is appropriate for
  safe/read-only requests. For `POST /api/v1/task`, an uncertain `5xx` or
  network result should be treated as "create outcome unknown" rather than
  automatically submitted again. The API does not currently provide
  `Idempotency-Key` replay semantics.
</Tip>

### Example error handling

<CodeGroup>
  ```python Python theme={null}
  import requests
  import time

  def create_task(api_key, payload, max_rate_limit_retries=3):
      rate_limit_attempts = 0
      while True:
          response = requests.post(
              "https://sunor.cc/api/v1/task",
              headers={
                  "Content-Type": "application/json",
                  "x-api-key": api_key,
              },
              json=payload,
          )

          if response.status_code == 202:
              return response.json()["data"]
          elif response.status_code == 429 and rate_limit_attempts < max_rate_limit_retries:
              retry_after = int(response.headers.get("Retry-After", 30))
              time.sleep(retry_after)
              rate_limit_attempts += 1
          elif response.status_code >= 500:
              raise RuntimeError(
                  "Task creation outcome is unknown; do not submit the same "
                  "payload again without an idempotency key."
              )
          else:
              error = response.json()
              raise Exception(f"API error {error['code']}: {error['message']}")
  ```

  ```javascript Node.js theme={null}
  async function createTask(apiKey, payload, maxRateLimitRetries = 3) {
    let rateLimitAttempts = 0;
    while (true) {
      const response = await fetch("https://sunor.cc/api/v1/task", {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
          "x-api-key": apiKey,
        },
        body: JSON.stringify(payload),
      });

      if (response.status === 202) {
        const json = await response.json();
        return json.data;
      } else if (
        response.status === 429 &&
        rateLimitAttempts < maxRateLimitRetries
      ) {
        const retryAfter = parseInt(response.headers.get("Retry-After") || "30");
        await new Promise((r) => setTimeout(r, retryAfter * 1000));
        rateLimitAttempts += 1;
      } else if (response.status >= 500) {
        throw new Error(
          "Task creation outcome is unknown; do not submit the same payload " +
            "again without an idempotency key.",
        );
      } else {
        const error = await response.json();
        throw new Error(`API error ${error.code}: ${error.message}`);
      }
    }
  }
  ```
</CodeGroup>
