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

# Authentication and rate limits

> Scope, rotate and revoke personal and team API keys with live role restrictions.

## Keys and permissions

Create personal keys in **Manage → My Settings → API Keys**. Admins create team keys in **Manage → Team Settings → API Keys**. The inventory shows name, identifying prefix, access, expiry and last use. The raw token is shown only when created.

| Setting                    | Options                                              |
| -------------------------- | ---------------------------------------------------- |
| Scope                      | Personal; Team for Admins                            |
| Access                     | Read-only; Edit for Members and Admins               |
| Administrative permissions | Admins only, with Edit                               |
| Expiry                     | 30 days, 90 days (default), 1 year; Never for Admins |

Read-only grants permitted operational reads, not credential reveal. Edit adds repository, secret-update and Scout operations allowed by the current role. Administrative permissions add supported deployment and infrastructure actions. Browser-only account management, key creation and credential reveal remain unavailable to API/MCP tokens.

Personal keys intersect saved grants with current active membership. Demotion permanently narrows the key; subsequent promotion does not widen it. Removal revokes personal keys and sessions. Team keys are service identities with explicit team grants and survive their creator's departure. Missing or revoked policy records fail closed. Queued effects recheck authority before execution; revocation does not undo effects already performed.

## Authentication

```http theme={"system"}
Authorization: Bearer twb_YOUR_KEY
```

Better Auth's API Key plugin generates and verifies opaque tokens. Towbar stores hashed verifiers and policy records; the token is not a JWT and contains no embedded role or credentials. Metadata and audit events never return a token or verifier. `GET /identity` identifies the current actor and team; team keys do not impersonate a human creator.

API and MCP require Bearer tokens and do not accept browser cookies. Browser sessions use cookies and origin validation. An `Origin` header must match the configured dashboard origin; CLI clients normally omit it. Use HTTPS outside local development, and keep tokens out of URLs, logs and committed files. API-key session emulation is disabled.

## Rotation

Create a replacement key, update the consumer, verify a permitted request, then revoke the previous key. Revocation is permanent. Key creation retries use an idempotency key and do not redisplay a previously returned token. API and MCP cannot create more keys.

## Configure rate limits

Set these in the API process environment or your self-hosted `.env` file and restart the API service:

```dotenv theme={"system"}
TOWBAR_API_RATE_LIMIT_MAX=60
TOWBAR_API_RATE_LIMIT_WINDOW_SECONDS=60
TOWBAR_TRUSTED_PROXY_HOPS=0
```

| Variable                               | Default | Allowed range     |
| -------------------------------------- | ------- | ----------------- |
| `TOWBAR_API_RATE_LIMIT_MAX`            | `60`    | 1–100000 requests |
| `TOWBAR_API_RATE_LIMIT_WINDOW_SECONDS` | `60`    | 1–86400 seconds   |
| `TOWBAR_TRUSTED_PROXY_HOPS`            | `0`     | 0–8 hops          |

The fixed window starts at the first request after expiry. Each key has its own persistent limit. All API and MCP keys from the same client IP also share an address window. Changing keys or alternating interfaces does not create a new allowance. The browser control plane and GitHub webhook have their own authentication behavior and are not part of this bucket.

With zero trusted proxy hops, Towbar uses the socket address and ignores `X-Forwarded-For`. Behind a reverse proxy, set the exact number of controlled proxy hops and prevent direct access to the API listener. An incorrect count can group every client under the proxy IP or trust a spoofed address. For example, one directly connected Caddy proxy typically requires `1`; an additional CDN changes the topology and needs a matching configuration.

The counter is updated atomically in PostgreSQL. A database outage fails requests rather than bypassing the limit. REST event streams count once when connected; subsequent reconnects count as new requests.
