---
title: "Shopping List"
description: "Read and manage the active profile's shopping list — recipes on it and which items are checked off."
---

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

# Shopping List

There's one shopping list per profile — not multiple named lists. See
[Shopping List](/features/shopping-list) for how ingredients from
different recipes get merged together. Every endpoint here operates on
the active profile's own list.

## `GET /api/shopping-list`

Returns the active profile's shopping list.

**Response:** `{ "shoppingList": { "recipeIds": string[], "checkedOff": string[] } }`.
`checkedOff` holds each checked-off ingredient's merged line key (its
name, lowercased), not a per-recipe ingredient ID.

## `DELETE /api/shopping-list`

Clears the list — empties `recipeIds` and `checkedOff` both.

**Response:** `{ "shoppingList": { "recipeIds": [], "checkedOff": [] } }`.

## `POST /api/shopping-list/recipes`

Adds a recipe to the list. Idempotent — adding the same recipe twice
doesn't duplicate it.

**Request body:** `{ "recipeId": string }`

**Response:** `{ "shoppingList": ShoppingList }`

## `DELETE /api/shopping-list/recipes/:recipeId`

Removes a recipe from the list.

**Response:** `{ "shoppingList": ShoppingList }`

## `PATCH /api/shopping-list/checked`

Replaces the full set of checked-off line keys — the client always sends
the complete list, not a single toggle.

**Request body:** `{ "checkedOff": string[] }`

**Response:** `{ "shoppingList": ShoppingList }`, or `400` if
`checkedOff` isn't an array of strings.

Source: https://docs.recipery.dev/api/shopping-list//index.md
