Files
mcp-familywall/SPEC.md
T
marcus 4c1e4e2c23 feat(tasks): support reminder write via dot-notation (v1.2.0)
- Add reminder_unit, reminder_value to create_task
- Add reminder_unit, reminder_value, clear_reminder to update_task
- Wire format verified: reminder.reminderUnit / .reminderValue /
  .reminderType (SNOOZE=active, NONE=clear) / .localId (optional)
- Valid units: MINUTE, HOUR, DAY (WEEK rejected by enum decoder)
- Clear requires full inactive block; partial updates reject with
  "task reminder invalid"
- Flat top-level keys, JSON string and bracket notation are silently
  ignored by the server — confirmed via isolated fuzz per variant
- Update SPEC.md, CLAUDE.md, README.md, CHANGELOG.md
- Remove outdated "not supported" warning in update_task docstring
2026-04-17 22:41:16 +02:00

36 KiB
Raw Blame History

Family Wall API Spezifikation

Erarbeitet durch Browser-Traffic-Analyse und React-Fiber-Analyse (April 2026). Es gibt keine offizielle API-Dokumentation.

Stand: v1.0.0 (2026-04-17)

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).

Performance-Hinweis: Bulk-Operationen

Bulk-Operationen (z.B. alle Tasks einer Liste löschen) bündeln mehrere Calls in einer einzigen Session: Login → Call1 → Call2 → ... → CallN → Logout. Das spart N1 Login/Logout-Roundtrips gegenüber N separaten Tool-Aufrufen.

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 in taskupdate2

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)
recurrency nein "DAILY" | "WEEKLY" | "MONTHLY" | "YEARLY" | "NONE" (entfernen)
recurrencyInterval nein int (z.B. 2 für "alle 2 Wochen")
rrule nein vollständige iCal-RRULE (z.B. "FREQ=WEEKLY;INTERVAL=2;BYDAY=FR")
byDay nein z.B. "FR", "1SA", "MO,TU,WE,TH,FR"
byMonthDay nein int (z.B. 7 für "am 7. des Monats")
recurrencyEndDate nein ISO-Datum (z.B. "2026-12-31")
endOccurence nein int (nach N Wiederholungen aufhören)
Hinweis: taskListId ist NICHT Pflicht beim Update.

⚠️ Encoding: Der FiZ-Ai()-Encoder serialisiert alle Felder flach als Top-Level-Form-Parameter. Recurrency-Felder werden direkt auf Top-Level gesendet (verifiziert via xb-Encoder im JS-Bundle).

Reminder-Schreibzugriff (verifiziert 2026-04-17):

Reminder werden via Dot-Notation als Unterfelder gesendet:

Parameter Wert
reminder.reminderUnit "MINUTE" | "HOUR" | "DAY" (WEEK wird abgelehnt)
reminder.reminderValue nicht-negativer Integer als String (z.B. "30")
reminder.reminderType "SNOOZE" (aktiv) oder "NONE" (Reminder entfernen)
reminder.localId optional; "0" akzeptiert

Wichtig:

  • Nur Dot-Notation funktioniert. Flache Top-Level-Keys (reminderUnit, reminderValue, …), JSON-String (reminder={…}) und Bracket-Notation (reminder[reminderUnit]) werden silent-ignored (HTTP 200, Reminder unverändert).
  • Partielle Reminder-Updates (z.B. nur reminder.reminderType=NONE) liefern task reminder invalid — immer vollständigen Block senden.
  • reminder=$empty wird silent-ignored; zum Entfernen muss reminder.reminderType=NONE mit reminder.reminderValue=0 und reminder.reminderUnit=MINUTE gesendet werden.
  • Reminder-Felder lassen sich in einem einzigen taskupdate2-Call gemeinsam mit recurrency/dueDate/text setzen — keine Interferenz.
  • $empty auf Unterfelder (reminder.reminderValue=$empty) führt zu Parse-Fehlern.

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 Objekt löschen (Task, Rezept, Essensplan-Eintrag)

POST https://api.familywall.com/api/metadelete

Body-Parameter:

Parameter Wert
id metaId des zu löschenden Objekts ⚠️ nicht metaId!

