API Documentation
Build integrations with SHELF using our RESTful JSON API. Manage inventory, shopping lists, and storage locations programmatically.
Base URL
https://myshelf.life/api/v1
Authentifizierung
Alle API-Anfragen müssen einen gültigen API-Schlüssel im Authorization-Header enthalten.
Authorization: Bearer YOUR_API_KEY
Berechtigungsstufen
- Nur lesen: Kann Daten abrufen (GET-Anfragen)
- Lesen & Schreiben: Kann Daten abrufen und ändern (alle Anfragen)
Fehlerantworten
Bei Fehlern gibt die API einen JSON-Body mit Fehlerdetails zurück.
{"error": "Invalid or disabled API key", "code": "unauthorized"}
{"error": "This API key does not have write permissions", "code": "forbidden"}
{"error": "Resource not found", "code": "not_found"}
{"error": "Name can't be blank", "code": "unprocessable_entity", "details": {"name": ["can't be blank"]}}
Endpunkte
Lese-Endpunkte
/api/v1/locations
Gibt alle aktiven Lagerorte deines Haushalts zurück.
Beispielantwort
{
"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"
}
]
}
/api/v1/inventory
Gibt alle Lagerorte mit ihren Artikeln zurück.
Beispielantwort
{
"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"
}
]
}
]
}
/api/v1/shopping_list
Gibt die aktive Einkaufsliste mit allen nicht abgehakten Artikeln zurück.
Beispielantwort
{
"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"
}
]
}
}
/api/v1/household_actions
Gibt alle Haushaltsaktionen (aktive und inaktive) mit ihrem aktuellen claimed_today-Status zurück.
Beispielantwort
{
"household_actions": [
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "Take out trash",
"emoji": "🗑️",
"points": 10,
"active": true,
"category": "Trash & Recycling",
"category_emoji": "🗑️",
"position": 0,
"claimed_today": true,
"created_at": "2026-01-15T10:30:00Z"
}
]
}
/api/v1/bonus_points
Gibt die Bonuspunkte des API-Nutzers für die aktuelle Woche und insgesamt zurück, sowie das Haushalts-Ranking (ein Eintrag pro Haushaltsmitglied, sortiert nach Wochenpunkten). Rückgängig gemachte Aktivitäten werden nicht gezählt.
Beispielantwort
{
"week": {
"start": "2026-05-04",
"end": "2026-05-10",
"user": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "Hendrik",
"score": 35
},
"standings": [
{ "user_id": "550e8400-e29b-41d4-a716-446655440000", "name": "Hendrik", "score": 35, "rank": 1 },
{ "user_id": "660e8400-e29b-41d4-a716-446655440000", "name": "Partner", "score": 20, "rank": 2 }
]
},
"all_time": {
"user": { "score": 1250, "activity_count": 217 }
}
}
/api/v1/leaderboard
Gibt das vollständige Haushalts-Ranking zurück. Anders als bonus_points (nur Bonus-Aktionen) zählt hier der komplette Wochen-Score — hinzugefügte Artikel, Einkaufsliste, Races und Bonus-Aktionen — dieselbe Wertung wie bei den Championships. Mit period=all_time wird die Gesamtwertung (Championship-Siege) zurückgegeben. Gleichstände teilen sich einen Rang.
Query Parameters
| Field | Type | Description |
|---|---|---|
| period | string | Optional. "weekly" (Standard) für die aktuelle Woche oder "all_time" für die Championship-Siege. |
Beispielantwort
{
"period": "weekly",
"week": { "start": "2026-05-04", "end": "2026-05-10" },
"user": {
"user_id": "550e8400-e29b-41d4-a716-446655440000",
"name": "Hendrik",
"score": 42,
"rank": 1,
"breakdown": { "add_item": 25, "cross_off_shopping": 6, "custom_actions": 11 }
},
"standings": [
{ "user_id": "550e8400-e29b-41d4-a716-446655440000", "name": "Hendrik", "score": 42, "rank": 1, "breakdown": { } },
{ "user_id": "660e8400-e29b-41d4-a716-446655440000", "name": "Partner", "score": 42, "rank": 1, "breakdown": { } }
]
}
/api/v1/bonus_points/activities
Gibt die letzten Bonus-Aktionen des Haushalts zurück (custom_action-Aktivitäten). Neueste zuerst.
Query Parameters
| Field | Type | Description |
|---|---|---|
| limit | integer | Optional. Maximale Anzahl zurückgegebener Aktivitäten (Standard 50, Maximum 200). |
| since | iso8601 | Optional. ISO8601-Zeitstempel; gibt nur Aktivitäten zurück, die ab dieser Zeit erstellt wurden. |
| user_id | uuid | Optional. UUID eines Haushaltsmitglieds zum Filtern. |
| include_undone | boolean | Optional. "false" angeben, um rückgängig gemachte Aktivitäten auszuschließen (Standard: true). |
Beispielantwort
{
"activities": [
{
"id": "770e8400-e29b-41d4-a716-446655440000",
"household_action": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "Coffee in bed",
"emoji": "☕",
"points": 10
},
"user": { "id": "660e8400-e29b-41d4-a716-446655440000", "name": "Hendrik" },
"points": 10,
"created_at": "2026-05-09T08:30:00Z",
"undone_at": null
}
],
"count": 1
}
Schreib-Endpunkte
Erforderliche Berechtigung: Lesen & Schreiben
/api/v1/inventory/items
Fügt einen neuen Artikel zu deinem Vorrat hinzu. Kategorie und Icon werden automatisch basierend auf dem Artikelnamen zugewiesen.
Anfrage-Body
| Field | Type | Description |
|---|---|---|
| name | string | Erforderlich. Der Artikelname. |
| location_id | uuid | Erforderlich. UUID des Lagerorts. |
| quantity | number | Optional. Numerische Menge (Standard: 1). |
| unit | string | Optional. Maßeinheit. |
| expires_on | date | Optional. Ablaufdatum (JJJJ-MM-TT). |
| notes | string | Optional. Zusätzliche Notizen. |
Beispielanfrage
curl -X POST "https://myshelf.life/api/v1/inventory/items" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"item": {"name": "Eggs", "location_id": "LOCATION_UUID", "quantity": 6, "expires_on": "2026-03-15"}}'
Beispielantwort (201)
{
"item": {
"id": "550e8400-e29b-41d4-a716-446655440010",
"name": "Eggs",
"quantity": "6.0",
"unit": null,
"category": "dairy",
"icon": "🥚",
"expires_on": "2026-03-15",
"status": "ok",
"notes": null,
"added_by": "Max",
"created_at": "2026-02-15T10:30:00Z"
}
}
/api/v1/shopping_list/items
Fügt einen neuen Artikel zur Einkaufsliste hinzu. Die Kategorie wird automatisch zugewiesen.
Anfrage-Body
| Field | Type | Description |
|---|---|---|
| name | string | Erforderlich. Der Artikelname. |
| quantity | number | Optional. Numerische Menge. |
| unit | string | Optional. Maßeinheit (z.B. "Liter", "g", "Stück"). |
Beispielanfrage
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"}}'
Beispielantwort (201)
{
"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"
}
}
/api/v1/shopping_list/items/:id
Aktualisiert Menge und/oder Einheit eines aktiven Einkaufslisten-Artikels. Abgehakte Artikel können nicht aktualisiert werden (422).
Beispielanfrage
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"}}'
Beispielantwort (200)
{
"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"
}
}
/api/v1/inventory/items/:id
Aktualisiert einen aktiven Vorratsartikel. Du kannst Menge, Einheit, Lagerort oder Ablaufdatum ändern. Archivierte Artikel geben 404 zurück.
Anfrage-Body
| Field | Type | Description |
|---|---|---|
| quantity | number | Neuer Mengenwert |
| unit | string | Neue Maßeinheit |
| location_id | uuid | UUID des neuen Lagerorts |
| expires_on | date | Neues Ablaufdatum (JJJJ-MM-TT) |
Beispielanfrage
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", "location_id": "LOCATION_UUID", "expires_on": "2026-03-15"}}'
Beispielantwort (200)
{
"item": {
"id": "550e8400-e29b-41d4-a716-446655440003",
"name": "Milch",
"quantity": "500.0",
"unit": "ml",
"category": "dairy",
"icon": "🥛",
"expires_on": "2026-03-15",
"status": "ok",
"notes": "Bio",
"added_by": "Max",
"created_at": "2026-01-15T10:30:00Z"
}
}
/api/v1/household_actions/:id/log
Protokolliert eine Haushaltsaktion, um Punkte zu verdienen. Gibt 422 zurück, wenn die Aktion inaktiv ist.
Beispielanfrage
curl -X POST "https://myshelf.life/api/v1/household_actions/ACTION_ID/log" \
-H "Authorization: Bearer YOUR_API_KEY"
Beispielantwort (201)
{
"household_action": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "Take out trash",
"emoji": "🗑️",
"points": 10,
"active": true,
"category": "Trash & Recycling",
"category_emoji": "🗑️",
"position": 0,
"claimed_today": true,
"created_at": "2026-01-15T10:30:00Z"
},
"activity": {
"id": "660e8400-e29b-41d4-a716-446655440000",
"activity_type": "custom_action",
"points": 10,
"created_at": "2026-03-07T14:00:00Z"
}
}
/api/v1/household_actions/:id/toggle
Schaltet eine Haushaltsaktion zwischen aktiv und inaktiv um.
Beispielanfrage
curl -X PATCH "https://myshelf.life/api/v1/household_actions/ACTION_ID/toggle" \
-H "Authorization: Bearer YOUR_API_KEY"
Beispielantwort (200)
{
"household_action": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "Take out trash",
"emoji": "🗑️",
"points": 10,
"active": false,
"category": "Trash & Recycling",
"category_emoji": "🗑️",
"position": 0,
"claimed_today": false,
"created_at": "2026-01-15T10:30:00Z"
}
}
/api/v1/activities/:id/undo
Markiert eine zuvor protokollierte Bonus-Aktivität als rückgängig gemacht und entfernt deren Punkte aus den Summen. Jedes Haushaltsmitglied kann jede Haushaltsaktivität rückgängig machen. Gibt 422 zurück, wenn die Aktivität bereits rückgängig gemacht wurde, 404, wenn die Aktivität nicht zu deinem Haushalt gehört oder keine Bonus-Aktion ist.
Beispielanfrage
curl -X POST "https://myshelf.life/api/v1/activities/ACTIVITY_ID/undo" \
-H "Authorization: Bearer YOUR_API_KEY"
Beispielantwort (200)
{
"activity": {
"id": "770e8400-e29b-41d4-a716-446655440000",
"household_action": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "Coffee in bed",
"emoji": "☕",
"points": 10
},
"user": { "id": "660e8400-e29b-41d4-a716-446655440000", "name": "Hendrik" },
"points": 10,
"created_at": "2026-05-09T08:30:00Z",
"undone_at": "2026-05-09T08:32:14Z"
}
}
/api/v1/activities/:id/redo
Stellt eine zuvor rückgängig gemachte Bonus-Aktivität wieder her und fügt deren Punkte wieder hinzu. Gibt 422 zurück, wenn die Aktivität nicht rückgängig gemacht wurde.
Beispielanfrage
curl -X POST "https://myshelf.life/api/v1/activities/ACTIVITY_ID/redo" \
-H "Authorization: Bearer YOUR_API_KEY"
Beispielantwort (200)
{
"activity": {
"id": "770e8400-e29b-41d4-a716-446655440000",
"household_action": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "Coffee in bed",
"emoji": "☕",
"points": 10
},
"user": { "id": "660e8400-e29b-41d4-a716-446655440000", "name": "Hendrik" },
"points": 10,
"created_at": "2026-05-09T08:30:00Z",
"undone_at": null
}
}
/api/v1/inventory/items/:id
Archiviert (soft-delete) einen Vorratsartikel. Bereits archivierte Artikel geben 404 zurück. Der Artikel kann über die Web-Oberfläche aus dem Archiv wiederhergestellt werden.
Beispielanfrage
curl -X DELETE "https://myshelf.life/api/v1/inventory/items/ITEM_ID" \
-H "Authorization: Bearer YOUR_API_KEY"
Beispielantwort (200)
{
"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"
}
}
Meal Plans
Plan meals per day (recipe = title, description, ingredients). Each ingredient may reference an inventory item via item_id, or 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 cooked deducts the consumed quantities (and archives an item once it reaches zero). Ideal for agent control.
/api/v1/meal_plans
List meal plans in a date range. Each ingredient is resolved against current inventory (in-stock status + matched item). Requires a Read key.
Query Parameters
| Field | Type | Description |
|---|---|---|
| from | date | Start date (YYYY-MM-DD). Defaults to today. Pass an earlier date to browse history. |
| to | date | End date (YYYY-MM-DD). Defaults to from + 6 days. |
Beispielantwort
{
"from": "2026-06-04",
"to": "2026-06-10",
"meal_plans": [
{
"id": "…",
"date": "2026-06-04",
"title": "Pasta Pomodoro",
"description": "Schnelle Tomaten-Pasta",
"cooked_at": null,
"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 }
]
}
]
}
/api/v1/meal_plans
Create a meal plan for a day. Requires a Read & Write key.
Anfrage-Body
| Field | Type | Description |
|---|---|---|
| date | string | Day the meal is planned for, YYYY-MM-DD (required) |
| title | string | Recipe title (required) |
| description | string | Short description (optional) |
| ingredients | array | [{ name, quantity, unit, item_id }] — item_id optional; if omitted it is matched to inventory by name on save (optional) |
Beispielanfrage
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"}]}}'
Example Response (201 Created)
{
"meal_plan": {
"id": "…",
"date": "2026-06-04",
"title": "Pasta Pomodoro",
"description": null,
"cooked_at": null,
"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": "Tomaten", "quantity": 1, "unit": "Dose", "item_id": null, "in_stock": false }
]
}
}
/api/v1/meal_plans/:id
Edit the recipe or move it to another day. Send only the fields you want to change. Requires a Read & Write key.
Anfrage-Body
| Field | Type | Description |
|---|---|---|
| date | string | Move to this day, YYYY-MM-DD (optional) |
| title | string | New recipe title (optional) |
| description | string | New description (optional) |
| ingredients | array | Replace the ingredient list, same shape as POST (optional) |
Beispielanfrage
curl -X PATCH "https://myshelf.life/api/v1/meal_plans/MEAL_PLAN_ID" \
-H "Authorization: Bearer YOUR_API_KEY" -H "Content-Type: application/json" \
-d '{"meal_plan": {"date": "2026-06-05"}}'
Example Response (200 OK)
{ "meal_plan": { "id": "…", "date": "2026-06-05", "title": "Pasta Pomodoro", "cooked_at": null, "ingredients": [ … ] } }
/api/v1/meal_plans/:id/cook
Mark the plan cooked and deduct the consumed inventory: each matched item is decremented by the recipe amount and archived once it reaches zero. Returns a consumed log. Requires a Read & Write key.
Beispielanfrage
curl -X POST "https://myshelf.life/api/v1/meal_plans/MEAL_PLAN_ID/cook" \
-H "Authorization: Bearer YOUR_API_KEY"
Example Response (200 OK)
{
"meal_plan": { "id": "…", "cooked_at": "2026-06-04T18:30:00Z", "…": "…" },
"consumed": [
{ "item_id": "…", "name": "Pasta", "action": "decremented", "used": 500, "remaining": "1500.0" },
{ "item_id": "…", "name": "Tomaten", "action": "archived", "used": 1, "remaining": 0 }
]
}
/api/v1/meal_plans/:id
Soft-delete (archive) a meal plan. Requires a Read & Write key.
Beispielanfrage
curl -X DELETE "https://myshelf.life/api/v1/meal_plans/MEAL_PLAN_ID" \
-H "Authorization: Bearer YOUR_API_KEY"
Example Response (200 OK)
{ "meal_plan": { "id": "…", "date": "2026-06-04", "title": "Pasta Pomodoro", "…": "…" } }
Beispiel mit curl
Hier ist ein Beispiel, wie du die API mit curl aufrufen kannst:
# 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"}}'