{"version":"1","scopes":["messages:send","messages:read","boards:read","boards:write","lists:read","lists:write","meals:read","meals:write","chores:read","chores:write","calendar:read","calendar:write","kb:read","kb:write","files:read","files:write","members:invite","connectors:use","connectors:manage","smart_home:use","smart_home:manage","vault:read","vault:manage","personal:read","personal:write","admin"],"auth_note":"Machines may use Authorization: Bearer <agent_token>. MCP clients may use OAuth 2.1 authorization code + S256 PKCE with a human-approved agent. Browsers use 30-day HttpOnly SameSite=Lax user (ofb_session) or agent (ofb_agent_session) cookies. User sessions follow a magic email link. Revocation takes effect immediately. Personal routes resolve the user from the caller's credential, never from a supplied user_id.","mcp":{"path":"/mcp","transport":"streamable-http","protocol_version":"2025-06-18","note":"POST JSON-RPC 2.0; Bearer agent tokens or OAuth 2.1. Protected tools challenge with OAuth discovery. Same agent scopes as REST. Single code-mode catalog: search_tools + execute (run JavaScript against a typed fb SDK — one async method per tool — in a fresh Dynamic Worker sandbox isolate per call: no filesystem, no env vars, network blocked; tools run with the caller's own credential). tools/call also accepts any underlying tool name directly. Agent skill at skill://ourfamilybrain/SKILL.md (resources/read) and GET /skill.md."},"oauth":{"protected_resource_metadata":"/.well-known/oauth-protected-resource","authorization_server_metadata":"/.well-known/oauth-authorization-server","registration_endpoint":"/oauth/register","authorization_endpoint":"/oauth/authorize","token_endpoint":"/oauth/token","scope":"mcp","code_challenge_method":"S256"},"endpoints":[{"method":"POST","path":"/v1/families","auth":false},{"method":"GET","path":"/v1/families/{family_id}","auth":true,"scopes":[],"note":"family name, id, created_at + member/agent counts; readable by any family member"},{"method":"GET","path":"/v1/families/{family_id}/metrics/summary","auth":true,"scopes":["admin"],"note":"?days=1..90 (default 7); per-tool/per-endpoint calls, avg/max ms, errors"},{"method":"POST","path":"/v1/families/{family_id}/invites","auth":true,"scopes":["admin","members:invite"]},{"method":"POST","path":"/v1/families/{family_id}/invites/email","auth":true,"scopes":["admin","members:invite"],"note":"mint an invite and email the code from hello@ourfamilybrain.com (20/family/hour)"},{"method":"GET","path":"/v1/families/{family_id}/invites","auth":true,"scopes":["admin","members:invite"],"note":"outstanding invite codes: code preview, uses/max, expiry, status, creator"},{"method":"POST","path":"/v1/families/{family_id}/invites/{invite_id}/revoke","auth":true,"scopes":["admin","members:invite"],"note":"revoke an invite code; revoked codes fail accept/redeem/info with invite_revoked"},{"method":"POST","path":"/v1/families/{family_id}/invites/{invite_id}/resend","auth":true,"scopes":["admin","members:invite"],"note":"resend an email invite: the old code is revoked and a fresh one is emailed to the recorded recipient"},{"method":"GET","path":"/v1/families/{family_id}/email-sends","auth":true,"scopes":["admin"],"note":"outbound email delivery metadata (never bodies)"},{"method":"GET","path":"/v1/families/{family_id}/features","auth":true,"scopes":[],"note":"readable by any family member; toggleable family features (all default on)"},{"method":"PUT","path":"/v1/families/{family_id}/features","auth":true,"scopes":["admin"],"note":"enable/disable features; disabled features 404 on their routes"},{"method":"POST","path":"/v1/invites/{code}/redeem","auth":false},{"method":"GET","path":"/v1/invites/{code}/info","auth":false,"note":"family_name + expires_at for the public /join page"},{"method":"POST","path":"/v1/invites/{code}/accept","auth":true,"note":"signed-in human joins the existing family"},{"method":"POST","path":"/v1/families/{family_id}/login-links","auth":true,"scopes":[],"note":"mint a single-use login link (10 min); any agent for itself, admin for any agent"},{"method":"POST","path":"/v1/login-links/redeem","auth":false,"note":"redeem a login code -> 30-day session token (shown once)"},{"method":"GET","path":"/v1/auth/agent-session","auth":true,"note":"read the browser's HttpOnly agent session"},{"method":"POST","path":"/v1/auth/agent-session","auth":true,"note":"exchange a one-time agent session token for an HttpOnly browser cookie"},{"method":"POST","path":"/v1/auth/agent-session/logout","auth":true,"note":"revoke the browser's agent session"},{"method":"POST","path":"/v1/auth/request-link","auth":false,"note":"email a single-use 15-minute magic sign-in link"},{"method":"GET","path":"/v1/auth/verify?token=…","auth":false,"note":"redeem a magic link -> 30-day user session (HttpOnly cookie); ?format=json for API clients"},{"method":"GET","path":"/v1/auth/me","auth":true,"note":"the signed-in person, their families (role, default) and their agents (cookie or Bearer user session)"},{"method":"GET","path":"/v1/auth/me/export","auth":true,"note":"download a ZIP backup of everything you can see: manifest.json (profile, personal space, and per-family lists with sections, boards with columns, notes with folders/tags/comments/versions, calendars, events, and file metadata; no secrets) plus each file's bytes under files/{file_id}/{filename}"},{"method":"GET","path":"/v1/auth/me/notification-prefs","auth":true,"note":"the signed-in person's email notification switches {assignments, mentions, direct_messages} (all default on)"},{"method":"PATCH","path":"/v1/auth/me/notification-prefs","auth":true,"note":"set email notification switches {assignments?, mentions?, direct_messages?} — booleans only"},{"method":"GET","path":"/v1/auth/me/unread-summary","auth":true,"note":"per-family unread thread counts + has_mention flags across all the person's families {families: [{family_id, family_name, unread, has_mention}], total_unread}; own messages and morning briefs never count"},{"method":"POST","path":"/v1/auth/me/avatar","auth":true,"note":"upload your avatar (multipart field 'file'; PNG/JPEG/GIF/WebP, 5 MiB max) -> {avatar_url}"},{"method":"DELETE","path":"/v1/auth/me/avatar","auth":true,"note":"remove your avatar -> {avatar_url: null}"},{"method":"GET","path":"/v1/users/{user_id}/avatar","auth":true,"note":"stream a person's avatar image; the requester must be that person or share a family with them; 404 when none"},{"method":"GET","path":"/v1/families/{family_id}/assigned-to-me","auth":true,"scopes":["lists:read"],"note":"the caller's open list items (with list_title + due) and today's chore assignments {items, chores: [{id, chore_list_id, list_name, title, due: today|overdue, done}], generated_at}"},{"method":"PATCH","path":"/v1/auth/me","auth":true,"note":"update name, email, or default_family_id (a family you're in)"},{"method":"POST","path":"/v1/auth/webauthn/register/options","auth":true,"note":"start adding a passkey to the signed-in account"},{"method":"POST","path":"/v1/auth/webauthn/register/verify","auth":true,"note":"finish adding a passkey"},{"method":"POST","path":"/v1/auth/webauthn/login/options","auth":false,"note":"start a passkey sign-in"},{"method":"POST","path":"/v1/auth/webauthn/login/verify","auth":false,"note":"finish a passkey sign-in; sets the session cookie"},{"method":"GET","path":"/v1/auth/webauthn/credentials","auth":true,"note":"the signed-in person's passkeys"},{"method":"DELETE","path":"/v1/auth/webauthn/credentials/{credential_id}","auth":true,"note":"remove one of your passkeys"},{"method":"POST","path":"/v1/feedback","auth":true,"note":"report a bug, request a feature, or send praise/a question {type, title, body}"},{"method":"GET","path":"/v1/feedback","auth":true,"note":"list submitted feedback"},{"method":"GET","path":"/api/feedback","auth":false,"note":"public feedback feed (titles and bodies only; no emails or tokens)"},{"method":"GET","path":"/v1/feedback/mine","auth":true,"note":"the caller's own feedback submissions, newest first"},{"method":"GET","path":"/v1/admin/overview","auth":true,"note":"app operator only: headline counts (families, users, agents, feedback, signups)"},{"method":"GET","path":"/v1/admin/activity","auth":true,"note":"app operator only: daily signups + active families + requests (?days=1..90)"},{"method":"GET","path":"/v1/admin/usage","auth":true,"note":"app operator only: top MCP tools and REST endpoints with error share (?days=1..90)"},{"method":"GET","path":"/v1/admin/flows","auth":true,"note":"app operator only: signup -> family -> connected assistant -> content funnel counts"},{"method":"GET","path":"/v1/admin/families","auth":true,"note":"app operator only: paginated family table (?limit=&offset=)"},{"method":"GET","path":"/v1/admin/feedback","auth":true,"note":"app operator only: feedback inbox across families (?status=&type=&limit=&offset=)"},{"method":"PATCH","path":"/v1/admin/feedback/{id}","auth":true,"note":"app operator only: set a feedback item's status {status}"},{"method":"POST","path":"/v1/auth/me/families","auth":true,"note":"start a family {name}; you become its admin, and your default if you had none"},{"method":"POST","path":"/v1/auth/logout","auth":true,"note":"revoke the user session and clear the cookie"},{"method":"POST","path":"/v1/agents","auth":true,"note":"create an agent under the signed-in person (name, kind, family_id? — defaults to your default family); API token shown once"},{"method":"PUT","path":"/v1/agents/{agent_id}/families/{family_id}","auth":true,"note":"add one of your agents to another family you're in (owner session); that family's admins set its scopes there"},{"method":"DELETE","path":"/v1/agents/{agent_id}/families/{family_id}","auth":true,"note":"take one of your agents out of one family (owner session); 409 last_family for its only family"},{"method":"DELETE","path":"/v1/agents/{agent_id}","auth":true,"note":"revoke one of your agents everywhere (owner session)"},{"method":"GET","path":"/v1/agents/me/families","auth":true,"note":"the families this agent is in, default first (agent token); calls without a family use the default"},{"method":"POST","path":"/v1/agents/claim","auth":true,"note":"signed-in human claims an unowned agent using its one-time claim code"},{"method":"POST","path":"/v1/agents/{agent_id}/regenerate-token","auth":true,"note":"rotate one of the user's agent API tokens (shown once)"},{"method":"POST","path":"/v1/sessions/revoke","auth":true,"note":"revoke the caller's session, or all of the agent's sessions with an agent token"},{"method":"DELETE","path":"/v1/families/{family_id}/agents/{agent_id}/sessions","auth":true,"scopes":["admin"],"note":"revoke all sessions of one agent"},{"method":"GET","path":"/v1/families/{family_id}/agents","auth":true,"scopes":["admin"]},{"method":"GET","path":"/v1/families/{family_id}/agents/me","auth":true,"scopes":[],"note":"the caller's own agent record (lets the console gate UI actions)"},{"method":"POST","path":"/v1/families/{family_id}/agents/me/claim-links","auth":true,"scopes":[],"note":"unowned agent mints a ten-minute human claim link"},{"method":"PUT","path":"/v1/families/{family_id}/agents/{agent_id}/scopes","auth":true,"scopes":["admin"]},{"method":"POST","path":"/v1/families/{family_id}/agents/{agent_id}/revoke","auth":true,"scopes":["admin"]},{"method":"GET","path":"/v1/families/{family_id}/people","auth":true,"scopes":[],"note":"same-family human roster for audience pickers"},{"method":"DELETE","path":"/v1/families/{family_id}/people/{user_id}","auth":true,"scopes":["admin"],"note":"remove a person from this family only: revokes their agents here; their account, Personal space, and other families stay. 400 for self or last person, 409 for the last admin"},{"method":"PUT","path":"/v1/families/{family_id}/people/{user_id}/role","auth":true,"scopes":["admin"],"note":"set a person's role {role: admin|member}; 409 if it would leave the family without an admin"},{"method":"PATCH","path":"/v1/families/{family_id}","auth":true,"scopes":["admin"],"note":"rename the family {name}"},{"method":"DELETE","path":"/v1/families/{family_id}","auth":true,"note":"delete the family (signed-in admin only); 409 unless nobody else and no other assistants are in it"},{"method":"POST","path":"/v1/families/{family_id}/leave","auth":true,"note":"leave the family (signed-in person); 409 for the last admin while others remain, or the last person (delete instead)"},{"method":"POST","path":"/v1/families/{family_id}/groups","auth":true,"scopes":["admin"],"note":"create a named audience group"},{"method":"GET","path":"/v1/families/{family_id}/groups","auth":true,"scopes":[],"note":"list audience groups and members"},{"method":"PATCH","path":"/v1/families/{family_id}/groups/{group_id}","auth":true,"scopes":["admin"],"note":"rename an audience group"},{"method":"DELETE","path":"/v1/families/{family_id}/groups/{group_id}","auth":true,"scopes":["admin"],"note":"delete an unreferenced audience group"},{"method":"PUT","path":"/v1/families/{family_id}/groups/{group_id}/members","auth":true,"scopes":["admin"],"note":"replace group membership with same-family user_ids"},{"method":"GET","path":"/v1/families/{family_id}/audit","auth":true,"scopes":["admin"],"note":"asc from cursor/since_id by default; order=desc + before_id reads newest-first; server-side filters: actor, action (exact or prefix), actions (csv), q"},{"method":"POST","path":"/v1/families/{family_id}/messages","auth":true,"scopes":["messages:send"]},{"method":"GET","path":"/v1/families/{family_id}/messages","auth":true,"scopes":["messages:read"]},{"method":"PATCH","path":"/v1/families/{family_id}/messages/{message_id}","auth":true,"scopes":["messages:send"]},{"method":"DELETE","path":"/v1/families/{family_id}/messages/{message_id}","auth":true,"scopes":["messages:send"]},{"method":"POST","path":"/v1/families/{family_id}/messages/{message_id}/reactions","auth":true,"scopes":["messages:send"]},{"method":"DELETE","path":"/v1/families/{family_id}/messages/{message_id}/reactions/{emoji}","auth":true,"scopes":["messages:send"]},{"method":"POST","path":"/v1/families/{family_id}/threads","auth":true,"scopes":["messages:send"]},{"method":"GET","path":"/v1/families/{family_id}/threads","auth":true,"scopes":["messages:read"]},{"method":"PATCH","path":"/v1/families/{family_id}/threads/{thread_id}","auth":true,"scopes":["messages:send"]},{"method":"DELETE","path":"/v1/families/{family_id}/threads/{thread_id}","auth":true,"scopes":["messages:send"]},{"method":"GET","path":"/v1/protocol","auth":false},{"method":"GET","path":"/v1/health","auth":false},{"method":"POST","path":"/v1/families/{family_id}/boards","auth":true,"scopes":["boards:write"]},{"method":"GET","path":"/v1/families/{family_id}/boards","auth":true,"scopes":["boards:read"]},{"method":"GET","path":"/v1/families/{family_id}/boards/{board_id}","auth":true,"scopes":["boards:read"]},{"method":"DELETE","path":"/v1/families/{family_id}/boards/{board_id}","auth":true,"scopes":["boards:write"]},{"method":"PATCH","path":"/v1/families/{family_id}/boards/{board_id}","auth":true,"scopes":["boards:write"]},{"method":"GET","path":"/v1/families/{family_id}/boards/{board_id}/lists","auth":true,"scopes":["boards:read"]},{"method":"POST","path":"/v1/families/{family_id}/boards/{board_id}/lists","auth":true,"scopes":["boards:write"]},{"method":"PATCH","path":"/v1/families/{family_id}/boards/{board_id}/lists/{list_id}","auth":true,"scopes":["boards:write"]},{"method":"DELETE","path":"/v1/families/{family_id}/boards/{board_id}/lists/{list_id}","auth":true,"scopes":["boards:write"]},{"method":"GET","path":"/v1/families/{family_id}/boards/{board_id}/labels","auth":true,"scopes":["boards:read"]},{"method":"POST","path":"/v1/families/{family_id}/boards/{board_id}/labels","auth":true,"scopes":["boards:write"]},{"method":"PATCH","path":"/v1/families/{family_id}/boards/{board_id}/labels/{label_id}","auth":true,"scopes":["boards:write"]},{"method":"DELETE","path":"/v1/families/{family_id}/boards/{board_id}/labels/{label_id}","auth":true,"scopes":["boards:write"]},{"method":"POST","path":"/v1/families/{family_id}/boards/{board_id}/cards/{card_id}/labels/{label_id}","auth":true,"scopes":["boards:write"]},{"method":"DELETE","path":"/v1/families/{family_id}/boards/{board_id}/cards/{card_id}/labels/{label_id}","auth":true,"scopes":["boards:write"]},{"method":"GET","path":"/v1/families/{family_id}/boards/{board_id}/cards/{card_id}/checklists","auth":true,"scopes":["boards:read"]},{"method":"POST","path":"/v1/families/{family_id}/boards/{board_id}/cards/{card_id}/checklists","auth":true,"scopes":["boards:write"]},{"method":"PATCH","path":"/v1/families/{family_id}/boards/{board_id}/cards/{card_id}/checklists/{checklist_id}","auth":true,"scopes":["boards:write"]},{"method":"DELETE","path":"/v1/families/{family_id}/boards/{board_id}/cards/{card_id}/checklists/{checklist_id}","auth":true,"scopes":["boards:write"]},{"method":"POST","path":"/v1/families/{family_id}/boards/{board_id}/cards/{card_id}/checklists/{checklist_id}/items","auth":true,"scopes":["boards:write"]},{"method":"PATCH","path":"/v1/families/{family_id}/boards/{board_id}/cards/{card_id}/checklists/{checklist_id}/items/{item_id}","auth":true,"scopes":["boards:write"]},{"method":"DELETE","path":"/v1/families/{family_id}/boards/{board_id}/cards/{card_id}/checklists/{checklist_id}/items/{item_id}","auth":true,"scopes":["boards:write"]},{"method":"POST","path":"/v1/families/{family_id}/boards/{board_id}/cards","auth":true,"scopes":["boards:write"]},{"method":"PATCH","path":"/v1/families/{family_id}/boards/{board_id}/cards/{card_id}","auth":true,"scopes":["boards:write"]},{"method":"DELETE","path":"/v1/families/{family_id}/boards/{board_id}/cards/{card_id}","auth":true,"scopes":["boards:write"]},{"method":"POST","path":"/v1/families/{family_id}/boards/{board_id}/cards/{card_id}/comments","auth":true,"scopes":["boards:write"]},{"method":"GET","path":"/v1/families/{family_id}/boards/{board_id}/cards/{card_id}/comments","auth":true,"scopes":["boards:read"]},{"method":"PATCH","path":"/v1/families/{family_id}/boards/{board_id}/cards/{card_id}/comments/{comment_id}","auth":true,"scopes":["boards:write"]},{"method":"DELETE","path":"/v1/families/{family_id}/boards/{board_id}/cards/{card_id}/comments/{comment_id}","auth":true,"scopes":["boards:write"]},{"method":"POST","path":"/v1/families/{family_id}/lists","auth":true,"scopes":["lists:write"]},{"method":"POST","path":"/v1/families/{family_id}/recipes","auth":true,"scopes":["meals:write"],"note":"create a recipe: title, description, ingredients[], instructions[], prep/cook minutes, servings"},{"method":"GET","path":"/v1/families/{family_id}/recipes","auth":true,"scopes":["meals:read"]},{"method":"GET","path":"/v1/families/{family_id}/recipes/{recipe_id}","auth":true,"scopes":["meals:read"]},{"method":"PATCH","path":"/v1/families/{family_id}/recipes/{recipe_id}","auth":true,"scopes":["meals:write"]},{"method":"DELETE","path":"/v1/families/{family_id}/recipes/{recipe_id}","auth":true,"scopes":["meals:write"]},{"method":"POST","path":"/v1/families/{family_id}/recipes/{recipe_id}/add-to-list","auth":true,"scopes":["meals:read","lists:write"],"note":"add a recipe's ingredients as items to a grocery list; body: { list_id }"},{"method":"POST","path":"/v1/families/{family_id}/meal-ideas","auth":true,"scopes":["meals:write"],"note":"create a meal idea (a combinable component, not a full recipe); body: { name, role?: main|side|other }"},{"method":"GET","path":"/v1/families/{family_id}/meal-ideas","auth":true,"scopes":["meals:read"]},{"method":"PATCH","path":"/v1/families/{family_id}/meal-ideas/{idea_id}","auth":true,"scopes":["meals:write"],"note":"update a meal idea; body: { name?, role? }"},{"method":"DELETE","path":"/v1/families/{family_id}/meal-ideas/{idea_id}","auth":true,"scopes":["meals:write"]},{"method":"POST","path":"/v1/families/{family_id}/meal-plans","auth":true,"scopes":["meals:write"],"note":"create a weekly meal plan; body: { week_start: YYYY-MM-DD (Monday) }"},{"method":"GET","path":"/v1/families/{family_id}/meal-plans","auth":true,"scopes":["meals:read"]},{"method":"GET","path":"/v1/families/{family_id}/meal-plans/{plan_id}","auth":true,"scopes":["meals:read"],"note":"includes entries: day 0-6 (Monday=0), meal_type breakfast/lunch/dinner; each entry has items[] (kind recipe|idea|text, with recipe_title / idea_name+idea_role resolved) plus legacy recipe_id/notes"},{"method":"DELETE","path":"/v1/families/{family_id}/meal-plans/{plan_id}","auth":true,"scopes":["meals:write"]},{"method":"POST","path":"/v1/families/{family_id}/meal-plans/{plan_id}/entries","auth":true,"scopes":["meals:write"],"note":"set a meal slot to a single recipe/note; body: { day, meal_type, recipe_id?, notes? }; upserts the (day, meal_type) cell and replaces its items"},{"method":"POST","path":"/v1/families/{family_id}/meal-plans/{plan_id}/items","auth":true,"scopes":["meals:write"],"note":"append one item to a meal slot (cells hold multiple items); body: { day, meal_type, kind: recipe|idea|text, recipe_id?|idea_id?|text? }"},{"method":"DELETE","path":"/v1/families/{family_id}/meal-plans/{plan_id}/items/{item_id}","auth":true,"scopes":["meals:write"],"note":"remove one item from a meal slot"},{"method":"POST","path":"/v1/families/{family_id}/lists/import","auth":true,"scopes":["lists:write"],"note":"create a list from pasted markdown/plain text; headings/bare headers become sections, ✓/☐ markers set done state; {dry_run:true} returns the parse plan (sections, counts, warnings) and writes nothing; {list_id} appends, matching sections by name"},{"method":"GET","path":"/v1/families/{family_id}/lists","auth":true,"scopes":["lists:read"]},{"method":"POST","path":"/v1/families/{family_id}/chores","auth":true,"scopes":["chores:write"],"note":"create a chore list (e.g. Morning routine)"},{"method":"GET","path":"/v1/families/{family_id}/chores","auth":true,"scopes":["chores:read"]},{"method":"GET","path":"/v1/families/{family_id}/chores/{list_id}","auth":true,"scopes":["chores:read"],"note":"list with items and today's completions"},{"method":"PUT","path":"/v1/families/{family_id}/chores/{list_id}","auth":true,"scopes":["chores:write"],"note":"rename the chore list"},{"method":"DELETE","path":"/v1/families/{family_id}/chores/{list_id}","auth":true,"scopes":["chores:write"]},{"method":"POST","path":"/v1/families/{family_id}/chores/{list_id}/items","auth":true,"scopes":["chores:write"],"note":"add a chore item; optional assignee_person_id"},{"method":"PUT","path":"/v1/families/{family_id}/chores/{list_id}/items/{item_id}","auth":true,"scopes":["chores:write"]},{"method":"DELETE","path":"/v1/families/{family_id}/chores/{list_id}/items/{item_id}","auth":true,"scopes":["chores:write"]},{"method":"POST","path":"/v1/families/{family_id}/chores/{list_id}/items/{item_id}/complete","auth":true,"scopes":["chores:write"],"note":"mark done for today; optional person_id (defaults to caller)"},{"method":"POST","path":"/v1/families/{family_id}/chores/{list_id}/items/{item_id}/uncomplete","auth":true,"scopes":["chores:write"],"note":"remove today's completion"},{"method":"GET","path":"/v1/families/{family_id}/chores/{list_id}/streaks","auth":true,"scopes":["chores:read"],"note":"current consecutive-day streak per person per item"},{"method":"GET","path":"/v1/families/{family_id}/lists/{list_id}","auth":true,"scopes":["lists:read"]},{"method":"PATCH","path":"/v1/families/{family_id}/lists/{list_id}","auth":true,"scopes":["lists:write"],"note":"rename; also toggles ordered/favorite/archived"},{"method":"DELETE","path":"/v1/families/{family_id}/lists/{list_id}","auth":true,"scopes":["lists:write"],"note":"tombstones the list and descendants; retained rows are hidden from reads for privacy-safe restore/retention"},{"method":"GET","path":"/v1/families/{family_id}/lists/{list_id}/sections","auth":true,"scopes":["lists:read"],"note":"paged, audience-filtered section collection"},{"method":"POST","path":"/v1/families/{family_id}/lists/{list_id}/sections","auth":true,"scopes":["lists:write"],"note":"create a section with title and optional audience"},{"method":"PATCH","path":"/v1/families/{family_id}/lists/{list_id}/sections/{section_id}","auth":true,"scopes":["lists:write"]},{"method":"DELETE","path":"/v1/families/{family_id}/lists/{list_id}/sections/{section_id}","auth":true,"scopes":["lists:write"],"note":"delete a section; items remain and become unsectioned"},{"method":"POST","path":"/v1/families/{family_id}/lists/{list_id}/items","auth":true,"scopes":["lists:write"],"note":"text plus optional parent_item_id, section_id, priority, due_at, notes, recurrence, reminder_minutes, labels, assignee_agent_id or assignee_user_id (a family member; naming one clears the other), and audience"},{"method":"POST","path":"/v1/families/{family_id}/lists/{list_id}/items/reorder","auth":true,"scopes":["lists:write"],"note":"item_ids in order, or item_id + position"},{"method":"PATCH","path":"/v1/families/{family_id}/lists/{list_id}/items/{item_id}","auth":true,"scopes":["lists:write"],"note":"edit text/done/assignee, parent_item_id, section_id, priority, due_at, notes, recurrence, reminder_minutes, labels, or audience"},{"method":"DELETE","path":"/v1/families/{family_id}/lists/{list_id}/items/{item_id}","auth":true,"scopes":["lists:write"],"note":"tombstones the item and descendants; response does not reveal hidden descendants"},{"method":"POST","path":"/v1/families/{family_id}/calendars","auth":true,"scopes":["calendar:write"]},{"method":"GET","path":"/v1/families/{family_id}/calendars","auth":true,"scopes":["calendar:read"]},{"method":"GET","path":"/v1/families/{family_id}/calendars/{calendar_id}","auth":true,"scopes":["calendar:read"]},{"method":"PATCH","path":"/v1/families/{family_id}/calendars/{calendar_id}","auth":true,"scopes":["calendar:write"]},{"method":"DELETE","path":"/v1/families/{family_id}/calendars/{calendar_id}","auth":true,"scopes":["calendar:write"]},{"method":"GET","path":"/v1/families/{family_id}/calendars/{calendar_id}/ics","auth":false,"note":"public ICS feed; ?token=<feed_token> is the credential"},{"method":"GET","path":"/v1/families/{family_id}/calendar-feeds/{feed_id}.ics","auth":false,"note":"personal ICS feed; ?token=<one-time personal feed token> is the credential; current family membership and audiences are re-evaluated per request"},{"method":"POST","path":"/v1/families/{family_id}/calendars/{calendar_id}/ics/rotate","auth":true,"scopes":["admin","calendar:write"],"note":"replace the public ICS feed token; previous URL stops working"},{"method":"POST","path":"/v1/families/{family_id}/calendars/{calendar_id}/events","auth":true,"scopes":["calendar:write"],"note":"calendar_id '-' uses/creates the default Family calendar"},{"method":"GET","path":"/v1/families/{family_id}/calendars/{calendar_id}/events","auth":true,"scopes":["calendar:read"],"note":"?from=&to= ISO timestamps; recurring events expanded"},{"method":"GET","path":"/v1/families/{family_id}/calendars/{calendar_id}/events/{event_id}","auth":true,"scopes":["calendar:read"]},{"method":"PATCH","path":"/v1/families/{family_id}/calendars/{calendar_id}/events/{event_id}","auth":true,"scopes":["calendar:write"]},{"method":"DELETE","path":"/v1/families/{family_id}/calendars/{calendar_id}/events/{event_id}","auth":true,"scopes":["calendar:write"]},{"method":"GET","path":"/v1/families/{family_id}/events/upcoming","auth":true,"scopes":["calendar:read"],"note":"family-wide upcoming feed (?days=14)"},{"method":"POST","path":"/v1/families/{family_id}/calendars/{calendar_id}/events/{event_id}/attendees","auth":true,"scopes":["calendar:write"]},{"method":"PATCH","path":"/v1/families/{family_id}/calendars/{calendar_id}/events/{event_id}/attendees/{attendee_id}","auth":true,"scopes":["calendar:write"]},{"method":"DELETE","path":"/v1/families/{family_id}/calendars/{calendar_id}/events/{event_id}/attendees/{attendee_id}","auth":true,"scopes":["calendar:write"]},{"method":"POST","path":"/v1/families/{family_id}/calendars/{calendar_id}/events/{event_id}/reminders","auth":true,"scopes":["calendar:write"]},{"method":"DELETE","path":"/v1/families/{family_id}/calendars/{calendar_id}/events/{event_id}/reminders/{reminder_id}","auth":true,"scopes":["calendar:write"]},{"method":"POST","path":"/v1/families/{family_id}/calendars/{calendar_id}/events/{event_id}/duplicate","auth":true,"scopes":["calendar:write"]},{"method":"POST","path":"/v1/families/{family_id}/calendars/{calendar_id}/subscriptions","auth":true,"scopes":["calendar:write"],"note":"mirror an external ICS feed URL"},{"method":"GET","path":"/v1/families/{family_id}/calendars/{calendar_id}/subscriptions","auth":true,"scopes":["calendar:read"]},{"method":"DELETE","path":"/v1/families/{family_id}/calendars/{calendar_id}/subscriptions/{subscription_id}","auth":true,"scopes":["calendar:write"]},{"method":"POST","path":"/v1/families/{family_id}/calendars/{calendar_id}/subscriptions/{subscription_id}/sync","auth":true,"scopes":["calendar:write"]},{"method":"POST","path":"/v1/families/{family_id}/calendars/{calendar_id}/import-ics","auth":true,"scopes":["calendar:write"],"note":"{ics} one-time import into this calendar; dedupes on uid / uid#recurrence-id within the calendar; returns {imported, updated, skipped, updated_or_skipped, failed, total, truncated}"},{"method":"GET","path":"/v1/families/{family_id}/calendars/{calendar_id}/export-ics","auth":true,"scopes":["calendar:read"],"note":"authenticated download of the full calendar as .ics — all events including past ones (unlike the tokenized publish feed)"},{"method":"GET","path":"/v1/families/{family_id}/links","auth":true,"note":"?from_type=note|event|list|card&from_id=; returns {links, backlinks} with audience-aware titles; card endpoints carry board_id, event endpoints carry calendar_id"},{"method":"POST","path":"/v1/families/{family_id}/links","auth":true,"note":"{from_type, from_id, to_type, to_id}; requires write scope of the from_type module"},{"method":"DELETE","path":"/v1/families/{family_id}/links/{link_id}","auth":true,"note":"requires write scope of the link's from_type module"},{"method":"POST","path":"/v1/families/{family_id}/kb","auth":true,"scopes":["kb:write"],"note":"accepts folder_id, tags[], pinned, archived"},{"method":"GET","path":"/v1/families/{family_id}/kb","auth":true,"scopes":["kb:read"],"note":"?q, ?folder_id (id|root), ?tag, ?trashed=1; entries carry folder_id, tags[], pinned, archived"},{"method":"POST","path":"/v1/families/{family_id}/kb/import","auth":true,"scopes":["kb:write"],"note":"batch-create entries: {folder_id, entries:[{title, body}]} (max 100); per-entry results + {created, failed} summary; a bad entry fails alone"},{"method":"GET","path":"/v1/families/{family_id}/kb/{entry_id}","auth":true,"scopes":["kb:read"]},{"method":"PATCH","path":"/v1/families/{family_id}/kb/{entry_id}","auth":true,"scopes":["kb:write"],"note":"title/body/folder_id/tags/pinned/archived; title/body edits snapshot a version"},{"method":"DELETE","path":"/v1/families/{family_id}/kb/{entry_id}","auth":true,"scopes":["kb:write"],"note":"soft-delete (trash)"},{"method":"POST","path":"/v1/families/{family_id}/kb/{entry_id}/restore","auth":true,"scopes":["kb:write"]},{"method":"DELETE","path":"/v1/families/{family_id}/kb/{entry_id}/purge","auth":true,"scopes":["kb:write"],"note":"permanent delete"},{"method":"GET","path":"/v1/families/{family_id}/kb/folders","auth":true,"scopes":["kb:read"]},{"method":"POST","path":"/v1/families/{family_id}/kb/folders","auth":true,"scopes":["kb:write"]},{"method":"PATCH","path":"/v1/families/{family_id}/kb/folders/{folder_id}","auth":true,"scopes":["kb:write"]},{"method":"DELETE","path":"/v1/families/{family_id}/kb/folders/{folder_id}","auth":true,"scopes":["kb:write"],"note":"entries move to Unfiled"},{"method":"GET","path":"/v1/families/{family_id}/kb/tags","auth":true,"scopes":["kb:read"]},{"method":"POST","path":"/v1/families/{family_id}/kb/tags","auth":true,"scopes":["kb:write"]},{"method":"DELETE","path":"/v1/families/{family_id}/kb/tags/{tag_id}","auth":true,"scopes":["kb:write"]},{"method":"GET","path":"/v1/families/{family_id}/kb/{entry_id}/versions","auth":true,"scopes":["kb:read"]},{"method":"GET","path":"/v1/families/{family_id}/kb/{entry_id}/comments","auth":true,"scopes":["kb:read"]},{"method":"POST","path":"/v1/families/{family_id}/kb/{entry_id}/comments","auth":true,"scopes":["kb:write"]},{"method":"DELETE","path":"/v1/families/{family_id}/kb/{entry_id}/comments/{comment_id}","auth":true,"scopes":["kb:write"]},{"method":"GET","path":"/v1/families/{family_id}/kb/templates","auth":true,"scopes":["kb:read"]},{"method":"POST","path":"/v1/families/{family_id}/kb/templates","auth":true,"scopes":["kb:write"]},{"method":"PATCH","path":"/v1/families/{family_id}/kb/templates/{template_id}","auth":true,"scopes":["kb:write"]},{"method":"DELETE","path":"/v1/families/{family_id}/kb/templates/{template_id}","auth":true,"scopes":["kb:write"]},{"method":"POST","path":"/v1/families/{family_id}/files","auth":true,"scopes":["files:write"],"note":"multipart/form-data (field 'file'); optional folder_id field; 25MB max"},{"method":"GET","path":"/v1/families/{family_id}/files","auth":true,"scopes":["files:read"],"note":"?folder_id={id|root}&trashed=1&q=&limit="},{"method":"GET","path":"/v1/families/{family_id}/files/{file_id}","auth":true,"scopes":["files:read"]},{"method":"GET","path":"/v1/families/{family_id}/files/{file_id}/download","auth":true,"scopes":["files:read"]},{"method":"PATCH","path":"/v1/families/{family_id}/files/{file_id}","auth":true,"scopes":["files:write"],"note":"rename / move {filename?, folder_id? (null = root)}"},{"method":"POST","path":"/v1/families/{family_id}/files/{file_id}/trash","auth":true,"scopes":["files:write"],"note":"soft-delete (move to trash)"},{"method":"POST","path":"/v1/families/{family_id}/files/{file_id}/restore","auth":true,"scopes":["files:write"]},{"method":"POST","path":"/v1/families/{family_id}/trash/empty","auth":true,"scopes":["files:write"],"note":"permanently delete all trashed files"},{"method":"DELETE","path":"/v1/families/{family_id}/files/{file_id}","auth":true,"scopes":["files:write"],"note":"hard delete (bytes removed)"},{"method":"GET","path":"/v1/families/{family_id}/file-folders","auth":true,"scopes":["files:read"]},{"method":"POST","path":"/v1/families/{family_id}/file-folders","auth":true,"scopes":["files:write"],"note":"{name, parent_id?}"},{"method":"PATCH","path":"/v1/families/{family_id}/file-folders/{folder_id}","auth":true,"scopes":["files:write"],"note":"{name?, parent_id? (null = root)}"},{"method":"DELETE","path":"/v1/families/{family_id}/file-folders/{folder_id}","auth":true,"scopes":["files:write"],"note":"deletes the folder tree; files move to root"},{"method":"GET","path":"/v1/families/{family_id}/search","auth":true,"scopes":[],"note":"q required; each result type gated by its own read scope"},{"method":"POST","path":"/v1/families/{family_id}/webhooks","auth":true,"scopes":["admin"]},{"method":"GET","path":"/v1/families/{family_id}/webhooks","auth":true,"scopes":["admin"]},{"method":"DELETE","path":"/v1/families/{family_id}/webhooks/{webhook_id}","auth":true,"scopes":["admin"]},{"method":"POST","path":"/v1/families/{family_id}/webhooks/{webhook_id}/test","auth":true,"scopes":["admin"]},{"method":"POST","path":"/v1/families/{family_id}/connectors","auth":true,"scopes":["connectors:manage"],"note":"register a shared MCP server (URL + auth, encrypted); tests it immediately"},{"method":"GET","path":"/v1/families/{family_id}/connectors","auth":true,"scopes":[],"note":"list connections without secrets; each row says whether you may use it"},{"method":"GET","path":"/v1/families/{family_id}/connectors/{connector_id}","auth":true,"scopes":[],"note":"detail + cached tool list; grants included for connectors:manage"},{"method":"PATCH","path":"/v1/families/{family_id}/connectors/{connector_id}","auth":true,"scopes":["connectors:manage"]},{"method":"DELETE","path":"/v1/families/{family_id}/connectors/{connector_id}","auth":true,"scopes":["connectors:manage"]},{"method":"POST","path":"/v1/families/{family_id}/connectors/{connector_id}/test","auth":true,"scopes":["connectors:manage"],"note":"initialize + tools/list; updates status"},{"method":"GET","path":"/v1/families/{family_id}/connectors/{connector_id}/tools","auth":true,"scopes":["connectors:use"],"note":"tool list for a connection you may use"},{"method":"POST","path":"/v1/families/{family_id}/connectors/{connector_id}/call","auth":true,"scopes":["connectors:use"],"note":"invoke a tool through the hub; the hub forwards with the stored credentials"},{"method":"POST","path":"/v1/families/{family_id}/connectors/{connector_id}/grants","auth":true,"scopes":["connectors:manage"],"note":"set the per-agent allowlist {agent_ids}"},{"method":"POST","path":"/v1/families/{family_id}/connectors/{connector_id}/reveal","auth":true,"scopes":["connectors:manage"],"note":"decrypt the stored credentials (audit-logged)"},{"method":"PUT","path":"/v1/families/{family_id}/smart-home/connection","auth":true,"scopes":["smart_home:manage"],"note":"connect Home Assistant {base_url, token}; token encrypted at rest, connection tested, devices synced"},{"method":"GET","path":"/v1/families/{family_id}/smart-home/connection","auth":true,"scopes":["smart_home:manage"],"note":"connection status (never the token)"},{"method":"DELETE","path":"/v1/families/{family_id}/smart-home/connection","auth":true,"scopes":["smart_home:manage"],"note":"disconnect and drop the cached device list"},{"method":"POST","path":"/v1/families/{family_id}/smart-home/sync","auth":true,"scopes":["smart_home:manage"],"note":"re-pull the device inventory from Home Assistant"},{"method":"GET","path":"/v1/families/{family_id}/smart-home/devices","auth":true,"scopes":["smart_home:use"],"note":"?domain=; only devices your role may see; each row says whether you may control it"},{"method":"PATCH","path":"/v1/families/{family_id}/smart-home/devices/{entity_id}","auth":true,"scopes":["smart_home:manage"],"note":"set per-device access {access: everyone|adults|hidden} and/or allowed_services (subset of the domain's services; null restores default; [] = view-only)"},{"method":"GET","path":"/v1/families/{family_id}/smart-home/devices/{entity_id}/grants","auth":true,"scopes":["smart_home:manage"],"note":"list per-member/per-agent grants for one device"},{"method":"PUT","path":"/v1/families/{family_id}/smart-home/devices/{entity_id}/grants","auth":true,"scopes":["smart_home:manage"],"note":"upsert a grant {grantee_kind: user|agent, grantee_id, can_view, can_control}; replaces the access level for that grantee"},{"method":"DELETE","path":"/v1/families/{family_id}/smart-home/devices/{entity_id}/grants/{grantee_kind}/{grantee_id}","auth":true,"scopes":["smart_home:manage"],"note":"remove a grant"},{"method":"POST","path":"/v1/families/{family_id}/smart-home/control","auth":true,"scopes":["smart_home:use"],"note":"{entity_id, service, service_data?}; policy-checked and audit-logged"},{"method":"GET","path":"/v1/families/{family_id}/smart-home/logbook","auth":true,"scopes":["smart_home:use"],"note":"?hours= (1-168, default 24); human-readable recent activity, filtered to devices you may see"},{"method":"GET","path":"/v1/families/{family_id}/smart-home/devices/{entity_id}/history","auth":true,"scopes":["smart_home:use"],"note":"?hours= (1-168, default 24); compact state history points plus min/max/avg stats for numeric sensors"},{"method":"POST","path":"/v1/families/{family_id}/smart-home/automations","auth":true,"scopes":["smart_home:manage"],"note":"create a native Home Assistant automation {name, description?, triggers[], conditions?[], actions[]}"},{"method":"DELETE","path":"/v1/families/{family_id}/smart-home/automations/{entity_id}","auth":true,"scopes":["smart_home:manage"],"note":"delete a config-managed automation"},{"method":"GET","path":"/v1/families/{family_id}/smart-home/members","auth":true,"scopes":["smart_home:manage"],"note":"family humans and their smart-home roles (adult|kid), plus the family's agents (grantee picker for per-device grants)"},{"method":"PUT","path":"/v1/families/{family_id}/smart-home/members/{user_id}","auth":true,"scopes":["smart_home:manage"],"note":"set a member's smart-home role {role}"},{"method":"POST","path":"/v1/families/{family_id}/secrets","auth":true,"scopes":["vault:manage"],"note":"store a shared secret (encrypted); family members can add entries, agents need vault:manage"},{"method":"GET","path":"/v1/families/{family_id}/secrets","auth":true,"scopes":["vault:read"],"note":"names and notes only — never values"},{"method":"GET","path":"/v1/families/{family_id}/secrets/{secret_id}/value","auth":true,"scopes":["vault:read"],"note":"decrypt one secret (audit-logged); people reveal as a family admin, the entry's creator, or when explicitly in the entry's audience"},{"method":"PATCH","path":"/v1/families/{family_id}/secrets/{secret_id}","auth":true,"scopes":["vault:manage"]},{"method":"DELETE","path":"/v1/families/{family_id}/secrets/{secret_id}","auth":true,"scopes":["vault:manage"]},{"method":"POST","path":"/v1/personal/items","auth":true,"scopes":["personal:write"],"note":"create a personal note or memory {kind, title?, body}"},{"method":"GET","path":"/v1/personal/items","auth":true,"scopes":["personal:read"],"note":"?q=&kind= search; each item carries hidden_agent_ids"},{"method":"GET","path":"/v1/personal/items/{item_id}","auth":true,"scopes":["personal:read"]},{"method":"PATCH","path":"/v1/personal/items/{item_id}","auth":true,"scopes":["personal:write"]},{"method":"DELETE","path":"/v1/personal/items/{item_id}","auth":true,"scopes":["personal:write"]},{"method":"POST","path":"/v1/personal/calendar-feeds","auth":true,"scopes":[],"note":"human session only; mint a human-owned ICS feed token; the raw token is returned once"},{"method":"GET","path":"/v1/personal/calendar-feeds","auth":true,"scopes":["personal:read"],"note":"paginated feed ids and revocation state (?limit=&cursor=); raw tokens are never returned"},{"method":"DELETE","path":"/v1/personal/calendar-feeds/{feed_id}","auth":true,"scopes":[],"note":"human session only; revoke one of the caller's personal ICS feeds"},{"method":"POST","path":"/v1/personal/items/{item_id}/hidden","auth":true,"scopes":["personal:write"],"note":"per-item opt-out {agent_id}; hidden agents get 404"},{"method":"DELETE","path":"/v1/personal/items/{item_id}/hidden/{agent_id}","auth":true,"scopes":["personal:write"]},{"method":"POST","path":"/v1/personal/items/{item_id}/copy-to-family","auth":true,"note":"deprecated: returns 409 review_required; create and review a Personal share draft instead"},{"method":"POST","path":"/v1/personal/share-drafts","auth":true,"scopes":["personal:write"],"note":"propose a frozen Personal item/list share; agents may suggest but only the human owner may publish"},{"method":"GET","path":"/v1/personal/share-drafts","auth":true,"scopes":["personal:read"],"note":"list the owner's Personal share drafts; hidden source items remain hidden from agents"},{"method":"GET","path":"/v1/personal/share-drafts/{draft_id}","auth":true,"scopes":["personal:read"]},{"method":"PATCH","path":"/v1/personal/share-drafts/{draft_id}","auth":true,"scopes":["personal:write"],"note":"edit the frozen proposed title/body/list snapshot or audience while pending"},{"method":"DELETE","path":"/v1/personal/share-drafts/{draft_id}","auth":true,"scopes":["personal:write"],"note":"discard a pending draft; publication is human-only"},{"method":"POST","path":"/v1/personal/share-drafts/{draft_id}/publish","auth":true,"note":"human session only; family_id is REQUIRED (?family_id= or body) — no default-family fallback; atomically publishes the reviewed copy into that family and marks the draft published; response names family_id"},{"method":"GET","path":"/v1/personal/audit","auth":true,"scopes":["personal:read"],"note":"?limit=; personal events only (user_id set, family_id NULL)"},{"method":"GET","path":"/v1/personal/lists","auth":true,"scopes":["personal:read"],"note":"personal lists (visibility=personal, family_id NULL, owned by the caller)"},{"method":"POST","path":"/v1/personal/lists","auth":true,"scopes":["personal:write"],"note":"{title, ordered?}; the list is personal at creation and carries no family (family_id NULL)"},{"method":"GET","path":"/v1/personal/lists/{list_id}","auth":true,"scopes":["personal:read"],"note":"returns {list, items}"},{"method":"PATCH","path":"/v1/personal/lists/{list_id}","auth":true,"scopes":["personal:write"],"note":"rename; also toggles ordered/favorite/archived"},{"method":"DELETE","path":"/v1/personal/lists/{list_id}","auth":true,"scopes":["personal:write"]},{"method":"POST","path":"/v1/personal/lists/{list_id}/share-to-family","auth":true,"note":"deprecated: returns 409 review_required; create and review a Personal share draft instead"},{"method":"POST","path":"/v1/personal/lists/{list_id}/items","auth":true,"scopes":["personal:write"],"note":"{text}"},{"method":"POST","path":"/v1/personal/lists/{list_id}/items/reorder","auth":true,"scopes":["personal:write"],"note":"item_ids in order, or item_id + position"},{"method":"PATCH","path":"/v1/personal/lists/{list_id}/items/{item_id}","auth":true,"scopes":["personal:write"],"note":"{text?, done?}"},{"method":"DELETE","path":"/v1/personal/lists/{list_id}/items/{item_id}","auth":true,"scopes":["personal:write"]},{"method":"PATCH","path":"/v1/agents/{agent_id}","auth":true,"note":"owner-only: human session flips one of their own agents' personal_access (0|1); writes personal.access_changed"}]}