Unterstützte Objekt-Typen:

  • Tasks: task/<id>
  • Rezepte: recipe/<id>
  • Essensplan-Einträge: dish/<id> und meal/<id>

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 metaId der neuen Liste kodiert den Kreis: taskList/CIRCLENUM_LISTNUM
  • Parameter familyId, circleId, family, id → werden ignoriert, nur scope wirkt

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

taskupdatelist Liste aktualisieren

POST https://api.familywall.com/api/taskupdatelist

Body-Parameter:

Parameter Pflicht Wert
metaId ja Listen-metaId ⚠️ nicht id!
name nein Neuer Listen-Name
color nein Hex-Farbwert z.B. "#E53935"
emoji nein Unicode-Emoji z.B. "🧪"
scope nein Kreis-metaId für sekundäre Kreise; automatisch aus metaId abgeleitet

Hinweis: Nur übergebene Felder werden geändert (Partial Update). Felder die nicht mitgeschickt werden bleiben auf dem Server unverändert. System-Listen (rights.canUpdate fehlt oder != "true") können nicht geändert werden. MCP-Server prüft rights.canUpdate vor dem Update via taskgettasklists.

Response:

a00.r.r                     → vollständiges Listen-Objekt (analog taskcreatelist)
  .metaId                   → Listen-ID
  .name                     → (aktualisierter) Listen-Name
  .taskListType             → SHOPPING_LIST oder TODOS
  .emoji                    → (aktualisiertes) Unicode-Emoji
  .color                    → (aktualisierter) Hex-Farbwert
  .familyId                 → Kreis-metaId
  .rights.canUpdate         → "true" für bearbeitbare Listen
  .rights.canDelete         → "true" für löschbare Listen
  .lastAction               → "UPDATED"

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 (Server):

  • 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

Scope-Verhalten (MCP-Tool get_lists, v0.8.2+):

  • Ohne scope: Der MCP-Server ruft für jeden Kreis separate taskgettasklists(scope=<circle_id>)-Calls ab und merged die Ergebnisse
  • Mit scope=family/XXXX oder scope="Kreis Name": Nur dieser Kreis (wie bisher)

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: ""null im MCP-Server.
  • color: Fehlt komplett wenn nicht gesetzt (nicht null oder ""). Normalisierung: fehlendes Feld → null im 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

Parser-Bug (v0.11.7): Das Feld .ingredientsList[] wird vom Server geparst und hat einen Bug bei Komma+Leerzeichen (z.B. "1, 5g" wird abgeschnitten). Der MCP-Client ignoriert .ingredientsList und generiert ingredients_parsed stattdessen client-seitig durch Splitting von .ingredients auf \r\n/\n.

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)
  .isRecipe                  → "true" oder "false" (wichtig!)

isRecipe-Flag (v0.11.8):

  • isRecipe="true" → Echtes Rezept in der Rezeptbox (get_recipe_box gibt es zurück)
  • isRecipe="false" → Freitext-Stub aus dem Essensplaner ODER altes importiertes Rezept, das nie korrekt getaggt wurde
  • get_recipe_box filtert strikt nach isRecipe="true" — konsistent mit der Family Wall App
  • Bekanntes Beispiel: recipe/16282169_7055369 ("Elsässer Flammkuchen") hat isRecipe=false trotz vorhandener Zutaten und Anleitung. Family Wall behandelt es nicht als Rezeptbox-Eintrag.

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 famlistfamily im 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"FamilyRoleTypeEnum decode 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
scope nein Kreis-metaId z.B. "family/23449644" (ohne scope → primärer Kreis)

Response:

a00.r.r                     → vollständiges Kreis-Objekt
  .metaId                   → Kreis-metaId (z.B. "family/23449644")
  .name                     → (aktualisierter) Kreis-Name (erster Buchstabe wird kapitalisiert)
  .family_id                → numerische Kreis-ID (ohne "family/"-Prefix)
  .members[]                → Mitglieder-Liste

Hinweise:

  • Ohne scope: aktualisiert den PRIMARY Kreis des Accounts.
  • Mit scope=family/XXXX: aktualisiert den angegebenen Kreis (primär oder sekundär).
  • Der Server kapitalisiert immer den ersten Buchstaben des Namens.
  • Nur der Name ist über die API änderbar (kein Bild, keine Farbe).

