# https://compresr.ai/docs/authentication

> Human-readable page: https://compresr.ai/docs/authentication

Every request needs an API key in the `X-API-Key` header. Create one in the [dashboard](/dashboard/api-keys) — keys start with `cmp_` and the full value is shown only once, so copy it immediately.

There are three ways to authenticate yourself:

## 1. Pass the key explicitly

Read it from the environment (or your secret manager) and hand it to the client. Never paste a key literal into source.

```python
import os
from compresr import CompressionClient

client = CompressionClient(api_key=os.environ["COMPRESR_API_KEY"])
```

**TypeScript**

```typescript
import { CompressionClient } from '@compresr/sdk';

const client = new CompressionClient({ apiKey: process.env.COMPRESR_API_KEY! });
```

**cURL**

```bash
curl -X POST https://api.compresr.ai/api/compress/question-specific/ \
  -H "X-API-Key: $COMPRESR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "context": "...",
    "query": "...",
    "compression_model_name": "{{DEFAULT_MODEL}}"
  }'
```

## 2. Set `COMPRESR_API_KEY`

Both SDKs read the `COMPRESR_API_KEY` environment variable when no key is passed explicitly:

```python
# export COMPRESR_API_KEY="cmp_your_api_key"
from compresr import CompressionClient

client = CompressionClient()  # key picked up from the environment
```

**TypeScript**

```typescript
// export COMPRESR_API_KEY="cmp_your_api_key"
import { CompressionClient } from '@compresr/sdk';

// Note: the options object is required, even when empty.
const client = new CompressionClient({}); // key picked up from the environment
```

**cURL**

```bash
export COMPRESR_API_KEY="cmp_your_api_key"

# cURL has no implicit pickup; reference the variable in the header.
curl -X POST https://api.compresr.ai/api/compress/question-specific/ \
  -H "X-API-Key: $COMPRESR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "context": "...",
    "query": "...",
    "compression_model_name": "{{DEFAULT_MODEL}}"
  }'
```

## 3. Log in once with the CLI

Both SDKs ship a `compresr-sdk` binary that stores a credential on your machine:

```bash
compresr-sdk login    # opens a browser flow, saves the key locally
compresr-sdk logout   # clears the local credential AND revokes the key server-side
```

`login` writes `~/.compresr/credentials` (INI, read by Python automatically) or `~/.compresr/credentials.json` (JSON, read by TypeScript via `createClient` from `@compresr/sdk/auth`). Deleting the file by hand only removes the local copy — use `logout` to actually revoke the key.

## When authentication fails

| Situation | Status | What you get |
|---|---|---|
| `X-API-Key` header missing | `422` | FastAPI's `{"detail": [...]}` shape, not the standard envelope |
| Key invalid, revoked, or expired | `401` | `code: authentication_error` |
| Wrong scope (e.g. a demo key on a compression endpoint) | `403` | `code: scope_error` |
| Balance or budget exhausted | `429` | `code: rate_limit_exceeded`, "usage limit exceeded" message |

Full envelope shapes and recovery guidance: [Error codes](/docs/api-reference/errors).

## Managing keys

Treat keys like passwords — anyone who has one can incur charges on your account until you revoke it.

**Storage.** Read keys from environment variables (`COMPRESR_API_KEY`); never hardcode them in source. Add `.env` to `.gitignore` before writing a key into it. In production, use a real secret manager (AWS/Google Secret Manager, Vault, Doppler, …) and inject at deploy time. Never put a key in client-side code, chat, tickets, or screenshots — if you do, treat it as leaked.

**Rotation.** Rotate on a schedule (90 days is a sane production default) and immediately on suspected compromise. Mint the new key, deploy it alongside the old one, confirm zero traffic on the old key in the dashboard usage log, then revoke it — revocation is immediate and returns `401` from that point on.

**Budgets and expiry.** A key can carry a monthly USD budget set at creation: once exhausted, requests return `429 rate_limit_exceeded` until you raise it or rotate. Small budgets cap the blast radius of keys handed to CI, contractors, or demos. A key can also carry an `expires_at` timestamp — past it, the key returns `401` with no further action needed. Use expiry for time-boxed access, budget-plus-rotation for permanent services.

**If a key leaks.** Revoke it in the [dashboard](/dashboard/api-keys) first — don't wait to confirm anyone saw it. Then rotate to a new key everywhere, audit the usage log for unfamiliar traffic, and if unexpected charges occurred, email founders@compresr.ai with the masked key preview from the dashboard (never the full key). Finish with a repo-wide scan (`git log -S "cmp_"`) — where one key leaked, others may have.
