{"openapi":"3.1.0","info":{"title":"VISION API","version":"1.0.0","description":"The REST routes behind achieve.vision, reachable with a personal access token or OAuth access token. For AI agents, the MCP server at /api/mcp is the recommended surface. Human-readable docs: https://achieve.vision/developers"},"servers":[{"url":"https://achieve.vision"}],"security":[{"bearer":[]}],"tags":[{"name":"Shared"},{"name":"Horizon"},{"name":"Luminate"},{"name":"Pupil"},{"name":"Loupe"},{"name":"Refract"}],"paths":{"/api/settings":{"get":{"summary":"Horizon view settings: horizonDays (filter window) and activeArea.","description":"Horizon view settings: horizonDays (filter window) and activeArea.","tags":["Shared"],"x-vision-scope":"any","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}}},"/api/prefs":{"get":{"summary":"The per-app preferences blob ({global, horizon, luminate, pupil, loupe, refract}). Absent keys mean the client-side d…","description":"The per-app preferences blob ({global, horizon, luminate, pupil, loupe, refract}). Absent keys mean the client-side default.\n\nhorizon.customCategories = [{id,label,icon}]; horizon.defaultArea/defaultImportance/defaultCategory; horizon.wakeHour (snooze mornings, default 8); loupe.zeroCatchRuns (default 5).","tags":["Shared"],"x-vision-scope":"any","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}}},"/api/attachments/{key}":{"get":{"summary":"Download a stored file (a Luminate PDF note's source PDF). key comes from a note's pdfKey.","description":"Download a stored file (a Luminate PDF note's source PDF). key comes from a note's pdfKey.","tags":["Luminate"],"x-vision-scope":"luminate:read","parameters":[{"name":"key","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}}},"/api/bootstrap/horizon":{"get":{"summary":"Everything Horizon boots with in one call: pending tasks, checklists (recurring templates), checklist items, metric l…","description":"Everything Horizon boots with in one call: pending tasks, checklists (recurring templates), checklist items, metric logs, areas, settings, prefs, and — with ?date — loupeToday.\n\nShips PENDING tasks only; done tasks come from GET /api/tasks?done=1.","tags":["Horizon"],"x-vision-scope":"horizon:read","parameters":[{"name":"date","in":"query","required":false,"description":"Local YYYY-MM-DD; enables loupeToday (Loupe checklists due that day, if the token also has loupe).","schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}}},"/api/tasks":{"get":{"summary":"All tasks (absorbed tasks never appear).","description":"All tasks (absorbed tasks never appear).\n\ndone=0 includes subtasks stranded open inside already-completed parents (left by clients that completed parents without cascading); the app hides any task with a done ancestor, so filter those out to match what the person sees. Task fields: id, parentId (dwell parent), title, notes, importance 1-5, area (domain id), category, followUp (due date YYYY-MM-DD), done, completedAt, festers, isMetric/metricUnit, snoozeUntil (epoch ms), timerStartedAt/timerMode/timerDurationSec/timerElapsedSec/timerAutoDone, campaign, checklistItemId, loupeChecklistId, inboxToken, createdAt.","tags":["Horizon"],"x-vision-scope":"horizon:read","parameters":[{"name":"done","in":"query","required":false,"description":"\"1\" = completed only, \"0\" = open only, omitted = both.","schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}},"post":{"summary":"Create a task.","description":"Create a task.\n\nsnoozeUntil/timer fields are not accepted on create — PATCH them after.","tags":["Horizon"],"x-vision-scope":"horizon:write","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","description":"New row id — generate a UUID. Ids are client-generated everywhere in VISION."},"title":{"type":"string","description":"Required. ≤500 chars. Renders **bold** *italic* __underline__ ~~strike~~ only."},"notes":{"type":"string","description":"Markdown."},"importance":{"type":"integer","description":"1-5, default 3."},"area":{"type":"string","description":"Domain id, default \"personal\"."},"category":{"type":"string","description":"todo|storage|idea|event|note|<custom id>, default todo."},"followUp":{"type":"string","description":"Due date YYYY-MM-DD."},"parentId":{"type":"string","description":"Dwell parent task id."},"festers":{"type":"boolean","description":"Default true."},"isMetric":{"type":"boolean","description":"A numeric reading task."},"metricUnit":{"type":"string"},"createdAt":{"type":"integer","description":"Epoch ms."}},"required":["id","title"]}}}}}},"/api/tasks/{id}":{"patch":{"summary":"Patch any of: parentId, title, importance, area, category, followUp, notes, done, completedAt, festers, isMetric, met…","description":"Patch any of: parentId, title, importance, area, category, followUp, notes, done, completedAt, festers, isMetric, metricUnit, timerStartedAt, timerMode, timerDurationSec, timerElapsedSec, timerAutoDone, campaign, snoozeUntil, remindAt, loupeChecklistId, checklistItemId, lastFesterDate.\n\nCompleting the way the app does: {done:true, completedAt:now} AND clear timer (timerStartedAt/timerMode/timerDurationSec null, timerElapsedSec = seconds run) AND snoozeUntil null. A task with open subtasks should only be completed together with them. Timer: timerMode \"up\"|\"down\", timerStartedAt epoch ms, timerDurationSec for countdowns.","tags":["Horizon"],"x-vision-scope":"horizon:write","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}},"delete":{"summary":"Delete a task and every descendant. 409 if the task itself is absorbed into a Loupe checklist.","description":"Delete a task and every descendant. 409 if the task itself is absorbed into a Loupe checklist.","tags":["Horizon"],"x-vision-scope":"horizon:write","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}}},"/api/tasks/search":{"get":{"summary":"Semantic search over open and done tasks (meaning, not keywords). Empty array on any search-index failure.","description":"Semantic search over open and done tasks (meaning, not keywords). Empty array on any search-index failure.","tags":["Horizon"],"x-vision-scope":"horizon:read","parameters":[{"name":"q","in":"query","required":true,"description":"Query.","schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}}},"/api/tasks/ai-sort":{"post":{"summary":"\"Help Me Sort\": classify up to 40 task titles into named groups. Streams SSE (assign / done events). Only classifies …","description":"\"Help Me Sort\": classify up to 40 task titles into named groups. Streams SSE (assign / done events). Only classifies — moving tasks is the caller's job.\n\nCosts a Workers AI call. Curated agents usually do this reasoning themselves.","tags":["Horizon"],"x-vision-scope":"horizon:write","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"titles":{"type":"array","description":"Task titles in order (≤50; the app sends 40).","items":{}},"hint":{"type":"string","description":"How to group, in the person's words."},"existingGroups":{"type":"array","description":"Group names from earlier chunks, so everything files into one taxonomy.","items":{}}},"required":["titles"]}}}}}},"/api/tasks/estimate":{"post":{"summary":"\"Estimate for me\": a countdown duration suggestion for a task title, anchored on this account's own recorded timer ru…","description":"\"Estimate for me\": a countdown duration suggestion for a task title, anchored on this account's own recorded timer runtimes.","tags":["Horizon"],"x-vision-scope":"horizon:write","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"title":{"type":"string"}},"required":["title"]}}}}}},"/api/tasks/{id}/inbox-token":{"get":{"summary":"The task's anonymous-inbox token and QR SVG (null if it isn't a receiver).","description":"The task's anonymous-inbox token and QR SVG (null if it isn't a receiver).","tags":["Horizon"],"x-vision-scope":"horizon:read","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}},"post":{"summary":"Make the task an anonymous-inbox receiver, or rotate its token (old links stop working). Public page: /inbox?t=<token…","description":"Make the task an anonymous-inbox receiver, or rotate its token (old links stop working). Public page: /inbox?t=<token>; submissions land as subtasks immediately.","tags":["Horizon"],"x-vision-scope":"horizon:write","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}},"delete":{"summary":"Stop the task receiving anonymous submissions.","description":"Stop the task receiving anonymous submissions.","tags":["Horizon"],"x-vision-scope":"horizon:write","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}}},"/api/inbox-submissions":{"get":{"summary":"Anonymous-inbox submissions (newest 100): text, status, receiverTaskId, taskId.","description":"Anonymous-inbox submissions (newest 100): text, status, receiverTaskId, taskId.","tags":["Horizon"],"x-vision-scope":"horizon:read","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}}},"/api/inbox-submissions/{id}/{action}":{"post":{"summary":"Decide a submission still marked pending (accept = create it as a subtask of its receiver). New submissions land as s…","description":"Decide a submission still marked pending (accept = create it as a subtask of its receiver). New submissions land as subtasks immediately, so this only matters for old rows.","tags":["Horizon"],"x-vision-scope":"horizon:write","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"action","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}}},"/api/checklists":{"get":{"summary":"Horizon recurring templates (not Loupe checklists): named groups of items that spawn tasks on a recurrence.","description":"Horizon recurring templates (not Loupe checklists): named groups of items that spawn tasks on a recurrence.","tags":["Horizon"],"x-vision-scope":"horizon:read","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}},"post":{"summary":"Create a recurring template.","description":"Create a recurring template.","tags":["Horizon"],"x-vision-scope":"horizon:write","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","description":"New row id — generate a UUID. Ids are client-generated everywhere in VISION."},"name":{"type":"string"},"area":{"type":"string"},"category":{"type":"string"}},"required":["id","name"]}}}}}},"/api/checklists/{id}":{"patch":{"summary":"Patch name, area, category.","description":"Patch name, area, category.","tags":["Horizon"],"x-vision-scope":"horizon:write","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}},"delete":{"summary":"Delete a template and its items.","description":"Delete a template and its items.","tags":["Horizon"],"x-vision-scope":"horizon:write","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}}},"/api/checklist-items":{"get":{"summary":"Items of recurring templates.","description":"Items of recurring templates.","tags":["Horizon"],"x-vision-scope":"horizon:read","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}},"post":{"summary":"Add a recurring item.","description":"Add a recurring item.\n\nRecurrence is evaluated client-side while a Horizon tab is open — there is no server cron.","tags":["Horizon"],"x-vision-scope":"horizon:write","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","description":"New row id — generate a UUID. Ids are client-generated everywhere in VISION."},"checklistId":{"type":"string"},"title":{"type":"string"},"importance":{"type":"integer","description":"1-5"},"recurrence":{"type":"string","description":"JSON string or null. {\"type\":\"weekdays\",\"days\":[1,3,5]} (0=Sunday) | {\"type\":\"interval\",\"n\":2,\"anchor\":\"scheduled\"|\"complete\"} | {\"type\":\"monthly\",\"day\":15|\"last\"} | {\"type\":\"yearly\",\"month\":0-11,\"day\":1-31}."},"festers":{"type":"boolean"},"isMetric":{"type":"boolean","description":"Spawned task records a number."},"metricUnit":{"type":"string"}},"required":["id","checklistId","title"]}}}}}},"/api/checklist-items/{id}":{"patch":{"summary":"Patch checklistId, title, importance, recurrence, lastAutoAddedDate, lastCompletedDate, festers, isMetric, metricUnit.","description":"Patch checklistId, title, importance, recurrence, lastAutoAddedDate, lastCompletedDate, festers, isMetric, metricUnit.","tags":["Horizon"],"x-vision-scope":"horizon:write","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}},"delete":{"summary":"Delete a recurring item.","description":"Delete a recurring item.","tags":["Horizon"],"x-vision-scope":"horizon:write","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}}},"/api/metric-logs":{"get":{"summary":"Numeric readings recorded against metric items.","description":"Numeric readings recorded against metric items.","tags":["Horizon"],"x-vision-scope":"horizon:read","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}},"post":{"summary":"Record a reading.","description":"Record a reading.","tags":["Horizon"],"x-vision-scope":"horizon:write","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","description":"New row id — generate a UUID. Ids are client-generated everywhere in VISION."},"checklistItemId":{"type":"string","description":"The metric item."},"value":{"type":"number","description":"Must be a JSON number."},"taskId":{"type":"string","description":"The spawned task the reading belongs to."},"createdAt":{"type":"integer","description":"Epoch ms."}},"required":["id","checklistItemId","value"]}}}}}},"/api/metric-logs/{id}":{"delete":{"summary":"Delete a reading.","description":"Delete a reading.","tags":["Horizon"],"x-vision-scope":"horizon:write","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}}},"/api/shared-lists":{"post":{"summary":"Create a printable/public check-off list snapshot of tasks; returns its /list?t= token URL.","description":"Create a printable/public check-off list snapshot of tasks; returns its /list?t= token URL.\n\nThe link is public to anyone holding it and has no revoke UI — create only when the person asks.","tags":["Horizon"],"x-vision-scope":"horizon:write","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"items":{"type":"array","description":"≤200 of {text (required), taskId, due YYYY-MM-DD, importance 1-5, notes}. A taskId links check-offs back to the real task.","items":{}},"title":{"type":"string","description":"Sheet heading."}},"required":["items"]}}}}}},"/api/areas":{"get":{"summary":"Domains (user-facing name for areas): id, label, color, sortOrder. Also readable with refract.","description":"Domains (user-facing name for areas): id, label, color, sortOrder. Also readable with refract.","tags":["Horizon"],"x-vision-scope":"horizon:read","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}},"post":{"summary":"Create a domain.","description":"Create a domain.","tags":["Horizon"],"x-vision-scope":"horizon:write","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","description":"New row id — generate a UUID. Ids are client-generated everywhere in VISION."},"label":{"type":"string"},"color":{"type":"string","description":"#rrggbb"},"sortOrder":{"type":"integer"}},"required":["id","label","color"]}}}}}},"/api/areas/{id}":{"patch":{"summary":"Patch label, color (#rrggbb), sortOrder.","description":"Patch label, color (#rrggbb), sortOrder.","tags":["Horizon"],"x-vision-scope":"horizon:write","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}},"delete":{"summary":"Delete a domain. 400 while any task still uses it — move those tasks first.","description":"Delete a domain. 400 while any task still uses it — move those tasks first.","tags":["Horizon"],"x-vision-scope":"horizon:write","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}}},"/api/notes":{"get":{"summary":"All notes, newest-edited first: id, title, body (markdown), folderId, pdfKey, pdfPageCount, createdAt, updatedAt.","description":"All notes, newest-edited first: id, title, body (markdown), folderId, pdfKey, pdfPageCount, createdAt, updatedAt.","tags":["Luminate"],"x-vision-scope":"luminate:read","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}},"post":{"summary":"Create a note.","description":"Create a note.","tags":["Luminate"],"x-vision-scope":"luminate:write","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","description":"New row id — generate a UUID. Ids are client-generated everywhere in VISION."},"title":{"type":"string","description":"≤300 chars."},"body":{"type":"string","description":"Markdown. __x__ = underline in this dialect."},"folderId":{"type":"string"}},"required":["id"]}}}}}},"/api/notes/{id}":{"patch":{"summary":"Patch title, body, folderId. Returns updatedAt.","description":"Patch title, body, folderId. Returns updatedAt.","tags":["Luminate"],"x-vision-scope":"luminate:write","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}},"delete":{"summary":"Delete a note, its PDF, annotations, and scan suggestions.","description":"Delete a note, its PDF, annotations, and scan suggestions.","tags":["Luminate"],"x-vision-scope":"luminate:write","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}}},"/api/notes/search":{"get":{"summary":"Semantic search over notes.","description":"Semantic search over notes.","tags":["Luminate"],"x-vision-scope":"luminate:read","parameters":[{"name":"q","in":"query","required":true,"description":"","schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}}},"/api/notes/{id}/pdf":{"post":{"summary":"Upload the source PDF for a PDF note (raw body, Content-Type application/pdf, ≤25MB).","description":"Upload the source PDF for a PDF note (raw body, Content-Type application/pdf, ≤25MB).","tags":["Luminate"],"x-vision-scope":"luminate:write","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}}},"/api/notes/{id}/pdf-scan":{"post":{"summary":"\"Scan for tasks\": extract up to 6 task suggestions from text lines of a PDF note (one AI call).","description":"\"Scan for tasks\": extract up to 6 task suggestions from text lines of a PDF note (one AI call).","tags":["Luminate"],"x-vision-scope":"luminate:write","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"lines":{"type":"array","description":"[{page, y, text}] — the app sends ≤250 per call.","items":{}},"append":{"type":"boolean","description":"Keep earlier suggestions (chunked scans)."}},"required":["lines"]}}}}}},"/api/note-folders":{"get":{"summary":"Folders: id, name, parentId, sortOrder.","description":"Folders: id, name, parentId, sortOrder.","tags":["Luminate"],"x-vision-scope":"luminate:read","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}},"post":{"summary":"Create a folder.","description":"Create a folder.","tags":["Luminate"],"x-vision-scope":"luminate:write","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","description":"New row id — generate a UUID. Ids are client-generated everywhere in VISION."},"name":{"type":"string"},"parentId":{"type":"string"},"sortOrder":{"type":"integer"}},"required":["id","name"]}}}}}},"/api/note-folders/{id}":{"patch":{"summary":"Patch name, parentId, sortOrder.","description":"Patch name, parentId, sortOrder.","tags":["Luminate"],"x-vision-scope":"luminate:write","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}},"delete":{"summary":"Delete a folder. Its notes and subfolders move up to its parent — never deleted.","description":"Delete a folder. Its notes and subfolders move up to its parent — never deleted.","tags":["Luminate"],"x-vision-scope":"luminate:write","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}}},"/api/note-annotations":{"get":{"summary":"PDF margin annotations: noteId, page, x, y (PDF points), text.","description":"PDF margin annotations: noteId, page, x, y (PDF points), text.","tags":["Luminate"],"x-vision-scope":"luminate:read","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}},"post":{"summary":"Add a margin annotation.","description":"Add a margin annotation.","tags":["Luminate"],"x-vision-scope":"luminate:write","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","description":"New row id — generate a UUID. Ids are client-generated everywhere in VISION."},"noteId":{"type":"string"},"page":{"type":"integer"},"y":{"type":"number","description":"PDF point-space."},"x":{"type":"number"},"text":{"type":"string"}},"required":["id","noteId","page","y"]}}}}}},"/api/note-annotations/{id}":{"patch":{"summary":"Patch text, x, y.","description":"Patch text, x, y.","tags":["Luminate"],"x-vision-scope":"luminate:write","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}},"delete":{"summary":"Delete an annotation.","description":"Delete an annotation.","tags":["Luminate"],"x-vision-scope":"luminate:write","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}}},"/api/note-pdf-suggestions":{"get":{"summary":"Task suggestions from PDF scans.","description":"Task suggestions from PDF scans.","tags":["Luminate"],"x-vision-scope":"luminate:read","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}}},"/api/note-pdf-suggestions/{id}":{"patch":{"summary":"Patch accepted, dismissed, taskId.","description":"Patch accepted, dismissed, taskId.","tags":["Luminate"],"x-vision-scope":"luminate:write","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}}},"/api/bootstrap/pupil":{"get":{"summary":"Everything Pupil boots with: members, certifications, member certifications, goals, notes, activity, prefs.","description":"Everything Pupil boots with: members, certifications, member certifications, goals, notes, activity, prefs.","tags":["Pupil"],"x-vision-scope":"pupil:read","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}}},"/api/pupil-members":{"get":{"summary":"Members: id, name, phone, payRate, availability (JSON string), notes, hiredDate.","description":"Members: id, name, phone, payRate, availability (JSON string), notes, hiredDate.","tags":["Pupil"],"x-vision-scope":"pupil:read","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}},"post":{"summary":"Create a member.","description":"Create a member.","tags":["Pupil"],"x-vision-scope":"pupil:write","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","description":"New row id — generate a UUID. Ids are client-generated everywhere in VISION."},"name":{"type":"string"},"phone":{"type":"string"},"payRate":{"type":"string"},"availability":{"type":"string","description":"JSON string, the 7-day grid object."},"hiredDate":{"type":"string","description":"YYYY-MM-DD"}},"required":["id"]}}}}}},"/api/pupil-members/{id}":{"patch":{"summary":"Patch name, phone, payRate, availability, notes, hiredDate. Pay rate / availability / hired date changes log a timeli…","description":"Patch name, phone, payRate, availability, notes, hiredDate. Pay rate / availability / hired date changes log a timeline activity.","tags":["Pupil"],"x-vision-scope":"pupil:write","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}},"delete":{"summary":"Delete a member and all of their goals, notes, certifications, activity.","description":"Delete a member and all of their goals, notes, certifications, activity.","tags":["Pupil"],"x-vision-scope":"pupil:write","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}}},"/api/pupil-certifications":{"get":{"summary":"Certification types: id, name.","description":"Certification types: id, name.","tags":["Pupil"],"x-vision-scope":"pupil:read","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}},"post":{"summary":"Create a certification type.","description":"Create a certification type.","tags":["Pupil"],"x-vision-scope":"pupil:write","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","description":"New row id — generate a UUID. Ids are client-generated everywhere in VISION."},"name":{"type":"string"}},"required":["id","name"]}}}}}},"/api/pupil-certifications/{id}":{"patch":{"summary":"Rename.","description":"Rename.","tags":["Pupil"],"x-vision-scope":"pupil:write","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}},"delete":{"summary":"Delete a type and every member's record of it.","description":"Delete a type and every member's record of it.","tags":["Pupil"],"x-vision-scope":"pupil:write","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}}},"/api/pupil-member-certifications":{"get":{"summary":"Who holds what: memberId, certificationId, certifiedDate, expiresDate.","description":"Who holds what: memberId, certificationId, certifiedDate, expiresDate.","tags":["Pupil"],"x-vision-scope":"pupil:read","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}},"post":{"summary":"Record a certification for a member.","description":"Record a certification for a member.","tags":["Pupil"],"x-vision-scope":"pupil:write","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","description":"New row id — generate a UUID. Ids are client-generated everywhere in VISION."},"memberId":{"type":"string"},"certificationId":{"type":"string"},"certifiedDate":{"type":"string"},"expiresDate":{"type":"string"}},"required":["id","memberId","certificationId"]}}}}}},"/api/pupil-member-certifications/{id}":{"patch":{"summary":"Patch certifiedDate, expiresDate.","description":"Patch certifiedDate, expiresDate.","tags":["Pupil"],"x-vision-scope":"pupil:write","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}},"delete":{"summary":"Remove.","description":"Remove.","tags":["Pupil"],"x-vision-scope":"pupil:write","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}}},"/api/pupil-goals":{"get":{"summary":"Goals: memberId, text, dueDate, done, completedAt.","description":"Goals: memberId, text, dueDate, done, completedAt.","tags":["Pupil"],"x-vision-scope":"pupil:read","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}},"post":{"summary":"Create a goal.","description":"Create a goal.","tags":["Pupil"],"x-vision-scope":"pupil:write","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","description":"New row id — generate a UUID. Ids are client-generated everywhere in VISION."},"memberId":{"type":"string"},"text":{"type":"string"},"dueDate":{"type":"string"}},"required":["id","memberId","text"]}}}}}},"/api/pupil-goals/{id}":{"patch":{"summary":"Patch text, dueDate, done, completedAt.","description":"Patch text, dueDate, done, completedAt.","tags":["Pupil"],"x-vision-scope":"pupil:write","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}},"delete":{"summary":"Delete a goal.","description":"Delete a goal.","tags":["Pupil"],"x-vision-scope":"pupil:write","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}}},"/api/pupil-notes":{"get":{"summary":"Dated note cards: memberId, body, createdAt.","description":"Dated note cards: memberId, body, createdAt.","tags":["Pupil"],"x-vision-scope":"pupil:read","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}},"post":{"summary":"Add a note.","description":"Add a note.","tags":["Pupil"],"x-vision-scope":"pupil:write","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","description":"New row id — generate a UUID. Ids are client-generated everywhere in VISION."},"memberId":{"type":"string"},"body":{"type":"string"}},"required":["id","memberId"]}}}}}},"/api/pupil-notes/{id}":{"patch":{"summary":"Patch body.","description":"Patch body.","tags":["Pupil"],"x-vision-scope":"pupil:write","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}},"delete":{"summary":"Delete a note.","description":"Delete a note.","tags":["Pupil"],"x-vision-scope":"pupil:write","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}}},"/api/pupil-activity":{"get":{"summary":"Single-line timeline entries (server-written only).","description":"Single-line timeline entries (server-written only).","tags":["Pupil"],"x-vision-scope":"pupil:read","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}}},"/api/pupil-imports":{"post":{"summary":"Idempotent import of one dated artifact; deduped by member+date+text, same member+date with new text = an edit.","description":"Idempotent import of one dated artifact; deduped by member+date+text, same member+date with new text = an edit.","tags":["Pupil"],"x-vision-scope":"pupil:write","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"memberId":{"type":"string"},"artifactType":{"type":"string","description":"note | goal"},"text":{"type":"string"},"date":{"type":"string","description":"YYYY-MM-DD"}},"required":["memberId","artifactType","text"]}}}}}},"/api/bootstrap/loupe":{"get":{"summary":"Everything Loupe boots with: folders, checklists, items, last 30 days of runs, items of open runs, prefs.","description":"Everything Loupe boots with: folders, checklists, items, last 30 days of runs, items of open runs, prefs.","tags":["Loupe"],"x-vision-scope":"loupe:read","parameters":[{"name":"date","in":"query","required":false,"description":"Local YYYY-MM-DD.","schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}}},"/api/loupe-folders":{"get":{"summary":"Deck folders (same semantics as Luminate folders).","description":"Deck folders (same semantics as Luminate folders).","tags":["Loupe"],"x-vision-scope":"loupe:read","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}},"post":{"summary":"Create a folder.","description":"Create a folder.","tags":["Loupe"],"x-vision-scope":"loupe:write","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","description":"New row id — generate a UUID. Ids are client-generated everywhere in VISION."},"name":{"type":"string"},"parentId":{"type":"string"},"position":{"type":"integer"}},"required":["id","name"]}}}}}},"/api/loupe-folders/{id}":{"patch":{"summary":"Patch name, parentId (cycle-checked), position.","description":"Patch name, parentId (cycle-checked), position.","tags":["Loupe"],"x-vision-scope":"loupe:write","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}},"delete":{"summary":"Delete a folder; contents move up to its parent.","description":"Delete a folder; contents move up to its parent.","tags":["Loupe"],"x-vision-scope":"loupe:write","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}}},"/api/loupe-checklists":{"get":{"summary":"{checklists:[…]}: id, name, pausePoint, mode (do_confirm|read_do|null), kind (normal|non_normal), cadence, cadenceDay…","description":"{checklists:[…]}: id, name, pausePoint, mode (do_confirm|read_do|null), kind (normal|non_normal), cadence, cadenceDays, dueTime, version, archived, position, folderId.","tags":["Loupe"],"x-vision-scope":"loupe:read","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}},"post":{"summary":"Create a checklist (id is the only required field).","description":"Create a checklist (id is the only required field).","tags":["Loupe"],"x-vision-scope":"loupe:write","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","description":"New row id — generate a UUID. Ids are client-generated everywhere in VISION."},"name":{"type":"string"},"pausePoint":{"type":"string"},"mode":{"type":"string","description":"do_confirm | read_do; omit = not chosen (no default by design)."},"kind":{"type":"string","description":"normal | non_normal"},"cadence":{"type":"string","description":"none|daily|weekdays|weekly|monthly"},"cadenceDays":{"type":"string","description":"CSV: weekly 0-6 (0=Sun), monthly 1-31."},"dueTime":{"type":"string","description":"HH:MM"},"folderId":{"type":"string"},"position":{"type":"integer"}},"required":["id"]}}}}}},"/api/loupe-checklists/{id}":{"patch":{"summary":"Patch name, pausePoint, mode, kind, cadence, cadenceDays, dueTime, archived, position, folderId. version is not patch…","description":"Patch name, pausePoint, mode, kind, cadence, cadenceDays, dueTime, archived, position, folderId. version is not patchable — cut a revision.","tags":["Loupe"],"x-vision-scope":"loupe:write","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}},"delete":{"summary":"Delete a checklist with its items, runs and revisions. Absorbed tasks are released back to Horizon first.","description":"Delete a checklist with its items, runs and revisions. Absorbed tasks are released back to Horizon first.","tags":["Loupe"],"x-vision-scope":"loupe:write","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}}},"/api/loupe-checklist-items":{"get":{"summary":"{items:[…]}: checklistId, challenge, response, note, position, killer, sourceTaskId.","description":"{items:[…]}: checklistId, challenge, response, note, position, killer, sourceTaskId.","tags":["Loupe"],"x-vision-scope":"loupe:read","parameters":[{"name":"checklistId","in":"query","required":false,"description":"Only this checklist.","schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}},"post":{"summary":"Add one item (appends unless position given).","description":"Add one item (appends unless position given).","tags":["Loupe"],"x-vision-scope":"loupe:write","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","description":"New row id — generate a UUID. Ids are client-generated everywhere in VISION."},"checklistId":{"type":"string"},"challenge":{"type":"string"},"response":{"type":"string"},"note":{"type":"string"},"killer":{"type":"boolean"},"position":{"type":"integer"}},"required":["id","checklistId"]}}}}}},"/api/loupe-checklists/{id}/items/bulk":{"post":{"summary":"Add up to 50 items in one request, at the end or after afterItemId.","description":"Add up to 50 items in one request, at the end or after afterItemId.","tags":["Loupe"],"x-vision-scope":"loupe:write","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"items":{"type":"array","description":"[{challenge (required), response, note, killer}]","items":{}},"afterItemId":{"type":"string"}},"required":["items"]}}}}}},"/api/loupe-checklist-items/{id}":{"patch":{"summary":"Patch challenge, response, note, position, killer.","description":"Patch challenge, response, note, position, killer.","tags":["Loupe"],"x-vision-scope":"loupe:write","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}},"delete":{"summary":"Remove an item; an absorbed source task is released first.","description":"Remove an item; an absorbed source task is released first.","tags":["Loupe"],"x-vision-scope":"loupe:write","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}}},"/api/loupe-checklist-items/{id}/release":{"post":{"summary":"Send an absorbed item back to Horizon as the task it came from, and drop the item.","description":"Send an absorbed item back to Horizon as the task it came from, and drop the item.","tags":["Loupe"],"x-vision-scope":"loupe:write","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}}},"/api/loupe-checklists/{id}/absorb":{"post":{"summary":"Turn Horizon tasks into items; the tasks are hidden (absorbedAt), never deleted or completed.","description":"Turn Horizon tasks into items; the tasks are hidden (absorbedAt), never deleted or completed.","tags":["Loupe"],"x-vision-scope":"loupe:write","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"taskIds":{"type":"array","description":"≤50 ids. Tasks with subtasks must not be absorbed.","items":{}}},"required":["taskIds"]}}}}}},"/api/loupe-checklists/{id}/stats":{"get":{"summary":"Evidence for the CURRENT version: runs, finished, median duration, per-item skip rate and catches.","description":"Evidence for the CURRENT version: runs, finished, median duration, per-item skip rate and catches.","tags":["Loupe"],"x-vision-scope":"loupe:read","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}}},"/api/loupe-checklist-runs":{"get":{"summary":"{runs:[…]} newest first: version, mode, runDate, startedAt, finishedAt, stoppedAt, stopReason, abandoned, taskId.","description":"{runs:[…]} newest first: version, mode, runDate, startedAt, finishedAt, stoppedAt, stopReason, abandoned, taskId.","tags":["Loupe"],"x-vision-scope":"loupe:read","parameters":[{"name":"checklistId","in":"query","required":false,"description":"","schema":{"type":"string"}},{"name":"limit","in":"query","required":false,"description":"1-200, default 50.","schema":{"type":"integer"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}},"post":{"summary":"Start a run (idempotent per checklist + runDate while open). Freezes item text.","description":"Start a run (idempotent per checklist + runDate while open). Freezes item text.\n\nRuns are the person's instrument — an agent running them defeats the point. Read-only use is the norm.","tags":["Loupe"],"x-vision-scope":"loupe:write","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","description":"New row id — generate a UUID. Ids are client-generated everywhere in VISION."},"checklistId":{"type":"string"},"runDate":{"type":"string","description":"The person's local YYYY-MM-DD."},"taskId":{"type":"string","description":"A hex to complete when the run finishes."}},"required":["id","checklistId"]}}}}}},"/api/loupe-checklist-runs/{id}":{"patch":{"summary":"Close a run: finishedAt | stoppedAt + stopReason | abandoned. Closed runs are immutable. A finish completes a linked …","description":"Close a run: finishedAt | stoppedAt + stopReason | abandoned. Closed runs are immutable. A finish completes a linked hex unless it holds open subtasks (taskCompleted:false, reason has_open_children); a stop never does.","tags":["Loupe"],"x-vision-scope":"loupe:write","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}},"delete":{"summary":"Delete a run and its items.","description":"Delete a run and its items.","tags":["Loupe"],"x-vision-scope":"loupe:write","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}}},"/api/loupe-checklist-run-items":{"get":{"summary":"Frozen run items: runId, state (pending|checked|skipped), caught, caughtNote, deviationReason.","description":"Frozen run items: runId, state (pending|checked|skipped), caught, caughtNote, deviationReason.","tags":["Loupe"],"x-vision-scope":"loupe:read","parameters":[{"name":"runId","in":"query","required":true,"description":"","schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}}},"/api/loupe-checklist-run-items/{id}":{"patch":{"summary":"Answer an item on an OPEN run (409 once closed): state, checkedAt, caught, caughtNote, deviationReason.","description":"Answer an item on an OPEN run (409 once closed): state, checkedAt, caught, caughtNote, deviationReason.","tags":["Loupe"],"x-vision-scope":"loupe:write","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}}},"/api/loupe-run-annotations":{"get":{"summary":"Corrections appended to closed runs.","description":"Corrections appended to closed runs.","tags":["Loupe"],"x-vision-scope":"loupe:read","parameters":[{"name":"runId","in":"query","required":true,"description":"","schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}},"post":{"summary":"Append a correction to a closed run.","description":"Append a correction to a closed run.","tags":["Loupe"],"x-vision-scope":"loupe:write","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","description":"New row id — generate a UUID. Ids are client-generated everywhere in VISION."},"runId":{"type":"string"},"text":{"type":"string"}},"required":["id","runId","text"]}}}}}},"/api/loupe-checklist-revisions":{"get":{"summary":"{revisions:[…]}: version, itemCount, note, snapshot (JSON), evidence (JSON).","description":"{revisions:[…]}: version, itemCount, note, snapshot (JSON), evidence (JSON).","tags":["Loupe"],"x-vision-scope":"loupe:read","parameters":[{"name":"checklistId","in":"query","required":false,"description":"","schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}},"post":{"summary":"Cut a revision: snapshot items + evidence at the current version, then version+1.","description":"Cut a revision: snapshot items + evidence at the current version, then version+1.","tags":["Loupe"],"x-vision-scope":"loupe:write","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","description":"New row id — generate a UUID. Ids are client-generated everywhere in VISION."},"checklistId":{"type":"string"},"note":{"type":"string","description":"What changed and why."}},"required":["id","checklistId"]}}}}}},"/api/bootstrap/refract":{"get":{"summary":"Everything Refract boots with: entries, questions, suggested tasks, areas, check-ins, insights, this week's achieveme…","description":"Everything Refract boots with: entries, questions, suggested tasks, areas, check-ins, insights, this week's achievements (hallItems), prefs.","tags":["Refract"],"x-vision-scope":"refract:read","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}}},"/api/refract-entries":{"get":{"summary":"Weekly entries, newest first: weekStart (Monday), worstPart, bestPart, bothering, proud, summary, feedback, locked, p…","description":"Weekly entries, newest first: weekStart (Monday), worstPart, bestPart, bothering, proud, summary, feedback, locked, per-answer summaries.","tags":["Refract"],"x-vision-scope":"refract:read","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}},"post":{"summary":"Create the entry for a week (a race with another device returns the existing row).","description":"Create the entry for a week (a race with another device returns the existing row).","tags":["Refract"],"x-vision-scope":"refract:write","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","description":"New row id — generate a UUID. Ids are client-generated everywhere in VISION."},"weekStart":{"type":"string","description":"Monday YYYY-MM-DD."}},"required":["id","weekStart"]}}}}}},"/api/refract-entries/{id}":{"patch":{"summary":"Patch worstPart, bestPart, bothering, proud (refused until the week's Sunday), locked (false = unlock).","description":"Patch worstPart, bestPart, bothering, proud (refused until the week's Sunday), locked (false = unlock).","tags":["Refract"],"x-vision-scope":"refract:write","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}},"delete":{"summary":"Delete a week's entry with its questions and suggestions.","description":"Delete a week's entry with its questions and suggestions.","tags":["Refract"],"x-vision-scope":"refract:write","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}}},"/api/refract-entries/{id}/generate":{"post":{"summary":"\"Reflect\": 3 follow-up questions + 3-5 suggested to-dos from the reflection and related history (one AI call). Refuse…","description":"\"Reflect\": 3 follow-up questions + 3-5 suggested to-dos from the reflection and related history (one AI call). Refused on a locked entry.","tags":["Refract"],"x-vision-scope":"refract:write","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}}},"/api/refract-entries/{id}/refract":{"post":{"summary":"\"Refract\": lock the entry and write summary, feedback, and per-answer summaries (one AI call).","description":"\"Refract\": lock the entry and write summary, feedback, and per-answer summaries (one AI call).","tags":["Refract"],"x-vision-scope":"refract:write","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}}},"/api/refract-questions":{"get":{"summary":"Follow-up questions: entryId, prompt, answer.","description":"Follow-up questions: entryId, prompt, answer.","tags":["Refract"],"x-vision-scope":"refract:read","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}}},"/api/refract-questions/{id}":{"patch":{"summary":"Patch answer.","description":"Patch answer.","tags":["Refract"],"x-vision-scope":"refract:write","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}}},"/api/refract-suggested-tasks":{"get":{"summary":"Suggested to-dos: entryId, title, rationale, whenHint, accepted, dismissed, taskId.","description":"Suggested to-dos: entryId, title, rationale, whenHint, accepted, dismissed, taskId.","tags":["Refract"],"x-vision-scope":"refract:read","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}}},"/api/refract-suggested-tasks/{id}":{"patch":{"summary":"Patch accepted, dismissed, taskId. Accepting in the app = create a Horizon task (category \"refract\", notes prefixed \"…","description":"Patch accepted, dismissed, taskId. Accepting in the app = create a Horizon task (category \"refract\", notes prefixed \"**When:** <whenHint>\") then PATCH accepted+taskId.","tags":["Refract"],"x-vision-scope":"refract:write","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}},"delete":{"summary":"Delete a suggestion.","description":"Delete a suggestion.","tags":["Refract"],"x-vision-scope":"refract:write","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}}},"/api/refract-checkins":{"get":{"summary":"Daily check-ins: weekStart, dayKey (mon-sat), prompt (frozen), answer.","description":"Daily check-ins: weekStart, dayKey (mon-sat), prompt (frozen), answer.","tags":["Refract"],"x-vision-scope":"refract:read","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}},"post":{"summary":"Answer a day's check-in (unique per week+day).","description":"Answer a day's check-in (unique per week+day).","tags":["Refract"],"x-vision-scope":"refract:write","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","description":"New row id — generate a UUID. Ids are client-generated everywhere in VISION."},"weekStart":{"type":"string","description":"Monday YYYY-MM-DD."},"dayKey":{"type":"string","description":"mon|tue|wed|thu|fri|sat"},"answer":{"type":"string","description":"≤500 chars."}},"required":["id","weekStart","dayKey","answer"]}}}}}},"/api/refract-checkins/{id}":{"patch":{"summary":"Patch answer.","description":"Patch answer.","tags":["Refract"],"x-vision-scope":"refract:write","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}}},"/api/refract-surface/run":{"post":{"summary":"Run the 8am/4pm/midnight surfacing pass (achievement sentence, Insights, narrative revision) now. AI calls; no-op whe…","description":"Run the 8am/4pm/midnight surfacing pass (achievement sentence, Insights, narrative revision) now. AI calls; no-op when nothing's new.","tags":["Refract"],"x-vision-scope":"refract:write","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{}}}},"400":{"$ref":"#/components/responses/Error"},"401":{"$ref":"#/components/responses/Error"},"403":{"$ref":"#/components/responses/Error"},"404":{"$ref":"#/components/responses/Error"}}}}},"components":{"securitySchemes":{"bearer":{"type":"http","scheme":"bearer","description":"A personal access token (vsp_…) from Preferences, or an OAuth access token (vsa_…)."},"oauth":{"type":"oauth2","flows":{"authorizationCode":{"authorizationUrl":"https://achieve.vision/authorize","tokenUrl":"https://achieve.vision/api/oauth/token","refreshUrl":"https://achieve.vision/api/oauth/token","scopes":{"horizon:read":"Read Horizon","horizon:write":"Read and change Horizon","luminate:read":"Read Luminate","luminate:write":"Read and change Luminate","pupil:read":"Read Pupil","pupil:write":"Read and change Pupil","refract:read":"Read Refract","refract:write":"Read and change Refract","loupe:read":"Read Loupe","loupe:write":"Read and change Loupe"}}}}},"responses":{"Error":{"description":"Error","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}}}}}}}}}