Vorherige Dokumentation korrigiert: Frühere SPEC-Einträge vermerkten, dass id/familyId ignoriert werden. Mit scope= funktioniert die Zielauswahl korrekt für beliebige Kreise.

Verifiziert am: 2026-04-16 via FW_DEBUG=1 (scope= auf sekundärem Kreis)

adminwipefamily Kreis löschen

POST https://api.familywall.com/api/adminwipefamily

Löscht einen Kreis und alle zugehörigen Inhalte (Listen, Tasks, Rezepte, Wall-Posts).

Body-Parameter:

Parameter Pflicht Wert
scope ja Kreis-metaId (z.B. family/23447378)

Response (Erfolg):

{ "a00": { "r": { "r": "true" } } }

Hinweise:

  • Löscht unwiderruflich alle Inhalte des Kreises.
  • Der primäre Kreis (isFirstFamily="true" in famlistfamily) kann NICHT gelöscht werden.
  • MCP-Server prüft isFirstFamily vor dem Löschen via famlistfamily im gleichen Session-Call.

Verifiziert am: 2026-04-16 via FW_DEBUG=1 (family/23447371 erfolgreich gelöscht)

Meal Planner API

Premium-Feature. Endpoints extrahiert aus JS-Bundle startupmodule.js?vfw=2026-04-03T140539. Browser-Analyse blockiert durch Service Worker. Response-Struktur wird nach erstem Deploy mit FW_DEBUG=1 verifiziert.

mplistinterval Essensplan für Datumsbereich abrufen

POST https://api.familywall.com/api/mplistinterval

Body-Parameter:

Parameter Pflicht Wert
from ja Start-Datum ISO 8601 (z.B. "2026-04-13")
to ja End-Datum ISO 8601 (z.B. "2026-04-19")

Response-Struktur:

a00.r.r
  .from                   → angefragtes Start-Datum (z.B. "2026-04-13")
  .to                     → angefragtes End-Datum (z.B. "2026-04-19")
  .list[]                 → geplante Mahlzeiten (dish-Objekte)
    .metaId               → "dish/<family_num>_<dish_num>"
    .date                 → Datum der Mahlzeit (z.B. "2026-04-17")
    .type                 → Mahlzeiten-Typ (s.u.)
    .name                 → Anzeigename (z.B. "Biga Pizzateig")
    .recipeId             → verknüpfte Rezept-metaId oder fehlt wenn freier Text
    .familyId             → Kreis-metaId
    .accountId            → Ersteller-accountId
    .sortingIndex         → Sortierung (numerischer Timestamp als String)
    .rights.canUpdate     → "true" wenn bearbeitbar
    .rights.canDelete     → "true" wenn löschbar
  .recipeList[]           → Rezept-Objekte der verknüpften Gerichte
    .metaId               → Rezept-ID (z.B. "recipe/16282169_7932720")
    .isRecipe             → "true" = echtes Rezept aus der Rezeptbox (hat Zutaten etc.)
                            "false" = Freitext-Stub (nur Name, keine Zutaten)
  .mealList[]             → Freitext-Notizen (meal-Objekte)
    .metaId               → "meal/<family_num>_<meal_num>"
    .date                 → Datum der Mahlzeit (z.B. "2026-04-17")
    .type                 → Mahlzeiten-Typ (BREAKFAST/LUNCH/SNACK/DINNER)
    .note                 → Freitext-Notiz (z.B. "Test")
    .serves               → Portionen als String (z.B. "1")
    .rights.canUpdate     → "true" wenn bearbeitbar
    .rights.canDelete     → "true" wenn löschbar

Mahlzeiten-Typen:

  • BREAKFAST Frühstück
  • LUNCH Mittagessen
  • SNACK Snack
  • DINNER Abendessen

Hinweis: recipeList wird vom MCP-Tool nicht zurückgegeben. Rezept-Details bei Bedarf separat via get_recipe abrufen. list[] (dish) und mealList[] (meal) werden gemergt und nach Datum + Typ sortiert zurückgegeben.

Verifiziert am: 2026-04-17 via FW_DEBUG=1

mpcreateByRecipeId Rezept in Essensplan eintragen

POST https://api.familywall.com/api/mpcreateByRecipeId

