{"openapi":"3.1.0","info":{"title":"Sensory Experience API","version":"1.2.0","description":"Role-enforced business workspace and event API. Inventory, saved templates and general accounting work without events. Payment processing is deferred. Read /docs/agent-manual.md before writing."},"security":[{"agentBearer":[]},{"staffSession":[]}],"components":{"securitySchemes":{"agentBearer":{"type":"http","scheme":"bearer"},"staffSession":{"type":"apiKey","in":"cookie","name":"__Host-sensory_session"},"participantToken":{"type":"apiKey","in":"header","name":"X-Participant-Token"}},"schemas":{"ShoppingReceipt":{"type":"object","required":["date","totalCents","location","photos"],"properties":{"id":{"type":"string","maxLength":120,"description":"Omit to add; supply a saved receipt ID to edit."},"date":{"type":"string","format":"date"},"totalCents":{"type":"integer","minimum":0,"maximum":1000000000,"description":"USD total in cents (1234 means $12.34)."},"location":{"type":"string","minLength":1,"maxLength":300},"photos":{"type":"array","maxItems":10,"uniqueItems":true,"items":{"type":"string","maxLength":1000},"description":"Accepted image attachment keys from this workspace. Empty allowed; PDFs are not receipt photos."},"created":{"type":"string","readOnly":true},"updated":{"type":"string","readOnly":true}}},"Fact":{"type":"object","required":["title","body","sourceUrl","stockIds","descriptors","archived"],"properties":{"id":{"type":"string","maxLength":120,"description":"Omit to create; use a saved id to edit."},"title":{"type":"string","minLength":1,"maxLength":120},"body":{"type":"string","minLength":1,"maxLength":2000},"sourceUrl":{"type":"string","maxLength":2000,"description":"Empty or an http/https URL."},"stockIds":{"type":"array","maxItems":100,"uniqueItems":true,"items":{"type":"string"},"description":"Existing inventory IDs; empty for no inventory link."},"descriptors":{"type":"array","maxItems":50,"uniqueItems":true,"items":{"type":"string","minLength":1,"maxLength":120},"description":"Sensory language terms; custom terms accepted. Case-insensitive duplicates rejected."},"archived":{"type":"boolean"},"created":{"type":"string","readOnly":true},"updated":{"type":"string","readOnly":true}}},"Answer":{"type":"object","properties":{"liking":{"type":"integer","minimum":1,"maximum":7},"intensity":{"type":"integer","minimum":1,"maximum":7},"descriptors":{"type":"array","maxItems":3,"items":{"type":"string","maxLength":80}},"measure":{"type":"string","maxLength":80},"notes":{"type":"string","maxLength":1000},"skip":{"type":"boolean"}}},"StudioAction":{"type":"object","description":"Administrator shopping receipts, shared facts, stock, saved templates and general business accounting do not require an event. Event operations require eventId.","required":["action"],"allOf":[{"if":{"properties":{"action":{"const":"saveShoppingReceipt"}}},"then":{"required":["receipt"]}},{"if":{"properties":{"action":{"const":"saveFact"}}},"then":{"required":["fact"]}},{"if":{"properties":{"action":{"const":"selectFacts"}}},"then":{"required":["factIds"]}},{"if":{"properties":{"action":{"enum":["selectFacts","saveEvent","ready","check","panel","screen","end","removePanel","usage","paperJoin","paperAnswer","correctAnswer","document","simulate"]}}},"then":{"required":["eventId"],"properties":{"eventId":{"type":"string","minLength":1}}}},{"if":{"properties":{"action":{"const":"savePanel"}},"not":{"required":["template"],"properties":{"template":{"const":true}}}},"then":{"required":["eventId"],"properties":{"eventId":{"type":"string","minLength":1}}}}],"properties":{"receipt":{"type":"object","required":["date","totalCents","location","photos"],"properties":{"id":{"type":"string","maxLength":120,"description":"Omit to add; supply a saved receipt ID to edit."},"date":{"type":"string","format":"date"},"totalCents":{"type":"integer","minimum":0,"maximum":1000000000,"description":"USD total in cents (1234 means $12.34)."},"location":{"type":"string","minLength":1,"maxLength":300},"photos":{"type":"array","maxItems":10,"uniqueItems":true,"items":{"type":"string","maxLength":1000},"description":"Accepted image attachment keys from this workspace. Empty allowed; PDFs are not receipt photos."},"created":{"type":"string","readOnly":true},"updated":{"type":"string","readOnly":true}}},"fact":{"type":"object","required":["title","body","sourceUrl","stockIds","descriptors","archived"],"properties":{"id":{"type":"string","maxLength":120,"description":"Omit to create; use a saved id to edit."},"title":{"type":"string","minLength":1,"maxLength":120},"body":{"type":"string","minLength":1,"maxLength":2000},"sourceUrl":{"type":"string","maxLength":2000,"description":"Empty or an http/https URL."},"stockIds":{"type":"array","maxItems":100,"uniqueItems":true,"items":{"type":"string"},"description":"Existing inventory IDs; empty for no inventory link."},"descriptors":{"type":"array","maxItems":50,"uniqueItems":true,"items":{"type":"string","minLength":1,"maxLength":120},"description":"Sensory language terms; custom terms accepted. Case-insensitive duplicates rejected."},"archived":{"type":"boolean"},"created":{"type":"string","readOnly":true},"updated":{"type":"string","readOnly":true}}},"factIds":{"type":"array","maxItems":100,"uniqueItems":true,"items":{"type":"string"},"description":"selectFacts replaces the event shortlist with active saved fact IDs. Empty clears it. Ended events cannot change selections."},"action":{"type":"string","enum":["saveShoppingReceipt","saveFact","selectFacts","newEvent","saveEvent","ready","check","panel","screen","end","savePanel","removePanel","stock","stockLoss","entry","reconcileEntry","usage","paperJoin","paperAnswer","correctAnswer","document","simulate"]},"eventId":{"type":"string","description":"Required for event operations and event panel copies. Omit for saveShoppingReceipt, saveFact, stock, stockLoss or savePanel with template:true. Ledger association comes from entry.eventId or the existing ledger record, not this field."},"name":{"type":"string"},"data":{"type":"object","description":"Complete event details from GET /api/studio, with intended edits."},"index":{"type":"integer","minimum":0},"command":{"type":"string","enum":["open","close","reopen","reveal"]},"closePrevious":{"type":"boolean"},"screen":{"type":"object","required":["kind","panel","metric","message","timer"],"allOf":[{"if":{"properties":{"kind":{"const":"fact"}}},"then":{"required":["factId"]}}],"properties":{"kind":{"enum":["welcome","panel","reveal","results","fact"]},"factId":{"type":"string","description":"Required for kind:fact; must be active and selected for the event. Public content is only available while shown."},"panel":{"type":"integer"},"metric":{"type":"string"},"message":{"type":"string","maxLength":1000},"timer":{"type":"number","description":"Unix milliseconds; zero clears the timer."}}},"panel":{"type":"object","description":"Complete panel object from the studio; stable item IDs required when editing an opened panel. Sample ingredients and allergens are read-only values resolved from stockId; any supplied sample label text is ignored."},"template":{"type":"boolean","description":"true saves a shared template without eventId; false or omitted edits/adds an event panel copy and requires eventId."},"stockId":{"type":"string"},"quantity":{"type":"number","exclusiveMinimum":0,"description":"Units to remove for stockLoss; cannot exceed on-hand quantity."},"notes":{"type":"string","maxLength":1000},"stock":{"type":"object","description":"Complete inventory record. Inventory is the source of truth for ingredients and allergen statements; linked samples and allergen sheets read these fields automatically. Omitting ingredients, allergens or photos preserves existing values. Empty strings clear label text; an empty array detaches photos.","properties":{"ingredients":{"type":"string","maxLength":10000,"description":"Full ingredients list from the actual package."},"allergens":{"type":"string","maxLength":10000,"description":"Package allergen statements, including Contains, May contain and shared-facility warnings."},"photos":{"type":"array","maxItems":20,"uniqueItems":true,"items":{"type":"string"},"description":"Accepted image keys only; PDFs are not package photos."},"photoLabels":{"type":"object","additionalProperties":{"type":"string","maxLength":80},"description":"Optional side labels keyed by an attached photo key."}}},"entry":{"type":"object","required":["kind","amount","description"],"properties":{"eventId":{"type":"string","description":"Optional. Omit or use an empty string for General business; supply an existing event ID only to associate this transaction with that event."},"kind":{"enum":["income","expense","refund","credit"]},"amount":{"type":"number","exclusiveMinimum":0},"description":{"type":"string"},"date":{"type":"string"},"category":{"type":"string"},"receipt":{"type":"string"},"reconciled":{"type":"boolean"}}},"participantId":{"type":"string"},"itemId":{"type":"string"},"answer":{"type":"object","properties":{"liking":{"type":"integer","minimum":1,"maximum":7},"intensity":{"type":"integer","minimum":1,"maximum":7},"descriptors":{"type":"array","maxItems":3,"items":{"type":"string","maxLength":80}},"measure":{"type":"string","maxLength":80},"notes":{"type":"string","maxLength":1000},"skip":{"type":"boolean"}}},"reason":{"type":"string","description":"For stockLoss: Spoiled, Damaged / ruined, Opened / discarded, Missing, or Other (notes required)."},"requestedBy":{"type":"string","description":"Authorized human host ID for agent corrections."},"count":{"type":"integer","minimum":1,"maximum":100},"approvalId":{"type":"string"},"key":{"type":"string"},"value":{"type":"boolean"},"id":{"type":"string"},"usage":{"type":"object","description":"After ending an event, account for every packedInventory item (legacy events use requirements). Used + waste + returned must equal packed quantity. Return only unopened unused items or reusable equipment. Saving persists inventoryUsage and event losses, releases reservations, and cannot be repeated.","additionalProperties":{"type":"object","required":["used","waste","returned"],"properties":{"used":{"type":"number","minimum":0},"waste":{"type":"number","minimum":0},"returned":{"type":"number","minimum":0}}}},"adjustCount":{"type":"boolean"}}}}},"paths":{"/api/auth/status":{"get":{"summary":"Current identity, role, environment and integration availability","security":[],"responses":{"200":{"description":"Successful response"},"202":{"description":"Human approval required; no business change applied"},"400":{"description":"Validation failed"},"401":{"description":"Authentication required"},"403":{"description":"Role or event assignment denied"},"409":{"description":"Conflicting update or idempotency-key reuse"},"429":{"description":"Rate limited"}}}},"/api/studio":{"get":{"summary":"Read your authorized studio records","description":"Includes shoppingReceipts for administrators only (separate from the accounting ledger), facts (shared library) and events[].selectedFactIds (event shortlist). Archived facts remain in staff data but cannot be selected or displayed.","responses":{"200":{"description":"Successful response"},"202":{"description":"Human approval required; no business change applied"},"400":{"description":"Validation failed"},"401":{"description":"Authentication required"},"403":{"description":"Role or event assignment denied"},"409":{"description":"Conflicting update or idempotency-key reuse"},"429":{"description":"Rate limited"}}},"post":{"summary":"Apply an event, inventory, template or manual accounting action","parameters":[{"name":"Idempotency-Key","in":"header","schema":{"type":"string","maxLength":120},"description":"Required for agents; reuse only for an exact retry."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","description":"Administrator shopping receipts, shared facts, stock, saved templates and general business accounting do not require an event. Event operations require eventId.","required":["action"],"allOf":[{"if":{"properties":{"action":{"const":"saveShoppingReceipt"}}},"then":{"required":["receipt"]}},{"if":{"properties":{"action":{"const":"saveFact"}}},"then":{"required":["fact"]}},{"if":{"properties":{"action":{"const":"selectFacts"}}},"then":{"required":["factIds"]}},{"if":{"properties":{"action":{"enum":["selectFacts","saveEvent","ready","check","panel","screen","end","removePanel","usage","paperJoin","paperAnswer","correctAnswer","document","simulate"]}}},"then":{"required":["eventId"],"properties":{"eventId":{"type":"string","minLength":1}}}},{"if":{"properties":{"action":{"const":"savePanel"}},"not":{"required":["template"],"properties":{"template":{"const":true}}}},"then":{"required":["eventId"],"properties":{"eventId":{"type":"string","minLength":1}}}}],"properties":{"receipt":{"type":"object","required":["date","totalCents","location","photos"],"properties":{"id":{"type":"string","maxLength":120,"description":"Omit to add; supply a saved receipt ID to edit."},"date":{"type":"string","format":"date"},"totalCents":{"type":"integer","minimum":0,"maximum":1000000000,"description":"USD total in cents (1234 means $12.34)."},"location":{"type":"string","minLength":1,"maxLength":300},"photos":{"type":"array","maxItems":10,"uniqueItems":true,"items":{"type":"string","maxLength":1000},"description":"Accepted image attachment keys from this workspace. Empty allowed; PDFs are not receipt photos."},"created":{"type":"string","readOnly":true},"updated":{"type":"string","readOnly":true}}},"fact":{"type":"object","required":["title","body","sourceUrl","stockIds","descriptors","archived"],"properties":{"id":{"type":"string","maxLength":120,"description":"Omit to create; use a saved id to edit."},"title":{"type":"string","minLength":1,"maxLength":120},"body":{"type":"string","minLength":1,"maxLength":2000},"sourceUrl":{"type":"string","maxLength":2000,"description":"Empty or an http/https URL."},"stockIds":{"type":"array","maxItems":100,"uniqueItems":true,"items":{"type":"string"},"description":"Existing inventory IDs; empty for no inventory link."},"descriptors":{"type":"array","maxItems":50,"uniqueItems":true,"items":{"type":"string","minLength":1,"maxLength":120},"description":"Sensory language terms; custom terms accepted. Case-insensitive duplicates rejected."},"archived":{"type":"boolean"},"created":{"type":"string","readOnly":true},"updated":{"type":"string","readOnly":true}}},"factIds":{"type":"array","maxItems":100,"uniqueItems":true,"items":{"type":"string"},"description":"selectFacts replaces the event shortlist with active saved fact IDs. Empty clears it. Ended events cannot change selections."},"action":{"type":"string","enum":["saveShoppingReceipt","saveFact","selectFacts","newEvent","saveEvent","ready","check","panel","screen","end","savePanel","removePanel","stock","stockLoss","entry","reconcileEntry","usage","paperJoin","paperAnswer","correctAnswer","document","simulate"]},"eventId":{"type":"string","description":"Required for event operations and event panel copies. Omit for saveShoppingReceipt, saveFact, stock, stockLoss or savePanel with template:true. Ledger association comes from entry.eventId or the existing ledger record, not this field."},"name":{"type":"string"},"data":{"type":"object","description":"Complete event details from GET /api/studio, with intended edits."},"index":{"type":"integer","minimum":0},"command":{"type":"string","enum":["open","close","reopen","reveal"]},"closePrevious":{"type":"boolean"},"screen":{"type":"object","required":["kind","panel","metric","message","timer"],"allOf":[{"if":{"properties":{"kind":{"const":"fact"}}},"then":{"required":["factId"]}}],"properties":{"kind":{"enum":["welcome","panel","reveal","results","fact"]},"factId":{"type":"string","description":"Required for kind:fact; must be active and selected for the event. Public content is only available while shown."},"panel":{"type":"integer"},"metric":{"type":"string"},"message":{"type":"string","maxLength":1000},"timer":{"type":"number","description":"Unix milliseconds; zero clears the timer."}}},"panel":{"type":"object","description":"Complete panel object from the studio; stable item IDs required when editing an opened panel. Sample ingredients and allergens are read-only values resolved from stockId; any supplied sample label text is ignored."},"template":{"type":"boolean","description":"true saves a shared template without eventId; false or omitted edits/adds an event panel copy and requires eventId."},"stockId":{"type":"string"},"quantity":{"type":"number","exclusiveMinimum":0,"description":"Units to remove for stockLoss; cannot exceed on-hand quantity."},"notes":{"type":"string","maxLength":1000},"stock":{"type":"object","description":"Complete inventory record. Inventory is the source of truth for ingredients and allergen statements; linked samples and allergen sheets read these fields automatically. Omitting ingredients, allergens or photos preserves existing values. Empty strings clear label text; an empty array detaches photos.","properties":{"ingredients":{"type":"string","maxLength":10000,"description":"Full ingredients list from the actual package."},"allergens":{"type":"string","maxLength":10000,"description":"Package allergen statements, including Contains, May contain and shared-facility warnings."},"photos":{"type":"array","maxItems":20,"uniqueItems":true,"items":{"type":"string"},"description":"Accepted image keys only; PDFs are not package photos."},"photoLabels":{"type":"object","additionalProperties":{"type":"string","maxLength":80},"description":"Optional side labels keyed by an attached photo key."}}},"entry":{"type":"object","required":["kind","amount","description"],"properties":{"eventId":{"type":"string","description":"Optional. Omit or use an empty string for General business; supply an existing event ID only to associate this transaction with that event."},"kind":{"enum":["income","expense","refund","credit"]},"amount":{"type":"number","exclusiveMinimum":0},"description":{"type":"string"},"date":{"type":"string"},"category":{"type":"string"},"receipt":{"type":"string"},"reconciled":{"type":"boolean"}}},"participantId":{"type":"string"},"itemId":{"type":"string"},"answer":{"type":"object","properties":{"liking":{"type":"integer","minimum":1,"maximum":7},"intensity":{"type":"integer","minimum":1,"maximum":7},"descriptors":{"type":"array","maxItems":3,"items":{"type":"string","maxLength":80}},"measure":{"type":"string","maxLength":80},"notes":{"type":"string","maxLength":1000},"skip":{"type":"boolean"}}},"reason":{"type":"string","description":"For stockLoss: Spoiled, Damaged / ruined, Opened / discarded, Missing, or Other (notes required)."},"requestedBy":{"type":"string","description":"Authorized human host ID for agent corrections."},"count":{"type":"integer","minimum":1,"maximum":100},"approvalId":{"type":"string"},"key":{"type":"string"},"value":{"type":"boolean"},"id":{"type":"string"},"usage":{"type":"object","description":"After ending an event, account for every packedInventory item (legacy events use requirements). Used + waste + returned must equal packed quantity. Return only unopened unused items or reusable equipment. Saving persists inventoryUsage and event losses, releases reservations, and cannot be repeated.","additionalProperties":{"type":"object","required":["used","waste","returned"],"properties":{"used":{"type":"number","minimum":0},"waste":{"type":"number","minimum":0},"returned":{"type":"number","minimum":0}}}},"adjustCount":{"type":"boolean"}}}}}},"responses":{"200":{"description":"Successful response"},"202":{"description":"Human approval required; no business change applied"},"400":{"description":"Validation failed"},"401":{"description":"Authentication required"},"403":{"description":"Role or event assignment denied"},"409":{"description":"Conflicting update or idempotency-key reuse"},"429":{"description":"Rate limited"}}}},"/api/event":{"get":{"summary":"Public event and your personal workbook when authenticated","description":"fact contains only the currently displayed active fact (id, title, body, sourceUrl), otherwise null. Library, inventory links, sensory links and shortlist remain private.","security":[{},{"participantToken":[]},{"agentBearer":[]}],"parameters":[{"name":"id","in":"query","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response"},"202":{"description":"Human approval required; no business change applied"},"400":{"description":"Validation failed"},"401":{"description":"Authentication required"},"403":{"description":"Role or event assignment denied"},"409":{"description":"Conflicting update or idempotency-key reuse"},"429":{"description":"Rate limited"}}},"post":{"summary":"Join, answer, save Flavorprint or request your review link","security":[{"participantToken":[]},{"agentBearer":[]},{}],"parameters":[{"name":"Idempotency-Key","in":"header","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["action","eventId"],"properties":{"action":{"enum":["join","answer","flavorprint","requestReviewLink"]},"eventId":{"type":"string"},"name":{"type":"string"},"email":{"type":"string"},"itemId":{"type":"string"},"answer":{"type":"object","properties":{"liking":{"type":"integer","minimum":1,"maximum":7},"intensity":{"type":"integer","minimum":1,"maximum":7},"descriptors":{"type":"array","maxItems":3,"items":{"type":"string","maxLength":80}},"measure":{"type":"string","maxLength":80},"notes":{"type":"string","maxLength":1000},"skip":{"type":"boolean"}}},"values":{"type":"object"}}}}}},"responses":{"200":{"description":"Successful response"},"202":{"description":"Human approval required; no business change applied"},"400":{"description":"Validation failed"},"401":{"description":"Authentication required"},"403":{"description":"Role or event assignment denied"},"409":{"description":"Conflicting update or idempotency-key reuse"},"429":{"description":"Rate limited"}}}},"/api/staff":{"get":{"summary":"Administrator: list staff and agent assignments","responses":{"200":{"description":"Successful response"},"202":{"description":"Human approval required; no business change applied"},"400":{"description":"Validation failed"},"401":{"description":"Authentication required"},"403":{"description":"Role or event assignment denied"},"409":{"description":"Conflicting update or idempotency-key reuse"},"429":{"description":"Rate limited"}}},"post":{"summary":"Human administrator: save/revoke access or issue a link/credential","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["action"],"properties":{"action":{"enum":["save","revoke","link","credential"]},"id":{"type":"string"},"name":{"type":"string"},"email":{"type":"string"},"kind":{"enum":["human","agent"]},"roles":{"type":"array","items":{"enum":["administrator","host","participant"]}},"events":{"type":"array","items":{"type":"string"}},"participantId":{"type":"string"},"sendEmail":{"type":"boolean"}}}}}},"responses":{"200":{"description":"Successful response"},"202":{"description":"Human approval required; no business change applied"},"400":{"description":"Validation failed"},"401":{"description":"Authentication required"},"403":{"description":"Role or event assignment denied"},"409":{"description":"Conflicting update or idempotency-key reuse"},"429":{"description":"Rate limited"}}}},"/api/audit":{"get":{"summary":"Read latest 100 authorized audit entries and pending approvals","parameters":[{"name":"eventId","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response"},"202":{"description":"Human approval required; no business change applied"},"400":{"description":"Validation failed"},"401":{"description":"Authentication required"},"403":{"description":"Role or event assignment denied"},"409":{"description":"Conflicting update or idempotency-key reuse"},"429":{"description":"Rate limited"}}},"post":{"summary":"Human administrator: approve or reject an exact pending request","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["id","action"],"properties":{"id":{"type":"string"},"action":{"enum":["approve","reject"]}}}}}},"responses":{"200":{"description":"Successful response"},"202":{"description":"Human approval required; no business change applied"},"400":{"description":"Validation failed"},"401":{"description":"Authentication required"},"403":{"description":"Role or event assignment denied"},"409":{"description":"Conflicting update or idempotency-key reuse"},"429":{"description":"Rate limited"}}}},"/api/upload":{"post":{"summary":"Stage image bytes for review, save a PDF, or accept/discard a staged image","parameters":[{"name":"eventId","in":"query","schema":{"type":"string"},"description":"Optional for administrator inventory, template photos and general receipts. Use an event ID for event attachments; host PDF uploads require an assigned event."},{"name":"X-File-Name","in":"header","schema":{"type":"string"},"description":"URL-encoded filename for raw uploads."}],"requestBody":{"required":true,"content":{"image/jpeg":{"schema":{"type":"string","format":"binary"}},"image/png":{"schema":{"type":"string","format":"binary"}},"image/webp":{"schema":{"type":"string","format":"binary"}},"application/pdf":{"schema":{"type":"string","format":"binary"}},"application/json":{"schema":{"type":"object","required":["action","key"],"properties":{"action":{"enum":["accept","discard"]},"key":{"type":"string"}}}}}},"responses":{"200":{"description":"Successful response"},"202":{"description":"Human approval required; no business change applied"},"400":{"description":"Validation failed"},"401":{"description":"Authentication required"},"403":{"description":"Role or event assignment denied"},"409":{"description":"Conflicting update or idempotency-key reuse"},"429":{"description":"Rate limited"}}}},"/api/file":{"get":{"summary":"Read an authorized attachment or event package photo","parameters":[{"name":"key","in":"query","required":true,"schema":{"type":"string"}},{"name":"event","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Successful response"},"202":{"description":"Human approval required; no business change applied"},"400":{"description":"Validation failed"},"401":{"description":"Authentication required"},"403":{"description":"Role or event assignment denied"},"409":{"description":"Conflicting update or idempotency-key reuse"},"429":{"description":"Rate limited"}}}},"/api/templates":{"get":{"summary":"Administrator: export content without photos or operational records","responses":{"200":{"description":"Successful response"},"202":{"description":"Human approval required; no business change applied"},"400":{"description":"Validation failed"},"401":{"description":"Authentication required"},"403":{"description":"Role or event assignment denied"},"409":{"description":"Conflicting update or idempotency-key reuse"},"429":{"description":"Rate limited"}}},"post":{"summary":"Human administrator: deliberately import reusable template content","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["format","version","panels"],"properties":{"format":{"const":"sensory-templates"},"version":{"const":1},"panels":{"type":"array","items":{"type":"object"}}}}}}},"responses":{"200":{"description":"Successful response"},"202":{"description":"Human approval required; no business change applied"},"400":{"description":"Validation failed"},"401":{"description":"Authentication required"},"403":{"description":"Role or event assignment denied"},"409":{"description":"Conflicting update or idempotency-key reuse"},"429":{"description":"Rate limited"}}}},"/api/review-links":{"post":{"summary":"Host: send personal links to participants with supplied emails","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["eventId"],"properties":{"eventId":{"type":"string"}}}}}},"responses":{"200":{"description":"Successful response"},"202":{"description":"Human approval required; no business change applied"},"400":{"description":"Validation failed"},"401":{"description":"Authentication required"},"403":{"description":"Role or event assignment denied"},"409":{"description":"Conflicting update or idempotency-key reuse"},"429":{"description":"Rate limited"}}}},"/api/mcp":{"post":{"summary":"Stateless Streamable HTTP MCP endpoint; bearer authentication required","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["jsonrpc","method"],"properties":{"jsonrpc":{"const":"2.0"},"id":{},"method":{"type":"string"},"params":{"type":"object"}}}}}},"responses":{"200":{"description":"Successful response"},"202":{"description":"Human approval required; no business change applied"},"400":{"description":"Validation failed"},"401":{"description":"Authentication required"},"403":{"description":"Role or event assignment denied"},"409":{"description":"Conflicting update or idempotency-key reuse"},"429":{"description":"Rate limited"}}}}}}