{"openapi":"3.1.0","info":{"title":"Historis API","version":"0.1.0","summary":"Public REST + MCP surface for the Historis operational memory.","description":"Historis keeps a shared, event-based timeline of what happened, linked to the right people. This document describes the public REST API and the MCP transport. Most REST endpoints require a Supabase session JWT (a signed-in person) and are rate-limited per identity; a Supabase OAuth 2.1 access token carries a client_id claim, belongs on the MCP transport, and is refused on the REST gates with 403 assistant_token_rejected (HIS-926). Discover the MCP server at /.well-known/mcp and the OAuth authorization server at /.well-known/oauth-authorization-server.","contact":{"name":"Historis","url":"https://historis.app"},"license":{"name":"Proprietary"}},"servers":[{"url":"https://api.historis.app","description":"Historis REST API"},{"url":"https://historis.app","description":"Marketing host (proxies /api/* to the REST API)"}],"tags":[{"name":"Auth","description":"Authentication and session management"},{"name":"Persons","description":"Contacts (clients, suppliers, partners)"},{"name":"Events","description":"Timeline events and their links"},{"name":"Search","description":"Full-text search"},{"name":"Tags","description":"Tag-based organization"},{"name":"Organization","description":"Organization, members, invitations"},{"name":"Teams","description":"Teams and team membership"},{"name":"Rules","description":"Markdown automation rules for agents"},{"name":"Knowledge","description":"Knowledge notes: faceted exploration and saved views"},{"name":"Dashboard","description":"Dashboard and usage insights"},{"name":"Billing","description":"Stripe subscriptions and billing"},{"name":"Webhooks","description":"Inbound webhook endpoints"},{"name":"Integrations","description":"Connected AI clients and permissions"},{"name":"Onboarding","description":"Onboarding checklist"},{"name":"MCP","description":"Model Context Protocol transport"},{"name":"OAuth","description":"OAuth consent proxy"},{"name":"Health","description":"Health checks"},{"name":"Discovery","description":"Self-describing discovery documents"}],"security":[{"bearerAuth":[]}],"paths":{"/api/health":{"get":{"tags":["Health"],"summary":"Liveness + schema health","responses":{"200":{"description":"Service status","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","enum":["ok","degraded"]},"timestamp":{"type":"string","format":"date-time"}},"required":["status"]}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"}},"security":[]}},"/api/auth/signup":{"post":{"tags":["Auth"],"summary":"Create an account","responses":{"200":{"description":"Session created","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"}},"security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Credentials"}}}}}},"/api/auth/login":{"post":{"tags":["Auth"],"summary":"Log in, returns a session (JWT)","responses":{"200":{"description":"Session","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"}},"security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Credentials"}}}}}},"/api/auth/logout":{"post":{"tags":["Auth"],"summary":"Log out the current session","responses":{"200":{"description":"Logged out","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"}}}},"/api/auth/session":{"get":{"tags":["Auth"],"summary":"Current session + user role","responses":{"200":{"description":"Session details","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"}}}},"/api/auth/reset-password":{"post":{"tags":["Auth"],"summary":"Send a password-reset email","responses":{"200":{"description":"Email queued","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"}},"security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"email":{"type":"string","format":"email"}},"required":["email"]}}}}}},"/api/auth/change-password":{"post":{"tags":["Auth"],"summary":"Change the current password","responses":{"200":{"description":"Password changed","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"}}}},"/api/auth/profile":{"patch":{"tags":["Auth"],"summary":"Update the user profile (name)","responses":{"200":{"description":"Updated profile","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string"}}}}}}}},"/api/auth/preferences":{"get":{"tags":["Auth"],"summary":"Read user preferences (locale, timezone, density, theme)","responses":{"200":{"description":"Preferences","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"}}},"patch":{"tags":["Auth"],"summary":"Update user preferences","responses":{"200":{"description":"Updated preferences","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}}}},"/api/auth/account":{"delete":{"tags":["Auth"],"summary":"Delete the current account","responses":{"200":{"description":"Account deleted","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"}}}},"/api/auth/refresh":{"post":{"tags":["Auth"],"summary":"Rotate the refresh token","responses":{"200":{"description":"New session","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"}},"security":[]}},"/api/bootstrap":{"post":{"tags":["Organization"],"summary":"Create the default organization on first login","responses":{"200":{"description":"Existing organization","content":{"application/json":{"schema":{"type":"object"}}}},"201":{"description":"Organization created","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"}}}},"/api/persons":{"get":{"tags":["Persons"],"summary":"List persons (paginated, filterable by tags/search)","responses":{"200":{"description":"Page of persons","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"}},"parameters":[{"$ref":"#/components/parameters/SearchQuery"},{"$ref":"#/components/parameters/TagsQuery"},{"$ref":"#/components/parameters/LimitQuery"},{"$ref":"#/components/parameters/OffsetQuery"}]},"post":{"tags":["Persons"],"summary":"Create a person","responses":{"201":{"description":"Created person","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"409":{"$ref":"#/components/responses/DuplicateEmail"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PersonInput"}}}}}},"/api/persons/{personId}":{"parameters":[{"name":"personId","in":"path","required":true,"schema":{"type":"string"}}],"get":{"tags":["Persons"],"summary":"Get a person and their events","responses":{"200":{"description":"Person","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"}}},"patch":{"tags":["Persons"],"summary":"Update a person","responses":{"200":{"description":"Updated person","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/DuplicateEmail"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PersonInput"}}}}},"delete":{"tags":["Persons"],"summary":"Delete a person","responses":{"204":{"description":"Deleted"},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"}}}},"/api/persons/{personId}/relations":{"parameters":[{"name":"personId","in":"path","required":true,"schema":{"type":"string"}}],"post":{"tags":["Persons"],"summary":"Create a contact-to-contact relation from this person","responses":{"201":{"description":"Relation created","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"relatedPersonId":{"type":"string","format":"uuid"},"type":{"type":"string"}},"required":["relatedPersonId"]}}}}}},"/api/persons/{personId}/relations/{relatedPersonId}":{"parameters":[{"name":"personId","in":"path","required":true,"schema":{"type":"string"}},{"name":"relatedPersonId","in":"path","required":true,"schema":{"type":"string"}}],"delete":{"tags":["Persons"],"summary":"Delete a contact-to-contact relation","responses":{"204":{"description":"Deleted"},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"}}}},"/api/events":{"get":{"tags":["Events"],"summary":"List events (paginated, filterable)","responses":{"200":{"description":"Page of events","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"}},"parameters":[{"$ref":"#/components/parameters/SearchQuery"},{"$ref":"#/components/parameters/TagsQuery"},{"$ref":"#/components/parameters/LimitQuery"},{"$ref":"#/components/parameters/OffsetQuery"}]},"post":{"tags":["Events"],"summary":"Create an event","responses":{"201":{"description":"Created event","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EventInput"}}}}}},"/api/events/{eventId}":{"parameters":[{"name":"eventId","in":"path","required":true,"schema":{"type":"string"}}],"get":{"tags":["Events"],"summary":"Get an event","responses":{"200":{"description":"Event","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"}}},"patch":{"tags":["Events"],"summary":"Update an event","responses":{"200":{"description":"Updated event","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EventInput"}}}}},"delete":{"tags":["Events"],"summary":"Delete an event","responses":{"204":{"description":"Deleted"},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"}}}},"/api/events/{eventId}/persons":{"parameters":[{"name":"eventId","in":"path","required":true,"schema":{"type":"string"}}],"post":{"tags":["Events"],"summary":"Link a person to an event","responses":{"200":{"description":"Linked","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"personId":{"type":"string","format":"uuid"}},"required":["personId"]}}}}}},"/api/events/{eventId}/persons/{personId}":{"parameters":[{"name":"eventId","in":"path","required":true,"schema":{"type":"string"}},{"name":"personId","in":"path","required":true,"schema":{"type":"string"}}],"delete":{"tags":["Events"],"summary":"Unlink a person from an event","responses":{"204":{"description":"Unlinked"},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"}}}},"/api/events/{eventId}/related":{"parameters":[{"name":"eventId","in":"path","required":true,"schema":{"type":"string"}}],"post":{"tags":["Events"],"summary":"Link an event to another event","responses":{"200":{"description":"Linked","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"relatedEventId":{"type":"string","format":"uuid"}},"required":["relatedEventId"]}}}}}},"/api/events/{eventId}/related/{relatedEventId}":{"parameters":[{"name":"eventId","in":"path","required":true,"schema":{"type":"string"}},{"name":"relatedEventId","in":"path","required":true,"schema":{"type":"string"}}],"delete":{"tags":["Events"],"summary":"Unlink a related event","responses":{"204":{"description":"Unlinked"},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"}}}},"/api/events/{parentId}/children":{"parameters":[{"name":"parentId","in":"path","required":true,"schema":{"type":"string"}}],"get":{"tags":["Events"],"summary":"List an event's child events (thread)","responses":{"200":{"description":"Child events","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"}}}},"/api/search":{"get":{"tags":["Search"],"summary":"Full-text search across events and persons","responses":{"200":{"description":"Search results","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"}},"parameters":[{"$ref":"#/components/parameters/SearchQuery"}]}},"/api/tags":{"get":{"tags":["Tags"],"summary":"List tags with counters","responses":{"200":{"description":"Tags","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"}}},"post":{"tags":["Tags"],"summary":"Create a tag","responses":{"201":{"description":"Created tag","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TagInput"}}}}}},"/api/tags/events":{"get":{"tags":["Tags"],"summary":"Tags used on events","responses":{"200":{"description":"Tags","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"}}}},"/api/tags/persons":{"get":{"tags":["Tags"],"summary":"Tags used on persons","responses":{"200":{"description":"Tags","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"}}}},"/api/tags/manage":{"get":{"tags":["Tags"],"summary":"Management list (all org tags incl. unused, with counts)","responses":{"200":{"description":"Tag management list","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"}},"parameters":[{"$ref":"#/components/parameters/SearchQuery"},{"$ref":"#/components/parameters/LimitQuery"},{"$ref":"#/components/parameters/OffsetQuery"}]}},"/api/tags/duplicates":{"get":{"tags":["Tags"],"summary":"Likely-duplicate tag pairs","responses":{"200":{"description":"Duplicate pairs","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"}}}},"/api/tags/followed":{"get":{"tags":["Tags"],"summary":"Tags the current user follows","responses":{"200":{"description":"Followed tags","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"}}}},"/api/tags/followed/{tagId}":{"parameters":[{"name":"tagId","in":"path","required":true,"schema":{"type":"string"}}],"put":{"tags":["Tags"],"summary":"Follow a tag","responses":{"200":{"description":"Followed","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"}}},"delete":{"tags":["Tags"],"summary":"Unfollow a tag","responses":{"204":{"description":"Unfollowed"},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"}}}},"/api/tags/{id}/impact":{"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"get":{"tags":["Tags"],"summary":"Org-wide impact preview for delete/merge dialogs","responses":{"200":{"description":"Impact","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"}}}},"/api/tags/{id}":{"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"patch":{"tags":["Tags"],"summary":"Update a tag description and/or name (owner-only rename)","responses":{"200":{"description":"Updated tag","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"409":{"$ref":"#/components/responses/Conflict"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TagInput"}}}}},"delete":{"tags":["Tags"],"summary":"Delete a tag","responses":{"204":{"description":"Deleted"},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"}}}},"/api/tags/merge":{"post":{"tags":["Tags"],"summary":"Merge one tag into another","responses":{"200":{"description":"Merged","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"fromSlug":{"type":"string"},"toSlug":{"type":"string"}},"required":["fromSlug","toSlug"]}}}}}},"/api/tags/keep-separate":{"get":{"tags":["Tags"],"summary":"List pairs marked \"keep separate\"","responses":{"200":{"description":"Pairs","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"}}},"post":{"tags":["Tags"],"summary":"Mark a pair as not duplicates","responses":{"200":{"description":"Marked","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TagPair"}}}}},"delete":{"tags":["Tags"],"summary":"Restore a dismissed pair","responses":{"200":{"description":"Restored","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TagPair"}}}}}},"/api/organization/members":{"get":{"tags":["Organization"],"summary":"List members","responses":{"200":{"description":"Members","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"}}}},"/api/organization/members/{userId}":{"parameters":[{"name":"userId","in":"path","required":true,"schema":{"type":"string"}}],"patch":{"tags":["Organization"],"summary":"Change a member's role (owner only)","responses":{"200":{"description":"Updated","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"role":{"type":"string","enum":["owner","member"]}},"required":["role"]}}}}},"delete":{"tags":["Organization"],"summary":"Remove a member (owner only)","responses":{"204":{"description":"Removed"},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"}}}},"/api/organization/invitations":{"get":{"tags":["Organization"],"summary":"List invitations (owner only)","responses":{"200":{"description":"Invitations","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"}}},"post":{"tags":["Organization"],"summary":"Create an invitation (owner only)","responses":{"201":{"description":"Invitation created","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"email":{"type":"string","format":"email"},"role":{"type":"string","enum":["owner","member"]}},"required":["email"]}}}}}},"/api/organization/invitations/{invitationId}":{"parameters":[{"name":"invitationId","in":"path","required":true,"schema":{"type":"string"}}],"delete":{"tags":["Organization"],"summary":"Cancel an invitation (owner only)","responses":{"204":{"description":"Cancelled"},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"}}}},"/api/organization/invitations/token/{token}":{"parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string"}}],"get":{"tags":["Organization"],"summary":"Public invitation details by token","responses":{"200":{"description":"Invitation","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"}},"security":[]}},"/api/organization/invitations/token/{token}/accept":{"parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string"}}],"post":{"tags":["Organization"],"summary":"Accept an invitation","responses":{"200":{"description":"Accepted","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"}}}},"/api/organization/leave":{"post":{"tags":["Organization"],"summary":"Leave the organization","responses":{"200":{"description":"Left","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"}}}},"/api/organization":{"delete":{"tags":["Organization"],"summary":"Delete the organization (owner only)","responses":{"200":{"description":"Deleted","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"}}}},"/api/organization/export":{"get":{"tags":["Organization"],"summary":"Export all organization data","responses":{"200":{"description":"Export","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"}}}},"/api/organization/info":{"get":{"tags":["Organization"],"summary":"Read organization info","responses":{"200":{"description":"Org info","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"}}},"patch":{"tags":["Organization"],"summary":"Update organization info","responses":{"200":{"description":"Updated","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}}}},"/api/organization/security":{"get":{"tags":["Organization"],"summary":"Read organization security settings (MFA, min visibility)","responses":{"200":{"description":"Security settings","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"}}},"patch":{"tags":["Organization"],"summary":"Update organization security settings (owner only)","responses":{"200":{"description":"Updated","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}}}},"/api/teams":{"get":{"tags":["Teams"],"summary":"List teams","responses":{"200":{"description":"Teams","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"}}},"post":{"tags":["Teams"],"summary":"Create a team","responses":{"201":{"description":"Created team","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string"}},"required":["name"]}}}}}},"/api/teams/{id}":{"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"patch":{"tags":["Teams"],"summary":"Update a team","responses":{"200":{"description":"Updated team","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}}},"delete":{"tags":["Teams"],"summary":"Delete a team","responses":{"204":{"description":"Deleted"},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"}}}},"/api/teams/{id}/members":{"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"get":{"tags":["Teams"],"summary":"List team members","responses":{"200":{"description":"Members","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"}}},"post":{"tags":["Teams"],"summary":"Add a member to a team","responses":{"200":{"description":"Added","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"userId":{"type":"string","format":"uuid"}},"required":["userId"]}}}}}},"/api/teams/{id}/members/{userId}":{"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"userId","in":"path","required":true,"schema":{"type":"string"}}],"put":{"tags":["Teams"],"summary":"Set a team member's role","responses":{"200":{"description":"Updated","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}}},"delete":{"tags":["Teams"],"summary":"Remove a member from a team","responses":{"204":{"description":"Removed"},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"}}}},"/api/rules":{"get":{"tags":["Rules"],"summary":"List rules","responses":{"200":{"description":"Rules","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"}}},"post":{"tags":["Rules"],"summary":"Create a rule","responses":{"201":{"description":"Created rule","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RuleInput"}}}}}},"/api/rules/{ruleId}":{"parameters":[{"name":"ruleId","in":"path","required":true,"schema":{"type":"string"}}],"get":{"tags":["Rules"],"summary":"Get a rule","responses":{"200":{"description":"Rule","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"}}},"patch":{"tags":["Rules"],"summary":"Update a rule","responses":{"200":{"description":"Updated rule","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RuleInput"}}}}},"delete":{"tags":["Rules"],"summary":"Delete a rule","responses":{"204":{"description":"Deleted"},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"}}}},"/api/knowledge":{"get":{"tags":["Knowledge"],"summary":"List knowledge notes","responses":{"200":{"description":"Notes and the exact total","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"}},"description":"Newest-updated first. Tag and person filters are AND (a note must carry every slug / link to every id). The three time windows are inclusive and independent: since/until on creation, updatedSince/updatedUntil on last modification, eventSince/eventUntil on the occurred_at of a linked event -- the date the note is about. Each bound accepts YYYY-MM-DD or a full ISO 8601 instant carrying Z or a numeric offset.","parameters":[{"name":"query","in":"query","required":false,"schema":{"type":"string","maxLength":500},"description":"Full-text query (French stemming, accent-insensitive)."},{"name":"status","in":"query","required":false,"schema":{"type":"string","enum":["active","archived","all"]},"description":"Note status (default active)."},{"name":"tags","in":"query","required":false,"schema":{"type":"string"},"description":"Comma-separated tag slugs, max 20. AND: a note must carry every one."},{"name":"personIds","in":"query","required":false,"schema":{"type":"string"},"description":"Comma-separated person ids, max 20. AND: a note must link to every one."},{"name":"since","in":"query","required":false,"schema":{"type":"string","format":"date-time"},"description":"Notes created at or after this instant. Accepts YYYY-MM-DD or a full ISO 8601 instant with Z or a numeric offset; inclusive."},{"name":"until","in":"query","required":false,"schema":{"type":"string","format":"date-time"},"description":"Notes created at or before this instant. Accepts YYYY-MM-DD or a full ISO 8601 instant with Z or a numeric offset; inclusive."},{"name":"updatedSince","in":"query","required":false,"schema":{"type":"string","format":"date-time"},"description":"Notes last modified at or after this instant. Accepts YYYY-MM-DD or a full ISO 8601 instant with Z or a numeric offset; inclusive."},{"name":"updatedUntil","in":"query","required":false,"schema":{"type":"string","format":"date-time"},"description":"Notes last modified at or before this instant. Accepts YYYY-MM-DD or a full ISO 8601 instant with Z or a numeric offset; inclusive."},{"name":"eventSince","in":"query","required":false,"schema":{"type":"string","format":"date-time"},"description":"Notes linked to an event that occurred at or after this instant (both event bounds apply to the same event). Accepts YYYY-MM-DD or a full ISO 8601 instant with Z or a numeric offset; inclusive."},{"name":"eventUntil","in":"query","required":false,"schema":{"type":"string","format":"date-time"},"description":"Notes linked to an event that occurred at or before this instant. Accepts YYYY-MM-DD or a full ISO 8601 instant with Z or a numeric offset; inclusive."},{"$ref":"#/components/parameters/LimitQuery"},{"$ref":"#/components/parameters/OffsetQuery"}]}},"/api/knowledge/facets":{"get":{"tags":["Knowledge"],"summary":"Facet counts for the current selection","responses":{"200":{"description":"Facet counts","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"}},"description":"Counts of contacts, tags and calendar months, each answering \"how many notes if I click this\". Tags and contacts are multi-select AND, so their buckets run over the SAME selection the list returns, the facet's own selected values included; the period bar is single-select, so its buckets run over that selection with its period bound cleared -- otherwise a bucket would predict a query the click does not run. clearedTotals is the same question for each bar's All chip: the total with that one axis cleared. Selected tags and personIds are always present, even at count 0. Months are UTC YYYY-MM buckets, cut on note creation or on a linked event's date per periodBasis.","parameters":[{"name":"query","in":"query","required":false,"schema":{"type":"string","maxLength":500},"description":"Full-text query (French stemming, accent-insensitive)."},{"name":"status","in":"query","required":false,"schema":{"type":"string","enum":["active","archived","all"]},"description":"Note status (default active)."},{"name":"tags","in":"query","required":false,"schema":{"type":"string"},"description":"Comma-separated tag slugs, max 20. AND: a note must carry every one."},{"name":"personIds","in":"query","required":false,"schema":{"type":"string"},"description":"Comma-separated person ids, max 20. AND: a note must link to every one."},{"name":"since","in":"query","required":false,"schema":{"type":"string","format":"date-time"},"description":"Notes created at or after this instant. Accepts YYYY-MM-DD or a full ISO 8601 instant with Z or a numeric offset; inclusive."},{"name":"until","in":"query","required":false,"schema":{"type":"string","format":"date-time"},"description":"Notes created at or before this instant. Accepts YYYY-MM-DD or a full ISO 8601 instant with Z or a numeric offset; inclusive."},{"name":"updatedSince","in":"query","required":false,"schema":{"type":"string","format":"date-time"},"description":"Notes last modified at or after this instant. Accepts YYYY-MM-DD or a full ISO 8601 instant with Z or a numeric offset; inclusive."},{"name":"updatedUntil","in":"query","required":false,"schema":{"type":"string","format":"date-time"},"description":"Notes last modified at or before this instant. Accepts YYYY-MM-DD or a full ISO 8601 instant with Z or a numeric offset; inclusive."},{"name":"eventSince","in":"query","required":false,"schema":{"type":"string","format":"date-time"},"description":"Notes linked to an event that occurred at or after this instant (both event bounds apply to the same event). Accepts YYYY-MM-DD or a full ISO 8601 instant with Z or a numeric offset; inclusive."},{"name":"eventUntil","in":"query","required":false,"schema":{"type":"string","format":"date-time"},"description":"Notes linked to an event that occurred at or before this instant. Accepts YYYY-MM-DD or a full ISO 8601 instant with Z or a numeric offset; inclusive."},{"name":"periodBasis","in":"query","required":false,"schema":{"type":"string","enum":["created","event"]},"description":"Which date the month buckets are cut on (default created)."}]}},"/api/knowledge/views":{"get":{"tags":["Knowledge"],"summary":"List the caller's saved views","responses":{"200":{"description":"Saved views and the server's caps","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"}},"description":"Also returns `limits` ({ maxViews, maxNameLength }) -- the server's own caps, shipped with the list so a client never mirrors them in its own constants or copy."},"post":{"tags":["Knowledge"],"summary":"Save a filter combination under a name","responses":{"201":{"description":"Created saved view","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"409":{"$ref":"#/components/responses/Conflict"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/KnowledgeSavedViewInput"}}}}}},"/api/knowledge/views/{viewId}":{"parameters":[{"name":"viewId","in":"path","required":true,"schema":{"type":"string"}}],"patch":{"tags":["Knowledge"],"summary":"Rename a saved view or replace its filters","responses":{"200":{"description":"Updated saved view","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"}},"description":"At least one of name or filters. filters is a full replacement, never a merge.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/KnowledgeSavedViewInput"}}}}},"delete":{"tags":["Knowledge"],"summary":"Delete a saved view","responses":{"204":{"description":"Deleted"},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"}}}},"/api/dashboard":{"get":{"tags":["Dashboard"],"summary":"Dashboard overview (counters + event columns)","responses":{"200":{"description":"Dashboard","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"}}}},"/api/insights":{"get":{"tags":["Dashboard"],"summary":"Usage insights metrics","responses":{"200":{"description":"Insights","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"}}}},"/api/integrations":{"get":{"tags":["Integrations"],"summary":"List connected AI clients and their per-client permissions","responses":{"200":{"description":"Integrations","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"}}}},"/api/integrations/permissions":{"patch":{"tags":["Integrations"],"summary":"Update org-wide MCP integration permissions (owner only)","responses":{"200":{"description":"Updated","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}}}},"/api/integrations/clients/{clientId}/permissions":{"parameters":[{"name":"clientId","in":"path","required":true,"schema":{"type":"string"}}],"patch":{"tags":["Integrations"],"summary":"Update a single AI client's permissions (owner only)","responses":{"200":{"description":"Updated","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}}}},"/api/onboarding/checklist":{"get":{"tags":["Onboarding"],"summary":"Onboarding checklist state","responses":{"200":{"description":"Checklist","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"}}}},"/api/billing/status":{"get":{"tags":["Billing"],"summary":"Subscription status","responses":{"200":{"description":"Status","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"}}}},"/api/billing/checkout":{"post":{"tags":["Billing"],"summary":"Create a Stripe Checkout session (Pro)","responses":{"200":{"description":"Checkout session","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"}},"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object"}}}}}},"/api/billing/checkout-business":{"post":{"tags":["Billing"],"summary":"Create a Stripe Checkout session (Business)","responses":{"200":{"description":"Checkout session","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"}},"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object"}}}}}},"/api/billing/portal":{"post":{"tags":["Billing"],"summary":"Create a Stripe Customer Portal session","responses":{"200":{"description":"Portal session","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"}}}},"/api/billing/invoices":{"get":{"tags":["Billing"],"summary":"List invoices","responses":{"200":{"description":"Invoices","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"}}}},"/api/billing/webhook":{"post":{"tags":["Billing"],"summary":"Stripe webhook (signature-verified, no session)","responses":{"200":{"description":"Acknowledged","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"}},"description":"Authenticated by the Stripe-Signature header, not a bearer token.","security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}}}},"/api/webhooks":{"get":{"tags":["Webhooks"],"summary":"List the org's inbound webhook endpoints","responses":{"200":{"description":"Endpoints","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"}}},"post":{"tags":["Webhooks"],"summary":"Create an inbound endpoint (returns the token once)","responses":{"201":{"description":"Endpoint created","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}}}},"/api/webhooks/{id}":{"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"patch":{"tags":["Webhooks"],"summary":"Update an inbound endpoint","responses":{"200":{"description":"Updated","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}}},"delete":{"tags":["Webhooks"],"summary":"Soft-revoke an inbound endpoint","responses":{"204":{"description":"Revoked"},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"}}}},"/api/webhooks/{id}/deliveries":{"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"get":{"tags":["Webhooks"],"summary":"The endpoint's last 50 deliveries","responses":{"200":{"description":"Deliveries","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"}}}},"/api/webhooks/ingest/{endpointId}":{"parameters":[{"name":"endpointId","in":"path","required":true,"schema":{"type":"string"}}],"post":{"tags":["Webhooks"],"summary":"Public ingestion endpoint (whk_ bearer token)","responses":{"200":{"description":"Idempotent replay","content":{"application/json":{"schema":{"type":"object"}}}},"201":{"description":"Event created","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"413":{"description":"Payload too large"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"}},"description":"Authenticated by the endpoint's own whk_ token (Authorization: Bearer whk_...), not a user session. Idempotency via an Idempotency-Key header or metadata.external_id.","security":[{"webhookToken":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookIngest"}}}}}},"/mcp":{"post":{"tags":["MCP"],"summary":"MCP transport (Streamable HTTP): JSON-RPC requests","responses":{"200":{"description":"JSON-RPC response","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"}},"description":"Model Context Protocol endpoint. The server is stateless: only POST is supported (GET/DELETE return 405 Allow: POST). Authenticated with a Supabase OAuth 2.1 access token (Bearer); an unauthenticated request returns 401 with a WWW-Authenticate challenge pointing at /.well-known/oauth-protected-resource (RFC 9728).","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}}}},"/api/oauth/authorizations/{id}":{"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"get":{"tags":["OAuth"],"summary":"Consent details (client name, scopes) for a pending grant","responses":{"200":{"description":"Consent details","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"}}}},"/api/oauth/authorizations/{id}/consent":{"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"post":{"tags":["OAuth"],"summary":"Approve or deny a pending OAuth authorization","responses":{"200":{"description":"Redirect URL","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/ServerError"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"action":{"type":"string","enum":["approve","deny"]}},"required":["action"]}}}}}},"/.well-known/mcp":{"get":{"tags":["Discovery"],"summary":"MCP Server Card","security":[],"responses":{"200":{"description":"The discovery document","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/.well-known/api-catalog":{"get":{"tags":["Discovery"],"summary":"API catalog linkset (RFC 9727)","security":[],"responses":{"200":{"description":"The discovery document","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/.well-known/oauth-authorization-server":{"get":{"tags":["Discovery"],"summary":"OAuth authorization server metadata (RFC 8414)","security":[],"responses":{"200":{"description":"The discovery document","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/.well-known/oauth-protected-resource":{"get":{"tags":["Discovery"],"summary":"OAuth protected resource metadata (RFC 9728)","security":[],"responses":{"200":{"description":"The discovery document","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/openapi.json":{"get":{"tags":["Discovery"],"summary":"This OpenAPI document","security":[],"responses":{"200":{"description":"The discovery document","content":{"application/json":{"schema":{"type":"object"}}}}}}}},"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"Supabase SESSION JWT of a signed-in person (POST /api/auth/login, or the sb-access-token cookie). A Supabase OAuth 2.1 access token -- one carrying a client_id claim, obtained via the authorization server at /.well-known/oauth-authorization-server -- is NOT accepted here since HIS-926: it is the credential of an assistant, is refused with 403 assistant_token_rejected, and belongs on the MCP transport, where the client's own read/write permissions apply."},"webhookToken":{"type":"http","scheme":"bearer","description":"An inbound webhook endpoint's own whk_ token, used only on POST /api/webhooks/ingest/{id}."}},"parameters":{"SearchQuery":{"name":"search","in":"query","required":false,"schema":{"type":"string"},"description":"Free-text filter."},"TagsQuery":{"name":"tags","in":"query","required":false,"schema":{"type":"string"},"description":"Comma-separated tag slugs."},"LimitQuery":{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":200},"description":"Page size."},"OffsetQuery":{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0},"description":"Page offset."}},"responses":{"Unauthorized":{"description":"Missing or invalid credentials","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Forbidden":{"description":"Authenticated but not allowed (role/plan/policy)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"NotFound":{"description":"Resource not found or not visible to the caller","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Conflict":{"description":"Conflict (e.g. slug collision)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"DuplicateEmail":{"description":"A person with this email already exists in the org","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"const":"duplicate_email"}}}}}},"ValidationError":{"description":"Request failed schema validation","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"}}}},"RateLimited":{"description":"Rate limit exceeded for the caller's identity/plan","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"retryAfter":{"type":"integer"},"upgrade_url":{"type":"string"}}}}}},"ServerError":{"description":"Internal server error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"schemas":{"Error":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]},"ValidationError":{"type":"object","properties":{"error":{"type":"string"},"details":{"type":"object","description":"z.flattenError() output"}},"required":["error"]},"Credentials":{"type":"object","properties":{"email":{"type":"string","format":"email"},"password":{"type":"string","minLength":8}},"required":["email","password"]},"Visibility":{"type":"string","enum":["organization","teams","private"]},"PersonInput":{"type":"object","properties":{"name":{"type":"string"},"email":{"type":"string","format":"email"},"phone":{"type":"string"},"description":{"type":"string"},"tags":{"type":"array","items":{"type":"string"}},"visibility":{"$ref":"#/components/schemas/Visibility"}},"required":["name"],"additionalProperties":false},"EventInput":{"type":"object","properties":{"content":{"type":"string"},"status":{"type":"string","enum":["open","in_progress","done"]},"deadline":{"type":"string","format":"date"},"tags":{"type":"array","items":{"type":"string"}},"personIds":{"type":"array","items":{"type":"string","format":"uuid"}},"visibility":{"$ref":"#/components/schemas/Visibility"}},"required":["content"],"additionalProperties":false},"TagInput":{"type":"object","properties":{"name":{"type":"string"},"description":{"type":"string","nullable":true}}},"TagPair":{"type":"object","properties":{"slugA":{"type":"string"},"slugB":{"type":"string"}},"required":["slugA","slugB"]},"RuleInput":{"type":"object","properties":{"name":{"type":"string"},"body":{"type":"string","description":"Markdown rule body"},"enabled":{"type":"boolean"}},"required":["name","body"]},"KnowledgeSavedViewInput":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":80},"filters":{"type":"object","description":"A strict object with arrays instead of CSV; an unknown key is rejected. Deliberately narrower than the GET /api/knowledge filter so a view is exactly replayable from the screen that saved it: no updatedSince/updatedUntil, and at most one time axis (carrying both a since/until and an eventSince/eventUntil range is rejected).","properties":{"query":{"type":"string","maxLength":500},"status":{"type":"string","enum":["active","archived","all"]},"tags":{"type":"array","items":{"type":"string"}},"personIds":{"type":"array","items":{"type":"string","format":"uuid"}},"since":{"type":"string","format":"date-time"},"until":{"type":"string","format":"date-time"},"eventSince":{"type":"string","format":"date-time"},"eventUntil":{"type":"string","format":"date-time"}},"additionalProperties":false}}},"WebhookIngest":{"type":"object","properties":{"content":{"type":"string"},"status":{"type":"string"},"tags":{"type":"array","items":{"type":"string"}},"person":{"type":"object","properties":{"name":{"type":"string"},"email":{"type":"string","format":"email"}}},"metadata":{"type":"object","additionalProperties":true}},"required":["content"]}}}}