Body-Parameter (verifiziert aus JS-Bundle startupmodule.js):

Parameter Pflicht Wert
recipeId ja Rezept-metaId (z.B. "recipe/16282169_7932720")
date ja Ziel-Datum ISO 8601 (z.B. "2026-04-20")
type ja Mahlzeiten-Typ: BREAKFAST, LUNCH, SNACK, DINNER
clientOpId nein Optionale Client-seitige Idempotenz-ID (wird weggelassen)

Response-Struktur:

a00.r.r                     → vollständiges dish-Objekt
  .metaId                   → neue Dish-ID (z.B. "dish/16282169_20009811")
  .date                     → Datum (z.B. "2026-04-18")
  .type                     → Mahlzeiten-Typ (BREAKFAST/LUNCH/SNACK/DINNER)
  .name                     → Rezeptname
  .recipeId                 → verknüpfte Rezept-metaId
  .familyId                 → Kreis-metaId
  .accountId                → Ersteller-accountId
  .sortingIndex             → Sortierung (numerischer Timestamp als String)
  .rights.canUpdate         → "true"
  .rights.canDelete         → "true"
a00.cn                      → "mpcreateByRecipeId" (Endpoint-Echo)

Verifiziert am: 2026-04-17 via FW_DEBUG=1

mpcreate Freitext-Mahlzeit in Essensplan eintragen

POST https://api.familywall.com/api/mpcreate

Body-Parameter (verifiziert aus JS-Bundle startupmodule.js):

Parameter Pflicht Wert
name ja Anzeigename der Mahlzeit (z.B. "Pfannkuchen")
date ja Ziel-Datum ISO 8601 (z.B. "2026-04-20")
type ja Mahlzeiten-Typ: BREAKFAST, LUNCH, SNACK, DINNER
clientOpId nein Optionale Client-seitige Idempotenz-ID (wird weggelassen)

Response-Struktur:

a00.r.r                     → Array (⚠️ nicht Objekt wie bei mpcreateByRecipeId!)
  [0]                       → neues dish-Objekt
    .metaId                 → neue Dish-ID (z.B. "dish/16282169_20010208")
    .date                   → Datum (z.B. "2026-04-20")
    .type                   → Mahlzeiten-Typ (BREAKFAST/LUNCH/SNACK/DINNER)
    .name                   → Freitext-Name
    .recipeId               → vom Server generierte Stub-Rezept-ID (isRecipe="false")
    .rights.canUpdate       → "true"
    .rights.canDelete       → "true"
a00.cn                      → "mpcreate" (Endpoint-Echo)

Hinweis: Der Server legt intern ein Stub-Rezept (isRecipe="false") an und verknüpft es mit dem Dish-Objekt. is_from_recipe_box ist daher false.

Verifiziert am: 2026-04-17 via FW_DEBUG=1

mpmealput Meal-Notiz erstellen/aktualisieren

POST https://api.familywall.com/api/mpmealput

Body-Parameter (verifiziert aus JS-Bundle, Encoder UI(O)):

Parameter Pflicht Wert
date ja Ziel-Datum ISO 8601 (z.B. "2026-04-20")
type ja Mahlzeiten-Typ: BREAKFAST, LUNCH, SNACK, DINNER
note nein Freitext-Notiz (z.B. "Bitte ohne Zwiebeln")
serves nein Portionen als String (z.B. "4") — Vt = int→string Konverter
metaId nein metaId eines bestehenden meal/-Objekts → Update; ohne → Create

Hinweis: Ohne metaId wird ein neues meal/-Objekt erstellt. Mit metaId wird ein bestehendes aktualisiert (Update, noch nicht implementiert).

Response-Struktur:

a00.r.r                     → meal-Objekt (Objekt, nicht Array)
  .metaId                   → neue/aktualisierte Meal-ID (z.B. "meal/16282169_...")
  .date                     → Datum
  .type                     → Mahlzeiten-Typ
  .note                     → Freitext-Notiz
  .serves                   → Portionen als String (z.B. "1")
  .familyId                 → Kreis-metaId
  .accountId                → Ersteller-accountId
  .rights.canUpdate         → "true"
  .rights.canDelete         → "true"

