> ## 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.

# API introduction

> A small REST API over your recipes, brew sessions, fermentation logs, and inventory.

Everything the Brewgravity web app can do with your data, you can do over HTTP. The
API is what the [MCP server](/docs/api-reference/mcp) runs on, and it is stable
enough to script against.

<Card title="Base URL" icon="server">
  ```
  https://brewgravity.com
  ```

  All endpoints below are under `/v1`.
</Card>

## Design

<AccordionGroup>
  <Accordion title="Everything is scoped to you" icon="user-lock">
    There is no `user_id` parameter anywhere, because there does not need to be
    one. Your API key identifies you, and every query is scoped to your account
    before it runs. An id belonging to someone else returns `404` — never `403`,
    which would confirm the row exists.
  </Accordion>

  <Accordion title="Metric, always" icon="ruler">
    Kilograms, grams, litres, degrees Celsius, minutes. The unit preference in
    the app is a display setting and does not affect the API. Gravity readings
    are specific gravity, with the unit you entered recorded alongside.
  </Accordion>

  <Accordion title="Children are created against their parent" icon="sitemap">
    A hop is created at `POST /v1/recipes/{recipeId}/hops`, but updated and
    deleted at `/v1/hops/{id}`. Ids are globally unique, so once you have one
    you do not need to remember what it belongs to.
  </Accordion>

  <Accordion title="Stats are computed, never stored" icon="calculator">
    `GET /v1/recipes/{id}/stats` recalculates from the current ingredients every
    time. There is no cache to invalidate and no stale number to work around.
  </Accordion>
</AccordionGroup>

## A first request

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

```json theme={null}
[
  {
    "id": "0f0a1b2c-3d4e-5f60-7182-93a4b5c6d7e8",
    "name": "House IPA",
    "style": "American IPA",
    "type": "all_grain",
    "batch_size_liters": 19,
    "boil_time_minutes": 60,
    "efficiency": 0.72,
    "est_color_srm": 6.4,
    "notes": null,
    "created_at": "2026-03-02T10:11:12.000Z",
    "updated_at": "2026-08-14T18:02:44.000Z"
  }
]
```

## Building a recipe end to end

<Steps>
  <Step title="Create the recipe">
    ```bash theme={null}
    curl -X POST https://brewgravity.com/v1/recipes \
      -H "X-API-Key: $GRAVITY_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{"name":"House IPA","style":"American IPA","batch_size_liters":19,"efficiency":0.72}'
    ```

    Keep the returned `id`.
  </Step>

  <Step title="Add ingredients">
    ```bash theme={null}
    curl -X POST https://brewgravity.com/v1/recipes/$RECIPE_ID/fermentables \
      -H "X-API-Key: $GRAVITY_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{"name":"Maris Otter","type":"grain","amount_kg":5,"color_srm":3,"yield_percent":81}'

    curl -X POST https://brewgravity.com/v1/recipes/$RECIPE_ID/hops \
      -H "X-API-Key: $GRAVITY_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{"name":"Citra","amount_grams":28,"alpha_acid":12.5,"time_minutes":60,"use":"boil"}'
    ```
  </Step>

  <Step title="Check the numbers">
    ```bash theme={null}
    curl https://brewgravity.com/v1/recipes/$RECIPE_ID/stats \
      -H "X-API-Key: $GRAVITY_API_KEY"
    ```

    Returns OG, FG, ABV, IBU, SRM, attenuation, calories, and BU:GU.
  </Step>

  <Step title="Brew it">
    ```bash theme={null}
    curl -X POST https://brewgravity.com/v1/sessions \
      -H "X-API-Key: $GRAVITY_API_KEY" \
      -H "Content-Type: application/json" \
      -d "{\"recipe_id\":\"$RECIPE_ID\",\"brew_date\":\"2026-09-01\"}"
    ```
  </Step>
</Steps>

## What is not in the REST surface

`POST /v1/chat` streams a response and is built for the app's chat panel rather
than for scripting. The threads themselves are ordinary REST resources under
`/v1/chats`, so listing and reading past conversations works normally.

## Next

<CardGroup cols={2}>
  <Card title="Authentication" icon="key" href="/docs/api-reference/authentication">
    Create an API key and make your first authenticated call.
  </Card>

  <Card title="Errors" icon="triangle-exclamation" href="/docs/api-reference/errors">
    Status codes, error shapes, and rate limits.
  </Card>
</CardGroup>
