{
  "openapi": "3.0.3",
  "info": {
    "title": "VOR Studio API",
    "version": "2.5.43 (v45.220)",
    "x-copyright": "© VOR Technologies",
    "description": "© VOR Technologies. Samma API för redaktionen (session) och agenter (Authorization: Bearer mms_…). Standardrätt för en agent: skapa utkast; publicera/schemalägga bara när administratören gett rätten för sektioner, mallar och språk. Alla fel är maskinläsbara: {ok:false, fel:[{falt, sprak, orsak, atgard}]}."
  },
  "servers": [
    {
      "url": "https://{domain}",
      "variables": {
        "domain": {
          "default": "your-domain.com",
          "description": "The address of your VOR installation"
        }
      }
    }
  ],
  "components": {
    "securitySchemes": {
      "agent": {
        "type": "http",
        "scheme": "bearer"
      },
      "session": {
        "type": "apiKey",
        "in": "cookie",
        "name": "vorsess"
      }
    },
    "schemas": {
      "Fel": {
        "type": "object",
        "properties": {
          "ok": {
            "type": "boolean",
            "example": false
          },
          "fel": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "falt": {
                  "type": "string"
                },
                "sprak": {
                  "type": "string"
                },
                "orsak": {
                  "type": "string"
                },
                "atgard": {
                  "type": "string"
                }
              }
            }
          }
        }
      },
      "Block": {
        "type": "object",
        "description": "ProseMirror-nod med stabilt attrs.id (b + 6–20 tecken). Tillåtna typer: paragraph, heading(level 2|3), bulletList, orderedList, blockquote, table, image(src, wpId, alt, caption), faktaruta(rubrik) med paragraph-innehåll (2.5.28: attrs.punkter [text …] eller attrs.text tas emot och blir stycken i content vid sparningen; en ruta utan innehåll ritas inte på sajten), relaterat(rubrik, lankar[{rubrik,url}]), inbaddning(url: YouTube/Instagram/TikTok/Spotify), produkt(namn, butik, pris, lank, bild, text), citat(text, vem), galleri(bilder[]), betyg(betyg 1–5, text), plats(namn, kategori, stadsdel, adress, karta, text), recept(rubrik, portioner, tid, grupper[{namn, rader[{mangd, vara}]}], steg[]). 2.5.29: image(layout: normal | bred | helbredd – bred = 120 % av spalten, helbredd = hela skärmbredden på dator; mobil alltid normal); avsnitt(rubrik, text – stycken åtskilda av tom rad, bild{src, wpId, alt, caption}) bara i mallen lista – sajten numrerar avsnitten själv (01, 02 … eller N … 01 efter meta.avsnittRiktning) och sätter nr/av vid sparningen; från tre avsnitt ritas en innehållsförteckning (nav.mmavs_toc) och från två en ItemList (JSON-LD) före det första; viktigast(punkter[3 korta strängar, högst 90 tecken – kontrollen varnar över 120]) = «Det viktigaste» / Key points; rattelse(datum ÅÅÅÅ-MM-DD, text) = «Rättelse …» / Correction. 2.5.30: jamforelse(rubrik, rader[{namn, bild{src, wpId, alt}, betyg 1–5 i halva steg, pris, butik, url + program eller lank – samma köplänksregler som produkt, plus[], minus[], etikett: vinnare | bastpris | budget, kommentar}]) = jämförelsetabellen i mallen basttest (Bäst i test) – ItemList med Product och betyg (JSON-LD) före blocket; stegforsteg(rubrik, behover[], tid, svarighet: latt | medel | svar, steg[{rubrik, text, bild{src, wpId, alt, caption}}], klart) = guideblocket i mallen howto (Steg för steg) – HowTo (JSON-LD) med totalTime när tiden går att tolka; evenemang(namn, start ÅÅÅÅ-MM-DDTHH:MM i Stockholmstid – krävs, slut, plats{namn, adress, stad, karta}, biljettUrl https – den enda tillåtna utlänken, biljettText, pris, arrangor, text) = evenemangsblocket i mallen evenemang – datumbricka, kartlänkar, biljettknapp, kalenderfil (VEVENT i UTC), nedräkning och Event (JSON-LD). 2.5.32: snabbfakta(rubrik – etiketten, standard «Snabbfakta», namn – vem eller vad, rader[{k, v}]) = nyckel/värde-rutan i alla mallar (kompakt tabell i faktarutans familj; en rad utan värde ritas inte; GET /studio/api/kandis?namn=… ger född/stjärntecken/känd för ur kändisdatat när personen finns där); fragasvar(rubrik, lage: snabba | intervju, fragor[{fraga, svar}]) = frågor och svar i mallen intervju («Snabba fem» som tät ruta, eller frågan i fet och svaret som löptext); tidslinje(rubrik, rader[{ar, text}]) = tidslinjen i mallen profil (lodrät linje, året i monospace); sociala(instagram, tiktok, youtube, x, facebook, webb – bara användarnamnet eller https-adressen) = knappar med ikon, ny flik, nofollow noopener; plusminus(plus[], minus[], dom) = plus- och minuslistorna med «Domen» i mallen recension; relaterat(auto: true, tagg) = «Senaste om personen»: sajten hämtar de fem senaste artiklarna med taggen ur indexet vid renderingen. Sökdata (JSON-LD) först i kroppen: intervju = Article med about: Person (när snabbfaktan har namn), profil = ProfilePage med mainEntity: Person (birthDate ur Född i ISO-form, sameAs ur de sociala kanalerna), recension = Review med itemReviewed (Titel/Produkt ur snabbfaktan eller rubriken), reviewRating ur betygsblocket (bestRating 5), author och publisher = sajten – inget betyg, inget Review. 2.5.33: liveinlagg(rubrik, inlagg[{id, tid ÅÅÅÅ-MM-DDTHH:MM i Stockholmstid, text, bild{src, wpId, alt, caption}, fast}]) = liverapporten i mallen liverapport – nyast överst, fästa först, «Direkt»/«Avslutad» ur revisionens meta.live (true|false), «Senaste inlägg HH:MM» ur datat; sajten hämtar nya inlägg ur GET /studio/live/{id}.json var 30:e sekund (publicera om för varje nytt inlägg); LiveBlogPosting (JSON-LD) före blocket; quizfragor(rubrik, typ: personlighet | kunskap, fragor[{fraga, bild, alternativ[{text, poang{A: 1} | ratt: true}]}], resultat[{nyckel, rubrik, text, bild} | {fran, till, rubrik, text}]) = quizet i mallen quiz – körs i läsarens webbläsare (datat som JSON i blocket, aldrig skript i brödtexten), minst tre frågor; galleri(lage: berattelse, bilder[{src, wpId, alt, caption, kredit}]) = bildberättelsen i mallen bildberattelse – helbreddsbilder i följd med bildtext och kredit, svepvy med räknaren «4/18» på mobilen, minst fyra bilder; ImageGallery (JSON-LD) före blocket.",
        "properties": {
          "type": {
            "type": "string"
          },
          "attrs": {
            "type": "object"
          },
          "content": {
            "type": "array",
            "items": {
              "type": "object",
              "description": "Barnnod: {type: \"text\", text, marks: [{type: bold|italic|link, attrs}]} eller ett block"
            }
          }
        }
      },
      "Sprakversion": {
        "type": "object",
        "properties": {
          "rubrik": {
            "type": "string"
          },
          "ingress": {
            "type": "string"
          },
          "block": {
            "type": "array",
            "items": {
              "type": "object",
              "description": "ProseMirror-nod med stabilt attrs.id (b + 6–20 tecken). Tillåtna typer: paragraph, heading(level 2|3), bulletList, orderedList, blockquote, table, image(src, wpId, alt, caption), faktaruta(rubrik) med paragraph-innehåll (2.5.28: attrs.punkter [text …] eller attrs.text tas emot och blir stycken i content vid sparningen; en ruta utan innehåll ritas inte på sajten), relaterat(rubrik, lankar[{rubrik,url}]), inbaddning(url: YouTube/Instagram/TikTok/Spotify), produkt(namn, butik, pris, lank, bild, text), citat(text, vem), galleri(bilder[]), betyg(betyg 1–5, text), plats(namn, kategori, stadsdel, adress, karta, text), recept(rubrik, portioner, tid, grupper[{namn, rader[{mangd, vara}]}], steg[]). 2.5.29: image(layout: normal | bred | helbredd – bred = 120 % av spalten, helbredd = hela skärmbredden på dator; mobil alltid normal); avsnitt(rubrik, text – stycken åtskilda av tom rad, bild{src, wpId, alt, caption}) bara i mallen lista – sajten numrerar avsnitten själv (01, 02 … eller N … 01 efter meta.avsnittRiktning) och sätter nr/av vid sparningen; från tre avsnitt ritas en innehållsförteckning (nav.mmavs_toc) och från två en ItemList (JSON-LD) före det första; viktigast(punkter[3 korta strängar, högst 90 tecken – kontrollen varnar över 120]) = «Det viktigaste» / Key points; rattelse(datum ÅÅÅÅ-MM-DD, text) = «Rättelse …» / Correction. 2.5.30: jamforelse(rubrik, rader[{namn, bild{src, wpId, alt}, betyg 1–5 i halva steg, pris, butik, url + program eller lank – samma köplänksregler som produkt, plus[], minus[], etikett: vinnare | bastpris | budget, kommentar}]) = jämförelsetabellen i mallen basttest (Bäst i test) – ItemList med Product och betyg (JSON-LD) före blocket; stegforsteg(rubrik, behover[], tid, svarighet: latt | medel | svar, steg[{rubrik, text, bild{src, wpId, alt, caption}}], klart) = guideblocket i mallen howto (Steg för steg) – HowTo (JSON-LD) med totalTime när tiden går att tolka; evenemang(namn, start ÅÅÅÅ-MM-DDTHH:MM i Stockholmstid – krävs, slut, plats{namn, adress, stad, karta}, biljettUrl https – den enda tillåtna utlänken, biljettText, pris, arrangor, text) = evenemangsblocket i mallen evenemang – datumbricka, kartlänkar, biljettknapp, kalenderfil (VEVENT i UTC), nedräkning och Event (JSON-LD). 2.5.32: snabbfakta(rubrik – etiketten, standard «Snabbfakta», namn – vem eller vad, rader[{k, v}]) = nyckel/värde-rutan i alla mallar (kompakt tabell i faktarutans familj; en rad utan värde ritas inte; GET /studio/api/kandis?namn=… ger född/stjärntecken/känd för ur kändisdatat när personen finns där); fragasvar(rubrik, lage: snabba | intervju, fragor[{fraga, svar}]) = frågor och svar i mallen intervju («Snabba fem» som tät ruta, eller frågan i fet och svaret som löptext); tidslinje(rubrik, rader[{ar, text}]) = tidslinjen i mallen profil (lodrät linje, året i monospace); sociala(instagram, tiktok, youtube, x, facebook, webb – bara användarnamnet eller https-adressen) = knappar med ikon, ny flik, nofollow noopener; plusminus(plus[], minus[], dom) = plus- och minuslistorna med «Domen» i mallen recension; relaterat(auto: true, tagg) = «Senaste om personen»: sajten hämtar de fem senaste artiklarna med taggen ur indexet vid renderingen. Sökdata (JSON-LD) först i kroppen: intervju = Article med about: Person (när snabbfaktan har namn), profil = ProfilePage med mainEntity: Person (birthDate ur Född i ISO-form, sameAs ur de sociala kanalerna), recension = Review med itemReviewed (Titel/Produkt ur snabbfaktan eller rubriken), reviewRating ur betygsblocket (bestRating 5), author och publisher = sajten – inget betyg, inget Review. 2.5.33: liveinlagg(rubrik, inlagg[{id, tid ÅÅÅÅ-MM-DDTHH:MM i Stockholmstid, text, bild{src, wpId, alt, caption}, fast}]) = liverapporten i mallen liverapport – nyast överst, fästa först, «Direkt»/«Avslutad» ur revisionens meta.live (true|false), «Senaste inlägg HH:MM» ur datat; sajten hämtar nya inlägg ur GET /studio/live/{id}.json var 30:e sekund (publicera om för varje nytt inlägg); LiveBlogPosting (JSON-LD) före blocket; quizfragor(rubrik, typ: personlighet | kunskap, fragor[{fraga, bild, alternativ[{text, poang{A: 1} | ratt: true}]}], resultat[{nyckel, rubrik, text, bild} | {fran, till, rubrik, text}]) = quizet i mallen quiz – körs i läsarens webbläsare (datat som JSON i blocket, aldrig skript i brödtexten), minst tre frågor; galleri(lage: berattelse, bilder[{src, wpId, alt, caption, kredit}]) = bildberättelsen i mallen bildberattelse – helbreddsbilder i följd med bildtext och kredit, svepvy med räknaren «4/18» på mobilen, minst fyra bilder; ImageGallery (JSON-LD) före blocket.",
              "properties": {
                "type": {
                  "type": "string"
                },
                "attrs": {
                  "type": "object"
                },
                "content": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "description": "Barnnod: {type: \"text\", text, marks: [{type: bold|italic|link, attrs}]} eller ett block"
                  }
                }
              }
            }
          },
          "meta": {
            "type": "object",
            "properties": {
              "seoTitel": {
                "type": "string"
              },
              "seoBesk": {
                "type": "string"
              },
              "puffTitel": {
                "type": "string"
              },
              "socialText": {
                "type": "string"
              },
              "puffBild": {
                "type": "integer",
                "description": "Egen puffbild (WordPress-mediets id); saknas = heron är puff"
              },
              "puffSrc": {
                "type": "string"
              },
              "avsnittRiktning": {
                "type": "string",
                "enum": [
                  "upp",
                  "ned"
                ],
                "description": "2.5.29 (mallen lista): upp = avsnitten numreras 1, 2, 3 …; ned = N … 2, 1 (topplista som räknar ner). Standard upp. Svenskans val gäller alla språk vid publiceringen"
              },
              "uppdaterad": {
                "type": "string",
                "description": "2.5.29: sätts av releasen (ISO-tid) när en redan publicerad artikel publiceras om. 2.5.31: visas inte publikt (Christens beslut) – syns bara i Studio. Skrivs inte av klienten"
              }
            }
          },
          "hero": {
            "type": "object",
            "properties": {
              "mediaId": {
                "type": "string"
              },
              "src": {
                "type": "string"
              },
              "wpId": {
                "type": "integer"
              },
              "alt": {
                "type": "string"
              },
              "caption": {
                "type": "string"
              },
              "bredd": {
                "type": "integer"
              },
              "hojd": {
                "type": "integer"
              },
              "fokus": {
                "type": "object",
                "description": "Fokuspunkt {x, y} i procent (0–100) – listorna beskär kring den",
                "properties": {
                  "x": {
                    "type": "integer"
                  },
                  "y": {
                    "type": "integer"
                  }
                }
              }
            }
          },
          "slug": {
            "type": "string"
          },
          "bas": {
            "type": "string",
            "description": "Revisionen du utgick från (arbetsrevision). Stämmer den inte svarar servern 409."
          },
          "kall_revision": {
            "type": "string"
          },
          "kommentar": {
            "type": "string"
          },
          "tvinga": {
            "type": "boolean"
          }
        }
      }
    }
  },
  "security": [
    {
      "agent": []
    },
    {
      "session": []
    }
  ],
  "paths": {
    "/studio/api/jag": {
      "get": {
        "summary": "Vem är jag – roll, sektioner, språk, rättigheter",
        "responses": {
          "200": {
            "description": "ok"
          }
        },
        "operationId": "getJag"
      }
    },
    "/studio/api/handbok": {
      "get": {
        "summary": "Redaktionshandboken – redaktionens regler för allt som skrivs i Studio (form, sektioner, länkar, taggar, bilder, plock, engelska, överlämning, publicering). Läs den i början av varje konversation och följ den.",
        "responses": {
          "200": {
            "description": "{ok, version, text}"
          }
        },
        "operationId": "getHandbok"
      }
    },
    "/studio/api/sektioner": {
      "get": {
        "summary": "Sektionerna med kompatibla mallar",
        "responses": {
          "200": {
            "description": "ok"
          }
        },
        "operationId": "getSektioner"
      }
    },
    "/studio/api/mallar": {
      "get": {
        "summary": "Mallarna (versionerade scheman: obligatoriska fält, tillåtna block, sektioner): nyhet, reportage, lista, recept, plock, guide, recension, sida – från 2.5.30 basttest (Bäst i test, blocket jamforelse), howto (Steg för steg, blocket stegforsteg) och evenemang (Evenemang, blocket evenemang) – och från 2.5.32 intervju (Intervju, blocket fragasvar + snabbfakta) och profil (Profil, blocken snabbfakta, tidslinje, sociala och relaterat i läget auto); recension (v2) har betyg, snabbfakta och plusminus som sina block; från 2.5.33 liverapport (Liverapport, blocket liveinlagg + meta.live), quiz (Quiz, blocket quizfragor) och bildberattelse (Bildberättelse, galleri i läget berattelse med minst fyra bilder). ?exempel=1 ger ett exempel per mall och språk; blockfalt beskriver varje blocks fält.",
        "responses": {
          "200": {
            "description": "ok"
          }
        },
        "operationId": "getMallar"
      }
    },
    "/studio/live/{id}.json": {
      "get": {
        "summary": "2.5.33: liverapportens inlägg som JSON – PUBLIK och inloggningsfri (ingen /api/-prefix), bara för innehåll vars senaste release är publicerad (aldrig utkast), Cache-Control public max-age=20. Svar: {ok, live, lage, senast (Stockholmstid), senastText HH:MM, senastRad (statusraden som HTML), antal, inlagg[{id, tid, fast, html}]} – fästa först, nyast överst. ?sprak=en ger den engelska versionen. Sajtens skript hämtar den var 30:e sekund så länge rapporten är direkt; 404 när rapporten inte är publicerad.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "sprak",
            "in": "query",
            "schema": {
              "type": "string",
              "example": "sv"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "ok"
          },
          "404": {
            "description": "ingen publicerad liverapport"
          }
        },
        "operationId": "getStudioLiveId"
      }
    },
    "/studio/api/kandis": {
      "get": {
        "summary": "2.5.32: slår upp en person i sajtens kändisdata (kändissidorna) – {hittad: true, namn, fodd, foddIso, stjarntecken, kandFor, vag, rader[{k, v}]} när hon finns, annars {hittad: false, kandidater[]}. Till snabbfaktan i intervjuer och profiler – hitta aldrig på uppgifter som saknas.",
        "parameters": [
          {
            "name": "namn",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "ok"
          }
        },
        "operationId": "getKandis"
      }
    },
    "/studio/api/innehall": {
      "get": {
        "summary": "Innehållslistan. 2.5.28: ?en=inaktuell – artiklar vars engelska står som «behöver uppdateras» (svenskan har en nyare revision än den engelskan översattes från); ?en=saknas – publicerade utan engelska; annat språk: &sprak=xx.",
        "parameters": [
          {
            "name": "sok",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "sektion",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "sida",
            "in": "query",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "en",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "inaktuell",
                "saknas"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "ok"
          }
        },
        "operationId": "getInnehall"
      },
      "post": {
        "summary": "Skapa innehåll (utkast). Idempotent med Idempotency-Key.",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "sektion",
                  "mall",
                  "rubrik"
                ],
                "properties": {
                  "sektion": {
                    "type": "string",
                    "example": "noje"
                  },
                  "mall": {
                    "type": "string",
                    "example": "nyhet"
                  },
                  "sprak": {
                    "type": "string",
                    "example": "sv",
                    "description": "Källspråk"
                  },
                  "rubrik": {
                    "type": "string"
                  },
                  "ingress": {
                    "type": "string"
                  },
                  "block": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "description": "ProseMirror-nod med stabilt attrs.id (b + 6–20 tecken). Tillåtna typer: paragraph, heading(level 2|3), bulletList, orderedList, blockquote, table, image(src, wpId, alt, caption), faktaruta(rubrik) med paragraph-innehåll (2.5.28: attrs.punkter [text …] eller attrs.text tas emot och blir stycken i content vid sparningen; en ruta utan innehåll ritas inte på sajten), relaterat(rubrik, lankar[{rubrik,url}]), inbaddning(url: YouTube/Instagram/TikTok/Spotify), produkt(namn, butik, pris, lank, bild, text), citat(text, vem), galleri(bilder[]), betyg(betyg 1–5, text), plats(namn, kategori, stadsdel, adress, karta, text), recept(rubrik, portioner, tid, grupper[{namn, rader[{mangd, vara}]}], steg[]). 2.5.29: image(layout: normal | bred | helbredd – bred = 120 % av spalten, helbredd = hela skärmbredden på dator; mobil alltid normal); avsnitt(rubrik, text – stycken åtskilda av tom rad, bild{src, wpId, alt, caption}) bara i mallen lista – sajten numrerar avsnitten själv (01, 02 … eller N … 01 efter meta.avsnittRiktning) och sätter nr/av vid sparningen; från tre avsnitt ritas en innehållsförteckning (nav.mmavs_toc) och från två en ItemList (JSON-LD) före det första; viktigast(punkter[3 korta strängar, högst 90 tecken – kontrollen varnar över 120]) = «Det viktigaste» / Key points; rattelse(datum ÅÅÅÅ-MM-DD, text) = «Rättelse …» / Correction. 2.5.30: jamforelse(rubrik, rader[{namn, bild{src, wpId, alt}, betyg 1–5 i halva steg, pris, butik, url + program eller lank – samma köplänksregler som produkt, plus[], minus[], etikett: vinnare | bastpris | budget, kommentar}]) = jämförelsetabellen i mallen basttest (Bäst i test) – ItemList med Product och betyg (JSON-LD) före blocket; stegforsteg(rubrik, behover[], tid, svarighet: latt | medel | svar, steg[{rubrik, text, bild{src, wpId, alt, caption}}], klart) = guideblocket i mallen howto (Steg för steg) – HowTo (JSON-LD) med totalTime när tiden går att tolka; evenemang(namn, start ÅÅÅÅ-MM-DDTHH:MM i Stockholmstid – krävs, slut, plats{namn, adress, stad, karta}, biljettUrl https – den enda tillåtna utlänken, biljettText, pris, arrangor, text) = evenemangsblocket i mallen evenemang – datumbricka, kartlänkar, biljettknapp, kalenderfil (VEVENT i UTC), nedräkning och Event (JSON-LD). 2.5.32: snabbfakta(rubrik – etiketten, standard «Snabbfakta», namn – vem eller vad, rader[{k, v}]) = nyckel/värde-rutan i alla mallar (kompakt tabell i faktarutans familj; en rad utan värde ritas inte; GET /studio/api/kandis?namn=… ger född/stjärntecken/känd för ur kändisdatat när personen finns där); fragasvar(rubrik, lage: snabba | intervju, fragor[{fraga, svar}]) = frågor och svar i mallen intervju («Snabba fem» som tät ruta, eller frågan i fet och svaret som löptext); tidslinje(rubrik, rader[{ar, text}]) = tidslinjen i mallen profil (lodrät linje, året i monospace); sociala(instagram, tiktok, youtube, x, facebook, webb – bara användarnamnet eller https-adressen) = knappar med ikon, ny flik, nofollow noopener; plusminus(plus[], minus[], dom) = plus- och minuslistorna med «Domen» i mallen recension; relaterat(auto: true, tagg) = «Senaste om personen»: sajten hämtar de fem senaste artiklarna med taggen ur indexet vid renderingen. Sökdata (JSON-LD) först i kroppen: intervju = Article med about: Person (när snabbfaktan har namn), profil = ProfilePage med mainEntity: Person (birthDate ur Född i ISO-form, sameAs ur de sociala kanalerna), recension = Review med itemReviewed (Titel/Produkt ur snabbfaktan eller rubriken), reviewRating ur betygsblocket (bestRating 5), author och publisher = sajten – inget betyg, inget Review. 2.5.33: liveinlagg(rubrik, inlagg[{id, tid ÅÅÅÅ-MM-DDTHH:MM i Stockholmstid, text, bild{src, wpId, alt, caption}, fast}]) = liverapporten i mallen liverapport – nyast överst, fästa först, «Direkt»/«Avslutad» ur revisionens meta.live (true|false), «Senaste inlägg HH:MM» ur datat; sajten hämtar nya inlägg ur GET /studio/live/{id}.json var 30:e sekund (publicera om för varje nytt inlägg); LiveBlogPosting (JSON-LD) före blocket; quizfragor(rubrik, typ: personlighet | kunskap, fragor[{fraga, bild, alternativ[{text, poang{A: 1} | ratt: true}]}], resultat[{nyckel, rubrik, text, bild} | {fran, till, rubrik, text}]) = quizet i mallen quiz – körs i läsarens webbläsare (datat som JSON i blocket, aldrig skript i brödtexten), minst tre frågor; galleri(lage: berattelse, bilder[{src, wpId, alt, caption, kredit}]) = bildberättelsen i mallen bildberattelse – helbreddsbilder i följd med bildtext och kredit, svepvy med räknaren «4/18» på mobilen, minst fyra bilder; ImageGallery (JSON-LD) före blocket.",
                      "properties": {
                        "type": {
                          "type": "string"
                        },
                        "attrs": {
                          "type": "object"
                        },
                        "content": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "description": "Barnnod: {type: \"text\", text, marks: [{type: bold|italic|link, attrs}]} eller ett block"
                          }
                        }
                      }
                    }
                  },
                  "hero": {
                    "type": "object"
                  },
                  "meta": {
                    "type": "object"
                  },
                  "taggar": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "kategorier": {
                    "type": "array",
                    "items": {
                      "type": "integer"
                    }
                  },
                  "sponsrad": {
                    "type": "object",
                    "properties": {
                      "partner": {
                        "type": "string"
                      },
                      "markning": {
                        "type": "string"
                      }
                    }
                  },
                  "kallor": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "titel": {
                          "type": "string"
                        },
                        "url": {
                          "type": "string"
                        },
                        "not": {
                          "type": "string"
                        }
                      }
                    }
                  },
                  "idem": {
                    "type": "string"
                  }
                }
              },
              "example": {
                "sektion": "noje",
                "mall": "nyhet",
                "rubrik": "Rubriken",
                "ingress": "Ingressen i en mening.",
                "taggar": [
                  "Kändisar"
                ],
                "block": [
                  {
                    "type": "paragraph",
                    "attrs": {
                      "id": "b1a2b3c4d5"
                    },
                    "content": [
                      {
                        "type": "text",
                        "text": "Första stycket."
                      }
                    ]
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "skapat"
          },
          "403": {
            "description": "saknar rätt"
          },
          "422": {
            "description": "valideringsfel",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "example": false
                    },
                    "fel": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "falt": {
                            "type": "string"
                          },
                          "sprak": {
                            "type": "string"
                          },
                          "orsak": {
                            "type": "string"
                          },
                          "atgard": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "operationId": "postInnehall"
      }
    },
    "/studio/api/innehall/{id}": {
      "get": {
        "summary": "Innehållet med alla språkversioner och arbetsrevisioner",
        "responses": {
          "200": {
            "description": "ok"
          },
          "404": {
            "description": "finns inte"
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "operationId": "getInnehallId"
      },
      "patch": {
        "summary": "Ändra sektion, mall, taggar, kategorier, sponsrad, källor, ansvarig, rubrik, status (utkast|granskning), raderad",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "sektion": {
                    "type": "string"
                  },
                  "mall": {
                    "type": "string"
                  },
                  "rubrik": {
                    "type": "string"
                  },
                  "taggar": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "kategorier": {
                    "type": "array",
                    "items": {
                      "type": "integer"
                    }
                  },
                  "sponsrad": {
                    "type": "object",
                    "properties": {
                      "partner": {
                        "type": "string"
                      },
                      "markning": {
                        "type": "string"
                      }
                    }
                  },
                  "kallor": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "titel": {
                          "type": "string"
                        },
                        "url": {
                          "type": "string"
                        },
                        "not": {
                          "type": "string"
                        }
                      }
                    }
                  },
                  "ansvarig": {
                    "type": "string"
                  },
                  "status": {
                    "type": "string",
                    "enum": [
                      "utkast",
                      "granskning"
                    ]
                  },
                  "raderad": {
                    "type": "boolean"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "ok"
          },
          "403": {
            "description": "saknar rätt"
          },
          "422": {
            "description": "fel",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "example": false
                    },
                    "fel": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "falt": {
                            "type": "string"
                          },
                          "sprak": {
                            "type": "string"
                          },
                          "orsak": {
                            "type": "string"
                          },
                          "atgard": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "operationId": "patchInnehallId"
      }
    },
    "/studio/api/innehall/{id}/sprak/{sprak}": {
      "put": {
        "summary": "Lämna en språkversion (ny oföränderlig revision). 409 vid konflikt.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "rubrik": {
                    "type": "string"
                  },
                  "ingress": {
                    "type": "string"
                  },
                  "block": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "description": "ProseMirror-nod med stabilt attrs.id (b + 6–20 tecken). Tillåtna typer: paragraph, heading(level 2|3), bulletList, orderedList, blockquote, table, image(src, wpId, alt, caption), faktaruta(rubrik) med paragraph-innehåll (2.5.28: attrs.punkter [text …] eller attrs.text tas emot och blir stycken i content vid sparningen; en ruta utan innehåll ritas inte på sajten), relaterat(rubrik, lankar[{rubrik,url}]), inbaddning(url: YouTube/Instagram/TikTok/Spotify), produkt(namn, butik, pris, lank, bild, text), citat(text, vem), galleri(bilder[]), betyg(betyg 1–5, text), plats(namn, kategori, stadsdel, adress, karta, text), recept(rubrik, portioner, tid, grupper[{namn, rader[{mangd, vara}]}], steg[]). 2.5.29: image(layout: normal | bred | helbredd – bred = 120 % av spalten, helbredd = hela skärmbredden på dator; mobil alltid normal); avsnitt(rubrik, text – stycken åtskilda av tom rad, bild{src, wpId, alt, caption}) bara i mallen lista – sajten numrerar avsnitten själv (01, 02 … eller N … 01 efter meta.avsnittRiktning) och sätter nr/av vid sparningen; från tre avsnitt ritas en innehållsförteckning (nav.mmavs_toc) och från två en ItemList (JSON-LD) före det första; viktigast(punkter[3 korta strängar, högst 90 tecken – kontrollen varnar över 120]) = «Det viktigaste» / Key points; rattelse(datum ÅÅÅÅ-MM-DD, text) = «Rättelse …» / Correction. 2.5.30: jamforelse(rubrik, rader[{namn, bild{src, wpId, alt}, betyg 1–5 i halva steg, pris, butik, url + program eller lank – samma köplänksregler som produkt, plus[], minus[], etikett: vinnare | bastpris | budget, kommentar}]) = jämförelsetabellen i mallen basttest (Bäst i test) – ItemList med Product och betyg (JSON-LD) före blocket; stegforsteg(rubrik, behover[], tid, svarighet: latt | medel | svar, steg[{rubrik, text, bild{src, wpId, alt, caption}}], klart) = guideblocket i mallen howto (Steg för steg) – HowTo (JSON-LD) med totalTime när tiden går att tolka; evenemang(namn, start ÅÅÅÅ-MM-DDTHH:MM i Stockholmstid – krävs, slut, plats{namn, adress, stad, karta}, biljettUrl https – den enda tillåtna utlänken, biljettText, pris, arrangor, text) = evenemangsblocket i mallen evenemang – datumbricka, kartlänkar, biljettknapp, kalenderfil (VEVENT i UTC), nedräkning och Event (JSON-LD). 2.5.32: snabbfakta(rubrik – etiketten, standard «Snabbfakta», namn – vem eller vad, rader[{k, v}]) = nyckel/värde-rutan i alla mallar (kompakt tabell i faktarutans familj; en rad utan värde ritas inte; GET /studio/api/kandis?namn=… ger född/stjärntecken/känd för ur kändisdatat när personen finns där); fragasvar(rubrik, lage: snabba | intervju, fragor[{fraga, svar}]) = frågor och svar i mallen intervju («Snabba fem» som tät ruta, eller frågan i fet och svaret som löptext); tidslinje(rubrik, rader[{ar, text}]) = tidslinjen i mallen profil (lodrät linje, året i monospace); sociala(instagram, tiktok, youtube, x, facebook, webb – bara användarnamnet eller https-adressen) = knappar med ikon, ny flik, nofollow noopener; plusminus(plus[], minus[], dom) = plus- och minuslistorna med «Domen» i mallen recension; relaterat(auto: true, tagg) = «Senaste om personen»: sajten hämtar de fem senaste artiklarna med taggen ur indexet vid renderingen. Sökdata (JSON-LD) först i kroppen: intervju = Article med about: Person (när snabbfaktan har namn), profil = ProfilePage med mainEntity: Person (birthDate ur Född i ISO-form, sameAs ur de sociala kanalerna), recension = Review med itemReviewed (Titel/Produkt ur snabbfaktan eller rubriken), reviewRating ur betygsblocket (bestRating 5), author och publisher = sajten – inget betyg, inget Review. 2.5.33: liveinlagg(rubrik, inlagg[{id, tid ÅÅÅÅ-MM-DDTHH:MM i Stockholmstid, text, bild{src, wpId, alt, caption}, fast}]) = liverapporten i mallen liverapport – nyast överst, fästa först, «Direkt»/«Avslutad» ur revisionens meta.live (true|false), «Senaste inlägg HH:MM» ur datat; sajten hämtar nya inlägg ur GET /studio/live/{id}.json var 30:e sekund (publicera om för varje nytt inlägg); LiveBlogPosting (JSON-LD) före blocket; quizfragor(rubrik, typ: personlighet | kunskap, fragor[{fraga, bild, alternativ[{text, poang{A: 1} | ratt: true}]}], resultat[{nyckel, rubrik, text, bild} | {fran, till, rubrik, text}]) = quizet i mallen quiz – körs i läsarens webbläsare (datat som JSON i blocket, aldrig skript i brödtexten), minst tre frågor; galleri(lage: berattelse, bilder[{src, wpId, alt, caption, kredit}]) = bildberättelsen i mallen bildberattelse – helbreddsbilder i följd med bildtext och kredit, svepvy med räknaren «4/18» på mobilen, minst fyra bilder; ImageGallery (JSON-LD) före blocket.",
                      "properties": {
                        "type": {
                          "type": "string"
                        },
                        "attrs": {
                          "type": "object"
                        },
                        "content": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "description": "Barnnod: {type: \"text\", text, marks: [{type: bold|italic|link, attrs}]} eller ett block"
                          }
                        }
                      }
                    }
                  },
                  "meta": {
                    "type": "object",
                    "properties": {
                      "seoTitel": {
                        "type": "string"
                      },
                      "seoBesk": {
                        "type": "string"
                      },
                      "puffTitel": {
                        "type": "string"
                      },
                      "socialText": {
                        "type": "string"
                      },
                      "puffBild": {
                        "type": "integer",
                        "description": "Egen puffbild (WordPress-mediets id); saknas = heron är puff"
                      },
                      "puffSrc": {
                        "type": "string"
                      },
                      "avsnittRiktning": {
                        "type": "string",
                        "enum": [
                          "upp",
                          "ned"
                        ],
                        "description": "2.5.29 (mallen lista): upp = avsnitten numreras 1, 2, 3 …; ned = N … 2, 1 (topplista som räknar ner). Standard upp. Svenskans val gäller alla språk vid publiceringen"
                      },
                      "uppdaterad": {
                        "type": "string",
                        "description": "2.5.29: sätts av releasen (ISO-tid) när en redan publicerad artikel publiceras om. 2.5.31: visas inte publikt (Christens beslut) – syns bara i Studio. Skrivs inte av klienten"
                      }
                    }
                  },
                  "hero": {
                    "type": "object",
                    "properties": {
                      "mediaId": {
                        "type": "string"
                      },
                      "src": {
                        "type": "string"
                      },
                      "wpId": {
                        "type": "integer"
                      },
                      "alt": {
                        "type": "string"
                      },
                      "caption": {
                        "type": "string"
                      },
                      "bredd": {
                        "type": "integer"
                      },
                      "hojd": {
                        "type": "integer"
                      },
                      "fokus": {
                        "type": "object",
                        "description": "Fokuspunkt {x, y} i procent (0–100) – listorna beskär kring den",
                        "properties": {
                          "x": {
                            "type": "integer"
                          },
                          "y": {
                            "type": "integer"
                          }
                        }
                      }
                    }
                  },
                  "slug": {
                    "type": "string"
                  },
                  "bas": {
                    "type": "string",
                    "description": "Revisionen du utgick från (arbetsrevision). Stämmer den inte svarar servern 409."
                  },
                  "kall_revision": {
                    "type": "string"
                  },
                  "kommentar": {
                    "type": "string"
                  },
                  "tvinga": {
                    "type": "boolean"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "ny revision {id, nr, hash}"
          },
          "409": {
            "description": "konflikt – någon annan sparade; svaret bär senaste revisionen"
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "sprak",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "operationId": "putInnehallIdSprakSprak"
      }
    },
    "/studio/api/innehall/{id}/sprak/{sprak}/status": {
      "post": {
        "summary": "Sätt språkstatus: utkast | granskning | godkand | behover_uppdateras. godkand kräver granskare/publicerare – eller en agent med publiceringsrätt på ägarens order (order_av). granskning mejlar redaktionen bara för personer (mejl:false stänger av; agenter mejlar aldrig).",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "status"
                ],
                "properties": {
                  "status": {
                    "type": "string",
                    "enum": [
                      "utkast",
                      "granskning",
                      "godkand",
                      "behover_uppdateras"
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "ok"
          },
          "403": {
            "description": "saknar rätt"
          },
          "422": {
            "description": "språkversionen saknas"
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "sprak",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "operationId": "postInnehallIdSprakSprakStatus"
      }
    },
    "/studio/api/innehall/{id}/sprak/{sprak}/revisioner": {
      "get": {
        "summary": "Revisionshistoriken",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "sprak",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "ok"
          }
        },
        "operationId": "getInnehallIdSprakSprakRevisioner"
      }
    },
    "/studio/api/innehall/{id}/sprak/{sprak}/aterstall": {
      "post": {
        "summary": "Återställ till en tidigare revision (blir en ny revision)",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "sprak",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "ok"
          }
        },
        "operationId": "postInnehallIdSprakSprakAterstall"
      }
    },
    "/studio/api/innehall/{id}/oversatt": {
      "post": {
        "summary": "Skapa översättningsutkast med AI-adaptern (jobb). Manuell översättning: PUT språkversionen direkt.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "fran": {
                    "type": "string"
                  },
                  "till": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "skrivOver": {
                    "type": "boolean"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "jobb {jobb, hamta}"
          },
          "409": {
            "description": "målspråket är redan bearbetat"
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "operationId": "postInnehallIdOversatt"
      }
    },
    "/studio/api/oversatt-lista": {
      "post": {
        "summary": "2.5.28: översätt om en lista artiklar i ett svep – ett jobb per artikel (samma jobb som innehall/{id}/oversatt). innehall: [id …] (högst 60) eller filter: \"inaktuell\". Engelskan sparas som utkast, inget publiceras. De två första jobben drivs direkt; resten av GET oversatt-lista?jobb= (svaret bär adressen i hamta) och av femminuterspasset.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "innehall": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "filter": {
                    "type": "string",
                    "enum": [
                      "inaktuell"
                    ]
                  },
                  "fran": {
                    "type": "string",
                    "default": "sv"
                  },
                  "till": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "default": [
                      "en"
                    ]
                  },
                  "skrivOver": {
                    "type": "boolean",
                    "description": "ersätt engelska som redan är godkänd/i granskning"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "{jobb: [{innehall, jobb, ok, orsak}], hamta}"
          },
          "422": {
            "description": "inget jobb lades"
          }
        },
        "operationId": "postOversattlista"
      },
      "get": {
        "summary": "2.5.28: läget för jobben (?jobb=a,b,c) – driver dessutom upp till två väntande jobb ett steg (~20 s) i bakgrunden. Hämta var 5–10 s tills klart = true.",
        "parameters": [
          {
            "name": "jobb",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "{jobb: [{jobb, innehall, status, framsteg, fel}], summa, klart}"
          }
        },
        "operationId": "getOversattlista"
      }
    },
    "/studio/api/svep/faktaruta": {
      "get": {
        "summary": "2.5.28: läsande svep – publicerade artiklar vars faktaruta står tom ute (ingen text) eller bara bär punkterna i attrs.punkter (tom ram tills artikeln publiceras om). Inget ändras.",
        "parameters": [
          {
            "name": "antal",
            "in": "query",
            "schema": {
              "type": "integer",
              "default": 1200
            }
          }
        ],
        "responses": {
          "200": {
            "description": "{granskade, traffar: [{id, rubrik, sprak, lank, rutor, tomma, punkter_i_attrs, atgard}]}"
          }
        },
        "operationId": "getSvepFaktaruta"
      }
    },
    "/studio/api/innehall/{id}/forslag": {
      "post": {
        "summary": "Förslag att välja bland: SEO-analys + SEO-titel/metabeskrivning/rubriker/ingress/pufftitel/delningstext, taggar (befintliga i WordPress först) + kategorier, «Läs också» ur sajtens eget index, alt-text för heron (bildmodell), puff (pufftitel + delningstext för sms och sociala medier). 2.5.29: typ viktigast ger {punkter: [tre strängar, högst 90 tecken], kalla: ai | text} till blocket «Det viktigaste» (kalla text = de första meningarna ur texten när modellen inte svarade). Inget skrivs in automatiskt.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "typ": {
                    "type": "string",
                    "enum": [
                      "alla",
                      "seo",
                      "taggar",
                      "lasocksa",
                      "alt",
                      "puff",
                      "viktigast"
                    ],
                    "default": "alla"
                  },
                  "sprak": {
                    "type": "string",
                    "example": "sv"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "ok"
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "operationId": "postInnehallIdForslag"
      }
    },
    "/studio/api/innehall/{id}/kopiera": {
      "post": {
        "summary": "Kopiera till nytt utkast (samma sektion, mall, taggar, kategorier; källspråket som rev 1)",
        "responses": {
          "201": {
            "description": "skapad"
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "operationId": "postInnehallIdKopiera"
      }
    },
    "/studio/api/innehall/{id}/validera": {
      "post": {
        "summary": "Kontrollen före publicering: blockerande fel och rådgivande varningar per språk. Svar {ok, blockerande, fel[], varningar[]} – varje fel har falt, sprak, orsak, atgard.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "sprak": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Språk att kontrollera; utelämnad = alla med arbetsrevision"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "ok"
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "operationId": "postInnehallIdValidera"
      }
    },
    "/studio/api/innehall/{id}/nedtagning": {
      "post": {
        "summary": "Ta ned en publicerad artikel (bara redaktionen: chefredaktör/administratör – agenter får 403)",
        "description": "WordPress får status utkast, artikeln försvinner ur sökindexet och sidcachen, Studio-status blir «nedtagen» och adressen leder till sektionen (302). Orsaken är obligatorisk och loggas. Publicera igen = vanlig release.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "orsak"
                ],
                "properties": {
                  "orsak": {
                    "type": "string",
                    "maxLength": 300
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Nedtagen: {status, wp, avindexerad, lank, leder_till}"
          },
          "403": {
            "description": "Agent eller utan publiceringsrätt"
          },
          "409": {
            "description": "Inte publicerad"
          },
          "422": {
            "description": "Orsak saknas"
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "operationId": "postInnehallIdNedtagning"
      }
    },
    "/studio/api/innehall/{id}/forhandsvisning": {
      "post": {
        "summary": "Förhandsvisning med sajtens rendering; dela=minuter ger en tidsbegränsad, återkallningsbar länk",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "sprak": {
                    "type": "string"
                  },
                  "revision": {
                    "type": "string"
                  },
                  "dela": {
                    "type": "integer"
                  }
                }
              }
            }
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "ok"
          }
        },
        "operationId": "postInnehallIdForhandsvisning"
      }
    },
    "/studio/api/innehall/{id}/release": {
      "post": {
        "summary": "Publiceringsrelease: bestämda revisioner för valda språk. lage = utkast | publicera | schemalagd (tid i Europe/Stockholm, ÅÅÅÅ-MM-DD HH:MM). datum (2.5.23, med lage publicera): publiceringsdatum ÅÅÅÅ-MM-DD HH:MM i Europe/Stockholm – bakåt i tiden publiceras artikeln nu men dateras så (WordPress date_gmt, innehall.publicerad), framåt blir releasen schemalagd; går även på en redan publicerad artikel. overstyr: true låter superadministratören/chefredaktören publicera trots blockerande fel (loggas; aldrig agenter). Godkännandet registreras i samma anrop (arbetsrevisionen blir godkänd) – ingen granskning, inga mejl. En agent anger order_av (personen som gav ordern i chatten); revisioner {sv: id} pekar ut en revision uttryckligen. Idempotent med Idempotency-Key. Svenskan går till WordPress (utkast i testläge), engelskan till sajtens engelska lager när svenskan är publik – antingen i samma anrop (sprak [\"sv\",\"en\"]) eller redan publicerad (innehall.status publicerad; från 2.5.18 räcker då sprak [\"en\"]). Språkversionens status (utkast/granskning/godkand) är det redaktionella läget och blir aldrig «publicerad» – publiceringsläget står på innehållet (status, publicerad) och per språk i release.resultat. Ett språk som ändå måste vänta ger 202 med vantar: true överst och en varning i varningar[].",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "sprak",
                  "lage"
                ],
                "properties": {
                  "sprak": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "lage": {
                    "type": "string",
                    "enum": [
                      "utkast",
                      "publicera",
                      "schemalagd"
                    ]
                  },
                  "tid": {
                    "type": "string",
                    "example": "2026-09-20 07:00"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "aktiverad/test – resultat per språk med URL:er och verifiering"
          },
          "202": {
            "description": "schemalagd – eller ett språk väntar (vantar: true, varningar[])"
          },
          "403": {
            "description": "saknar publiceringsrätt"
          },
          "422": {
            "description": "blockerande fel",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "example": false
                    },
                    "fel": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "falt": {
                            "type": "string"
                          },
                          "sprak": {
                            "type": "string"
                          },
                          "orsak": {
                            "type": "string"
                          },
                          "atgard": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "502": {
            "description": "delvis – ett språk misslyckades, inget annat publicerades tyst"
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "operationId": "postInnehallIdRelease"
      }
    },
    "/studio/api/release/{id}": {
      "get": {
        "summary": "Releasens status och resultat",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "ok"
          }
        },
        "operationId": "getReleaseId"
      }
    },
    "/studio/api/release/{id}/avbryt": {
      "post": {
        "summary": "Avbryt en schemalagd release",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "ok"
          }
        },
        "operationId": "postReleaseIdAvbryt"
      }
    },
    "/studio/api/releaser": {
      "get": {
        "summary": "Kalendern: releaser i ett tidsspann (fran, till i ms)",
        "responses": {
          "200": {
            "description": "ok"
          }
        },
        "operationId": "getReleaser"
      }
    },
    "/studio/api/jobb/{id}": {
      "get": {
        "summary": "Jobbstatus (översättning m.m.)",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "ok"
          }
        },
        "operationId": "getJobbId"
      }
    },
    "/studio/api/media": {
      "get": {
        "summary": "Mediebiblioteket (sok, sida)",
        "parameters": [
          {
            "name": "sok",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "sida",
            "in": "query",
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "ok"
          }
        },
        "operationId": "getMedia"
      },
      "post": {
        "summary": "Ladda upp en bild: JSON {url, namn, alt, bildtext, fotograf, kalla, kredit, rattighet, giltig_till} (bara https till publika värdar) – eller rå bild i kroppen (image/jpeg|png|webp|gif, ≤40 MB) med X-Namn, X-Alt, X-Kredit m.fl. Dubbletter känns igen på innehållet.",
        "description": "Svaret ger media {id, url, wp_id, bredd, hojd} – använd wp_id och src i hero eller i ett image-block. WordPress skalar till 2 560 px.",
        "parameters": [
          {
            "name": "X-Namn",
            "in": "header",
            "schema": {
              "type": "string"
            },
            "description": "Filnamn utan ändelse (URL-kodat), t.ex. oslo-hotell"
          },
          {
            "name": "X-Alt",
            "in": "header",
            "schema": {
              "type": "string"
            },
            "description": "Alt-text (URL-kodad UTF-8)"
          },
          {
            "name": "X-Kredit",
            "in": "header",
            "schema": {
              "type": "string"
            },
            "description": "Fotokredit som visas, t.ex. Foto: Namn/Byrå (URL-kodad)"
          },
          {
            "name": "X-Fotograf",
            "in": "header",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-Kalla",
            "in": "header",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-Rattighet",
            "in": "header",
            "schema": {
              "type": "string",
              "enum": [
                "okand",
                "egen",
                "licens",
                "press",
                "shutterstock",
                "adobe",
                "ai"
              ]
            }
          },
          {
            "name": "X-Bildtext",
            "in": "header",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "X-Sprak",
            "in": "header",
            "schema": {
              "type": "string",
              "example": "sv"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "url"
                ],
                "properties": {
                  "url": {
                    "type": "string",
                    "description": "https-adress till en publik bild (data:-URI avvisas – skicka då råa bytes)"
                  },
                  "namn": {
                    "type": "string"
                  },
                  "alt": {
                    "type": "string"
                  },
                  "bildtext": {
                    "type": "string"
                  },
                  "fotograf": {
                    "type": "string"
                  },
                  "kalla": {
                    "type": "string"
                  },
                  "kredit": {
                    "type": "string",
                    "description": "Fotokredit som visas, t.ex. «Foto: Namn/Byrå»"
                  },
                  "rattighet": {
                    "type": "string",
                    "enum": [
                      "okand",
                      "egen",
                      "licens",
                      "press",
                      "shutterstock",
                      "adobe",
                      "ai"
                    ]
                  },
                  "giltig_till": {
                    "type": "string",
                    "example": "2027-12-31"
                  },
                  "sprak": {
                    "type": "string",
                    "example": "sv"
                  }
                }
              }
            },
            "image/jpeg": {
              "schema": {
                "type": "string",
                "format": "binary"
              }
            },
            "image/png": {
              "schema": {
                "type": "string",
                "format": "binary"
              }
            },
            "image/webp": {
              "schema": {
                "type": "string",
                "format": "binary"
              }
            },
            "image/gif": {
              "schema": {
                "type": "string",
                "format": "binary"
              }
            }
          },
          "description": "JSON med url – eller filens råa bytes i kroppen (≤40 MB) med metadata i X-huvudena (URL-kodade UTF-8). Råbytes är vägen för en fil du har lokalt."
        },
        "responses": {
          "201": {
            "description": "media"
          },
          "422": {
            "description": "fel typ/storlek/URL",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean",
                      "example": false
                    },
                    "fel": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "falt": {
                            "type": "string"
                          },
                          "sprak": {
                            "type": "string"
                          },
                          "orsak": {
                            "type": "string"
                          },
                          "atgard": {
                            "type": "string"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "operationId": "postMedia"
      }
    },
    "/studio/api/media/wp": {
      "get": {
        "summary": "Sök i WordPress mediebibliotek (sok, minst 2 tecken) – bilder som redan finns på sajten",
        "parameters": [
          {
            "name": "sok",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "ok"
          }
        },
        "operationId": "getMediaWp"
      },
      "post": {
        "summary": "Ta in en WordPress-bild i Studios register – ingen ny uppladdning",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "wp_id"
                ],
                "properties": {
                  "wp_id": {
                    "type": "integer"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "fanns redan"
          },
          "201": {
            "description": "skapad"
          }
        },
        "operationId": "postMediaWp"
      }
    },
    "/studio/api/media/{id}": {
      "get": {
        "summary": "Mediepost med texter",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "ok"
          }
        },
        "operationId": "getMediaId"
      },
      "patch": {
        "summary": "Rättigheter: fotograf, kalla, kredit, rattighet (okand|egen|licens|press|shutterstock|adobe|ai), underlag, giltig_till, begransning, granskad",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "ok"
          }
        },
        "operationId": "patchMediaId"
      }
    },
    "/studio/api/media/{id}/text/{sprak}": {
      "put": {
        "summary": "Alt-text och bildtext per språk (och per användning)",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "alt": {
                    "type": "string",
                    "maxLength": 300
                  },
                  "bildtext": {
                    "type": "string",
                    "maxLength": 400
                  },
                  "anvandning": {
                    "type": "string",
                    "default": "standard"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "ok"
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "sprak",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "operationId": "putMediaIdTextSprak"
      }
    },
    "/studio/api/media/{id}/anvandning": {
      "get": {
        "summary": "Var bilden används",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "ok"
          }
        },
        "operationId": "getMediaIdAnvandning"
      }
    },
    "/studio/api/dubbletter": {
      "get": {
        "summary": "Dubblettkollen (2.5.14, G1): rader som delar WordPress-id eller adress (sektion + slug). Tom lista = inga dubbletter. Redaktionsledningen och agenter.",
        "responses": {
          "200": {
            "description": "{wp: [...], adress: [...], kontrollerad}"
          }
        },
        "operationId": "getDubbletter"
      }
    },
    "/studio/api/media/{id}/fil": {
      "put": {
        "summary": "Byt bildens innehåll men behåll adressen (2.5.14, C1): råa bytes i kroppen ersätter filen på samma /files/-adress – allt som pekar på filnamnet (guidernas heron och puffar) visar den nya bilden. {id} är Studios medie-id eller WordPress-id (wp_id).",
        "description": "Bytet sker i vår egen bildbank (R2) som sajten serverar /files/ ur; Cloudflares kant töms för adressen. WordPress egna storleksvarianter (-768x512 osv.) berörs inte – Studio-sidor använder originalet. Svaret ger media med nya mått, storlek och hash.",
        "parameters": [
          {
            "name": "X-Alt",
            "in": "header",
            "schema": {
              "type": "string"
            },
            "description": "Alt-text (URL-kodad UTF-8)"
          },
          {
            "name": "X-Kredit",
            "in": "header",
            "schema": {
              "type": "string"
            },
            "description": "Fotokredit som visas, t.ex. Foto: Namn/Byrå (URL-kodad)"
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "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"
              }
            },
            "image/gif": {
              "schema": {
                "type": "string",
                "format": "binary"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "media (ny bredd/hojd/storlek/hash), r2, purge"
          },
          "404": {
            "description": "mediet finns inte"
          },
          "409": {
            "description": "samma innehåll som redan ligger där"
          },
          "422": {
            "description": "fel typ/storlek"
          },
          "503": {
            "description": "bildbanken (R2) saknas i workern"
          }
        },
        "operationId": "putMediaIdFil"
      }
    },
    "/studio/api/taggar": {
      "get": {
        "summary": "Taggar (samma som Insights › Taggar): läget, de hundra största taggarna, artiklar utan tagg",
        "responses": {
          "200": {
            "description": "ok"
          }
        },
        "operationId": "getTaggar"
      }
    },
    "/studio/api/kategorier": {
      "get": {
        "summary": "Kategorier ur WordPress",
        "responses": {
          "200": {
            "description": "ok"
          }
        },
        "operationId": "getKategorier"
      }
    },
    "/studio/api/agenter": {
      "get": {
        "summary": "Agentkonton (admin)",
        "responses": {
          "200": {
            "description": "ok"
          }
        },
        "operationId": "getAgenter"
      },
      "post": {
        "summary": "Skapa agentkonto – nyckeln visas en gång (admin)",
        "responses": {
          "200": {
            "description": "ok"
          }
        },
        "operationId": "postAgenter"
      }
    },
    "/studio/api/uppdrag": {
      "get": {
        "summary": "Uppdragskön (samma som Insights › Uppdrag): väntar på granskning, öppna, klara, avfärdade",
        "responses": {
          "200": {
            "description": "ok"
          }
        },
        "operationId": "getUppdrag"
      },
      "post": {
        "summary": "Nytt uppdrag till VOR {text, sektion, prioritet}",
        "responses": {
          "201": {
            "description": "skapat"
          }
        },
        "operationId": "postUppdrag"
      }
    },
    "/studio/api/uppdrag/{id}/{atgard}": {
      "post": {
        "summary": "godkann (granskning → godkänt), tillbaka eller avfarda (→ avfärdat) – kräver publiceringsrätt",
        "responses": {
          "200": {
            "description": "ok"
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "atgard",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "operationId": "postUppdragIdAtgard"
      }
    },
    "/studio/api/utkast": {
      "get": {
        "summary": "Väntar på ditt ja (samma som Insights › Utkast): utkast VOR skrivit utanför Studio – väntar, schemalagda, publicerade – och Studios innehåll i granskning",
        "responses": {
          "200": {
            "description": "ok"
          }
        },
        "operationId": "getUtkast"
      }
    },
    "/studio/api/utkast/{id}/publicera": {
      "post": {
        "summary": "Publicera nu {last:true} eller schemalägg {last:true, nar:'ÅÅÅÅ-MM-DDTHH:MM'} ett utkast VOR skrivit – kräver publiceringsrätt",
        "responses": {
          "200": {
            "description": "ok"
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "operationId": "postUtkastIdPublicera"
      }
    },
    "/studio/api/utkast/{id}/avfarda": {
      "post": {
        "summary": "Avfärda ett utkast (försvinner ur listan, ingenting raderas i WordPress) – kräver publiceringsrätt",
        "responses": {
          "200": {
            "description": "ok"
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "operationId": "postUtkastIdAvfarda"
      }
    },
    "/studio/api/utkast/{id}/forhandsvisning": {
      "post": {
        "summary": "Förhandsvisning (sv + en) i sajtens mall för WordPress-typerna som byggs i workern",
        "responses": {
          "200": {
            "description": "ok"
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "operationId": "postUtkastIdForhandsvisning"
      }
    },
    "/studio/api/forslagvy": {
      "get": {
        "summary": "Förslag (samma som Insights › Förslag): affärsmöjligheter, redaktionella uppslag, Google Trends, beställda, kampanjer att plocka ur, källorna",
        "responses": {
          "200": {
            "description": "ok"
          }
        },
        "operationId": "getForslagvy"
      }
    },
    "/studio/api/forslag/{id}/bestall": {
      "post": {
        "summary": "Beställ ett förslag {typ, sektion, prioritet} – blir ett uppdrag i ditt namn (samma som Beställ på översikten)",
        "responses": {
          "201": {
            "description": "skapat"
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "operationId": "postForslagIdBestall"
      }
    },
    "/studio/api/forslag/{id}/angra": {
      "post": {
        "summary": "Ångra beställning eller avfärdande (→ nytt)",
        "responses": {
          "200": {
            "description": "ok"
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "operationId": "postForslagIdAngra"
      }
    },
    "/studio/api/forslag/kampanj/{id}/plock": {
      "post": {
        "summary": "Beställ en plocklista på en kampanj {antal} – ett uppdrag i ditt namn",
        "responses": {
          "201": {
            "description": "skapat"
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "operationId": "postForslagKampanjIdPlock"
      }
    },
    "/studio/api/forslag/bygg": {
      "post": {
        "summary": "Hämta nya förslag (omvärldsbevakningen) – kräver publiceringsrätt",
        "responses": {
          "200": {
            "description": "ok"
          }
        },
        "operationId": "postForslagBygg"
      }
    },
    "/studio/api/taggar/forslag": {
      "post": {
        "summary": "Föreslå taggar för en artikel {lank} ur taggfloran (högst fyra)",
        "responses": {
          "200": {
            "description": "ok"
          }
        },
        "operationId": "postTaggarForslag"
      }
    },
    "/studio/api/taggar/satt": {
      "post": {
        "summary": "Sätt taggar {lank, taggar:[…]} på artikeln i WordPress och uppdatera sökindexet – kräver publiceringsrätt",
        "responses": {
          "200": {
            "description": "ok"
          }
        },
        "operationId": "postTaggarSatt"
      }
    },
    "/studio/api/ordbok": {
      "get": {
        "summary": "Ordbok & personer (samma som Insights › Personer + Ordboken): de mest omskrivna personerna med tagg/text och senaste artiklar, namn utan egen tagg, de vanligaste orden och namnen",
        "responses": {
          "200": {
            "description": "ok"
          }
        },
        "operationId": "getOrdbok"
      }
    },
    "/studio/api/ordbok/tagg": {
      "post": {
        "summary": "Skapa taggen {namn} i WordPress för ett namn utan egen tagg – kräver publiceringsrätt",
        "responses": {
          "201": {
            "description": "skapad"
          }
        },
        "operationId": "postOrdbokTagg"
      }
    },
    "/studio/api/kop/lankvakt": {
      "get": {
        "summary": "Länkvakten (samma som Insights › Länkvakten): trasiga köplänkar, länkar utan artikel-ID, sidor som inte svarar, körningarna",
        "responses": {
          "200": {
            "description": "ok"
          }
        },
        "operationId": "getKopLankvakt"
      }
    },
    "/studio/api/appar": {
      "get": {
        "summary": "Appbiblioteket: apparna i appen familj för familj med användningen (7 och 30 dagar, dag för dag)",
        "responses": {
          "200": {
            "description": "ok"
          }
        },
        "operationId": "getAppar"
      }
    },
    "/studio/api/oversikt": {
      "get": {
        "summary": "Översikten: utkast, granskningskö, saknade språk, kommande, misslyckade, senast publicerat",
        "responses": {
          "200": {
            "description": "ok"
          }
        },
        "operationId": "getOversikt"
      }
    },
    "/studio/api/mallar/{id}": {
      "get": {
        "summary": "En mall",
        "responses": {
          "200": {
            "description": "ok"
          },
          "404": {
            "description": "finns inte"
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "operationId": "getMallarId"
      }
    },
    "/studio/api/innehall/{id}/revision/{rid}": {
      "get": {
        "summary": "En revision (vilket språk som helst) – för jämförelse block för block",
        "responses": {
          "200": {
            "description": "ok"
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "rid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "operationId": "getInnehallIdRevisionRid"
      }
    },
    "/studio/api/innehall/{id}/releaser": {
      "get": {
        "summary": "Innehållets releaser",
        "responses": {
          "200": {
            "description": "ok"
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "operationId": "getInnehallIdReleaser"
      }
    },
    "/studio/api/innehall/{id}/kommentarer": {
      "get": {
        "summary": "Interna kommentarer",
        "responses": {
          "200": {
            "description": "ok"
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "operationId": "getInnehallIdKommentarer"
      },
      "post": {
        "summary": "Ny intern kommentar till redaktionen",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "text"
                ],
                "properties": {
                  "text": {
                    "type": "string",
                    "maxLength": 2000
                  },
                  "block": {
                    "type": "string",
                    "description": "Blockets attrs.id om kommentaren gäller ett block"
                  },
                  "sprak": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "skapad"
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "operationId": "postInnehallIdKommentarer"
      }
    },
    "/studio/api/innehall/{id}/kommentarer/{kid}": {
      "patch": {
        "summary": "Markera kommentar löst/olöst ({lost})",
        "responses": {
          "200": {
            "description": "ok"
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "kid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "operationId": "patchInnehallIdKommentarerKid"
      }
    },
    "/studio/api/innehall/{id}/delningar": {
      "get": {
        "summary": "Delade förhandsvisningar",
        "responses": {
          "200": {
            "description": "ok"
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "operationId": "getInnehallIdDelningar"
      }
    },
    "/studio/api/innehall/{id}/delningar/{token}": {
      "delete": {
        "summary": "Återkalla en delad förhandsvisning",
        "responses": {
          "200": {
            "description": "ok"
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "token",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "operationId": "deleteInnehallIdDelningarToken"
      }
    },
    "/studio/api/innehall/{id}/las": {
      "post": {
        "summary": "Mjukt redigeringslås per språk ({sprak}), 90 s – konfliktkontrollen är revisionerna",
        "responses": {
          "200": {
            "description": "ok"
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "operationId": "postInnehallIdLas"
      }
    },
    "/studio/api/innehall/{id}/logg": {
      "get": {
        "summary": "Innehållets logg (vem gjorde vad, när – även releaser)",
        "responses": {
          "200": {
            "description": "ok"
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "operationId": "getInnehallIdLogg"
      }
    },
    "/studio/api/release/{id}/kor": {
      "post": {
        "summary": "Kör en schemalagd/misslyckad release nu (publicerare)",
        "responses": {
          "200": {
            "description": "ok"
          },
          "409": {
            "description": "körs redan"
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "operationId": "postReleaseIdKor"
      }
    },
    "/studio/api/jobb": {
      "get": {
        "summary": "Jobblistan (senaste 100)",
        "responses": {
          "200": {
            "description": "ok"
          }
        },
        "operationId": "getJobb"
      }
    },
    "/studio/api/agenter/{id}": {
      "patch": {
        "summary": "Ändra agentens rättigheter ({rattigheter}) eller återkalla nyckeln ({aterkalla:true}) (admin)",
        "responses": {
          "200": {
            "description": "ok"
          }
        },
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "operationId": "patchAgenterId"
      }
    },
    "/studio/api/roller": {
      "get": {
        "summary": "Redaktionens Studio-roller (admin)",
        "responses": {
          "200": {
            "description": "ok"
          }
        },
        "operationId": "getRoller"
      },
      "put": {
        "summary": "Sätt roll, sektioner och språk för ett konto (admin)",
        "responses": {
          "200": {
            "description": "ok"
          }
        },
        "operationId": "putRoller"
      }
    },
    "/studio/api/installningar": {
      "get": {
        "summary": "Inställningar: sprak3, skarp, granssnitt",
        "responses": {
          "200": {
            "description": "ok"
          }
        },
        "operationId": "getInstallningar"
      },
      "put": {
        "summary": "Ändra inställningar (admin): sprak3 (två bokstäver), skarp (true/false)",
        "responses": {
          "200": {
            "description": "ok"
          }
        },
        "operationId": "putInstallningar"
      }
    },
    "/studio/api/logg": {
      "get": {
        "summary": "Hela loggen (admin/publicerare)",
        "responses": {
          "200": {
            "description": "ok"
          }
        },
        "operationId": "getLogg"
      }
    },
    "/studio/api/export": {
      "get": {
        "summary": "Export av allt innehåll, språkversioner, revisioner, medieposter, releaser (JSON, admin) – aldrig agentnycklar",
        "responses": {
          "200": {
            "description": "ok"
          }
        },
        "operationId": "getExport"
      }
    },
    "/studio/api/utlankar": {
      "get": {
        "summary": "Utlänkar: interna vägar /ut/<grupp>/<id> som sajten vidarebefordrar till affiliateprogrammet (platsblockets bokning.vag)",
        "parameters": [
          {
            "name": "sok",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "ok"
          }
        },
        "operationId": "getUtlankar"
      },
      "put": {
        "summary": "Registrera en eller flera utlänkar. vag = /ut/<grupp>/<id>; mal = https hos ett känt program eller hotellbolag (listan i GET-svarets regel). Samma vag igen skriver över målet",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "vag": {
                    "type": "string",
                    "example": "/ut/hotell/aman-tokyo"
                  },
                  "mal": {
                    "type": "string",
                    "example": "https://www.hotels.com/…"
                  },
                  "namn": {
                    "type": "string"
                  },
                  "utlankar": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "vag": {
                          "type": "string"
                        },
                        "mal": {
                          "type": "string"
                        },
                        "namn": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "sparade + fel"
          },
          "400": {
            "description": "inget kunde sparas"
          }
        },
        "operationId": "putUtlankar"
      }
    },
    "/studio/api/utlankar/ut/{grupp}/{id}": {
      "delete": {
        "summary": "Ta bort en utlänk (admin eller agent)",
        "parameters": [
          {
            "name": "grupp",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "ok"
          }
        },
        "operationId": "deleteUtlankarUtGruppId"
      }
    },
    "/studio/api/openapi.json": {
      "get": {
        "summary": "Den här specifikationen. ?urval=chatgpt ger de 29 operationer en skrivande agent behöver (ChatGPT Actions tar högst 30)",
        "responses": {
          "200": {
            "description": "ok"
          }
        },
        "operationId": "getOpenapi"
      }
    }
  }
}