{"service":"cfp-scheduler-killer","apiVersion":"v1","description":"Read and write API for conference programs. Every entity carries a stable id, and every join carries the id on both sides. Never match on a name.","auth":{"scheme":"Bearer token, or ?token=","header":"Authorization: Bearer <token>","note":"A token widens what you can read (unpublished rows, statuses, the change feed). It never unlocks private fields: answers marked private on the event's form \u2014 notes to the committee \u2014 are absent from every response, authenticated or not."},"conventions":{"ids":"Opaque, stable, and never reused. Person ids are stable across events.","pagination":"None. Everything is returned in one response at conference scale.","caching":"Every response carries an ETag; send If-None-Match and get a 304.","versioning":"`scheduleVersion` bumps on any change to the event. Poll it, or use /changes?since= for what moved.","publication":"Public responses describe the PUBLISHED program: accepted AND the speaker has been informed, minus anything in a known scheduling conflict."},"endpoints":[{"method":"GET","path":"/api/v1","auth":"public","summary":"This index: what the service is and where the endpoints are."},{"method":"GET","path":"/demo","auth":"public","summary":"Open the demo: one GET, no signup, lands signed in on a live review board."},{"method":"GET","path":"/api/v1/events/{slug}","auth":"public","summary":"Event detail \u2014 ids, dates, timezone, CFP state, and a link to every other endpoint."},{"method":"GET","path":"/api/v1/events/{slug}/docs","auth":"public","summary":"This page."},{"method":"GET","path":"/api/v1/events/{slug}/sessions","auth":"public","summary":"The published program. Every row carries `id` and `speakerIds`."},{"method":"GET","path":"/api/v1/events/{slug}/submissions","auth":"token","summary":"Every submission in every state, with `status`, `notified` and `notifiedAt`."},{"method":"GET","path":"/api/v1/events/{slug}/submissions/{id}","auth":"public","summary":"One submission in full. Unpublished rows require a token."},{"method":"POST","path":"/api/v1/events/{slug}/submissions/{id}/reviews","auth":"reviewer-or-review-bot","summary":"Record an idempotent human or AI review; key scope selects the fact type."},{"method":"GET","path":"/api/v1/events/{slug}/speakers","auth":"public","summary":"One row per PERSON, with `id` and `sessionIds`."},{"method":"GET","path":"/api/v1/events/{slug}/speakers/{personId}","auth":"public","summary":"One speaker and all of their visible sessions."},{"method":"POST","path":"/api/v1/events/{slug}/speakers/{personId}/publish","auth":"token","summary":"Publish one manually managed event speaker. Appends a speaker.published fact."},{"method":"POST","path":"/api/v1/events/{slug}/speakers/{personId}/unpublish","auth":"token","summary":"Unpublish one manually managed event speaker. Appends a speaker.unpublished fact."},{"method":"GET","path":"/api/v1/events/{slug}/schedule","auth":"public","summary":"Days, rooms, placements and blocks \u2014 joined by `sessionId` and `roomId`, plus what is still unscheduled."},{"method":"GET","path":"/api/v1/events/{slug}/rooms","auth":"public","summary":"The rooms, with stable ids."},{"method":"GET","path":"/api/v1/events/{slug}/changes","auth":"token","summary":"Incremental change feed \u2014 ids only, monotonic `seq`."},{"method":"GET","path":"/events/{slug}/exports/sessions.json","auth":"public","summary":"ai.engineer-shaped sessions feed (plus `id` and `speakerIds`)."},{"method":"GET","path":"/events/{slug}/exports/speakers.json","auth":"public","summary":"ai.engineer-shaped speakers feed (plus `id` and `sessionIds`)."},{"method":"GET","path":"/events/{slug}/exports/calendar.ics","auth":"public","summary":"The program as a calendar feed. UIDs are stable \u2014 a late room assignment amends the invite."},{"method":"GET","path":"/events/{slug}/llms.txt","auth":"public","summary":"A markdown index of everything above, for an agent."}]}