# SHELF API Reference

Build integrations with SHELF using our RESTful JSON API. Manage inventory, shopping lists, and storage locations programmatically.

**Base URL:** `https://myshelf.life/api/v1`

---

## Authentication

All API requests require a Bearer token in the Authorization header:

```
Authorization: Bearer YOUR_API_KEY
```

API keys can be created in the SHELF app under Settings > API Keys.

### Permission Levels

- **Read**: Can view locations, inventory, and shopping list data
- **Read & Write**: Full access including creating, updating, and deleting items

---

## Error Responses

The API returns standard HTTP status codes with JSON error bodies:

### 401 Unauthorized

```json
{"error": "Invalid or disabled API key", "code": "unauthorized"}
```

### 403 Forbidden

```json
{"error": "This API key does not have write permissions", "code": "forbidden"}
```

### 404 Not Found

```json
{"error": "Resource not found", "code": "not_found"}
```

### 422 Unprocessable Entity

```json
{"error": "Name can't be blank", "code": "unprocessable_entity", "details": {"name": ["can't be blank"]}}
```

---

## Endpoints

### Read Endpoints

These endpoints require a key with **Read** permission or higher.

#### GET /api/v1/locations

List all storage locations in your household.

**Example Request:**

```bash
curl -H "Authorization: Bearer YOUR_API_KEY" \
     https://myshelf.life/api/v1/locations
```

**Example Response:**

```json
{
  "locations": [
    {
      "id": "550e8400-e29b-41d4-a716-446655440000",
      "name": "Kühlschrank",
      "icon": "🧊",
      "location_type": "standard",
      "is_default": true,
      "items_count": 15,
      "created_at": "2024-01-15T10:30:00Z"
    }
  ]
}
```

#### GET /api/v1/inventory

Get full inventory grouped by location, including all items with expiry dates and status.

**Example Request:**

```bash
curl -H "Authorization: Bearer YOUR_API_KEY" \
     https://myshelf.life/api/v1/inventory
```

**Example Response:**

```json
{
  "locations": [
    {
      "id": "550e8400-e29b-41d4-a716-446655440000",
      "name": "Kühlschrank",
      "icon": "🧊",
      "location_type": "standard",
      "items": [
        {
          "id": "550e8400-e29b-41d4-a716-446655440003",
          "name": "Milch",
          "quantity": 2.0,
          "unit": "Liter",
          "category": "dairy",
          "icon": "🥛",
          "expires_on": "2026-03-01",
          "status": "ok",
          "notes": "Bio",
          "added_by": "Max",
          "created_at": "2026-01-15T10:30:00Z"
        }
      ]
    }
  ]
}
```

#### GET /api/v1/shopping_list

Get the active shopping list with all items.

**Example Request:**

```bash
curl -H "Authorization: Bearer YOUR_API_KEY" \
     https://myshelf.life/api/v1/shopping_list
```

**Example Response:**

```json
{
  "shopping_list": {
    "id": "550e8400-e29b-41d4-a716-446655440001",
    "name": "Einkaufsliste",
    "active_count": 5,
    "items": [
      {
        "id": "550e8400-e29b-41d4-a716-446655440002",
        "name": "Milch",
        "quantity": 2.0,
        "unit": "Liter",
        "category": "dairy",
        "added_by": "Max",
        "created_at": "2024-01-20T14:00:00Z"
      }
    ]
  }
}
```

---

### Write Endpoints

These endpoints require a key with **Read & Write** permission.

#### POST /api/v1/shopping_list/items

Add a new item to the shopping list.

**Request Body:**

| Field    | Type   | Description                      |
|----------|--------|----------------------------------|
| name     | string | Item name (required)             |
| quantity | number | Amount (optional, default: 1)    |
| unit     | string | Unit of measurement (optional)   |

**Example Request:**

```bash
curl -X POST "https://myshelf.life/api/v1/shopping_list/items" \
     -H "Authorization: Bearer YOUR_API_KEY" \
     -H "Content-Type: application/json" \
     -d '{"item": {"name": "Milch", "quantity": 2, "unit": "Liter"}}'
```

**Example Response (201 Created):**

```json
{
  "item": {
    "id": "550e8400-e29b-41d4-a716-446655440010",
    "name": "Milch",
    "quantity": "2.0",
    "unit": "Liter",
    "category": "dairy",
    "added_by": "Max",
    "created_at": "2026-02-15T10:30:00Z"
  }
}
```

#### PATCH /api/v1/shopping_list/items/:id

Update a shopping list item.

**Example Request:**

```bash
curl -X PATCH "https://myshelf.life/api/v1/shopping_list/items/ITEM_ID" \
     -H "Authorization: Bearer YOUR_API_KEY" \
     -H "Content-Type: application/json" \
     -d '{"item": {"quantity": 500, "unit": "ml"}}'
```

**Example Response (200 OK):**

