> For the complete documentation index, see [llms.txt](https://docs.brewfather.app/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.brewfather.app/api.md).

# API

{% hint style="warning" %}
API version 1 is deprecated and will be discontinued; please convert to version 2 (this version).
{% endhint %}

{% hint style="info" %}
**Changes in version 2 of the API include**:

* A new method of paging the GET requests that lists multiple elements. The parameter "offset" is replaced with "start\_after". Use the "\_id" in the last element of the previous request to get to the next set of elements.
* The default ordering of elements has changed to use the "\_id" field instead of the "name" field.
* Added new query parameters order\_by and order\_by\_direction to enable custom ordering of the results
* GET batches no longer have a default value for the "status" parameter
* Version 2 has an increased rate limit
* Measured values can now be updated for a batch PATCH
* Recipes can now be created, updated, and deleted via the API
* Batches can now be deleted via the API
* Inventory items can now be created and deleted via the API, and inventory PATCH supports partial item updates in addition to inventory-only stock adjustments
* Delete operations require separate `*.delete` API-key scopes
  {% endhint %}

## Disclaimer

Please keep yourself updated on the API documentation as important messages and changes will be listed above this disclaimer.

Data returned from the API will be in metric units. Requests are ordered by the "\_id" field.

## Authentication

The authorization header must consist of your userid:apikey (base64 encoded).

**Example**:

UserId: xyz123\
API-key: 1234567890123456789012345678901234567890abcd\
\
Base64 encode: "xyz123:1234567890123456789012345678901234567890abcd"

```javascript
curl -H "authorization: Basic eHl6MTIzOjEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTBhYmNk" \
https://api.brewfather.app/v2/batches
```

In Postman, you can configure Basic Authorization by clicking the **Authorization** tab, selecting **Basic Auth** from the drop-down selector, and then typing the **username** (userid from above) and **password** (api-key from above) on the right of the colon on each row.

The API supports HTTPS traffic only (for security reasons).

## Generate API-Key

In the Settings page, you can click GENERATE in the API-section to create your API-key. You can currently only have one API-key per account.

### Scopes

Scopes control what the API-key can access. Currently, you can choose:

| Scope              | Permission       |
| ------------------ | ---------------- |
| `recipes.read`     | Read Recipes     |
| `recipes.write`    | Edit Recipes     |
| `recipes.delete`   | Delete Recipes   |
| `batches.read`     | Read Batches     |
| `batches.write`    | Edit Batches     |
| `batches.delete`   | Delete Batches   |
| `inventory.read`   | Read Inventory   |
| `inventory.write`  | Edit Inventory   |
| `inventory.delete` | Delete Inventory |

Delete operations always require the separate Delete scopes — an Edit scope does not allow deleting.

When you generate your API-key you can select different scopes that the API-key can access, when new scopes are added you might need to generate a new key with the new scopes to allow access to the new scopes.

## Rate Limit

Currently, you can do a maximum of 500 calls per hour per API-key.

Rate limits can be changed at any time, build your integration to handle HTTP code **429 Too Many Requests**, the response will include a [`Retry-After`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Retry-After) header.

## Batches

Endpoints for managing brewing batches, readings, and the brew tracker.

## Get Batches

<mark style="color:blue;">`GET`</mark> `https://api.brewfather.app/v2/batches`

This endpoint allows you to list your batches. By default it returns batches with all statuses. Use the query parameter "status" to query for a given status.

**Requires API scope**: `batches.read`

**Default fields** (when `complete` is false): `_id`, `name`, `batchNo`, `status`, `brewer`, `brewDate`, `recipe.name`. Use `include` to request additional fields, or set `complete=true` for all fields.

#### Query Parameters

| Name                 | Type    | Description                                                                                                                                                                                 |
| -------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| include              | string  | Comma-separated list of additional fields to include when complete is false. Example "recipe.fermentation,recipe.mash" to include the fermentation and mash profile.                        |
| complete             | boolean | Valid values "True" or "False". Includes all the data in the result if True. Defaults to "**False**". If False only Name, Batch Number, Status, Brewer, Brew Date, Recipe Name is returned. |
| status               | string  | Valid values "**Planning**", "**Brewing**", "**Fermenting**", "**Conditioning**", "**Completed**", "**Archived**".                                                                          |
| limit                | number  | Amount of documents to fetch. Defaults to **10**. Max **50**.                                                                                                                               |
| start\_after         | string  | "\_id" of the last item in the previous request                                                                                                                                             |
| order\_by            | string  | The field to order by, defaults to "\_id"                                                                                                                                                   |
| order\_by\_direction | string  | Direction to order result, valid values "asc" for ascending and "desc" for descending. Defaults to "asc"                                                                                    |

#### Headers

| Name          | Type   | Description         |
| ------------- | ------ | ------------------- |
| Authorization | string | See authentication. |

{% tabs %}
{% tab title="200 " %}
Array of [Batch Object](/api/types.md#batch-object)
{% endtab %}

{% tab title="400 Bad Request" %}

```
Invalid order by direction
```

Returned when `order_by_direction` is not "asc" or "desc".
{% endtab %}

{% tab title="401 Unauthorized" %}

```
Unauthorized
```

Returned when the authorization header is missing or invalid.
{% endtab %}

{% tab title="403 Forbidden" %}

```
Forbidden
```

Returned when the API key lacks the `batches.read` scope.
{% endtab %}
{% endtabs %}

## Get Batch

<mark style="color:blue;">`GET`</mark> `https://api.brewfather.app/v2/batches/:id`

This endpoint allows you to fetch a specific batch.\
\
**Requires API scope**: `batches.read`\
\
\&#xNAN;**:id** is the **\_id** property from the batch JSON.

#### Query Parameters

| Name    | Type   | Description                                                                                                                                                                                                                |
| ------- | ------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| include | string | Array of fields to include. Example "recipe.fermentation,recipe.mash" to include the fermentation and mash profile. When omitted all fields are included. Default fields are included in addition to the requested fields. |

#### Headers

| Name          | Type   | Description         |
| ------------- | ------ | ------------------- |
| Authorization | string | See authentication. |

{% tabs %}
{% tab title="200 " %}
[Batch Object](/api/types.md#batch-object)
{% endtab %}

{% tab title="400 Bad Request" %}

```
Missing ID
```

Returned when the batch ID is not provided.
{% endtab %}

{% tab title="401 Unauthorized" %}

```
Unauthorized
```

Returned when the authorization header is missing or invalid.
{% endtab %}

{% tab title="403 Forbidden" %}

```
Forbidden
```

Returned when the API key lacks the `batches.read` scope.
{% endtab %}

{% tab title="404 Not Found" %}
Returned when the batch with the given ID does not exist.
{% endtab %}
{% endtabs %}

## Update Batch

<mark style="color:purple;">`PATCH`</mark> `https://api.brewfather.app/v2/batches/:id`

This endpoint allows you to update specific fields of a specific batch. Currently supports setting the status and measured values, please let us know what fields you would like to be able to update via the API.

**Requires API scope**: `batches.write`

#### Request Body

All fields are optional. Send only the fields you want to update. To clear a measured value, send `null`.

| Name                     | Type   | Description                                                                                                        |
| ------------------------ | ------ | ------------------------------------------------------------------------------------------------------------------ |
| status                   | string | Valid values "**Planning**", "**Brewing**", "**Fermenting**", "**Conditioning**", "**Completed**", "**Archived**". |
| measuredMashPh           | number | Mash pH. Value between **0** and **14**. Set to `null` to clear.                                                   |
| measuredBoilSize         | number | Pre-Boil Volume in Liters. Minimum value **0**. Set to `null` to clear.                                            |
| measuredFirstWortGravity | number | Pre-Sparge Gravity in SG. Value between **0.1** and **1.9** (e.g., 1.055). Set to `null` to clear.                 |
| measuredPreBoilGravity   | number | Pre-Boil Gravity in SG. Value between **0.1** and **1.9** (e.g., 1.055). Set to `null` to clear.                   |
| measuredPostBoilGravity  | number | Post-Boil Gravity in SG. Value between **0.1** and **1.9** (e.g., 1.055). Set to `null` to clear.                  |
| measuredKettleSize       | number | Post-Boil Volume in Liters. Minimum value **0**. Set to `null` to clear.                                           |
| measuredOg               | number | Original Gravity in SG. Value between **0.1** and **1.9** (e.g., 1.055). Set to `null` to clear.                   |
| measuredFermenterTopUp   | number | Fermenter Top-Up Volume in Liters. Minimum value **0**. Set to `null` to clear.                                    |
| measuredBatchSize        | number | Fermenter Volume in Liters. Minimum value **0**. Set to `null` to clear.                                           |
| measuredFg               | number | Final Gravity in SG. Value between **0.1** and **1.9** (e.g., 1.011). Set to `null` to clear.                      |
| measuredBottlingSize     | number | Final Bottling/Kegging Volume in Liters. Minimum value **0**. Set to `null` to clear.                              |
| carbonationTemp          | number | Carbonation Temperature in Celsius (°C). Value between **-50** and **100**. Set to `null` to clear.                |

#### Headers

| Name          | Type   | Description         |
| ------------- | ------ | ------------------- |
| Authorization | string | See authentication. |
| Content-Type  | string | application/json    |

{% tabs %}
{% tab title="200 Success" %}

```
Updated
```

**Note**: If no valid fields are provided, returns `"Nothing to update"`.
{% endtab %}

{% tab title="400 Bad Request" %}

```
Invalid status
```

Or

```
Invalid {field_name}
```

Or

```
Missing ID
```

Returned when validation fails or required parameters are missing.
{% endtab %}

{% tab title="401 Unauthorized" %}

```
Unauthorized
```

Returned when the authorization header is missing or invalid.
{% endtab %}

{% tab title="403 Forbidden" %}

```
Forbidden
```

Returned when the API key lacks the `batches.write` scope.
{% endtab %}

{% tab title="404 Not Found" %}
Returned when the batch with the given ID does not exist.
{% endtab %}

{% tab title="Example" %}

```bash
curl -X PATCH "https://api.brewfather.app/v2/batches/:id" \
  -H "authorization: Basic YOUR_BASE64_ENCODED_CREDENTIALS" \
  -H "Content-Type: application/json" \
  -d '{"status":"Fermenting","measuredOg":1.050,"measuredFg":1.012}'
```

**Clear a value:**

```bash
curl -X PATCH "https://api.brewfather.app/v2/batches/:id" \
  -H "authorization: Basic YOUR_BASE64_ENCODED_CREDENTIALS" \
  -H "Content-Type: application/json" \
  -d '{"measuredOg":null}'
```

{% endtab %}
{% endtabs %}

## Delete Batch

<mark style="color:red;">`DELETE`</mark> `https://api.brewfather.app/v2/batches/:id`

This endpoint allows you to delete a specific batch.

**Requires API scope**: `batches.delete`

**:id** is the **\_id** property from the batch JSON.

#### Headers

| Name          | Type   | Description         |
| ------------- | ------ | ------------------- |
| Authorization | string | See authentication. |

{% tabs %}
{% tab title="200 Success" %}

```
Deleted
```

{% endtab %}

{% tab title="400 Bad Request" %}

```
Missing ID
```

Returned when the batch ID is not provided.
{% endtab %}

{% tab title="401 Unauthorized" %}

```
Unauthorized
```

Returned when the authorization header is missing or invalid.
{% endtab %}

{% tab title="403 Forbidden" %}

```
Forbidden
```

Returned when the API key lacks the `batches.delete` scope.
{% endtab %}

{% tab title="404 Not Found" %}

```
Not Found
```

Returned when the batch with the given ID does not exist.
{% endtab %}

{% tab title="Example" %}

```bash
curl -X DELETE "https://api.brewfather.app/v2/batches/:id" \
  -H "authorization: Basic YOUR_BASE64_ENCODED_CREDENTIALS"
```

{% endtab %}
{% endtabs %}

## Get Batch Last Reading

<mark style="color:blue;">`GET`</mark> `https://api.brewfather.app/v2/batches/:id/readings/last`

This endpoint allows you to fetch the latest reading received.\
\
**Requires API scope**: `batches.read`\
\
\&#xNAN;**:id** is the **\_id** property from the batch JSON.

#### Headers

| Name          | Type   | Description         |
| ------------- | ------ | ------------------- |
| Authorization | string | See authentication. |

{% tabs %}
{% tab title="200 Example (Time in milliseconds):" %}

```
{
    "battery": 4.082377,
    "id": "GREEN",
    "rssi": -75,
    "temp": 5.1,
    "type": "iSpindel",
    "sg": 1.039,
    "time": 1572383500131,
    "angle": 32.8009
}
```

{% endtab %}

{% tab title="400 Bad Request" %}

```
Missing ID
```

Returned when the batch ID is not provided.
{% endtab %}

{% tab title="401 Unauthorized" %}

```
Unauthorized
```

Returned when the authorization header is missing or invalid.
{% endtab %}

{% tab title="403 Forbidden" %}

```
Forbidden
```

Returned when the API key lacks the `batches.read` scope.
{% endtab %}

{% tab title="404 Not Found" %}
Returned when no reading exists for the given batch.
{% endtab %}
{% endtabs %}

## Get Batch All Readings

<mark style="color:blue;">`GET`</mark> `https://api.brewfather.app/v2/batches/:id/readings`

This endpoint allows you to fetch all readings stored in a batch. If you only need the latest reading use the call above.\
\
**Requires API scope**: `batches.read`\
\
\&#xNAN;**:id** is the **\_id** property from the batch JSON.

#### Headers

| Name          | Type   | Description         |
| ------------- | ------ | ------------------- |
| Authorization | string | See authentication. |

{% tabs %}
{% tab title="200 " %}
Array of [Reading Object](/api/types.md#reading-object)
{% endtab %}

{% tab title="401 Unauthorized" %}

```
Unauthorized
```

Returned when the authorization header is missing or invalid.
{% endtab %}

{% tab title="403 Forbidden" %}

```
Forbidden
```

Returned when the API key lacks the `batches.read` scope.
{% endtab %}
{% endtabs %}

## Get Batch Brew Tracker

<mark style="color:blue;">`GET`</mark> `https://api.brewfather.app/v2/batches/:id/brewtracker`

This endpoint allows you to fetch the latest stored status of the brewtracker. Brew tracker does not get updated every second, position is calculated from start time of the stage. Brewfather triggers an update/save at certain events.\
\
**Requires API scope**: `batches.read`\
\
\&#xNAN;**:id** is the **\_id** property from the batch JSON.

#### Headers

| Name          | Type   | Description         |
| ------------- | ------ | ------------------- |
| Authorization | string | See authentication. |

{% tabs %}
{% tab title="200 " %}
[Brew Tracker Object](/api/types.md#brew-tracker-object)
{% endtab %}

{% tab title="400 Bad Request" %}

```
Missing ID
```

Returned when the batch ID is not provided.
{% endtab %}

{% tab title="401 Unauthorized" %}

```
Unauthorized
```

Returned when the authorization header is missing or invalid.
{% endtab %}

{% tab title="403 Forbidden" %}

```
Forbidden
```

Returned when the API key lacks the `batches.read` scope.
{% endtab %}

{% tab title="404 Not Found" %}
Returned when the brew tracker for the given batch does not exist.
{% endtab %}
{% endtabs %}

## Recipes

Endpoints for managing recipes, including listing, creating, updating, and deleting.

## Get Recipes

<mark style="color:blue;">`GET`</mark> `https://api.brewfather.app/v2/recipes`

This endpoint allows you to list your recipes.

**Requires API scope**: `recipes.read`

**Default fields** (when `complete` is false): `_id`, `name`, `author`, `type`, `equipment.name`, `style.name`. Use `include` to request additional fields, or set `complete=true` for all fields.

#### Query Parameters

| Name                 | Type    | Description                                                                                                                                                 |
| -------------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- |
| include              | string  | Array of additional fields to include when complete is false. Example "fermentation,mash" to include the fermentation and mash profile.                     |
| complete             | boolean | Valid values "True" or "False". Includes all the data in the result if True. Defaults to "False". If False only Name, Author, Style Name, Type is returned. |
| limit                | number  | Amount of documents to fetch. Defaults to **10**. Max **50**.                                                                                               |
| start\_after         | string  | "\_id" of the last item in the previous request                                                                                                             |
| order\_by            | string  | The field to order by, defaults to "\_id"                                                                                                                   |
| order\_by\_direction | string  | Direction to order result, valid values "asc" for ascending and "desc" for descending. Defaults to "asc"                                                    |

#### Headers

| Name          | Type   | Description         |
| ------------- | ------ | ------------------- |
| Authorization | string | See authentication. |

{% tabs %}
{% tab title="200 " %}
Array of [Recipe Object](/api/types.md#recipe-object)
{% endtab %}

{% tab title="400 Bad Request" %}

```
Invalid order by direction
```

Returned when `order_by_direction` is not "asc" or "desc".
{% endtab %}

{% tab title="401 Unauthorized" %}

```
Unauthorized
```

Returned when the authorization header is missing or invalid.
{% endtab %}

{% tab title="403 Forbidden" %}

```
Forbidden
```

Returned when the API key lacks the `recipes.read` scope.
{% endtab %}
{% endtabs %}

## Get Recipe

<mark style="color:blue;">`GET`</mark> `https://api.brewfather.app/v2/recipes/:id`

This endpoint allows you to fetch a specific recipe.\
\
**Requires API scope**: `recipes.read`\
\
\&#xNAN;**:id** is the **\_id** property from the recipe JSON.

#### Query Parameters

| Name    | Type   | Description                                                                                                                                                                                                             |
| ------- | ------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| include | string | Array of additional fields to include. Example "fermentation,mash" to include the fermentation and mash profile. When omitted all fields are included. Default fields are included in addition to the requested fields. |

#### Headers

| Name          | Type   | Description         |
| ------------- | ------ | ------------------- |
| Authorization | string | See authentication. |

{% tabs %}
{% tab title="200 " %}
[Recipe Object](/api/types.md#recipe-object)
{% endtab %}

{% tab title="400 Bad Request" %}

```
Missing ID
```

Returned when the recipe ID is not provided.
{% endtab %}

{% tab title="401 Unauthorized" %}

```
Unauthorized
```

Returned when the authorization header is missing or invalid.
{% endtab %}

{% tab title="403 Forbidden" %}

```
Forbidden
```

Returned when the API key lacks the `recipes.read` scope.
{% endtab %}

{% tab title="404 Not Found" %}
Returned when the recipe with the given ID does not exist.
{% endtab %}
{% endtabs %}

## Create Recipe

<mark style="color:green;">`POST`</mark> `https://api.brewfather.app/v2/recipes`

This endpoint allows you to create a new recipe. The request body is validated and sanitized before being stored. Server-managed fields (such as `_id`, `_uid`, timestamps, and calculated data) are set automatically and cannot be overridden.

**Requires API scope**: `recipes.write`

#### Request Body

Send a JSON object with the recipe data. At minimum, include a `name` field. All data should be in metric units (liters, kg, Celsius, SG). See [Recipe Object](/api/types.md#recipe-object) for available fields.

Root fields starting with `_`, plus `createdAt`, `updatedAt`, and `data`, are server-managed and will be ignored or overwritten if provided. Common server-managed fields include:

| Field           | Description                                      |
| --------------- | ------------------------------------------------ |
| \_id            | Generated unique identifier                      |
| \_uid           | Set to the authenticated user                    |
| \_rev           | Generated revision identifier                    |
| \_type          | Set to "recipe"                                  |
| \_init          | Initialization flag                              |
| \_public        | Community visibility (defaults to false)         |
| \_origin        | Clone source tracking                            |
| \_timestamp     | Server-managed timestamp                         |
| \_created       | Server-managed creation timestamp                |
| \_timestamp\_ms | Server-managed timestamp in milliseconds         |
| \_app\_metadata | Internal metadata                                |
| createdAt       | Server-managed creation timestamp                |
| updatedAt       | Server-managed update timestamp                  |
| \_share         | Share token                                      |
| \_ev            | Recipe engine version                            |
| \_ev\_updated   | Engine version timestamp                         |
| \_versionId     | Managed by versioning system                     |
| \_versionNumber | Managed by versioning system                     |
| data            | Calculated recipe data (generated by the system) |

#### Headers

| Name          | Type   | Description         |
| ------------- | ------ | ------------------- |
| Authorization | string | See authentication. |
| Content-Type  | string | application/json    |

{% tabs %}
{% tab title="201 Created" %}

```json
{
  "id": "generated_recipe_id"
}
```

Returns the generated `_id` of the new recipe.
{% endtab %}

{% tab title="400 Bad Request" %}

```
Missing body
```

Or a JSON array of validation errors if the recipe data fails schema validation.
{% endtab %}

{% tab title="401 Unauthorized" %}

```
Unauthorized
```

Returned when the authorization header is missing or invalid.
{% endtab %}

{% tab title="403 Forbidden" %}

```
Forbidden
```

Returned when the API key lacks the `recipes.write` scope.
{% endtab %}

{% tab title="Example" %}

```bash
curl -X POST "https://api.brewfather.app/v2/recipes" \
  -H "authorization: Basic YOUR_BASE64_ENCODED_CREDENTIALS" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "My IPA",
    "type": "All Grain",
    "boilTime": 60,
    "batchSize": 23,
    "fermentables": [
      {"name": "Pale Malt", "amount": 5, "type": "Grain", "color": 3.5}
    ],
    "hops": [
      {"name": "Citra", "amount": 30, "use": "Boil", "time": 60, "alpha": 12}
    ],
    "yeasts": [
      {"name": "US-05", "amount": 1, "type": "Ale", "form": "Dry"}
    ]
  }'
```

{% endtab %}
{% endtabs %}

## Update Recipe

<mark style="color:purple;">`PATCH`</mark> `https://api.brewfather.app/v2/recipes/:id`

This endpoint allows you to update an existing recipe. The incoming data is merged with the existing recipe, validated, and sanitized before being stored. Server-managed fields cannot be overridden.

**Requires API scope**: `recipes.write`

**:id** is the **\_id** property from the recipe JSON.

#### Request Body

Send a JSON object with the fields you want to update. The update is a shallow merge: top-level fields in the request body replace the corresponding fields in the existing recipe, while fields not included in the request body are preserved. Array fields (such as `fermentables`, `hops`, `yeasts`, `miscs`) replace the entire array.

The same server-managed fields listed in [Create Recipe](#create-recipe) are protected and will be ignored if provided.

#### Headers

| Name          | Type   | Description         |
| ------------- | ------ | ------------------- |
| Authorization | string | See authentication. |
| Content-Type  | string | application/json    |

{% tabs %}
{% tab title="200 Success" %}

```
Updated
```

{% endtab %}

{% tab title="400 Bad Request" %}

```
Missing body
```

Or

```
Missing ID
```

Or a JSON array of validation errors if the merged recipe data fails schema validation.
{% endtab %}

{% tab title="401 Unauthorized" %}

```
Unauthorized
```

Returned when the authorization header is missing or invalid.
{% endtab %}

{% tab title="403 Forbidden" %}

```
Forbidden
```

Returned when the API key lacks the `recipes.write` scope.
{% endtab %}

{% tab title="404 Not Found" %}

```
Not Found
```

Returned when the recipe with the given ID does not exist.
{% endtab %}

{% tab title="Example" %}

```bash
curl -X PATCH "https://api.brewfather.app/v2/recipes/:id" \
  -H "authorization: Basic YOUR_BASE64_ENCODED_CREDENTIALS" \
  -H "Content-Type: application/json" \
  -d '{"name": "My Updated IPA", "boilTime": 90}'
```

**Replace ingredient list:**

```bash
curl -X PATCH "https://api.brewfather.app/v2/recipes/:id" \
  -H "authorization: Basic YOUR_BASE64_ENCODED_CREDENTIALS" \
  -H "Content-Type: application/json" \
  -d '{
    "hops": [
      {"name": "Citra", "amount": 40, "use": "Boil", "time": 60, "alpha": 12},
      {"name": "Mosaic", "amount": 30, "use": "Dry Hop", "time": 3, "timeUnit": "day", "alpha": 11.5}
    ]
  }'
```

{% endtab %}
{% endtabs %}

## Delete Recipe

<mark style="color:red;">`DELETE`</mark> `https://api.brewfather.app/v2/recipes/:id`

This endpoint allows you to delete a specific recipe.

**Requires API scope**: `recipes.delete`

**:id** is the **\_id** property from the recipe JSON.

#### Headers

| Name          | Type   | Description         |
| ------------- | ------ | ------------------- |
| Authorization | string | See authentication. |

{% tabs %}
{% tab title="200 Success" %}

```
Deleted
```

{% endtab %}

{% tab title="400 Bad Request" %}

```
Missing ID
```

Returned when the recipe ID is not provided.
{% endtab %}

{% tab title="401 Unauthorized" %}

```
Unauthorized
```

Returned when the authorization header is missing or invalid.
{% endtab %}

{% tab title="403 Forbidden" %}

```
Forbidden
```

Returned when the API key lacks the `recipes.delete` scope.
{% endtab %}

{% tab title="404 Not Found" %}

```
Not Found
```

Returned when the recipe with the given ID does not exist.
{% endtab %}

{% tab title="Example" %}

```bash
curl -X DELETE "https://api.brewfather.app/v2/recipes/:id" \
  -H "authorization: Basic YOUR_BASE64_ENCODED_CREDENTIALS"
```

{% endtab %}
{% endtabs %}

## Inventory

Endpoints for managing inventory items: fermentables, hops, miscellaneous ingredients, and yeasts.

The write endpoints below use the same collection names as the read endpoints:

| Collection     | Object type                                            |
| -------------- | ------------------------------------------------------ |
| `fermentables` | [Fermentable Object](/api/types.md#fermentable-object) |
| `hops`         | [Hop Object](/api/types.md#hop-object)                 |
| `miscs`        | [Misc Object](/api/types.md#misc-object)               |
| `yeasts`       | [Yeast Object](/api/types.md#yeast-object)             |

Create and PATCH requests validate and sanitize the same object shape returned by the corresponding GET endpoints. All root-level fields starting with `_` (such as `_id`, `_rev`, `_timestamp`) plus `createdAt` are server-managed and ignored if provided in the request body; `updatedAt` and the revision/timestamp fields are always set by the server.

Inventory PATCH supports two modes:

* If the request body only contains `inventory` and/or `inventory_adjust`, it updates the stock amount only.
* If the request body contains any other field, it performs a partial update: only the fields you send are sanitized, validated, and written. Fields not included in the body are left untouched. `inventory_adjust` can be combined with other fields and is applied as a stock adjustment (it is never stored as a field on the item).

`inventory` and `inventory_adjust` accept finite numbers or numeric strings. Partial numeric strings such as `5kg` are rejected.

This differs from recipe PATCH, which merges the request body over the existing recipe and validates the whole document.

## Get Fermentables

<mark style="color:blue;">`GET`</mark> `https://api.brewfather.app/v2/inventory/fermentables`

This endpoint allows you to list your inventory items. It will only list items you have added manually or edited the default values for, or added an inventory amount on.

**Requires API scope**: `inventory.read`

**Default fields** (when `complete` is false): `_id`, `name`, `inventory`, `alpha`, `supplier`, `type`, `attenuation`, `use`. Use `include` to request additional fields, or set `complete=true` for all fields.

#### Query Parameters

| Name                 | Type    | Description                                                                                                                                      |
| -------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------ |
| inventory\_negative  | boolean | If true, only include items with inventory **< 0**. Results will be ordered by inventory amount ascending.                                       |
| include              | string  | Comma-separated list of additional fields to include when complete is false.                                                                     |
| complete             | boolean | Valid values "True" or "False". Includes all the data in the result if True. Defaults to "**False**".                                            |
| inventory\_exists    | boolean | Valid values "True" or "False". If true, only include items with inventory **> 0**. Results will be ordered by inventory amount instead of \_id. |
| limit                | number  | Amount of documents to fetch. Defaults to **10**. Max **50**.                                                                                    |
| start\_after         | string  | "\_id" of the last item in the previous request                                                                                                  |
| order\_by            | string  | The field to order by, defaults to "\_id"                                                                                                        |
| order\_by\_direction | string  | Direction to order result, valid values "asc" for ascending and "desc" for descending. Defaults to "asc"                                         |

#### Headers

| Name          | Type   | Description         |
| ------------- | ------ | ------------------- |
| Authorization | string | See authentication. |

{% tabs %}
{% tab title="200 " %}
Array of [Fermentable Object](/api/types.md#fermentable-object)
{% endtab %}

{% tab title="400 Bad Request" %}

```
Invalid order by direction
```

Returned when `order_by_direction` is not "asc" or "desc".
{% endtab %}

{% tab title="401 Unauthorized" %}

```
Unauthorized
```

Returned when the authorization header is missing or invalid.
{% endtab %}

{% tab title="403 Forbidden" %}

```
Forbidden
```

Returned when the API key lacks the `inventory.read` scope.
{% endtab %}
{% endtabs %}

## Get Fermentable

<mark style="color:blue;">`GET`</mark> `https://api.brewfather.app/v2/inventory/fermentables/:id`

This endpoint allows you to fetch a specific item.

**Requires API scope**: `inventory.read`

#### Query Parameters

| Name    | Type   | Description                                                                                                                        |
| ------- | ------ | ---------------------------------------------------------------------------------------------------------------------------------- |
| include | string | Array of fields to include. When omitted all fields are included. Default fields are included in addition to the requested fields. |

#### Headers

| Name          | Type   | Description         |
| ------------- | ------ | ------------------- |
| Authorization | string | See authentication. |

{% tabs %}
{% tab title="200 " %}
[Fermentable Object](/api/types.md#fermentable-object)
{% endtab %}

{% tab title="400 Bad Request" %}

```
Missing ID
```

Returned when the fermentable ID is not provided.
{% endtab %}

{% tab title="401 Unauthorized" %}

```
Unauthorized
```

Returned when the authorization header is missing or invalid.
{% endtab %}

{% tab title="403 Forbidden" %}

```
Forbidden
```

Returned when the API key lacks the `inventory.read` scope.
{% endtab %}

{% tab title="404 Not Found" %}
Returned when the fermentable with the given ID does not exist.
{% endtab %}
{% endtabs %}

## Create Fermentable

<mark style="color:green;">`POST`</mark> `https://api.brewfather.app/v2/inventory/fermentables`

This endpoint allows you to create a new fermentable inventory item.

**Requires API scope**: `inventory.write`

#### Request Body

Send a JSON object with the fermentable data. See [Fermentable Object](/api/types.md#fermentable-object) for available fields.

The server-managed inventory fields listed in [Inventory](#inventory) are ignored if provided.

#### Headers

| Name          | Type   | Description         |
| ------------- | ------ | ------------------- |
| Authorization | string | See authentication. |
| Content-Type  | string | application/json    |

{% tabs %}
{% tab title="201 Created" %}

```json
{
  "id": "generated_inventory_id"
}
```

Returns the generated `_id` of the new inventory item.
{% endtab %}

{% tab title="400 Bad Request" %}

```
Missing body
```

Or a JSON array of validation errors if the fermentable data fails schema validation.
{% endtab %}

{% tab title="401 Unauthorized" %}

```
Unauthorized
```

Returned when the authorization header is missing or invalid.
{% endtab %}

{% tab title="403 Forbidden" %}

```
Forbidden
```

Returned when the API key lacks the `inventory.write` scope.
{% endtab %}

{% tab title="Example" %}

```bash
curl -X POST "https://api.brewfather.app/v2/inventory/fermentables" \
  -H "authorization: Basic YOUR_BASE64_ENCODED_CREDENTIALS" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Pilsner Malt",
    "type": "Grain",
    "color": 1.7,
    "yield": 80.5,
    "inventory": 25000,
    "supplier": "Weyermann"
  }'
```

{% endtab %}
{% endtabs %}

## Update Fermentable

<mark style="color:purple;">`PATCH`</mark> `https://api.brewfather.app/v2/inventory/fermentables/:id`

This endpoint allows you to update a specific fermentable. If the request body only contains `inventory` and/or `inventory_adjust`, it updates the inventory amount only. If the body contains any other field, it performs a partial update of just the provided fields, validated against the fermentable schema.

**Requires API scope**: `inventory.write`

#### Request Body

| Name              | Type           | Description                                                                                                                                                                                                                             |
| ----------------- | -------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| inventory         | number\|string | In inventory-only mode, set the inventory amount to the given value. Takes precedence over `inventory_adjust`.                                                                                                                          |
| inventory\_adjust | number\|string | In inventory-only mode, adjust the existing inventory amount by adding (positive) or subtracting (negative) the given amount.                                                                                                           |
| any other field   | mixed          | If the body contains any field other than `inventory` or `inventory_adjust`, the endpoint switches to partial update mode: the provided fields are validated as fermentable fields and written, other fields on the item are untouched. |

**Note**: If both `inventory` and `inventory_adjust` are provided, `inventory` takes precedence and `inventory_adjust` is ignored. `inventory_adjust` is applied as an adjustment to the stored stock amount and is never stored as a field on the item. `inventory` and `inventory_adjust` must be finite numeric values or numeric strings; partial numeric strings return `400`. In partial update mode, the protected fields listed in [Inventory](#inventory) are ignored if provided.

#### Headers

| Name          | Type   | Description         |
| ------------- | ------ | ------------------- |
| Authorization | string | See authentication. |
| Content-Type  | string | application/json    |

{% tabs %}
{% tab title="200 Success" %}

```
Updated
```

**Note**: If no valid fields are provided, returns `"Nothing to update"`.
{% endtab %}

{% tab title="400 Bad Request" %}

```
Missing ID
```

Returned when the `:id` parameter is missing. Or

```
Invalid inventory
```

Returned in inventory-only mode when the provided `inventory` value cannot be parsed as a number. Or

```
Invalid inventory_adjust
```

Returned in either mode when the provided `inventory_adjust` value cannot be parsed as a number. Or a JSON array of validation errors if a partial update fails schema validation (including an unparseable `inventory` value in partial update mode).
{% endtab %}

{% tab title="401 Unauthorized" %}

```
Unauthorized
```

Returned when the authorization header is missing or invalid.
{% endtab %}

{% tab title="403 Forbidden" %}

```
Forbidden
```

Returned when the API key lacks the `inventory.write` scope.
{% endtab %}

{% tab title="404 Not Found" %}

```
Not Found
```

Returned when the inventory item with the specified ID doesn't exist.
{% endtab %}

{% tab title="Example - Set Absolute Amount" %}

```bash
curl -X PATCH "https://api.brewfather.app/v2/inventory/fermentables/:id" \
  -H "authorization: Basic YOUR_BASE64_ENCODED_CREDENTIALS" \
  -H "Content-Type: application/json" \
  -d '{"inventory":500}'
```

{% endtab %}

{% tab title="Example - Adjust Amount" %}

```bash
curl -X PATCH "https://api.brewfather.app/v2/inventory/fermentables/:id" \
  -H "authorization: Basic YOUR_BASE64_ENCODED_CREDENTIALS" \
  -H "Content-Type: application/json" \
  -d '{"inventory_adjust":-100}'
```

Subtracts 100 grams from current inventory.
{% endtab %}

{% tab title="Example - Update Item Fields" %}

```bash
curl -X PATCH "https://api.brewfather.app/v2/inventory/fermentables/:id" \
  -H "authorization: Basic YOUR_BASE64_ENCODED_CREDENTIALS" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Pilsner Malt",
    "type": "Grain",
    "color": 1.8,
    "yield": 81,
    "supplier": "BestMalz",
    "inventory": 24000
  }'
```

{% endtab %}
{% endtabs %}

## Delete Fermentable

<mark style="color:red;">`DELETE`</mark> `https://api.brewfather.app/v2/inventory/fermentables/:id`

This endpoint allows you to delete a specific fermentable inventory item.

**Requires API scope**: `inventory.delete`

#### Headers

| Name          | Type   | Description         |
| ------------- | ------ | ------------------- |
| Authorization | string | See authentication. |

{% tabs %}
{% tab title="200 Success" %}

```
Deleted
```

{% endtab %}

{% tab title="400 Bad Request" %}

```
Missing ID
```

Returned when the fermentable ID is not provided.
{% endtab %}

{% tab title="401 Unauthorized" %}

```
Unauthorized
```

Returned when the authorization header is missing or invalid.
{% endtab %}

{% tab title="403 Forbidden" %}

```
Forbidden
```

Returned when the API key lacks the `inventory.delete` scope.
{% endtab %}

{% tab title="404 Not Found" %}

```
Not Found
```

Returned when the fermentable with the given ID does not exist.
{% endtab %}

{% tab title="Example" %}

```bash
curl -X DELETE "https://api.brewfather.app/v2/inventory/fermentables/:id" \
  -H "authorization: Basic YOUR_BASE64_ENCODED_CREDENTIALS"
```

{% endtab %}
{% endtabs %}

## Get Hops

<mark style="color:blue;">`GET`</mark> `https://api.brewfather.app/v2/inventory/hops`

This endpoint allows you to list your inventory items. It will only list items you have added manually or edited the default values for, or added an inventory amount on.

**Requires API scope**: `inventory.read`

**Default fields** (when `complete` is false): `_id`, `name`, `inventory`, `alpha`, `supplier`, `type`, `attenuation`, `use`. Use `include` to request additional fields, or set `complete=true` for all fields.

#### Query Parameters

| Name                 | Type    | Description                                                                                                                                      |
| -------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------ |
| inventory\_negative  | boolean | If true, only include items with inventory **< 0**. Results will be ordered by inventory amount ascending.                                       |
| include              | string  | Comma-separated list of additional fields to include when complete is false.                                                                     |
| complete             | boolean | Valid values "True" or "False". Includes all the data in the result if True. Defaults to "**False**".                                            |
| inventory\_exists    | boolean | Valid values "True" or "False". If true, only include items with inventory **> 0**. Results will be ordered by inventory amount instead of \_id. |
| limit                | number  | Amount of documents to fetch. Defaults to **10**. Max **50**.                                                                                    |
| start\_after         | string  | "\_id" of the last item in the previous request                                                                                                  |
| order\_by            | string  | The field to order by, defaults to "\_id"                                                                                                        |
| order\_by\_direction | string  | Direction to order result, valid values "asc" for ascending and "desc" for descending. Defaults to "asc"                                         |

#### Headers

| Name          | Type   | Description         |
| ------------- | ------ | ------------------- |
| Authorization | string | See authentication. |

{% tabs %}
{% tab title="200 " %}
Array of [Hop Object](/api/types.md#hop-object)
{% endtab %}

{% tab title="400 Bad Request" %}

```
Invalid order by direction
```

Returned when `order_by_direction` is not "asc" or "desc".
{% endtab %}

{% tab title="401 Unauthorized" %}

```
Unauthorized
```

Returned when the authorization header is missing or invalid.
{% endtab %}

{% tab title="403 Forbidden" %}

```
Forbidden
```

Returned when the API key lacks the `inventory.read` scope.
{% endtab %}
{% endtabs %}

## Get Hop

<mark style="color:blue;">`GET`</mark> `https://api.brewfather.app/v2/inventory/hops/:id`

This endpoint allows you to fetch a specific item.

**Requires API scope**: `inventory.read`

#### Query Parameters

| Name    | Type   | Description                                                                                                                        |
| ------- | ------ | ---------------------------------------------------------------------------------------------------------------------------------- |
| include | string | Array of fields to include. When omitted all fields are included. Default fields are included in addition to the requested fields. |

#### Headers

| Name          | Type   | Description         |
| ------------- | ------ | ------------------- |
| Authorization | string | See authentication. |

{% tabs %}
{% tab title="200 " %}
[Hop Object](/api/types.md#hop-object)
{% endtab %}

{% tab title="400 Bad Request" %}

```
Missing ID
```

Returned when the hop ID is not provided.
{% endtab %}

{% tab title="401 Unauthorized" %}

```
Unauthorized
```

Returned when the authorization header is missing or invalid.
{% endtab %}

{% tab title="403 Forbidden" %}

```
Forbidden
```

Returned when the API key lacks the `inventory.read` scope.
{% endtab %}

{% tab title="404 Not Found" %}
Returned when the hop with the given ID does not exist.
{% endtab %}
{% endtabs %}

## Create Hop

<mark style="color:green;">`POST`</mark> `https://api.brewfather.app/v2/inventory/hops`

This endpoint allows you to create a new hop inventory item.

**Requires API scope**: `inventory.write`

#### Request Body

Send a JSON object with the hop data. See [Hop Object](/api/types.md#hop-object) for available fields.

The server-managed inventory fields listed in [Inventory](#inventory) are ignored if provided.

#### Headers

| Name          | Type   | Description         |
| ------------- | ------ | ------------------- |
| Authorization | string | See authentication. |
| Content-Type  | string | application/json    |

{% tabs %}
{% tab title="201 Created" %}

```json
{
  "id": "generated_inventory_id"
}
```

Returns the generated `_id` of the new inventory item.
{% endtab %}

{% tab title="400 Bad Request" %}

```
Missing body
```

Or a JSON array of validation errors if the hop data fails schema validation.
{% endtab %}

{% tab title="401 Unauthorized" %}

```
Unauthorized
```

Returned when the authorization header is missing or invalid.
{% endtab %}

{% tab title="403 Forbidden" %}

```
Forbidden
```

Returned when the API key lacks the `inventory.write` scope.
{% endtab %}

{% tab title="Example" %}

```bash
curl -X POST "https://api.brewfather.app/v2/inventory/hops" \
  -H "authorization: Basic YOUR_BASE64_ENCODED_CREDENTIALS" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Cascade",
    "alpha": 5.5,
    "use": "Boil",
    "inventory": 500,
    "origin": "US"
  }'
```

{% endtab %}
{% endtabs %}

## Update Hop

<mark style="color:purple;">`PATCH`</mark> `https://api.brewfather.app/v2/inventory/hops/:id`

This endpoint allows you to update a specific hop. If the request body only contains `inventory` and/or `inventory_adjust`, it updates the inventory amount only. If the body contains any other field, it performs a partial update of just the provided fields, validated against the hop schema.

**Requires API scope**: `inventory.write`

#### Request Body

| Name              | Type           | Description                                                                                                                                                                                                                     |
| ----------------- | -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| inventory         | number\|string | In inventory-only mode, set the inventory amount to the given value. Takes precedence over `inventory_adjust`.                                                                                                                  |
| inventory\_adjust | number\|string | In inventory-only mode, adjust the existing inventory amount by adding (positive) or subtracting (negative) the given amount.                                                                                                   |
| any other field   | mixed          | If the body contains any field other than `inventory` or `inventory_adjust`, the endpoint switches to partial update mode: the provided fields are validated as hop fields and written, other fields on the item are untouched. |

**Note**: If both `inventory` and `inventory_adjust` are provided, `inventory` takes precedence and `inventory_adjust` is ignored. `inventory_adjust` is applied as an adjustment to the stored stock amount and is never stored as a field on the item. `inventory` and `inventory_adjust` must be finite numeric values or numeric strings; partial numeric strings return `400`. In partial update mode, the protected fields listed in [Inventory](#inventory) are ignored if provided.

#### Headers

| Name          | Type   | Description         |
| ------------- | ------ | ------------------- |
| Authorization | string | See authentication. |
| Content-Type  | string | application/json    |

{% tabs %}
{% tab title="200 Success" %}

```
Updated
```

**Note**: If no valid fields are provided, returns `"Nothing to update"`.
{% endtab %}

{% tab title="400 Bad Request" %}

```
Missing ID
```

Returned when the `:id` parameter is missing. Or

```
Invalid inventory
```

Returned in inventory-only mode when the provided `inventory` value cannot be parsed as a number. Or

```
Invalid inventory_adjust
```

Returned in either mode when the provided `inventory_adjust` value cannot be parsed as a number. Or a JSON array of validation errors if a partial update fails schema validation (including an unparseable `inventory` value in partial update mode).
{% endtab %}

{% tab title="401 Unauthorized" %}

```
Unauthorized
```

Returned when the authorization header is missing or invalid.
{% endtab %}

{% tab title="403 Forbidden" %}

```
Forbidden
```

Returned when the API key lacks the `inventory.write` scope.
{% endtab %}

{% tab title="404 Not Found" %}

```
Not Found
```

Returned when the inventory item with the specified ID doesn't exist.
{% endtab %}

{% tab title="Example - Set Absolute Amount" %}

```bash
curl -X PATCH "https://api.brewfather.app/v2/inventory/hops/:id" \
  -H "authorization: Basic YOUR_BASE64_ENCODED_CREDENTIALS" \
  -H "Content-Type: application/json" \
  -d '{"inventory":100}'
```

{% endtab %}

{% tab title="Example - Adjust Amount" %}

```bash
curl -X PATCH "https://api.brewfather.app/v2/inventory/hops/:id" \
  -H "authorization: Basic YOUR_BASE64_ENCODED_CREDENTIALS" \
  -H "Content-Type: application/json" \
  -d '{"inventory_adjust":-10}'
```

Subtracts 10 grams from current inventory.
{% endtab %}

{% tab title="Example - Update Item Fields" %}

```bash
curl -X PATCH "https://api.brewfather.app/v2/inventory/hops/:id" \
  -H "authorization: Basic YOUR_BASE64_ENCODED_CREDENTIALS" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Cascade",
    "alpha": 6.1,
    "use": "Dry Hop",
    "time": 3,
    "timeUnit": "day",
    "inventory": 450
  }'
```

{% endtab %}
{% endtabs %}

## Delete Hop

<mark style="color:red;">`DELETE`</mark> `https://api.brewfather.app/v2/inventory/hops/:id`

This endpoint allows you to delete a specific hop inventory item.

**Requires API scope**: `inventory.delete`

#### Headers

| Name          | Type   | Description         |
| ------------- | ------ | ------------------- |
| Authorization | string | See authentication. |

{% tabs %}
{% tab title="200 Success" %}

```
Deleted
```

{% endtab %}

{% tab title="400 Bad Request" %}

```
Missing ID
```

Returned when the hop ID is not provided.
{% endtab %}

{% tab title="401 Unauthorized" %}

```
Unauthorized
```

Returned when the authorization header is missing or invalid.
{% endtab %}

{% tab title="403 Forbidden" %}

```
Forbidden
```

Returned when the API key lacks the `inventory.delete` scope.
{% endtab %}

{% tab title="404 Not Found" %}

```
Not Found
```

Returned when the hop with the given ID does not exist.
{% endtab %}

{% tab title="Example" %}

```bash
curl -X DELETE "https://api.brewfather.app/v2/inventory/hops/:id" \
  -H "authorization: Basic YOUR_BASE64_ENCODED_CREDENTIALS"
```

{% endtab %}
{% endtabs %}

## Get Miscs

<mark style="color:blue;">`GET`</mark> `https://api.brewfather.app/v2/inventory/miscs`

This endpoint allows you to list your inventory items. It will only list items you have added manually or edited the default values for, or added an inventory amount on.

**Requires API scope**: `inventory.read`

**Default fields** (when `complete` is false): `_id`, `name`, `inventory`, `alpha`, `supplier`, `type`, `attenuation`, `use`. Use `include` to request additional fields, or set `complete=true` for all fields.

#### Query Parameters

| Name                 | Type    | Description                                                                                                                                      |
| -------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------ |
| inventory\_negative  | boolean | If true, only include items with inventory **< 0**. Results will be ordered by inventory amount ascending.                                       |
| include              | string  | Comma-separated list of additional fields to include when complete is false.                                                                     |
| complete             | boolean | Valid values "True" or "False". Includes all the data in the result if True. Defaults to "**False**".                                            |
| inventory\_exists    | boolean | Valid values "True" or "False". If true, only include items with inventory **> 0**. Results will be ordered by inventory amount instead of \_id. |
| limit                | number  | Amount of documents to fetch. Defaults to **10**. Max **50**.                                                                                    |
| start\_after         | string  | "\_id" of the last item in the previous request                                                                                                  |
| order\_by            | string  | The field to order by, defaults to "\_id"                                                                                                        |
| order\_by\_direction | string  | Direction to order result, valid values "asc" for ascending and "desc" for descending. Defaults to "asc"                                         |

#### Headers

| Name          | Type   | Description         |
| ------------- | ------ | ------------------- |
| Authorization | string | See authentication. |

{% tabs %}
{% tab title="200 " %}
Array of [Misc Object](/api/types.md#misc-object)
{% endtab %}

{% tab title="400 Bad Request" %}

```
Invalid order by direction
```

Returned when `order_by_direction` is not "asc" or "desc".
{% endtab %}

{% tab title="401 Unauthorized" %}

```
Unauthorized
```

Returned when the authorization header is missing or invalid.
{% endtab %}

{% tab title="403 Forbidden" %}

```
Forbidden
```

Returned when the API key lacks the `inventory.read` scope.
{% endtab %}
{% endtabs %}

## Get Misc

<mark style="color:blue;">`GET`</mark> `https://api.brewfather.app/v2/inventory/miscs/:id`

This endpoint allows you to fetch a specific item.

**Requires API scope**: `inventory.read`

#### Query Parameters

| Name    | Type   | Description                                                                                                                        |
| ------- | ------ | ---------------------------------------------------------------------------------------------------------------------------------- |
| include | string | Array of fields to include. When omitted all fields are included. Default fields are included in addition to the requested fields. |

#### Headers

| Name          | Type   | Description         |
| ------------- | ------ | ------------------- |
| Authorization | string | See authentication. |

{% tabs %}
{% tab title="200 " %}
[Misc Object](/api/types.md#misc-object)
{% endtab %}

{% tab title="400 Bad Request" %}

```
Missing ID
```

Returned when the misc ID is not provided.
{% endtab %}

{% tab title="401 Unauthorized" %}

```
Unauthorized
```

Returned when the authorization header is missing or invalid.
{% endtab %}

{% tab title="403 Forbidden" %}

```
Forbidden
```

Returned when the API key lacks the `inventory.read` scope.
{% endtab %}

{% tab title="404 Not Found" %}
Returned when the misc item with the given ID does not exist.
{% endtab %}
{% endtabs %}

## Create Misc

<mark style="color:green;">`POST`</mark> `https://api.brewfather.app/v2/inventory/miscs`

This endpoint allows you to create a new misc inventory item.

**Requires API scope**: `inventory.write`

#### Request Body

Send a JSON object with the misc ingredient data. See [Misc Object](/api/types.md#misc-object) for available fields.

The server-managed inventory fields listed in [Inventory](#inventory) are ignored if provided.

#### Headers

| Name          | Type   | Description         |
| ------------- | ------ | ------------------- |
| Authorization | string | See authentication. |
| Content-Type  | string | application/json    |

{% tabs %}
{% tab title="201 Created" %}

```json
{
  "id": "generated_inventory_id"
}
```

Returns the generated `_id` of the new inventory item.
{% endtab %}

{% tab title="400 Bad Request" %}

```
Missing body
```

Or a JSON array of validation errors if the misc data fails schema validation.
{% endtab %}

{% tab title="401 Unauthorized" %}

```
Unauthorized
```

Returned when the authorization header is missing or invalid.
{% endtab %}

{% tab title="403 Forbidden" %}

```
Forbidden
```

Returned when the API key lacks the `inventory.write` scope.
{% endtab %}

{% tab title="Example" %}

```bash
curl -X POST "https://api.brewfather.app/v2/inventory/miscs" \
  -H "authorization: Basic YOUR_BASE64_ENCODED_CREDENTIALS" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Irish Moss",
    "type": "Fining",
    "use": "Boil",
    "time": 15,
    "inventory": 100
  }'
```

{% endtab %}
{% endtabs %}

## Update Misc

<mark style="color:purple;">`PATCH`</mark> `https://api.brewfather.app/v2/inventory/miscs/:id`

This endpoint allows you to update a specific misc ingredient. If the request body only contains `inventory` and/or `inventory_adjust`, it updates the inventory amount only. If the body contains any other field, it performs a partial update of just the provided fields, validated against the misc schema.

**Requires API scope**: `inventory.write`

#### Request Body

| Name              | Type           | Description                                                                                                                                                                                                                      |
| ----------------- | -------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| inventory         | number\|string | In inventory-only mode, set the inventory amount to the given value. Takes precedence over `inventory_adjust`.                                                                                                                   |
| inventory\_adjust | number\|string | In inventory-only mode, adjust the existing inventory amount by adding (positive) or subtracting (negative) the given amount.                                                                                                    |
| any other field   | mixed          | If the body contains any field other than `inventory` or `inventory_adjust`, the endpoint switches to partial update mode: the provided fields are validated as misc fields and written, other fields on the item are untouched. |

**Note**: If both `inventory` and `inventory_adjust` are provided, `inventory` takes precedence and `inventory_adjust` is ignored. `inventory_adjust` is applied as an adjustment to the stored stock amount and is never stored as a field on the item. `inventory` and `inventory_adjust` must be finite numeric values or numeric strings; partial numeric strings return `400`. In partial update mode, the protected fields listed in [Inventory](#inventory) are ignored if provided.

#### Headers

| Name          | Type   | Description         |
| ------------- | ------ | ------------------- |
| Authorization | string | See authentication. |
| Content-Type  | string | application/json    |

{% tabs %}
{% tab title="200 Success" %}

```
Updated
```

**Note**: If no valid fields are provided, returns `"Nothing to update"`.
{% endtab %}

{% tab title="400 Bad Request" %}

```
Missing ID
```

Returned when the `:id` parameter is missing. Or

```
Invalid inventory
```

Returned in inventory-only mode when the provided `inventory` value cannot be parsed as a number. Or

```
Invalid inventory_adjust
```

Returned in either mode when the provided `inventory_adjust` value cannot be parsed as a number. Or a JSON array of validation errors if a partial update fails schema validation (including an unparseable `inventory` value in partial update mode).
{% endtab %}

{% tab title="401 Unauthorized" %}

```
Unauthorized
```

Returned when the authorization header is missing or invalid.
{% endtab %}

{% tab title="403 Forbidden" %}

```
Forbidden
```

Returned when the API key lacks the `inventory.write` scope.
{% endtab %}

{% tab title="404 Not Found" %}

```
Not Found
```

Returned when the inventory item with the specified ID doesn't exist.
{% endtab %}

{% tab title="Example - Set Absolute Amount" %}

```bash
curl -X PATCH "https://api.brewfather.app/v2/inventory/miscs/:id" \
  -H "authorization: Basic YOUR_BASE64_ENCODED_CREDENTIALS" \
  -H "Content-Type: application/json" \
  -d '{"inventory":50}'
```

{% endtab %}

{% tab title="Example - Adjust Amount" %}

```bash
curl -X PATCH "https://api.brewfather.app/v2/inventory/miscs/:id" \
  -H "authorization: Basic YOUR_BASE64_ENCODED_CREDENTIALS" \
  -H "Content-Type: application/json" \
  -d '{"inventory_adjust":10}'
```

Adds 10 grams/ml to current inventory.
{% endtab %}

{% tab title="Example - Update Item Fields" %}

```bash
curl -X PATCH "https://api.brewfather.app/v2/inventory/miscs/:id" \
  -H "authorization: Basic YOUR_BASE64_ENCODED_CREDENTIALS" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Irish Moss",
    "type": "Fining",
    "use": "Boil",
    "time": 10,
    "inventory": 110,
    "notes": "Granulated"
  }'
```

{% endtab %}
{% endtabs %}

## Delete Misc

<mark style="color:red;">`DELETE`</mark> `https://api.brewfather.app/v2/inventory/miscs/:id`

This endpoint allows you to delete a specific misc inventory item.

**Requires API scope**: `inventory.delete`

#### Headers

| Name          | Type   | Description         |
| ------------- | ------ | ------------------- |
| Authorization | string | See authentication. |

{% tabs %}
{% tab title="200 Success" %}

```
Deleted
```

{% endtab %}

{% tab title="400 Bad Request" %}

```
Missing ID
```

Returned when the misc ID is not provided.
{% endtab %}

{% tab title="401 Unauthorized" %}

```
Unauthorized
```

Returned when the authorization header is missing or invalid.
{% endtab %}

{% tab title="403 Forbidden" %}

```
Forbidden
```

Returned when the API key lacks the `inventory.delete` scope.
{% endtab %}

{% tab title="404 Not Found" %}

```
Not Found
```

Returned when the misc item with the given ID does not exist.
{% endtab %}

{% tab title="Example" %}

```bash
curl -X DELETE "https://api.brewfather.app/v2/inventory/miscs/:id" \
  -H "authorization: Basic YOUR_BASE64_ENCODED_CREDENTIALS"
```

{% endtab %}
{% endtabs %}

## Get Yeasts

<mark style="color:blue;">`GET`</mark> `https://api.brewfather.app/v2/inventory/yeasts`

This endpoint allows you to list your inventory items. It will only list items you have added manually or edited the default values for, or added an inventory amount on.

**Requires API scope**: `inventory.read`

**Default fields** (when `complete` is false): `_id`, `name`, `inventory`, `alpha`, `supplier`, `type`, `attenuation`, `use`. Use `include` to request additional fields, or set `complete=true` for all fields.

#### Query Parameters

| Name                 | Type    | Description                                                                                                                                      |
| -------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------ |
| inventory\_negative  | boolean | If true, only include items with inventory **< 0**. Results will be ordered by inventory amount ascending.                                       |
| include              | string  | Comma-separated list of additional fields to include when complete is false.                                                                     |
| complete             | boolean | Valid values "True" or "False". Includes all the data in the result if True. Defaults to "**False**".                                            |
| inventory\_exists    | boolean | Valid values "True" or "False". If true, only include items with inventory **> 0**. Results will be ordered by inventory amount instead of \_id. |
| limit                | number  | Amount of documents to fetch. Defaults to **10**. Max **50**.                                                                                    |
| start\_after         | string  | "\_id" of the last item in the previous request                                                                                                  |
| order\_by            | string  | The field to order by, defaults to "\_id"                                                                                                        |
| order\_by\_direction | string  | Direction to order result, valid values "asc" for ascending and "desc" for descending. Defaults to "asc"                                         |

#### Headers

| Name          | Type   | Description         |
| ------------- | ------ | ------------------- |
| Authorization | string | See authentication. |

{% tabs %}
{% tab title="200 " %}
Array of [Yeast Object](/api/types.md#yeast-object)
{% endtab %}

{% tab title="400 Bad Request" %}

```
Invalid order by direction
```

Returned when `order_by_direction` is not "asc" or "desc".
{% endtab %}

{% tab title="401 Unauthorized" %}

```
Unauthorized
```

Returned when the authorization header is missing or invalid.
{% endtab %}

{% tab title="403 Forbidden" %}

```
Forbidden
```

Returned when the API key lacks the `inventory.read` scope.
{% endtab %}
{% endtabs %}

## Get Yeast

<mark style="color:blue;">`GET`</mark> `https://api.brewfather.app/v2/inventory/yeasts/:id`

This endpoint allows you to fetch a specific item.

**Requires API scope**: `inventory.read`

#### Query Parameters

| Name    | Type   | Description                                                                                                                        |
| ------- | ------ | ---------------------------------------------------------------------------------------------------------------------------------- |
| include | string | Array of fields to include. When omitted all fields are included. Default fields are included in addition to the requested fields. |

#### Headers

| Name          | Type   | Description         |
| ------------- | ------ | ------------------- |
| Authorization | string | See authentication. |

{% tabs %}
{% tab title="200 " %}
[Yeast Object](/api/types.md#yeast-object)
{% endtab %}

{% tab title="400 Bad Request" %}

```
Missing ID
```

Returned when the yeast ID is not provided.
{% endtab %}

{% tab title="401 Unauthorized" %}

```
Unauthorized
```

Returned when the authorization header is missing or invalid.
{% endtab %}

{% tab title="403 Forbidden" %}

```
Forbidden
```

Returned when the API key lacks the `inventory.read` scope.
{% endtab %}

{% tab title="404 Not Found" %}
Returned when the yeast with the given ID does not exist.
{% endtab %}
{% endtabs %}

## Create Yeast

<mark style="color:green;">`POST`</mark> `https://api.brewfather.app/v2/inventory/yeasts`

This endpoint allows you to create a new yeast inventory item.

**Requires API scope**: `inventory.write`

#### Request Body

Send a JSON object with the yeast data. See [Yeast Object](/api/types.md#yeast-object) for available fields.

The server-managed inventory fields listed in [Inventory](#inventory) are ignored if provided.

#### Headers

| Name          | Type   | Description         |
| ------------- | ------ | ------------------- |
| Authorization | string | See authentication. |
| Content-Type  | string | application/json    |

{% tabs %}
{% tab title="201 Created" %}

```json
{
  "id": "generated_inventory_id"
}
```

Returns the generated `_id` of the new inventory item.
{% endtab %}

{% tab title="400 Bad Request" %}

```
Missing body
```

Or a JSON array of validation errors if the yeast data fails schema validation.
{% endtab %}

{% tab title="401 Unauthorized" %}

```
Unauthorized
```

Returned when the authorization header is missing or invalid.
{% endtab %}

{% tab title="403 Forbidden" %}

```
Forbidden
```

Returned when the API key lacks the `inventory.write` scope.
{% endtab %}

{% tab title="Example" %}

```bash
curl -X POST "https://api.brewfather.app/v2/inventory/yeasts" \
  -H "authorization: Basic YOUR_BASE64_ENCODED_CREDENTIALS" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "US-05",
    "type": "Ale",
    "form": "Dry",
    "inventory": 5,
    "laboratory": "Fermentis"
  }'
```

{% endtab %}
{% endtabs %}

## Update Yeast

<mark style="color:purple;">`PATCH`</mark> `https://api.brewfather.app/v2/inventory/yeasts/:id`

This endpoint allows you to update a specific yeast. If the request body only contains `inventory` and/or `inventory_adjust`, it updates the inventory amount only. If the body contains any other field, it performs a partial update of just the provided fields, validated against the yeast schema.

**Requires API scope**: `inventory.write`

#### Request Body

| Name              | Type           | Description                                                                                                                                                                                                                       |
| ----------------- | -------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| inventory         | number\|string | In inventory-only mode, set the inventory amount to the given value. Takes precedence over `inventory_adjust`.                                                                                                                    |
| inventory\_adjust | number\|string | In inventory-only mode, adjust the existing inventory amount by adding (positive) or subtracting (negative) the given amount.                                                                                                     |
| any other field   | mixed          | If the body contains any field other than `inventory` or `inventory_adjust`, the endpoint switches to partial update mode: the provided fields are validated as yeast fields and written, other fields on the item are untouched. |

**Note**: If both `inventory` and `inventory_adjust` are provided, `inventory` takes precedence and `inventory_adjust` is ignored. `inventory_adjust` is applied as an adjustment to the stored stock amount and is never stored as a field on the item. `inventory` and `inventory_adjust` must be finite numeric values or numeric strings; partial numeric strings return `400`. In partial update mode, the protected fields listed in [Inventory](#inventory) are ignored if provided.

#### Headers

| Name          | Type   | Description         |
| ------------- | ------ | ------------------- |
| Authorization | string | See authentication. |
| Content-Type  | string | application/json    |

{% tabs %}
{% tab title="200 Success" %}

```
Updated
```

**Note**: If no valid fields are provided, returns `"Nothing to update"`.
{% endtab %}

{% tab title="400 Bad Request" %}

```
Missing ID
```

Returned when the `:id` parameter is missing. Or

```
Invalid inventory
```

Returned in inventory-only mode when the provided `inventory` value cannot be parsed as a number. Or

```
Invalid inventory_adjust
```

Returned in either mode when the provided `inventory_adjust` value cannot be parsed as a number. Or a JSON array of validation errors if a partial update fails schema validation (including an unparseable `inventory` value in partial update mode).
{% endtab %}

{% tab title="401 Unauthorized" %}

```
Unauthorized
```

Returned when the authorization header is missing or invalid.
{% endtab %}

{% tab title="403 Forbidden" %}

```
Forbidden
```

Returned when the API key lacks the `inventory.write` scope.
{% endtab %}

{% tab title="404 Not Found" %}

```
Not Found
```

Returned when the inventory item with the specified ID doesn't exist.
{% endtab %}

{% tab title="Example - Set Absolute Amount" %}

```bash
curl -X PATCH "https://api.brewfather.app/v2/inventory/yeasts/:id" \
  -H "authorization: Basic YOUR_BASE64_ENCODED_CREDENTIALS" \
  -H "Content-Type: application/json" \
  -d '{"inventory":5}'
```

{% endtab %}

{% tab title="Example - Adjust Amount" %}

```bash
curl -X PATCH "https://api.brewfather.app/v2/inventory/yeasts/:id" \
  -H "authorization: Basic YOUR_BASE64_ENCODED_CREDENTIALS" \
  -H "Content-Type: application/json" \
  -d '{"inventory_adjust":-1}'
```

Subtracts 1 unit from current inventory.
{% endtab %}

{% tab title="Example - Update Item Fields" %}

```bash
curl -X PATCH "https://api.brewfather.app/v2/inventory/yeasts/:id" \
  -H "authorization: Basic YOUR_BASE64_ENCODED_CREDENTIALS" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "US-05",
    "type": "Ale",
    "form": "Dry",
    "attenuation": 78,
    "inventory": 4
  }'
```

{% endtab %}
{% endtabs %}

## Delete Yeast

<mark style="color:red;">`DELETE`</mark> `https://api.brewfather.app/v2/inventory/yeasts/:id`

This endpoint allows you to delete a specific yeast inventory item.

**Requires API scope**: `inventory.delete`

#### Headers

| Name          | Type   | Description         |
| ------------- | ------ | ------------------- |
| Authorization | string | See authentication. |

{% tabs %}
{% tab title="200 Success" %}

```
Deleted
```

{% endtab %}

{% tab title="400 Bad Request" %}

```
Missing ID
```

Returned when the yeast ID is not provided.
{% endtab %}

{% tab title="401 Unauthorized" %}

```
Unauthorized
```

Returned when the authorization header is missing or invalid.
{% endtab %}

{% tab title="403 Forbidden" %}

```
Forbidden
```

Returned when the API key lacks the `inventory.delete` scope.
{% endtab %}

{% tab title="404 Not Found" %}

```
Not Found
```

Returned when the yeast with the given ID does not exist.
{% endtab %}

{% tab title="Example" %}

```bash
curl -X DELETE "https://api.brewfather.app/v2/inventory/yeasts/:id" \
  -H "authorization: Basic YOUR_BASE64_ENCODED_CREDENTIALS"
```

{% endtab %}
{% endtabs %}

***

## Reference

* [Response Types](/api/types.md) — Complete field documentation for all API response objects
* [Enum Reference](/api/enums.md) — Valid values for all enum fields

## Related docs

* [API Types](/api/types.md)
* [API Enums](/api/enums.md)
* [Connected Apps](/connected-apps.md)
* [Webhooks](/webhooks.md)


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.brewfather.app/api.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
