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

> ## Agent Instructions
> The Deepshi API is an OpenAI-compatible gateway. Base URL: https://api.deepshi.ai/v1. API keys start with sk-bf- and go in the Authorization: Bearer header. Prefer the official OpenAI SDKs pointed at the Deepshi base URL. Model ids are clean with no provider prefix (e.g. deepshi-3.0, claude-opus-4.8, gpt-5.5). Chat and image requests are synchronous; video and music requests are asynchronous job APIs (create, then poll). Every synchronous response carries usage.cost.total_cost in USD. Do not reference the internal /api/* admin plane or virtual keys.

# Errors & status codes

> Understand the HTTP status codes the API returns and how to handle them.

The Deepshi API uses standard HTTP status codes. Errors return a JSON body with an `error` object describing what went wrong.

```json theme={null}
{
  "error": {
    "message": "You have insufficient credits to complete this request.",
    "type": "insufficient_quota",
    "code": "insufficient_quota",
    "param": null
  }
}
```

The `code` is a machine-readable string (for example `invalid_api_key`, `model_not_found`, or `insufficient_quota`), not the HTTP status, and it may be `null`. Match on the HTTP status code for routing, and on `error.code` for specifics.

## Status codes

| Status                  | Meaning                                                            | What to do                                                                          |
| ----------------------- | ------------------------------------------------------------------ | ----------------------------------------------------------------------------------- |
| `200 OK`                | Success                                                            | Nothing to do.                                                                      |
| `400 Bad Request`       | Malformed request, or a model id that doesn't exist in the catalog | Check your JSON body and that `model` is a valid catalog id.                        |
| `401 Unauthorized`      | Missing, malformed, or unknown API key                             | Verify the `Authorization: Bearer YOUR_DEEPSHI_API_KEY` header.                     |
| `402 Payment Required`  | Out of credits                                                     | [Top up your balance.](/get-started/pricing-credits)                                |
| `403 Forbidden`         | Key revoked or inactive, or not allowed to use the requested model | Use an active key, and check the model is one your key can call (`GET /v1/models`). |
| `429 Too Many Requests` | Rate limit exceeded                                                | Back off and retry with exponential backoff.                                        |
| `5xx`                   | Temporary server error                                             | Retry with backoff.                                                                 |

## Rate limits

Request rate limits depend on your **plan** and apply across **all of your API keys** together. If you exceed your limit, requests return **`429`** until the window resets, and the blocked request is **not charged**. Back off and retry with exponential backoff (see below), and upgrade your plan for a higher limit.

## Handling errors in code

Retry transient failures (`429` and `5xx`) with exponential backoff, and surface the others to the user:

```python theme={null}
import time
from openai import OpenAI, APIStatusError

client = OpenAI(base_url="https://api.deepshi.ai/v1", api_key="YOUR_DEEPSHI_API_KEY")

def chat_with_retry(messages, retries=3):
    for attempt in range(retries):
        try:
            return client.chat.completions.create(
                model="deepshi-3.0", messages=messages,
            )
        except APIStatusError as e:
            if e.status_code in (429, 500, 502, 503) and attempt < retries - 1:
                time.sleep(2 ** attempt)   # backoff
                continue
            raise
```

<Warning>
  Don't retry `400`, `401`, `402`, or `403`. They won't succeed on retry. Fix
  the request, key, balance, or model access instead.
</Warning>

## Media-specific errors

A few errors are specific to the image, video, and music APIs:

* **`400 PROMPT_TOO_LONG`**: the prompt exceeds the model's `prompt_max_length`. Each model's limit is in `GET /v1/models` and on its [model page](/models/overview). Shorten the prompt.
* **`400` for unsupported parameters or values**: for example a `resolution` or `duration` the model doesn't offer. Check the model's allowed values in `GET /v1/models`.

## Async job failures

Video and music jobs fail differently from synchronous requests. Creating the job succeeds, and the failure appears later, when polling: a normal `200` response with `status: "failed"` and an `error` object.

```json theme={null}
{
  "id": "vid_a1b2c3...",
  "object": "video",
  "status": "failed",
  "error": { "message": "A description of what went wrong" }
}
```

Always check `status` when polling; an HTTP-level check alone won't catch it. A failed job is **not charged**. To retry, fix whatever the `error` describes and create a new job.
