- get_lists(scope): API scope parameter now used server-side; accepts circle
metaId ("family/XXXX") or circle name; returns circle_id field per list
- create_list(circle_id): new optional param; passes as API scope param
- delete_list: derives circle from list metaId and passes scope for
secondary-circle lists
- Added _circle_id_from_list_id() helper (taskList/FAMNUM_LISTNUM -> family/FAMNUM)
- SPEC.md: documented scope param for taskgettasklists, taskcreatelist, taskdeletelist
- Verified: familyId/circleId/id params ignored by API, only scope works
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
20 KiB
Family Wall API – Spezifikation
Erarbeitet durch Browser-Traffic-Analyse und React-Fiber-Analyse (April 2026). Es gibt keine offizielle API-Dokumentation.
Base URL
https://api.familywall.com/api
Authentifizierung
Login
POST https://api.familywall.com/api/log2in Content-Type: application/x-www-form-urlencoded
Request-Parameter:
| Parameter | Wert |
|---|---|
identifier |
E-Mail-Adresse |
password |
Passwort |
type |
"email" (verifiziert) |
Response (Erfolg):
{ "r": { "r": <SessionObject> } }
Response (Fehler):
{ "ex": { "ex": <ErrorObject> } }
{ "un": { "un": <ErrorObject> } }
Der Server setzt nach erfolgreichem Login ein Session-Cookie:
Set-Cookie: JSESSIONID=<session-id>
Folgecalls (nach Login)
| Cookie | JSESSIONID=<session-id> |
| Header | Tokencsrf: <session-id> (identisch zur JSESSIONID) |
| Content-Type | application/x-www-form-urlencoded |
Logout
POST https://api.familywall.com/api/log2out
Keine Parameter. Session wird serverseitig invalidiert.
Session-Strategie
Kein Session-Caching. Jeder MCP-Tool-Call führt folgende Sequenz aus:
POST /api/log2in → Session-ID
POST /api/<endpoint> → Nutzdaten (ggf. mehrere Calls in einer Session)
POST /api/log2out → Session invalidieren
Credentials (E-Mail + Passwort) werden einmalig via mcp-familywall setup
im OS Keyring gespeichert (Keys: email, password).
Fehlerbehandlung
Silent-Fail Warnung
Die API gibt Fehler manchmal NICHT auf Top-Level zurück, sondern eingebettet:
{"a00": {"un": {"un": {"message": "missing value in: taskId"}}}}
fw_client.py prüft beide Ebenen (a00.un.un und Top-Level ex/un)
und wirft FamilyWallError. Nie eine Response als Erfolg werten ohne
beide Fehlerebenen zu prüfen.
Sentinel-Wert $empty
Das FiZ-Server-Framework nutzt $empty als Sentinel-String um optionale
Felder zu löschen. Alle anderen Werte ("", null, "null", "0",
"-1", "remove", "clear", Epoch-Timestamps) werden vom Server mit
"is not a valid Date" abgelehnt.
Aktuell genutzt für:
dueDate=$empty→ löscht Fälligkeitsdatum intaskupdate2
Gefunden durch: React-Fiber-Analyse des nativen datetime-local-Inputs –
nach Klick auf "Löschen" im Custom-Datepicker wird der Input-Wert auf
"$empty" gesetzt, was beim Speichern an die API gesendet wird.
Bekannte Endpoints
famlistfamily – Kreise + Mitglieder abrufen
POST https://api.familywall.com/api/famlistfamily
Body-Parameter: keine
Response-Struktur:
a00.r.r[] → Kreise
.metaId → Kreis-ID (z.B. "family/23431854")
.name → Kreis-Name
.members[] → Mitglieder des Kreises
.accountId → numerische User-ID
.firstName → Anzeigename (bevorzugen)
.name → E-Mail als Fallback
.role → Familienrolle (Parent/Child/Unknown)
.right → Berechtigung (SuperAdmin etc.)
.color → Profilfarbe (#RRGGBB)
.medias[0].pictureUrl → Avatar-URL
.identifiers[type=Email].value → E-Mail-Adresse
accgetallfamily – Listen, Tasks, Kategorien abrufen
POST https://api.familywall.com/api/accgetallfamily
Body-Parameter:
| Parameter | Wert |
|---|---|
a01call |
"taskcategorysync" |
a02call |
"tasksync" |
Response-Struktur:
a00.r.r[] → Kategorien (taskcategorysync)
.metaId → Kategorie-ID
.name → Kategoriename (Systembezeichnung)
.taskListType → SHOPPING_LIST oder TODOS
.sortingIndexByTaskList → Sortierreihenfolge pro Liste
.rights.canDelete → "true" = custom, null = System
.locale → Sprachcode (de/en/fr/...), fehlt bei custom
a02.r.r.updatedCreated[] → Tasks (tasksync)
.metaId → Task-ID
.text → Aufgabentext
.description → optionale Beschreibung
.taskListId → Listen-ID
.complete → "true" / "false" (String!)
.taskCategoryId → Kategorie-ID (optional)
.dueDate → Fälligkeitsdatum (ISO 8601, optional)
.assignee[] → Liste von Member-IDs (optional)
.assigneeIds[] → alternativ zu assignee[]
wallget – Wall-Aktivitäten abrufen
POST https://api.familywall.com/api/wallget
Response-Struktur:
a00.r.r[]
.metaId → Post-ID (z.B. "wall/23431854_31119189")
.type → STATUS, FAMILY_CREATED, etc.
.text → Post-Text
.modifDate → Timestamp (ISO 8601)
.creator.accountId → Author-ID
.moodMap → {"<accountId>": ["STAR"]} für Likes
.moodStarShortcut → true wenn geliked
.comments[] → Kommentare
taskcreate2 – Task erstellen
POST https://api.familywall.com/api/taskcreate2
Body-Parameter:
| Parameter | Pflicht | Wert |
|---|---|---|
taskListId |
ja | Listen-metaId |
text |
ja | Aufgabentext |
description |
nein | Beschreibung |
taskCategoryId |
nein | Kategorie-metaId (vollständig, z.B. taskCategory/23431854_200) |
dueDate |
nein | ISO 8601 (z.B. 2026-04-30T18:00:00) |
assignee |
nein | Member-accountId, mehrfach sendbar für mehrere Zuweisungen |
Response:
a00.r.r → vollständiges Task-Objekt
.metaId → neue Task-ID
taskupdate2 – Task aktualisieren
POST https://api.familywall.com/api/taskupdate2
Body-Parameter:
| Parameter | Pflicht | Wert |
|---|---|---|
metaId |
ja | Task-metaId |
text |
nein | neuer Titel |
description |
nein | neue Beschreibung |
taskCategoryId |
nein | neue Kategorie-metaId |
dueDate |
nein | ISO 8601 oder $empty zum Löschen |
assignee |
nein | Member-accountId (mehrfach sendbar), "" zum Entfernen aller |
taskListId |
nein | neue Listen-metaId (verschiebt Task) |
Hinweis: taskListId ist NICHT Pflicht beim Update.
Response:
a00.r.r → vollständiges Task-Objekt
taskmark – Task abhaken/wiedereröffnen
POST https://api.familywall.com/api/taskmark
Body-Parameter:
| Parameter | Wert |
|---|---|
taskId |
Task-metaId ⚠️ nicht metaId! |
complete |
"true" oder "false" (String!) |
Response:
a00.r.r → Task-Objekt mit lastAction: "MARK_COMPLETED"
metadelete – Task löschen
POST https://api.familywall.com/api/metadelete
Body-Parameter:
| Parameter | Wert |
|---|---|
id |
Task-metaId ⚠️ nicht metaId! |
Response:
a00.r.r → "true" (String)
wallmood – Post liken
POST https://api.familywall.com/api/wallmood
Body-Parameter:
| Parameter | Wert |
|---|---|
wall_message_id |
Post-metaId ⚠️ nicht wallId oder id! |
moodType |
"STAR" für Like |
Bekannte Einschränkungen:
- Unlike: Endpoint/Parameter unbekannt (Service Worker verschlüsselt Request-Body)
- Self-Like: API antwortet 200, macht aber serverseitig nichts
moodType="NONE"und andere Werte haben keine Wirkung
Response:
a00.r.r → Wall-Objekt mit moodMap, refAction: "MOOD_STAR"
taskcategoryput – Kategorie erstellen/aktualisieren
POST https://api.familywall.com/api/taskcategoryput
Body-Parameter:
| Parameter | Pflicht | Wert |
|---|---|---|
name |
ja | Kategoriename |
emoji |
nein | Unicode-Emoji oder beliebiger String |
Hinweis: Kategorien sind family-wide – listId hat keine Wirkung.
Response:
a00.r.r → Kategorie-Objekt mit metaId
taskcategorydelete – Kategorie löschen
POST https://api.familywall.com/api/taskcategorydelete
Body-Parameter:
| Parameter | Wert |
|---|---|
id |
Kategorie-metaId ⚠️ nicht metaId! |
Hinweis: System-Kategorien (rights.canDelete=null) können technisch
gelöscht werden, sind dann aber dauerhaft weg und nicht wiederherstellbar.
MCP-Server schützt dagegen durch Check auf rights.canDelete.
taskcreatelist – Liste erstellen
POST https://api.familywall.com/api/taskcreatelist
Body-Parameter:
| Parameter | Pflicht | Wert |
|---|---|---|
name |
ja | Listen-Name (max 200 Zeichen) |
taskListType |
ja | "SHOPPING_LIST" oder "TODOS" |
sharedToAll |
nein | "true" / "false" (default: "true") |
color |
nein | Hex-Farbwert z.B. "#4784EC" |
emoji |
nein | Unicode-Emoji z.B. "🛒" |
scope |
nein | Kreis-metaId z.B. "family/23447378" (ohne scope → primärer Kreis) |
Scope-Verhalten:
- Ohne
scope: Liste wird im primären Kreis des Accounts erstellt - Mit
scope=family/XXXX: Liste wird im angegebenen Kreis erstellt - Die
metaIdder neuen Liste kodiert den Kreis:taskList/CIRCLENUM_LISTNUM - Parameter
familyId,circleId,family,id→ werden ignoriert, nurscopewirkt
Response:
a00.r.r → vollständiges Listen-Objekt
.metaId → neue Listen-ID (z.B. "taskList/23431854_29759623")
.name → Listen-Name
.taskListType → SHOPPING_LIST oder TODOS
.sharedToAll → "true" / "false"
.emoji → Unicode-Emoji (fehlt wenn nicht gesetzt)
.color → Hex-Farbwert z.B. "#E53935" (fehlt wenn nicht gesetzt)
.familyId → Kreis-metaId des erstellten Liste
.rights.canDelete → "true" (user-created lists)
Verifiziert am: 2026-04-16 via FW_DEBUG=1
taskdeletelist – Liste löschen
POST https://api.familywall.com/api/taskdeletelist
Body-Parameter:
| Parameter | Pflicht | Wert |
|---|---|---|
id |
ja | Listen-metaId ⚠️ nicht listId oder taskListId! |
scope |
nein | Kreis-metaId (erforderlich für sekundäre Kreise) |
Response:
a00.r.r → "true" (String)
Hinweis: Löscht die Liste und alle enthaltenen Tasks unwiderruflich.
System-Listen (rights.canDelete fehlt oder null) sind nicht löschbar.
MCP-Server prüft dies vor dem Löschen via taskgettasklists.
Für Listen in sekundären Kreisen muss scope=family/XXXX mitgeschickt werden.
Verifiziert am: 2026-04-16 via FW_DEBUG=1
taskgettasklists – Listen abrufen
POST https://api.familywall.com/api/taskgettasklists
Body-Parameter:
| Parameter | Pflicht | Wert |
|---|---|---|
scope |
nein | Kreis-metaId z.B. "family/23447378" (ohne scope → primärer Kreis) |
Scope-Verhalten:
- Ohne
scope: Nur Listen des primären Kreises werden zurückgegeben - Mit
scope=family/XXXX: Nur Listen des angegebenen Kreises - Es gibt keinen servereitigen Filter für mehrere Kreise gleichzeitig
- Andere Parameter (
familyId,circleId, etc.) werden ignoriert
Response-Struktur:
a00.r.r[] → Liste aller Task-Listen des Kreises
.metaId → Listen-ID (z.B. "taskList/23431854_29740942")
.name → Systembezeichnung oder Benutzer-Name
.taskListType → SHOPPING_LIST oder TODOS
.familyId → Kreis-metaId (z.B. "family/23431854")
.emoji → Unicode-Emoji oder "" (leerer String = kein Emoji)
.color → Hex-Farbwert z.B. "#E53935" (fehlt wenn nicht gesetzt)
.remainingTaskNumber → offene Tasks (String)
.totalTaskNumber → Gesamt-Tasks (String)
.sharedToAll → "true" / "false"
.sharedMemberIds[] → Member-accountIds
.rights.canDelete → "true" = löschbar, fehlt/leer = Systemliste
.systemId → vorhanden nur bei Systemlisten (z.B. "-10", "-11")
metaId-Encoding: taskList/<family_num>_<list_num> — die family_num kodiert den Kreis.
Beispiel: taskList/23431854_29740942 gehört zu family/23431854.
Hinweis emoji/color:
emoji: Systemlisten liefern"", user-created Listen liefern den Emoji-String oder""wenn kein Emoji gesetzt. Normalisierung:""→nullim MCP-Server.color: Fehlt komplett wenn nicht gesetzt (nichtnulloder""). Normalisierung: fehlendes Feld →nullim MCP-Server.
Verifiziert am: 2026-04-16 via FW_DEBUG=1
Systembezeichnungen für Listen-Namen
| Systembezeichnung | Deutsch |
|---|---|
SYS-CAT-SHOPPINGLIST |
Einkaufsliste |
SYS-CAT-TODOLIST |
Aufgaben |
Debug-Logging
Wenn die Umgebungsvariable FW_DEBUG=1 gesetzt ist, loggt fw_client.py
vollständige Request-Bodies und Responses nach stderr.
Wichtig: Keine Secrets in Debug-Ausgaben (Passwort maskieren).
Wann FW_DEBUG=1 nutzen:
- Neue Endpoints verifizieren
- Parameter-Namen unbekannt
- Silent-Fail debuggen
- Service Worker blockiert Browser-DevTools
Service Worker
Die Family Wall Web-App registriert einen Service Worker der bestimmte HTTP-Requests abfängt und modifiziert bevor sie das Netzwerk erreichen. Betroffen sind u.a. Unlike-Calls und möglicherweise andere schreibende Operationen.
Folge: Browser-DevTools Network-Tab und JS-Interceptoren (XHR/Fetch)
zeigen nicht den echten Request-Body für diese Calls.
Lösung: FW_DEBUG=1 auf MCP-Server-Seite zeigt was tatsächlich gesendet wird.
mprecipeput – Rezept erstellen
POST https://api.familywall.com/api/mprecipeput
Wichtig: Alle Parameter haben das Präfix recipe. (verifiziert via FW_DEBUG=1).
Body-Parameter:
| Parameter | Pflicht | Wert |
|---|---|---|
recipe.name |
ja | Rezeptname |
recipe.isRecipe |
ja | immer "true" |
recipe.description |
nein | Kurzbeschreibung |
recipe.ingredients |
nein | Zutaten als Freitext (Zeilen mit \n trennen) |
recipe.instructions |
nein | Anleitung als Freitext (Zeilen mit \n trennen) |
recipe.prepTime |
nein | Zubereitungszeit in Minuten (String, z.B. "30") |
recipe.cookTime |
nein | Kochzeit in Minuten (String, z.B. "60") |
recipe.serves |
nein | Portionen (String, z.B. "4") |
recipe.url |
nein | externe URL |
Response:
a00.r.r → vollständiges Rezept-Objekt
.metaId → neue Rezept-ID (z.B. "recipe/23431854_10968866")
.name → Rezeptname
.description → Beschreibung
.ingredients → Zutaten Freitext (API liefert \r\n als Zeilenumbrüche)
.ingredientsList[] → auto-geparste Zutaten (read-only, vom Server generiert)
.metaId → "recipeIngredient/<id>"
.name → Zutatname
.instructions → Anleitung Freitext
.prepTime → Zubereitungszeit als String ("30")
.cookTime → Kochzeit als String ("60")
.serves → Portionen als String ("4")
.url → externe URL (fehlt wenn leer)
.isRecipe → "true"
.isFavorite → "false"
.recipeCategories[] → []
.recipeCategoryIdList[] → []
.rights.canDelete → "true" für eigene Rezepte
.rights.canUpdate → "true" für eigene Rezepte
.familyId, .accountId, .creationDate, .moodMap, .moodStarShortcut
Verifiziert am: 2026-04-16 via FW_DEBUG=1
mprecipeput – Rezept aktualisieren (Update)
POST https://api.familywall.com/api/mprecipeput
Identisch zum Create-Aufruf, aber mit zusätzlichem recipe.metaId-Parameter.
Der Server unterscheidet Create vs. Update anhand ob recipe.metaId vorhanden ist.
Nur geänderte Felder müssen mitgeschickt werden (Partial Update).
recipe.name und recipe.isRecipe="true" sollten immer mitgeschickt werden.
Zusätzlicher Parameter:
| Parameter | Pflicht | Wert |
|---|---|---|
recipe.metaId |
ja (für Update) | metaId des zu aktualisierenden Rezepts |
Newline-Hinweis: Zutaten und Anleitung müssen echte \n-Zeichen enthalten
(nicht die zwei-Zeichen-Sequenz \n). Literale Backslash-n werden vom Server
als ein Element interpretiert → kein Splitting in ingredientsList.
Verifiziert am: 2026-04-16 via FW_DEBUG=1
metasync (id='recipe') – Alle Rezepte abrufen
POST https://api.familywall.com/api/metasync
Body-Parameter:
| Parameter | Wert |
|---|---|
id |
"recipe" (lowercase, enum-Wert) |
Response-Struktur:
a00.r.r.updatedCreated[] → Liste aller Rezepte der Familie
→ Felder identisch mit mprecipeput-Response (siehe oben)
Hinweis: Der Parameter id nimmt einen MetaIdTypeEnum-Wert, kein tatsächliches Objekt.
Nur "recipe" (lowercase) funktioniert – "RECIPE", "Recipe" und andere Schreibweisen
liefern MetaIdTypeEnum-Fehler.
Verifiziert am: 2026-04-16 via FW_DEBUG=1
metadelete – Rezept löschen
POST https://api.familywall.com/api/metadelete
Identisch mit dem Task-Löschen-Endpoint. Funktioniert auch für Rezepte.
Body-Parameter:
| Parameter | Wert |
|---|---|
id |
Rezept-metaId (z.B. "recipe/23431854_10968866") |
Response:
a00.r.r → "true" (String)
Verifiziert am: 2026-04-16 via FW_DEBUG=1
acccreatefamily – Kreis erstellen
POST https://api.familywall.com/api/acccreatefamily
Body-Parameter:
| Parameter | Pflicht | Wert |
|---|---|---|
name |
ja | Kreis-Name |
Response:
a00.r.r → numerische Kreis-ID als String (z.B. "23447369")
→ vollständige metaId: "family/" + id
Hinweise:
- Der Server kapitalisiert den ersten Buchstaben des Namens.
- Kreise können über die API nicht gelöscht werden (
metadelete→ "delete not supported"). - Vollständige Kreisdaten (incl. Name) via
famlistfamilyim gleichen Session-Call abrufbar.
Verifiziert am: 2026-04-16 via FW_DEBUG=1
accinvite – Mitglied einladen
POST https://api.familywall.com/api/accinvite
Body-Parameter:
| Parameter | Pflicht | Wert |
|---|---|---|
familyId |
ja | Kreis-metaId (z.B. "family/23447369") |
identifier |
ja | E-Mail-Adresse des Eingeladenen |
role |
ja | "Unknown" (einziger verifizierter Enum-Wert für FamilyRoleTypeEnum) |
firstname |
ja | Vorname des Eingeladenen |
Einschränkung: Der Endpoint funktioniert nur für Personen, die noch kein
Family Wall-Konto haben. Bei bestehenden Accounts antwortet der Server mit:
"This api is now only used to create and invite an account with login only."
Fehler-Struktur (HTTP 200, aber Fehler unter a00.ex):**
{"a00": {"ex": {"ex": {"FiZClassId": "17", "message": "..."}}}}
→ fw_client.py prüft a00.ex und wirft FamilyWallError.
Response (Erfolg):
a00.r.r → Einladungsobjekt (Struktur unbekannt, da nicht testbar mit Test-Account)
Bekannte Enum-Werte für role:
"Unknown"✓ verifiziert"Parent","Child"→FamilyRoleTypeEnumdecode error
Verifiziert am: 2026-04-16 via FW_DEBUG=1
accupdatefamily – Kreis umbenennen
POST https://api.familywall.com/api/accupdatefamily
Body-Parameter:
| Parameter | Pflicht | Wert |
|---|---|---|
name |
ja | Neuer Kreis-Name |
Hinweis: Aktualisiert immer den PRIMARY Kreis des Accounts (ignoriert id/familyId Parameter).
Verifiziert am: 2026-04-16 via FW_DEBUG=1
Offene Punkte
- Unlike-Endpoint (Service Worker blockiert Analyse)
- Erinnerungen (reminder) – nur Premium-Account
- Wiederholungen (repeat) – nur Premium-Account
- Sortierung von Kategorien via API
- mpadditemtolist (Zutaten aus Rezept → Einkaufsliste)
- Einladung bestehender FamilyWall-Nutzer (accinvite nur für neue Accounts)
- Kreis-Delete-Endpoint (API: "delete not supported" für family-Objekte)