Files
mcp-familywall/SPEC.md
T
marcus 2bc03e2165 feat(circles): create_circle + add_member_to_circle (v0.7.0)
- acccreatefamily endpoint creates a new circle (returns numeric ID)
- accinvite endpoint invites new users by email (familyId, identifier, role, firstname)
- fw_client now detects a00.ex errors (was only checking a00.un before)
- New modules/circles.py with FamilyRoleTypeEnum constants
- SPEC.md updated with acccreatefamily, accinvite, accupdatefamily docs
- Note: circle deletion not supported by FW API (metadelete → "delete not supported")
- Note: accinvite only works for new (non-existing) FW accounts

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-16 17:59:20 +02:00

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

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

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. "🛒"

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)
  .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 Wert
id Listen-metaId ⚠️ nicht listId oder taskListId!

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.

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

taskgettasklists Listen abrufen

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

Body-Parameter: keine

Response-Struktur:

a00.r.r[]                   → Liste aller Task-Listen
  .metaId                   → Listen-ID (z.B. "taskList/23431854_29740942")
  .name                     → Systembezeichnung oder Benutzer-Name
  .taskListType             → SHOPPING_LIST oder TODOS
  .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")

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

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

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)