{"openapi":"3.1.0","info":{"title":"LoreKit REST API","version":"1.0.0","description":"Persistent memory for AI coding agents.\n\n**Authentication** — every endpoint accepts a Bearer token: a LoreKit API token\n(`lk_ro_*` to explore, `lk_rw_*` to test writes) or your Supabase session (JWT).\nGenerate a token from [Settings → API keys](/settings/api-keys) and paste it into the\n**Authorize** box above — one token works on every endpoint, orgs included.\n\n**Safe by default here** — this console pre-fills `X-LoreKit-Dry-Run: true`, so create /\nupdate / delete requests sent from it are validated and authorized but make **no changes**.\nClear that header on an operation to execute for real. A request sent WITHOUT the header\n(curl, an SDK, an agent) executes for real.\n\n**For agents and scripts** — the same reference as Markdown: [/api-docs.md](/api-docs.md)."},"servers":[{"url":"https://pqokxlhvnosogizsjztg.supabase.co/functions/v1","description":"Supabase Edge Functions"}],"security":[{"BearerAuth":[]}],"components":{"securitySchemes":{"BearerAuth":{"type":"http","scheme":"bearer","description":"LoreKit API token (lk_rw_*, lk_ro_*, lk_wo_*) or Supabase JWT. Every route — memories and orgs alike — accepts either; access is gated by the token read/write permission, not by auth tier."}},"schemas":{"Memory":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"scope":{"type":"string"},"key":{"type":"string"},"value":{"type":"string"},"tags":{"type":"array","items":{"type":"string"}},"source_agent":{"type":["string","null"]},"trigger":{"type":["string","null"]},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"},"expires_at":{"type":["string","null"],"format":"date-time"},"archived_at":{"type":["string","null"],"format":"date-time"},"origin_repo":{"type":["string","null"]},"origin_branch":{"type":["string","null"]},"origin_commit":{"type":["string","null"]},"origin_pr":{"type":["number","null"]},"kind":{"type":["string","null"]},"host":{"type":["string","null"]},"seen_count":{"type":"integer"},"read_count":{"type":"integer","minimum":0},"last_read_at":{"type":["string","null"],"format":"date-time"},"last_opened_at":{"type":["string","null"],"format":"date-time"},"opened_count":{"type":"integer","minimum":0},"cited_count":{"type":"integer","minimum":0},"last_cited_at":{"type":["string","null"],"format":"date-time"},"org_id":{"type":["string","null"],"format":"uuid"},"org":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"slug":{"type":"string"}},"required":["id","name","slug"]},"created_by":{"type":["string","null"],"format":"uuid"},"updated_by":{"type":["string","null"],"format":"uuid"}},"required":["id","scope","key","value","tags","source_agent","trigger","created_at","updated_at","expires_at","archived_at"]},"MemoryPage":{"type":"object","properties":{"entries":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"scope":{"type":"string"},"key":{"type":"string"},"value":{"type":"string"},"tags":{"type":"array","items":{"type":"string"}},"source_agent":{"type":["string","null"]},"trigger":{"type":["string","null"]},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"},"expires_at":{"type":["string","null"],"format":"date-time"},"archived_at":{"type":["string","null"],"format":"date-time"},"origin_repo":{"type":["string","null"]},"origin_branch":{"type":["string","null"]},"origin_commit":{"type":["string","null"]},"origin_pr":{"type":["number","null"]},"kind":{"type":["string","null"]},"host":{"type":["string","null"]},"seen_count":{"type":"integer"},"read_count":{"type":"integer","minimum":0},"last_read_at":{"type":["string","null"],"format":"date-time"},"last_opened_at":{"type":["string","null"],"format":"date-time"},"opened_count":{"type":"integer","minimum":0},"cited_count":{"type":"integer","minimum":0},"last_cited_at":{"type":["string","null"],"format":"date-time"},"org_id":{"type":["string","null"],"format":"uuid"},"org":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"slug":{"type":"string"}},"required":["id","name","slug"]},"created_by":{"type":["string","null"],"format":"uuid"},"updated_by":{"type":["string","null"],"format":"uuid"}},"required":["id","scope","key","value","tags","source_agent","trigger","created_at","updated_at","expires_at","archived_at"]}},"hasMore":{"type":"boolean"},"nextCursor":{"type":["string","null"]},"total":{"type":"integer","minimum":0}},"required":["entries","hasMore","nextCursor"]},"CreateMemoryBody":{"type":"object","properties":{"scope":{"type":"string","minLength":1},"key":{"type":"string","minLength":1,"maxLength":512},"value":{"type":"string","maxLength":65536},"tags":{"type":"array","items":{"type":"string"},"default":[]},"source_agent":{"type":"string"},"trigger":{"type":"string"},"created_at":{"type":"string"},"org":{"type":"string"},"ttl_days":{"type":"integer","minimum":1,"maximum":365},"clear_ttl":{"type":"boolean","default":false},"kind":{"type":"string","enum":["lesson","bus","signal"]},"host":{"type":"string","maxLength":64},"origin_repo":{"type":"string"},"origin_branch":{"type":"string"},"origin_commit":{"type":"string"},"origin_pr":{"anyOf":[{"type":"number"},{"type":"string"}]},"cited":{"type":"array","items":{"type":"string","maxLength":1024}}},"required":["scope","key","value"]},"UpdateMemoryBody":{"type":"object","properties":{"value":{"type":"string","maxLength":65536},"tags":{"type":"array","items":{"type":"string"},"default":[]},"source_agent":{"type":"string"},"trigger":{"type":"string"},"ttl_days":{"type":"integer","minimum":1,"maximum":365},"clear_ttl":{"type":"boolean","default":false},"kind":{"type":"string","enum":["lesson","bus","signal"]},"host":{"type":"string","maxLength":64}}},"SearchMemoriesBody":{"type":"object","properties":{"q":{"type":"string"},"scopes":{"type":"array","items":{"type":"string","minLength":1}},"tags":{"type":"array","items":{"type":"string"}},"filter":{"type":"object","description":"Recursive filter tree. Either a condition `{ field, op, value }` or a group `{ and: [...] }` / `{ or: [...] }`, nestable to any depth. Operators: is, is_not, contains, does_not_contain, starts_with, ends_with, is_set, is_not_set.","example":{"and":[{"field":"scope","op":"is","value":"global"},{"or":[{"field":"key","op":"contains","value":"auth"},{"field":"tags","op":"contains","value":"ci"}]}]}},"limit":{"type":"integer","minimum":1,"maximum":100,"default":50},"cursor":{"type":"string"}}},"ListMemoriesBody":{"type":"object","properties":{"scope":{"type":"string","minLength":1},"key":{"type":"string","minLength":1,"maxLength":512},"key_prefix":{"type":"string","minLength":1,"maxLength":512},"q":{"type":"string","minLength":1,"maxLength":512},"created_since":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}([T ]\\d{2}:\\d{2}(:\\d{2}(\\.\\d{1,6})?)?(Z|[+-]\\d{2}:?\\d{2})?)?$"},"created_until":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}([T ]\\d{2}:\\d{2}(:\\d{2}(\\.\\d{1,6})?)?(Z|[+-]\\d{2}:?\\d{2})?)?$"},"tags":{"type":"array","items":{"type":"string","minLength":1,"maxLength":512},"maxItems":1000},"tags_mode":{"type":"string","enum":["any","all","none"],"default":"any"},"exclude_tags":{"type":"array","items":{"type":"string","minLength":1,"maxLength":512},"maxItems":1000},"source_agent":{"type":"array","items":{"type":"string","minLength":1,"maxLength":512},"maxItems":1000},"source_agent_mode":{"type":"string","enum":["in","nin"],"default":"in"},"trigger":{"type":"array","items":{"type":"string","minLength":1,"maxLength":512},"maxItems":1000},"trigger_mode":{"type":"string","enum":["in","nin"],"default":"in"},"kind":{"type":"array","items":{"type":"string","minLength":1,"maxLength":512},"maxItems":1000},"kind_mode":{"type":"string","enum":["in","nin"],"default":"in"},"host":{"type":"array","items":{"type":"string","minLength":1,"maxLength":512},"maxItems":1000},"host_mode":{"type":"string","enum":["in","nin"],"default":"in"},"origin_repo":{"type":"array","items":{"type":"string","minLength":1,"maxLength":512},"maxItems":1000},"origin_repo_mode":{"type":"string","enum":["in","nin"],"default":"in"},"origin_branch":{"type":"array","items":{"type":"string","minLength":1,"maxLength":512},"maxItems":1000},"origin_branch_mode":{"type":"string","enum":["in","nin"],"default":"in"},"origin_pr":{"type":"array","items":{"type":"string","minLength":1,"maxLength":512},"maxItems":1000},"origin_pr_mode":{"type":"string","enum":["in","nin"],"default":"in"},"owner":{"type":"array","items":{"type":"string","minLength":1,"maxLength":512},"maxItems":1000},"owner_mode":{"type":"string","enum":["in","nin"],"default":"in"},"sort":{"type":"string","enum":["updated_at","created_at","opened_count","last_opened_at"],"default":"updated_at"},"archived":{"type":"boolean","default":false},"expiring_within_days":{"type":"integer","minimum":1,"maximum":365},"min_age_days":{"type":"integer","minimum":1,"maximum":3650},"unseen_days":{"type":"integer","minimum":1,"maximum":3650},"max_seen_count":{"type":"integer","minimum":0,"maximum":100000},"max_read_count":{"type":"integer","minimum":0,"maximum":100000},"max_opened_count":{"type":"integer","minimum":0,"maximum":100000},"opened_within_days":{"type":"integer","minimum":1,"maximum":3650},"min_seen_count":{"type":"integer","minimum":2,"maximum":100000},"min_read_count":{"type":"integer","minimum":1,"maximum":100000},"min_opened_count":{"type":"integer","minimum":1,"maximum":100000},"limit":{"type":"integer","minimum":1,"maximum":100,"default":50},"cursor":{"type":"string"}}},"ReadMemoriesBody":{"type":"object","properties":{"refs":{"type":"array","items":{"type":"string"},"minItems":1}},"required":["refs"]},"ReadMemoriesResponse":{"type":"object","properties":{"entries":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"scope":{"type":"string"},"key":{"type":"string"},"value":{"type":"string"},"tags":{"type":"array","items":{"type":"string"}},"source_agent":{"type":["string","null"]},"trigger":{"type":["string","null"]},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"},"expires_at":{"type":["string","null"],"format":"date-time"},"archived_at":{"type":["string","null"],"format":"date-time"},"origin_repo":{"type":["string","null"]},"origin_branch":{"type":["string","null"]},"origin_commit":{"type":["string","null"]},"origin_pr":{"type":["number","null"]},"kind":{"type":["string","null"]},"host":{"type":["string","null"]},"seen_count":{"type":"integer"},"read_count":{"type":"integer","minimum":0},"last_read_at":{"type":["string","null"],"format":"date-time"},"last_opened_at":{"type":["string","null"],"format":"date-time"},"opened_count":{"type":"integer","minimum":0},"cited_count":{"type":"integer","minimum":0},"last_cited_at":{"type":["string","null"],"format":"date-time"},"org_id":{"type":["string","null"],"format":"uuid"},"org":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"slug":{"type":"string"}},"required":["id","name","slug"]},"created_by":{"type":["string","null"],"format":"uuid"},"updated_by":{"type":["string","null"],"format":"uuid"}},"required":["id","scope","key","value","tags","source_agent","trigger","created_at","updated_at","expires_at","archived_at"]}},"missing":{"type":"array","items":{"type":"string"}}},"required":["entries","missing"]},"ListFacetsBody":{"type":"object","properties":{"archived":{"type":"boolean","default":false},"facets":{"type":"array","items":{"type":"string","enum":["tag","source_agent","trigger","kind","host","origin_repo","origin_branch","origin_pr","owner"]}},"scope":{"type":"string","minLength":1},"created_since":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}([T ]\\d{2}:\\d{2}(:\\d{2}(\\.\\d{1,6})?)?(Z|[+-]\\d{2}:?\\d{2})?)?$"},"created_until":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}([T ]\\d{2}:\\d{2}(:\\d{2}(\\.\\d{1,6})?)?(Z|[+-]\\d{2}:?\\d{2})?)?$"},"tags":{"type":"array","items":{"type":"string","minLength":1,"maxLength":512},"maxItems":1000},"tags_mode":{"type":"string","enum":["any","all","none"],"default":"any"},"exclude_tags":{"type":"array","items":{"type":"string","minLength":1,"maxLength":512},"maxItems":1000},"source_agent":{"type":"array","items":{"type":"string","minLength":1,"maxLength":512},"maxItems":1000},"source_agent_mode":{"type":"string","enum":["in","nin"],"default":"in"},"trigger":{"type":"array","items":{"type":"string","minLength":1,"maxLength":512},"maxItems":1000},"trigger_mode":{"type":"string","enum":["in","nin"],"default":"in"},"kind":{"type":"array","items":{"type":"string","minLength":1,"maxLength":512},"maxItems":1000},"kind_mode":{"type":"string","enum":["in","nin"],"default":"in"},"host":{"type":"array","items":{"type":"string","minLength":1,"maxLength":512},"maxItems":1000},"host_mode":{"type":"string","enum":["in","nin"],"default":"in"},"origin_repo":{"type":"array","items":{"type":"string","minLength":1,"maxLength":512},"maxItems":1000},"origin_repo_mode":{"type":"string","enum":["in","nin"],"default":"in"},"origin_branch":{"type":"array","items":{"type":"string","minLength":1,"maxLength":512},"maxItems":1000},"origin_branch_mode":{"type":"string","enum":["in","nin"],"default":"in"},"origin_pr":{"type":"array","items":{"type":"string","minLength":1,"maxLength":512},"maxItems":1000},"origin_pr_mode":{"type":"string","enum":["in","nin"],"default":"in"},"owner":{"type":"array","items":{"type":"string","minLength":1,"maxLength":512},"maxItems":1000},"owner_mode":{"type":"string","enum":["in","nin"],"default":"in"},"min_age_days":{"type":"integer","minimum":1,"maximum":3650},"unseen_days":{"type":"integer","minimum":1,"maximum":3650},"max_seen_count":{"type":"integer","minimum":0,"maximum":100000},"max_read_count":{"type":"integer","minimum":0,"maximum":100000},"max_opened_count":{"type":"integer","minimum":0,"maximum":100000},"opened_within_days":{"type":"integer","minimum":1,"maximum":3650},"min_seen_count":{"type":"integer","minimum":2,"maximum":100000},"min_read_count":{"type":"integer","minimum":1,"maximum":100000},"min_opened_count":{"type":"integer","minimum":1,"maximum":100000}}},"ActivityBody":{"type":"object","properties":{"bucket":{"type":"string","enum":["hour","day"],"default":"day"},"since":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}([T ]\\d{2}:\\d{2}(:\\d{2}(\\.\\d{1,6})?)?(Z|[+-]\\d{2}:?\\d{2})?)?$"},"until":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}([T ]\\d{2}:\\d{2}(:\\d{2}(\\.\\d{1,6})?)?(Z|[+-]\\d{2}:?\\d{2})?)?$"},"scope":{"type":"string","minLength":1},"tags":{"type":"array","items":{"type":"string","minLength":1,"maxLength":512},"maxItems":1000},"tags_mode":{"type":"string","enum":["any","all","none"],"default":"any"},"exclude_tags":{"type":"array","items":{"type":"string","minLength":1,"maxLength":512},"maxItems":1000},"source_agent":{"type":"array","items":{"type":"string","minLength":1,"maxLength":512},"maxItems":1000},"source_agent_mode":{"type":"string","enum":["in","nin"],"default":"in"},"trigger":{"type":"array","items":{"type":"string","minLength":1,"maxLength":512},"maxItems":1000},"trigger_mode":{"type":"string","enum":["in","nin"],"default":"in"},"kind":{"type":"array","items":{"type":"string","minLength":1,"maxLength":512},"maxItems":1000},"kind_mode":{"type":"string","enum":["in","nin"],"default":"in"},"host":{"type":"array","items":{"type":"string","minLength":1,"maxLength":512},"maxItems":1000},"host_mode":{"type":"string","enum":["in","nin"],"default":"in"},"origin_repo":{"type":"array","items":{"type":"string","minLength":1,"maxLength":512},"maxItems":1000},"origin_repo_mode":{"type":"string","enum":["in","nin"],"default":"in"},"origin_branch":{"type":"array","items":{"type":"string","minLength":1,"maxLength":512},"maxItems":1000},"origin_branch_mode":{"type":"string","enum":["in","nin"],"default":"in"},"origin_pr":{"type":"array","items":{"type":"string","minLength":1,"maxLength":512},"maxItems":1000},"origin_pr_mode":{"type":"string","enum":["in","nin"],"default":"in"},"owner":{"type":"array","items":{"type":"string","minLength":1,"maxLength":512},"maxItems":1000},"owner_mode":{"type":"string","enum":["in","nin"],"default":"in"},"min_age_days":{"type":"integer","minimum":1,"maximum":3650},"unseen_days":{"type":"integer","minimum":1,"maximum":3650},"max_seen_count":{"type":"integer","minimum":0,"maximum":100000},"max_read_count":{"type":"integer","minimum":0,"maximum":100000},"max_opened_count":{"type":"integer","minimum":0,"maximum":100000},"opened_within_days":{"type":"integer","minimum":1,"maximum":3650},"min_seen_count":{"type":"integer","minimum":2,"maximum":100000},"min_read_count":{"type":"integer","minimum":1,"maximum":100000},"min_opened_count":{"type":"integer","minimum":1,"maximum":100000}}},"RestoreMemoryBody":{"type":"object","properties":{"scope":{"type":"string","minLength":1},"key":{"type":"string","minLength":1,"maxLength":512}},"required":["scope","key"]},"PurgeMemoriesBody":{"type":"object","properties":{"retention_days":{"type":"integer","minimum":1,"maximum":365,"default":30}}},"RestoreResponse":{"type":"object","properties":{"restored":{"type":"boolean"}},"required":["restored"]},"PurgeResponse":{"type":"object","properties":{"purged":{"type":"integer","minimum":0}},"required":["purged"]},"ScopesResponse":{"type":"object","properties":{"scopes":{"type":"array","items":{"type":"object","properties":{"scope":{"type":"string"},"count":{"type":"integer","minimum":0},"last_activity":{"type":["string","null"]}},"required":["scope","count"]}}},"required":["scopes"]},"MemoryQuotaResponse":{"type":"object","properties":{"plan":{"type":"string"},"personal":{"type":"object","properties":{"count":{"type":"integer","minimum":0},"limit":{"type":"integer","minimum":0},"remaining":{"type":"integer","minimum":0}},"required":["count","limit","remaining"]},"org_count":{"type":"integer","minimum":0},"total":{"type":"integer","minimum":0}},"required":["plan","personal","org_count","total"]},"UsageStatsResponse":{"type":"object","properties":{"range":{"type":"object","properties":{"since":{"type":["string","null"]},"until":{"type":["string","null"]}},"required":["since","until"]},"correlation_id":{"type":["string","null"]},"summary":{"type":"object","properties":{"total_events":{"type":"integer","minimum":0},"reads":{"type":"integer","minimum":0},"writes":{"type":"integer","minimum":0},"other":{"type":"integer","minimum":0},"records_read":{"type":"integer","minimum":0},"archived":{"type":"integer","minimum":0},"expired":{"type":"integer","minimum":0},"by_outcome":{"type":"object","additionalProperties":{"type":"integer","minimum":0}},"peak_memory_count":{"type":["integer","null"],"minimum":0}},"required":["total_events","reads","writes","other","records_read","archived","expired","by_outcome"]},"by_tool":{"type":"array","items":{"type":"object","properties":{"tool_name":{"type":"string"},"outcome":{"type":"string"},"scope_type":{"type":["string","null"]},"client":{"type":["string","null"]},"kind":{"type":["string","null"]},"host":{"type":["string","null"]},"event_count":{"type":"integer","minimum":0},"record_count":{"type":"integer","minimum":0},"total_duration_ms":{"type":["integer","null"],"minimum":0}},"required":["tool_name","outcome","scope_type","event_count","record_count","total_duration_ms"]}},"by_scope_type":{"type":"array","items":{"type":"object","properties":{"scope_type":{"type":["string","null"]},"event_count":{"type":"integer","minimum":0}},"required":["scope_type","event_count"]}}},"required":["range","correlation_id","summary","by_tool","by_scope_type"]},"Org":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"slug":{"type":"string"},"name":{"type":"string"},"created_at":{"type":"string","format":"date-time"}},"required":["id","slug","name","created_at"]},"OrgList":{"type":"object","properties":{"entries":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"slug":{"type":"string"},"name":{"type":"string"},"created_at":{"type":"string","format":"date-time"}},"required":["id","slug","name","created_at"]}}},"required":["entries"]},"CreateOrgBody":{"type":"object","properties":{"slug":{"type":"string","minLength":3,"maxLength":50,"pattern":"^[a-z0-9][a-z0-9-]*[a-z0-9]$"},"name":{"type":"string","minLength":1,"maxLength":100}},"required":["slug","name"]},"RenameOrgBody":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":100}},"required":["name"]},"OrgMember":{"type":"object","properties":{"user_id":{"type":"string","format":"uuid"},"role":{"type":"string","enum":["owner","admin","member","viewer"]},"joined_at":{"type":"string","format":"date-time"},"display_name":{"type":["string","null"]},"avatar_url":{"type":["string","null"]}},"required":["user_id","role","joined_at","display_name","avatar_url"]},"OrgMemberList":{"type":"object","properties":{"entries":{"type":"array","items":{"type":"object","properties":{"user_id":{"type":"string","format":"uuid"},"role":{"type":"string","enum":["owner","admin","member","viewer"]},"joined_at":{"type":"string","format":"date-time"},"display_name":{"type":["string","null"]},"avatar_url":{"type":["string","null"]}},"required":["user_id","role","joined_at","display_name","avatar_url"]}}},"required":["entries"]},"UpdateMemberRoleBody":{"type":"object","properties":{"role":{"type":"string","enum":["owner","admin","member","viewer"]}},"required":["role"]},"OrgInvite":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"org_id":{"type":"string","format":"uuid"},"email":{"type":["string","null"]},"handle":{"type":["string","null"]},"role":{"type":"string","enum":["owner","admin","member","viewer"]},"created_at":{"type":"string","format":"date-time"},"expires_at":{"type":["string","null"],"format":"date-time"}},"required":["id","org_id","email","handle","role","created_at","expires_at"]},"OrgInviteList":{"type":"object","properties":{"entries":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"org_id":{"type":"string","format":"uuid"},"email":{"type":["string","null"]},"handle":{"type":["string","null"]},"role":{"type":"string","enum":["owner","admin","member","viewer"]},"created_at":{"type":"string","format":"date-time"},"expires_at":{"type":["string","null"],"format":"date-time"}},"required":["id","org_id","email","handle","role","created_at","expires_at"]}}},"required":["entries"]},"CreateInviteBody":{"type":"object","properties":{"email":{"type":"string","format":"email"},"handle":{"type":"string","minLength":1},"role":{"type":"string","enum":["admin","member","viewer"],"default":"member"}}},"BlogLikes":{"type":"object","properties":{"likes":{"type":"integer","minimum":0}},"required":["likes"]},"Error":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"details":{"type":"object","additionalProperties":{}}},"required":["error"]}},"parameters":{}},"paths":{"/memories":{"get":{"summary":"List memories","tags":["Memories"],"description":"Lists live memories by default. Filters AND across dimensions and OR within one, so `?kind=lesson&host=reviewer` reads \"reviewer's lessons\".\n\n`expiring_within_days=N` narrows to lore whose TTL runs out soon — `expires_at` strictly after now and at or before now + N days. The lower bound is exclusive because that is what \"still live\" means everywhere else in the API (an already-expired memory is never returned); the upper bound is inclusive, so \"within 7 days\" includes one expiring exactly 7 days out. Memories with no TTL are never in the result. It is a RELATIVE horizon rather than an absolute timestamp so a saved or shared link keeps answering the same question tomorrow.\n\nAn invalid `scope` is a `400`, not a silently ignored filter — a scope filter is the question being asked, so an ungrammatical one is rejected rather than matched against nothing and reported as an empty page. The value is validated, never normalised: the write path stores `scope` verbatim, so the filter matches exactly what was written.","security":[{"BearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1},"required":false,"name":"scope","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":512},"required":false,"name":"key","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":512},"required":false,"name":"key_prefix","in":"query"},{"schema":{"type":"string"},"required":false,"name":"tags","in":"query"},{"schema":{"type":"string","enum":["any","all","none"],"default":"any"},"required":false,"name":"tags_mode","in":"query"},{"schema":{"type":"string"},"required":false,"name":"exclude_tags","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":512},"required":false,"name":"q","in":"query"},{"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}([T ]\\d{2}:\\d{2}(:\\d{2}(\\.\\d{1,6})?)?(Z|[+-]\\d{2}:?\\d{2})?)?$"},"required":false,"name":"created_since","in":"query"},{"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}([T ]\\d{2}:\\d{2}(:\\d{2}(\\.\\d{1,6})?)?(Z|[+-]\\d{2}:?\\d{2})?)?$"},"required":false,"name":"created_until","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":2048},"required":false,"name":"source_agent","in":"query"},{"schema":{"type":"string","enum":["in","nin"],"default":"in"},"required":false,"name":"source_agent_mode","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":2048},"required":false,"name":"trigger","in":"query"},{"schema":{"type":"string","enum":["in","nin"],"default":"in"},"required":false,"name":"trigger_mode","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":2048},"required":false,"name":"kind","in":"query"},{"schema":{"type":"string","enum":["in","nin"],"default":"in"},"required":false,"name":"kind_mode","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":2048},"required":false,"name":"host","in":"query"},{"schema":{"type":"string","enum":["in","nin"],"default":"in"},"required":false,"name":"host_mode","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":2048},"required":false,"name":"origin_repo","in":"query"},{"schema":{"type":"string","enum":["in","nin"],"default":"in"},"required":false,"name":"origin_repo_mode","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":2048},"required":false,"name":"origin_branch","in":"query"},{"schema":{"type":"string","enum":["in","nin"],"default":"in"},"required":false,"name":"origin_branch_mode","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":2048},"required":false,"name":"origin_pr","in":"query"},{"schema":{"type":"string","enum":["in","nin"],"default":"in"},"required":false,"name":"origin_pr_mode","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":2048},"required":false,"name":"owner","in":"query"},{"schema":{"type":"string","enum":["in","nin"],"default":"in"},"required":false,"name":"owner_mode","in":"query"},{"schema":{"type":"string","enum":["updated_at","created_at","opened_count","last_opened_at"],"default":"updated_at"},"required":false,"name":"sort","in":"query"},{"schema":{"type":"string","enum":["true","false"],"default":"false"},"required":false,"name":"archived","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":365},"required":false,"name":"expiring_within_days","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":3650},"required":false,"name":"min_age_days","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":3650},"required":false,"name":"unseen_days","in":"query"},{"schema":{"type":["integer","null"],"minimum":0,"maximum":100000},"required":false,"name":"max_seen_count","in":"query"},{"schema":{"type":["integer","null"],"minimum":0,"maximum":100000},"required":false,"name":"max_read_count","in":"query"},{"schema":{"type":["integer","null"],"minimum":0,"maximum":100000},"required":false,"name":"max_opened_count","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":3650},"required":false,"name":"opened_within_days","in":"query"},{"schema":{"type":"integer","minimum":2,"maximum":100000},"required":false,"name":"min_seen_count","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100000},"required":false,"name":"min_read_count","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100000},"required":false,"name":"min_opened_count","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100,"default":50},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string"},"required":false,"name":"cursor","in":"query"},{"name":"X-LoreKit-Client","in":"header","required":false,"description":"Which surface is calling. One of `dashboard`, `cli`, `mcp`, `api`; anything else is recorded as unattributed. Purely for usage analytics — it never changes the response. Optional: an absent header records this transport's own default (`api`), so send it only to identify a MORE SPECIFIC calling surface (e.g. `cli`). Reads attributed to `dashboard` are excluded from `GET /memories/read-activity`.","schema":{"type":"string","enum":["dashboard","cli","mcp","api"]}}],"responses":{"200":{"description":"Paginated memories","content":{"application/json":{"schema":{"type":"object","properties":{"entries":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"scope":{"type":"string"},"key":{"type":"string"},"value":{"type":"string"},"tags":{"type":"array","items":{"type":"string"}},"source_agent":{"type":["string","null"]},"trigger":{"type":["string","null"]},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"},"expires_at":{"type":["string","null"],"format":"date-time"},"archived_at":{"type":["string","null"],"format":"date-time"},"origin_repo":{"type":["string","null"]},"origin_branch":{"type":["string","null"]},"origin_commit":{"type":["string","null"]},"origin_pr":{"type":["number","null"]},"kind":{"type":["string","null"]},"host":{"type":["string","null"]},"seen_count":{"type":"integer"},"read_count":{"type":"integer","minimum":0},"last_read_at":{"type":["string","null"],"format":"date-time"},"last_opened_at":{"type":["string","null"],"format":"date-time"},"opened_count":{"type":"integer","minimum":0},"cited_count":{"type":"integer","minimum":0},"last_cited_at":{"type":["string","null"],"format":"date-time"},"org_id":{"type":["string","null"],"format":"uuid"},"org":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"slug":{"type":"string"}},"required":["id","name","slug"]},"created_by":{"type":["string","null"],"format":"uuid"},"updated_by":{"type":["string","null"],"format":"uuid"}},"required":["id","scope","key","value","tags","source_agent","trigger","created_at","updated_at","expires_at","archived_at"]}},"hasMore":{"type":"boolean"},"nextCursor":{"type":["string","null"]},"total":{"type":"integer","minimum":0}},"required":["entries","hasMore","nextCursor"]}}}},"400":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"details":{"type":"object","additionalProperties":{}}},"required":["error"]}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"details":{"type":"object","additionalProperties":{}}},"required":["error"]}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"details":{"type":"object","additionalProperties":{}}},"required":["error"]}}}}}},"post":{"summary":"Create or update a memory","tags":["Memories"],"security":[{"BearerAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"scope":{"type":"string","minLength":1},"key":{"type":"string","minLength":1,"maxLength":512},"value":{"type":"string","maxLength":65536},"tags":{"type":"array","items":{"type":"string"},"default":[]},"source_agent":{"type":"string"},"trigger":{"type":"string"},"created_at":{"type":"string"},"org":{"type":"string"},"ttl_days":{"type":"integer","minimum":1,"maximum":365},"clear_ttl":{"type":"boolean","default":false},"kind":{"type":"string","enum":["lesson","bus","signal"]},"host":{"type":"string","maxLength":64},"origin_repo":{"type":"string"},"origin_branch":{"type":"string"},"origin_commit":{"type":"string"},"origin_pr":{"anyOf":[{"type":"number"},{"type":"string"}]},"cited":{"type":"array","items":{"type":"string","maxLength":1024}}},"required":["scope","key","value"]}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"scope":{"type":"string"},"key":{"type":"string"},"value":{"type":"string"},"tags":{"type":"array","items":{"type":"string"}},"source_agent":{"type":["string","null"]},"trigger":{"type":["string","null"]},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"},"expires_at":{"type":["string","null"],"format":"date-time"},"archived_at":{"type":["string","null"],"format":"date-time"},"origin_repo":{"type":["string","null"]},"origin_branch":{"type":["string","null"]},"origin_commit":{"type":["string","null"]},"origin_pr":{"type":["number","null"]},"kind":{"type":["string","null"]},"host":{"type":["string","null"]},"seen_count":{"type":"integer"},"read_count":{"type":"integer","minimum":0},"last_read_at":{"type":["string","null"],"format":"date-time"},"last_opened_at":{"type":["string","null"],"format":"date-time"},"opened_count":{"type":"integer","minimum":0},"cited_count":{"type":"integer","minimum":0},"last_cited_at":{"type":["string","null"],"format":"date-time"},"org_id":{"type":["string","null"],"format":"uuid"},"org":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"slug":{"type":"string"}},"required":["id","name","slug"]},"created_by":{"type":["string","null"],"format":"uuid"},"updated_by":{"type":["string","null"],"format":"uuid"}},"required":["id","scope","key","value","tags","source_agent","trigger","created_at","updated_at","expires_at","archived_at"]}}}},"400":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"details":{"type":"object","additionalProperties":{}}},"required":["error"]}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"details":{"type":"object","additionalProperties":{}}},"required":["error"]}}}},"429":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"details":{"type":"object","additionalProperties":{}}},"required":["error"]}}}}},"parameters":[{"name":"X-LoreKit-Client","in":"header","required":false,"description":"Which surface is calling. One of `dashboard`, `cli`, `mcp`, `api`; anything else is recorded as unattributed. Purely for usage analytics — it never changes the response. Optional: an absent header records this transport's own default (`api`), so send it only to identify a MORE SPECIFIC calling surface (e.g. `cli`). Reads attributed to `dashboard` are excluded from `GET /memories/read-activity`.","schema":{"type":"string","enum":["dashboard","cli","mcp","api"]}},{"name":"X-LoreKit-Dry-Run","in":"header","required":false,"description":"Safe-explore mode. `true` validates and authorizes the request but makes NO changes. Absent or `false` executes it for real — the server default is `false`; only this reference's try-it console pre-fills `true`.","schema":{"type":"boolean","default":true},"x-server-default":false}]},"delete":{"summary":"Archive (or, with force=true, hard-delete) a memory by scope+key; ?org=<slug> targets org-owned lore","tags":["Memories"],"description":"An invalid `scope` is a `400`, not a `404` — a bad scope is bad input, not a missing memory.","security":[{"BearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1},"required":false,"name":"scope","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":512},"required":false,"name":"key","in":"query"},{"schema":{"type":"string","enum":["true","false"],"default":"false"},"required":false,"name":"force","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":50},"required":false,"name":"org","in":"query"},{"name":"X-LoreKit-Client","in":"header","required":false,"description":"Which surface is calling. One of `dashboard`, `cli`, `mcp`, `api`; anything else is recorded as unattributed. Purely for usage analytics — it never changes the response. Optional: an absent header records this transport's own default (`api`), so send it only to identify a MORE SPECIFIC calling surface (e.g. `cli`). Reads attributed to `dashboard` are excluded from `GET /memories/read-activity`.","schema":{"type":"string","enum":["dashboard","cli","mcp","api"]}},{"name":"X-LoreKit-Dry-Run","in":"header","required":false,"description":"Safe-explore mode. `true` validates and authorizes the request but makes NO changes. Absent or `false` executes it for real — the server default is `false`; only this reference's try-it console pre-fills `true`.","schema":{"type":"boolean","default":true},"x-server-default":false}],"responses":{"204":{"description":"Archived or deleted"},"400":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"details":{"type":"object","additionalProperties":{}}},"required":["error"]}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"details":{"type":"object","additionalProperties":{}}},"required":["error"]}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"details":{"type":"object","additionalProperties":{}}},"required":["error"]}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"details":{"type":"object","additionalProperties":{}}},"required":["error"]}}}}}}},"/memories/list":{"post":{"summary":"List memories (filters in a JSON body)","tags":["Memories"],"description":"The same read as `GET /memories`.\n\nThe BODY form of the read above, for callers whose filters do not fit a URL. Every dimension is a real array (`{\"host\": [\"reviewer\", \"aw\"], \"host_mode\": \"in\"}`) bounded at 1000 values of 512 characters each, where the query form caps a dimension at 2048 characters and splits every value on a comma. Both transports decode to ONE normalised filter shape server-side, so they return the same rows and report under the same usage tool name — this is a transport choice and nothing else. The body is optional: a bodiless request is the unfiltered read.","security":[{"BearerAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"scope":{"type":"string","minLength":1},"key":{"type":"string","minLength":1,"maxLength":512},"key_prefix":{"type":"string","minLength":1,"maxLength":512},"q":{"type":"string","minLength":1,"maxLength":512},"created_since":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}([T ]\\d{2}:\\d{2}(:\\d{2}(\\.\\d{1,6})?)?(Z|[+-]\\d{2}:?\\d{2})?)?$"},"created_until":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}([T ]\\d{2}:\\d{2}(:\\d{2}(\\.\\d{1,6})?)?(Z|[+-]\\d{2}:?\\d{2})?)?$"},"tags":{"type":"array","items":{"type":"string","minLength":1,"maxLength":512},"maxItems":1000},"tags_mode":{"type":"string","enum":["any","all","none"],"default":"any"},"exclude_tags":{"type":"array","items":{"type":"string","minLength":1,"maxLength":512},"maxItems":1000},"source_agent":{"type":"array","items":{"type":"string","minLength":1,"maxLength":512},"maxItems":1000},"source_agent_mode":{"type":"string","enum":["in","nin"],"default":"in"},"trigger":{"type":"array","items":{"type":"string","minLength":1,"maxLength":512},"maxItems":1000},"trigger_mode":{"type":"string","enum":["in","nin"],"default":"in"},"kind":{"type":"array","items":{"type":"string","minLength":1,"maxLength":512},"maxItems":1000},"kind_mode":{"type":"string","enum":["in","nin"],"default":"in"},"host":{"type":"array","items":{"type":"string","minLength":1,"maxLength":512},"maxItems":1000},"host_mode":{"type":"string","enum":["in","nin"],"default":"in"},"origin_repo":{"type":"array","items":{"type":"string","minLength":1,"maxLength":512},"maxItems":1000},"origin_repo_mode":{"type":"string","enum":["in","nin"],"default":"in"},"origin_branch":{"type":"array","items":{"type":"string","minLength":1,"maxLength":512},"maxItems":1000},"origin_branch_mode":{"type":"string","enum":["in","nin"],"default":"in"},"origin_pr":{"type":"array","items":{"type":"string","minLength":1,"maxLength":512},"maxItems":1000},"origin_pr_mode":{"type":"string","enum":["in","nin"],"default":"in"},"owner":{"type":"array","items":{"type":"string","minLength":1,"maxLength":512},"maxItems":1000},"owner_mode":{"type":"string","enum":["in","nin"],"default":"in"},"sort":{"type":"string","enum":["updated_at","created_at","opened_count","last_opened_at"],"default":"updated_at"},"archived":{"type":"boolean","default":false},"expiring_within_days":{"type":"integer","minimum":1,"maximum":365},"min_age_days":{"type":"integer","minimum":1,"maximum":3650},"unseen_days":{"type":"integer","minimum":1,"maximum":3650},"max_seen_count":{"type":"integer","minimum":0,"maximum":100000},"max_read_count":{"type":"integer","minimum":0,"maximum":100000},"max_opened_count":{"type":"integer","minimum":0,"maximum":100000},"opened_within_days":{"type":"integer","minimum":1,"maximum":3650},"min_seen_count":{"type":"integer","minimum":2,"maximum":100000},"min_read_count":{"type":"integer","minimum":1,"maximum":100000},"min_opened_count":{"type":"integer","minimum":1,"maximum":100000},"limit":{"type":"integer","minimum":1,"maximum":100,"default":50},"cursor":{"type":"string"}}}}}},"responses":{"200":{"description":"Paginated memories","content":{"application/json":{"schema":{"type":"object","properties":{"entries":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"scope":{"type":"string"},"key":{"type":"string"},"value":{"type":"string"},"tags":{"type":"array","items":{"type":"string"}},"source_agent":{"type":["string","null"]},"trigger":{"type":["string","null"]},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"},"expires_at":{"type":["string","null"],"format":"date-time"},"archived_at":{"type":["string","null"],"format":"date-time"},"origin_repo":{"type":["string","null"]},"origin_branch":{"type":["string","null"]},"origin_commit":{"type":["string","null"]},"origin_pr":{"type":["number","null"]},"kind":{"type":["string","null"]},"host":{"type":["string","null"]},"seen_count":{"type":"integer"},"read_count":{"type":"integer","minimum":0},"last_read_at":{"type":["string","null"],"format":"date-time"},"last_opened_at":{"type":["string","null"],"format":"date-time"},"opened_count":{"type":"integer","minimum":0},"cited_count":{"type":"integer","minimum":0},"last_cited_at":{"type":["string","null"],"format":"date-time"},"org_id":{"type":["string","null"],"format":"uuid"},"org":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"slug":{"type":"string"}},"required":["id","name","slug"]},"created_by":{"type":["string","null"],"format":"uuid"},"updated_by":{"type":["string","null"],"format":"uuid"}},"required":["id","scope","key","value","tags","source_agent","trigger","created_at","updated_at","expires_at","archived_at"]}},"hasMore":{"type":"boolean"},"nextCursor":{"type":["string","null"]},"total":{"type":"integer","minimum":0}},"required":["entries","hasMore","nextCursor"]}}}},"400":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"details":{"type":"object","additionalProperties":{}}},"required":["error"]}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"details":{"type":"object","additionalProperties":{}}},"required":["error"]}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"details":{"type":"object","additionalProperties":{}}},"required":["error"]}}}}},"parameters":[{"name":"X-LoreKit-Client","in":"header","required":false,"description":"Which surface is calling. One of `dashboard`, `cli`, `mcp`, `api`; anything else is recorded as unattributed. Purely for usage analytics — it never changes the response. Optional: an absent header records this transport's own default (`api`), so send it only to identify a MORE SPECIFIC calling surface (e.g. `cli`). Reads attributed to `dashboard` are excluded from `GET /memories/read-activity`.","schema":{"type":"string","enum":["dashboard","cli","mcp","api"]}}]}},"/memories/search":{"post":{"summary":"Search memories with OR+AND filtering","tags":["Memories"],"security":[{"BearerAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"q":{"type":"string"},"scopes":{"type":"array","items":{"type":"string","minLength":1}},"tags":{"type":"array","items":{"type":"string"}},"filter":{"type":"object","description":"Recursive filter tree. Either a condition `{ field, op, value }` or a group `{ and: [...] }` / `{ or: [...] }`, nestable to any depth. Operators: is, is_not, contains, does_not_contain, starts_with, ends_with, is_set, is_not_set.","example":{"and":[{"field":"scope","op":"is","value":"global"},{"or":[{"field":"key","op":"contains","value":"auth"},{"field":"tags","op":"contains","value":"ci"}]}]}},"limit":{"type":"integer","minimum":1,"maximum":100,"default":50},"cursor":{"type":"string"}}}}}},"responses":{"200":{"description":"Search results","content":{"application/json":{"schema":{"type":"object","properties":{"entries":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"scope":{"type":"string"},"key":{"type":"string"},"value":{"type":"string"},"tags":{"type":"array","items":{"type":"string"}},"source_agent":{"type":["string","null"]},"trigger":{"type":["string","null"]},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"},"expires_at":{"type":["string","null"],"format":"date-time"},"archived_at":{"type":["string","null"],"format":"date-time"},"origin_repo":{"type":["string","null"]},"origin_branch":{"type":["string","null"]},"origin_commit":{"type":["string","null"]},"origin_pr":{"type":["number","null"]},"kind":{"type":["string","null"]},"host":{"type":["string","null"]},"seen_count":{"type":"integer"},"read_count":{"type":"integer","minimum":0},"last_read_at":{"type":["string","null"],"format":"date-time"},"last_opened_at":{"type":["string","null"],"format":"date-time"},"opened_count":{"type":"integer","minimum":0},"cited_count":{"type":"integer","minimum":0},"last_cited_at":{"type":["string","null"],"format":"date-time"},"org_id":{"type":["string","null"],"format":"uuid"},"org":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"slug":{"type":"string"}},"required":["id","name","slug"]},"created_by":{"type":["string","null"],"format":"uuid"},"updated_by":{"type":["string","null"],"format":"uuid"}},"required":["id","scope","key","value","tags","source_agent","trigger","created_at","updated_at","expires_at","archived_at"]}},"hasMore":{"type":"boolean"},"nextCursor":{"type":["string","null"]},"total":{"type":"integer","minimum":0}},"required":["entries","hasMore","nextCursor"]}}}},"400":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"details":{"type":"object","additionalProperties":{}}},"required":["error"]}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"details":{"type":"object","additionalProperties":{}}},"required":["error"]}}}}},"parameters":[{"name":"X-LoreKit-Client","in":"header","required":false,"description":"Which surface is calling. One of `dashboard`, `cli`, `mcp`, `api`; anything else is recorded as unattributed. Purely for usage analytics — it never changes the response. Optional: an absent header records this transport's own default (`api`), so send it only to identify a MORE SPECIFIC calling surface (e.g. `cli`). Reads attributed to `dashboard` are excluded from `GET /memories/read-activity`.","schema":{"type":"string","enum":["dashboard","cli","mcp","api"]}}]}},"/memories/restore":{"post":{"summary":"Restore an archived memory by scope+key","tags":["Memories"],"description":"An invalid `scope` is a `400`, not a `404` — a bad scope is bad input, not a missing memory.","security":[{"BearerAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"scope":{"type":"string","minLength":1},"key":{"type":"string","minLength":1,"maxLength":512}},"required":["scope","key"]}}}},"responses":{"200":{"description":"Restored","content":{"application/json":{"schema":{"type":"object","properties":{"restored":{"type":"boolean"}},"required":["restored"]}}}},"400":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"details":{"type":"object","additionalProperties":{}}},"required":["error"]}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"details":{"type":"object","additionalProperties":{}}},"required":["error"]}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"details":{"type":"object","additionalProperties":{}}},"required":["error"]}}}}},"parameters":[{"name":"X-LoreKit-Client","in":"header","required":false,"description":"Which surface is calling. One of `dashboard`, `cli`, `mcp`, `api`; anything else is recorded as unattributed. Purely for usage analytics — it never changes the response. Optional: an absent header records this transport's own default (`api`), so send it only to identify a MORE SPECIFIC calling surface (e.g. `cli`). Reads attributed to `dashboard` are excluded from `GET /memories/read-activity`.","schema":{"type":"string","enum":["dashboard","cli","mcp","api"]}},{"name":"X-LoreKit-Dry-Run","in":"header","required":false,"description":"Safe-explore mode. `true` validates and authorizes the request but makes NO changes. Absent or `false` executes it for real — the server default is `false`; only this reference's try-it console pre-fills `true`.","schema":{"type":"boolean","default":true},"x-server-default":false}]}},"/memories/purge":{"post":{"summary":"Hard-delete archived memories older than retention_days","tags":["Memories"],"security":[{"BearerAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"retention_days":{"type":"integer","minimum":1,"maximum":365,"default":30}}}}}},"responses":{"200":{"description":"Number of memories hard-deleted","content":{"application/json":{"schema":{"type":"object","properties":{"purged":{"type":"integer","minimum":0}},"required":["purged"]}}}},"400":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"details":{"type":"object","additionalProperties":{}}},"required":["error"]}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"details":{"type":"object","additionalProperties":{}}},"required":["error"]}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"details":{"type":"object","additionalProperties":{}}},"required":["error"]}}}},"429":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"details":{"type":"object","additionalProperties":{}}},"required":["error"]}}}}},"parameters":[{"name":"X-LoreKit-Client","in":"header","required":false,"description":"Which surface is calling. One of `dashboard`, `cli`, `mcp`, `api`; anything else is recorded as unattributed. Purely for usage analytics — it never changes the response. Optional: an absent header records this transport's own default (`api`), so send it only to identify a MORE SPECIFIC calling surface (e.g. `cli`). Reads attributed to `dashboard` are excluded from `GET /memories/read-activity`.","schema":{"type":"string","enum":["dashboard","cli","mcp","api"]}},{"name":"X-LoreKit-Dry-Run","in":"header","required":false,"description":"Safe-explore mode. `true` validates and authorizes the request but makes NO changes. Absent or `false` executes it for real — the server default is `false`; only this reference's try-it console pre-fills `true`.","schema":{"type":"boolean","default":true},"x-server-default":false}]}},"/memories/purge-expired":{"post":{"summary":"Hard-delete memories whose TTL has elapsed","tags":["Memories"],"security":[{"BearerAuth":[]}],"responses":{"200":{"description":"Number of memories hard-deleted","content":{"application/json":{"schema":{"type":"object","properties":{"purged":{"type":"integer","minimum":0}},"required":["purged"]}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"details":{"type":"object","additionalProperties":{}}},"required":["error"]}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"details":{"type":"object","additionalProperties":{}}},"required":["error"]}}}},"429":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"details":{"type":"object","additionalProperties":{}}},"required":["error"]}}}}},"parameters":[{"name":"X-LoreKit-Client","in":"header","required":false,"description":"Which surface is calling. One of `dashboard`, `cli`, `mcp`, `api`; anything else is recorded as unattributed. Purely for usage analytics — it never changes the response. Optional: an absent header records this transport's own default (`api`), so send it only to identify a MORE SPECIFIC calling surface (e.g. `cli`). Reads attributed to `dashboard` are excluded from `GET /memories/read-activity`.","schema":{"type":"string","enum":["dashboard","cli","mcp","api"]}},{"name":"X-LoreKit-Dry-Run","in":"header","required":false,"description":"Safe-explore mode. `true` validates and authorizes the request but makes NO changes. Absent or `false` executes it for real — the server default is `false`; only this reference's try-it console pre-fills `true`.","schema":{"type":"boolean","default":true},"x-server-default":false}]}},"/memories/scopes":{"get":{"summary":"List every visible scope with its active memory count","tags":["Memories"],"security":[{"BearerAuth":[]}],"responses":{"200":{"description":"Scopes","content":{"application/json":{"schema":{"type":"object","properties":{"scopes":{"type":"array","items":{"type":"object","properties":{"scope":{"type":"string"},"count":{"type":"integer","minimum":0},"last_activity":{"type":["string","null"]}},"required":["scope","count"]}}},"required":["scopes"]}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"details":{"type":"object","additionalProperties":{}}},"required":["error"]}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"details":{"type":"object","additionalProperties":{}}},"required":["error"]}}}}},"parameters":[{"name":"X-LoreKit-Client","in":"header","required":false,"description":"Which surface is calling. One of `dashboard`, `cli`, `mcp`, `api`; anything else is recorded as unattributed. Purely for usage analytics — it never changes the response. Optional: an absent header records this transport's own default (`api`), so send it only to identify a MORE SPECIFIC calling surface (e.g. `cli`). Reads attributed to `dashboard` are excluded from `GET /memories/read-activity`.","schema":{"type":"string","enum":["dashboard","cli","mcp","api"]}}]}},"/memories/quota":{"get":{"summary":"Your active memories against your plan cap, and how many you can still write","tags":["Memories"],"description":"`personal` is the pair the memory cap enforces: personal memories against the personal limit, with `remaining` writes left before `POST /memories` is refused with `memory_cap`. Org-owned memories count against each org's own cap, so they are reported as `org_count` and are not subtracted from `remaining`. A token narrowed to `personal` or to selected orgs gets `org_count` and `total` over only the orgs it reaches (`0` under `personal`). Requires a user-scoped credential; a service-role token has no user and gets 403.","security":[{"BearerAuth":[]}],"responses":{"200":{"description":"Quota","content":{"application/json":{"schema":{"type":"object","properties":{"plan":{"type":"string"},"personal":{"type":"object","properties":{"count":{"type":"integer","minimum":0},"limit":{"type":"integer","minimum":0},"remaining":{"type":"integer","minimum":0}},"required":["count","limit","remaining"]},"org_count":{"type":"integer","minimum":0},"total":{"type":"integer","minimum":0}},"required":["plan","personal","org_count","total"]}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"details":{"type":"object","additionalProperties":{}}},"required":["error"]}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"details":{"type":"object","additionalProperties":{}}},"required":["error"]}}}}},"parameters":[{"name":"X-LoreKit-Client","in":"header","required":false,"description":"Which surface is calling. One of `dashboard`, `cli`, `mcp`, `api`; anything else is recorded as unattributed. Purely for usage analytics — it never changes the response. Optional: an absent header records this transport's own default (`api`), so send it only to identify a MORE SPECIFIC calling surface (e.g. `cli`). Reads attributed to `dashboard` are excluded from `GET /memories/read-activity`.","schema":{"type":"string","enum":["dashboard","cli","mcp","api"]}}]}},"/memories/tags":{"get":{"summary":"List every visible label with how many memories carry it","tags":["Memories"],"security":[{"BearerAuth":[]}],"parameters":[{"schema":{"type":"string","enum":["true","false"],"default":"false"},"required":false,"name":"archived","in":"query"},{"name":"X-LoreKit-Client","in":"header","required":false,"description":"Which surface is calling. One of `dashboard`, `cli`, `mcp`, `api`; anything else is recorded as unattributed. Purely for usage analytics — it never changes the response. Optional: an absent header records this transport's own default (`api`), so send it only to identify a MORE SPECIFIC calling surface (e.g. `cli`). Reads attributed to `dashboard` are excluded from `GET /memories/read-activity`.","schema":{"type":"string","enum":["dashboard","cli","mcp","api"]}}],"responses":{"200":{"description":"Labels","content":{"application/json":{"schema":{"type":"object","properties":{"tags":{"type":"array","items":{"type":"object","properties":{"tag":{"type":"string"},"count":{"type":"integer","minimum":0}},"required":["tag","count"]}}},"required":["tags"]}}}},"400":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"details":{"type":"object","additionalProperties":{}}},"required":["error"]}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"details":{"type":"object","additionalProperties":{}}},"required":["error"]}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"details":{"type":"object","additionalProperties":{}}},"required":["error"]}}}}}}},"/memories/facets":{"get":{"summary":"List every filterable value (label, agent, trigger, repo, branch, pull request) with its memory count","tags":["Memories"],"description":"An invalid `scope` is a `400`, not a silently ignored filter — the menu counts and the list they drill into agree on what a scope is. The `created_since`/`created_until` window and the five retention thresholds (`min_age_days`, `unseen_days`, `max_seen_count`, `max_read_count`, `max_opened_count`) and their four reverse directions (`opened_within_days`, `min_seen_count`, `min_read_count`, `min_opened_count`) narrow the counted population exactly as they do on `GET /memories`, so a count matches the list under the same parameters. They emit no facet rows of their own — they are comparisons, not enumerable dimensions. `q`, `key` and `expiring_within_days` remain unmirrored, so with those active a count is an upper bound.","security":[{"BearerAuth":[]}],"parameters":[{"schema":{"type":"string","enum":["true","false"],"default":"false"},"required":false,"name":"archived","in":"query"},{"schema":{"type":"string"},"required":false,"name":"facets","in":"query"},{"schema":{"type":"string","minLength":1},"required":false,"name":"scope","in":"query"},{"schema":{"type":"string"},"required":false,"name":"tags","in":"query"},{"schema":{"type":"string","enum":["any","all","none"],"default":"any"},"required":false,"name":"tags_mode","in":"query"},{"schema":{"type":"string"},"required":false,"name":"exclude_tags","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":2048},"required":false,"name":"source_agent","in":"query"},{"schema":{"type":"string","enum":["in","nin"],"default":"in"},"required":false,"name":"source_agent_mode","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":2048},"required":false,"name":"trigger","in":"query"},{"schema":{"type":"string","enum":["in","nin"],"default":"in"},"required":false,"name":"trigger_mode","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":2048},"required":false,"name":"kind","in":"query"},{"schema":{"type":"string","enum":["in","nin"],"default":"in"},"required":false,"name":"kind_mode","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":2048},"required":false,"name":"host","in":"query"},{"schema":{"type":"string","enum":["in","nin"],"default":"in"},"required":false,"name":"host_mode","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":2048},"required":false,"name":"origin_repo","in":"query"},{"schema":{"type":"string","enum":["in","nin"],"default":"in"},"required":false,"name":"origin_repo_mode","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":2048},"required":false,"name":"origin_branch","in":"query"},{"schema":{"type":"string","enum":["in","nin"],"default":"in"},"required":false,"name":"origin_branch_mode","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":2048},"required":false,"name":"origin_pr","in":"query"},{"schema":{"type":"string","enum":["in","nin"],"default":"in"},"required":false,"name":"origin_pr_mode","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":2048},"required":false,"name":"owner","in":"query"},{"schema":{"type":"string","enum":["in","nin"],"default":"in"},"required":false,"name":"owner_mode","in":"query"},{"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}([T ]\\d{2}:\\d{2}(:\\d{2}(\\.\\d{1,6})?)?(Z|[+-]\\d{2}:?\\d{2})?)?$"},"required":false,"name":"created_since","in":"query"},{"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}([T ]\\d{2}:\\d{2}(:\\d{2}(\\.\\d{1,6})?)?(Z|[+-]\\d{2}:?\\d{2})?)?$"},"required":false,"name":"created_until","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":3650},"required":false,"name":"min_age_days","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":3650},"required":false,"name":"unseen_days","in":"query"},{"schema":{"type":["integer","null"],"minimum":0,"maximum":100000},"required":false,"name":"max_seen_count","in":"query"},{"schema":{"type":["integer","null"],"minimum":0,"maximum":100000},"required":false,"name":"max_read_count","in":"query"},{"schema":{"type":["integer","null"],"minimum":0,"maximum":100000},"required":false,"name":"max_opened_count","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":3650},"required":false,"name":"opened_within_days","in":"query"},{"schema":{"type":"integer","minimum":2,"maximum":100000},"required":false,"name":"min_seen_count","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100000},"required":false,"name":"min_read_count","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100000},"required":false,"name":"min_opened_count","in":"query"},{"name":"X-LoreKit-Client","in":"header","required":false,"description":"Which surface is calling. One of `dashboard`, `cli`, `mcp`, `api`; anything else is recorded as unattributed. Purely for usage analytics — it never changes the response. Optional: an absent header records this transport's own default (`api`), so send it only to identify a MORE SPECIFIC calling surface (e.g. `cli`). Reads attributed to `dashboard` are excluded from `GET /memories/read-activity`.","schema":{"type":"string","enum":["dashboard","cli","mcp","api"]}}],"responses":{"200":{"description":"Facet values","content":{"application/json":{"schema":{"type":"object","properties":{"facets":{"type":"array","items":{"type":"object","properties":{"facet":{"type":"string","enum":["tag","source_agent","trigger","kind","host","origin_repo","origin_branch","origin_pr","owner"]},"value":{"type":"string"},"count":{"type":"integer","minimum":0}},"required":["facet","value","count"]}}},"required":["facets"]}}}},"400":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"details":{"type":"object","additionalProperties":{}}},"required":["error"]}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"details":{"type":"object","additionalProperties":{}}},"required":["error"]}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"details":{"type":"object","additionalProperties":{}}},"required":["error"]}}}}}},"post":{"summary":"List every filterable value with its memory count (filters in a JSON body)","tags":["Memories"],"description":"The same drill-down catalog as `GET /memories/facets`. `facets` is an array of the closed facet vocabulary rather than a comma list, so an unknown name is a `400` here where the query form tolerated one and narrowed to nothing.\n\nThe BODY form of the read above, for callers whose filters do not fit a URL. Every dimension is a real array (`{\"host\": [\"reviewer\", \"aw\"], \"host_mode\": \"in\"}`) bounded at 1000 values of 512 characters each, where the query form caps a dimension at 2048 characters and splits every value on a comma. Both transports decode to ONE normalised filter shape server-side, so they return the same rows and report under the same usage tool name — this is a transport choice and nothing else. The body is optional: a bodiless request is the unfiltered read.","security":[{"BearerAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"archived":{"type":"boolean","default":false},"facets":{"type":"array","items":{"type":"string","enum":["tag","source_agent","trigger","kind","host","origin_repo","origin_branch","origin_pr","owner"]}},"scope":{"type":"string","minLength":1},"created_since":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}([T ]\\d{2}:\\d{2}(:\\d{2}(\\.\\d{1,6})?)?(Z|[+-]\\d{2}:?\\d{2})?)?$"},"created_until":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}([T ]\\d{2}:\\d{2}(:\\d{2}(\\.\\d{1,6})?)?(Z|[+-]\\d{2}:?\\d{2})?)?$"},"tags":{"type":"array","items":{"type":"string","minLength":1,"maxLength":512},"maxItems":1000},"tags_mode":{"type":"string","enum":["any","all","none"],"default":"any"},"exclude_tags":{"type":"array","items":{"type":"string","minLength":1,"maxLength":512},"maxItems":1000},"source_agent":{"type":"array","items":{"type":"string","minLength":1,"maxLength":512},"maxItems":1000},"source_agent_mode":{"type":"string","enum":["in","nin"],"default":"in"},"trigger":{"type":"array","items":{"type":"string","minLength":1,"maxLength":512},"maxItems":1000},"trigger_mode":{"type":"string","enum":["in","nin"],"default":"in"},"kind":{"type":"array","items":{"type":"string","minLength":1,"maxLength":512},"maxItems":1000},"kind_mode":{"type":"string","enum":["in","nin"],"default":"in"},"host":{"type":"array","items":{"type":"string","minLength":1,"maxLength":512},"maxItems":1000},"host_mode":{"type":"string","enum":["in","nin"],"default":"in"},"origin_repo":{"type":"array","items":{"type":"string","minLength":1,"maxLength":512},"maxItems":1000},"origin_repo_mode":{"type":"string","enum":["in","nin"],"default":"in"},"origin_branch":{"type":"array","items":{"type":"string","minLength":1,"maxLength":512},"maxItems":1000},"origin_branch_mode":{"type":"string","enum":["in","nin"],"default":"in"},"origin_pr":{"type":"array","items":{"type":"string","minLength":1,"maxLength":512},"maxItems":1000},"origin_pr_mode":{"type":"string","enum":["in","nin"],"default":"in"},"owner":{"type":"array","items":{"type":"string","minLength":1,"maxLength":512},"maxItems":1000},"owner_mode":{"type":"string","enum":["in","nin"],"default":"in"},"min_age_days":{"type":"integer","minimum":1,"maximum":3650},"unseen_days":{"type":"integer","minimum":1,"maximum":3650},"max_seen_count":{"type":"integer","minimum":0,"maximum":100000},"max_read_count":{"type":"integer","minimum":0,"maximum":100000},"max_opened_count":{"type":"integer","minimum":0,"maximum":100000},"opened_within_days":{"type":"integer","minimum":1,"maximum":3650},"min_seen_count":{"type":"integer","minimum":2,"maximum":100000},"min_read_count":{"type":"integer","minimum":1,"maximum":100000},"min_opened_count":{"type":"integer","minimum":1,"maximum":100000}}}}}},"responses":{"200":{"description":"Facet values","content":{"application/json":{"schema":{"type":"object","properties":{"facets":{"type":"array","items":{"type":"object","properties":{"facet":{"type":"string","enum":["tag","source_agent","trigger","kind","host","origin_repo","origin_branch","origin_pr","owner"]},"value":{"type":"string"},"count":{"type":"integer","minimum":0}},"required":["facet","value","count"]}}},"required":["facets"]}}}},"400":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"details":{"type":"object","additionalProperties":{}}},"required":["error"]}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"details":{"type":"object","additionalProperties":{}}},"required":["error"]}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"details":{"type":"object","additionalProperties":{}}},"required":["error"]}}}}},"parameters":[{"name":"X-LoreKit-Client","in":"header","required":false,"description":"Which surface is calling. One of `dashboard`, `cli`, `mcp`, `api`; anything else is recorded as unattributed. Purely for usage analytics — it never changes the response. Optional: an absent header records this transport's own default (`api`), so send it only to identify a MORE SPECIFIC calling surface (e.g. `cli`). Reads attributed to `dashboard` are excluded from `GET /memories/read-activity`.","schema":{"type":"string","enum":["dashboard","cli","mcp","api"]}}]}},"/memories/pivot":{"get":{"summary":"Cross-tabulate two filterable dimensions and count the memories in each cell","tags":["Memories"],"description":"`GET /memories/facets` with a second group-by. `row` and `col` name any two of the facet dimensions (they may be the same, giving that dimension’s diagonal). **Both axes are self-excluded from the filters**, so a caller that turns a cell into `row in [x] AND col in [y]` and asks again still gets every other cell back — that is what keeps a drilled-in grid navigable instead of collapsing to the clicked cell. A pair counting zero emits no cell. `truncated` reports whether `limit` cut the grid. The `created_since`/`created_until` window, the five retention thresholds and their four reverse directions narrow the counted population, matching `GET /memories/facets`.","security":[{"BearerAuth":[]}],"parameters":[{"schema":{"type":"string","enum":["tag","source_agent","trigger","kind","host","origin_repo","origin_branch","origin_pr","owner"]},"required":true,"name":"row","in":"query"},{"schema":{"type":"string","enum":["tag","source_agent","trigger","kind","host","origin_repo","origin_branch","origin_pr","owner"]},"required":true,"name":"col","in":"query"},{"schema":{"type":"string","enum":["true","false"],"default":"false"},"required":false,"name":"archived","in":"query"},{"schema":{"type":"string","pattern":"^\\d+$"},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string","minLength":1},"required":false,"name":"scope","in":"query"},{"schema":{"type":"string"},"required":false,"name":"tags","in":"query"},{"schema":{"type":"string","enum":["any","all","none"],"default":"any"},"required":false,"name":"tags_mode","in":"query"},{"schema":{"type":"string"},"required":false,"name":"exclude_tags","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":2048},"required":false,"name":"source_agent","in":"query"},{"schema":{"type":"string","enum":["in","nin"],"default":"in"},"required":false,"name":"source_agent_mode","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":2048},"required":false,"name":"trigger","in":"query"},{"schema":{"type":"string","enum":["in","nin"],"default":"in"},"required":false,"name":"trigger_mode","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":2048},"required":false,"name":"kind","in":"query"},{"schema":{"type":"string","enum":["in","nin"],"default":"in"},"required":false,"name":"kind_mode","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":2048},"required":false,"name":"host","in":"query"},{"schema":{"type":"string","enum":["in","nin"],"default":"in"},"required":false,"name":"host_mode","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":2048},"required":false,"name":"origin_repo","in":"query"},{"schema":{"type":"string","enum":["in","nin"],"default":"in"},"required":false,"name":"origin_repo_mode","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":2048},"required":false,"name":"origin_branch","in":"query"},{"schema":{"type":"string","enum":["in","nin"],"default":"in"},"required":false,"name":"origin_branch_mode","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":2048},"required":false,"name":"origin_pr","in":"query"},{"schema":{"type":"string","enum":["in","nin"],"default":"in"},"required":false,"name":"origin_pr_mode","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":2048},"required":false,"name":"owner","in":"query"},{"schema":{"type":"string","enum":["in","nin"],"default":"in"},"required":false,"name":"owner_mode","in":"query"},{"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}([T ]\\d{2}:\\d{2}(:\\d{2}(\\.\\d{1,6})?)?(Z|[+-]\\d{2}:?\\d{2})?)?$"},"required":false,"name":"created_since","in":"query"},{"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}([T ]\\d{2}:\\d{2}(:\\d{2}(\\.\\d{1,6})?)?(Z|[+-]\\d{2}:?\\d{2})?)?$"},"required":false,"name":"created_until","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":3650},"required":false,"name":"min_age_days","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":3650},"required":false,"name":"unseen_days","in":"query"},{"schema":{"type":["integer","null"],"minimum":0,"maximum":100000},"required":false,"name":"max_seen_count","in":"query"},{"schema":{"type":["integer","null"],"minimum":0,"maximum":100000},"required":false,"name":"max_read_count","in":"query"},{"schema":{"type":["integer","null"],"minimum":0,"maximum":100000},"required":false,"name":"max_opened_count","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":3650},"required":false,"name":"opened_within_days","in":"query"},{"schema":{"type":"integer","minimum":2,"maximum":100000},"required":false,"name":"min_seen_count","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100000},"required":false,"name":"min_read_count","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100000},"required":false,"name":"min_opened_count","in":"query"},{"name":"X-LoreKit-Client","in":"header","required":false,"description":"Which surface is calling. One of `dashboard`, `cli`, `mcp`, `api`; anything else is recorded as unattributed. Purely for usage analytics — it never changes the response. Optional: an absent header records this transport's own default (`api`), so send it only to identify a MORE SPECIFIC calling surface (e.g. `cli`). Reads attributed to `dashboard` are excluded from `GET /memories/read-activity`.","schema":{"type":"string","enum":["dashboard","cli","mcp","api"]}}],"responses":{"200":{"description":"Pivot cells","content":{"application/json":{"schema":{"type":"object","properties":{"row":{"type":"string","enum":["tag","source_agent","trigger","kind","host","origin_repo","origin_branch","origin_pr","owner"]},"col":{"type":"string","enum":["tag","source_agent","trigger","kind","host","origin_repo","origin_branch","origin_pr","owner"]},"cells":{"type":"array","items":{"type":"object","properties":{"row":{"type":"string"},"col":{"type":"string"},"count":{"type":"integer","minimum":0}},"required":["row","col","count"]}},"truncated":{"type":"boolean"}},"required":["row","col","cells","truncated"]}}}},"400":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"details":{"type":"object","additionalProperties":{}}},"required":["error"]}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"details":{"type":"object","additionalProperties":{}}},"required":["error"]}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"details":{"type":"object","additionalProperties":{}}},"required":["error"]}}}}}},"post":{"summary":"Cross-tabulate two dimensions (filters in a JSON body)","tags":["Memories"],"description":"The same cross-tabulation as `GET /memories/pivot`.\n\nThe BODY form of the read above, for callers whose filters do not fit a URL. Every dimension is a real array (`{\"host\": [\"reviewer\", \"aw\"], \"host_mode\": \"in\"}`) bounded at 1000 values of 512 characters each, where the query form caps a dimension at 2048 characters and splits every value on a comma. Both transports decode to ONE normalised filter shape server-side, so they return the same rows and report under the same usage tool name — this is a transport choice and nothing else. The body is optional: a bodiless request is the unfiltered read.","security":[{"BearerAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"row":{"type":"string","enum":["tag","source_agent","trigger","kind","host","origin_repo","origin_branch","origin_pr","owner"]},"col":{"type":"string","enum":["tag","source_agent","trigger","kind","host","origin_repo","origin_branch","origin_pr","owner"]},"archived":{"type":"boolean","default":false},"limit":{"type":"integer","minimum":1,"maximum":2000},"scope":{"type":"string","minLength":1},"created_since":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}([T ]\\d{2}:\\d{2}(:\\d{2}(\\.\\d{1,6})?)?(Z|[+-]\\d{2}:?\\d{2})?)?$"},"created_until":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}([T ]\\d{2}:\\d{2}(:\\d{2}(\\.\\d{1,6})?)?(Z|[+-]\\d{2}:?\\d{2})?)?$"},"tags":{"type":"array","items":{"type":"string","minLength":1,"maxLength":512},"maxItems":1000},"tags_mode":{"type":"string","enum":["any","all","none"],"default":"any"},"exclude_tags":{"type":"array","items":{"type":"string","minLength":1,"maxLength":512},"maxItems":1000},"source_agent":{"type":"array","items":{"type":"string","minLength":1,"maxLength":512},"maxItems":1000},"source_agent_mode":{"type":"string","enum":["in","nin"],"default":"in"},"trigger":{"type":"array","items":{"type":"string","minLength":1,"maxLength":512},"maxItems":1000},"trigger_mode":{"type":"string","enum":["in","nin"],"default":"in"},"kind":{"type":"array","items":{"type":"string","minLength":1,"maxLength":512},"maxItems":1000},"kind_mode":{"type":"string","enum":["in","nin"],"default":"in"},"host":{"type":"array","items":{"type":"string","minLength":1,"maxLength":512},"maxItems":1000},"host_mode":{"type":"string","enum":["in","nin"],"default":"in"},"origin_repo":{"type":"array","items":{"type":"string","minLength":1,"maxLength":512},"maxItems":1000},"origin_repo_mode":{"type":"string","enum":["in","nin"],"default":"in"},"origin_branch":{"type":"array","items":{"type":"string","minLength":1,"maxLength":512},"maxItems":1000},"origin_branch_mode":{"type":"string","enum":["in","nin"],"default":"in"},"origin_pr":{"type":"array","items":{"type":"string","minLength":1,"maxLength":512},"maxItems":1000},"origin_pr_mode":{"type":"string","enum":["in","nin"],"default":"in"},"owner":{"type":"array","items":{"type":"string","minLength":1,"maxLength":512},"maxItems":1000},"owner_mode":{"type":"string","enum":["in","nin"],"default":"in"},"min_age_days":{"type":"integer","minimum":1,"maximum":3650},"unseen_days":{"type":"integer","minimum":1,"maximum":3650},"max_seen_count":{"type":"integer","minimum":0,"maximum":100000},"max_read_count":{"type":"integer","minimum":0,"maximum":100000},"max_opened_count":{"type":"integer","minimum":0,"maximum":100000},"opened_within_days":{"type":"integer","minimum":1,"maximum":3650},"min_seen_count":{"type":"integer","minimum":2,"maximum":100000},"min_read_count":{"type":"integer","minimum":1,"maximum":100000},"min_opened_count":{"type":"integer","minimum":1,"maximum":100000}},"required":["row","col"]}}}},"responses":{"200":{"description":"Pivot cells","content":{"application/json":{"schema":{"type":"object","properties":{"row":{"type":"string","enum":["tag","source_agent","trigger","kind","host","origin_repo","origin_branch","origin_pr","owner"]},"col":{"type":"string","enum":["tag","source_agent","trigger","kind","host","origin_repo","origin_branch","origin_pr","owner"]},"cells":{"type":"array","items":{"type":"object","properties":{"row":{"type":"string"},"col":{"type":"string"},"count":{"type":"integer","minimum":0}},"required":["row","col","count"]}},"truncated":{"type":"boolean"}},"required":["row","col","cells","truncated"]}}}},"400":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"details":{"type":"object","additionalProperties":{}}},"required":["error"]}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"details":{"type":"object","additionalProperties":{}}},"required":["error"]}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"details":{"type":"object","additionalProperties":{}}},"required":["error"]}}}}},"parameters":[{"name":"X-LoreKit-Client","in":"header","required":false,"description":"Which surface is calling. One of `dashboard`, `cli`, `mcp`, `api`; anything else is recorded as unattributed. Purely for usage analytics — it never changes the response. Optional: an absent header records this transport's own default (`api`), so send it only to identify a MORE SPECIFIC calling surface (e.g. `cli`). Reads attributed to `dashboard` are excluded from `GET /memories/read-activity`.","schema":{"type":"string","enum":["dashboard","cli","mcp","api"]}}]}},"/memories/activity":{"get":{"summary":"Memories created per UTC hour/day per scope over a window","tags":["Memories"],"description":"An invalid `scope` is a `400`, not a silently ignored filter — the same rule the read counterpart `GET /memories/read-activity` follows. The five retention thresholds (`min_age_days`, `unseen_days`, `max_seen_count`, `max_read_count`, `max_opened_count`) and their four reverse directions (`opened_within_days`, `min_seen_count`, `min_read_count`, `min_opened_count`) narrow the counted population exactly as they do on `GET /memories`, so a series matches the list under the same parameters. There is no `created_since`/`created_until` pair here, unlike `/facets` and `/pivot`: this route’s own `since`/`until` already bound `created_at`.","security":[{"BearerAuth":[]}],"parameters":[{"schema":{"type":"string","enum":["hour","day"],"default":"day"},"required":false,"name":"bucket","in":"query"},{"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}([T ]\\d{2}:\\d{2}(:\\d{2}(\\.\\d{1,6})?)?(Z|[+-]\\d{2}:?\\d{2})?)?$"},"required":false,"name":"since","in":"query"},{"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}([T ]\\d{2}:\\d{2}(:\\d{2}(\\.\\d{1,6})?)?(Z|[+-]\\d{2}:?\\d{2})?)?$"},"required":false,"name":"until","in":"query"},{"schema":{"type":"string","minLength":1},"required":false,"name":"scope","in":"query"},{"schema":{"type":"string"},"required":false,"name":"tags","in":"query"},{"schema":{"type":"string","enum":["any","all","none"],"default":"any"},"required":false,"name":"tags_mode","in":"query"},{"schema":{"type":"string"},"required":false,"name":"exclude_tags","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":2048},"required":false,"name":"source_agent","in":"query"},{"schema":{"type":"string","enum":["in","nin"],"default":"in"},"required":false,"name":"source_agent_mode","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":2048},"required":false,"name":"trigger","in":"query"},{"schema":{"type":"string","enum":["in","nin"],"default":"in"},"required":false,"name":"trigger_mode","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":2048},"required":false,"name":"kind","in":"query"},{"schema":{"type":"string","enum":["in","nin"],"default":"in"},"required":false,"name":"kind_mode","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":2048},"required":false,"name":"host","in":"query"},{"schema":{"type":"string","enum":["in","nin"],"default":"in"},"required":false,"name":"host_mode","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":2048},"required":false,"name":"origin_repo","in":"query"},{"schema":{"type":"string","enum":["in","nin"],"default":"in"},"required":false,"name":"origin_repo_mode","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":2048},"required":false,"name":"origin_branch","in":"query"},{"schema":{"type":"string","enum":["in","nin"],"default":"in"},"required":false,"name":"origin_branch_mode","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":2048},"required":false,"name":"origin_pr","in":"query"},{"schema":{"type":"string","enum":["in","nin"],"default":"in"},"required":false,"name":"origin_pr_mode","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":2048},"required":false,"name":"owner","in":"query"},{"schema":{"type":"string","enum":["in","nin"],"default":"in"},"required":false,"name":"owner_mode","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":3650},"required":false,"name":"min_age_days","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":3650},"required":false,"name":"unseen_days","in":"query"},{"schema":{"type":["integer","null"],"minimum":0,"maximum":100000},"required":false,"name":"max_seen_count","in":"query"},{"schema":{"type":["integer","null"],"minimum":0,"maximum":100000},"required":false,"name":"max_read_count","in":"query"},{"schema":{"type":["integer","null"],"minimum":0,"maximum":100000},"required":false,"name":"max_opened_count","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":3650},"required":false,"name":"opened_within_days","in":"query"},{"schema":{"type":"integer","minimum":2,"maximum":100000},"required":false,"name":"min_seen_count","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100000},"required":false,"name":"min_read_count","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100000},"required":false,"name":"min_opened_count","in":"query"},{"name":"X-LoreKit-Client","in":"header","required":false,"description":"Which surface is calling. One of `dashboard`, `cli`, `mcp`, `api`; anything else is recorded as unattributed. Purely for usage analytics — it never changes the response. Optional: an absent header records this transport's own default (`api`), so send it only to identify a MORE SPECIFIC calling surface (e.g. `cli`). Reads attributed to `dashboard` are excluded from `GET /memories/read-activity`.","schema":{"type":"string","enum":["dashboard","cli","mcp","api"]}}],"responses":{"200":{"description":"Activity buckets","content":{"application/json":{"schema":{"type":"object","properties":{"bucket":{"type":"string","enum":["hour","day"]},"since":{"type":"string"},"until":{"type":"string"},"buckets":{"type":"array","items":{"type":"object","properties":{"bucket":{"type":"string"},"scope":{"type":"string"},"count":{"type":"integer","minimum":0}},"required":["bucket","scope","count"]}}},"required":["bucket","since","until","buckets"]}}}},"400":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"details":{"type":"object","additionalProperties":{}}},"required":["error"]}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"details":{"type":"object","additionalProperties":{}}},"required":["error"]}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"details":{"type":"object","additionalProperties":{}}},"required":["error"]}}}}}},"post":{"summary":"Memories created per UTC hour/day per scope over a window (filters in a JSON body)","tags":["Memories"],"description":"The same series as `GET /memories/activity`.\n\nThe BODY form of the read above, for callers whose filters do not fit a URL. Every dimension is a real array (`{\"host\": [\"reviewer\", \"aw\"], \"host_mode\": \"in\"}`) bounded at 1000 values of 512 characters each, where the query form caps a dimension at 2048 characters and splits every value on a comma. Both transports decode to ONE normalised filter shape server-side, so they return the same rows and report under the same usage tool name — this is a transport choice and nothing else. The body is optional: a bodiless request is the unfiltered read.","security":[{"BearerAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"bucket":{"type":"string","enum":["hour","day"],"default":"day"},"since":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}([T ]\\d{2}:\\d{2}(:\\d{2}(\\.\\d{1,6})?)?(Z|[+-]\\d{2}:?\\d{2})?)?$"},"until":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}([T ]\\d{2}:\\d{2}(:\\d{2}(\\.\\d{1,6})?)?(Z|[+-]\\d{2}:?\\d{2})?)?$"},"scope":{"type":"string","minLength":1},"tags":{"type":"array","items":{"type":"string","minLength":1,"maxLength":512},"maxItems":1000},"tags_mode":{"type":"string","enum":["any","all","none"],"default":"any"},"exclude_tags":{"type":"array","items":{"type":"string","minLength":1,"maxLength":512},"maxItems":1000},"source_agent":{"type":"array","items":{"type":"string","minLength":1,"maxLength":512},"maxItems":1000},"source_agent_mode":{"type":"string","enum":["in","nin"],"default":"in"},"trigger":{"type":"array","items":{"type":"string","minLength":1,"maxLength":512},"maxItems":1000},"trigger_mode":{"type":"string","enum":["in","nin"],"default":"in"},"kind":{"type":"array","items":{"type":"string","minLength":1,"maxLength":512},"maxItems":1000},"kind_mode":{"type":"string","enum":["in","nin"],"default":"in"},"host":{"type":"array","items":{"type":"string","minLength":1,"maxLength":512},"maxItems":1000},"host_mode":{"type":"string","enum":["in","nin"],"default":"in"},"origin_repo":{"type":"array","items":{"type":"string","minLength":1,"maxLength":512},"maxItems":1000},"origin_repo_mode":{"type":"string","enum":["in","nin"],"default":"in"},"origin_branch":{"type":"array","items":{"type":"string","minLength":1,"maxLength":512},"maxItems":1000},"origin_branch_mode":{"type":"string","enum":["in","nin"],"default":"in"},"origin_pr":{"type":"array","items":{"type":"string","minLength":1,"maxLength":512},"maxItems":1000},"origin_pr_mode":{"type":"string","enum":["in","nin"],"default":"in"},"owner":{"type":"array","items":{"type":"string","minLength":1,"maxLength":512},"maxItems":1000},"owner_mode":{"type":"string","enum":["in","nin"],"default":"in"},"min_age_days":{"type":"integer","minimum":1,"maximum":3650},"unseen_days":{"type":"integer","minimum":1,"maximum":3650},"max_seen_count":{"type":"integer","minimum":0,"maximum":100000},"max_read_count":{"type":"integer","minimum":0,"maximum":100000},"max_opened_count":{"type":"integer","minimum":0,"maximum":100000},"opened_within_days":{"type":"integer","minimum":1,"maximum":3650},"min_seen_count":{"type":"integer","minimum":2,"maximum":100000},"min_read_count":{"type":"integer","minimum":1,"maximum":100000},"min_opened_count":{"type":"integer","minimum":1,"maximum":100000}}}}}},"responses":{"200":{"description":"Activity buckets","content":{"application/json":{"schema":{"type":"object","properties":{"bucket":{"type":"string","enum":["hour","day"]},"since":{"type":"string"},"until":{"type":"string"},"buckets":{"type":"array","items":{"type":"object","properties":{"bucket":{"type":"string"},"scope":{"type":"string"},"count":{"type":"integer","minimum":0}},"required":["bucket","scope","count"]}}},"required":["bucket","since","until","buckets"]}}}},"400":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"details":{"type":"object","additionalProperties":{}}},"required":["error"]}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"details":{"type":"object","additionalProperties":{}}},"required":["error"]}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"details":{"type":"object","additionalProperties":{}}},"required":["error"]}}}}},"parameters":[{"name":"X-LoreKit-Client","in":"header","required":false,"description":"Which surface is calling. One of `dashboard`, `cli`, `mcp`, `api`; anything else is recorded as unattributed. Purely for usage analytics — it never changes the response. Optional: an absent header records this transport's own default (`api`), so send it only to identify a MORE SPECIFIC calling surface (e.g. `cli`). Reads attributed to `dashboard` are excluded from `GET /memories/read-activity`.","schema":{"type":"string","enum":["dashboard","cli","mcp","api"]}}]}},"/memories/read-activity":{"get":{"summary":"Memory records read per UTC hour/day over a window","tags":["Memories"],"description":"Records read (not read *calls*) per bucket, summed over `memory.read` / `memory.list` / `memory.search` / `memory.list_archived`. Calls that identified themselves as the LoreKit dashboard (`X-LoreKit-Client: dashboard`) are EXCLUDED: browsing your own lore in the web UI is visualisation, not consumption, and would otherwise make this series grow every time you looked at it. `GET /memories/usage` still counts them — use it for the complete ledger.\n\nBuckets are returned one per `(bucket, scope, read_kind)` cell, mirroring `GET /memories/activity`. `scope` is nullable: a read whose scope the server could not resolve (carried in a request body, or ungrammatical) is recorded as unattributed rather than dropped, so it still counts toward the unfiltered total. Pass the optional `scope` query parameter to restrict the series to one exact scope; because the metric is additive, those buckets SUM to the per-scope headline. That per-scope total can legitimately be SMALLER than the account total — the difference is the unattributable reads. An invalid `scope` is a `400`, not a silently ignored filter.\n\n`read_kind` (migration 00080) splits retrieved from opened: `'targeted'` is `memory.read` (one exact scope+key — an agent deliberately opening a specific lesson); `'bulk'` is `memory.list`/`memory.search`/`memory.list_archived` (every row a listing call returned, e.g. a session-start hook injecting lessons). Retrieved + opened sum to the same total this endpoint always returned — the split refines the series, it does not change it.","security":[{"BearerAuth":[]}],"parameters":[{"schema":{"type":"string","enum":["hour","day"],"default":"day"},"required":false,"name":"bucket","in":"query"},{"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}([T ]\\d{2}:\\d{2}(:\\d{2}(\\.\\d{1,6})?)?(Z|[+-]\\d{2}:?\\d{2})?)?$"},"required":false,"name":"since","in":"query"},{"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}([T ]\\d{2}:\\d{2}(:\\d{2}(\\.\\d{1,6})?)?(Z|[+-]\\d{2}:?\\d{2})?)?$"},"required":false,"name":"until","in":"query"},{"schema":{"type":"string","minLength":1},"required":false,"name":"scope","in":"query"},{"name":"X-LoreKit-Client","in":"header","required":false,"description":"Which surface is calling. One of `dashboard`, `cli`, `mcp`, `api`; anything else is recorded as unattributed. Purely for usage analytics — it never changes the response. Optional: an absent header records this transport's own default (`api`), so send it only to identify a MORE SPECIFIC calling surface (e.g. `cli`). Reads attributed to `dashboard` are excluded from `GET /memories/read-activity`.","schema":{"type":"string","enum":["dashboard","cli","mcp","api"]}}],"responses":{"200":{"description":"Read-activity buckets","content":{"application/json":{"schema":{"type":"object","properties":{"bucket":{"type":"string","enum":["hour","day"]},"since":{"type":"string"},"until":{"type":"string"},"buckets":{"type":"array","items":{"type":"object","properties":{"bucket":{"type":"string"},"scope":{"type":["string","null"]},"read_kind":{"type":"string","enum":["targeted","bulk"]},"count":{"type":"integer","minimum":0}},"required":["bucket","scope","count"]}}},"required":["bucket","since","until","buckets"]}}}},"400":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"details":{"type":"object","additionalProperties":{}}},"required":["error"]}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"details":{"type":"object","additionalProperties":{}}},"required":["error"]}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"details":{"type":"object","additionalProperties":{}}},"required":["error"]}}}}}}},"/memories/read-ranking":{"get":{"summary":"Memories ranked by how often they have actually been read (hot or cold lore)","tags":["Memories"],"description":"Ranks memories by `read_count` (migration 00077) — how many times a `memory.read` / `memory.list` / `memory.search` / `memory.list_archived` call actually returned this exact row, not just how often the account read *something*. `direction=hot` (default) surfaces the most-consumed lore first; `direction=cold` surfaces the least, oldest-created first among ties — the prune-list input the `lorekit-groom` skill consumes.\n\n`counting_since` is the date this counter started: a `cold` row with `read_count: 0` means \"not read since that date\", never \"never read\" — a memory written earlier may have been read plenty under the old, uncounted regime. Render the qualifier; never the bare word \"never\". `seen_count` (how many times the memory has been WRITTEN) rides along so a reader can compare consumption against recurrence in one response. Active memories only (archived/expired rows are excluded — they are already pruned). An invalid `scope` is a `400`, not a silently ignored filter.","security":[{"BearerAuth":[]}],"parameters":[{"schema":{"type":"string","enum":["hot","cold"],"default":"hot"},"required":false,"name":"direction","in":"query"},{"schema":{"type":"string","minLength":1},"required":false,"name":"scope","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100,"default":20},"required":false,"name":"limit","in":"query"},{"name":"X-LoreKit-Client","in":"header","required":false,"description":"Which surface is calling. One of `dashboard`, `cli`, `mcp`, `api`; anything else is recorded as unattributed. Purely for usage analytics — it never changes the response. Optional: an absent header records this transport's own default (`api`), so send it only to identify a MORE SPECIFIC calling surface (e.g. `cli`). Reads attributed to `dashboard` are excluded from `GET /memories/read-activity`.","schema":{"type":"string","enum":["dashboard","cli","mcp","api"]}}],"responses":{"200":{"description":"Ranked memories","content":{"application/json":{"schema":{"type":"object","properties":{"direction":{"type":"string","enum":["hot","cold"]},"counting_since":{"type":"string","format":"date-time"},"entries":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"scope":{"type":"string"},"key":{"type":"string"},"read_count":{"type":"integer","minimum":0},"last_read_at":{"type":["string","null"],"format":"date-time"},"seen_count":{"type":"integer"},"created_at":{"type":"string","format":"date-time"}},"required":["id","scope","key","read_count","last_read_at","created_at"]}}},"required":["direction","counting_since","entries"]}}}},"400":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"details":{"type":"object","additionalProperties":{}}},"required":["error"]}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"details":{"type":"object","additionalProperties":{}}},"required":["error"]}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"details":{"type":"object","additionalProperties":{}}},"required":["error"]}}}}}}},"/memories/utility":{"get":{"summary":"Every lesson placed on the delivered × chosen grid, plus what delivery costs","tags":["Memories"],"description":"Answers \"is this lore earning its place?\" by dividing rather than ranking. `read_count` counts every read including the bulk ride-alongs in a `memory.list` page (99.80% of them), so ranking by it — which `GET /memories/read-ranking` does — mostly ranks SCOPE BREADTH, and its cold end nominates narrow scopes for pruning instead of unused lore. Pull-through (`opened_count / read_count`, migration 00104) is a proper fraction, so the breadth appears in both halves and cancels.\n\nTwo axes give four quadrants plus a fifth state: **load-bearing** (delivered widely, chosen often — promote to a rule), **specialist** (narrow reach, high uptake — broaden its scope), **noise-tax** (injected constantly, never chosen — prune first), **dormant** (rarely offered, never taken — archive), and **unproven** (too young or too few deliveries to read a rate from). `unproven` is not a hedge: it is the state today's UI cannot express, where a fresh memory and a dead one look identical. The `thresholds` that draw the lines travel in every response so a client can caption them rather than restate them.\n\n**Two windows, and both are reported.** `census` counts the LIFETIME counters on `memories` — the same two columns a per-lesson chip reads, so a card and the grid cannot disagree — while `cost` sums `memory_read_daily` over `[since, until)`, the only source that can be windowed at all. Caption each; do not present one as the other.\n\n`cost.delivered_tokens` is ESTIMATED at four characters per token, not tokenized — the figure is an order of magnitude for a headline, and any surface rendering it must say so. `counting_since` is the date read counting started: a `0` means \"not delivered since that date\", never \"never delivered\". Passing `quadrant` additionally returns that quadrant's rows (`entries`); omitting it returns the counts alone. An invalid `scope` is a `400`.","security":[{"BearerAuth":[]}],"parameters":[{"schema":{"type":"string","enum":["load-bearing","specialist","noise-tax","dormant","unproven"]},"required":false,"name":"quadrant","in":"query"},{"schema":{"type":"string","minLength":1},"required":false,"name":"scope","in":"query"},{"schema":{"type":"string","format":"date-time"},"required":false,"name":"since","in":"query"},{"schema":{"type":"string","format":"date-time"},"required":false,"name":"until","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100,"default":20},"required":false,"name":"limit","in":"query"},{"name":"X-LoreKit-Client","in":"header","required":false,"description":"Which surface is calling. One of `dashboard`, `cli`, `mcp`, `api`; anything else is recorded as unattributed. Purely for usage analytics — it never changes the response. Optional: an absent header records this transport's own default (`api`), so send it only to identify a MORE SPECIFIC calling surface (e.g. `cli`). Reads attributed to `dashboard` are excluded from `GET /memories/read-activity`.","schema":{"type":"string","enum":["dashboard","cli","mcp","api"]}}],"responses":{"200":{"description":"Quadrant census, delivery cost, and the requested quadrant's rows","content":{"application/json":{"schema":{"type":"object","properties":{"thresholds":{"type":"object","properties":{"min_deliveries":{"type":"integer","minimum":0},"min_age_days":{"type":"integer","minimum":0},"chosen_pull_through":{"type":"number"},"broad_reach_deliveries":{"type":"integer","minimum":0}},"required":["min_deliveries","min_age_days","chosen_pull_through","broad_reach_deliveries"]},"counting_since":{"type":"string","format":"date-time"},"census":{"type":"object","properties":{"load-bearing":{"type":"integer","minimum":0},"specialist":{"type":"integer","minimum":0},"noise-tax":{"type":"integer","minimum":0},"dormant":{"type":"integer","minimum":0},"unproven":{"type":"integer","minimum":0}},"required":["load-bearing","specialist","noise-tax","dormant","unproven"]},"cost":{"type":"object","properties":{"delivered_reads":{"type":"integer","minimum":0},"chosen_reads":{"type":"integer","minimum":0},"delivered_tokens":{"type":"integer","minimum":0},"chosen_tokens":{"type":"integer","minimum":0}},"required":["delivered_reads","chosen_reads","delivered_tokens","chosen_tokens"]},"window":{"type":"object","properties":{"since":{"type":["string","null"],"format":"date-time"},"until":{"type":["string","null"],"format":"date-time"}},"required":["since","until"]},"quadrant":{"type":["string","null"],"enum":["load-bearing","specialist","noise-tax","dormant","unproven"]},"entries":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"scope":{"type":"string"},"key":{"type":"string"},"read_count":{"type":"integer","minimum":0},"opened_count":{"type":"integer","minimum":0},"last_opened_at":{"type":["string","null"],"format":"date-time"},"created_at":{"type":"string","format":"date-time"}},"required":["id","scope","key","read_count","opened_count","last_opened_at","created_at"]}}},"required":["thresholds","counting_since","census","cost","window","quadrant","entries"]}}}},"400":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"details":{"type":"object","additionalProperties":{}}},"required":["error"]}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"details":{"type":"object","additionalProperties":{}}},"required":["error"]}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"details":{"type":"object","additionalProperties":{}}},"required":["error"]}}}}}}},"/memories/clusters":{"get":{"summary":"Groups of near-duplicate memories, ranked as merge candidates (read-only)","tags":["Memories"],"description":"Clusters the caller's recent lore by Jaccard similarity over tokenized bodies and returns each group with its member count, its similarity RANGE (`min_similarity`/`max_similarity`, measured over the pairs that LINKED the group, so both are `>= threshold`; clusters form transitively, so two members of one cluster may be less alike than `min_similarity` reads) and, when the member keys match a known recurrence class, that class plus whether the match is `pure` (every member matched, nothing else joined). Ordering is by score: summed `seen_count` first, then size, then similarity — \"which redundancy has cost the most\".\n\n**Read-only is the contract, not a phase.** Deciding that N near-duplicate lessons are really one entry is a human judgment, so there is deliberately no merge counterpart and no parameter that makes this route act. It surfaces and ranks the evidence and stops.\n\n**It answers a WINDOWED question.** Candidates are cut at `candidate_limit` in `updated_at desc` order *before* clustering, so `candidates === candidate_limit` means the answer is \"what have I recently written that duplicates something else recent\", not \"what are all the duplicates in my store\". `lorekit dedupe` streams the whole scope through the identical clustering core and is the answer to the second question.\n\nMember bodies are never returned — only `hook`, the first line — for the same reason `GET /memories/relevant` returns none: the point is deciding which lessons to look at. An invalid `scope` is a `400`, not a silently ignored filter.","security":[{"BearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1},"required":false,"name":"scope","in":"query"},{"schema":{"type":"number","minimum":0.5,"maximum":1,"default":0.8},"required":false,"name":"threshold","in":"query"},{"schema":{"type":["integer","null"],"minimum":0,"maximum":1000,"default":3},"required":false,"name":"min_seen_count","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":50,"default":20},"required":false,"name":"limit","in":"query"},{"name":"X-LoreKit-Client","in":"header","required":false,"description":"Which surface is calling. One of `dashboard`, `cli`, `mcp`, `api`; anything else is recorded as unattributed. Purely for usage analytics — it never changes the response. Optional: an absent header records this transport's own default (`api`), so send it only to identify a MORE SPECIFIC calling surface (e.g. `cli`). Reads attributed to `dashboard` are excluded from `GET /memories/read-activity`.","schema":{"type":"string","enum":["dashboard","cli","mcp","api"]}}],"responses":{"200":{"description":"Ranked duplicate clusters","content":{"application/json":{"schema":{"type":"object","properties":{"threshold":{"type":"number"},"candidates":{"type":"integer","minimum":0},"candidate_limit":{"type":"integer","exclusiveMinimum":0},"clusters":{"type":"array","items":{"type":"object","properties":{"size":{"type":"integer","minimum":2},"score":{"type":"number","minimum":0},"min_similarity":{"type":"number","minimum":0,"maximum":1},"max_similarity":{"type":"number","minimum":0,"maximum":1},"recurrence_class":{"type":["object","null"],"properties":{"id":{"type":"string"},"name":{"type":"string"},"matched":{"type":"array","items":{"type":"string"}},"pure":{"type":"boolean"}},"required":["id","name","matched","pure"]},"members":{"type":"array","items":{"type":"object","properties":{"scope":{"type":"string"},"key":{"type":"string"},"hook":{"type":"string"},"seen_count":{"type":["integer","null"],"minimum":0},"updated_at":{"type":["string","null"],"format":"date-time"},"status":{"type":["string","null"]}},"required":["scope","key","hook","seen_count","updated_at","status"]}}},"required":["size","score","min_similarity","max_similarity","recurrence_class","members"]}}},"required":["threshold","candidates","candidate_limit","clusters"]}}}},"400":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"details":{"type":"object","additionalProperties":{}}},"required":["error"]}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"details":{"type":"object","additionalProperties":{}}},"required":["error"]}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"details":{"type":"object","additionalProperties":{}}},"required":["error"]}}}}}}},"/memories/relevant":{"get":{"summary":"Top-K lessons ranked for a query — the shortlist, not the whole match set","tags":["Memories"],"description":"The one verb that RANKS. Every other read returns a single-signal ordering — `GET /memories` is `updated_at` desc, `POST /memories/search` is FTS rank — so a caller wanting a useful shortlist had to fetch a page and re-sort it, and every client that did so disagreed with the others. Here the score combines RECENCY (exponential decay, 14-day half-life), SALIENCE (`log1p(seen_count)` normalised across the candidates, so a lesson learned twelve times outranks one written once) and RELEVANCE (full-text match on `q`). The response is a compact index — scope, key, a one-line hook and the score — because the point is deciding WHICH few lessons deserve a reader's attention; fetch the bodies with `GET /memories/:id` or `memory.read`. `q` is optional: without it the ranking is recency + salience, which answers \"what matters generally\" rather than \"what matters for this\". `scopes` is ordered most-specific first and that order breaks ties, so a project lesson wins over the global one it ties with.","security":[{"BearerAuth":[]}],"parameters":[{"schema":{"type":"string","maxLength":1000},"required":false,"name":"q","in":"query"},{"schema":{"type":"string"},"required":false,"name":"scopes","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":50,"default":10},"required":false,"name":"limit","in":"query"},{"schema":{"type":["number","null"],"minimum":0,"maximum":1,"default":0},"required":false,"name":"min_score","in":"query"},{"name":"X-LoreKit-Client","in":"header","required":false,"description":"Which surface is calling. One of `dashboard`, `cli`, `mcp`, `api`; anything else is recorded as unattributed. Purely for usage analytics — it never changes the response. Optional: an absent header records this transport's own default (`api`), so send it only to identify a MORE SPECIFIC calling surface (e.g. `cli`). Reads attributed to `dashboard` are excluded from `GET /memories/read-activity`.","schema":{"type":"string","enum":["dashboard","cli","mcp","api"]}}],"responses":{"200":{"description":"Ranked lessons","content":{"application/json":{"schema":{"type":"object","properties":{"entries":{"type":"array","items":{"type":"object","properties":{"scope":{"type":"string","minLength":1},"key":{"type":"string"},"hook":{"type":"string"},"score":{"type":"number"},"factors":{"type":"object","properties":{"recency":{"type":"number"},"salience":{"type":"number"},"relevance":{"type":"number"},"outcome":{"type":"number"}},"required":["recency","salience","relevance","outcome"]},"seen_count":{"type":["integer","null"]},"updated_at":{"type":["string","null"]}},"required":["scope","key","hook","score","factors","seen_count","updated_at"]}},"candidates":{"type":"integer"}},"required":["entries","candidates"]}}}},"400":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"details":{"type":"object","additionalProperties":{}}},"required":["error"]}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"details":{"type":"object","additionalProperties":{}}},"required":["error"]}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"details":{"type":"object","additionalProperties":{}}},"required":["error"]}}}}}}},"/memories/usage":{"get":{"summary":"Aggregate usage statistics for your own activity (reads, writes, outcomes, per scope-type) over an optional period","tags":["Memories"],"description":"`by_tool` rows are grouped by `(tool_name, outcome, scope_type, client, kind, host)` (migration 00079 added the last three). `client` is which surface called (`dashboard`/`cli`/`mcp`/`api`); `kind`/`host` are the memory taxonomy family/owner. `host` is bounded to this window's own top 20 by event count — anything else is the literal `'other'`, never an unbounded free-text value. `scope_type` may carry a legacy free-text value predating validation hardening; group by it defensively rather than assuming the closed `global|project|repo|branch|mixed|invalid` vocabulary is exhaustive.\n\n`summary.peak_memory_count` (migration 00081) is the highest active-memory-count snapshot taken on a write event in this window — \"how full WAS this account\", distinct from the `/settings/plan` page's existing LIVE count. `null` when the window has no write events. No plan limit accompanies it; pair it with your own limit reading.","security":[{"BearerAuth":[]}],"parameters":[{"schema":{"type":"string","enum":["24h","7d","30d","90d","all"]},"required":false,"name":"period","in":"query"},{"schema":{"type":"string","format":"date-time"},"required":false,"name":"since","in":"query"},{"schema":{"type":"string","format":"date-time"},"required":false,"name":"until","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":200},"required":false,"name":"correlation_id","in":"query"},{"name":"X-LoreKit-Client","in":"header","required":false,"description":"Which surface is calling. One of `dashboard`, `cli`, `mcp`, `api`; anything else is recorded as unattributed. Purely for usage analytics — it never changes the response. Optional: an absent header records this transport's own default (`api`), so send it only to identify a MORE SPECIFIC calling surface (e.g. `cli`). Reads attributed to `dashboard` are excluded from `GET /memories/read-activity`.","schema":{"type":"string","enum":["dashboard","cli","mcp","api"]}}],"responses":{"200":{"description":"Usage statistics","content":{"application/json":{"schema":{"type":"object","properties":{"range":{"type":"object","properties":{"since":{"type":["string","null"]},"until":{"type":["string","null"]}},"required":["since","until"]},"correlation_id":{"type":["string","null"]},"summary":{"type":"object","properties":{"total_events":{"type":"integer","minimum":0},"reads":{"type":"integer","minimum":0},"writes":{"type":"integer","minimum":0},"other":{"type":"integer","minimum":0},"records_read":{"type":"integer","minimum":0},"archived":{"type":"integer","minimum":0},"expired":{"type":"integer","minimum":0},"by_outcome":{"type":"object","additionalProperties":{"type":"integer","minimum":0}},"peak_memory_count":{"type":["integer","null"],"minimum":0}},"required":["total_events","reads","writes","other","records_read","archived","expired","by_outcome"]},"by_tool":{"type":"array","items":{"type":"object","properties":{"tool_name":{"type":"string"},"outcome":{"type":"string"},"scope_type":{"type":["string","null"]},"client":{"type":["string","null"]},"kind":{"type":["string","null"]},"host":{"type":["string","null"]},"event_count":{"type":"integer","minimum":0},"record_count":{"type":"integer","minimum":0},"total_duration_ms":{"type":["integer","null"],"minimum":0}},"required":["tool_name","outcome","scope_type","event_count","record_count","total_duration_ms"]}},"by_scope_type":{"type":"array","items":{"type":"object","properties":{"scope_type":{"type":["string","null"]},"event_count":{"type":"integer","minimum":0}},"required":["scope_type","event_count"]}}},"required":["range","correlation_id","summary","by_tool","by_scope_type"]}}}},"400":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"details":{"type":"object","additionalProperties":{}}},"required":["error"]}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"details":{"type":"object","additionalProperties":{}}},"required":["error"]}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"details":{"type":"object","additionalProperties":{}}},"required":["error"]}}}}}}},"/memories/usage/runs":{"get":{"summary":"Enumerate runs (correlation_id values) with what each one read, wrote, and touched","tags":["Memories"],"description":"The payoff view for `?correlation_id=` on `GET /memories/usage`: that filters TO one run, this is how you discover which ones exist. Each run is a distinct `correlation_id` — a local session, a CI job, or a PR automation (`session_kind`, migration 00082) — with its first/last-seen timestamps, read/write event and record counts (the SAME broader `READ_TOOL_NAMES`/`WRITE_TOOL_NAMES` vocabulary `summarizeUsageRows` uses for `/usage`'s own summary, not `GET /memories/read-activity`'s narrower 4-tool definition), distinct scopes touched, and total duration.\n\nKeyset-paginated (`cursor`/`next_cursor`), never OFFSET. `range` echoes the window actually queried — an unbounded request is narrowed to 90 days server-side and captioned here rather than silently answering less than \"all time\" implies.","security":[{"BearerAuth":[]}],"parameters":[{"schema":{"type":"string","format":"date-time"},"required":false,"name":"since","in":"query"},{"schema":{"type":"string","format":"date-time"},"required":false,"name":"until","in":"query"},{"schema":{"type":"string"},"required":false,"name":"cursor","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100,"default":20},"required":false,"name":"limit","in":"query"},{"name":"X-LoreKit-Client","in":"header","required":false,"description":"Which surface is calling. One of `dashboard`, `cli`, `mcp`, `api`; anything else is recorded as unattributed. Purely for usage analytics — it never changes the response. Optional: an absent header records this transport's own default (`api`), so send it only to identify a MORE SPECIFIC calling surface (e.g. `cli`). Reads attributed to `dashboard` are excluded from `GET /memories/read-activity`.","schema":{"type":"string","enum":["dashboard","cli","mcp","api"]}}],"responses":{"200":{"description":"Runs page","content":{"application/json":{"schema":{"type":"object","properties":{"range":{"type":"object","properties":{"since":{"type":"string"},"until":{"type":"string"}},"required":["since","until"]},"runs":{"type":"array","items":{"type":"object","properties":{"correlation_id":{"type":"string"},"session_kind":{"type":["string","null"]},"first_seen":{"type":"string","format":"date-time"},"last_seen":{"type":"string","format":"date-time"},"read_events":{"type":"integer","minimum":0},"records_read":{"type":"integer","minimum":0},"write_events":{"type":"integer","minimum":0},"distinct_scopes":{"type":"integer","minimum":0},"total_duration_ms":{"type":"integer","minimum":0}},"required":["correlation_id","session_kind","first_seen","last_seen","read_events","records_read","write_events","distinct_scopes","total_duration_ms"]}},"next_cursor":{"type":["string","null"]}},"required":["range","runs","next_cursor"]}}}},"400":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"details":{"type":"object","additionalProperties":{}}},"required":["error"]}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"details":{"type":"object","additionalProperties":{}}},"required":["error"]}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"details":{"type":"object","additionalProperties":{}}},"required":["error"]}}}}}}},"/memories/{id}":{"get":{"summary":"Get memory by ID","tags":["Memories"],"security":[{"BearerAuth":[]}],"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"},{"name":"X-LoreKit-Client","in":"header","required":false,"description":"Which surface is calling. One of `dashboard`, `cli`, `mcp`, `api`; anything else is recorded as unattributed. Purely for usage analytics — it never changes the response. Optional: an absent header records this transport's own default (`api`), so send it only to identify a MORE SPECIFIC calling surface (e.g. `cli`). Reads attributed to `dashboard` are excluded from `GET /memories/read-activity`.","schema":{"type":"string","enum":["dashboard","cli","mcp","api"]}}],"responses":{"200":{"description":"Memory","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"scope":{"type":"string"},"key":{"type":"string"},"value":{"type":"string"},"tags":{"type":"array","items":{"type":"string"}},"source_agent":{"type":["string","null"]},"trigger":{"type":["string","null"]},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"},"expires_at":{"type":["string","null"],"format":"date-time"},"archived_at":{"type":["string","null"],"format":"date-time"},"origin_repo":{"type":["string","null"]},"origin_branch":{"type":["string","null"]},"origin_commit":{"type":["string","null"]},"origin_pr":{"type":["number","null"]},"kind":{"type":["string","null"]},"host":{"type":["string","null"]},"seen_count":{"type":"integer"},"read_count":{"type":"integer","minimum":0},"last_read_at":{"type":["string","null"],"format":"date-time"},"last_opened_at":{"type":["string","null"],"format":"date-time"},"opened_count":{"type":"integer","minimum":0},"cited_count":{"type":"integer","minimum":0},"last_cited_at":{"type":["string","null"],"format":"date-time"},"org_id":{"type":["string","null"],"format":"uuid"},"org":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"slug":{"type":"string"}},"required":["id","name","slug"]},"created_by":{"type":["string","null"],"format":"uuid"},"updated_by":{"type":["string","null"],"format":"uuid"}},"required":["id","scope","key","value","tags","source_agent","trigger","created_at","updated_at","expires_at","archived_at"]}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"details":{"type":"object","additionalProperties":{}}},"required":["error"]}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"details":{"type":"object","additionalProperties":{}}},"required":["error"]}}}}}},"patch":{"summary":"Update a memory","tags":["Memories"],"security":[{"BearerAuth":[]}],"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"},{"name":"X-LoreKit-Client","in":"header","required":false,"description":"Which surface is calling. One of `dashboard`, `cli`, `mcp`, `api`; anything else is recorded as unattributed. Purely for usage analytics — it never changes the response. Optional: an absent header records this transport's own default (`api`), so send it only to identify a MORE SPECIFIC calling surface (e.g. `cli`). Reads attributed to `dashboard` are excluded from `GET /memories/read-activity`.","schema":{"type":"string","enum":["dashboard","cli","mcp","api"]}},{"name":"X-LoreKit-Dry-Run","in":"header","required":false,"description":"Safe-explore mode. `true` validates and authorizes the request but makes NO changes. Absent or `false` executes it for real — the server default is `false`; only this reference's try-it console pre-fills `true`.","schema":{"type":"boolean","default":true},"x-server-default":false}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"value":{"type":"string","maxLength":65536},"tags":{"type":"array","items":{"type":"string"},"default":[]},"source_agent":{"type":"string"},"trigger":{"type":"string"},"ttl_days":{"type":"integer","minimum":1,"maximum":365},"clear_ttl":{"type":"boolean","default":false},"kind":{"type":"string","enum":["lesson","bus","signal"]},"host":{"type":"string","maxLength":64}}}}}},"responses":{"200":{"description":"Updated memory","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"scope":{"type":"string"},"key":{"type":"string"},"value":{"type":"string"},"tags":{"type":"array","items":{"type":"string"}},"source_agent":{"type":["string","null"]},"trigger":{"type":["string","null"]},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"},"expires_at":{"type":["string","null"],"format":"date-time"},"archived_at":{"type":["string","null"],"format":"date-time"},"origin_repo":{"type":["string","null"]},"origin_branch":{"type":["string","null"]},"origin_commit":{"type":["string","null"]},"origin_pr":{"type":["number","null"]},"kind":{"type":["string","null"]},"host":{"type":["string","null"]},"seen_count":{"type":"integer"},"read_count":{"type":"integer","minimum":0},"last_read_at":{"type":["string","null"],"format":"date-time"},"last_opened_at":{"type":["string","null"],"format":"date-time"},"opened_count":{"type":"integer","minimum":0},"cited_count":{"type":"integer","minimum":0},"last_cited_at":{"type":["string","null"],"format":"date-time"},"org_id":{"type":["string","null"],"format":"uuid"},"org":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"slug":{"type":"string"}},"required":["id","name","slug"]},"created_by":{"type":["string","null"],"format":"uuid"},"updated_by":{"type":["string","null"],"format":"uuid"}},"required":["id","scope","key","value","tags","source_agent","trigger","created_at","updated_at","expires_at","archived_at"]}}}},"400":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"details":{"type":"object","additionalProperties":{}}},"required":["error"]}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"details":{"type":"object","additionalProperties":{}}},"required":["error"]}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"details":{"type":"object","additionalProperties":{}}},"required":["error"]}}}}}},"delete":{"summary":"Archive a memory (soft-delete), or hard-delete it with force=true","tags":["Memories"],"security":[{"BearerAuth":[]}],"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"},{"schema":{"type":"string","minLength":1},"required":false,"name":"scope","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":512},"required":false,"name":"key","in":"query"},{"schema":{"type":"string","enum":["true","false"],"default":"false"},"required":false,"name":"force","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":50},"required":false,"name":"org","in":"query"},{"name":"X-LoreKit-Client","in":"header","required":false,"description":"Which surface is calling. One of `dashboard`, `cli`, `mcp`, `api`; anything else is recorded as unattributed. Purely for usage analytics — it never changes the response. Optional: an absent header records this transport's own default (`api`), so send it only to identify a MORE SPECIFIC calling surface (e.g. `cli`). Reads attributed to `dashboard` are excluded from `GET /memories/read-activity`.","schema":{"type":"string","enum":["dashboard","cli","mcp","api"]}},{"name":"X-LoreKit-Dry-Run","in":"header","required":false,"description":"Safe-explore mode. `true` validates and authorizes the request but makes NO changes. Absent or `false` executes it for real — the server default is `false`; only this reference's try-it console pre-fills `true`.","schema":{"type":"boolean","default":true},"x-server-default":false}],"responses":{"204":{"description":"Archived or deleted"},"401":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"details":{"type":"object","additionalProperties":{}}},"required":["error"]}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"details":{"type":"object","additionalProperties":{}}},"required":["error"]}}}}}}},"/memories/read":{"post":{"summary":"Batch-read memories by scope::key reference","tags":["Memories"],"description":"Fetch several lessons in one call. Each entry in `refs` is a `scope::key` reference, parsed by the same grammar `POST /memories`'s `cited` field uses. A reference in more than one scope resolves independently rather than failing the whole call: one that is well-formed but matches no lesson is named in `missing`, while a malformed one — and every reference past the 32nd — is dropped silently and appears in neither list. `missing` is a not-found list, never a malformed-input or truncation report.","security":[{"BearerAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"refs":{"type":"array","items":{"type":"string"},"minItems":1}},"required":["refs"]}}}},"responses":{"200":{"description":"Batch read result","content":{"application/json":{"schema":{"type":"object","properties":{"entries":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"scope":{"type":"string"},"key":{"type":"string"},"value":{"type":"string"},"tags":{"type":"array","items":{"type":"string"}},"source_agent":{"type":["string","null"]},"trigger":{"type":["string","null"]},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"},"expires_at":{"type":["string","null"],"format":"date-time"},"archived_at":{"type":["string","null"],"format":"date-time"},"origin_repo":{"type":["string","null"]},"origin_branch":{"type":["string","null"]},"origin_commit":{"type":["string","null"]},"origin_pr":{"type":["number","null"]},"kind":{"type":["string","null"]},"host":{"type":["string","null"]},"seen_count":{"type":"integer"},"read_count":{"type":"integer","minimum":0},"last_read_at":{"type":["string","null"],"format":"date-time"},"last_opened_at":{"type":["string","null"],"format":"date-time"},"opened_count":{"type":"integer","minimum":0},"cited_count":{"type":"integer","minimum":0},"last_cited_at":{"type":["string","null"],"format":"date-time"},"org_id":{"type":["string","null"],"format":"uuid"},"org":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"slug":{"type":"string"}},"required":["id","name","slug"]},"created_by":{"type":["string","null"],"format":"uuid"},"updated_by":{"type":["string","null"],"format":"uuid"}},"required":["id","scope","key","value","tags","source_agent","trigger","created_at","updated_at","expires_at","archived_at"]}},"missing":{"type":"array","items":{"type":"string"}}},"required":["entries","missing"]}}}},"400":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"details":{"type":"object","additionalProperties":{}}},"required":["error"]}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"details":{"type":"object","additionalProperties":{}}},"required":["error"]}}}}},"parameters":[{"name":"X-LoreKit-Client","in":"header","required":false,"description":"Which surface is calling. One of `dashboard`, `cli`, `mcp`, `api`; anything else is recorded as unattributed. Purely for usage analytics — it never changes the response. Optional: an absent header records this transport's own default (`api`), so send it only to identify a MORE SPECIFIC calling surface (e.g. `cli`). Reads attributed to `dashboard` are excluded from `GET /memories/read-activity`.","schema":{"type":"string","enum":["dashboard","cli","mcp","api"]}}]}},"/memories/{id}/restore":{"post":{"summary":"Restore an archived memory by ID","tags":["Memories"],"security":[{"BearerAuth":[]}],"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"},{"name":"X-LoreKit-Client","in":"header","required":false,"description":"Which surface is calling. One of `dashboard`, `cli`, `mcp`, `api`; anything else is recorded as unattributed. Purely for usage analytics — it never changes the response. Optional: an absent header records this transport's own default (`api`), so send it only to identify a MORE SPECIFIC calling surface (e.g. `cli`). Reads attributed to `dashboard` are excluded from `GET /memories/read-activity`.","schema":{"type":"string","enum":["dashboard","cli","mcp","api"]}},{"name":"X-LoreKit-Dry-Run","in":"header","required":false,"description":"Safe-explore mode. `true` validates and authorizes the request but makes NO changes. Absent or `false` executes it for real — the server default is `false`; only this reference's try-it console pre-fills `true`.","schema":{"type":"boolean","default":true},"x-server-default":false}],"responses":{"200":{"description":"Restored","content":{"application/json":{"schema":{"type":"object","properties":{"restored":{"type":"boolean"}},"required":["restored"]}}}},"400":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"details":{"type":"object","additionalProperties":{}}},"required":["error"]}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"details":{"type":"object","additionalProperties":{}}},"required":["error"]}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"details":{"type":"object","additionalProperties":{}}},"required":["error"]}}}}}}},"/orgs":{"get":{"summary":"List my organizations","tags":["Orgs"],"security":[{"BearerAuth":[]}],"responses":{"200":{"description":"Orgs","content":{"application/json":{"schema":{"type":"object","properties":{"entries":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"slug":{"type":"string"},"name":{"type":"string"},"created_at":{"type":"string","format":"date-time"}},"required":["id","slug","name","created_at"]}}},"required":["entries"]}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"details":{"type":"object","additionalProperties":{}}},"required":["error"]}}}}},"parameters":[{"name":"X-LoreKit-Client","in":"header","required":false,"description":"Which surface is calling. One of `dashboard`, `cli`, `mcp`, `api`; anything else is recorded as unattributed. Purely for usage analytics — it never changes the response. Optional: an absent header records this transport's own default (`api`), so send it only to identify a MORE SPECIFIC calling surface (e.g. `cli`). Reads attributed to `dashboard` are excluded from `GET /memories/read-activity`.","schema":{"type":"string","enum":["dashboard","cli","mcp","api"]}}]},"post":{"summary":"Create an organization","tags":["Orgs"],"security":[{"BearerAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"slug":{"type":"string","minLength":3,"maxLength":50,"pattern":"^[a-z0-9][a-z0-9-]*[a-z0-9]$"},"name":{"type":"string","minLength":1,"maxLength":100}},"required":["slug","name"]}}}},"responses":{"201":{"description":"Created org","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"slug":{"type":"string"},"name":{"type":"string"},"created_at":{"type":"string","format":"date-time"}},"required":["id","slug","name","created_at"]}}}},"400":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"details":{"type":"object","additionalProperties":{}}},"required":["error"]}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"details":{"type":"object","additionalProperties":{}}},"required":["error"]}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"details":{"type":"object","additionalProperties":{}}},"required":["error"]}}}}},"parameters":[{"name":"X-LoreKit-Client","in":"header","required":false,"description":"Which surface is calling. One of `dashboard`, `cli`, `mcp`, `api`; anything else is recorded as unattributed. Purely for usage analytics — it never changes the response. Optional: an absent header records this transport's own default (`api`), so send it only to identify a MORE SPECIFIC calling surface (e.g. `cli`). Reads attributed to `dashboard` are excluded from `GET /memories/read-activity`.","schema":{"type":"string","enum":["dashboard","cli","mcp","api"]}},{"name":"X-LoreKit-Dry-Run","in":"header","required":false,"description":"Safe-explore mode. `true` validates and authorizes the request but makes NO changes. Absent or `false` executes it for real — the server default is `false`; only this reference's try-it console pre-fills `true`.","schema":{"type":"boolean","default":true},"x-server-default":false}]}},"/orgs/{slug}":{"get":{"summary":"Get organization","tags":["Orgs"],"security":[{"BearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":3,"maxLength":50},"required":true,"name":"slug","in":"path"},{"name":"X-LoreKit-Client","in":"header","required":false,"description":"Which surface is calling. One of `dashboard`, `cli`, `mcp`, `api`; anything else is recorded as unattributed. Purely for usage analytics — it never changes the response. Optional: an absent header records this transport's own default (`api`), so send it only to identify a MORE SPECIFIC calling surface (e.g. `cli`). Reads attributed to `dashboard` are excluded from `GET /memories/read-activity`.","schema":{"type":"string","enum":["dashboard","cli","mcp","api"]}}],"responses":{"200":{"description":"Org","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"slug":{"type":"string"},"name":{"type":"string"},"created_at":{"type":"string","format":"date-time"}},"required":["id","slug","name","created_at"]}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"details":{"type":"object","additionalProperties":{}}},"required":["error"]}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"details":{"type":"object","additionalProperties":{}}},"required":["error"]}}}}}},"patch":{"summary":"Rename organization","tags":["Orgs"],"security":[{"BearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":3,"maxLength":50},"required":true,"name":"slug","in":"path"},{"name":"X-LoreKit-Client","in":"header","required":false,"description":"Which surface is calling. One of `dashboard`, `cli`, `mcp`, `api`; anything else is recorded as unattributed. Purely for usage analytics — it never changes the response. Optional: an absent header records this transport's own default (`api`), so send it only to identify a MORE SPECIFIC calling surface (e.g. `cli`). Reads attributed to `dashboard` are excluded from `GET /memories/read-activity`.","schema":{"type":"string","enum":["dashboard","cli","mcp","api"]}},{"name":"X-LoreKit-Dry-Run","in":"header","required":false,"description":"Safe-explore mode. `true` validates and authorizes the request but makes NO changes. Absent or `false` executes it for real — the server default is `false`; only this reference's try-it console pre-fills `true`.","schema":{"type":"boolean","default":true},"x-server-default":false}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":100}},"required":["name"]}}}},"responses":{"200":{"description":"Updated org","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"slug":{"type":"string"},"name":{"type":"string"},"created_at":{"type":"string","format":"date-time"}},"required":["id","slug","name","created_at"]}}}},"400":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"details":{"type":"object","additionalProperties":{}}},"required":["error"]}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"details":{"type":"object","additionalProperties":{}}},"required":["error"]}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"details":{"type":"object","additionalProperties":{}}},"required":["error"]}}}}}},"delete":{"summary":"Delete organization — owner only","tags":["Orgs"],"security":[{"BearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":3,"maxLength":50},"required":true,"name":"slug","in":"path"},{"name":"X-LoreKit-Client","in":"header","required":false,"description":"Which surface is calling. One of `dashboard`, `cli`, `mcp`, `api`; anything else is recorded as unattributed. Purely for usage analytics — it never changes the response. Optional: an absent header records this transport's own default (`api`), so send it only to identify a MORE SPECIFIC calling surface (e.g. `cli`). Reads attributed to `dashboard` are excluded from `GET /memories/read-activity`.","schema":{"type":"string","enum":["dashboard","cli","mcp","api"]}},{"name":"X-LoreKit-Dry-Run","in":"header","required":false,"description":"Safe-explore mode. `true` validates and authorizes the request but makes NO changes. Absent or `false` executes it for real — the server default is `false`; only this reference's try-it console pre-fills `true`.","schema":{"type":"boolean","default":true},"x-server-default":false}],"responses":{"204":{"description":"Deleted"},"401":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"details":{"type":"object","additionalProperties":{}}},"required":["error"]}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"details":{"type":"object","additionalProperties":{}}},"required":["error"]}}}}}}},"/orgs/{slug}/members":{"get":{"summary":"List members","tags":["Members"],"security":[{"BearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":3,"maxLength":50},"required":true,"name":"slug","in":"path"},{"name":"X-LoreKit-Client","in":"header","required":false,"description":"Which surface is calling. One of `dashboard`, `cli`, `mcp`, `api`; anything else is recorded as unattributed. Purely for usage analytics — it never changes the response. Optional: an absent header records this transport's own default (`api`), so send it only to identify a MORE SPECIFIC calling surface (e.g. `cli`). Reads attributed to `dashboard` are excluded from `GET /memories/read-activity`.","schema":{"type":"string","enum":["dashboard","cli","mcp","api"]}}],"responses":{"200":{"description":"Members","content":{"application/json":{"schema":{"type":"object","properties":{"entries":{"type":"array","items":{"type":"object","properties":{"user_id":{"type":"string","format":"uuid"},"role":{"type":"string","enum":["owner","admin","member","viewer"]},"joined_at":{"type":"string","format":"date-time"},"display_name":{"type":["string","null"]},"avatar_url":{"type":["string","null"]}},"required":["user_id","role","joined_at","display_name","avatar_url"]}}},"required":["entries"]}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"details":{"type":"object","additionalProperties":{}}},"required":["error"]}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"details":{"type":"object","additionalProperties":{}}},"required":["error"]}}}}}}},"/orgs/{slug}/members/{userId}":{"patch":{"summary":"Update member role","tags":["Members"],"security":[{"BearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":3,"maxLength":50},"required":true,"name":"slug","in":"path"},{"schema":{"type":"string","format":"uuid"},"required":true,"name":"userId","in":"path"},{"name":"X-LoreKit-Client","in":"header","required":false,"description":"Which surface is calling. One of `dashboard`, `cli`, `mcp`, `api`; anything else is recorded as unattributed. Purely for usage analytics — it never changes the response. Optional: an absent header records this transport's own default (`api`), so send it only to identify a MORE SPECIFIC calling surface (e.g. `cli`). Reads attributed to `dashboard` are excluded from `GET /memories/read-activity`.","schema":{"type":"string","enum":["dashboard","cli","mcp","api"]}},{"name":"X-LoreKit-Dry-Run","in":"header","required":false,"description":"Safe-explore mode. `true` validates and authorizes the request but makes NO changes. Absent or `false` executes it for real — the server default is `false`; only this reference's try-it console pre-fills `true`.","schema":{"type":"boolean","default":true},"x-server-default":false}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"role":{"type":"string","enum":["owner","admin","member","viewer"]}},"required":["role"]}}}},"responses":{"200":{"description":"Updated"},"400":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"details":{"type":"object","additionalProperties":{}}},"required":["error"]}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"details":{"type":"object","additionalProperties":{}}},"required":["error"]}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"details":{"type":"object","additionalProperties":{}}},"required":["error"]}}}}}},"delete":{"summary":"Remove member","tags":["Members"],"security":[{"BearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":3,"maxLength":50},"required":true,"name":"slug","in":"path"},{"schema":{"type":"string","format":"uuid"},"required":true,"name":"userId","in":"path"},{"name":"X-LoreKit-Client","in":"header","required":false,"description":"Which surface is calling. One of `dashboard`, `cli`, `mcp`, `api`; anything else is recorded as unattributed. Purely for usage analytics — it never changes the response. Optional: an absent header records this transport's own default (`api`), so send it only to identify a MORE SPECIFIC calling surface (e.g. `cli`). Reads attributed to `dashboard` are excluded from `GET /memories/read-activity`.","schema":{"type":"string","enum":["dashboard","cli","mcp","api"]}},{"name":"X-LoreKit-Dry-Run","in":"header","required":false,"description":"Safe-explore mode. `true` validates and authorizes the request but makes NO changes. Absent or `false` executes it for real — the server default is `false`; only this reference's try-it console pre-fills `true`.","schema":{"type":"boolean","default":true},"x-server-default":false}],"responses":{"204":{"description":"Removed"},"401":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"details":{"type":"object","additionalProperties":{}}},"required":["error"]}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"details":{"type":"object","additionalProperties":{}}},"required":["error"]}}}}}}},"/orgs/{slug}/invites":{"get":{"summary":"List pending invites","tags":["Invites"],"security":[{"BearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":3,"maxLength":50},"required":true,"name":"slug","in":"path"},{"name":"X-LoreKit-Client","in":"header","required":false,"description":"Which surface is calling. One of `dashboard`, `cli`, `mcp`, `api`; anything else is recorded as unattributed. Purely for usage analytics — it never changes the response. Optional: an absent header records this transport's own default (`api`), so send it only to identify a MORE SPECIFIC calling surface (e.g. `cli`). Reads attributed to `dashboard` are excluded from `GET /memories/read-activity`.","schema":{"type":"string","enum":["dashboard","cli","mcp","api"]}}],"responses":{"200":{"description":"Invites","content":{"application/json":{"schema":{"type":"object","properties":{"entries":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"org_id":{"type":"string","format":"uuid"},"email":{"type":["string","null"]},"handle":{"type":["string","null"]},"role":{"type":"string","enum":["owner","admin","member","viewer"]},"created_at":{"type":"string","format":"date-time"},"expires_at":{"type":["string","null"],"format":"date-time"}},"required":["id","org_id","email","handle","role","created_at","expires_at"]}}},"required":["entries"]}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"details":{"type":"object","additionalProperties":{}}},"required":["error"]}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"details":{"type":"object","additionalProperties":{}}},"required":["error"]}}}}}},"post":{"summary":"Send an invite","tags":["Invites"],"security":[{"BearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":3,"maxLength":50},"required":true,"name":"slug","in":"path"},{"name":"X-LoreKit-Client","in":"header","required":false,"description":"Which surface is calling. One of `dashboard`, `cli`, `mcp`, `api`; anything else is recorded as unattributed. Purely for usage analytics — it never changes the response. Optional: an absent header records this transport's own default (`api`), so send it only to identify a MORE SPECIFIC calling surface (e.g. `cli`). Reads attributed to `dashboard` are excluded from `GET /memories/read-activity`.","schema":{"type":"string","enum":["dashboard","cli","mcp","api"]}},{"name":"X-LoreKit-Dry-Run","in":"header","required":false,"description":"Safe-explore mode. `true` validates and authorizes the request but makes NO changes. Absent or `false` executes it for real — the server default is `false`; only this reference's try-it console pre-fills `true`.","schema":{"type":"boolean","default":true},"x-server-default":false}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"email":{"type":"string","format":"email"},"handle":{"type":"string","minLength":1},"role":{"type":"string","enum":["admin","member","viewer"],"default":"member"}}}}}},"responses":{"201":{"description":"Invite sent","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"org_id":{"type":"string","format":"uuid"},"email":{"type":["string","null"]},"handle":{"type":["string","null"]},"role":{"type":"string","enum":["owner","admin","member","viewer"]},"created_at":{"type":"string","format":"date-time"},"expires_at":{"type":["string","null"],"format":"date-time"}},"required":["id","org_id","email","handle","role","created_at","expires_at"]}}}},"400":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"details":{"type":"object","additionalProperties":{}}},"required":["error"]}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"details":{"type":"object","additionalProperties":{}}},"required":["error"]}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"details":{"type":"object","additionalProperties":{}}},"required":["error"]}}}}}}},"/orgs/{slug}/invites/{inviteId}":{"delete":{"summary":"Revoke an invite","tags":["Invites"],"security":[{"BearerAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":3,"maxLength":50},"required":true,"name":"slug","in":"path"},{"schema":{"type":"string","format":"uuid"},"required":true,"name":"inviteId","in":"path"},{"name":"X-LoreKit-Client","in":"header","required":false,"description":"Which surface is calling. One of `dashboard`, `cli`, `mcp`, `api`; anything else is recorded as unattributed. Purely for usage analytics — it never changes the response. Optional: an absent header records this transport's own default (`api`), so send it only to identify a MORE SPECIFIC calling surface (e.g. `cli`). Reads attributed to `dashboard` are excluded from `GET /memories/read-activity`.","schema":{"type":"string","enum":["dashboard","cli","mcp","api"]}},{"name":"X-LoreKit-Dry-Run","in":"header","required":false,"description":"Safe-explore mode. `true` validates and authorizes the request but makes NO changes. Absent or `false` executes it for real — the server default is `false`; only this reference's try-it console pre-fills `true`.","schema":{"type":"boolean","default":true},"x-server-default":false}],"responses":{"204":{"description":"Revoked"},"401":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"details":{"type":"object","additionalProperties":{}}},"required":["error"]}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"details":{"type":"object","additionalProperties":{}}},"required":["error"]}}}}}}},"/blog/likes":{"get":{"summary":"Get a blog post's like total (public)","tags":["Blog"],"security":[],"parameters":[{"schema":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-z0-9]+(?:-[a-z0-9]+)*$"},"required":true,"name":"slug","in":"query"}],"responses":{"200":{"description":"The post's global like total","content":{"application/json":{"schema":{"type":"object","properties":{"likes":{"type":"integer","minimum":0}},"required":["likes"]}}}},"400":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"details":{"type":"object","additionalProperties":{}}},"required":["error"]}}}}}},"post":{"summary":"Add a like to a blog post (public)","tags":["Blog"],"security":[],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"slug":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[a-z0-9]+(?:-[a-z0-9]+)*$"},"delta":{"type":"integer","minimum":1,"maximum":100,"default":1}},"required":["slug"]}}}},"responses":{"200":{"description":"The post's global like total","content":{"application/json":{"schema":{"type":"object","properties":{"likes":{"type":"integer","minimum":0}},"required":["likes"]}}}},"400":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"details":{"type":"object","additionalProperties":{}}},"required":["error"]}}}}}}}},"webhooks":{},"x-tagGroups":[{"name":"Memories","tags":["Memories"]},{"name":"Organizations","tags":["Orgs","Members","Invites"]}]}