Verifiziert am: 2026-04-17 (Parameter aus JS-Bundle; Response-Struktur aus Sg-Klasse im Bundle)

Weitere Meal Planner Endpoints (nicht implementiert)

Endpoint Parameter Bedeutung
mpmove metaId, date, type, clientOpId Mahlzeit zu anderem Datum/Typ verschieben
mpdelete metaId Mahlzeit löschen
mpsettings Einstellungen lesen

Quelle: JS-Bundle-Analyse (startupmodule.js). Status: Endpunkte bekannt, Response-Struktur unbekannt.

Recipe Categories API Details

Recipe categories are managed via mprecipeput endpoint. Each recipe can have zero or more categories assigned via recipe.recipeCategoryIdList (sent multiple times for each category).

Response structure (in mprecipeput response):

a00.r.r
  .recipeCategoryIdList[]   → List of assigned category IDs (e.g. ["category/23431854_2"])
  .recipeCategories[]       → List of system names (e.g. ["KIDS_LOVE"])

Category IDs have format category/<family_id>_<index>. Categories are family-wide. Standard categories (_2 to _6) are always available and derived from the family's metaId. No API endpoint needed IDs are constructed as category/<familyId>_<N>. Premium accounts may have additional categories beyond the 5 available in free tier.

metamood Rezept-Reaktion (Stern setzen)

POST https://api.familywall.com/api/metamood

Body-Parameter:

Parameter Pflicht Wert
id ja Rezept-metaId ⚠️ nicht metaId!
moodType nein "STAR", "LIKE", "BEST_MOMENT", ... (Wert wird angenommen aber ignoriert)

Response:

a00.r.r                     → Rezept-Objekt (FiZClassId: "8004")
  .metaId                   → Rezept-ID
  .isFavorite               → aktueller Wert (unverändert)
  .moodStarShortcut         → aktueller Wert (unverändert)
  .moodMap                  → aktueller Wert (unverändert)

Bekannte Einschränkungen:

  • Eigene Rezepte können nicht reagiert werden (Self-Reaction-Restriction, analog zu wallmood)
  • Der Endpoint akzeptiert Requests (HTTP 200, kein Fehler), verändert aber bei eigenen Rezepten keinen State
  • FiZClassId: "8004" im Response deutet auf "verarbeitet aber nicht geändert" hin
  • Möglicherweise funktioniert der Endpoint für Rezepte anderer Familienmitglieder (nicht testbar mit Einzel-Account)

Entdeckt: 2026-04-17 via FW_DEBUG=1 Probing

mpstar Rezept als Favorit markieren (Service Worker blockiert)

POST https://api.familywall.com/api/mpstar

Status: Nicht direkt zugänglich. Der Server antwortet mit "The call mpstar is not registered". Der Browser-Aufruf data-fw-onclick="mpstar" wird vom Service Worker abgefangen und transformiert, bevor er den Server erreicht. Die Transformation ist ohne Service-Worker-Analyse nicht bekannt.

Hypothesen zum echten Endpoint:

  • Könnte eine transformierte Form von metamood sein (mit Verschlüsselung/Token)
  • Könnte ein separater "Lesezeichen"-Endpoint sein der isFavorite setzt (vs. moodMap-Stern)
  • Könnte Premium-only sein

Zum Entsperren nötig:

  • Service-Worker-Quellcode analysieren (DevTools Application > Service Workers > Source)
  • ODER: FW_DEBUG=1 auf einem echten Multi-User-Account mit Rezepten anderer Mitglieder testen

Entdeckt: 2026-04-17 via FW_DEBUG=1 Probing (ausgiebige Endpoint-Suche)

Offene Punkte

  • Unlike-Endpoint (Service Worker blockiert Analyse)
  • mpstar / isFavorite für Rezepte (Service Worker blockiert Analyse, siehe oben)
  • Erinnerungen (reminder) nur Premium-Account
  • Wiederholungen (repeat) nur Premium-Account
  • Rezept-Kategorien-Listing-Endpoint (derzeit keine API, müssen aus Rezepten extrahiert werden)
  • mpadditemtolist (nicht nötig Family Wall kann das nativ über die Web-App)
  • Einladung bestehender FamilyWall-Nutzer (accinvite nur für neue Accounts)