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

# Wattetheria API: Authentication with Bearer Tokens

> Learn how to locate your control-plane Bearer token, pass it in every API request, and handle 401 errors across all deployment modes.

Every request to the Wattetheria Control Plane API (except `GET /v1/health`) must carry a Bearer token in the `Authorization` header. The token is generated automatically when your node first starts and is written to a well-known path on disk. You never set this token manually — you only read it from wherever your deployment mode placed it.

## Token File Locations

The path to your token depends on how you launched the node.

<ParamField path="Release binary" type="string">
  When you run the pre-built release binary from its default working directory, the token is written to:

  ```
  ./data/wattetheria/control.token
  ```
</ParamField>

<ParamField path="Source build" type="string">
  When you build and run from source using `--data-dir .wattetheria`, the token is written to:

  ```
  .wattetheria/control.token
  ```

  This path is relative to the directory where you ran the CLI. The leading dot makes the directory hidden by default on macOS and Linux.
</ParamField>

<ParamField path="Docker dev stack" type="string">
  When you use the provided Docker Compose dev stack, the token is persisted inside the named volume `wattetheria_state`. You can read it by exec-ing into the running container:

  ```bash theme={null}
  docker exec -it wattetheria cat /state/control.token
  ```

  The exact mount path inside the container may vary; check your `docker-compose.yml` for the volume mount target.
</ParamField>

## Passing the Token

Include the token value in the `Authorization` header on every request. The most convenient approach in a shell script or one-off `curl` command is to read the file inline using command substitution:

```bash theme={null}
curl -H "Authorization: Bearer $(cat ./data/wattetheria/control.token)" \
  http://127.0.0.1:7777/v1/health
```

For repeated use, you can export the token as an environment variable once per session:

<CodeGroup>
  ```bash Release / source build theme={null}
  export WATT_TOKEN=$(cat ./data/wattetheria/control.token)

  curl -H "Authorization: Bearer $WATT_TOKEN" \
    http://127.0.0.1:7777/v1/state
  ```

  ```bash Docker dev stack theme={null}
  export WATT_TOKEN=$(docker exec -it wattetheria cat /state/control.token | tr -d '\r')

  curl -H "Authorization: Bearer $WATT_TOKEN" \
    http://127.0.0.1:7777/v1/state
  ```
</CodeGroup>

<Tip>
  Store `$WATT_TOKEN` in your shell's environment file (`.bashrc`, `.zshrc`, etc.) if you interact with the API frequently during development. The token does not rotate unless you wipe node state and restart.
</Tip>

## 401 Unauthorized

If the token is missing, malformed, or does not match the value the node generated, every protected endpoint returns:

```json theme={null}
{
  "error": "unauthorized",
  "message": "Bearer token is missing or invalid."
}
```

<ResponseField name="error" type="string">
  Machine-readable error code. Always `"unauthorized"` for token failures.
</ResponseField>

<ResponseField name="message" type="string">
  Human-readable explanation. Useful for distinguishing a missing header from a bad token value.
</ResponseField>

The most common cause of a `401` outside of a misconfigured header is reading the token file before the node has finished its startup sequence. Wait until the node logs indicate it is ready, then re-read the file.

<Note>
  `GET /v1/health` does not require a token. It is intentionally unauthenticated so that orchestration tooling and container health checks can probe liveness without needing access to the token file.
</Note>
