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

# Authentication

> Bearer-token API auth. Clerk-backed control plane comes when we ship the dashboard.

<Note>
  Podflare has two auth surfaces. This page covers **API auth** — the
  bearer token SDKs send on every request. The **control plane** (humans
  logging into a dashboard to manage orgs, keys, and billing) will be
  built on Clerk once the web app ships.
</Note>

## API auth model

* Every request to `/v1/*` except `/v1/healthz` requires
  `Authorization: Bearer <key>`.
* Valid keys are configured server-side (env var in v0, DB later).
* A dev-mode toggle disables enforcement entirely for local work.

## Configuring hostd

<ParamField path="PODFLARE_API_KEYS" type="string (comma-separated)">
  Comma-separated list of valid bearer tokens. Any of these authenticates
  a request. If unset **and** hostd is bound to a loopback address, auth
  is silently disabled (dev mode). Hostd refuses to start otherwise.
</ParamField>

<ParamField path="PODFLARE_AUTH_DISABLED" type="bool" default="false">
  Set to `1` to bypass auth entirely. Only useful for local dev / the
  SSH-tunnel loop. Logs a loud warning at startup.
</ParamField>

<ParamField path="PODFLARE_HOSTD_ADDR" type="string" default="127.0.0.1:7070">
  Where hostd binds. A non-loopback bind + no keys + no disable flag is
  refused at startup — we won't accidentally expose an unauth'd API.
</ParamField>

## SDK usage

<CodeGroup>
  ```python Python theme={null}
  from podflare import Sandbox

  # Explicit
  sbx = Sandbox(api_key="pk_your_key_here")

  # Or via env
  # export PODFLARE_API_KEY=pk_...
  sbx = Sandbox()
  ```

  ```ts TypeScript theme={null}
  import { Sandbox } from "podflare";

  const sbx = await Sandbox.create({ apiKey: "pk_your_key_here" });

  // or env: PODFLARE_API_KEY=pk_...
  const sbx2 = await Sandbox.create();
  ```

  ```bash curl theme={null}
  curl -X POST https://api.podflare.ai/v1/sandboxes \
    -H "Authorization: Bearer pk_your_key_here" \
    -H "content-type: application/json" \
    -d '{}'
  ```
</CodeGroup>

## Headers

The SDK sets three headers, all pass-through to hostd:

| Header                                   | Purpose                             |
| ---------------------------------------- | ----------------------------------- |
| `Authorization: Bearer <key>`            | API auth (this page).               |
| `traceparent: 00-<trace>-<span>-<flags>` | W3C Trace Context for span nesting. |
| `content-type: application/json`         | Request body shape.                 |

## MCP server

Pass the key in the MCP server's env block so it forwards on every
sandbox call:

```json theme={null}
{
  "mcpServers": {
    "podflare": {
      "command": "node",
      "args": ["/absolute/path/to/podflare/mcp/dist/index.js"],
      "env": {
        "PODFLARE_HOSTD_URL": "https://api.podflare.ai",
        "PODFLARE_API_KEY": "pk_your_key_here"
      }
    }
  }
}
```

## Errors

* `401 Unauthorized` — no key, or the key isn't in hostd's allowlist.
  Response body: `{"error": "missing Authorization: Bearer <key>"}` or
  `{"error": "invalid api key"}`.

## What's coming (Clerk control plane)

Next steps once we build the dashboard:

1. User signs up via Clerk (email, Google, GitHub — social login + MFA).
2. User lands in a Podflare workspace (Clerk org).
3. Dashboard lets them CRUD API keys, see usage, view traces.
4. Keys are stored in our database with scopes + rotation support, not
   the env var baseline v0 uses.
5. The SDK flow above stays identical — only the key *issuance* surface
   changes.

Contributions welcome; the control-plane repo is planned separately.
