{"openapi":"3.1.0","info":{"title":"hackviz ingest-API","summary":"Sanntids agentvisualisering for hackathon","description":"Ingest-API for hackviz: utviklerne pusher status, livssyklus og fase fra agentene sine,\nog visualiseringen viser det i sanntid på storskjerm.\n\n**Autentisering:** alle `POST /api/v1/*`-kall krever headeren `X-Api-Key` med team-nøkkelen.\nLese-endepunktene (`/`, `/events`, `/manual`, `/apidoc`, `/openapi.json`) er åpne.\n\n**Kom i gang:** se utviklermanualen på [/manual](/manual) for oppskrifter til Claude Code,\nCodex og generiske agenter.\n\n**Gyldige statuser:** planning, coding, building, reading, searching, testing, debugging,\nreviewing, talking, waiting_agent, waiting_human, deploying, committing, celebrating,\nblocked, idle. Ukjent verdi faller trygt tilbake til `idle`.\n","contact":{"name":"Arild Ovesen","email":"arild.ovesen@kristiansund.kommune.no"},"version":"1.0.0"},"paths":{"/api/v1/status":{"post":{"tags":["ingest"],"summary":"Push en statusoppdatering for en agent","description":"Oppdaterer agentens status, posisjon og aktivitetstekst. Kall dette hver gang agenten bytter aktivitet (koder, tester, venter, …). Ukjent status → idle. Et valgfritt `code_snippet` havner i kodefeeden (secret-scrubbet).","operationId":"post_status_api_v1_status_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusUpdate"}}},"required":true},"responses":{"202":{"description":"Mottatt og publisert til visningen.","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Post Status Api V1 Status Post"}}}},"401":{"description":"Manglende eller ugyldig X-Api-Key."},"422":{"description":"Ugyldig payload (validering feilet)."},"429":{"description":"Rate limit nådd; se Retry-After-headeren."}}}},"/api/v1/lifecycle":{"post":{"tags":["ingest"],"summary":"Meld en livssyklus-hendelse (ble med / gikk / terminert / krasjet)","description":"Styrer spawn og exit. `agent_joined` spawner figuren i døra; `agent_finished` går rolig ut døra; `agent_terminated` og `agent_crashed` hopper ut nærmeste vindu.","operationId":"post_lifecycle_api_v1_lifecycle_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LifecycleEvent"}}},"required":true},"responses":{"202":{"description":"Mottatt og publisert til visningen.","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Post Lifecycle Api V1 Lifecycle Post"}}}},"401":{"description":"Manglende eller ugyldig X-Api-Key."},"422":{"description":"Ugyldig payload (validering feilet)."},"429":{"description":"Rate limit nådd; se Retry-After-headeren."}}}},"/api/v1/phase":{"post":{"tags":["ingest"],"summary":"Sett overordnet fase for hele teamet","description":"Oppdaterer fasebanneret øverst og legger en linje i aktivitetsfeeden.","operationId":"post_phase_api_v1_phase_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PhaseUpdate"}}},"required":true},"responses":{"202":{"description":"Mottatt og publisert til visningen.","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Post Phase Api V1 Phase Post"}}}},"401":{"description":"Manglende eller ugyldig X-Api-Key."},"422":{"description":"Ugyldig payload (validering feilet)."},"429":{"description":"Rate limit nådd; se Retry-After-headeren."}}}},"/api/v1/reset":{"post":{"tags":["ingest"],"summary":"Nullstill visningen (tøm agenter, fase og feeder)","description":"Fjerner alle agenter og pusher et friskt snapshot, så hver skjerm tømmes.","operationId":"post_reset_api_v1_reset_post","responses":{"202":{"description":"Mottatt og publisert til visningen.","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Post Reset Api V1 Reset Post"}}}},"401":{"description":"Manglende eller ugyldig X-Api-Key."},"422":{"description":"Ugyldig payload (validering feilet)."},"429":{"description":"Rate limit nådd; se Retry-After-headeren."}}}},"/":{"get":{"tags":["view"],"summary":"Index","operationId":"index__get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/manual":{"get":{"tags":["view"],"summary":"Manual","description":"Utviklermanual: hvordan koble en agent til visualiseringen.","operationId":"manual_manual_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/apidoc":{"get":{"tags":["view"],"summary":"Apidoc","description":"API-referanse (ReDoc) rendret fra /openapi.json.","operationId":"apidoc_apidoc_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/events":{"get":{"tags":["view"],"summary":"Events","operationId":"events_events_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/state":{"get":{"tags":["view"],"summary":"Get State","operationId":"get_state_api_v1_state_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Get State Api V1 State Get"}}}}}}},"/healthz":{"get":{"tags":["view"],"summary":"Healthz","operationId":"healthz_healthz_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Healthz Healthz Get"}}}}}}},"/qr.png":{"get":{"tags":["view"],"summary":"Qr","operationId":"qr_qr_png_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}}},"components":{"schemas":{"LifecycleEvent":{"properties":{"agent_id":{"type":"string","maxLength":64,"minLength":1,"pattern":"^[a-zA-Z0-9_-]+$","title":"Agent Id","description":"Samme agent-id som i statusoppdateringene.","examples":["team1-backend"]},"agent_name":{"type":"string","maxLength":48,"minLength":1,"title":"Agent Name","examples":["Bygge-Bjarne"]},"event":{"$ref":"#/components/schemas/LifecycleEventType","description":"joined = spawner i døra; finished = ut døra; terminated/crashed = ut vinduet."},"timestamp":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Timestamp","description":"Valgfri ISO 8601-tid; settes til nåtid om utelatt."}},"type":"object","required":["agent_id","agent_name","event"],"title":"LifecycleEvent","description":"Livssyklus-hendelse for POST /api/v1/lifecycle: agenten ble med, leverte og gikk,\nble terminert eller krasjet. Styrer spawn- og exit-animasjonen (dør vs. vindu).","examples":[{"agent_id":"team1-backend","agent_name":"Bygge-Bjarne","event":"agent_joined"}]},"LifecycleEventType":{"type":"string","enum":["agent_joined","agent_finished","agent_terminated","agent_crashed"],"title":"LifecycleEventType","description":"Lifecycle vocabulary v1 (CLAUDE.md section 4).\n\nJoined spawns at the door; finished walks out calmly; terminated and\ncrashed jump out the nearest window. The distinction is semantic and\nmust stay readable for the audience."},"PhaseUpdate":{"properties":{"phase":{"type":"string","maxLength":96,"minLength":1,"title":"Phase","description":"Fasenavn som vises i banneret.","examples":["Fase 2: Bygger API"]},"description":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Description","description":"Valgfri kort beskrivelse under fasetittelen.","examples":["Ingest og sanntidspush tar form"]},"progress":{"anyOf":[{"type":"number","maximum":1.0,"minimum":0.0},{"type":"null"}],"title":"Progress","description":"Valgfri fremdrift 0.0–1.0 for fremdriftslinja.","examples":[0.4]}},"type":"object","required":["phase"],"title":"PhaseUpdate","description":"Overordnet fase for POST /api/v1/phase. Vises i banneret øverst og som en linje i\naktivitetsfeeden. Gjelder hele teamet, ikke en enkelt agent.","examples":[{"description":"Ingest og sanntidspush tar form","phase":"Fase 2: Bygger API","progress":0.4}]},"StatusUpdate":{"properties":{"agent_id":{"type":"string","maxLength":64,"minLength":1,"pattern":"^[a-zA-Z0-9_-]+$","title":"Agent Id","description":"Stabil, unik id for agenten. Samme id over tid = samme figur på skjermen.","examples":["team1-backend"]},"agent_name":{"type":"string","maxLength":48,"minLength":1,"title":"Agent Name","description":"Visningsnavn over figuren.","examples":["Bygge-Bjarne"]},"status":{"type":"string","maxLength":32,"minLength":1,"title":"Status","description":"En av statusverdiene i AgentStatus. Ukjent verdi → idle.","examples":["coding"]},"phase":{"anyOf":[{"type":"string","maxLength":96},{"type":"null"}],"title":"Phase","description":"Valgfri fase-etikett agenten jobber i.","examples":["Fase 2: Bygger API"]},"detail":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Detail","description":"Kort menneskelesbar tekst. Vises i aktivitetsfeeden (secret-scrubbet).","examples":["Skriver ingest-endepunktet"]},"code_snippet":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Code Snippet","description":"Valgfritt kodeutdrag til kodefeeden. Maks 2000 tegn, secret-scrubbet."},"timestamp":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Timestamp","description":"Valgfri ISO 8601-tid. Utelates den, settes serverens nåtid."}},"type":"object","required":["agent_id","agent_name","status"],"title":"StatusUpdate","description":"Statusoppdatering for én agent. Pushes til POST /api/v1/status hver gang agenten\nbytter aktivitet. Ukjent `status` faller tilbake til `idle` uten å knekke visningen.","examples":[{"agent_id":"team1-backend","agent_name":"Bygge-Bjarne","code_snippet":"@router.post('/status')\nasync def post_status(...): ...","detail":"Skriver ingest-endepunktet","phase":"Fase 2: Bygger API","status":"coding"}]}}},"tags":[{"name":"ingest","description":"Autentiserte skrive-endepunkter agentene pusher til."},{"name":"view","description":"Åpne lese-endepunkter: visning, strøm, helse, docs."}]}