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

# Authentication

> API keys for scripts, session cookies for the app.

Brewgravity accepts two credentials, and treats them identically once verified —
the same ownership rules apply either way.

<CardGroup cols={2}>
  <Card title="API key" icon="key">
    `X-API-Key` header. For scripts, the MCP server, and anything that is not a
    browser.
  </Card>

  <Card title="Session cookie" icon="cookie-bite">
    Set when you sign in to the web app. Browser requests must send
    `credentials: 'include'`.
  </Card>
</CardGroup>

## Creating an API key

There is no key management screen yet. Keys are created through the auth API,
using your signed-in session — which means the simplest route is your browser's
console.

<Steps>
  <Step title="Sign in to Brewgravity">
    Open [brewgravity.com](https://brewgravity.com) and sign in normally.
  </Step>

  <Step title="Open the browser console">
    <kbd>⌘</kbd><kbd>⌥</kbd><kbd>J</kbd> on macOS, <kbd>Ctrl</kbd><kbd>Shift</kbd><kbd>J</kbd> on Windows and Linux.
  </Step>

  <Step title="Create the key">
    ```js theme={null}
    await fetch('/api/auth/api-key/create', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      credentials: 'include',
      body: JSON.stringify({ name: 'laptop script' }),
    }).then(r => r.json())
    ```
  </Step>

  <Step title="Copy the key">
    The response contains a `key` field. **This is the only time the full key is
    ever returned** — copy it now, into a password manager or an environment
    variable, not into a file you will commit.
  </Step>
</Steps>

<Warning>
  An API key has the same access to your account as you do: it can read, modify,
  and delete every recipe, session, log, and inventory item you own. Treat it
  like a password. Do not put it in client-side code, a public repository, or a
  URL.
</Warning>

### Managing keys

The same auth API lists and revokes them, again from a signed-in browser:

```js theme={null}
// List your keys (the full key values are not returned)
await fetch('/api/auth/api-key/list', { credentials: 'include' }).then(r => r.json())

// Revoke one
await fetch('/api/auth/api-key/delete', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  credentials: 'include',
  body: JSON.stringify({ keyId: '<id from the list above>' }),
}).then(r => r.json())
```

If a key leaks, revoke it. Creating a replacement takes a few seconds and
nothing else about your account needs to change.

## Using a key

Send it in the `X-API-Key` header on every request:

<CodeGroup>
  ```bash cURL theme={null}
  curl https://brewgravity.com/v1/recipes \
    -H "X-API-Key: $GRAVITY_API_KEY"
  ```

  ```js JavaScript theme={null}
  const res = await fetch('https://brewgravity.com/v1/recipes', {
    headers: { 'X-API-Key': process.env.GRAVITY_API_KEY },
  });
  const recipes = await res.json();
  ```

  ```python Python theme={null}
  import os, requests

  r = requests.get(
      "https://brewgravity.com/v1/recipes",
      headers={"X-API-Key": os.environ["GRAVITY_API_KEY"]},
  )
  recipes = r.json()
  ```
</CodeGroup>

## Checking a key works

```bash theme={null}
curl https://brewgravity.com/v1/me \
  -H "X-API-Key: $GRAVITY_API_KEY"
```

```json theme={null}
{
  "id": "a1b2c3d4-...",
  "email": "you@example.com",
  "name": "Your Name"
}
```

A missing, malformed, expired, or revoked key returns `401 Unauthorized` with
`{"error":"Unauthorized"}`. There is no distinction between the cases, by
design.

## Browser requests

If you are calling the API from a browser on `brewgravity.com` — a bookmarklet,
a console snippet, a userscript — the session cookie already works and you do
not need a key:

```js theme={null}
await fetch('/v1/recipes', { credentials: 'include' }).then(r => r.json())
```

Cross-origin requests are restricted to known origins. Server-side code should
use an API key rather than trying to reuse a cookie.