```json
{
  "item": {
    "id": "550e8400-e29b-41d4-a716-446655440002",
    "name": "Milch",
    "quantity": "500.0",
    "unit": "ml",
    "category": "dairy",
    "added_by": "Max",
    "created_at": "2026-01-20T14:00:00Z"
  }
}
```

#### PATCH /api/v1/inventory/items/:id

Update an inventory item (quantity, unit, notes, expiry date, etc.).

**Example Request:**

```bash
curl -X PATCH "https://myshelf.life/api/v1/inventory/items/ITEM_ID" \
     -H "Authorization: Bearer YOUR_API_KEY" \
     -H "Content-Type: application/json" \
     -d '{"item": {"quantity": 500, "unit": "ml"}}'
```

**Example Response (200 OK):**

```json
{
  "item": {
    "id": "550e8400-e29b-41d4-a716-446655440003",
    "name": "Milch",
    "quantity": "500.0",
    "unit": "ml",
    "category": "dairy",
    "icon": "🥛",
    "expires_on": "2026-03-01",
    "status": "ok",
    "notes": "Bio",
    "added_by": "Max",
    "created_at": "2026-01-15T10:30:00Z"
  }
}
```

#### DELETE /api/v1/inventory/items/:id

Archive an inventory item (moves it to the archive, does not permanently delete).

**Example Request:**

```bash
curl -X DELETE "https://myshelf.life/api/v1/inventory/items/ITEM_ID" \
     -H "Authorization: Bearer YOUR_API_KEY"
```

**Example Response (200 OK):**

```json
{
  "item": {
    "id": "550e8400-e29b-41d4-a716-446655440003",
    "name": "Milch",
    "quantity": "2.0",
    "unit": "Liter",
    "category": "dairy",
    "icon": "🥛",
    "expires_on": "2026-03-01",
    "status": "ok",
    "notes": "Bio",
    "added_by": "Max",
    "created_at": "2026-01-15T10:30:00Z"
  }
}
```

---

## Quick Start Examples

```bash
# Read shopping list
curl -H "Authorization: Bearer YOUR_API_KEY" \
     https://myshelf.life/api/v1/shopping_list

# Add item to shopping list
curl -X POST "https://myshelf.life/api/v1/shopping_list/items" \
     -H "Authorization: Bearer YOUR_API_KEY" \
     -H "Content-Type: application/json" \
     -d '{"item": {"name": "Milch", "quantity": 2, "unit": "Liter"}}'
```

---

## Meal Plans

Plan meals per day. Each meal plan is a recipe (title, description, ingredients)
scheduled for a date — freely movable between days. Each ingredient may reference
an inventory item it consumes (via `item_id`); if omitted it is matched by name
against your active inventory, so responses show **what a meal would consume and
whether it is in stock**. Marking a plan as *cooked* deducts the consumed
quantities (and archives an item once it reaches zero).

### GET /api/v1/meal_plans

Requires **Read**. Meal plans in a date range (defaults to the current week).
Query params: `from`, `to` (YYYY-MM-DD). Ingredients are resolved against current inventory.

```bash
curl -H "Authorization: Bearer YOUR_API_KEY" \
     "https://myshelf.life/api/v1/meal_plans?from=2026-06-02&to=2026-06-08"
```

```json
{
  "from": "2026-06-02", "to": "2026-06-08",
  "meal_plans": [{
    "id": "…", "date": "2026-06-04", "title": "Pasta Pomodoro",
    "in_stock_count": 1, "total_ingredients": 2,
    "ingredients": [
      {"name": "Pasta", "quantity": 500, "unit": "g", "item_id": "…", "in_stock": true, "available_quantity": "2.0", "location": "Vorratskammer"},
      {"name": "Basilikum", "quantity": 1, "unit": null, "item_id": null, "in_stock": false}
    ]
  }]
}
```

### POST /api/v1/meal_plans

Requires **Read & Write**. Body: `meal_plan` with `date` (required), `title`
(required), `description`, and `ingredients` (`[{ name, quantity, unit, item_id }]`).

```bash
curl -X POST "https://myshelf.life/api/v1/meal_plans" \
     -H "Authorization: Bearer YOUR_API_KEY" -H "Content-Type: application/json" \
     -d '{"meal_plan": {"date": "2026-06-04", "title": "Pasta Pomodoro", "ingredients": [{"name": "Pasta", "quantity": 500, "unit": "g"}, {"name": "Tomaten", "quantity": 1, "unit": "Dose"}]}}'
```

### PATCH /api/v1/meal_plans/:id

Requires **Read & Write**. Edit the recipe or move it to another `date` (same body shape as POST).

### DELETE /api/v1/meal_plans/:id

Requires **Read & Write**. Soft-deletes (archives) the meal plan.

### POST /api/v1/meal_plans/:id/cook

Requires **Read & Write**. Marks the plan cooked and deducts consumed inventory
(decrement by the recipe amount; archive at zero). Returns a `consumed` log.

```bash
curl -X POST "https://myshelf.life/api/v1/meal_plans/MEAL_PLAN_ID/cook" \
     -H "Authorization: Bearer YOUR_API_KEY"
```
