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

# Authentication

<Info>
  **Private Beta:** Stratus is currently in private beta. Visit [stratus.run](https://stratus.run/?beta=true) to apply for access. Once approved you'll be able to create an account and generate API keys immediately.
</Info>

Stratus X1 uses a **two-tier key model**. Your Stratus API key is the only hard requirement — LLM provider keys are optional.

<CardGroup cols={2}>
  <Card title="Stratus API Key" icon="key" color="#22d3ee">
    Authenticates you with Stratus X1. Create and manage keys in the [Dashboard → API Keys](https://stratus.run/dashboard?tab=overview). Keys start with `stratus_sk_live_`.
  </Card>

  <Card title="LLM Provider Key" icon="plug" color="#c084fc">
    Optional. Your **OpenAI, Anthropic, Google Gemini, or OpenRouter** key. When omitted, Formation's shared OpenRouter pool activates automatically. Add your own key to remove the 25% pool markup and pay providers directly.
  </Card>
</CardGroup>

## Stratus API Keys

Stratus uses API keys for authentication. All requests must include your API key in the `Authorization` header.

### Getting Your API Key

1. Sign in at [stratus.run/signin](https://stratus.run/signin) using Google, GitHub, Telegram, or email OTP
2. Navigate to [Dashboard → API Keys](https://stratus.run/dashboard?tab=overview)
3. Click "Create New API Key"
4. Name your key and copy it

### API Key Format

Stratus API keys use the format `stratus_sk_live_*`. Keys are also accepted via the `x-api-key` header (Anthropic SDK convention).

<Warning>
  **Keep your API key secret.** Never commit it to version control or expose it in client-side code.
</Warning>

## Using Your API Key

### Environment Variables

**Recommended:** Store your API key in environment variables.

```bash theme={null}
# .env file
STRATUS_API_KEY=stratus_sk_live_your-key-here
```

Add to `.gitignore`:

```
.env
.env.local
```

### In Your Code

#### TypeScript / Node.js

```typescript theme={null}
import OpenAI from 'openai';

const client = new OpenAI({
  baseURL: 'https://api.stratus.run/v1',
  apiKey: process.env.STRATUS_API_KEY
});
```

#### Python

```python theme={null}
import os
from openai import OpenAI

client = OpenAI(
    base_url="https://api.stratus.run/v1",
    api_key=os.environ["STRATUS_API_KEY"]
)
```

### HTTP Requests

```bash theme={null}
curl https://api.stratus.run/v1/chat/completions \
  -H "Authorization: Bearer stratus_sk_live_..." \
  -H "Content-Type: application/json" \
  -d '{...}'
```

## Key Resolution Priority

When Stratus receives a chat or messages request, it resolves which LLM key to use in this order:

| Priority                  | Source                                         | How to use                                                            | Markup                           |
| ------------------------- | ---------------------------------------------- | --------------------------------------------------------------------- | -------------------------------- |
| **1 — Inline headers**    | Your key passed directly in the request header | `X-OpenAI-Key`, `X-Anthropic-Key`, `X-Google-Key`, `X-OpenRouter-Key` | None — you pay provider directly |
| **2 — Vault-stored keys** | Your key saved via `POST /v1/account/llm-keys` | Set once, used automatically                                          | None — you pay provider directly |
| **3 — Formation pool**    | Formation's shared OpenRouter key              | Automatic fallback when no native key is found                        | 25% markup on credit cost        |

Formation's pool means **every account can make requests on day one**, with no external setup required. Adding your own key at any priority level bypasses the pool entirely.

### Inline Key Headers

Pass your own key directly per-request. Useful for testing, CI pipelines, or multi-key setups:

```bash theme={null}
curl https://api.stratus.run/v1/chat/completions \
  -H "Authorization: Bearer $STRATUS_API_KEY" \
  -H "X-OpenAI-Key: sk-proj-..." \
  -H "Content-Type: application/json" \
  -d '{"model": "stratus-x1ac-base-gpt-4o", "messages": [...]}'
```

All four providers are supported:

| Header             | Provider      | Key format                |
| ------------------ | ------------- | ------------------------- |
| `X-OpenAI-Key`     | OpenAI        | `sk-proj-...` or `sk-...` |
| `X-Anthropic-Key`  | Anthropic     | `sk-ant-...`              |
| `X-Google-Key`     | Google Gemini | `AIza...`                 |
| `X-OpenRouter-Key` | OpenRouter    | `sk-or-...`               |

Inline keys take precedence over everything — vault-stored keys and the Formation pool are both bypassed.

### Formation's Pool (Zero-Config Default)

When no key is supplied at priority 1 or 2, Stratus transparently routes the request through Formation's shared OpenRouter pool. The response includes billing transparency fields:

```json theme={null}
{
  "stratus": {
    "key_source": "formation",
    "formation_markup_applied": 0.25
  }
}
```

When you supply your own key, `key_source` is `"user"` and `formation_markup_applied` is `null`.

### Benefits of Bring-Your-Own-Key (BYOK)

<CardGroup cols={2}>
  <Card title="No Markup" icon="dollar-sign">
    Pay providers directly at your rates. Formation's 25% pool markup is not applied.
  </Card>

  <Card title="Privacy" icon="lock">
    Vault-stored keys are encrypted at rest using AES-256-GCM and never leave encrypted storage.
  </Card>

  <Card title="Cost Control" icon="sliders">
    Use your negotiated provider rates. High-volume accounts often get better rates than the pool.
  </Card>

  <Card title="Compliance" icon="shield-check">
    Meet data residency and privacy requirements by using your own provider account.
  </Card>
</CardGroup>

### Setting Up Vault-Stored Keys (Optional)

Store your provider keys once — Stratus encrypts them and uses them automatically on every request, bypassing the Formation pool markup entirely.

<Tabs>
  <Tab title="Dashboard">
    The fastest way. No code required.

    1. Go to [stratus.run/dashboard?tab=llm-keys](https://stratus.run/dashboard?tab=llm-keys)
    2. Enter keys for the providers you use — you only need to fill in the ones you want to use
    3. Click **Save Keys**

    Your keys are encrypted at rest (AES-256-GCM) and used automatically from that point forward. All future requests will show `key_source: "user"` in the response and no Formation markup will be applied.

    <Info>
      You can add, update, or remove keys from the dashboard at any time. Changes take effect immediately.
    </Info>
  </Tab>

  <Tab title="API">
    Use the `POST /v1/account/llm-keys` endpoint for programmatic setup — useful for automated provisioning or CI environments.

    ```typescript theme={null}
    // One-time setup — removes the Formation pool markup
    await fetch('https://api.stratus.run/v1/account/llm-keys', {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${process.env.STRATUS_API_KEY}`,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        openai_key: process.env.OPENAI_API_KEY,         // sk-proj-... (optional)
        anthropic_key: process.env.ANTHROPIC_API_KEY,   // sk-ant-...  (optional)
        google_key: process.env.GOOGLE_API_KEY,          // AIza...     (optional)
        openrouter_key: process.env.OPENROUTER_API_KEY,  // sk-or-...   (optional)
      })
    });
    ```

    After setup, all future requests automatically use your stored key:

    ```typescript theme={null}
    const response = await client.chat.completions.create({
      model: 'stratus-x1ac-base-gpt-4o',
      messages: [{ role: 'user', content: 'Hello' }]
    });

    // response.stratus.key_source === "user"
    // response.stratus.formation_markup_applied === null
    ```

    See [LLM Key Management](/docs/api-reference/llm-keys) for the full GET and DELETE endpoints.
  </Tab>
</Tabs>

## Managing Your API Keys

### Creating Keys

Create API keys from the [Stratus dashboard](https://stratus.run/dashboard?tab=overview). Each account supports up to **3 active API keys** — useful for separating environments or rotating keys without downtime.

### Revoking Keys

If a key is compromised:

1. Go to [Dashboard → API Keys](https://stratus.run/dashboard?tab=overview)
2. Click "Delete" on the compromised key
3. The key is immediately invalid
4. Create a new key and update your applications

## Troubleshooting

All errors use an OpenAI-compatible response shape:

```json theme={null}
{
  "error": {
    "message": "...",
    "type": "...",
    "code": "..."
  }
}
```

### 401 — Missing API Key

```json theme={null}
{
  "error": {
    "message": "Missing or invalid API key. Include 'Authorization: Bearer sk-...' header.",
    "type": "authentication_error",
    "code": "missing_api_key"
  }
}
```

**Cause:** No `Authorization` header was sent, or it isn't formatted as `Bearer <token>`.

**Fix:** Add `Authorization: Bearer stratus_sk_live_<your-key>` to every request. The `x-api-key` header is also accepted.

***

### 401 — Invalid API Key

```json theme={null}
{
  "error": {
    "message": "Invalid API key provided.",
    "type": "authentication_error",
    "code": "invalid_api_key"
  }
}
```

**Cause:** A key was sent but it doesn't exist, has been revoked, or is inactive.

**Fix:** Confirm the key is still active in [Dashboard → API Keys](https://stratus.run/dashboard?tab=overview). If it was deleted, generate a new one. Keys must start with `stratus_sk_live_`.

***

### 402 — Insufficient Credits

```json theme={null}
{
  "error": {
    "message": "Insufficient credits. Required: 0.05, Available: 0.01",
    "type": "insufficient_credits",
    "code": "insufficient_credits",
    "required_credits": 0.05,
    "available_credits": 0.01
  }
}
```

**Cause:** The estimated cost of the request exceeds your credit balance. The model was never called — this is a pre-flight check.

**Fix:** Top up credits from the [dashboard](https://stratus.run/dashboard). If you're seeing a `formation_markup` variant of this error, registering your own provider key via `POST /v1/account/llm-keys` eliminates the 25% markup and reduces the required credits.

***

### 401 — No Provider Key Found

```json theme={null}
{
  "error": {
    "message": "No openai key or OpenRouter key found. Add one via POST /v1/account/llm-keys with provider='openai' or provider='openrouter'.",
    "type": "missing_provider_key"
  }
}
```

**Cause:** The requested model's provider has no key available from any source — no inline header, no vault-stored key, and Formation's pool either isn't enabled or doesn't support this model.

**Fix:** Add a key for the relevant provider via [Dashboard → LLM Keys](https://stratus.run/dashboard?tab=llm-keys) or pass it inline per-request using `X-OpenAI-Key` / `X-Anthropic-Key` / `X-Google-Key`.

***

### 400 — LLM Key Validation Failed

```json theme={null}
{
  "error": {
    "message": "Invalid API key: Key validation failed: anthropic: Authentication failed"
  }
}
```

**Cause:** When storing a key via `POST /v1/account/llm-keys`, Stratus makes a live test call to the provider. The provider rejected it — wrong key, permissions issue, or the key is rate-limited.

**Fix:** Verify the key in your provider's dashboard and confirm it has API access enabled. If the provider is throttling it, wait a moment and retry.

***

### 422 — Validation Error

```json theme={null}
{
  "error": {
    "message": "Request validation failed",
    "type": "validation_error",
    "details": [...]
  }
}
```

**Cause:** The request body failed schema validation — missing required field, wrong type, or an unrecognized value.

**Fix:** Check the `details` array for field-level error messages and correct the request payload. See the [API Reference](/docs/api-reference/chat-completions) for required fields.

## Next Steps

<CardGroup cols={3}>
  <Card title="Quickstart" icon="rocket" color="#22d3ee" href="/docs/quickstart">
    Make your first API call in under 60 seconds.
  </Card>

  <Card title="Tutorials" icon="graduation-cap" color="#c084fc" href="/docs/tutorials/web-navigation">
    Real-world agents — navigation, cascades, concurrency.
  </Card>

  <Card title="API Reference" icon="code" color="#34d399" href="/docs/api-reference/introduction">
    Full endpoint docs, parameters, and error codes.
  </Card>
</CardGroup>
