{"openapi":"3.1.0","info":{"title":"De Arbetar För Dig — API","version":"0.4.0","description":"Öppen demokrati-API — gör svensk kommunalpolitik tillgänglig, sökbar och begriplig. Sverige har 290 kommuner; API:t är strukturerat per kommun (`/v1/{kommun}/...`) för att kunna växa bortom den första, **Göteborg**, som just nu är den enda med data.\n\n**HAL Format (Hypertext Application Language):**\n\nAlla svar följer HAL-standarden för hypermedia API:er.\n\n*Listor (collections):*\n```json\n{\n  \"_embedded\": { \"items\": [...] },\n  \"_links\": { \"self\": { \"href\": \"/v1/goteborg/politiker\" } },\n  \"total\": 125\n}\n```\n\n*Resurser (single item):*\n```json\n{\n  \"_embedded\": {\n    \"item\": { \"id\": \"...\", \"namn\": \"...\" },\n    \"related\": { \"möten\": [...] }\n  },\n  \"_links\": {\n    \"self\": { \"href\": \"/v1/goteborg/politiker/{id}\" },\n    \"collection\": { \"href\": \"/v1/goteborg/politiker\" }\n  }\n}\n```\n\n**Endpoints:**\n- `/möten?år=` — Lista sammanträden (KF+KS) med url per möte\n- `/möten/{datum}` — Enskilt möte: beslut, närvaro, anföranden\n- `/politiker` — Förtroendevalda (KF-ledamöter, nämnder, bolagsstyrelser) med uppdrag och möten\n- `/politiker/{id}` — Detaljprofil inkl. lista över möten där politikern talade\n- `/politiker/{id}/anforanden?datum=` — Anföranden (tal) per möte\n- `/kandidater` — Kandidater till KF, val 2026 (Valmyndigheten), länkade till sittande politiker där matchning finns\n- `/beslut` — KF/KS-beslut med voteringar och ärendenummer\n- `/möten/{datum}/anföranden` — Alla anföranden från ett sammanträde (?talare=, ?ärende=, ?q=)\n- `/budget?år=` — Kommunbudget per nämnd (2022–2026)\n- `/graf?typ=&datum=&limit=&offset=` — Knowledge graph (noder + kanter). Paragrafernas tunga texter (`fulltext`, `handlingText`) utelämnas som standard — `?fulltext=true` eller `/beslut/{id}` ger dem\n- `/graf/node/{id}` — Graf-nod med relaterade noder och kanter\n- `/stats` — Demokratisk hälsa (Rice-index, Gini, konsensusgrad)\n- `/metrics` — Beslutskraft och partilojalitet\n- `/sök?q=` — Fulltextsökning över alla resurser: typade träffar (`beslut`, `politiker`, `dokument`, `forvaltning`, `anforande`) med utdrag, score och frontend-URL. Filter: `typ`, `organ` (kf/ks/namnd), `parti`, `från`/`till`, `limit`/`offset`\n\n**Svarsheaders:** lyckade GET-svar under `/v1` cachas fem minuter\n(`Cache-Control: public, max-age=300`) och har `ETag` — skicka\n`If-None-Match` för att få `304` i stället för kroppen. Datan uppdateras av\nveckovisa scrapers. Rate limit är 200 anrop/minut per IP (`429`). Alla fel svarar\nJSON (`{ \"error\": \"...\" }`), även 404, 405 och 500.\n\n**Datakällor:** Nämndhandlingar (goteborg.se), Yttrandeprotokoll PDF, Valmyndigheten","license":{"name":"AGPL-3.0","url":"https://www.gnu.org/licenses/agpl-3.0.html"},"contact":{"name":"DeArbetarForDig","url":"https://github.com/DeArbetarForDig/dearbetarfordig.se"}},"servers":[{"url":"https://api.dearbetarfordig.se","description":"Produktion"},{"url":"http://localhost:3000","description":"Lokal utveckling"}],"components":{"schemas":{"PolitikerSummary":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"namn":{"type":"string"},"parti":{"type":"string"},"email":{"type":["string","null"]},"antalUppdrag":{"type":"number"}},"required":["id","namn","parti","email","antalUppdrag"]},"PolitikerList":{"type":"object","properties":{"_embedded":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/PolitikerSummary"}}},"required":["items"]},"_links":{"type":"object","properties":{"self":{"type":"object","properties":{"href":{"type":"string"},"title":{"type":"string"}},"required":["href"]}},"required":["self"]},"total":{"type":"number"}},"required":["_embedded","_links","total"]},"Fel":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]},"PolitikerDetail":{"type":"object","properties":{"_embedded":{"type":"object","properties":{"item":{"type":"object","properties":{"id":{"type":"string"},"namn":{"type":"string"},"parti":{"type":"string"},"email":{"type":["string","null"]},"foto":{},"sociala":{},"uppdrag":{}},"required":["id","namn","parti","email"]},"related":{"type":"object","properties":{"möten":{"type":"array","items":{}}},"required":["möten"]}},"required":["item"]},"_links":{"type":"object","properties":{"self":{"type":"object","properties":{"href":{"type":"string"},"title":{"type":"string"}},"required":["href"]}},"required":["self"]}},"required":["_embedded","_links"]},"Arvode":{"type":"object","properties":{"_embedded":{"type":"object","properties":{"item":{"type":"object","properties":{"politiker":{"type":"object","properties":{"id":{"type":"string"},"namn":{"type":"string"},"parti":{"type":"string"}},"required":["id","namn","parti"]},"grundarvode_kr":{"type":"number"},"fast_arvode_kr":{"type":"number"},"förrättningsarvode_kr":{"type":"number"},"antal_möten_deltog":{"type":"number"},"total_ersättning_kr":{"type":"number"},"källa":{"type":"string"}},"required":["politiker","grundarvode_kr","fast_arvode_kr","förrättningsarvode_kr","antal_möten_deltog","total_ersättning_kr","källa"]}},"required":["item"]},"_links":{"type":"object","properties":{"self":{"type":"object","properties":{"href":{"type":"string"},"title":{"type":"string"}},"required":["href"]}},"required":["self"]}},"required":["_embedded","_links"]},"PolitikerProfil":{"type":"object","properties":{"_embedded":{"type":"object","properties":{"item":{"type":"object","properties":{"politiker":{"type":"object","properties":{"id":{"type":"string"},"namn":{"type":"string"},"parti":{"type":"string"}},"required":["id","namn","parti"]},"axes":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"label":{"type":"string"},"percentile":{"type":["number","null"]},"rawLabel":{"type":"string"},"populationSize":{"type":"number"}},"required":["key","label","percentile","rawLabel","populationSize"]}}},"required":["politiker","axes"]}},"required":["item"]},"_links":{"type":"object","properties":{"self":{"type":"object","properties":{"href":{"type":"string"},"title":{"type":"string"}},"required":["href"]}},"required":["self"]}},"required":["_embedded","_links"]},"Kandidat":{"type":"object","properties":{"id":{"type":"string"},"namn":{"type":"string"},"parti":{"type":"string"},"partiNamn":{"type":["string","null"]},"listplats":{"type":["number","null"]},"ålder":{"type":["number","null"]},"kön":{"type":["string","null"]},"fastställd":{"type":"boolean"},"politikerId":{"type":["string","null"]}},"required":["id","namn","parti","partiNamn","listplats","ålder","kön","fastställd","politikerId"]},"KandidatList":{"type":"object","properties":{"_embedded":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/Kandidat"}}},"required":["items"]},"_links":{"type":"object","properties":{"self":{"type":"object","properties":{"href":{"type":"string"},"title":{"type":"string"}},"required":["href"]}},"required":["self"]},"total":{"type":"number"}},"required":["_embedded","_links","total"]},"Mote":{"type":"object","properties":{"_embedded":{"type":"object","properties":{"item":{"type":"object","properties":{"datum":{},"label":{},"antalBeslut":{"type":"number"},"videoUrl":{}},"required":["antalBeslut"]},"related":{"type":"object","properties":{"beslut":{"type":"array","items":{}},"närvarande":{"type":"array","items":{}},"anföranden":{"type":"array","items":{}}},"required":["beslut","närvarande","anföranden"]}},"required":["item"]},"_links":{"type":"object","properties":{"self":{"type":"object","properties":{"href":{"type":"string"},"title":{"type":"string"}},"required":["href"]}},"required":["self"]}},"required":["_embedded","_links"]},"MoteAnforanden":{"type":"object","properties":{"_embedded":{"type":"object","properties":{"items":{"type":"array","items":{}}},"required":["items"]},"_links":{"type":"object","properties":{"self":{"type":"object","properties":{"href":{"type":"string"},"title":{"type":"string"}},"required":["href"]}},"required":["self"]},"total":{"type":"number"}},"required":["_embedded","_links","total"]},"Anföranden":{"type":"object","properties":{"_embedded":{"type":"object","properties":{"items":{"type":"array","items":{"type":"object","properties":{"id":{},"talare":{"type":"string"},"parti":{"type":"string"},"politikerId":{"type":["string","null"]},"text":{}},"required":["talare","parti","politikerId"]}}},"required":["items"]},"_links":{"type":"object","properties":{"self":{"type":"object","properties":{"href":{"type":"string"},"title":{"type":"string"}},"required":["href"]}},"required":["self"]},"total":{"type":"number"}},"required":["_embedded","_links","total"]},"BudgetUtfall":{"type":"object","properties":{"_embedded":{"type":"object","properties":{"items":{"type":"array","items":{}}},"required":["items"]},"_links":{"type":"object","properties":{"self":{"type":"object","properties":{"href":{"type":"string"},"title":{"type":"string"}},"required":["href"]}},"required":["self"]},"total":{"type":"number"}},"required":["_embedded","_links","total"]},"GraphNode":{"type":"object","properties":{"id":{"type":"string"},"typ":{"type":"string"},"label":{"type":"string"},"data":{}},"required":["id","typ","label"]},"GraphEdge":{"type":"object","properties":{"id":{"type":"string"},"from_id":{"type":"string"},"to_id":{"type":"string"},"typ":{"type":"string"},"label":{"type":["string","null"]},"data":{}},"required":["from_id","to_id","typ"]},"Sökresultat":{"type":"object","properties":{"query":{"type":"string"},"total":{"type":"number","description":"Exakt antal träffar för frågan och filtren (count(*) över hela träffmängden, inte bara sidan). Paginera med limit/offset — hela listan är sorterad innan sidan skärs ut."},"resultat":{"type":"array","items":{"type":"object","properties":{"typ":{"type":"string","enum":["beslut","politiker","dokument","forvaltning","anforande"]},"organ":{"type":["string","null"],"enum":["kf","ks","namnd"],"description":"Beslutande organ. null för träfftyper som inte tillhör ett organ (`politiker`, `dokument`)."},"id":{"type":"string"},"titel":{"type":"string"},"datum":{"type":["string","null"]},"parti":{"type":["string","null"],"description":"Parti för politiker- och anförandeträffar. För beslutsträffar ekar fältet det tillämpade `parti`-filtret (partiet vars ledamöter röstat/yrkat/talat i ärendet) — null när inget filter angetts."},"utdrag":{"type":"string"},"score":{"type":"number","description":"Relevans 0–1, relativ inom svaret (normaliserad mot svarets högsta ts_rank) — jämför inte score mellan två olika sökningar."},"url":{"type":["string","null"],"description":"Frontend-sida för träffen. null för `dokument`, som inte har någon publicerad sida — följ `_links.self` i stället."},"via":{"type":"object","properties":{"id":{"type":"string"},"typ":{"type":"string","enum":["revision"]},"relation":{"type":"string","enum":["hänvisar_till","behandlad_i"]},"label":{"type":["string","null"]}},"required":["id","typ","relation","label"],"description":"Satt när träffen kom med via grafexpansion i stället för en textträff: `id` är noden som matchade och `relation` kanten dit."},"_links":{"type":"object","properties":{"self":{"type":"object","properties":{"href":{"type":"string"}},"required":["href"]}},"required":["self"]}},"required":["typ","organ","id","titel","datum","parti","utdrag","score","url","_links"]}},"_links":{"type":"object","properties":{"self":{"type":"object","properties":{"href":{"type":"string"}},"required":["href"]},"next":{"type":"object","properties":{"href":{"type":"string"}},"required":["href"]},"prev":{"type":"object","properties":{"href":{"type":"string"}},"required":["href"]}},"required":["self"],"description":"next/prev finns bara när det finns fler sidor."}},"required":["query","total","resultat","_links"]},"Stats":{"type":"object","properties":{"kommun":{"type":"string"},"politiker":{"type":"number"},"partier":{},"graf":{"type":"object","properties":{"nodes":{"type":"number"},"edges":{"type":"number"}},"required":["nodes","edges"]}},"required":["kommun","politiker","graf"]},"Metrics":{"type":"object","properties":{"kommun":{"type":"string"},"period":{"type":"string"},"beslutskraft":{"type":"object","properties":{"totalt":{"type":"number"},"bifall":{"type":"number"},"bordläggning":{"type":"number"},"beslutskraftProcent":{"type":"number"},"bordläggningsorsaker":{}},"required":["totalt","bifall","bordläggning","beslutskraftProcent"]},"konsensus":{"type":"object","properties":{"totaltÄrenden":{"type":"number"},"utanVotering":{"type":"number"},"medVotering":{"type":"number"},"konsensusgradProcent":{"type":"number"}},"required":["totaltÄrenden","utanVotering","medVotering","konsensusgradProcent"]},"aktivitet":{"type":"object","properties":{"jävsanmälningar":{"type":"number"},"reservationer":{"type":"number"},"yrkanden":{"type":"number"}},"required":["jävsanmälningar","reservationer","yrkanden"]},"riceIndex":{},"röstÖverensstämmelse":{"type":"object","properties":{"partier":{"type":"array","items":{}},"matris":{"type":"array","items":{"type":"array","items":{"type":["number","null"]}}}},"required":["partier","matris"]},"närvaro":{"type":"object","properties":{"registreringar":{"type":"number"},"möten":{"type":"number"},"snittPerMöte":{"type":"number"}},"required":["registreringar","möten","snittPerMöte"]},"debatt":{"type":"object","properties":{"giniKoefficient":{"type":"number"},"anföranden":{"type":"number"},"djupPerÄrende":{"type":"number"},"perÅr":{"type":"array","items":{}}},"required":["giniKoefficient","anföranden","djupPerÄrende","perÅr"]},"partilojalitet":{}},"required":["kommun","period","beslutskraft","konsensus","aktivitet","röstÖverensstämmelse","närvaro","debatt"]},"Direktörer":{"type":"object","properties":{"kommun":{"type":"string"},"datum":{"type":"string"},"antal":{"type":"number"},"direktörer":{"type":"array","items":{}}},"required":["antal","direktörer"]},"DirektörResultat":{"type":"object","properties":{"direktör":{},"nämnd":{},"utfall":{"type":"array","items":{}},"revision":{"type":"array","items":{}}},"required":["utfall","revision"]},"Förvaltningar":{"type":"object","properties":{"_embedded":{"type":"object","properties":{"items":{"type":"array","items":{"type":"object","properties":{"id":{},"nämndId":{},"direktör":{},"nämnd":{},"utfall":{},"revision":{}}}}},"required":["items"]},"_links":{"type":"object","properties":{"self":{"type":"object","properties":{"href":{"type":"string"},"title":{"type":"string"}},"required":["href"]}},"required":["self"]},"total":{"type":"number"}},"required":["_embedded","_links","total"]},"FörvaltningDetail":{"type":"object","properties":{"_embedded":{"type":"object","properties":{"item":{"type":"object","properties":{"direktör":{},"nämnd":{},"budget":{}}},"related":{"type":"object","properties":{"utfall":{"type":"array","items":{}},"revision":{"type":"array","items":{}},"revisionsrapporter":{"type":"array","items":{}},"leverantörsutfall":{"type":"array","items":{}},"avtal":{"type":"array","items":{}},"ledamöter":{"type":"array","items":{}}},"required":["utfall","revision","revisionsrapporter","leverantörsutfall","avtal","ledamöter"]}},"required":["item"]},"_links":{"type":"object","properties":{"self":{"type":"object","properties":{"href":{"type":"string"},"title":{"type":"string"}},"required":["href"]}},"required":["self"]}},"required":["_embedded","_links"]},"Trender":{"type":"object","properties":{"kpis":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"namn":{"type":"string"},"kategori":{"type":"string"},"enhet":{"type":"string"},"nämndId":{"type":"string"},"nämndNamn":{"type":"string"},"göteborg":{"type":"array","items":{"type":"object","properties":{"år":{"type":"number"},"värde":{"type":["number","null"]}},"required":["år","värde"]}},"utfallÄndring":{"type":["object","null"],"properties":{"från":{"type":"number"},"till":{"type":"number"},"procent":{"type":"number"}},"required":["från","till","procent"]},"budget":{"type":"array","items":{"type":"object","properties":{"år":{"type":"number"},"värde":{"type":["number","null"]}},"required":["år","värde"]}},"budgetÄndring":{"type":["object","null"],"properties":{"från":{"type":"number"},"till":{"type":"number"},"procent":{"type":"number"}},"required":["från","till","procent"]}},"required":["id","namn","kategori","enhet","göteborg","utfallÄndring"]}}},"required":["kpis"]}},"parameters":{}},"paths":{"/v1/{kommun}/politiker":{"get":{"operationId":"listPolitiker","tags":["Politiker"],"summary":"Lista alla politiker","parameters":[{"schema":{"type":"string"},"required":true,"name":"kommun","in":"path"},{"schema":{"type":"string"},"required":false,"name":"parti","in":"query"},{"schema":{"type":"string","pattern":"^[1-9]\\d*$","description":"Max antal politiker, default 50, max 2000"},"required":false,"name":"limit","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PolitikerList"}}}},"400":{"description":"Ogiltig parameter","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Fel"}}}},"404":{"description":"Okänd kommun (eller resurs som inte finns)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Fel"}}}},"429":{"description":"Rate limit överskriden (200 anrop/minut per IP)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Fel"}}}}}}},"/v1/{kommun}/politiker/{id}":{"get":{"operationId":"getPolitiker","tags":["Politiker"],"summary":"Enskild politiker med alla uppdrag","parameters":[{"schema":{"type":"string"},"required":true,"name":"kommun","in":"path"},{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PolitikerDetail"}}}},"400":{"description":"Ogiltig parameter","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Fel"}}}},"404":{"description":"Ej hittad","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"429":{"description":"Rate limit överskriden (200 anrop/minut per IP)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Fel"}}}}}}},"/v1/{kommun}/politiker/{id}/arvode":{"get":{"operationId":"getPolitikerArvode","tags":["Politiker"],"summary":"Ersättning för förtroendevald — fast arvode + förrättningsarvode","description":"Beräknar total ersättning baserat på:\n- Fast arvode: procent av grundarvodet (80 475 kr/mån 2026) beroende på ordförandeuppdrag\n- Förrättningsarvode: 1 640 kr per KF-sammanträde (heldag) baserat på registrerad närvaro\n- Källa: Göteborgs Stads regler för arvoden (KS 2025-12-10 §946, Bilaga 2)","parameters":[{"schema":{"type":"string"},"required":true,"name":"kommun","in":"path"},{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Arvode"}}}},"400":{"description":"Ogiltig parameter","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Fel"}}}},"404":{"description":"Ej hittad","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"429":{"description":"Rate limit överskriden (200 anrop/minut per IP)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Fel"}}}}}}},"/v1/{kommun}/politiker/{id}/profil":{"get":{"operationId":"getPolitikerProfil","tags":["Politiker"],"summary":"Percentil-normerad profil (närvaro, debattaktivitet, initiativ, partilojalitet) för radardiagram","description":"Varje axel är en percentil (0–100) bland politiker med tillräckligt underlag:\n- Närvaro: andel av samtliga sammanträden (alla organ) med registrerad närvaro\n- Debattaktivitet: anföranden per sammanträde med närvaro (kräver ≥3 sammanträden)\n- Initiativ: antal inlämnade motioner + yrkanden (rått antal — gynnar längre mandattid)\n- Partilojalitet: andel egna ja/nej-röster som matchar partiets majoritet per paragraf (kräver ≥5 röster)","parameters":[{"schema":{"type":"string"},"required":true,"name":"kommun","in":"path"},{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PolitikerProfil"}}}},"400":{"description":"Ogiltig parameter","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Fel"}}}},"404":{"description":"Ej hittad","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"429":{"description":"Rate limit överskriden (200 anrop/minut per IP)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Fel"}}}}}}},"/v1/{kommun}/kandidater":{"get":{"operationId":"listKandidater","tags":["Kandidater"],"summary":"Kandidater till kommunfullmäktige, val 2026","description":"Rådata från Valmyndigheten (data.val.se), kommunfullmäktige-listor. Kandidater som redan sitter i KF är länkade till sin politiker-profil via politikerId.","parameters":[{"schema":{"type":"string"},"required":true,"name":"kommun","in":"path"},{"schema":{"type":"string"},"required":false,"name":"parti","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/KandidatList"}}}},"400":{"description":"Ogiltig parameter","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Fel"}}}},"404":{"description":"Okänd kommun (eller resurs som inte finns)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Fel"}}}},"429":{"description":"Rate limit överskriden (200 anrop/minut per IP)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Fel"}}}}}}},"/v1/{kommun}/möten":{"get":{"operationId":"listMoten","tags":["Möten"],"summary":"Lista alla sammanträden","parameters":[{"schema":{"type":"string"},"required":true,"name":"kommun","in":"path"},{"schema":{"type":"string"},"required":false,"name":"år","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"_embedded":{"type":"object","properties":{"items":{"type":"array","items":{"type":"object","properties":{"datum":{},"label":{},"antalBeslut":{"type":"number"},"närvarande":{"type":"number"},"videoUrl":{}},"required":["antalBeslut","närvarande"]}}},"required":["items"]},"_links":{"type":"object","properties":{"self":{"type":"object","properties":{"href":{"type":"string"},"title":{"type":"string"}},"required":["href"]}},"required":["self"]},"total":{"type":"number"}},"required":["_embedded","_links","total"]}}}},"400":{"description":"Ogiltig parameter","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Fel"}}}},"404":{"description":"Okänd kommun (eller resurs som inte finns)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Fel"}}}},"429":{"description":"Rate limit överskriden (200 anrop/minut per IP)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Fel"}}}}}}},"/v1/{kommun}/möten/{datum}":{"get":{"operationId":"getMote","tags":["Möten"],"summary":"Enskilt sammanträde — beslut, närvaro och anföranden","parameters":[{"schema":{"type":"string"},"required":true,"name":"kommun","in":"path"},{"schema":{"type":"string"},"required":true,"name":"datum","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Mote"}}}},"400":{"description":"Ogiltig parameter","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Fel"}}}},"404":{"description":"Ej hittad","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"429":{"description":"Rate limit överskriden (200 anrop/minut per IP)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Fel"}}}}}}},"/v1/{kommun}/möten/{datum}/anföranden":{"get":{"operationId":"listAnforandenForMote","tags":["Möten"],"summary":"Alla anföranden från ett sammanträde (?talare=, ?ärende=, ?q=)","parameters":[{"schema":{"type":"string"},"required":true,"name":"kommun","in":"path"},{"schema":{"type":"string"},"required":true,"name":"datum","in":"path"},{"schema":{"type":"string"},"required":false,"name":"talare","in":"query"},{"schema":{"type":"string"},"required":false,"name":"ärende","in":"query"},{"schema":{"type":"string"},"required":false,"name":"q","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MoteAnforanden"}}}},"400":{"description":"Ogiltig parameter","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Fel"}}}},"404":{"description":"Ej hittad","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"429":{"description":"Rate limit överskriden (200 anrop/minut per IP)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Fel"}}}}}}},"/v1/{kommun}/beslut":{"get":{"operationId":"listBeslut","tags":["Beslut"],"summary":"Lista/sök beslut","parameters":[{"schema":{"type":"string"},"required":true,"name":"kommun","in":"path"},{"schema":{"type":"string"},"required":false,"name":"datum","in":"query"},{"schema":{"type":"string"},"required":false,"name":"år","in":"query"},{"schema":{"type":"string"},"required":false,"name":"sök","in":"query"},{"schema":{"type":"string","enum":["kf","ks","all"]},"required":false,"name":"organ","in":"query"},{"schema":{"type":"string","pattern":"^[1-9]\\d*$","description":"Max antal beslut, default 50, max 2000"},"required":false,"name":"limit","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"_embedded":{"type":"object","properties":{"items":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"organ":{"type":"string"},"paragraf":{"type":["string","null"]},"rubrik":{"type":"string"},"datum":{},"beslut":{},"votering":{},"namnupprop":{"type":"boolean"},"ärendeNr":{}},"required":["id","organ","paragraf","rubrik","namnupprop"]}}},"required":["items"]},"_links":{"type":"object","properties":{"self":{"type":"object","properties":{"href":{"type":"string"},"title":{"type":"string"}},"required":["href"]}},"required":["self"]},"total":{"type":"number"}},"required":["_embedded","_links","total"]}}}},"400":{"description":"Ogiltig parameter","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Fel"}}}},"404":{"description":"Okänd kommun (eller resurs som inte finns)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Fel"}}}},"429":{"description":"Rate limit överskriden (200 anrop/minut per IP)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Fel"}}}}}}},"/v1/{kommun}/beslut/{id}":{"get":{"operationId":"getBeslut","tags":["Beslut"],"summary":"Enskilt beslut med kopplingar","parameters":[{"schema":{"type":"string"},"required":true,"name":"kommun","in":"path"},{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"_embedded":{"type":"object","properties":{"item":{},"related":{"type":"object","properties":{"kopplingar":{"type":"array","items":{"type":"object","properties":{"typ":{"type":"string"},"riktning":{"type":"string"},"nod":{"type":["object","null"],"properties":{"id":{},"typ":{},"label":{}}}},"required":["typ","riktning","nod"]}}},"required":["kopplingar"]}}},"_links":{"type":"object","properties":{"self":{"type":"object","properties":{"href":{"type":"string"},"title":{"type":"string"}},"required":["href"]}},"required":["self"]}},"required":["_embedded","_links"]}}}},"400":{"description":"Ogiltig parameter","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Fel"}}}},"404":{"description":"Ej hittad","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"429":{"description":"Rate limit överskriden (200 anrop/minut per IP)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Fel"}}}}}}},"/v1/{kommun}/beslut/{id}/anforanden":{"get":{"operationId":"listAnforandenForBeslut","tags":["Beslut"],"summary":"Anföranden (debattinlägg) kopplade till ett beslut","parameters":[{"schema":{"type":"string"},"required":true,"name":"kommun","in":"path"},{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Anföranden"}}}},"400":{"description":"Ogiltig parameter","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Fel"}}}},"404":{"description":"Okänd kommun (eller resurs som inte finns)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Fel"}}}},"429":{"description":"Rate limit överskriden (200 anrop/minut per IP)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Fel"}}}}}}},"/v1/{kommun}/budget":{"get":{"operationId":"getBudget","tags":["Budget"],"summary":"Kommunbudget per nämnd (filtrera på år med ?år=2024)","parameters":[{"schema":{"type":"string"},"required":true,"name":"kommun","in":"path"},{"schema":{"type":"string"},"required":false,"name":"år","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"anyOf":[{"type":"object","properties":{"_embedded":{"type":"object","properties":{"item":{"type":"object","properties":{"år":{"type":"number"},"totalMnkr":{},"styre":{},"beslut":{}},"required":["år"]},"related":{"type":"object","properties":{"nämnder":{"type":"array","items":{}}},"required":["nämnder"]}},"required":["item"]},"_links":{"type":"object","properties":{"self":{"type":"object","properties":{"href":{"type":"string"},"title":{"type":"string"}},"required":["href"]}},"required":["self"]}},"required":["_embedded","_links"]},{"type":"object","properties":{"_embedded":{"type":"object","properties":{"items":{"type":"array","items":{"type":"object","properties":{"år":{},"totalMnkr":{},"styre":{}}}}},"required":["items"]},"_links":{"type":"object","properties":{"self":{"type":"object","properties":{"href":{"type":"string"},"title":{"type":"string"}},"required":["href"]}},"required":["self"]},"total":{"type":"number"}},"required":["_embedded","_links","total"]}]}}}},"400":{"description":"Ogiltig parameter","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Fel"}}}},"404":{"description":"Okänd kommun (eller resurs som inte finns)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Fel"}}}},"429":{"description":"Rate limit överskriden (200 anrop/minut per IP)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Fel"}}}}}}},"/v1/{kommun}/budget/utfall":{"get":{"operationId":"getBudgetUtfall","tags":["Budget"],"summary":"Ekonomiskt utfall per nämnd för ett år (?år=2025) — kommunbidrag, kostnader, resultat, status","parameters":[{"schema":{"type":"string"},"required":true,"name":"kommun","in":"path"},{"schema":{"type":"string"},"required":true,"name":"år","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BudgetUtfall"}}}},"400":{"description":"Ogiltig parameter","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Fel"}}}},"404":{"description":"Okänd kommun (eller resurs som inte finns)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Fel"}}}},"429":{"description":"Rate limit överskriden (200 anrop/minut per IP)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Fel"}}}}}}},"/v1/{kommun}/graf":{"get":{"operationId":"getGraf","tags":["Knowledge Graph"],"summary":"Graf översikt eller filtrering","parameters":[{"schema":{"type":"string"},"required":true,"name":"kommun","in":"path"},{"schema":{"type":"string"},"required":false,"name":"datum","in":"query"},{"schema":{"type":"string"},"required":false,"name":"typ","in":"query"},{"schema":{"type":"string","pattern":"^[1-9]\\d*$","description":"Max antal noder, default 500, max 5000"},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string","pattern":"^\\d+$","description":"Paginering, default 0"},"required":false,"name":"offset","in":"query"},{"schema":{"type":"string","enum":["true","false"],"description":"true tar med paragrafernas fulltext (stora svar — 3 900 paragrafer är ~113 MB). Default false, då `data.fulltextTecken` visar hur lång texten är."},"required":false,"name":"fulltext","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"nodes":{},"edges":{},"antal":{"type":"number"},"total":{"type":"number"}}}}}},"400":{"description":"Ogiltig parameter","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Fel"}}}},"404":{"description":"Okänd kommun (eller resurs som inte finns)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Fel"}}}},"429":{"description":"Rate limit överskriden (200 anrop/minut per IP)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Fel"}}}}}}},"/v1/{kommun}/graf/node/{id}":{"get":{"operationId":"getGrafNode","tags":["Knowledge Graph"],"summary":"Traversera graf — enskild nod med alla kopplingar","parameters":[{"schema":{"type":"string"},"required":true,"name":"kommun","in":"path"},{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"node":{"$ref":"#/components/schemas/GraphNode"},"edges":{"type":"array","items":{"$ref":"#/components/schemas/GraphEdge"}},"related":{"type":"array","items":{"$ref":"#/components/schemas/GraphNode"}}},"required":["node","edges","related"]}}}},"400":{"description":"Ogiltig parameter","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Fel"}}}},"404":{"description":"Ej hittad","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"429":{"description":"Rate limit överskriden (200 anrop/minut per IP)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Fel"}}}}}}},"/v1/{kommun}/sök":{"get":{"operationId":"search","tags":["Sök"],"summary":"Fritextsökning över beslut, politiker, dokument, förvaltningar och anförandemetadata","description":"Fulltextsökning (PostgreSQL `swedish`-konfiguration) över hela korpusen i ett anrop.\n\n**Träfftyper** (`typ`) och vad som är indexerat per typ:\n\n| typ | indexerad text | `url` |\n|---|---|---|\n| `beslut` | rubrik + protokollets fulltext (KF/KS-paragrafer) | beslutssidan |\n| `politiker` | namn, parti, uppdrag | politikersidan |\n| `dokument` | titel + fulltext (allmänna handlingar) | null — sida saknas |\n| `forvaltning` | förvaltning, nämnd, revisionsanmärkningar, revisionsrapporter | förvaltningssidan |\n| `anforande` | talare, ärenderubrik och talets ordagranna text (yttrandeprotokollen) | mötessidan |\n\nFör anföranden är `utdrag` ett citat ur själva inlägget. Hela inlägget och\ndess talarkoppling hämtas via `/v1/{kommun}/möten/{datum}/anföranden` (som\nockså har `?q=` och `?talare=` inom ett möte).\n\n**Filtret `organ`** gäller alla träfftyper, inte bara beslut:\n\n| organ | ger |\n|---|---|\n| `kf` | `beslut` (kf-paragrafer) + `anforande` |\n| `ks` | `beslut` (ks-paragrafer) |\n| `namnd` | `forvaltning` + `dokument` |\n| `all` (default) | allt, inklusive `politiker` |\n\nEn politiker tillhör inget organ och faller därför bort så snart `organ`\nefterfrågas explicit. Samma sak gäller `parti`: bara `beslut`, `politiker`\noch `anforande` har partikoppling, och datumfilter (`från`/`till`) utesluter\nde datumlösa typerna `politiker` och `forvaltning`. Kombinationer som\nutesluter varandra ger `200` med `total: 0`, inte fel.\n\n**Nämndnivå:** nämndbeslut finns inte som egna `beslut`-objekt (bara KF/KS\nprotokollförs som paragrafer). De träffas i stället som `forvaltning` via\nrevisionsanmärkningarnas fritext — t.ex. inköps- och upphandlingsnämndens\nbojkottbeslut 2024-06-13.\n\n**Grafexpansion:** när en revisionsanmärkning matchar följs dess\n`hänvisar_till`/`behandlad_i`-kanter till berörda KF-beslut, som läggs till\nmed `via` ifyllt. Det gör att t.ex. revisionsberättelsen som beviljade\nansvarsfrihet hittas även om själva sökordet inte står i dess text.\n\n**Ordlogik:** orden ORas (delträff ger träff); träffar som innehåller *alla*\nord exakt rankas högre. `score` är relativ inom svaret (0–1), inte ett\nabsolut mått.\n\n**Prefixmatchning (sammansatta ord):** stemmern (`swedish`) delar inte\nsammansättningar, så ord vars stam är minst 5 tecken matchas även som prefix.\n`bojkott` hittar därför \"bojkottbeslutet\", `upphandling` hittar\n\"upphandlingsnämnden\", och en påbörjad sökning (`upphandlingsn`) fungerar.\nKortare stammar prefixas inte — \"varor\" → `'var'` hade matchat\nvara/varit/varje och dränkt resultatet. Ord som ger flera lexem (datum som\n`2024-06-13`) prefixas inte heller.\n\n**Kvarstående begränsning:** motsatt riktning fungerar inte — skriver man hela\nsammansättningen medan korpusen bara har delarna ger det noll träffar\n(`jävsanmälan` → 0, medan `jäv` ger 100). Det kräver ordledsdelning, som\nligger utanför v1.\n\n**Paginering och `total`:** `total` är exakt — hela träffmängden rankas i\ndatabasen och räknas med `count(*)`, varefter sidan skärs ut med\n`limit`/`offset`. Pagineringen är därför stabil hela vägen genom resultatet\n(inget dolt fönster), och `_links.next`/`prev` finns så länge det finns\nfler sidor.\n\n**Svarsformat:** till skillnad från API:ets övriga listor använder `/sök` inte\nHAL-konventet (`_embedded.items`) utan en platt `resultat`-array — träffarna\när blandade resurstyper, inte en samling av en typ, och varje träff bär sin\negen `_links.self` till rätt API-resurs.\n\n**Tomt resultat** ger `200` med `total: 0` och `resultat: []` — aldrig 404.","parameters":[{"schema":{"type":"string"},"required":true,"name":"kommun","in":"path"},{"schema":{"type":"string","minLength":2,"maxLength":200,"description":"Fritextfråga, 2–200 tecken. Högst 12 ord används; överskjutande ord ignoreras.","example":"Israel bojkott"},"required":true,"name":"q","in":"query"},{"schema":{"type":"string","enum":["beslut","politiker","dokument","forvaltning","anforande"],"description":"Begränsa till en träfftyp"},"required":false,"name":"typ","in":"query"},{"schema":{"type":"string","enum":["kf","ks","namnd","all"],"description":"Beslutande organ, default `all`. `kf` → beslut + anföranden, `ks` → beslut, `namnd` → förvaltningar + dokument (nämndnivå). Se tabellen i endpointbeskrivningen."},"required":false,"name":"organ","in":"query"},{"schema":{"type":"string","description":"Partibeteckning, t.ex. `C`. Begränsar till träffar med partikoppling: politiker i partiet, beslut där partiets ledamöter röstat/yrkat/talat, samt partiets anföranden. Dokument- och förvaltningsträffar saknar partikoppling och faller bort."},"required":false,"name":"parti","in":"query"},{"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Datum från (ISO 8601, YYYY-MM-DD)","example":"2024-01-01"},"required":false,"name":"från","in":"query"},{"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Alias för `från` (ASCII, slipper procent-kodning)"},"required":false,"name":"fran","in":"query"},{"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$","description":"Datum till (ISO 8601, YYYY-MM-DD)","example":"2024-12-31"},"required":false,"name":"till","in":"query"},{"schema":{"type":"string","pattern":"^[1-9]\\d*$","description":"Antal träffar per sida, default 20, max 100 (större värden kapas)"},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string","pattern":"^\\d+$","description":"Paginering, default 0"},"required":false,"name":"offset","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Sökresultat"}}}},"400":{"description":"Ogiltig parameter","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"404":{"description":"Okänd kommun (eller resurs som inte finns)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Fel"}}}},"429":{"description":"Rate limit överskriden (200 anrop/minut per IP)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Fel"}}}}}}},"/v1/{kommun}/stats":{"get":{"operationId":"getStats","tags":["Statistik"],"summary":"Övergripande statistik","parameters":[{"schema":{"type":"string"},"required":true,"name":"kommun","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Stats"}}}},"400":{"description":"Ogiltig parameter","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Fel"}}}},"404":{"description":"Okänd kommun (eller resurs som inte finns)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Fel"}}}},"429":{"description":"Rate limit överskriden (200 anrop/minut per IP)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Fel"}}}}}}},"/v1/{kommun}/metrics":{"get":{"operationId":"getMetrics","tags":["Statistik"],"summary":"Demokratiska nyckeltal","description":"Automatiskt beräknade KPI:er för kommunfullmäktige: beslutskraft, konsensus, partilojalitet, aktivitet.","parameters":[{"schema":{"type":"string"},"required":true,"name":"kommun","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Metrics"}}}},"400":{"description":"Ogiltig parameter","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Fel"}}}},"404":{"description":"Okänd kommun (eller resurs som inte finns)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Fel"}}}},"429":{"description":"Rate limit överskriden (200 anrop/minut per IP)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Fel"}}}}}}},"/v1/{kommun}/dokument":{"get":{"operationId":"listDokument","tags":["Dokument"],"summary":"Lista alla dokument med metadata","parameters":[{"schema":{"type":"string"},"required":true,"name":"kommun","in":"path"},{"schema":{"type":"string"},"required":false,"name":"typ","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"antal":{"type":"number"},"dokument":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"titel":{"type":"string"},"typ":{"type":"string"},"nämnd":{"type":"string"},"datum":{"type":"string"},"källa":{"type":"string"},"graf_nod":{"type":["string","null"]},"chars":{"type":"number"}},"required":["id","titel","typ","nämnd","datum","källa","graf_nod","chars"]}}},"required":["antal","dokument"]}}}},"400":{"description":"Ogiltig parameter","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Fel"}}}},"404":{"description":"Okänd kommun (eller resurs som inte finns)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Fel"}}}},"429":{"description":"Rate limit överskriden (200 anrop/minut per IP)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Fel"}}}}}}},"/v1/{kommun}/dokument/sök":{"get":{"operationId":"searchDokument","tags":["Dokument"],"summary":"Sök i dokumentinnehåll (fulltext) — DEPRECERAD, använd /sök?typ=dokument","deprecated":true,"description":"**Deprecerad.** `/v1/{kommun}/sök?typ=dokument` gör samma sak och\nmer: typade träffar, filter på organ/datum, paginering, `_links` och utdrag\nutan HTML. Den här routen fanns före den generella sökningen och är nu en\ndelmängd av den.\n\nSvaret bär `Deprecation`- och `Link`-headers enligt RFC 8594. Routen tas\nbort tidigast 2027-01-01 (`Sunset`).","parameters":[{"schema":{"type":"string"},"required":true,"name":"kommun","in":"path"},{"schema":{"type":"string","minLength":2},"required":true,"name":"q","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"query":{"type":"string"},"resultat":{"type":"array","items":{"type":"object","properties":{"id":{},"titel":{},"typ":{},"datum":{},"utdrag":{}}}}},"required":["query","resultat"]}}}},"400":{"description":"Ogiltig parameter","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Fel"}}}},"404":{"description":"Okänd kommun (eller resurs som inte finns)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Fel"}}}},"429":{"description":"Rate limit överskriden (200 anrop/minut per IP)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Fel"}}}}}}},"/v1/{kommun}/dokument/{id}":{"get":{"operationId":"getDokument","tags":["Dokument"],"summary":"Hämta dokument med full text","parameters":[{"schema":{"type":"string"},"required":true,"name":"kommun","in":"path"},{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"titel":{"type":"string"},"typ":{"type":"string"},"nämnd":{"type":"string"},"datum":{"type":"string"},"källa":{"type":"string"},"graf_nod":{"type":["string","null"]},"innehåll":{"type":"string"}},"required":["id","titel","typ","nämnd","datum","källa","graf_nod","innehåll"]}}}},"400":{"description":"Ogiltig parameter","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Fel"}}}},"404":{"description":"Ej hittad","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"429":{"description":"Rate limit överskriden (200 anrop/minut per IP)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Fel"}}}}}}},"/v1/{kommun}/lon/direktorer":{"get":{"operationId":"listDirektorer","tags":["Löner"],"summary":"Löner för förvaltningsdirektörer","parameters":[{"schema":{"type":"string"},"required":true,"name":"kommun","in":"path"},{"schema":{"type":"string","enum":["namn","lön","anställd"]},"required":false,"name":"sort","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Direktörer"}}}},"400":{"description":"Ogiltig parameter","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Fel"}}}},"404":{"description":"Okänd kommun (eller resurs som inte finns)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Fel"}}}},"429":{"description":"Rate limit överskriden (200 anrop/minut per IP)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Fel"}}}}}}},"/v1/{kommun}/lon/direktorer/{id}/resultat":{"get":{"operationId":"getDirektorResultat","tags":["Löner"],"summary":"Förvaltningsdirektörs resultat — budget, utfall, revision","description":"Sammanställer ekonomiskt utfall, revisionskritik och kopplingar för en direktör.","parameters":[{"schema":{"type":"string"},"required":true,"name":"kommun","in":"path"},{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DirektörResultat"}}}},"400":{"description":"Ogiltig parameter","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Fel"}}}},"404":{"description":"Ej hittad","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"429":{"description":"Rate limit överskriden (200 anrop/minut per IP)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Fel"}}}}}}},"/v1/{kommun}/forvaltningar":{"get":{"operationId":"listForvaltningar","tags":["Förvaltningar"],"summary":"Lista alla förvaltningar med direktör, budget och utfall","parameters":[{"schema":{"type":"string"},"required":true,"name":"kommun","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Förvaltningar"}}}},"400":{"description":"Ogiltig parameter","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Fel"}}}},"404":{"description":"Okänd kommun (eller resurs som inte finns)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Fel"}}}},"429":{"description":"Rate limit överskriden (200 anrop/minut per IP)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Fel"}}}}}}},"/v1/{kommun}/forvaltningar/{id}":{"get":{"operationId":"getForvaltning","tags":["Förvaltningar"],"summary":"Enskild förvaltning — direktör, nämnd, budget, utfall, revision, revisionsrapporter, leverantörsutfall, avtal, ledamöter","parameters":[{"schema":{"type":"string"},"required":true,"name":"kommun","in":"path"},{"schema":{"type":"string"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FörvaltningDetail"}}}},"400":{"description":"Ogiltig parameter","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Fel"}}}},"404":{"description":"Ej hittad","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}},"429":{"description":"Rate limit överskriden (200 anrop/minut per IP)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Fel"}}}}}}},"/v1/{kommun}/trender":{"get":{"operationId":"getTrender","tags":["Trender"],"summary":"Göteborgs trender över tid (Kolada) parat mot nämndbudget — skola, äldreomsorg, miljö m.fl.","parameters":[{"schema":{"type":"string"},"required":true,"name":"kommun","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Trender"}}}},"400":{"description":"Ogiltig parameter","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Fel"}}}},"404":{"description":"Okänd kommun (eller resurs som inte finns)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Fel"}}}},"429":{"description":"Rate limit överskriden (200 anrop/minut per IP)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Fel"}}}}}}}},"webhooks":{}}