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

# Authentication

> One header on every request.

```
Authorization: Bearer nj_sk_YOUR_API_KEY
```

## Get a key

Create one at [Developers → Keys](https://www.ninjachat.ai/developers/keys). Keys start with `nj_sk_` and are shown **once** — copy immediately.

Browsing and estimates are free. Paid calls draw from your **Developer Balance** — top up at [Developers → Billing](https://www.ninjachat.ai/developers/billing), or verify your phone on your first paid action to unlock a \$0.50 starter balance.

## Use it

<CodeGroup>
  ```typescript TypeScript SDK theme={null}
  import { NinjaChat } from "@ninjachat/sdk";

  const client = new NinjaChat({
    apiKey: process.env.NINJACHAT_API_KEY!,
  });

  const response = await client.responses.create({
    model: "ninja/auto",
    input: "Hello",
  });
  ```

  ```python Python SDK theme={null}
  import os
  from ninjachat import NinjaChat

  client = NinjaChat(api_key=os.environ["NINJACHAT_API_KEY"])
  response = client.responses.create(
      model="ninja/auto",
      input="Hello",
  )
  ```

  ```bash cURL theme={null}
  curl https://www.ninjachat.ai/api/v1/responses \
    -H "Authorization: Bearer $NINJACHAT_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{"model":"ninja/auto","input":"Hello"}'
  ```
</CodeGroup>

## Keep it secret

Environment variables, never hardcoded:

```bash theme={null}
export NINJACHAT_API_KEY="nj_sk_YOUR_API_KEY"   # or a .env file in .gitignore
```

And never in frontend code — CORS is open on `/api/v1/*`, but a key in the browser is a key stolen. Proxy through your backend:

```python theme={null}
@app.post("/api/chat")
def proxy(req):
    return client.responses.create(
        model="ninja/auto",
        input=req.json["message"],
    )
```

## Key management

* Up to **25 active keys** per account — use separate keys for dev / staging / prod; once you hit the cap, revoke one to create another
* Revoke instantly from [Developers → Keys](https://www.ninjachat.ai/developers/keys); revoked keys stop **immediately**
* The same key works for the [MCP server](/mcp/overview) — agents and code share one balance

## Auth errors

| Status | Error                | Fix                                                                                                                                                                                       |
| ------ | -------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 401    | `missing_api_key`    | Add the `Authorization: Bearer nj_sk_...` header                                                                                                                                          |
| 401    | `invalid_api_key`    | Key is malformed or revoked — create a new one                                                                                                                                            |
| 401    | `expired_api_key`    | Key passed its expiry date — create a new one                                                                                                                                             |
| 403    | `read_only_key`      | Key was created read-only and can't make billable requests — use a full-access key                                                                                                        |
| 403    | `insufficient_scope` | The credential can't call this endpoint (a Continue with NinjaChat wallet token can only spend on inference, not read usage, sessions, webhooks, or battles) — use a regular `nj_sk_` key |
