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

# API tokens

> Create Embedder bearer tokens, configure daemon and API authentication, and keep Embedder credentials separate from model-provider keys.

An Embedder API token authorizes HTTP API and daemon requests. Send it in:

```text theme={"system"}
Authorization: Bearer <token>
```

<Warning>
  Treat the token as an account credential. Keep it in a secret store or process environment and replace it if it is exposed.
</Warning>

For organization usage data, follow [Get an Analytics API token](/api-reference/analytics-token) and enable the required `analytics:read` scope.

## Create a token in the app

Open [Account](https://app.embedder.com/account), select **Tokens**, create a token with a name that identifies its machine or job, and copy the value into that machine's secret store.

Examples of useful names:

```text theme={"system"}
daemon-lab-mac
daemon-ci-rack
api-release-script
```

Do not reuse one key across unrelated machines. Separate keys let you replace one credential without interrupting every daemon.

## Create a token through the API

The CLI's token-creation contract is:

```bash theme={"system"}
curl -X POST \
  "https://backend-service-prod.embedder.com/api/v1/tokens" \
  -H "Authorization: Bearer $EXISTING_EMBEDDER_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "daemon-lab-mac",
    "expiresIn": null
  }'
```

The response contains the new secret in `key`:

```json theme={"system"}
{
  "key": "..."
}
```

Capture that value from the creation response. The current CLI contract does not define a token-list response that can recover it later.

`name` is required by the CLI flow. `embedder start daemon` generates `Embedder daemon <short-hostname>` and truncates it to 32 characters.

The daemon creation flow sends `expiresIn: null` and does not send a scopes field. The client contract does not define a token-count limit or the server's expiry units, so this reference does not assign behavior to them.

## Use a token with HTTP

```bash theme={"system"}
export EMBEDDER_API_KEY="your-token"

curl "https://backend-service-prod.embedder.com/api/v1/users/me" \
  -H "Authorization: Bearer $EMBEDDER_API_KEY" \
  -H "Accept: application/json"
```

An invalid or rejected bearer receives `401`. A valid bearer can still receive `403` when the account, role, organization feature, or operation does not permit the request.

## Use a token with the daemon

For a non-interactive host:

```bash theme={"system"}
export EMBEDDER_API_KEY="your-token"
embedder start daemon
```

PowerShell:

```powershell theme={"system"}
$env:EMBEDDER_API_KEY = "your-token"
embedder start daemon
```

`embedder start daemon` resolves authentication in this order:

1. `EMBEDDER_API_KEY`
2. A stored daemon key for the backend URL
3. A key created from the current interactive login
4. A pasted key

The detached child receives the selected key as `EMBEDDER_API_KEY`.

The foreground `embedder --daemon` mode is stricter. It accepts the environment variable or a stored daemon key and fails if neither exists.

## Stored daemon keys

When the CLI creates or prompts for a daemon key, it stores the key in an encrypted file below `~/.embedder`. The filename is scoped by environment and a hash of the normalized backend URL.

This prevents a key created for one backend from being sent to another backend by mistake.

`EMBEDDER_API_KEY` always takes precedence over the stored file. Use that precedence to test a replacement before changing any saved credential.

## `EMBEDDER_API_KEY` and `EMBEDDER_AUTH_TOKEN`

These variables serve different launch paths:

| Variable              | Purpose                                                                                                      |
| --------------------- | ------------------------------------------------------------------------------------------------------------ |
| `EMBEDDER_API_KEY`    | Daemon key and HTTP examples                                                                                 |
| `EMBEDDER_AUTH_TOKEN` | Overrides stored interactive credentials for `--server`, `embedder status`, and other user-session API calls |

Both values are sent as bearer tokens. The names describe which client path reads them.

`EMBEDDER_AUTH_TOKEN` wins over the encrypted interactive credential file. It does not replace `EMBEDDER_API_KEY` in daemon mode.

## Model-provider keys are separate

An Embedder token is not an OpenAI-compatible endpoint key, GitHub Copilot credential, ChatGPT credential, or MCP token.

| Credential                       | Configuration                                    |
| -------------------------------- | ------------------------------------------------ |
| Embedder API token               | `EMBEDDER_API_KEY` or `EMBEDDER_AUTH_TOKEN`      |
| Local model endpoint key         | `/connect` or `~/.embedder/local-endpoints.json` |
| GitHub Copilot and ChatGPT OAuth | `/connect`                                       |
| MCP bearer or API key            | `~/.embedder/mcp.json` or the MCP catalog        |

Using a model-provider key as `EMBEDDER_API_KEY` produces `401` because it was not issued by the Embedder backend.

## Rotate a daemon key

<Steps>
  <Step title="Create a replacement">
    Create a new key in the app or with `POST /api/v1/tokens`.
  </Step>

  <Step title="Test it">
    ```bash theme={"system"}
    curl "https://backend-service-prod.embedder.com/api/v1/users/me" \
      -H "Authorization: Bearer $NEW_KEY"
    ```

    `embedder status` reads `EMBEDDER_AUTH_TOKEN`, so use the direct API request when you are testing a daemon key.
  </Step>

  <Step title="Restart the daemon">
    ```bash theme={"system"}
    embedder stop daemon
    EMBEDDER_API_KEY="$NEW_KEY" embedder start daemon
    ```
  </Step>

  <Step title="Remove the old key">
    Revoke the old credential from the API key settings after the replacement daemon shows `connected` in `embedder monitor`.
  </Step>
</Steps>

This reference does not define an HTTP revocation route. Use the app's API key controls rather than guessing a `DELETE /tokens/...` endpoint.

## Handle authentication failures

<AccordionGroup>
  <Accordion title="The daemon exits after a 401 or 403 WebSocket upgrade">
    The backend rejected the key before the daemon connected. Confirm the key belongs to the selected backend and that `--backend-url`, `EMBEDDER_BACKEND_URL`, and `EMBEDDER_API_URL` point to the intended deployment.
  </Accordion>

  <Accordion title="A stored daemon key is rejected during start">
    `embedder start daemon` removes the rejected stored key from its resolution path and asks for a replacement. Set `EMBEDDER_API_KEY` to bypass the stored value.
  </Accordion>

  <Accordion title="The API works but the daemon claims no work">
    Authentication succeeded. Check the repository mapping and any `--team` and `--project` override; queue eligibility is separate from bearer validation.
  </Accordion>

  <Accordion title="A provider key returns 401 as EMBEDDER_API_KEY">
    Create an Embedder token. Local model, Copilot, Codex, and MCP credentials are not interchangeable with the Embedder bearer.
  </Accordion>
</AccordionGroup>
