{"openapi":"3.1.0","info":{"title":"instnt studio API","version":"1.0","description":"## Basis\n\nAlles staat onder `https://instnt.studio/api/`. Verzoeken en antwoorden zijn JSON in UTF-8, tenzij hieronder anders staat (CSV, PDF, JavaScript). De app zelf gebruikt dezelfde API; wat in de app kan, kan via de API, binnen de rechten van de gebruiker.\n\nElke route werkt ook met `.php` erachter (`/api/events.php`). Dat houdt adressen uit de oude PHP-API geldig; gebruik zelf de korte vorm.\n\n## Inloggen met een API-sleutel\n\nMaak een sleutel onder **Instellingen → API-sleutels** en stuur hem mee als `Authorization: Bearer studio_…`. Studio toont de sleutel één keer en bewaart alleen een hash. Een sleutel heeft de rechten van wie hem maakte, plus een bereik: **lezen** (alleen GET), **lezen en schrijven** (ook POST) of **MCP** (alleen `/api/mcp`). Het aantal sleutels hangt af van het plan.\n\nEen paar routes zijn voor mensen en werken nooit met een sleutel: tokens, tweestap, wachtwoord wijzigen, de workspace verwijderen, meekijken als klant, uitloggen en het beheer van instnt. Die geven `403 token_not_allowed`. Schrijven met een leessleutel geeft `403 token_read_only`. `GET /api/me` kijkt alleen naar de sessie en geeft met een sleutel `user: null`.\n\n## Workspace en rechten\n\nEen gebruiker hoort bij precies één workspace, dus een sleutel werkt altijd in die workspace; er is geen header om te kiezen. Het team heeft drie rollen: **eigenaar** en **lid** mogen beheren, **kijker** alleen lezen. Een **klant** ziet alleen de projecten waar hij toegang toe heeft, per onderdeel (Overzicht, Website, Zoeken, Product, Advies, Ads) met een niveau. Vraagt een klant naar een project of onderdeel dat niet van hem is, dan geeft Studio 404 in plaats van 403: een klant hoeft niet te weten dat het bestaat.\n\nEen eigenaar die meekijkt als klant kan niets wijzigen (`403 viewing_as_readonly`).\n\n## Lezen en schrijven\n\nPer onderwerp is er meestal één adres: `GET` om te lezen, met parameters in de querystring (vaak `project_id`), en `POST` met een JSON-body om te schrijven. De body heeft een veld `action` dat zegt wat er moet gebeuren, bijvoorbeeld `{\"action\": \"status\", \"id\": 12, \"status\": \"done\"}`. Onbekende acties geven `422 unknown_action`.\n\nWerk dat lang duurt (crawl, rapport, adviezen verversen, cookiescan) gaat op de achtergrond: het antwoord is `202` met een `task_id`, en `GET /api/task?id=…` geeft `queued`, `running`, `done` of `failed`.\n\nLijsten hebben meestal een vaste bovengrens (bijvoorbeeld 500 adviezen of 300 pagina's). Pagina's bestaan alleen waar het hieronder staat, met `page`: contacten (50 per pagina), het logboek van automatiseringen (25) en de contacten in een funnel.\n\n## Antwoorden en fouten\n\nEen geslaagd antwoord heeft `\"ok\": true` met de gegevens ernaast. Een fout heeft `\"ok\": false`, een vaste code in `error`, soms een leesbare uitleg in `detail` (Nederlands) en bij formulieren per veld een melding in `fields`.\n\nVeelvoorkomende codes: `401 unauthorized` (geen of ongeldige sleutel), `402 plan_limit` of `plan_feature` (het plan staat het niet toe), `403 forbidden`, `404 not_found`, `410` (verlopen link of uitnodiging), `422 validation` of `unknown_action`, `429 too_many_requests` en `502` als een externe dienst (Google, GitHub) faalt.\n\n## Limieten\n\nPer API-sleutel 120 verzoeken per minuut. Openbare adressen hebben hun eigen grenzen: inloggen 5 per minuut per e-mailadres en 20 per IP, deellinks en statuspagina's 30 per minuut per IP, server-naar-server-events 600 per minuut per IP, metingen van het sitescript 60 per minuut per bezoeker, inkomende webhooks van automatiseringen 30 per minuut per adres, sitegebeurtenissen 120 per minuut per adres.\n\n## Andere sleutels\n\nNaast de persoonlijke API-sleutel zijn er sleutels voor één doel: een **deploysleutel** (`POST /api/deploys` en `/api/components`), een **conversiesleutel** per bron (`POST /api/events`), een **terugschrijfsleutel** voor de WordPress- of Drupal-module (`/api/titles`) en adressen met het geheim erin (inkomende webhooks, back-uppings, datafeeds). Die staan bij de routes zelf.\n\nDeze referentie bestaat ook als OpenAPI 3.1: `GET /api/openapi.json` (Nederlands) of `?lang=en`.","contact":{"name":"instnt","email":"info@instnt.nl"}},"servers":[{"url":"https://instnt.studio"}],"tags":[{"name":"Account en inloggen","description":"Inloggen, uitnodigingen, wachtwoorden, tweestap en de eigen sleutels. Op een paar na zijn dit routes voor mensen."},{"name":"Workspace, team en abonnement","description":"Wie toegang heeft, uitnodigingen, huisstijl, facturen en het beheer van instnt."},{"name":"Projecten en overzicht","description":"Projecten, de overzichten over alle klanten heen, dashboards, doelen, de tijdlijn en uren."},{"name":"Bronnen en koppelingen","description":"Google-koppelingen, Search Console, eigen systemen (instnt-metrics), aanvullende diensten en inkomende formulieren. Geheimen gaan nooit terug naar de browser; een ingevuld geheim staat als `<veld>_configured: true`."},{"name":"Cijfers","description":"Bezoek, conversie, omzet en de eigen metingen van het sitescript. GA4 en Search Console komen live van Google (gecachet); de rest uit de eigen feitentabellen."},{"name":"Zoeken en SEO","description":"Het werkblad met zoektermen, gevolgde zoekwoorden, concurrentie, de site-audit, logbestanden en content."},{"name":"Advies, vragen en AI","description":"Adviezen met hun status, playbooks, tests, vragen van klanten en AI-taken."},{"name":"Uptime en techniek","description":"Uptime-controles, JavaScript-fouten, back-ups, onderhoud, sitecontroles, versies met bekende lekken en de cookiescan."},{"name":"Rapporten","description":"Maandrapporten, kwartaal- en jaaroverzichten, deellinks en PDF. Klanten zien alleen gepubliceerde rapporten."},{"name":"Google Ads","description":"Inzichten, doelen, zoekwoordideeën en de Ads-piloot met voorstellen."},{"name":"Automatiseringen en meldingen","description":"Automatiseringen (trigger, filters, acties), het logboek, goedkeuringen, meldingsregels en de kanalen: uitgaande webhooks, Slack en Teams. Uitgaande webhooks hebben de vorm `{\"event\", \"sent_at\", \"data\"}` met de header `X-Studio-Signature: sha256=<HMAC-SHA256 van de body met het geheim>`, plus `X-Studio-Timestamp`, `X-Studio-Delivery` en `X-Studio-Signature-V2` (HMAC van `<timestamp>.<delivery>.<body>`) om oude of herhaalde berichten te weigeren."},{"name":"Studio Mail","description":"Contacten, lijsten, opt-in-formulieren, sjablonen, verzenddomeinen en -accounts (`/api/contacts`), en funnels, campagnes en segmenten (`/api/mail`). Een onbekende actie geeft hier `422 validation`."},{"name":"Server naar server","description":"Adressen voor andere systemen: conversie-events, deploys, lockbestanden, MCP, inkomende webhooks en het sitescript. Elk heeft een eigen sleutel of een geheim adres."},{"name":"Openbaar","description":"Zonder inlog: gedeelde rapporten, statuspagina's, datafeeds en de eigen cijfers op de site."},{"name":"Intern","description":"Adressen voor diensten waar Studio mee praat. Ze controleren de handtekening van de afzender en zijn niet bedoeld om zelf aan te roepen.","x-internal":true}],"paths":{"/api/me":{"get":{"tags":["Account en inloggen"],"operationId":"get_me","summary":"Wie is er ingelogd","description":"Met een sessie: de gebruiker, workspace, rol, functies, plan en wat op goedkeuring wacht. Zonder sessie: `user: null` en wat het inlogscherm nodig heeft. Kijkt niet naar API-sleutels.\n\n**Toegang:** Geen inlog","security":[],"x-studio-auth":"public","responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"user":{"type":["object","null"],"description":"id, email, name, is_admin, role, can_manage, is_client, two_factor"},"workspaces":{"type":"array","items":{"type":"object"},"description":"id, slug, name, role"},"features":{"type":"object"},"modules":{"type":"object","description":"Per module of hij aan staat voor de werkruimte (plan en instelling)."},"plan":{"type":["object","null"],"description":"key, label, limits, usage, trial_ends_at, active, cancel_from, data_delete_on"},"approvals_open":{"type":"integer"},"terms":{"type":["object","null"],"description":"alleen voor de eigenaar / owner only: version, required, deadline, blocking"},"start_page":{"type":["string","null"]},"viewed_by":{"type":["object","null"]},"google_connect":{"type":"boolean"},"setup_required":{"type":"boolean"},"google_login":{"type":"boolean"},"signup_open":{"type":"boolean"},"brand":{"type":["object","null"]}}}}}}}}},"/api/login":{"post":{"tags":["Account en inloggen"],"operationId":"post_login","summary":"Inloggen met e-mail en wachtwoord","description":"Zet het sessiecookie. Staat tweestap aan, dan komt er eerst een `challenge` terug voor `/api/login/two-factor`. De app voor iOS en macOS stuurt `client: app` mee en krijgt dan een `token` in het antwoord in plaats van een cookie; dat gaat mee als `Authorization: Bearer studioapp_…` en staat onder Account → Apparaten.\n\n**Toegang:** Geen inlog","security":[],"x-studio-auth":"public","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"email":{"type":"string","format":"email"},"password":{"type":"string"},"client":{"type":"string","enum":["app"],"description":"Alleen de app."},"device_name":{"type":"string","description":"Naam onder Account → Apparaten; zonder naam \"iPhone van <voornaam>\"."},"device_model":{"type":"string","description":"iPhone, iPad of Mac."}},"required":["email","password"]}}}},"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"two_factor":{"type":"boolean"},"challenge":{"type":"string"},"token":{"type":"string","description":"Alleen met `client: app`, één keer te zien."},"device_name":{"type":"string"}}}}}},"401":{"$ref":"#/components/responses/401"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/login/two-factor":{"post":{"tags":["Account en inloggen"],"operationId":"post_login_two_factor","summary":"Tweede stap: code uit de app of herstelcode","description":"Na vijf foute codes vervalt de tussenstap. Begon de login in de app, dan komt er een `token` terug in plaats van een cookie.\n\n**Toegang:** Geen inlog","security":[],"x-studio-auth":"public","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"challenge":{"type":"string","description":"Uit het antwoord van /api/login; na Google staat hij in een cookie."},"code":{"type":"string"}},"required":["code"]}}}},"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"token":{"type":["string","null"]},"device_name":{"type":["string","null"]}}}}}},"401":{"$ref":"#/components/responses/401"},"410":{"$ref":"#/components/responses/410"},"429":{"$ref":"#/components/responses/429"}}}},"/api/login/google":{"get":{"tags":["Account en inloggen"],"operationId":"get_login_google","summary":"Inloggen met Google starten","description":"Stuurt de browser door naar Google (OpenID Connect met PKCE). Alleen voor bestaande gebruikers. 404 als Google-inloggen niet is ingesteld. De app start met `?client=app&code_challenge=…` (S256, minstens 43 tekens) en komt terug op `instntstudio://login?code=…`, `?challenge=…` (tweestap) of `?error=…`.\n\n**Toegang:** Geen inlog","security":[],"x-studio-auth":"public","responses":{"302":{"description":"Doorsturen; het adres staat in Location.","headers":{"Location":{"schema":{"type":"string","format":"uri"}}}}}}},"/api/login/app":{"post":{"tags":["Account en inloggen"],"operationId":"post_login_app","summary":"App: code van na Google inwisselen","description":"Eenmalig en twee minuten geldig; een verkeerde verifier verbruikt de code ook.\n\n**Toegang:** Geen inlog","security":[],"x-studio-auth":"public","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"code":{"type":"string"},"code_verifier":{"type":"string","description":"Waarvan de app bij de start de S256-hash meegaf."}},"required":["code","code_verifier"]}}}},"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"token":{"type":"string"},"device_name":{"type":"string"}}}}}},"410":{"$ref":"#/components/responses/410"},"429":{"$ref":"#/components/responses/429"}}}},"/api/login/google/callback":{"get":{"tags":["Account en inloggen"],"operationId":"get_login_google_callback","summary":"Terugkeer van Google","description":"Google stuurt de browser hierheen. Een kleine pagina zet de sessie en gaat terug naar de app.\n\n**Toegang:** Geen inlog","security":[],"x-studio-auth":"public","responses":{"200":{"description":"Gelukt.","content":{"text/html":{"schema":{"type":"string"}}}}}}},"/api/logout":{"post":{"tags":["Account en inloggen"],"operationId":"post_logout","summary":"Uitloggen","description":"Beëindigt de sessie en wist het cookie.\n\n**Toegang:** Alleen met een sessie in de app, niet met een API-sleutel","security":[{"session":[]}],"x-studio-auth":"session","responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true}}}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/setup":{"post":{"tags":["Account en inloggen"],"operationId":"post_setup","summary":"Eerste gebruiker aanmaken","description":"Werkt alleen zolang er nog geen gebruikers zijn (installatie); daarna `403 already_installed`.\n\n**Toegang:** Geen inlog","security":[],"x-studio-auth":"public","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"email":{"type":"string","format":"email"},"name":{"type":"string"},"password":{"type":"string","description":"Minstens 10 tekens."}},"required":["email","password"]}}}},"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true}}}}}}}}},"/api/signup":{"post":{"tags":["Account en inloggen"],"operationId":"post_signup","summary":"Aanmelden als bureau (proefperiode)","description":"Stuurt een bevestigingsmail. Geeft altijd `sent: true`, ook als het adres al bestaat. 404 zolang aanmelden dicht staat.\n\n**Toegang:** Geen inlog","security":[],"x-studio-auth":"public","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"email":{"type":"string","format":"email"},"name":{"type":"string"},"agency":{"type":"string"},"password":{"type":"string","description":"Minstens 10 tekens."},"partner":{"type":"string","description":"Partnercode."},"terms":{"type":"boolean","description":"Akkoord met voorwaarden en verwerkersovereenkomst; versie en tijd worden vastgelegd."}},"required":["email","name","agency","password","terms"]}}}},"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"sent":{"type":"boolean"}}}}}}}}},"/api/signup/confirm":{"post":{"tags":["Account en inloggen"],"operationId":"post_signup_confirm","summary":"Aanmelding bevestigen","description":"Maakt gebruiker en workspace en start een sessie. `410 signup_expired` na 24 uur, `409 exists` als het adres al een account heeft.\n\n**Toegang:** Geen inlog","security":[],"x-studio-auth":"public","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"token":{"type":"string"}},"required":["token"]}}}},"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true}}}}}}}}},"/api/invitation":{"get":{"tags":["Account en inloggen"],"operationId":"get_invitation","summary":"Uitnodiging bekijken","description":"**Toegang:** Geen inlog","security":[],"x-studio-auth":"public","parameters":[{"name":"token","in":"query","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"email":{"type":"string","format":"email"},"workspace":{"type":"string"},"project":{"type":["string","null"]},"existing_user":{"type":"boolean"}}}}}},"410":{"$ref":"#/components/responses/410"}}},"post":{"tags":["Account en inloggen"],"operationId":"post_invitation","summary":"Uitnodiging aannemen","description":"Nieuwe gebruiker: naam en wachtwoord kiezen. Bestaande gebruiker: met het eigen wachtwoord bevestigen, of zonder als je al ingelogd bent als die gebruiker. Je kunt bij meerdere workspaces horen. Start een sessie in de workspace van de uitnodiging.\n\n**Toegang:** Geen inlog","security":[],"x-studio-auth":"public","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"token":{"type":"string"},"password":{"type":"string"},"name":{"type":"string"}},"required":["token","password"]}}}},"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true}}}}}},"401":{"$ref":"#/components/responses/401"},"409":{"$ref":"#/components/responses/409"},"410":{"$ref":"#/components/responses/410"},"422":{"$ref":"#/components/responses/422"}}}},"/api/password/forgot":{"post":{"tags":["Account en inloggen"],"operationId":"post_password_forgot","summary":"Herstellink aanvragen","description":"Antwoordt altijd hetzelfde, zodat niet te zien is welke adressen een account hebben. De link werkt 60 minuten.\n\n**Toegang:** Geen inlog","security":[],"x-studio-auth":"public","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"email":{"type":"string","format":"email"}},"required":["email"]}}}},"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true}}}}}}}}},"/api/password/reset":{"post":{"tags":["Account en inloggen"],"operationId":"post_password_reset","summary":"Nieuw wachtwoord instellen","description":"Beëindigt alle andere sessies en start een nieuwe.\n\n**Toegang:** Geen inlog","security":[],"x-studio-auth":"public","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"token":{"type":"string"},"password":{"type":"string","description":"Minstens 10 tekens, hooguit 72 bytes, niet uit een bekend datalek."}},"required":["token","password"]}}}},"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true}}}}}},"410":{"$ref":"#/components/responses/410"},"422":{"$ref":"#/components/responses/422"}}}},"/api/password/change":{"post":{"tags":["Account en inloggen"],"operationId":"post_password_change","summary":"Wachtwoord wijzigen","description":"Andere sessies vervallen; deze blijft geldig.\n\n**Wie:** De ingelogde gebruiker zelf.\n\n**Toegang:** Alleen met een sessie in de app, niet met een API-sleutel","security":[{"session":[]}],"x-studio-auth":"session","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"current":{"type":"string"},"password":{"type":"string","description":"Minstens 10 tekens, hooguit 72 bytes, niet uit een bekend datalek."}},"required":["current","password"]}}}},"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true}}}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/two-factor":{"post":{"tags":["Account en inloggen"],"operationId":"post_two_factor","summary":"Tweestapsverificatie beheren","description":"**Wie:** De ingelogde gebruiker zelf.\n\n**Toegang:** Alleen met een sessie in de app, niet met een API-sleutel","security":[{"session":[]}],"x-studio-auth":"session","requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"action":{"const":"status"}},"required":["action"],"title":"status"},{"type":"object","properties":{"action":{"const":"setup"}},"required":["action"],"title":"setup","description":"Nieuw geheim; nog niet actief tot `confirm`."},{"type":"object","properties":{"action":{"const":"confirm"},"code":{"type":"string"}},"required":["action","code"],"title":"confirm","description":"Zet tweestap aan en beëindigt andere sessies."},{"type":"object","properties":{"action":{"const":"disable"},"password":{"type":"string","description":"Verplicht als je een wachtwoord hebt."},"code":{"type":"string"}},"required":["action","code"],"title":"disable","description":"Kan niet als tweestap verplicht is."},{"type":"object","properties":{"action":{"const":"recovery_codes"},"password":{"type":"string","description":"Verplicht als je een wachtwoord hebt."},"code":{"type":"string","description":"Verplicht zonder wachtwoord."}},"required":["action"],"title":"recovery_codes"}]}}}},"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"ok":{"const":true},"enabled":{"type":"boolean"},"required":{"type":"boolean"},"enforced":{"type":"boolean","description":"Verplicht: beheerder, of de workspace eist het."},"has_password":{"type":"boolean"},"recovery_codes_left":{"type":"integer"}},"title":"status"},{"type":"object","properties":{"ok":{"const":true},"secret":{"type":"string"},"uri":{"type":"string"}},"title":"setup"},{"type":"object","properties":{"ok":{"const":true},"recovery_codes":{"type":"array","items":{"type":"string"}}},"title":"confirm"},{"type":"object","properties":{"ok":{"const":true}},"title":"disable"},{"type":"object","properties":{"ok":{"const":true},"recovery_codes":{"type":"array","items":{"type":"string"}}},"title":"recovery_codes"}]}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/tokens":{"get":{"tags":["Account en inloggen"],"operationId":"get_tokens","summary":"Eigen API-sleutels","description":"**Wie:** De ingelogde gebruiker zelf.\n\n**Toegang:** Alleen met een sessie in de app, niet met een API-sleutel","security":[{"session":[]}],"x-studio-auth":"session","responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"tokens":{"type":"array","items":{"type":"object"},"description":"id, name, scope, last_used_at, created_at, archived_at, workspace_id, workspace"}}}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}},"post":{"tags":["Account en inloggen"],"operationId":"post_tokens","summary":"API-sleutel maken of intrekken","description":"**Wie:** De ingelogde gebruiker zelf.\n\n**Toegang:** Alleen met een sessie in de app, niet met een API-sleutel","security":[{"session":[]}],"x-studio-auth":"session","requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"action":{"const":"create"},"name":{"type":"string"},"scope":{"type":"string","enum":["mcp","read","write"],"description":"Standaard mcp."}},"required":["action"],"title":"create","description":"De sleutel werkt alleen in de workspace waarin hij is gemaakt. Een oudere sleutel zonder workspace kiest er een met de header `X-Workspace: <id>`."},{"type":"object","properties":{"action":{"const":"delete"},"id":{"type":"integer"}},"required":["action","id"],"title":"delete"}]}}}},"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"ok":{"const":true},"token":{"type":"string","description":"Eén keer te zien."}},"title":"create"},{"type":"object","properties":{"ok":{"const":true}},"title":"delete"}]}}}},"401":{"$ref":"#/components/responses/401"},"402":{"$ref":"#/components/responses/402"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/devices":{"get":{"tags":["Account en inloggen"],"operationId":"get_devices","summary":"Toestellen voor pushmeldingen","description":"**Wie:** De ingelogde gebruiker zelf.\n\n**Toegang:** Sessie of API-sleutel (lezen of schrijven)","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"devices":{"type":"array","items":{"type":"object"},"description":"id, environment, created_at, last_sent_at"}}}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}},"post":{"tags":["Account en inloggen"],"operationId":"post_devices","summary":"Toestel aan- of afmelden voor push","description":"**Wie:** De ingelogde gebruiker zelf.\n\n**Toegang:** Sessie of API-sleutel met schrijfrecht","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"action":{"const":"register"},"token":{"type":"string","description":"APNs-toesteltoken, hex."},"environment":{"type":"string","enum":["sandbox","production"]}},"required":["action","token"],"title":"register"},{"type":"object","properties":{"action":{"const":"remove"},"token":{"type":"string"}},"required":["action","token"],"title":"remove"}]}}}},"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"ok":{"const":true}},"title":"register"},{"type":"object","properties":{"ok":{"const":true}},"title":"remove"}]}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/view-as":{"post":{"tags":["Account en inloggen"],"operationId":"post_view_as","summary":"Meekijken als klant","description":"Zolang het meekijken loopt, kan er niets gewijzigd worden.\n\n**Wie:** Alleen de eigenaar van de workspace.\n\n**Toegang:** Alleen met een sessie in de app, niet met een API-sleutel","security":[{"session":[]}],"x-studio-auth":"session","requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"action":{"const":"start"},"user_id":{"type":"integer","description":"Een klant van de eigen workspace."}},"required":["action","user_id"],"title":"start"},{"type":"object","properties":{"action":{"const":"stop"}},"required":["action"],"title":"stop"}]}}}},"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"ok":{"const":true}},"title":"start"},{"type":"object","properties":{"ok":{"const":true}},"title":"stop"}]}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/profile":{"get":{"tags":["Account en inloggen"],"operationId":"get_profile","summary":"Je eigen account","description":"**Wie:** De ingelogde gebruiker zelf.\n\n**Toegang:** Alleen met een sessie in de app, niet met een API-sleutel","security":[{"session":[]}],"x-studio-auth":"session","responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"profile":{"type":"object","description":"name, email, timezone, avatar, has_password, google, created_at"},"pending_email":{"type":["object","null"],"description":"email, expires_at"},"reauth":{"type":"string","enum":["password","code","google","none"],"description":"Hoe je je identiteit bevestigt bij een gevoelige actie."},"notify":{"type":"array","items":{"type":"object"},"description":"key, label, on"},"quiet_hours":{"type":["object","null"],"description":"Stille uren voor push: from en to, HH:MM in je eigen tijdzone."},"sessions":{"type":"array","items":{"type":"object"},"description":"key, kind (browser|app), device, network, via, created_at, last_used_at, last_used_label, current"},"workspaces":{"type":"array","items":{"type":"object"},"description":"id, name, role, suspended_at"},"delete_blockers":{"type":"array","items":{"type":"string"},"description":"Workspaces waar je eigenaar van bent; zolang die er zijn, kan je account niet weg."},"timezones":{"type":"array","items":{"type":"string"}}}}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}},"post":{"tags":["Account en inloggen"],"operationId":"post_profile","summary":"Je account wijzigen","description":"**Wie:** De ingelogde gebruiker zelf.\n\n**Toegang:** Alleen met een sessie in de app, niet met een API-sleutel","security":[{"session":[]}],"x-studio-auth":"session","requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"action":{"const":"profile"},"name":{"type":"string"},"timezone":{"type":["string","null"],"description":"IANA-naam, bijv. Europe/Amsterdam. Geldt voor tijden in mails en lijsten."}},"required":["action","name"],"title":"profile"},{"type":"object","properties":{"action":{"const":"avatar"},"avatar":{"type":"string","format":"binary","description":"JPG, PNG, WebP of GIF tot 3 MB; wordt 160 × 160 WebP zonder metadata."}},"required":["action","avatar"],"title":"avatar","description":"Multipart-formulier."},{"type":"object","properties":{"action":{"const":"avatar_delete"}},"required":["action"],"title":"avatar_delete"},{"type":"object","properties":{"action":{"const":"email"},"email":{"type":"string","format":"email"},"password":{"type":"string","description":"Je wachtwoord; zonder wachtwoord (alleen Google) een code uit de app, of eerst opnieuw inloggen met Google."},"code":{"type":"string"}},"required":["action","email"],"title":"email","description":"Stuurt een link naar het nieuwe adres; tot die is geopend blijft het oude gelden."},{"type":"object","properties":{"action":{"const":"email_cancel"}},"required":["action"],"title":"email_cancel"},{"type":"object","properties":{"action":{"const":"notify"},"prefs":{"type":"object","description":"Per soort aan of uit: alerts, anomalies, digest, automations. Facturen en beveiliging kun je niet uitzetten."}},"required":["action","prefs"],"title":"notify"},{"type":"object","properties":{"action":{"const":"quiet_hours"},"from":{"type":"string","description":"HH:MM; zonder from en to staan de stille uren uit."},"to":{"type":"string"}},"required":["action"],"title":"quiet_hours","description":"Pushmeldingen komen dan zonder geluid binnen."},{"type":"object","properties":{"action":{"const":"session_revoke"},"key":{"type":"string"}},"required":["action","key"],"title":"session_revoke","description":"Bij een app ook de pushmeldingen naar dat toestel."},{"type":"object","properties":{"action":{"const":"sessions_revoke_others"}},"required":["action"],"title":"sessions_revoke_others"},{"type":"object","properties":{"action":{"const":"reauth"},"password":{"type":"string","description":"Je wachtwoord; zonder wachtwoord (alleen Google) een code uit de app, of eerst opnieuw inloggen met Google."},"code":{"type":"string"}},"required":["action"],"title":"reauth","description":"Bevestigt je identiteit voor tien minuten."},{"type":"object","properties":{"action":{"const":"leave"},"workspace_id":{"type":"integer"}},"required":["action","workspace_id"],"title":"leave","description":"Niet als eigenaar: draag eerst het eigendom over."},{"type":"object","properties":{"action":{"const":"delete_account"},"password":{"type":"string","description":"Je wachtwoord; zonder wachtwoord (alleen Google) een code uit de app, of eerst opnieuw inloggen met Google."},"code":{"type":"string"}},"required":["action"],"title":"delete_account","description":"Anonimiseert je account en logt uit. Niet zolang je eigenaar bent van een workspace."}]}}}},"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"ok":{"const":true}},"title":"profile"},{"type":"object","properties":{"ok":{"const":true},"avatar":{"type":"string"}},"title":"avatar"},{"type":"object","properties":{"ok":{"const":true}},"title":"avatar_delete"},{"type":"object","properties":{"ok":{"const":true},"mailed":{"type":"boolean"},"pending_email":{"type":["object","null"],"description":"email, expires_at"}},"title":"email"},{"type":"object","properties":{"ok":{"const":true}},"title":"email_cancel"},{"type":"object","properties":{"ok":{"const":true},"prefs":{"type":"object"}},"title":"notify"},{"type":"object","properties":{"ok":{"const":true},"quiet_hours":{"type":["object","null"],"description":"from, to"}},"title":"quiet_hours"},{"type":"object","properties":{"ok":{"const":true},"sessions":{"type":"array","items":{"type":"object"}}},"title":"session_revoke"},{"type":"object","properties":{"ok":{"const":true},"revoked":{"type":"integer"},"sessions":{"type":"array","items":{"type":"object"}}},"title":"sessions_revoke_others"},{"type":"object","properties":{"ok":{"const":true}},"title":"reauth"},{"type":"object","properties":{"ok":{"const":true}},"title":"leave"},{"type":"object","properties":{"ok":{"const":true}},"title":"delete_account"}]}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/email/confirm":{"post":{"tags":["Account en inloggen"],"operationId":"post_email_confirm","summary":"Nieuw e-mailadres bevestigen","description":"De link uit de mail naar het nieuwe adres (24 uur). Het oude adres krijgt een mail met een link om terug te draaien.\n\n**Toegang:** Geen inlog; het geheim zit in het adres","security":[],"x-studio-auth":"url","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"token":{"type":"string"}},"required":["token"]}}}},"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"email":{"type":"string","format":"email"}}}}}},"404":{"$ref":"#/components/responses/404"},"410":{"$ref":"#/components/responses/410"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/email/undo":{"post":{"tags":["Account en inloggen"],"operationId":"post_email_undo","summary":"E-mailwijziging terugdraaien","description":"De link uit de mail naar het oude adres (24 uur). Zet het oude adres terug, beëindigt alle sessies en trekt API-sleutels in.\n\n**Toegang:** Geen inlog; het geheim zit in het adres","security":[],"x-studio-auth":"url","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"token":{"type":"string"}},"required":["token"]}}}},"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"email":{"type":"string","format":"email"}}}}}},"404":{"$ref":"#/components/responses/404"},"410":{"$ref":"#/components/responses/410"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/access":{"get":{"tags":["Workspace, team en abonnement"],"operationId":"get_access","summary":"Team, klanten en uitnodigingen","description":"**Wie:** Eigenaar of lid; kijkers en klanten krijgen 403.\n\n**Toegang:** Alleen met een sessie in de app, niet met een API-sleutel","security":[{"session":[]}],"x-studio-auth":"session","parameters":[{"name":"project_id","in":"query","required":false,"schema":{"type":"integer"},"description":"Met project: de klanten van dat project. Zonder: het team."}],"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"team":{"type":"array","items":{"type":"object"},"description":"id, email, name, role, last_login_at, two_factor, avatar, archived"},"clients":{"type":"array","items":{"type":"object"},"description":"id, email, name, last_login_at, projects"},"require_two_factor":{"type":"boolean"},"is_owner":{"type":"boolean"},"me":{"type":"integer"},"people":{"type":"array","items":{"type":"object"},"description":"id, email, name, preset, permissions, last_login_at, since"},"invitations":{"type":"array","items":{"type":"object"},"description":"id, email, role, preset, expires_at, created_at"},"presets":{"type":"array","items":{"type":"object"},"description":"id, label, permissions"}}}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}},"post":{"tags":["Workspace, team en abonnement"],"operationId":"post_access","summary":"Uitnodigen en toegang regelen","description":"**Wie:** Eigenaar of lid; kijkers en klanten krijgen 403.\n\n**Toegang:** Alleen met een sessie in de app, niet met een API-sleutel","security":[{"session":[]}],"x-studio-auth":"session","requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"action":{"const":"invite"},"email":{"type":"string","format":"email"},"role":{"type":"string","enum":["client","member","viewer"],"description":"Standaard client. Lid of kijker uitnodigen kan alleen de eigenaar."},"project_id":{"type":"integer","description":"Verplicht voor een klant."},"preset":{"type":"string","enum":["client_readonly","client_approver","client_limited"]}},"required":["action","email"],"title":"invite","description":"Iemand die al bij een ander bureau hoort, kan ook worden uitgenodigd; hij wisselt dan tussen workspaces."},{"type":"object","properties":{"action":{"const":"update"},"project_id":{"type":"integer"},"user_id":{"type":"integer"},"preset":{"type":"string","enum":["client_readonly","client_approver","client_limited"]}},"required":["action","project_id","user_id","preset"],"title":"update"},{"type":"object","properties":{"action":{"const":"remove"},"project_id":{"type":"integer"},"user_id":{"type":"integer"}},"required":["action","project_id","user_id"],"title":"remove","description":"De klant verliest de toegang tot dit project."},{"type":"object","properties":{"action":{"const":"revoke"},"invitation_id":{"type":"integer"}},"required":["action","invitation_id"],"title":"revoke"},{"type":"object","properties":{"action":{"const":"resend"},"invitation_id":{"type":"integer"}},"required":["action","invitation_id"],"title":"resend","description":"Nieuwe link (de oude vervalt), weer 14 dagen geldig."},{"type":"object","properties":{"action":{"const":"remove_member"},"user_id":{"type":"integer"}},"required":["action","user_id"],"title":"remove_member","description":"Haalt iemand uit de workspace, met een mail. De eigenaar voor teamleden; eigenaar of lid voor klanten."},{"type":"object","properties":{"action":{"const":"change_role"},"user_id":{"type":"integer"},"role":{"type":"string","enum":["member","viewer"]}},"required":["action","user_id","role"],"title":"change_role","description":"Alleen de eigenaar van de workspace."},{"type":"object","properties":{"action":{"const":"transfer"},"user_id":{"type":"integer","description":"Iemand uit het team."},"password":{"type":"string","description":"Je wachtwoord; zonder wachtwoord (alleen Google) een code uit de app, of eerst opnieuw inloggen met Google."},"code":{"type":"string"}},"required":["action","user_id"],"title":"transfer","description":"Eén eigenaar per workspace: de nieuwe wordt eigenaar, jij wordt teamlid. Beiden krijgen een mail. Alleen de eigenaar van de workspace."},{"type":"object","properties":{"action":{"const":"require_two_factor"},"on":{"type":"boolean"}},"required":["action","on"],"title":"require_two_factor","description":"Teamleden zonder tweestap kunnen daarna alleen nog tweestap instellen. Eerst zelf aanzetten. Alleen de eigenaar van de workspace."}]}}}},"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"ok":{"const":true},"invitation_id":{"type":"integer"},"link":{"type":"string","format":"uri","description":"De uitnodigingslink, ook als de mail niet aankomt."},"mailed":{"type":"boolean"},"granted":{"type":"boolean","description":"Al klant van dit bureau: meteen toegang, geen uitnodiging."}},"title":"invite"},{"type":"object","properties":{"ok":{"const":true}},"title":"update"},{"type":"object","properties":{"ok":{"const":true}},"title":"remove"},{"type":"object","properties":{"ok":{"const":true}},"title":"revoke"},{"type":"object","properties":{"ok":{"const":true},"link":{"type":"string","format":"uri"},"mailed":{"type":"boolean"}},"title":"resend"},{"type":"object","properties":{"ok":{"const":true}},"title":"remove_member"},{"type":"object","properties":{"ok":{"const":true}},"title":"change_role"},{"type":"object","properties":{"ok":{"const":true}},"title":"transfer"},{"type":"object","properties":{"ok":{"const":true}},"title":"require_two_factor"}]}}}},"401":{"$ref":"#/components/responses/401"},"402":{"$ref":"#/components/responses/402"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/workspace/export":{"get":{"tags":["Workspace, team en abonnement"],"operationId":"get_workspace_export","summary":"Alle gegevens van de workspace exporteren","description":"Een JSON-bestand als download. Werkt ook met een leessleutel van de eigenaar.\n\n**Wie:** Alleen de eigenaar van de workspace.\n\n**Toegang:** Alleen met een sessie in de app, niet met een API-sleutel","security":[{"session":[]}],"x-studio-auth":"session","responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true}},"additionalProperties":true}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/workspace/delete":{"post":{"tags":["Workspace, team en abonnement"],"operationId":"post_workspace_delete","summary":"Workspace verwijderen","description":"Vraagt de naam van de workspace en je identiteit. `409 has_invoices` zolang er facturen zijn (bewaarplicht).\n\n**Wie:** Alleen de eigenaar van de workspace.\n\n**Toegang:** Alleen met een sessie in de app, niet met een API-sleutel","security":[{"session":[]}],"x-studio-auth":"session","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string"},"password":{"type":"string","description":"Je wachtwoord; zonder wachtwoord (alleen Google) een code uit de app, of eerst opnieuw inloggen met Google."},"code":{"type":"string"}},"required":["name"]}}}},"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true}}}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/workspace/switch":{"post":{"tags":["Workspace, team en abonnement"],"operationId":"post_workspace_switch","summary":"Andere workspace kiezen","description":"Geldt voor deze sessie en wordt onthouden voor de volgende login. Alleen een workspace waar je lid van bent.\n\n**Wie:** De ingelogde gebruiker zelf.\n\n**Toegang:** Alleen met een sessie in de app, niet met een API-sleutel","security":[{"session":[]}],"x-studio-auth":"session","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"workspace_id":{"type":"integer"}},"required":["workspace_id"]}}}},"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"workspace_id":{"type":"integer"}}}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/workspace/create":{"post":{"tags":["Workspace, team en abonnement"],"operationId":"post_workspace_create","summary":"Nieuwe workspace","description":"Je wordt eigenaar. Met een proefperiode, tenzij je die al eens had als eigenaar; dan kies je meteen een plan.\n\n**Wie:** De ingelogde gebruiker zelf.\n\n**Toegang:** Alleen met een sessie in de app, niet met een API-sleutel","security":[{"session":[]}],"x-studio-auth":"session","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string"}},"required":["name"]}}}},"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"workspace_id":{"type":"integer"},"trial":{"type":"boolean"}}}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/workspace/rename":{"post":{"tags":["Workspace, team en abonnement"],"operationId":"post_workspace_rename","summary":"Naam van de workspace wijzigen","description":"Alleen de eigenaar, niet met een API-sleutel.\n\n**Wie:** Alleen de eigenaar van de workspace.\n\n**Toegang:** Alleen met een sessie in de app, niet met een API-sleutel","security":[{"session":[]}],"x-studio-auth":"session","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string"}},"required":["name"]}}}},"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"name":{"type":"string"}}}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/logboek":{"get":{"tags":["Workspace, team en abonnement"],"operationId":"get_logboek","summary":"Logboek van de workspace","description":"Wie deed wat, twee jaar terug. Met `format=csv` als bestand (hooguit 10.000 regels).\n\n**Wie:** Alleen de eigenaar van de workspace.\n\n**Toegang:** Alleen met een sessie in de app, niet met een API-sleutel","security":[{"session":[]}],"x-studio-auth":"session","parameters":[{"name":"user_id","in":"query","required":false,"schema":{"type":"integer"}},{"name":"group","in":"query","required":false,"schema":{"type":"string","enum":["toegang","account","abonnement","werk","koppelingen","mail"]}},{"name":"from","in":"query","required":false,"schema":{"type":"string","format":"date"}},{"name":"to","in":"query","required":false,"schema":{"type":"string","format":"date"}},{"name":"page","in":"query","required":false,"schema":{"type":"integer"}},{"name":"format","in":"query","required":false,"schema":{"type":"string","enum":["csv"]}}],"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"entries":{"type":"array","items":{"type":"object"},"description":"id, at, action, label, subject, user, details"},"total":{"type":"integer"},"page":{"type":"integer"},"per_page":{"type":"integer"},"retention_days":{"type":"integer"},"groups":{"type":"array","items":{"type":"object"},"description":"key, label"},"people":{"type":"array","items":{"type":"object"},"description":"id, name, email"}}}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/branding":{"get":{"tags":["Workspace, team en abonnement"],"operationId":"get_branding","summary":"Huisstijl van het bureau en een project","description":"**Wie:** Alleen het team (eigenaar, lid of kijker); klanten krijgen 403.\n\n**Toegang:** Sessie of API-sleutel (lezen of schrijven)","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","parameters":[{"name":"project_id","in":"query","required":false,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"workspace":{"type":"object","description":"logo, color, custom_domain, domain_status"},"project":{"type":["object","null"],"description":"logo, color"}}}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}},"post":{"tags":["Workspace, team en abonnement"],"operationId":"post_branding","summary":"Huisstijl en eigen domein instellen","description":"**Wie:** Eigenaar of lid; kijkers en klanten krijgen 403.\n\n**Toegang:** Sessie of API-sleutel met schrijfrecht","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"action":{"const":"save"},"project_id":{"type":"integer","description":"Zonder project: het bureau (alleen de eigenaar)."},"logo":{"type":"string","description":"PNG, JPEG of WebP als base64 of data-URL, hooguit 300 kB."},"color":{"type":"string"},"remove_logo":{"type":"boolean"}},"required":["action"],"title":"save"},{"type":"object","properties":{"action":{"const":"domain"},"domain":{"type":"string","description":"Subdomein van je eigen domein; leeg haalt het weg."}},"required":["action"],"title":"domain","description":"Alleen de eigenaar van de workspace."},{"type":"object","properties":{"action":{"const":"domain_check"}},"required":["action"],"title":"domain_check","description":"Alleen de eigenaar van de workspace."}]}}}},"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"ok":{"const":true}},"title":"save"},{"type":"object","properties":{"ok":{"const":true},"domain":{"type":["string","null"]},"status":{"type":"string"},"target":{"type":"string"}},"title":"domain"},{"type":"object","properties":{"ok":{"const":true},"domain":{"type":["string","null"]},"status":{"type":"string"},"target":{"type":"string"}},"title":"domain_check"}]}}}},"401":{"$ref":"#/components/responses/401"},"402":{"$ref":"#/components/responses/402"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/billing":{"get":{"tags":["Workspace, team en abonnement"],"operationId":"get_billing","summary":"Abonnement, factuurgegevens en facturen","description":"**Wie:** Alleen de eigenaar van de workspace.\n\n**Toegang:** Alleen met een sessie in de app, niet met een API-sleutel","security":[{"session":[]}],"x-studio-auth":"session","responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"details":{"type":["object","null"],"description":"name, address, postcode, city, country, vat_number, email, cc_email, reference"},"interval":{"type":"string"},"yearly_from":{"type":["string","null"],"format":"date"},"price":{"type":["object","null"],"description":"month, year, label"},"exempt":{"type":"boolean"},"vat":{"type":["object","null"],"description":"verified, checked_at"},"payments":{"type":"object","description":"online, mode (off, test, live, wrong)"},"mandate":{"type":"object","description":"active, method (directdebit, creditcard), details (gemaskeerd / masked), status, methods"},"suspended":{"type":["string","null"]},"invoices":{"type":"array","items":{"type":"object"},"description":"id, number, period, period_label, issued_on, due_on, gross_cents, refunded_cents, credited_cents, due_cents, status (open, paid, refunded, chargeback, credited, credit), last_payment_status, credit_of, credit_of_number, paid_at, pay_url"},"subscription":{"type":"object","description":"state (proef, actief, opzegging, opgezegd, verlopen, geschorst, gepauzeerd), plan, label, interval, trial_ends_at, paid_until, term, cancel_from, pending, data_delete_on, data_purged_at, pause (?object: since, until, cancelled), pause_blocked (?string), pause_max_months"},"plans":{"type":"array","items":{"type":"object"},"description":"key, label, price, price_year, price_next (?object: from, price, price_year), pitch, limits, ads_modes, white_label, over (wat niet past / what does not fit)"},"usage":{"type":"object"},"addons":{"type":"array","items":{"type":"object"},"description":"key, label, price (euro per maand per stuk / euro per month each), limit, amount, quantity, available"},"archived":{"type":"object","description":"projects, team, keywords, dashboards, api_tokens, automations"},"upcoming":{"type":"array","items":{"type":"object"},"description":"date, period_label, lines, net_cents, vat_cents, gross_cents"},"history":{"type":"array","items":{"type":"object"},"description":"id, text, kind, pending, note, created_at"},"terms":{"type":"object","description":"version, accepted_version, accepted_at, required, deadline, blocking, terms_url, dpa_url"},"has_password":{"type":"boolean"}}}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}},"post":{"tags":["Workspace, team en abonnement"],"operationId":"post_billing","summary":"Abonnement wijzigen, opzeggen, factuurgegevens","description":"Groter plan: direct, per dag of het verschil voor de rest van het jaar. Kleiner plan of terug naar per maand: na de betaalde periode. Een kleiner plan, opzeggen en pauzeren vragen herbevestigen: `password`, of zonder wachtwoord `code` uit de authenticator of een verse login met Google (hooguit tien minuten oud).\n\n**Wie:** Alleen de eigenaar van de workspace.\n\n**Toegang:** Alleen met een sessie in de app, niet met een API-sleutel","security":[{"session":[]}],"x-studio-auth":"session","requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"action":{"const":"details"},"name":{"type":"string"},"address":{"type":"string"},"postcode":{"type":"string"},"city":{"type":"string"},"country":{"type":"string","description":"Landcode, standaard NL."},"vat_number":{"type":"string","description":"Buiten NL in de EU gecontroleerd bij VIES; alleen dan wordt de btw verlegd."},"email":{"type":"string","format":"email"},"cc_email":{"type":"string","format":"email","description":"Krijgt een kopie van elke factuur en herinnering."},"reference":{"type":"string","description":"Eigen kenmerk (inkoopordernummer) op de factuur."}},"required":["action","name","address","postcode","city","email"],"title":"details"},{"type":"object","properties":{"action":{"const":"yearly"}},"required":["action"],"title":"yearly","description":"Per jaar betalen vanaf de eerste van de volgende maand."},{"type":"object","properties":{"action":{"const":"preview"},"plan":{"type":"string","enum":["solo","inzicht","copiloot","begeleid"]},"interval":{"type":"string","enum":["maand","jaar"]}},"required":["action","plan","interval"],"title":"preview","description":"Wat er zou gebeuren, zonder iets te wijzigen."},{"type":"object","properties":{"action":{"const":"change"},"plan":{"type":"string","enum":["solo","inzicht","copiloot","begeleid"]},"interval":{"type":"string","enum":["maand","jaar"]},"archive":{"type":"object","description":"Per onderdeel de id's die apart gaan (projects, team, clients, api_tokens, automations, keywords:<project>, dashboards:<project>)."},"password":{"type":"string","description":"Bij een kleiner plan: je wachtwoord, of zonder wachtwoord een code uit de app (of eerst opnieuw inloggen met Google)."},"code":{"type":"string"}},"required":["action","plan","interval"],"title":"change"},{"type":"object","properties":{"action":{"const":"cancel"},"password":{"type":"string","description":"Je wachtwoord, of zonder wachtwoord een code uit de app (of eerst opnieuw inloggen met Google)."},"code":{"type":"string"}},"required":["action"],"title":"cancel","description":"Opzeggen per einde van de betaalde periode."},{"type":"object","properties":{"action":{"const":"resume"}},"required":["action"],"title":"resume","description":"Een opzegging intrekken die nog niet is ingegaan."},{"type":"object","properties":{"action":{"const":"withdraw"}},"required":["action"],"title":"withdraw","description":"Een geplande wijziging (kleiner plan, andere betaalwijze) intrekken; alles blijft zoals het nu is. Niet voor een opzegging, een pauze of wat beheer plande."},{"type":"object","properties":{"action":{"const":"restore"},"kind":{"type":"string","enum":["projects","team","keywords","dashboards","api_tokens","automations"]},"id":{"type":"string"}},"required":["action","kind","id"],"title":"restore","description":"Iets dat apart staat terugzetten, als het plan er ruimte voor heeft."},{"type":"object","properties":{"action":{"const":"terms"}},"required":["action"],"title":"terms","description":"Akkoord met de huidige voorwaarden en verwerkersovereenkomst."},{"type":"object","properties":{"action":{"const":"mandate_setup"},"method":{"type":"string","enum":["ideal","bancontact","creditcard"]}},"required":["action","method"],"title":"mandate_setup","description":"Automatisch betalen: een eerste betaling bij Mollie geeft een machtiging. Staat er een factuur open, dan is dat de eerste betaling; anders € 0,00 (creditcard) of € 0,01 die meteen terug gaat."},{"type":"object","properties":{"action":{"const":"mandate_revoke"}},"required":["action"],"title":"mandate_revoke","description":"Automatisch betalen uitzetten; facturen komen weer met een betaallink."},{"type":"object","properties":{"action":{"const":"pause"},"months":{"type":"integer","description":"1 tot 3."},"password":{"type":"string","description":"Of `code` / een verse Google-login, zie herbevestigen."}},"required":["action","months"],"title":"pause","description":"Pauzeren vanaf vandaag: niets betalen, alleen kijken, geen achtergrondwerk. Alleen bij betalen per maand, één keer per twaalf maanden."},{"type":"object","properties":{"action":{"const":"end_pause"}},"required":["action"],"title":"end_pause","description":"De pauze nu beëindigen; het abonnement gaat vandaag weer in."},{"type":"object","properties":{"action":{"const":"addon"},"addon":{"type":"string","description":"Sleutel uit `addons`."},"quantity":{"type":"integer","description":"0 tot 20; 0 = weg."}},"required":["action","addon","quantity"],"title":"addon","description":"Extra ruimte bovenop het plan, vanaf vandaag per dag op de maandfactuur. Minder mag alleen als alles nog past."}]}}}},"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"ok":{"const":true},"vat":{"type":"string","description":"valid, invalid, unavailable, n.v.t."},"message":{"type":["string","null"]}},"title":"details"},{"type":"object","properties":{"ok":{"const":true},"yearly_from":{"type":"string","format":"date"},"message":{"type":"string"}},"title":"yearly"},{"type":"object","properties":{"ok":{"const":true},"preview":{"type":"object","description":"rows, effective_from, immediate, kind, message, over, upgrade_cents, replaces"}},"title":"preview"},{"type":"object","properties":{"ok":{"const":true},"message":{"type":"string"},"effective_from":{"type":"string","format":"date"}},"title":"change"},{"type":"object","properties":{"ok":{"const":true},"ends_on":{"type":"string","format":"date"},"message":{"type":"string"}},"title":"cancel"},{"type":"object","properties":{"ok":{"const":true},"message":{"type":"string"}},"title":"resume"},{"type":"object","properties":{"ok":{"const":true},"message":{"type":"string"}},"title":"withdraw"},{"type":"object","properties":{"ok":{"const":true},"message":{"type":"string"}},"title":"restore"},{"type":"object","properties":{"ok":{"const":true},"terms":{"type":"object"}},"title":"terms"},{"type":"object","properties":{"ok":{"const":true},"checkout_url":{"type":"string","format":"uri"}},"title":"mandate_setup"},{"type":"object","properties":{"ok":{"const":true},"message":{"type":"string"}},"title":"mandate_revoke"},{"type":"object","properties":{"ok":{"const":true},"until":{"type":"string","format":"date"},"message":{"type":"string"}},"title":"pause"},{"type":"object","properties":{"ok":{"const":true},"message":{"type":"string"}},"title":"end_pause"},{"type":"object","properties":{"ok":{"const":true},"message":{"type":"string"},"addons":{"type":"array","items":{"type":"object"}}},"title":"addon"}]}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/billing/pdf":{"get":{"tags":["Workspace, team en abonnement"],"operationId":"get_billing_pdf","summary":"Factuur als PDF","description":"**Wie:** Alleen de eigenaar van de workspace.\n\n**Toegang:** Alleen met een sessie in de app, niet met een API-sleutel","security":[{"session":[]}],"x-studio-auth":"session","parameters":[{"name":"id","in":"query","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Gelukt.","content":{"application/pdf":{"schema":{"type":"string","format":"binary"}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/partner":{"get":{"tags":["Workspace, team en abonnement"],"operationId":"get_partner","summary":"Partnerprogramma: code, aangebrachte bureaus en commissie","description":"**Wie:** Alleen de eigenaar van de workspace.\n\n**Toegang:** Alleen met een sessie in de app, niet met een API-sleutel","security":[{"session":[]}],"x-studio-auth":"session","responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"partner":{"type":["object","null"],"description":"code, commission_pct, discount_pct, active, link, referred, commission"}}}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/werkwijzen":{"get":{"tags":["Workspace, team en abonnement"],"operationId":"get_werkwijzen","summary":"Werkwijzen van het eigen team","description":"**Wie:** Alleen het team (eigenaar, lid of kijker); klanten krijgen 403.\n\n**Toegang:** Sessie of API-sleutel (lezen of schrijven)","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","parameters":[{"name":"slug","in":"query","required":false,"schema":{"type":"string"},"description":"Eén werkwijze als HTML."}],"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"standards":{"type":"array","items":{"type":"object"}},"standard":{"type":"object"}}}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/admin":{"get":{"tags":["Workspace, team en abonnement"],"operationId":"get_admin","summary":"Beheer: workspaces, gebruikers, wachtrij, plannen","description":"**Wie:** Alleen platformbeheerders van instnt; anderen krijgen 404 of 403.\n\n**Toegang:** Alleen met een sessie in de app, niet met een API-sleutel","security":[{"session":[]}],"x-studio-auth":"session","responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"workspaces":{"type":"array","items":{"type":"object"}},"users":{"type":"array","items":{"type":"object"}},"queue":{"type":"object","description":"pending, oldest, failed"},"tables":{"type":"array","items":{"type":"object"}},"flags":{"type":"object"},"plans":{"type":"object"},"backup":{"type":["object","null"]},"plesk":{"type":"object"},"partners":{"type":"array","items":{"type":"object"}}}}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}},"post":{"tags":["Workspace, team en abonnement"],"operationId":"post_admin","summary":"Beheeracties","description":"**Wie:** Alleen platformbeheerders van instnt; anderen krijgen 404 of 403.\n\n**Toegang:** Alleen met een sessie in de app, niet met een API-sleutel","security":[{"session":[]}],"x-studio-auth":"session","requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"action":{"const":"feature"},"workspace_id":{"type":"integer"},"feature":{"type":"string"},"state":{"type":"string","enum":["aan","uit","standaard"]}},"required":["action","workspace_id","feature","state"],"title":"feature"},{"type":"object","properties":{"action":{"const":"retry"},"id":{"type":"integer","description":"Mislukte taak."}},"required":["action","id"],"title":"retry"},{"type":"object","properties":{"action":{"const":"forget"},"id":{"type":"integer"}},"required":["action","id"],"title":"forget"},{"type":"object","properties":{"action":{"const":"plan"},"workspace_id":{"type":"integer"},"plan":{"type":"string"},"trial_days":{"type":"integer"}},"required":["action","workspace_id","plan"],"title":"plan"},{"type":"object","properties":{"action":{"const":"interval"},"workspace_id":{"type":"integer"},"interval":{"type":"string","enum":["maand","jaar"]},"from":{"type":"string","format":"date","description":"De eerste van een maand."}},"required":["action","workspace_id","interval"],"title":"interval"},{"type":"object","properties":{"action":{"const":"trial_extend"},"workspace_id":{"type":"integer"},"days":{"type":"integer","description":"1–90, standaard 7; vanaf de huidige einddatum."}},"required":["action","workspace_id"],"title":"trial_extend"},{"type":"object","properties":{"action":{"const":"data_hold"},"workspace_id":{"type":"integer"},"until":{"type":["string","null"],"format":"date","description":"Opruimen uitstellen tot deze datum; leeg heft het op."}},"required":["action","workspace_id"],"title":"data_hold"},{"type":"object","properties":{"action":{"const":"partner"},"workspace_id":{"type":"integer"},"code":{"type":"string"},"commission_pct":{"type":"integer"},"discount_pct":{"type":"integer"},"active":{"type":"boolean"}},"required":["action","workspace_id","code"],"title":"partner"},{"type":"object","properties":{"action":{"const":"commission_paid"},"invoice_id":{"type":"integer"}},"required":["action","invoice_id"],"title":"commission_paid"},{"type":"object","properties":{"action":{"const":"mark_paid"},"invoice_id":{"type":"integer"},"paid_on":{"type":"string","format":"date","description":"Tussen factuurdatum en vandaag."},"reference":{"type":"string"}},"required":["action","invoice_id"],"title":"mark_paid","description":"Betaald per bankoverschrijving; heft een schorsing op."},{"type":"object","properties":{"action":{"const":"credit"},"invoice_id":{"type":"integer"},"amount_cents":{"type":"integer","description":"Zonder btw; leeg is de hele factuur."},"reason":{"type":"string"},"refund":{"type":"boolean","description":"Ook terugbetalen via Mollie."}},"required":["action","invoice_id","reason"],"title":"credit"},{"type":"object","properties":{"action":{"const":"remind"},"invoice_id":{"type":"integer"}},"required":["action","invoice_id"],"title":"remind"},{"type":"object","properties":{"action":{"const":"discount"},"workspace_id":{"type":"integer"},"kind":{"type":"string","enum":["pct","fixed"]},"value":{"type":"integer","description":"Procent (1–100) of centen per factuur."},"months":{"type":"integer"},"note":{"type":"string"},"starts_on":{"type":"string","format":"date"}},"required":["action","workspace_id","kind","value","note"],"title":"discount"},{"type":"object","properties":{"action":{"const":"discount_end"},"id":{"type":"integer"}},"required":["action","id"],"title":"discount_end"},{"type":"object","properties":{"action":{"const":"close_workspace"},"workspace_id":{"type":"integer"},"reason":{"type":"string"}},"required":["action","workspace_id"],"title":"close_workspace"},{"type":"object","properties":{"action":{"const":"unsuspend"},"workspace_id":{"type":"integer"}},"required":["action","workspace_id"],"title":"unsuspend"},{"type":"object","properties":{"action":{"const":"end_pause"},"workspace_id":{"type":"integer"}},"required":["action","workspace_id"],"title":"end_pause","description":"Een pauze beëindigen; de klant krijgt een mail."},{"type":"object","properties":{"action":{"const":"price_schedule"},"plan":{"type":"string"},"price":{"type":"number"},"price_year":{"type":"number"},"from":{"type":"string","format":"date","description":"Minstens 30 dagen vooruit; betalende klanten op dat plan krijgen een mail."}},"required":["action","plan","price","price_year","from"],"title":"price_schedule"},{"type":"object","properties":{"action":{"const":"price_cancel"},"id":{"type":"integer"}},"required":["action","id"],"title":"price_cancel"},{"type":"object","properties":{"action":{"const":"partner_payout_info"},"workspace_id":{"type":"integer"},"name":{"type":"string"},"iban":{"type":"string"}},"required":["action","workspace_id"],"title":"partner_payout_info"},{"type":"object","properties":{"action":{"const":"payout"}},"required":["action"],"title":"payout","description":"Alle open commissie van betaalde facturen in één uitbetaling."},{"type":"object","properties":{"action":{"const":"payout_paid"},"id":{"type":"integer"}},"required":["action","id"],"title":"payout_paid"},{"type":"object","properties":{"action":{"const":"plesk_add"},"url":{"type":"string","format":"uri"},"api_key":{"type":"string"},"name":{"type":"string"}},"required":["action","url","api_key"],"title":"plesk_add"},{"type":"object","properties":{"action":{"const":"plesk_check"},"id":{"type":"integer"}},"required":["action","id"],"title":"plesk_check"},{"type":"object","properties":{"action":{"const":"plesk_remove"},"id":{"type":"integer"}},"required":["action","id"],"title":"plesk_remove"}]}}}},"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"ok":{"const":true}},"title":"feature"},{"type":"object","properties":{"ok":{"const":true}},"title":"retry"},{"type":"object","properties":{"ok":{"const":true}},"title":"forget"},{"type":"object","properties":{"ok":{"const":true}},"title":"plan"},{"type":"object","properties":{"ok":{"const":true}},"title":"interval"},{"type":"object","properties":{"ok":{"const":true},"trial_ends_at":{"type":"string","format":"date-time"}},"title":"trial_extend"},{"type":"object","properties":{"ok":{"const":true}},"title":"data_hold"},{"type":"object","properties":{"ok":{"const":true}},"title":"partner"},{"type":"object","properties":{"ok":{"const":true},"updated":{"type":"integer"}},"title":"commission_paid"},{"type":"object","properties":{"ok":{"const":true}},"title":"mark_paid"},{"type":"object","properties":{"ok":{"const":true},"number":{"type":"string"},"gross_cents":{"type":"integer"}},"title":"credit"},{"type":"object","properties":{"ok":{"const":true}},"title":"remind"},{"type":"object","properties":{"ok":{"const":true}},"title":"discount"},{"type":"object","properties":{"ok":{"const":true}},"title":"discount_end"},{"type":"object","properties":{"ok":{"const":true}},"title":"close_workspace"},{"type":"object","properties":{"ok":{"const":true}},"title":"unsuspend"},{"type":"object","properties":{"ok":{"const":true}},"title":"end_pause"},{"type":"object","properties":{"ok":{"const":true},"announced":{"type":"integer"}},"title":"price_schedule"},{"type":"object","properties":{"ok":{"const":true}},"title":"price_cancel"},{"type":"object","properties":{"ok":{"const":true}},"title":"partner_payout_info"},{"type":"object","properties":{"ok":{"const":true},"id":{"type":"integer"}},"title":"payout"},{"type":"object","properties":{"ok":{"const":true}},"title":"payout_paid"},{"type":"object","properties":{"ok":{"const":true},"id":{"type":"integer"},"domains":{"type":["integer","null"]},"error":{"type":["string","null"]}},"title":"plesk_add"},{"type":"object","properties":{"ok":{"const":true},"domains":{"type":"integer"}},"title":"plesk_check"},{"type":"object","properties":{"ok":{"const":true}},"title":"plesk_remove"}]}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/admin/invoices":{"get":{"tags":["Workspace, team en abonnement"],"operationId":"get_admin_invoices","summary":"Beheer: alle facturen en creditfacturen","description":"**Wie:** Alleen platformbeheerders van instnt; anderen krijgen 404 of 403.\n\n**Toegang:** Alleen met een sessie in de app, niet met een API-sleutel","security":[{"session":[]}],"x-studio-auth":"session","parameters":[{"name":"status","in":"query","required":false,"schema":{"type":"string"},"description":"open, paid, credit, … of te_laat."},{"name":"period","in":"query","required":false,"schema":{"type":"string"},"description":"jjjj of jjjj-mm (factuurdatum)."},{"name":"workspace_id","in":"query","required":false,"schema":{"type":"integer"}},{"name":"q","in":"query","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"invoices":{"type":"array","items":{"type":"object"}},"totals":{"type":"object","description":"count, net_cents, vat_cents, gross_cents, open_cents, late_cents"},"workspaces":{"type":"array","items":{"type":"object"}}}}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/admin/invoice/pdf":{"get":{"tags":["Workspace, team en abonnement"],"operationId":"get_admin_invoice_pdf","summary":"Beheer: factuur of creditfactuur als PDF","description":"**Wie:** Alleen platformbeheerders van instnt; anderen krijgen 404 of 403.\n\n**Toegang:** Alleen met een sessie in de app, niet met een API-sleutel","security":[{"session":[]}],"x-studio-auth":"session","parameters":[{"name":"id","in":"query","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Gelukt.","content":{"application/pdf":{"schema":{"type":"string","format":"binary"}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/admin/export":{"get":{"tags":["Workspace, team en abonnement"],"operationId":"get_admin_export","summary":"Beheer: CSV voor de boekhouding, ICP-opgave, partneruitbetaling","description":"**Wie:** Alleen platformbeheerders van instnt; anderen krijgen 404 of 403.\n\n**Toegang:** Alleen met een sessie in de app, niet met een API-sleutel","security":[{"session":[]}],"x-studio-auth":"session","parameters":[{"name":"kind","in":"query","required":true,"schema":{"type":"string","enum":["invoices","icp","payout"]}},{"name":"from","in":"query","required":false,"schema":{"type":"string","format":"date"}},{"name":"to","in":"query","required":false,"schema":{"type":"string","format":"date"}},{"name":"quarter","in":"query","required":false,"schema":{"type":"string"},"description":"Als 2026-Q3."},{"name":"id","in":"query","required":false,"schema":{"type":"integer"},"description":"Uitbetaling."}],"responses":{"200":{"description":"Gelukt.","content":{"text/csv":{"schema":{"type":"string"}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/projects":{"get":{"tags":["Projecten en overzicht"],"operationId":"get_projects","summary":"Projecten met het aantal bronnen","description":"**Wie:** Iedereen in de workspace; een klant ziet alleen zijn eigen projecten.\n\n**Toegang:** Sessie of API-sleutel (lezen of schrijven)","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"projects":{"type":"array","items":{"type":"object"},"description":"id, name, color, website (het ingestelde adres, of afgeleid uit uptime of Search Console), website_set, position (eigen volgorde van de gebruiker, of null), brand_terms, template, conversion_value, property_count, app_source_count, search_console_count, access"},"templates":{"type":"object"}}},"example":{"ok":true,"projects":[{"id":5,"name":"Bakkerij Jansen","color":"#3552c9","brand_terms":"jansen","template":"lokaal","conversion_value":45,"property_count":1,"app_source_count":0,"search_console_count":1,"access":{"overview":"manage","website":"manage","search":"manage","product":"manage","advice":"manage","ads":"manage"}}],"templates":{}}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}},"post":{"tags":["Projecten en overzicht"],"operationId":"post_projects","summary":"Projecten maken, wijzigen en indelen","description":"**Wie:** Eigenaar of lid; kijkers en klanten krijgen 403.\n\n**Toegang:** Sessie of API-sleutel met schrijfrecht","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"action":{"const":"create"},"name":{"type":"string"},"template":{"type":"string","enum":["webshop","saas","lokaal","b2b","content"],"description":"Verplicht sinds 06-10-2026: het Overzicht kiest zijn kengetallen op het soort project."}},"required":["action","name","template"],"title":"create"},{"type":"object","properties":{"action":{"const":"rename"},"project_id":{"type":"integer"},"name":{"type":"string"}},"required":["action","project_id","name"],"title":"rename"},{"type":"object","properties":{"action":{"const":"update"},"project_id":{"type":"integer"},"name":{"type":"string"},"color":{"type":"string","description":"Als #rrggbb."},"conversion_value":{"type":["number","null"]},"template":{"type":["string","null"]},"brand_terms":{"type":"string","description":"Komma-gescheiden."},"website":{"type":"string","description":"Adres van de site; leeg wist het. Een ander domein verhuist uptimecontroles en sitecontrole mee."}},"required":["action","project_id","name","color"],"title":"update"},{"type":"object","properties":{"action":{"const":"delete"},"project_id":{"type":"integer"}},"required":["action","project_id"],"title":"delete","description":"Bronnen blijven bestaan en worden los."},{"type":"object","properties":{"action":{"const":"assign"},"property_id":{"type":"integer","description":"GA4-property."},"project_id":{"type":["integer","null"]}},"required":["action","property_id"],"title":"assign"},{"type":"object","properties":{"action":{"const":"rename_property"},"property_id":{"type":"integer"},"name":{"type":"string","description":"Leeg zet de naam uit Google terug."}},"required":["action","property_id"],"title":"rename_property"}]}}}},"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"ok":{"const":true},"project_id":{"type":"integer"}},"title":"create"},{"type":"object","properties":{"ok":{"const":true}},"title":"rename"},{"type":"object","properties":{"ok":{"const":true},"website":{"type":["object","null"],"description":"moved (int), search_console (object[]: id, site_url; hoort nog bij het oude domein)"}},"title":"update"},{"type":"object","properties":{"ok":{"const":true}},"title":"delete"},{"type":"object","properties":{"ok":{"const":true}},"title":"assign"},{"type":"object","properties":{"ok":{"const":true}},"title":"rename_property"}]}}}},"401":{"$ref":"#/components/responses/401"},"402":{"$ref":"#/components/responses/402"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/glance":{"get":{"tags":["Projecten en overzicht"],"operationId":"get_glance","summary":"Alles in één oogopslag (menubalk en widgets)","description":"Klein genoeg om elke minuut op te vragen. `live` is null als Google niet bereikbaar is.\n\n**Wie:** Iedereen in de workspace; een klant ziet alleen zijn eigen projecten.\n\n**Toegang:** Sessie of API-sleutel (lezen of schrijven)","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"projects":{"type":"array","items":{"type":"object"},"description":"id, name, monitored, down, uptime_30d, live, visitors_today, visitors_yesterday, leads_today, open_advice, open_questions"},"totals":{"type":"object","description":"sites_total, sites_up, uptime_30d, visitors_today, visitors_yesterday, leads_today, open_advice, last_deploy, approvals"},"live":{"type":["array","null"],"items":{"type":"object"},"description":"project, live"},"live_total":{"type":["integer","null"]},"down":{"type":"array","items":{"type":"object"},"description":"project, url, since"},"open_questions":{"type":["integer","null"]},"new_advice":{"type":"integer"},"proposals":{"type":"array","items":{"type":"object"}},"studio":{"type":"string","format":"uri"}}}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/extension/connect":{"post":{"tags":["Projecten en overzicht"],"operationId":"post_extension_connect","summary":"Sleutel voor de browserextensie maken","description":"Een sleutel met bereik `extension`: die mag alleen `/api/extension/*`. Studio geeft hem via de pagina aan de extensie; hij staat daarna bij API-sleutels en is daar in te trekken.\n\n**Wie:** De ingelogde gebruiker zelf.\n\n**Toegang:** Alleen met een sessie in de app, niet met een API-sleutel","security":[{"session":[]}],"x-studio-auth":"session","responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"token":{"type":"string"},"studio":{"type":"string","format":"uri"}}}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/extension/sites":{"get":{"tags":["Projecten en overzicht"],"operationId":"get_extension_sites","summary":"Projecten met hun domeinen (extensie)","description":"Registreerbare domeinen per project waarvan je de website mag zien. De extensie telt daar je eigen bezoeken niet mee, als je dat aanzet.\n\n**Wie:** Iedereen in de workspace; een klant ziet alleen zijn eigen projecten.\n\n**Toegang:** Sessie of API-sleutel (lezen of schrijven)","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"projects":{"type":"array","items":{"type":"object"},"description":"id, name, domains"},"studio":{"type":"string","format":"uri"}}}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/extension/site":{"get":{"tags":["Projecten en overzicht"],"operationId":"get_extension_site","summary":"Het project bij een adres, met cijfers (extensie)","description":"**Wie:** Iedereen in de workspace; een klant ziet alleen zijn eigen projecten.\n\n**Toegang:** Sessie of API-sleutel (lezen of schrijven)","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","parameters":[{"name":"url","in":"query","required":true,"schema":{"type":"string","format":"uri"}}],"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"project":{"type":["object","null"],"description":"id, name, link"},"visitors_today":{"type":["integer","null"]},"visitors_yesterday":{"type":["integer","null"]},"uptime":{"type":"object","description":"monitored, down, uptime_30d"},"security_score":{"type":["object","null"],"description":"score, previous"},"open_advice":{"type":["integer","null"]},"last_deploy":{"type":["object","null"],"description":"title, at"},"refs_today":{"type":"array","items":{"type":"object"},"description":"ref, visitors"}}}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/extension/post":{"get":{"tags":["Projecten en overzicht"],"operationId":"get_extension_post","summary":"Wie een post volgt (extensie)","description":"**Wie:** Iedereen in de workspace; een klant ziet alleen zijn eigen projecten.\n\n**Toegang:** Sessie of API-sleutel (lezen of schrijven)","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","parameters":[{"name":"url","in":"query","required":true,"schema":{"type":"string","format":"uri"},"description":"Link naar een post op Reddit, Hacker News, Bluesky of Mastodon."}],"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"platform":{"type":"string"},"followed":{"type":"array","items":{"type":"object"},"description":"id, project (id, name), ref, score, comments, last_checked_at, last_error"},"projects":{"type":"array","items":{"type":"object"},"description":"id, name; waar je hem kunt volgen"}}}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}},"post":{"tags":["Projecten en overzicht"],"operationId":"post_extension_post","summary":"Cijfers van een post die je bekijkt naar Studio (extensie)","description":"Voor Reddit, dat servers weigert: de extensie leest score en reacties van de pagina die je zelf open hebt, na een klik.\n\n**Wie:** Wie de website van het project mag beheren.\n\n**Toegang:** Sessie of API-sleutel met schrijfrecht","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"action":{"const":"snapshot"},"url":{"type":"string","format":"uri"},"score":{"type":"integer"},"comments":{"type":"integer"},"title":{"type":"string"},"author":{"type":"string"}},"required":["action","url","score","comments"],"title":"snapshot","description":"404 als niemand in deze workspace de post volgt."},{"type":"object","properties":{"action":{"const":"follow"},"url":{"type":"string","format":"uri"},"project_id":{"type":"integer"},"ref":{"type":"string"},"score":{"type":"integer"},"comments":{"type":"integer"},"title":{"type":"string"},"author":{"type":"string"}},"required":["action","url","project_id"],"title":"follow"}]}}}},"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"ok":{"const":true},"updated":{"type":"integer"}},"title":"snapshot"},{"type":"object","properties":{"ok":{"const":true},"id":{"type":"integer"},"updated":{"type":"integer"}},"title":"follow"}]}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/runtime":{"get":{"tags":["Projecten en overzicht"],"operationId":"get_runtime","summary":"Versies en lekken over alle projecten","description":"PHP, webserver, database, besturingssysteem en CMS per project (21-10-2026), de beste bron eerst: de site zelf (plugin, module, pakket), dan de headers, dan Plesk. Met de status uit endoflife.date: ok, update (er is een nieuwere release in dezelfde lijn), eol (geen beveiligingsupdates meer) of onbekend. Met `cve` of `product` + `below` zie je welke projecten een lek raakt; `certain` is false als alleen 8.3 bekend is (Plesk).\n\n**Wie:** Alleen het team (eigenaar, lid of kijker); klanten krijgen 403.\n\n**Toegang:** Sessie of API-sleutel (lezen of schrijven)","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","parameters":[{"name":"cve","in":"query","required":false,"schema":{"type":"string"},"description":"Een CVE, bijv. CVE-2026-1234: lekken die Studio al vond plus de geraakte versies uit de NVD."},{"name":"product","in":"query","required":false,"schema":{"type":"string","enum":["php","nginx","apache","litespeed","mysql","mariadb","postgresql","wordpress","drupal"]}},{"name":"below","in":"query","required":false,"schema":{"type":"string"}},{"name":"from","in":"query","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"projects":{"type":"array","items":{"type":"object"},"description":"project_id, project, items (per product: label, version, source site|header|plesk, detail, state ok|update|eol|onbekend, cycle, latest, eol), vulnerabilities (serious, total)"},"products":{"type":"object"},"checked_at":{"type":["string","null"]},"lookup":{"type":"object","description":"cve, summary, severity, ranges, projects (project_id, project, product, version, certain, fixed_in, resolved), source nvd|studio|onbekend"}}}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}},"post":{"tags":["Projecten en overzicht"],"operationId":"post_runtime","summary":"Versies nu controleren","description":"**Wie:** Eigenaar of lid.\n\n**Toegang:** Sessie of API-sleutel met schrijfrecht","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"action":{"const":"check"}},"required":["action"],"title":"check","description":"Haalt de releases op, neemt over wat headers en Plesk weten en loopt de lekken in plugins en pakketten op de achtergrond na. Hooguit eens per minuut."}]}}}},"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"ok":{"const":true},"projects":{"type":"array","items":{"type":"object"}}},"title":"check"}]}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/tech-overview":{"get":{"tags":["Projecten en overzicht"],"operationId":"get_tech_overview","summary":"Technisch overzicht over alle projecten","description":"Per project een score met de punten die aandacht vragen: onbereikbaar, certificaat, domein, lekken, PHP, Web Vitals, headers, back-ups en JavaScript-fouten. Zie het voorbeeld met Home Assistant hierboven.\n\n**Wie:** Alleen het team (eigenaar, lid of kijker); klanten krijgen 403.\n\n**Toegang:** Sessie of API-sleutel (lezen of schrijven)","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"kpis":{"type":"object","description":"projects, attention, down, certs_14d, domains_30d, vulns_critical_high, vulns_open, php_outdated, vitals_poor, js_new_7d, sources_error, sources_waiting, app_downloads_total (?int, eerste downloads van alle gekoppelde apps sinds de lancering), app_downloads_7d (?int)"},"sources":{"type":"array","items":{"type":"object"},"description":"bronnen met status error, stale of unknown, met project_name (zie GET /api/inventory)"},"projects":{"type":"array","items":{"type":"object"},"description":"id, name, score, status, issues, sites, down, uptime_30d, ssl, domain, vulns, php, php_outdated, vitals, headers, js_errors_7d, js_new_7d, backup, last_deploy"},"apps":{"type":"array","items":{"type":"object"},"description":"project_id, project, connect, downloads_total, downloads_7d, downloads_30d, downloads_prev_30d, crashes_7d, rating, reviews, version"}}},"example":{"ok":true,"kpis":{"projects":9,"attention":2,"down":0,"certs_14d":1,"domains_30d":0,"vulns_critical_high":1,"vulns_open":3,"php_outdated":0,"vitals_poor":0,"js_new_7d":4,"sources_error":1,"sources_waiting":2},"projects":[]}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/source-catalog":{"get":{"tags":["Projecten en overzicht"],"operationId":"get_source_catalog","summary":"Catalogus van bronnen: aanbevolen en wat nodig is","description":"Voor de catalogus onder Bronnen. `recommended`: per soort de projecten waar Studio de dienst op de site zag (Wat draait er) zonder koppeling. `capabilities`: per soort de onderdelen met de rechten die minimaal nodig zijn. De stand per bron staat in GET /api/inventory.\n\n**Wie:** Alleen het team (eigenaar, lid of kijker); klanten krijgen 403.\n\n**Toegang:** Sessie of API-sleutel (lezen of schrijven)","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"recommended":{"type":"object","description":"soort → object[]: project_id, project, host, label"},"capabilities":{"type":"object","description":"soort → object[]: key, label, needs, why, write"}}}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/app-downloads":{"get":{"tags":["Projecten en overzicht"],"operationId":"get_app_downloads","summary":"Downloads van de app van een project","description":"Uit de verkooprapporten van App Store Connect die Studio bewaart, aangevuld met App Analytics: eerste downloads per dag (365 dagen), per maand (24) en per jaar, het totaal sinds de lancering, landen en de vergelijking met vorig jaar. Voor een dag die App Analytics dekt telt die waarde, net als in App Store Connect; `analytics_differs` meldt dat het verkooprapport iets anders zegt (vaak een ontbrekend vendornummer). `acquisition` is het overzicht van App Store Connect per datum: vertoningen (inclusief productpagina's), productpaginaweergaven, eerste downloads, opnieuw gedownload, updates, conversie (downloads ÷ unieke vertoningen), herkomst, en sessies en crashes (alleen opt-in), voor de laatste dag, 7 en 30 dagen. Herdownloads en updates staan apart. `null` is onbekend, geen nul. Vraagt het onderdeel Product.\n\n**Wie:** Iedereen in de workspace; een klant ziet alleen zijn eigen projecten.\n\n**Toegang:** Sessie of API-sleutel (lezen of schrijven)","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","parameters":[{"name":"project_id","in":"query","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"apps":{"type":"array","items":{"type":"object"},"description":"account_id, app_id, name, history_running, analytics_differs, acquisition (last_day, periods (dag, 7d, 30d: impressions, impressions_unique, page_views, page_views_unique, first_downloads, redownloads, updates, sessions, crashes, installs, deletions, conversion, sources, territories, crashes_by_version, from, to), days, covered) of null, total (downloads, redownloads, updates, complete), d7, d30, prev30, days (day, value), months (month, value, running), years (year, value, running), countries, countries_30d, compare (label, previous_label, value, previous), history (pending, fetched)"}}},"example":{"ok":true,"apps":[{"app_id":"6818309309","name":"Kenteken Spel","total":{"downloads":412,"redownloads":37,"updates":220,"complete":true},"d7":58,"d30":190,"prev30":164}]}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/app-downloads/total":{"get":{"tags":["Projecten en overzicht"],"operationId":"get_app_downloads_total","summary":"Downloads van alle apps samen","description":"Het hoogste niveau: alle apps van alle Apple-accounts van de werkruimte, ook apps die niet aan een project hangen.\n\n**Wie:** Alleen het team (eigenaar, lid of kijker); klanten krijgen 403.\n\n**Toegang:** Sessie of API-sleutel (lezen of schrijven)","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","parameters":[{"name":"include_archived","in":"query","required":false,"schema":{"type":"boolean"},"description":"Ook gearchiveerde apps meetellen; standaard volgens de instelling van de werkruimte."}],"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"apps":{"type":"integer"},"total":{"type":["integer","null"]},"d7":{"type":["integer","null"]},"d30":{"type":["integer","null"]},"prev30":{"type":["integer","null"]},"archived_excluded":{"type":"integer"},"include_archived":{"type":"boolean"}}}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/project-overview":{"get":{"tags":["Projecten en overzicht"],"operationId":"get_project_overview","summary":"Overzicht van één project: wat aandacht vraagt en de kengetallen van zijn soort","description":"Hooguit zes kengetallen, gekozen op het soort project (webshop, SaaS, lokaal, B2B, content); met een app worden de laatste twee downloads en beoordeling. Een kengetal zonder bron heeft `missing: true` en `connect` met wat je moet koppelen. Wat de kijker per onderdeel niet mag zien, valt weg; omzet en ROAS alleen voor het team of een klant die het overzicht mag goedkeuren. Downloads zijn een aantal en volgen het onderdeel Product. Zonder gekozen soort staat er een voorstel in `suggested`; Studio slaat dat nooit zelf op.\n\n**Wie:** Iedereen in de workspace; een klant ziet alleen zijn eigen projecten.\n\n**Toegang:** Sessie of API-sleutel (lezen of schrijven)","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","parameters":[{"name":"project_id","in":"query","required":true,"schema":{"type":"integer"}},{"name":"days","in":"query","required":false,"schema":{"type":"integer","enum":[7,28,90]},"description":"Standaard 28."}],"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"type":{"type":["string","null"]},"suggested":{"type":["object","null"],"description":"type, reason"},"has_app":{"type":"boolean"},"days":{"type":"integer"},"types":{"type":"object"},"can_manage":{"type":"boolean"},"attention":{"type":"object","description":"items (key, tone, text, tab), actions (id, title), checked_at"},"kpis":{"type":"array","items":{"type":"object"},"description":"key, label, value, previous, unit (count|pct|eur|ratio|stars|text), series, tone, hint, invert, of missing en connect (label, kind, tab of href)"},"trend":{"type":"object","description":"visitors, leads, clicks — elk null of een reeks (day, value) met elke dag van de periode"},"funnel":{"type":["array","null"],"items":{"type":"object"},"description":"label, value — bezoeken, formulier begonnen en verstuurd, leads; alleen stappen met gegevens"}}},"example":{"ok":true,"type":"saas","suggested":null,"has_app":true,"days":28,"attention":{"items":[{"key":"ssl","tone":"warn","text":"Certificaat van voorbeeld.nl verloopt over 12 dagen","tab":"uptime"}],"actions":[{"id":41,"title":"Titels herschrijven voor zoektermen op plek 4 tot 10"}],"checked_at":"2026-10-06 10:41:00"},"kpis":[{"key":"status","label":"Bereikbaar (30 d)","value":99.98,"unit":"pct","hint":"nu bereikbaar"},{"key":"signups","label":"Aanmeldingen","value":42,"previous":35,"unit":"count","series":[1,3,2]},{"key":"downloads","label":"Downloads","missing":true,"connect":{"label":"Koppel App Store Connect","kind":"appstore_connect"}}]}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/work":{"get":{"tags":["Projecten en overzicht"],"operationId":"get_work","summary":"Werkbord: adviezen over alle klanten en de werklast","description":"**Wie:** Alleen het team (eigenaar, lid of kijker); klanten krijgen 403.\n\n**Toegang:** Sessie of API-sleutel (lezen of schrijven)","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","parameters":[{"name":"assignee","in":"query","required":false,"schema":{"type":"string"},"description":"`me` of een gebruikers-id."}],"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"columns":{"type":"object","description":"open, planned, done"},"workload":{"type":"array","items":{"type":"object"},"description":"project_id, name, open, planned, overdue, done_30"},"team":{"type":"array","items":{"type":"object"}},"me":{"type":"integer"},"today":{"type":"string","format":"date"},"health":{"type":"array","items":{"type":"object"}}}}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/portfolio":{"get":{"tags":["Projecten en overzicht"],"operationId":"get_portfolio","summary":"Projectlijst: één rij per project","description":"De startpagina van het team: per project status (ok, warn, bad) met de punten die aandacht vragen, uptime, tags, klanten, bezoek en het resultaat dat bij het soort project hoort, de app en het laatste rapport. Dezelfde cijfers als Techniek en het projectoverzicht.\n\n**Wie:** Alleen het team (eigenaar, lid of kijker); klanten krijgen 403.\n\n**Toegang:** Sessie of API-sleutel (lezen of schrijven)","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","parameters":[{"name":"days","in":"query","required":false,"schema":{"type":"integer","enum":[7,28,90]},"description":"Standaard 28."}],"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"projects":{"type":"array","items":{"type":"object"},"description":"id, name, color, template, suggested, tags, clients (id, name), status, issues, uptime_30d, down, headline (visitors, result: key, label, value, previous, unit), app (downloads_30d, downloads_prev_30d, downloads_total, rating, reviews), report (period, status), open_advice"},"kpis":{"type":"object","description":"projects, attention, visitors, downloads_7d, open_advice"},"unassigned_sources":{"type":"integer"},"templates":{"type":"object"},"days":{"type":"integer"}}}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/portfolio-trend":{"get":{"tags":["Projecten en overzicht"],"operationId":"get_portfolio_trend","summary":"Verloop over alle projecten","description":"Bezoek, conversies (GA4 key events plus leads uit het sitescript) en omzet (betaald min terugbetaald, plus winkelomzet) per dag over alle projecten samen, met het totaal, de periode ervoor en de verdeling per project. Een metriek zonder enige bron is null.\n\n**Wie:** Alleen het team (eigenaar, lid of kijker); klanten krijgen 403.\n\n**Toegang:** Sessie of API-sleutel (lezen of schrijven)","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","parameters":[{"name":"days","in":"query","required":false,"schema":{"type":"integer","enum":[7,28,90]},"description":"Standaard 28."}],"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"days":{"type":"integer"},"metrics":{"type":"object","description":"visitors, conversions, revenue — elk null of { unit, total, previous, series (day, value), by_project (id, name, color, value) }"}}}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/benchmarks":{"get":{"tags":["Projecten en overzicht"],"operationId":"get_benchmarks","summary":"Benchmarks: een project naast vergelijkbare projecten","description":"Mediaan, 25e en 75e percentiel en het aantal projecten per kengetal, plus de waarde en positie van dit project (`better_than` van `others`). Elke nacht berekend. Cijfers alleen bij minstens 5 projecten in de groep (`enough`); gedeeld over werkruimtes heen bovendien uit minstens 3 werkruimtes, en alleen als je werkruimte zelf deelt. Nooit namen of waarden van andere projecten. Zonder `project_id`: per kengetal over alle projecten van de werkruimte, met de projecten in het zwakste kwart (alleen het team). Een klant krijgt `hidden: true` tenzij het team benchmarks voor klanten aanzet; eigen tags en gedeelde cijfers ziet een klant nooit.\n\n**Wie:** Team; klanten met toegang tot het onderdeel Overzicht.\n\n**Toegang:** Sessie of API-sleutel (lezen of schrijven)","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","parameters":[{"name":"project_id","in":"query","required":false,"schema":{"type":"integer"}},{"name":"period","in":"query","required":false,"schema":{"type":"integer","enum":[28,90]},"description":"Standaard 28."},{"name":"scope","in":"query","required":false,"schema":{"type":"string","enum":["werkruimte","gedeeld"]},"description":"Standaard werkruimte."},{"name":"group","in":"query","required":false,"schema":{"type":"string"},"description":"Sleutel uit `groups`, bijv. `soort:webshop` of `tech:drupal`. Zonder: de meest specifieke groep met de meeste bruikbare kengetallen."}],"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"period":{"type":"integer"},"scope":{"type":"string"},"group":{"type":"string"},"groups":{"type":"array","items":{"type":"object"},"description":"key, label, usable"},"metrics":{"type":"array","items":{"type":"object"},"description":"metric, label, unit, higher_is_better, note, value, n, min, enough, median, p25, p75, position (better_than, others, percentile); zonder project_id: behind (project_id, name, value) in plaats van value en position"},"settings":{"type":"object","description":"Alleen zonder project_id: share, show_clients."},"computed_at":{"type":["string","null"]},"hidden":{"type":"boolean"}}}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}},"post":{"tags":["Projecten en overzicht"],"operationId":"post_benchmarks","summary":"Benchmarks instellen","description":"**Wie:** Eigenaar of lid; kijkers en klanten krijgen 403.\n\n**Toegang:** Sessie of API-sleutel met schrijfrecht","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"action":{"const":"settings"},"share":{"type":"boolean","description":"Anoniem meedoen met de vergelijking over werkruimtes heen. Standaard uit."},"show_clients":{"type":"boolean","description":"Klanten zien de positie van hun eigen project. Standaard uit."}},"required":["action"],"title":"settings"}]}}}},"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"ok":{"const":true},"settings":{"type":"object","description":"share, show_clients"}},"title":"settings"}]}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/report-overview":{"get":{"tags":["Projecten en overzicht"],"operationId":"get_report_overview","summary":"Maandrapporten over alle projecten","description":"Per project de stand van het rapport van één maand: ontbreekt, concept (fouten bij het ophalen), klaar, verstuurd of geopend (door een klant, in Studio of via een deellink; alleen een teller, niet wie).\n\n**Wie:** Alleen het team (eigenaar, lid of kijker); klanten krijgen 403.\n\n**Toegang:** Sessie of API-sleutel (lezen of schrijven)","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","parameters":[{"name":"period","in":"query","required":false,"schema":{"type":"string"},"description":"Een afgesloten maand als 2026-09; standaard de vorige maand."}],"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"period":{"type":"string"},"label":{"type":"string"},"periods":{"type":"array","items":{"type":"object"},"description":"period, label"},"rows":{"type":"array","items":{"type":"object"},"description":"project_id, project, color, clients, tags, report_id, status, errors, generated_at, published_at, views, first_viewed_at"},"counts":{"type":"object","description":"ontbreekt, concept, klaar, verstuurd, geopend"},"can_manage":{"type":"boolean"}}}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}},"post":{"tags":["Projecten en overzicht"],"operationId":"post_report_overview","summary":"Concepten maken en klaarstaande rapporten versturen","description":"**Wie:** Eigenaar of lid; kijkers en klanten krijgen 403.\n\n**Toegang:** Sessie of API-sleutel met schrijfrecht","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"action":{"const":"generate_missing"},"period":{"type":"string"}},"required":["action"],"title":"generate_missing","description":"Een concept voor elk project zonder rapport, op de achtergrond (202)."},{"type":"object","properties":{"action":{"const":"publish_ready"},"period":{"type":"string"},"ids":{"type":"array","items":{"type":"integer"},"description":"Alleen deze rapporten; standaard alle met status klaar."}},"required":["action"],"title":"publish_ready","description":"Alleen status klaar; een concept met fouten blijft staan. Klanten krijgen de rapportmail via de standaardautomatisering."}]}}}},"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"ok":{"const":true},"queued":{"type":"integer"},"tasks":{"type":"array","items":{"type":"string"}}},"title":"generate_missing"},{"type":"object","properties":{"ok":{"const":true},"published":{"type":"integer"},"notified":{"type":"integer"}},"title":"publish_ready"}]}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/today":{"get":{"tags":["Projecten en overzicht"],"operationId":"get_today","summary":"Vandaag: wat er over alle projecten aandacht vraagt","description":"Storingen, kritieke en hoge lekken (per pakket en versie over alle projecten samen), certificaten en domeinen die binnen 14 dagen verlopen, bronnen die niet werken, nieuwe fouten na een deploy, een daling in de App Store-beoordeling, acties die op jou wachten en rapporten van vorige maand die als concept klaarstaan. Elk punt heeft een `to` naar de plek waar je het oplost.\n\n**Wie:** Alleen het team (eigenaar, lid of kijker); klanten krijgen 403.\n\n**Toegang:** Sessie of API-sleutel (lezen of schrijven)","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"items":{"type":"array","items":{"type":"object"},"description":"key, group (storing|lek|verloop|bron|fout|beoordeling|actie|rapport), tone (bad|warn|info), title, detail, projects (id, name), to, fix (?object: steps[], links[] (label, url), copy[] (label, value); \"Zo los je het op\")"},"groups":{"type":"object"},"counts":{"type":"object","description":"bad, total"}}},"example":{"ok":true,"items":[{"key":"lek-0","group":"lek","tone":"bad","title":"Drupal core 10.2.3, 3 projecten","detail":"2 lekken, ernst kritiek · opgelost in 10.2.4","projects":[{"id":3,"name":"Alpha"}],"to":"/techniek"}],"counts":{"bad":1,"total":1}}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/tags":{"get":{"tags":["Projecten en overzicht"],"operationId":"get_tags","summary":"Tags van de projecten","description":"Platform (Web, iOS) en techniek (Drupal 11, Laravel 13, PHP 8.4) herkent Studio zelf, uit koppelingen, lockbestanden, de Drupal-module of WordPress-plugin, de sitecontrole en Plesk; `origin` en `origin_at` zeggen waar en wanneer. Eigen tags maakt het team.\n\n**Wie:** Alleen het team (eigenaar, lid of kijker); klanten krijgen 403.\n\n**Toegang:** Sessie of API-sleutel (lezen of schrijven)","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","parameters":[{"name":"project_id","in":"query","required":false,"schema":{"type":"integer"},"description":"Alleen dit project."},{"name":"hidden","in":"query","required":false,"schema":{"type":"boolean"},"description":"Ook uitgezette automatische tags."}],"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"tags":{"type":"array","items":{"type":"object"},"description":"id, project_id, kind (platform|tech|own), slug, key, label, color, auto, hidden, origin, origin_at"}}}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}},"post":{"tags":["Projecten en overzicht"],"operationId":"post_tags","summary":"Tags toevoegen, uitzetten en opnieuw herkennen","description":"**Wie:** Eigenaar of lid; kijkers en klanten krijgen 403.\n\n**Toegang:** Sessie of API-sleutel met schrijfrecht","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"action":{"const":"add"},"project_id":{"type":"integer"},"label":{"type":"string","description":"Hooguit 40 tekens."},"color":{"type":"string","description":"Als #rrggbb."}},"required":["action","project_id","label"],"title":"add"},{"type":"object","properties":{"action":{"const":"remove"},"tag_id":{"type":"integer"}},"required":["action","tag_id"],"title":"remove","description":"Een eigen tag gaat weg; een automatische tag gaat uit en komt bij de volgende herkenning niet terug."},{"type":"object","properties":{"action":{"const":"restore"},"tag_id":{"type":"integer"}},"required":["action","tag_id"],"title":"restore"},{"type":"object","properties":{"action":{"const":"detect"},"project_id":{"type":"integer","description":"Zonder: alle projecten."}},"required":["action"],"title":"detect"}]}}}},"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"ok":{"const":true},"tag":{"type":"object"}},"title":"add"},{"type":"object","properties":{"ok":{"const":true}},"title":"remove"},{"type":"object","properties":{"ok":{"const":true},"tag":{"type":"object"}},"title":"restore"},{"type":"object","properties":{"ok":{"const":true},"tags":{"type":"array","items":{"type":"object"}}},"title":"detect"}]}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/views":{"get":{"tags":["Projecten en overzicht"],"operationId":"get_views","summary":"Je bewaarde weergaven van de projectlijst","description":"**Wie:** Alleen het team (eigenaar, lid of kijker); klanten krijgen 403.\n\n**Toegang:** Sessie of API-sleutel (lezen of schrijven)","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"views":{"type":"array","items":{"type":"object"},"description":"id, name, filters (client, type, tags, attention)"}}}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}},"post":{"tags":["Projecten en overzicht"],"operationId":"post_views","summary":"Weergaven bewaren en verwijderen","description":"**Wie:** Alleen het team (eigenaar, lid of kijker); klanten krijgen 403.\n\n**Toegang:** Sessie of API-sleutel met schrijfrecht","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"action":{"const":"save"},"name":{"type":"string"},"filters":{"type":"object","description":"client (?int), type (?string), tags (string[], als kind:slug, bijv. tech:drupal), attention (bool)."},"view_id":{"type":"integer","description":"Met id: bijwerken."}},"required":["action","name"],"title":"save"},{"type":"object","properties":{"action":{"const":"delete"},"view_id":{"type":"integer"}},"required":["action","view_id"],"title":"delete"}]}}}},"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"ok":{"const":true},"view_id":{"type":"integer"}},"title":"save"},{"type":"object","properties":{"ok":{"const":true}},"title":"delete"}]}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/preferences":{"get":{"tags":["Projecten en overzicht"],"operationId":"get_preferences","summary":"Je persoonlijke voorkeuren","description":"**Wie:** Alleen het team (eigenaar, lid of kijker); klanten krijgen 403.\n\n**Toegang:** Sessie of API-sleutel (lezen of schrijven)","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"start_page":{"type":["string","null"],"description":"je eigen keuze, null is de standaard"},"start_page_default":{"type":"string"},"options":{"type":"object"}}}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}},"post":{"tags":["Projecten en overzicht"],"operationId":"post_preferences","summary":"Startpagina kiezen, Wat is er nieuw gelezen, taal van de app","description":"**Wie:** Iedereen voor `locale`; de rest alleen het team.\n\n**Toegang:** Sessie of API-sleutel met schrijfrecht","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"action":{"const":"start_page"},"start_page":{"type":["string","null"],"enum":["overzicht","vandaag","projecten","techniek",null]}},"required":["action"],"title":"start_page","description":"Null zet de standaard terug: Vandaag voor wie alleen werkt, Projecten voor een team."},{"type":"object","properties":{"action":{"const":"changelog_seen"},"version":{"type":"string","description":"Datum van de bovenste versie, jjjj-mm-dd."}},"required":["action","version"],"title":"changelog_seen","description":"Gaat nooit terug in de tijd; /api/me geeft changelog_seen mee."},{"type":"object","properties":{"action":{"const":"locale"},"locale":{"type":"string","enum":["nl","en"]}},"required":["action","locale"],"title":"locale","description":"Taal van de app voor deze gebruiker; /api/me geeft hem mee als user.locale. Standaard nl."},{"type":"object","properties":{"action":{"const":"project_order"},"ids":{"type":"array","items":{"type":"integer"},"description":"Project-id's in de gewenste volgorde."}},"required":["action","ids"],"title":"project_order","description":"Per gebruiker; ook voor klanten. Projecten die je niet mag zien worden overgeslagen. GET /api/projects en /api/portfolio sorteren erop."}]}}}},"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"ok":{"const":true},"start_page":{"type":"string"}},"title":"start_page"},{"type":"object","properties":{"ok":{"const":true},"changelog_seen":{"type":"string"}},"title":"changelog_seen"},{"type":"object","properties":{"ok":{"const":true},"locale":{"type":"string"}},"title":"locale"},{"type":"object","properties":{"ok":{"const":true},"ids":{"type":"array","items":{"type":"integer"}}},"title":"project_order"}]}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/portal":{"get":{"tags":["Projecten en overzicht"],"operationId":"get_portal","summary":"Startpagina voor klanten","description":"Per project het resultaat van deze maand tegenover dezelfde dagen vorige maand, doelen, wat gedaan is en wat er komt.\n\n**Wie:** Iedereen in de workspace; een klant ziet alleen zijn eigen projecten.\n\n**Toegang:** Sessie of API-sleutel (lezen of schrijven)","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"month":{"type":"string"},"days_so_far":{"type":"integer"},"projects":{"type":"array","items":{"type":"object"},"description":"id, name, numbers, series (day, value: bezoeken per dag deze maand), goals, done, next, report, weekly_update"}}}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}},"post":{"tags":["Projecten en overzicht"],"operationId":"post_portal","summary":"Weekupdate aan of uit","description":"**Wie:** Klanten met toegang tot het project.\n\n**Toegang:** Sessie of API-sleutel met schrijfrecht","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"action":{"const":"weekly"},"project_id":{"type":"integer"},"on":{"type":"boolean"}},"required":["action","project_id","on"],"title":"weekly"}]}}}},"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"ok":{"const":true},"weekly_update":{"type":"boolean"}},"title":"weekly"}]}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/notifications":{"get":{"tags":["Projecten en overzicht"],"operationId":"get_notifications","summary":"Meldingencentrum: wat er is gebeurd","description":"De bel in de app, per gebruiker en werkruimte, van de laatste 30 dagen: storingen en herstel, afwijkingen, nieuw gevonden bronnen, goedkeuringen, vragen van klanten, afgewezen app-versies, bevestigde adviezen en nieuwe formulierinzendingen. Een klant ziet alleen storingen van zijn eigen projecten, antwoorden op zijn vragen en inzendingen als hij Website mag bekijken. Storingen en afwijkingen volgen de meldingsvoorkeuren van het account.\n\n**Wie:** Iedereen in de workspace; een klant ziet alleen zijn eigen projecten.\n\n**Toegang:** Sessie of API-sleutel (lezen of schrijven)","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","parameters":[{"name":"count","in":"query","required":false,"schema":{"type":"boolean"},"description":"Alleen het aantal ongelezen."}],"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"items":{"type":"array","items":{"type":"object"},"description":"key, kind (storing|afwijking|nieuw|goedkeuring|vraag|antwoord|app|bevestigd|inzending), tone (bad|warn|info|ok), title, detail, at (?datetime), to, project (?object: id, name), read"},"unread":{"type":"integer"},"kinds":{"type":"object"}}}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}},"post":{"tags":["Projecten en overzicht"],"operationId":"post_notifications","summary":"Meldingen als gelezen markeren","description":"**Wie:** Iedereen in de workspace; een klant ziet alleen zijn eigen projecten.\n\n**Toegang:** Sessie of API-sleutel met schrijfrecht","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"action":{"const":"read"},"keys":{"type":"array","items":{"type":"string"},"description":"Sleutels uit items[].key, hooguit 200."}},"required":["action","keys"],"title":"read"},{"type":"object","properties":{"action":{"const":"read_all"}},"required":["action"],"title":"read_all","description":"Alles wat nu in de bel staat; wat daarna binnenkomt is weer nieuw."}]}}}},"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"ok":{"const":true},"unread":{"type":"integer"}},"title":"read"},{"type":"object","properties":{"ok":{"const":true},"marked":{"type":"integer"},"unread":{"type":"integer"}},"title":"read_all"}]}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/start-checklist":{"get":{"tags":["Projecten en overzicht"],"operationId":"get_start_checklist","summary":"Checklist bij de start van een werkruimte","description":"De stappen waarmee een werkruimte gaat werken, berekend uit de stand van nu: Google, eerste project, soort, bereikbaarheid, script, Search Console, klant, en voor de eigenaar tweestap en factuurgegevens.\n\n**Wie:** Eigenaar en teamleden; voor anderen is checklist null.\n\n**Toegang:** Sessie of API-sleutel (lezen of schrijven)","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"checklist":{"type":["object","null"],"description":"steps (object[]: key, done, title, why, to, action), done (int), total (int), complete (bool), hidden (bool)"}}}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}},"post":{"tags":["Projecten en overzicht"],"operationId":"post_start_checklist","summary":"Checklist verbergen of terughalen","description":"**Wie:** Eigenaar en teamleden.\n\n**Toegang:** Sessie of API-sleutel met schrijfrecht","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"action":{"const":"hide"}},"required":["action"],"title":"hide","description":"Per persoon en per werkruimte."},{"type":"object","properties":{"action":{"const":"show"}},"required":["action"],"title":"show"}]}}}},"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"ok":{"const":true},"checklist":{"type":"object"}},"title":"hide"},{"type":"object","properties":{"ok":{"const":true},"checklist":{"type":"object"}},"title":"show"}]}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/search":{"get":{"tags":["Projecten en overzicht"],"operationId":"get_search","summary":"Zoeken over projecten, adviezen, zoektermen en pagina's","description":"**Wie:** Iedereen in de workspace; een klant ziet alleen zijn eigen projecten.\n\n**Toegang:** Sessie of API-sleutel (lezen of schrijven)","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","parameters":[{"name":"q","in":"query","required":true,"schema":{"type":"string"},"description":"Minstens twee tekens."}],"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"results":{"type":"array","items":{"type":"object"},"description":"kind, title, subtitle, project_id, tab, filter"}}}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/task":{"get":{"tags":["Projecten en overzicht"],"operationId":"get_task","summary":"Stand van een achtergrondtaak","description":"**Wie:** Iedereen in de workspace; een klant ziet alleen zijn eigen projecten.\n\n**Toegang:** Sessie of API-sleutel (lezen of schrijven)","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","parameters":[{"name":"id","in":"query","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"status":{"type":"string","enum":["queued","running","done","failed"]},"result":{"type":["object","null"]},"error":{"type":["string","null"]}}}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/inventory":{"get":{"tags":["Projecten en overzicht"],"operationId":"get_inventory","summary":"Alle bronnen met hun status","description":"GA4, Search Console, eigen systemen, aanvullende diensten en uptime-controles, met per bron of hij werkt.\n\n**Wie:** Alleen het team (eigenaar, lid of kijker); klanten krijgen 403.\n\n**Toegang:** Sessie of API-sleutel (lezen of schrijven)","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","parameters":[{"name":"project_id","in":"query","required":false,"schema":{"type":"integer"},"description":"Alleen de bronnen van dit project; dan zonder `projects`."}],"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"items":{"type":"array","items":{"type":"object"},"description":"key, type, subtype, id, name, detail, project_id, status (ok|error|stale|unknown|off|setup|tracking), status_text, action, fix (?object: steps[], links[] (label, url), copy[] (label, value); \"Zo los je het op\"), last_ok_at, last_error_at, fetching, can_fetch, can_assign, missing (object[]: id, label, since, since_text; cijfers die de bron eerder meestuurde en al een tijd niet meer)"},"projects":{"type":"array","items":{"type":"object"},"description":"id, name, color, sources, problems, unchecked, clients, open_advice, monitors_down, latest_report"},"counts":{"type":"object","description":"error, waiting, ok"}}}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}},"post":{"tags":["Projecten en overzicht"],"operationId":"post_inventory","summary":"Een bron nu ophalen, of een ontbrekend cijfer niet meer verwachten","description":"**Wie:** Eigenaar of lid; kijkers en klanten krijgen 403.\n\n**Toegang:** Sessie of API-sleutel met schrijfrecht","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"action":{"const":"fetch"},"type":{"type":"string","enum":["ga","search","app","integration"]},"id":{"type":"integer"}},"required":["action","type","id"],"title":"fetch","description":"Eén API-verzoek (de meeste koppelingen, eigen systemen) meteen; GA4, Search Console, betalingen, Ads en App Store Connect via de wachtrij, met `fetching: true` tot hij klaar is. Hooguit eens per minuut per bron (429)."},{"type":"object","properties":{"action":{"const":"ignore_metric"},"id":{"type":"integer","description":"Het `id` uit `missing`."}},"required":["action","id"],"title":"ignore_metric","description":"Het cijfer is bewust weg: geen signaal meer. Komt het later terug, dan telt het gewoon weer mee."}]}}}},"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"ok":{"const":true},"item":{"type":"object","description":"zoals in GET /api/inventory"}},"title":"fetch"},{"type":"object","properties":{"ok":{"const":true},"ignored":{"type":"boolean"}},"title":"ignore_metric"}]}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/discovery":{"get":{"tags":["Projecten en overzicht"],"operationId":"get_discovery","summary":"Nieuw gevonden bronnen","description":"Wat Studio via een koppeling ziet maar nergens aan hangt (Analytics-properties, Search Console-sites, apps, bedrijfsprofielen en voor beheerders Plesk-domeinen), plus wat genegeerd of gearchiveerd is. Studio beslist zelf niets. Soorten op \"verbergen\" staan alleen in `hidden`.\n\n**Wie:** Alleen het team (eigenaar, lid of kijker); klanten krijgen 403.\n\n**Toegang:** Sessie of API-sleutel (lezen of schrijven)","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"new":{"type":"array","items":{"type":"object"},"description":"key, type (ga|search|apple|gbp|plesk), ref, name, detail, project_id, project_name, state, decided_at, data_deleted, suggestion {name, template}"},"ignored":{"type":"array","items":{"type":"object"}},"archived":{"type":"array","items":{"type":"object"}},"linked":{"type":"array","items":{"type":"object"}},"archived_projects":{"type":"array","items":{"type":"object"},"description":"id, name, archived_at"},"hidden":{"type":"integer"},"notify":{"type":"integer"},"settings":{"type":"object","description":"modes {ga, search, apple, gbp, plesk: melden|stil|verbergen}, include_archived"},"can_manage":{"type":"boolean"},"projects":{"type":"array","items":{"type":"object"},"description":"id, name"},"templates":{"type":"array","items":{"type":"object"},"description":"key, label"}}}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}},"post":{"tags":["Projecten en overzicht"],"operationId":"post_discovery","summary":"Koppelen, negeren, archiveren of terughalen","description":"**Wie:** Eigenaar of lid; kijkers en klanten krijgen 403.\n\n**Toegang:** Sessie of API-sleutel met schrijfrecht","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"action":{"const":"link"},"key":{"type":"string"},"project_id":{"type":"integer"}},"required":["action","key","project_id"],"title":"link"},{"type":"object","properties":{"action":{"const":"new_project"},"key":{"type":"string"},"name":{"type":"string"},"template":{"type":"string"}},"required":["action","key","name","template"],"title":"new_project"},{"type":"object","properties":{"action":{"const":"ignore"},"keys":{"type":"array","items":{"type":"string"}}},"required":["action","keys"],"title":"ignore"},{"type":"object","properties":{"action":{"const":"archive"},"keys":{"type":"array","items":{"type":"string"}},"delete_data":{"type":"boolean","description":"Ook de opgehaalde gegevens verwijderen; standaard bewaard."}},"required":["action","keys"],"title":"archive","description":"Daarna haalt Studio niets meer op en telt de bron niet mee in totalen. Een gekoppelde Analytics- of Search Console-bron gaat los van het project (onthouden voor terughalen); een gekoppelde app of vestiging blijft hangen."},{"type":"object","properties":{"action":{"const":"restore"},"keys":{"type":"array","items":{"type":"string"}}},"required":["action","keys"],"title":"restore"},{"type":"object","properties":{"action":{"const":"settings"},"modes":{"type":"object"},"include_archived":{"type":"boolean"}},"required":["action"],"title":"settings"},{"type":"object","properties":{"action":{"const":"search_locations"}},"required":["action"],"title":"search_locations"}]}}}},"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"ok":{"const":true}},"title":"link"},{"type":"object","properties":{"ok":{"const":true},"project_id":{"type":"integer"}},"title":"new_project"},{"type":"object","properties":{"ok":{"const":true},"count":{"type":"integer"}},"title":"ignore"},{"type":"object","properties":{"ok":{"const":true},"count":{"type":"integer"}},"title":"archive"},{"type":"object","properties":{"ok":{"const":true},"count":{"type":"integer"}},"title":"restore"},{"type":"object","properties":{"ok":{"const":true},"settings":{"type":"object"}},"title":"settings"},{"type":"object","properties":{"ok":{"const":true},"found":{"type":"integer"}},"title":"search_locations"}]}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/capabilities":{"get":{"tags":["Projecten en overzicht"],"operationId":"get_capabilities","summary":"Wat Studio met een koppeling kan","description":"Per onderdeel wat minimaal nodig is, wat de sleutel volgens de laatste meting mag (ja, nee, onbekend) en of het aan staat. Uit betekent dat Studio het helemaal niet ophaalt. `minimal` zegt welke rechten genoeg zijn voor wat aan staat; `warnings` noemt sleutels met meer rechten dan nodig.\n\n**Wie:** Alleen het team (eigenaar, lid of kijker); klanten krijgen 403.\n\n**Toegang:** Sessie of API-sleutel (lezen of schrijven)","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","parameters":[{"name":"subject_type","in":"query","required":true,"schema":{"type":"string"},"description":"apple, google, integration, slack of chat."},{"name":"subject_id","in":"query","required":true,"schema":{"type":"integer"},"description":"Id van het Apple-account, de Google-koppeling, de projectkoppeling, de workspace (slack) of het kanaal."}],"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"type":{"type":"string"},"name":{"type":"string"},"items":{"type":"array","items":{"type":"object"},"description":"cap, label, needs, why, write, enabled, have (ja|nee|onbekend), detail, state (aan|uit|niet mogelijk|niet gemeten)"},"measured_at":{"type":["string","null"]},"warnings":{"type":"array","items":{"type":"string"}},"fix":{"type":["object","null"],"description":"Waar je de rechten verlaagt: steps, links (label, url), copy (label, value)."},"keys":{"type":"array","items":{"type":"object"},"description":"key_id, role, role_label, account_key, allowed (alleen Apple)"},"minimal":{"type":["string","null"]},"can_manage":{"type":"boolean"}}}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}},"post":{"tags":["Projecten en overzicht"],"operationId":"post_capabilities","summary":"Onderdeel aan- of uitzetten, of opnieuw meten","description":"**Wie:** Eigenaar of lid; kijkers en klanten krijgen 403.\n\n**Toegang:** Sessie of API-sleutel met schrijfrecht","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"action":{"const":"toggle"},"subject_type":{"type":"string"},"subject_id":{"type":"integer"},"cap":{"type":"string"},"enabled":{"type":"boolean"}},"required":["action","subject_type","subject_id","cap","enabled"],"title":"toggle"},{"type":"object","properties":{"action":{"const":"measure"},"subject_type":{"type":"string"},"subject_id":{"type":"integer"}},"required":["action","subject_type","subject_id"],"title":"measure","description":"Alleen leesverzoeken bij de dienst; een onderdeel dat iets zou veranderen probeert Studio niet uit. Hooguit eens per minuut (429)."}]}}}},"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"ok":{"const":true},"items":{"type":"array","items":{"type":"object"}}},"title":"toggle"},{"type":"object","properties":{"ok":{"const":true},"items":{"type":"array","items":{"type":"object"}}},"title":"measure"}]}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/dashboards":{"get":{"tags":["Projecten en overzicht"],"operationId":"get_dashboards","summary":"Alle dashboards van de werkruimte","description":"Dashboards over meerdere projecten (zonder `project_id`) eerst, daarna die per project.\n\n**Wie:** Alleen het team (eigenaar, lid of kijker); klanten krijgen 403.\n\n**Toegang:** Sessie of API-sleutel (lezen of schrijven)","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"dashboards":{"type":"array","items":{"type":"object"},"description":"id, name, goal, project_id, project_name, tiles (aantal), scope"},"can_edit":{"type":"boolean"},"limit":{"type":["integer","null"]},"workspace_count":{"type":"integer"}}}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/dashboard":{"get":{"tags":["Projecten en overzicht"],"operationId":"get_dashboard","summary":"Dashboard van een project, of over projecten heen","description":"Met `project_id` een projectdashboard. Alleen `dashboard_id` zonder `project_id` geeft een dashboard over projecten heen (alleen het team): `tiles` over de projecten in `scope`, plus losse projecttegels; `catalog` en `project_catalog` zijn de keuzes.\n\n**Wie:** Team; klanten met toegang tot het onderdeel Overzicht.\n\n**Toegang:** Sessie of API-sleutel (lezen of schrijven)","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","parameters":[{"name":"project_id","in":"query","required":false,"schema":{"type":"integer"},"description":"Leeg voor een dashboard over projecten heen."},{"name":"dashboard_id","in":"query","required":false,"schema":{"type":"integer"},"description":"Standaard het eerste."}],"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"dashboards":{"type":"array","items":{"type":"object"},"description":"id, name, goal"},"current":{"type":"object","description":"id, name, goal"},"tiles":{"type":"array","items":{"type":"object"}},"chosen":{"type":"array","items":{"type":"string"}},"catalog":{"type":"object"},"goals":{"type":"object"},"can_edit":{"type":"boolean"},"limit":{"type":["integer","null"]}}}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}},"post":{"tags":["Projecten en overzicht"],"operationId":"post_dashboard","summary":"Dashboards maken, wijzigen en verwijderen","description":"**Wie:** Eigenaar of lid; kijkers en klanten krijgen 403.\n\n**Toegang:** Sessie of API-sleutel met schrijfrecht","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"action":{"const":"create"},"project_id":{"type":"integer","description":"Leeg: een dashboard over projecten heen."},"goal":{"type":"string","description":"Een doel uit `goals`; standaard eigen."},"name":{"type":"string"}},"required":["action"],"title":"create"},{"type":"object","properties":{"action":{"const":"save"},"dashboard_id":{"type":"integer"},"tiles":{"type":["object","string"],"description":"Hooguit twaalf, uit `catalog`; over projecten heen ook {key, project_id} voor één project."},"name":{"type":"string"},"scope":{"type":"object","description":"Alleen over projecten heen: {tags: [\"platform:ios\"], project_ids: [3]}; leeg is alle projecten."}},"required":["action","dashboard_id"],"title":"save"},{"type":"object","properties":{"action":{"const":"delete"},"dashboard_id":{"type":"integer"}},"required":["action","dashboard_id"],"title":"delete","description":"Het laatste dashboard van een project blijft staan."}]}}}},"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"ok":{"const":true},"id":{"type":"integer"}},"title":"create"},{"type":"object","properties":{"ok":{"const":true}},"title":"save"},{"type":"object","properties":{"ok":{"const":true}},"title":"delete"}]}}}},"401":{"$ref":"#/components/responses/401"},"402":{"$ref":"#/components/responses/402"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/goals":{"get":{"tags":["Projecten en overzicht"],"operationId":"get_goals","summary":"Maanddoelen, prognose en benchmark","description":"**Wie:** Team; klanten met toegang tot het onderdeel Overzicht.\n\n**Toegang:** Sessie of API-sleutel (lezen of schrijven)","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","parameters":[{"name":"project_id","in":"query","required":true,"schema":{"type":"integer"},"description":"Project-id."}],"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"goals":{"type":"array","items":{"type":"object"},"description":"metric, label, target, value, projected, status"},"metrics":{"type":"object"},"can_manage":{"type":"boolean"},"suggested":{"type":["object","null"]},"forecast":{"type":["object","null"]},"languages":{"type":["object","null"]},"benchmark":{"type":["object","null"]},"signals":{"type":["object","null"]}}}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}},"post":{"tags":["Projecten en overzicht"],"operationId":"post_goals","summary":"Maanddoel zetten of weghalen","description":"**Wie:** Eigenaar of lid (beheer van Overzicht); anderen krijgen 404.\n\n**Toegang:** Sessie of API-sleutel met schrijfrecht","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"action":{"const":"set"},"project_id":{"type":"integer"},"metric":{"type":"string","enum":["sessions","key_events","new_users","clicks"]},"target":{"type":"integer","description":"Minstens 1."}},"required":["action","project_id","metric","target"],"title":"set"},{"type":"object","properties":{"action":{"const":"delete"},"project_id":{"type":"integer"},"metric":{"type":"string","enum":["sessions","key_events","new_users","clicks"]}},"required":["action","project_id","metric"],"title":"delete"}]}}}},"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"ok":{"const":true},"goals":{"type":"array","items":{"type":"object"}}},"title":"set"},{"type":"object","properties":{"ok":{"const":true},"goals":{"type":"array","items":{"type":"object"}}},"title":"delete"}]}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/annotations":{"get":{"tags":["Projecten en overzicht"],"operationId":"get_annotations","summary":"Tijdlijn van een project","description":"**Wie:** Team; klanten met toegang tot het onderdeel Overzicht.\n\n**Toegang:** Sessie of API-sleutel (lezen of schrijven)","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","parameters":[{"name":"project_id","in":"query","required":true,"schema":{"type":"integer"},"description":"Project-id."},{"name":"days","in":"query","required":false,"schema":{"type":"integer"},"description":"1 tot 800; standaard 28."}],"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"annotations":{"type":"array","items":{"type":"object"},"description":"id, kind, title, detail, url, happened_at"},"can_manage":{"type":"boolean"}}}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}},"post":{"tags":["Projecten en overzicht"],"operationId":"post_annotations","summary":"Gebeurtenis op de tijdlijn of deploysleutel","description":"**Wie:** Eigenaar of lid; kijkers en klanten krijgen 403.\n\n**Toegang:** Sessie of API-sleutel met schrijfrecht","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"action":{"const":"create"},"project_id":{"type":["integer","null"],"description":"Null: voor alle projecten."},"date":{"type":"string","format":"date"},"kind":{"type":"string","enum":["notitie","google","meting","deploy"]},"title":{"type":"string"},"detail":{"type":"string"},"url":{"type":"string","format":"uri"}},"required":["action","title"],"title":"create"},{"type":"object","properties":{"action":{"const":"delete"},"id":{"type":"integer"}},"required":["action","id"],"title":"delete"},{"type":"object","properties":{"action":{"const":"deploy_token"},"project_id":{"type":["integer","null"]}},"required":["action"],"title":"deploy_token"}]}}}},"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"ok":{"const":true}},"title":"create"},{"type":"object","properties":{"ok":{"const":true}},"title":"delete"},{"type":"object","properties":{"ok":{"const":true},"token":{"type":"string","description":"Voor POST /api/deploys en /api/components; één keer te zien."},"url":{"type":"string","format":"uri"}},"title":"deploy_token"}]}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/checklist":{"get":{"tags":["Projecten en overzicht"],"operationId":"get_checklist","summary":"Inrichtingschecklist van een project","description":"**Wie:** Alleen het team (eigenaar, lid of kijker); klanten krijgen 403.\n\n**Toegang:** Sessie of API-sleutel (lezen of schrijven)","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","parameters":[{"name":"project_id","in":"query","required":true,"schema":{"type":"integer"},"description":"Project-id."}],"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"sections":{"type":"array","items":{"type":"object"}},"can_manage":{"type":"boolean"}}}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}},"post":{"tags":["Projecten en overzicht"],"operationId":"post_checklist","summary":"Checklistpunt afvinken of opnieuw controleren","description":"**Wie:** Eigenaar of lid; kijkers en klanten krijgen 403.\n\n**Toegang:** Sessie of API-sleutel met schrijfrecht","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"action":{"const":"set"},"project_id":{"type":"integer"},"key":{"type":"string"},"state":{"type":["string","null"],"enum":["done","na",null],"description":"Null zet het punt terug."},"note":{"type":"string"}},"required":["action","project_id","key"],"title":"set"},{"type":"object","properties":{"action":{"const":"recheck"},"project_id":{"type":"integer"}},"required":["action","project_id"],"title":"recheck"}]}}}},"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"ok":{"const":true},"sections":{"type":"array","items":{"type":"object"}}},"title":"set"},{"type":"object","properties":{"ok":{"const":true},"task_id":{"type":"string","description":"Volg de taak met GET /api/task?id=…"}},"title":"recheck"}]}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/hours":{"get":{"tags":["Projecten en overzicht"],"operationId":"get_hours","summary":"Urenbudget per klant","description":"**Wie:** Alleen het team (eigenaar, lid of kijker); klanten krijgen 403.\n\n**Toegang:** Sessie of API-sleutel (lezen of schrijven)","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","parameters":[{"name":"month","in":"query","required":false,"schema":{"type":"string","pattern":"^\\d{4}-(0[1-9]|1[0-2])$"},"description":"Standaard deze maand."}],"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"month":{"type":"string","pattern":"^\\d{4}-(0[1-9]|1[0-2])$"},"projects":{"type":"array","items":{"type":"object"},"description":"project_id, name, budget, spent, pace"},"entries":{"type":"array","items":{"type":"object"},"description":"id, project_id, project, day, minutes, note, user, advice"},"can_manage":{"type":"boolean"}}}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}},"post":{"tags":["Projecten en overzicht"],"operationId":"post_hours","summary":"Uren boeken en budgetten zetten","description":"**Wie:** Alleen het team (eigenaar, lid of kijker); klanten krijgen 403.\n\n**Toegang:** Sessie of API-sleutel met schrijfrecht","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"action":{"const":"budget"},"project_id":{"type":"integer"},"hours":{"type":["number","null"],"description":"Per maand; leeg is geen afspraak."}},"required":["action","project_id"],"title":"budget","description":"Alleen de eigenaar van de workspace."},{"type":"object","properties":{"action":{"const":"log"},"project_id":{"type":"integer"},"day":{"type":"string","format":"date","description":"Niet in de toekomst."},"minutes":{"type":"integer","description":"1 tot 1440."},"note":{"type":"string"},"recommendation_id":{"type":"integer"}},"required":["action","project_id","minutes"],"title":"log"},{"type":"object","properties":{"action":{"const":"delete"},"id":{"type":"integer"}},"required":["action","id"],"title":"delete","description":"Je eigen uren, of als eigenaar die van anderen."}]}}}},"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"ok":{"const":true}},"title":"budget"},{"type":"object","properties":{"ok":{"const":true},"id":{"type":"integer"}},"title":"log"},{"type":"object","properties":{"ok":{"const":true}},"title":"delete"}]}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/page-insight":{"get":{"tags":["Projecten en overzicht"],"operationId":"get_page_insight","summary":"Wat Studio weet over één pagina","description":"Voor de browserextensie: zoekt het project op domein en geeft crawl, zoektermen, adviezen en snelheid voor dat pad, per onderdeel waar je toegang toe hebt.\n\n**Wie:** Iedereen in de workspace; een klant ziet alleen zijn eigen projecten.\n\n**Toegang:** Sessie of API-sleutel (lezen of schrijven)","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","parameters":[{"name":"url","in":"query","required":true,"schema":{"type":"string","format":"uri"}}],"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"project":{"type":["object","null"],"description":"id, name"},"path":{"type":"string"},"crawl":{"type":["object","null"]},"queries":{"type":"array","items":{"type":"object"}},"advice":{"type":"array","items":{"type":"object"}},"speed":{"type":["object","null"]},"link":{"type":"string","format":"uri"}}}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/domains":{"get":{"tags":["Projecten en overzicht"],"operationId":"get_domains","summary":"Domeinen van een project","description":"**Wie:** Eigenaar of lid (beheer van Website); anderen krijgen 404.\n\n**Toegang:** Sessie of API-sleutel (lezen of schrijven)","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","parameters":[{"name":"project_id","in":"query","required":true,"schema":{"type":"integer"},"description":"Project-id."}],"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"domains":{"type":"array","items":{"type":"object"},"description":"id, domain, record, verified, via (dns|plugin), plugin, primary, source (auto|manual), verified_at, checked_at"}}}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}},"post":{"tags":["Projecten en overzicht"],"operationId":"post_domains","summary":"Domein verifiëren, toevoegen, weghalen of hoofddomein maken","description":"**Wie:** Eigenaar of lid (beheer van Website); anderen krijgen 404.\n\n**Toegang:** Sessie of API-sleutel met schrijfrecht","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"action":{"const":"check"},"project_id":{"type":"integer"},"domain":{"type":"string"}},"required":["action","project_id","domain"],"title":"check"},{"type":"object","properties":{"action":{"const":"add"},"project_id":{"type":"integer"},"domain":{"type":"string","description":"Een domein of adres; Studio bewaart het domein zelf (zonder www)."}},"required":["action","project_id","domain"],"title":"add"},{"type":"object","properties":{"action":{"const":"remove"},"project_id":{"type":"integer"},"domain":{"type":"string"}},"required":["action","project_id","domain"],"title":"remove","description":"Het domein komt niet terug, ook niet via een oude Search Console-property. De sitecontrole op dat domein gaat mee."},{"type":"object","properties":{"action":{"const":"primary"},"project_id":{"type":"integer"},"domain":{"type":"string"},"move":{"type":"boolean","description":"Standaard true: uptimecontroles verhuizen mee en het oude hoofddomein gaat weg."}},"required":["action","project_id","domain"],"title":"primary"}]}}}},"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"ok":{"const":true},"verified":{"type":"boolean"},"domains":{"type":"array","items":{"type":"object"}}},"title":"check"},{"type":"object","properties":{"ok":{"const":true},"verified":{"type":"boolean"},"domains":{"type":"array","items":{"type":"object"}}},"title":"add"},{"type":"object","properties":{"ok":{"const":true},"left":{"type":"object","description":"monitors (string[]), search_console (string[]); wijst nog naar het domein"},"domains":{"type":"array","items":{"type":"object"}}},"title":"remove"},{"type":"object","properties":{"ok":{"const":true},"website":{"type":"object","description":"moved, search_console"},"domains":{"type":"array","items":{"type":"object"}}},"title":"primary"}]}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/mail-funnels":{"get":{"tags":["Projecten en overzicht"],"operationId":"get_mail_funnels","summary":"Mailfunnels uit andere systemen","description":"Wat een site zelf verstuurt (veld `mail_funnels` in het metrics-contract), straks ook Mailchimp en Brevo. Alleen aantallen. Zonder `project_id` alle projecten (alleen het team).\n\n**Wie:** Het team; met `project_id` ook klanten met Mailfunnels.\n\n**Toegang:** Sessie of API-sleutel (lezen of schrijven)","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","parameters":[{"name":"project_id","in":"query","required":false,"schema":{"type":"integer"}},{"name":"days","in":"query","required":false,"schema":{"type":"integer","enum":[7,30,90]}}],"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"days":{"type":"integer"},"funnels":{"type":"array","items":{"type":"object"},"description":"id, key, project_id, project, origin (site|mailchimp|brevo), name, status (actief|aan|uit|weg), trigger, audience, goal, url (alleen team), seen_at, sent, clicked, converted, unsubscribed, delivered, bounced, complained, revenue, click_rate, conversion_rate, unsubscribe_rate, series (date, sent, clicked, converted, unsubscribed), steps (id, name, subject + dezelfde tellers)"}}}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/social-posts":{"get":{"tags":["Projecten en overzicht"],"operationId":"get_social_posts","summary":"Gevolgde posts op social media","description":"**Wie:** Wie de website van het project mag zien.\n\n**Toegang:** Sessie of API-sleutel (lezen of schrijven)","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","parameters":[{"name":"project_id","in":"query","required":true,"schema":{"type":"integer"},"description":"Project-id."}],"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"posts":{"type":"array","items":{"type":"object"},"description":"id, platform (reddit|hackernews|bluesky|mastodon), url, title, community, author, ref, posted_at, score, comments, ratio, last_checked_at, last_error, series (at, score, comments), visitors, signups, days (day, visitors, signups)"},"can_manage":{"type":"boolean"}}}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}},"post":{"tags":["Projecten en overzicht"],"operationId":"post_social_posts","summary":"Een post volgen, bijwerken of niet meer volgen","description":"**Wie:** Wie de website van het project mag beheren.\n\n**Toegang:** Sessie of API-sleutel met schrijfrecht","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"action":{"const":"add"},"project_id":{"type":"integer"},"url":{"type":"string","format":"uri","description":"Link naar een post op Reddit, Hacker News, Bluesky of Mastodon."},"ref":{"type":"string"}},"required":["action","project_id","url"],"title":"add"},{"type":"object","properties":{"action":{"const":"update"},"id":{"type":"integer"},"ref":{"type":"string"}},"required":["action","id"],"title":"update"},{"type":"object","properties":{"action":{"const":"refresh"},"id":{"type":"integer"}},"required":["action","id"],"title":"refresh"},{"type":"object","properties":{"action":{"const":"delete"},"id":{"type":"integer"}},"required":["action","id"],"title":"delete"}]}}}},"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"ok":{"const":true},"id":{"type":"integer"},"error":{"type":["string","null"]}},"title":"add"},{"type":"object","properties":{"ok":{"const":true}},"title":"update"},{"type":"object","properties":{"ok":{"const":true}},"title":"refresh"},{"type":"object","properties":{"ok":{"const":true}},"title":"delete"}]}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/site-events":{"get":{"tags":["Projecten en overzicht"],"operationId":"get_site_events","summary":"Sitegebeurtenissen van een project","description":"**Wie:** Alleen het team (eigenaar, lid of kijker); klanten krijgen 403.\n\n**Toegang:** Sessie of API-sleutel (lezen of schrijven)","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","parameters":[{"name":"project_id","in":"query","required":true,"schema":{"type":"integer"},"description":"Project-id."},{"name":"status","in":"query","required":false,"schema":{"type":"string","enum":["ok","opnieuw","dubbel","mislukt","geweigerd","ongeldig"]}},{"name":"entry","in":"query","required":false,"schema":{"type":"integer"},"description":"Eén regel uit het logboek, met runs_detail (automatisering, voorwaarden, acties)."}],"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"log":{"type":"array","items":{"type":"object"},"description":"id, event, event_id, data, private_keys (alleen namen), status, reason, http_status, runs, duration_ms, received_at; de laatste 100"},"hook":{"type":["object","null"],"description":"received, last_at, created_at"},"events":{"type":"array","items":{"type":"object"},"description":"event, total, refs (ref, n), days (day, n); 30 dagen"},"automations":{"type":"array","items":{"type":"object"},"description":"id, name, enabled, event"},"retrying":{"type":"integer"},"can_manage":{"type":"boolean"}}}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}},"post":{"tags":["Projecten en overzicht"],"operationId":"post_site_events","summary":"Adres voor sitegebeurtenissen maken of weghalen","description":"**Wie:** Eigenaar of lid; kijkers en klanten krijgen 403.\n\n**Toegang:** Sessie of API-sleutel met schrijfrecht","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"action":{"const":"create"},"project_id":{"type":"integer"}},"required":["action","project_id"],"title":"create","description":"Een nieuw adres vervangt het oude. Het geheim is maar één keer te zien."},{"type":"object","properties":{"action":{"const":"delete"},"project_id":{"type":"integer"}},"required":["action","project_id"],"title":"delete"}]}}}},"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"ok":{"const":true},"url":{"type":"string"},"secret":{"type":"string"}},"title":"create"},{"type":"object","properties":{"ok":{"const":true}},"title":"delete"}]}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/project-tips":{"get":{"tags":["Projecten en overzicht"],"operationId":"get_project_tips","summary":"Wat je bij een project nog kunt instellen","description":"Uit de basis, wat Studio op de site ziet maar niet gekoppeld is, en wat minstens de helft van de projecten van dezelfde soort heeft.\n\n**Wie:** Alleen het team (eigenaar, lid of kijker); klanten krijgen 403.\n\n**Toegang:** Sessie of API-sleutel (lezen of schrijven)","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","parameters":[{"name":"project_id","in":"query","required":true,"schema":{"type":"integer"},"description":"Project-id."},{"name":"all","in":"query","required":false,"schema":{"type":"boolean"},"description":"Ook de weggeklikte."}],"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"tips":{"type":"array","items":{"type":"object"},"description":"key, source (basis|gezien|soortgelijk), title, why, action {label, to}, peers (?object: count, total, template), dismissed"}}}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}},"post":{"tags":["Projecten en overzicht"],"operationId":"post_project_tips","summary":"Tip wegklikken of terugzetten","description":"**Wie:** Alleen het team (eigenaar, lid of kijker); klanten krijgen 403.\n\n**Toegang:** Sessie of API-sleutel met schrijfrecht","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"action":{"const":"dismiss"},"project_id":{"type":"integer"},"key":{"type":"string"}},"required":["action","project_id","key"],"title":"dismiss","description":"Voor het hele team."},{"type":"object","properties":{"action":{"const":"restore"},"project_id":{"type":"integer"},"key":{"type":"string"}},"required":["action","project_id","key"],"title":"restore"}]}}}},"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"ok":{"const":true},"tips":{"type":"array","items":{"type":"object"}}},"title":"dismiss"},{"type":"object","properties":{"ok":{"const":true},"tips":{"type":"array","items":{"type":"object"}}},"title":"restore"}]}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/connections":{"get":{"tags":["Bronnen en koppelingen"],"operationId":"get_connections","summary":"Google-koppelingen met hun GA4-properties","description":"**Wie:** Alleen het team (eigenaar, lid of kijker); klanten krijgen 403.\n\n**Toegang:** Sessie of API-sleutel (lezen of schrijven)","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"connections":{"type":"array","items":{"type":"object"},"description":"id, kind, google_email, status, own_key, usable, created_at, properties"}}}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}},"post":{"tags":["Bronnen en koppelingen"],"operationId":"post_connections","summary":"Service-account koppelen, vervangen of weghalen","description":"**Wie:** Eigenaar of lid; kijkers en klanten krijgen 403.\n\n**Toegang:** Sessie of API-sleutel met schrijfrecht","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"action":{"const":"create"},"key":{"type":["object","string"],"description":"De service-account-JSON, als object of tekst. Wordt meteen bij Google getest."}},"required":["action","key"],"title":"create"},{"type":"object","properties":{"action":{"const":"replace_key"},"connection_id":{"type":"integer"},"key":{"type":["object","string"]}},"required":["action","connection_id","key"],"title":"replace_key","description":"Behoudt de koppeling en alle indelingen; de oude sleutel blijft actief als de nieuwe niet werkt."},{"type":"object","properties":{"action":{"const":"toggle"},"property_id":{"type":"integer"},"enabled":{"type":"boolean"}},"required":["action","property_id","enabled"],"title":"toggle"},{"type":"object","properties":{"action":{"const":"refresh"}},"required":["action"],"title":"refresh","description":"Leegt de caches van de workspace, bijvoorbeeld na nieuwe leestoegang in Analytics."},{"type":"object","properties":{"action":{"const":"delete"},"connection_id":{"type":"integer"}},"required":["action","connection_id"],"title":"delete"}]}}}},"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"ok":{"const":true},"connection_id":{"type":"integer"},"google_email":{"type":"string","format":"email"},"property_count":{"type":"integer"}},"title":"create"},{"type":"object","properties":{"ok":{"const":true},"google_email":{"type":"string","format":"email"},"property_count":{"type":"integer"}},"title":"replace_key"},{"type":"object","properties":{"ok":{"const":true}},"title":"toggle"},{"type":"object","properties":{"ok":{"const":true}},"title":"refresh"},{"type":"object","properties":{"ok":{"const":true}},"title":"delete"}]}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/connections/google":{"get":{"tags":["Bronnen en koppelingen"],"operationId":"get_connections_google","summary":"Koppelen met Google starten (OAuth)","description":"Stuurt de browser naar Google voor leestoegang tot Analytics, Search Console en het Bedrijfsprofiel. Bedoeld voor de browser.\n\n**Wie:** Eigenaar of lid; kijkers en klanten krijgen 403.\n\n**Toegang:** Sessie of API-sleutel (lezen of schrijven)","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","responses":{"302":{"description":"Doorsturen; het adres staat in Location.","headers":{"Location":{"schema":{"type":"string","format":"uri"}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/connections/google/callback":{"get":{"tags":["Bronnen en koppelingen"],"operationId":"get_connections_google_callback","summary":"Terugkeer van Google na koppelen","description":"**Toegang:** Geen inlog","security":[],"x-studio-auth":"public","responses":{"200":{"description":"Gelukt.","content":{"text/html":{"schema":{"type":"string"}}}}}}},"/api/connections/oauth/{provider}":{"get":{"tags":["Bronnen en koppelingen"],"operationId":"get_connections_oauth_provider","summary":"Koppelen met Teamleader of Microsoft Advertising starten (OAuth)","description":"`provider` is `teamleader` of `microsoft_ads`. Stuurt de browser naar de dienst; bij terugkeer bewaart instnt studio het refresh-token versleuteld bij de koppeling. Zonder app op de server (client-ID en geheim in .env) gaat de browser terug met `oauth=niet-ingericht`.\n\n**Wie:** Eigenaar of lid; kijkers en klanten krijgen 403.\n\n**Toegang:** Sessie of API-sleutel (lezen of schrijven)","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","parameters":[{"name":"provider","in":"path","required":true,"schema":{"type":"string"}},{"name":"integration_id","in":"query","required":true,"schema":{"type":"integer"},"description":"Een koppeling van de soort teamleader of microsoft_ads, eerst aangemaakt met POST /api/integrations."}],"responses":{"302":{"description":"Doorsturen; het adres staat in Location.","headers":{"Location":{"schema":{"type":"string","format":"uri"}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/connections/oauth/{provider}/callback":{"get":{"tags":["Bronnen en koppelingen"],"operationId":"get_connections_oauth_provider_callback","summary":"Terugkeer van Teamleader of Microsoft na koppelen","description":"**Toegang:** Geen inlog","security":[],"x-studio-auth":"public","parameters":[{"name":"provider","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Gelukt.","content":{"text/html":{"schema":{"type":"string"}}}}}}},"/api/search-console":{"get":{"tags":["Bronnen en koppelingen"],"operationId":"get_search_console","summary":"Search Console-properties","description":"**Wie:** Alleen het team (eigenaar, lid of kijker); klanten krijgen 403.\n\n**Toegang:** Sessie of API-sleutel (lezen of schrijven)","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"sites":{"type":"array","items":{"type":"object"},"description":"id, project_id, connection_id, site_url, display_name, status"}}}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}},"post":{"tags":["Bronnen en koppelingen"],"operationId":"post_search_console","summary":"Search Console-properties toevoegen en indelen","description":"**Wie:** Eigenaar of lid; kijkers en klanten krijgen 403.\n\n**Toegang:** Sessie of API-sleutel met schrijfrecht","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"action":{"const":"available"},"connection_id":{"type":"integer"}},"required":["action","connection_id"],"title":"available"},{"type":"object","properties":{"action":{"const":"create"},"project_id":{"type":"integer"},"connection_id":{"type":"integer"},"site_url":{"type":"string"}},"required":["action","project_id","connection_id","site_url"],"title":"create"},{"type":"object","properties":{"action":{"const":"update"},"site_id":{"type":"integer"},"display_name":{"type":"string"}},"required":["action","site_id"],"title":"update"},{"type":"object","properties":{"action":{"const":"assign"},"site_id":{"type":"integer"},"project_id":{"type":["integer","null"]}},"required":["action","site_id"],"title":"assign"},{"type":"object","properties":{"action":{"const":"delete"},"site_id":{"type":"integer"}},"required":["action","site_id"],"title":"delete"}]}}}},"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"ok":{"const":true},"sites":{"type":"array","items":{"type":"object"},"description":"site_url"}},"title":"available"},{"type":"object","properties":{"ok":{"const":true},"site_id":{"type":"integer"}},"title":"create"},{"type":"object","properties":{"ok":{"const":true}},"title":"update"},{"type":"object","properties":{"ok":{"const":true}},"title":"assign"},{"type":"object","properties":{"ok":{"const":true}},"title":"delete"}]}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/sources":{"get":{"tags":["Bronnen en koppelingen"],"operationId":"get_sources","summary":"Eigen systemen (instnt-metrics)","description":"**Wie:** Alleen het team (eigenaar, lid of kijker); klanten krijgen 403.\n\n**Toegang:** Sessie of API-sleutel (lezen of schrijven)","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"sources":{"type":"array","items":{"type":"object"},"description":"id, project_id, name, url, status"}}}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}},"post":{"tags":["Bronnen en koppelingen"],"operationId":"post_sources","summary":"Eigen systeem koppelen of wijzigen","description":"**Wie:** Eigenaar of lid; kijkers en klanten krijgen 403.\n\n**Toegang:** Sessie of API-sleutel met schrijfrecht","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"action":{"const":"create"},"name":{"type":"string"},"url":{"type":"string","format":"uri","description":"https; http alleen voor localhost."},"token":{"type":"string"},"project_id":{"type":"integer"}},"required":["action","name","url","token"],"title":"create","description":"Wordt meteen getest tegen het instnt-metrics-contract; `422 source_rejected` met de reden als dat faalt."},{"type":"object","properties":{"action":{"const":"update"},"source_id":{"type":"integer"},"name":{"type":"string"},"url":{"type":"string","format":"uri"},"token":{"type":"string","description":"Leeg houdt het bestaande token."}},"required":["action","source_id","name"],"title":"update"},{"type":"object","properties":{"action":{"const":"assign"},"source_id":{"type":"integer"},"project_id":{"type":["integer","null"]}},"required":["action","source_id"],"title":"assign"},{"type":"object","properties":{"action":{"const":"delete"},"source_id":{"type":"integer"}},"required":["action","source_id"],"title":"delete"}]}}}},"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"ok":{"const":true},"source_id":{"type":"integer"},"preview":{"type":"object"}},"title":"create"},{"type":"object","properties":{"ok":{"const":true}},"title":"update"},{"type":"object","properties":{"ok":{"const":true}},"title":"assign"},{"type":"object","properties":{"ok":{"const":true}},"title":"delete"}]}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/integrations":{"get":{"tags":["Bronnen en koppelingen"],"operationId":"get_integrations","summary":"Aanvullende diensten van een project","description":"`oauth` staat er alleen bij teamleader en microsoft_ads: `connected` (er is een token) en `available` (de server kan koppelen).\n\n**Wie:** Team; klanten met toegang tot het onderdeel Website.\n\n**Toegang:** Sessie of API-sleutel (lezen of schrijven)","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","parameters":[{"name":"project_id","in":"query","required":true,"schema":{"type":"integer"},"description":"Project-id."}],"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"integrations":{"type":"array","items":{"type":"object"},"description":"id, project_id, kind, name, status, config, oauth"}}}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}},"post":{"tags":["Bronnen en koppelingen"],"operationId":"post_integrations","summary":"Dienst koppelen, testen of wijzigen","description":"**Wie:** Eigenaar of lid; kijkers en klanten krijgen 403.\n\n**Toegang:** Sessie of API-sleutel met schrijfrecht","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"action":{"const":"create"},"project_id":{"type":"integer"},"kind":{"type":"string","description":"Bijvoorbeeld clarity, sentry, umami, posthog, mollie, stripe, github, bing, dataforseo, shopify, woocommerce, appstore_connect. De volledige lijst staat in de bronnenmarkt."},"config":{"type":"object","description":"Voor appstore_connect: `account_id` en `app_id` (zie /api/appstore-accounts). Een config met issuer_id, key_id en private_key wordt een Apple-account."},"name":{"type":"string"}},"required":["action","project_id","kind","config"],"title":"create"},{"type":"object","properties":{"action":{"const":"update"},"integration_id":{"type":"integer"},"config":{"type":"object","description":"Een leeg geheim veld houdt het bestaande geheim."}},"required":["action","integration_id","config"],"title":"update"},{"type":"object","properties":{"action":{"const":"test"},"integration_id":{"type":"integer"}},"required":["action","integration_id"],"title":"test","description":"Haalt meteen één keer op."},{"type":"object","properties":{"action":{"const":"appstore_analytics"},"integration_id":{"type":"integer"},"key_id":{"type":"string","description":"Sleutel-ID van een App Store Connect-sleutel met de rol Admin."},"private_key":{"type":"string","description":"Inhoud van het .p8-bestand van die sleutel."}},"required":["action","integration_id","key_id","private_key"],"title":"appstore_analytics","description":"Alleen voor een App Store Connect-koppeling: vraagt App Analytics eenmalig aan bij Apple. De Admin-sleutel wordt alleen voor deze aanvraag gebruikt en niet bewaard."},{"type":"object","properties":{"action":{"const":"delete"},"integration_id":{"type":"integer"}},"required":["action","integration_id"],"title":"delete"}]}}}},"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"ok":{"const":true},"integration_id":{"type":"integer"}},"title":"create"},{"type":"object","properties":{"ok":{"const":true}},"title":"update"},{"type":"object","properties":{"ok":{"const":true},"testable":{"type":"boolean"},"passed":{"type":"boolean"},"metrics":{"type":"object"},"items":{"type":"array","items":{"type":"string"}},"error":{"type":"string"}},"title":"test"},{"type":"object","properties":{"ok":{"const":true},"analytics":{"type":"boolean"}},"title":"appstore_analytics"},{"type":"object","properties":{"ok":{"const":true}},"title":"delete"}]}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/appstore-accounts":{"get":{"tags":["Bronnen en koppelingen"],"operationId":"get_appstore_accounts","summary":"Apple-accounts voor App Store Connect","description":"Per account de apps van het team en aan welk project elke app hangt. De .p8-sleutel komt nooit terug.\n\n**Wie:** Alleen het team (eigenaar, lid of kijker); klanten krijgen 403.\n\n**Toegang:** Sessie of API-sleutel (lezen of schrijven)","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"accounts":{"type":"array","items":{"type":"object"},"description":"id, name, issuer_id, key_id, vendor_number, key_configured, status, status_message, checked_at, history (running, pending), keys (id, role, role_label, key_id, status, status_message, denied), webhook (url, secret; alleen voor beheerders), apps (id, name, bundle_id, sku, downloads_total, downloads_complete, downloads_30d, project_id, project_name, integration_id, analytics)"},"projects":{"type":"array","items":{"type":"object"},"description":"id, name"}}}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}},"post":{"tags":["Bronnen en koppelingen"],"operationId":"post_appstore_accounts","summary":"Apple-account toevoegen, apps koppelen of App Analytics aanzetten","description":"**Wie:** Eigenaar of lid; kijkers en klanten krijgen 403.\n\n**Toegang:** Sessie of API-sleutel met schrijfrecht","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"action":{"const":"create"},"issuer_id":{"type":"string"},"key_id":{"type":"string"},"private_key":{"type":"string","description":"Inhoud van het .p8-bestand (rol Sales and Reports)."},"vendor_number":{"type":"string","description":"Eén of meer vendornummers, gescheiden door een komma."},"name":{"type":"string"}},"required":["action","issuer_id","key_id","private_key"],"title":"create","description":"Test de sleutel eerst bij Apple door de apps op te halen; een sleutel die Apple weigert wordt niet opgeslagen. Dezelfde issuer en sleutel-ID werken het bestaande account bij."},{"type":"object","properties":{"action":{"const":"update"},"account_id":{"type":"integer"},"name":{"type":"string"},"issuer_id":{"type":"string","description":"Een gewijzigde ID wordt eerst bij Apple getest."},"key_id":{"type":"string","description":"Een gewijzigde ID wordt eerst bij Apple getest."},"vendor_number":{"type":"string","description":"Eén of meer, gescheiden door een komma. Een ander nummer haalt de geschiedenis opnieuw op."},"private_key":{"type":"string","description":"Leeg houdt de bestaande sleutel."}},"required":["action","account_id"],"title":"update"},{"type":"object","properties":{"action":{"const":"refresh"},"account_id":{"type":"integer"}},"required":["action","account_id"],"title":"refresh","description":"Haalt de apps opnieuw op bij Apple."},{"type":"object","properties":{"action":{"const":"link"},"account_id":{"type":"integer"},"app_id":{"type":"string"},"project_id":{"type":["integer","null"],"description":"Leeg of null ontkoppelt de app."}},"required":["action","account_id","app_id"],"title":"link","description":"Een app hangt aan hooguit één project, en een project heeft één App Store Connect-bron: een nieuwe koppeling vervangt de oude."},{"type":"object","properties":{"action":{"const":"history"},"account_id":{"type":"integer"}},"required":["action","account_id"],"title":"history","description":"Haalt de ontbrekende verkooprapporten op: jaren (tien jaar terug), maanden en dagen (één jaar). Gebeurt ook vanzelf na het toevoegen en twee keer per dag; een afgesloten periode vraagt Studio nooit opnieuw op."},{"type":"object","properties":{"action":{"const":"analytics"},"account_id":{"type":"integer"},"key_id":{"type":"string","description":"Sleutel-ID van een sleutel met de rol Admin."},"private_key":{"type":"string"},"app_ids":{"type":"array","items":{"type":"string"},"description":"Leeg is alle apps van het account."}},"required":["action","account_id","key_id","private_key"],"title":"analytics","description":"Vraagt App Analytics aan per app. De Admin-sleutel wordt alleen voor deze aanvragen gebruikt en niet bewaard."},{"type":"object","properties":{"action":{"const":"delete"},"account_id":{"type":"integer"}},"required":["action","account_id"],"title":"delete","description":"`409 in_use` zolang er apps aan projecten hangen."},{"type":"object","properties":{"action":{"const":"key_add"},"account_id":{"type":"integer"},"role":{"type":"string","enum":["sales","developer","customer_support","marketing","app_manager","admin"]},"key_id":{"type":"string"},"private_key":{"type":"string"}},"required":["action","account_id","role","key_id","private_key"],"title":"key_add","description":"Extra sleutel met een eigen rol, van hetzelfde team (zelfde issuer-ID). Wordt eerst bij Apple getest. Studio kiest per onderdeel de sleutel met de minste rechten die het mag, en onthoudt een weigering (403) een week. Developer opent builddetails, feedback uit TestFlight, diagnoses, Xcode Cloud, Game Center en aankopen; Customer Support antwoorden op reviews en naam en ondertitel van de winkelpagina."},{"type":"object","properties":{"action":{"const":"key_delete"},"account_id":{"type":"integer"},"key_id":{"type":"integer","description":"Het id uit `keys`, niet de sleutel-ID van Apple."}},"required":["action","account_id","key_id"],"title":"key_delete"},{"type":"object","properties":{"action":{"const":"webhook"},"account_id":{"type":"integer"}},"required":["action","account_id"],"title":"webhook","description":"Nieuw adres en geheim voor meldingen van App Store Connect (Gebruikers en toegang → Integraties → Webhooks). Een oud adres werkt daarna niet meer."}]}}}},"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"ok":{"const":true},"account_id":{"type":"integer"},"apps":{"type":"integer"}},"title":"create"},{"type":"object","properties":{"ok":{"const":true}},"title":"update"},{"type":"object","properties":{"ok":{"const":true},"apps":{"type":"integer"}},"title":"refresh"},{"type":"object","properties":{"ok":{"const":true},"integration_id":{"type":["integer","null"]}},"title":"link"},{"type":"object","properties":{"ok":{"const":true},"started":{"type":"boolean"},"pending":{"type":"integer"}},"title":"history"},{"type":"object","properties":{"ok":{"const":true},"enabled":{"type":"array","items":{"type":"string"}},"failed":{"type":"object","description":"app_id → melding"}},"title":"analytics"},{"type":"object","properties":{"ok":{"const":true}},"title":"delete"},{"type":"object","properties":{"ok":{"const":true}},"title":"key_add"},{"type":"object","properties":{"ok":{"const":true}},"title":"key_delete"},{"type":"object","properties":{"ok":{"const":true},"webhook":{"type":"object","description":"url, secret"}},"title":"webhook"}]}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/google-play-accounts":{"get":{"tags":["Bronnen en koppelingen"],"operationId":"get_google_play_accounts","summary":"Google Play-accounts","description":"Per account de apps die het service-account ziet, met installaties en aan welk project elke app hangt. De sleutel komt nooit terug, alleen het e-mailadres van het service-account.\n\n**Wie:** Alleen het team (eigenaar, lid of kijker); klanten krijgen 403.\n\n**Toegang:** Sessie of API-sleutel (lezen of schrijven)","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"accounts":{"type":"array","items":{"type":"object"},"description":"id, name, client_email, bucket, status, status_message, checked_at, apps (package_name, title, installs_total, installs_30d, project_id, project_name, state)"},"projects":{"type":"array","items":{"type":"object"},"description":"id, name"},"can_manage":{"type":"boolean"}}}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}},"post":{"tags":["Bronnen en koppelingen"],"operationId":"post_google_play_accounts","summary":"Google Play-account toevoegen of apps koppelen","description":"**Wie:** Eigenaar of lid; kijkers en klanten krijgen 403.\n\n**Toegang:** Sessie of API-sleutel met schrijfrecht","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"action":{"const":"create"},"key":{"type":"string","description":"De JSON-sleutel van een service-account uit Google Cloud, uitgenodigd in Play Console."},"bucket":{"type":"string","description":"Cloud Storage-URI van de rapporten (gs://pubsite_prod_…). Zonder bucket geen installaties."},"name":{"type":"string"}},"required":["action","key"],"title":"create","description":"Test de sleutel eerst bij Google door de apps op te halen; een sleutel die niets mag, wordt niet opgeslagen. Hetzelfde service-account werkt het bestaande account bij."},{"type":"object","properties":{"action":{"const":"update"},"account_id":{"type":"integer"},"name":{"type":"string"},"bucket":{"type":"string"},"key":{"type":"string","description":"Alleen een nieuwe sleutel van hetzelfde service-account."}},"required":["action","account_id"],"title":"update"},{"type":"object","properties":{"action":{"const":"refresh"},"account_id":{"type":"integer"}},"required":["action","account_id"],"title":"refresh","description":"Apps en installatierapporten opnieuw ophalen; hooguit eens per minuut."},{"type":"object","properties":{"action":{"const":"link"},"account_id":{"type":"integer"},"package_name":{"type":"string"},"project_id":{"type":["integer","null"],"description":"Leeg of null ontkoppelt de app."}},"required":["action","account_id","package_name"],"title":"link","description":"Een app hangt aan hooguit één project; daarna volgt meteen een eerste ronde (installaties, vitals, reviews, versies)."},{"type":"object","properties":{"action":{"const":"delete"},"account_id":{"type":"integer"}},"required":["action","account_id"],"title":"delete","description":"Haalt ook de koppelingen van de apps bij projecten weg. De opgehaalde installaties gaan mee."}]}}}},"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"ok":{"const":true},"account_id":{"type":"integer"},"apps":{"type":"integer"}},"title":"create"},{"type":"object","properties":{"ok":{"const":true}},"title":"update"},{"type":"object","properties":{"ok":{"const":true},"apps":{"type":"integer"},"files":{"type":"integer"}},"title":"refresh"},{"type":"object","properties":{"ok":{"const":true},"linked":{"type":"boolean"},"integration_id":{"type":"integer"}},"title":"link"},{"type":"object","properties":{"ok":{"const":true}},"title":"delete"}]}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/google-play":{"get":{"tags":["Bronnen en koppelingen"],"operationId":"get_google_play","summary":"Google Play: installaties, vitals en versies van een app","description":"Per Google Play-app van het project: installaties door gebruikers per dag (365 dagen) en maand uit de maandrapporten in Cloud Storage, actieve toestellen, beoordeling, Android vitals (door gebruikers gemerkte crashes en ANR, gemiddeld over 28 dagen, met de grens van Google) en de versies per track. Een onderdeel dat uit staat bij het account geeft `null`. `null` in een dag is onbekend, geen nul. Reviews staan onder /api/reputation. Vraagt het onderdeel Product.\n\n**Wie:** Iedereen in de workspace; een klant ziet alleen zijn eigen projecten.\n\n**Toegang:** Sessie of API-sleutel (lezen of schrijven)","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","parameters":[{"name":"project_id","in":"query","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"apps":{"type":"array","items":{"type":"object"},"description":"account_id, package_name, name, store_url, bucket, installs (total (downloads, complete), d7, d30, prev30, uninstalls_30d, active_devices, active_on, rating, days (day, value), months (month, value, running), first_month) of null, vitals (user_crash_rate, user_anr_rate, crash_rate, anr_rate, crash_limit, anr_limit, crash_bad, anr_bad, until, days (day, crash, anr)) of null, tracks (track, label, releases (name, status, version_codes, user_fraction, notes)) of null, tracks_at, fetched_at"}}}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/app-store":{"get":{"tags":["Bronnen en koppelingen"],"operationId":"get_app_store","summary":"App Store voor makers: versies, TestFlight, reviews, prestaties, abonnementen en winkelpagina","description":"Per app van het project wat App Store Connect weet, opgehaald elk half uur (versies, builds, testgroepen, feedback, reviews) en één keer per dag (de rest). `sections` geeft per onderdeel de stand: `ok`, `leeg`, `fout`, of `sleutel` met in `message` welke rol er nodig is. Abonnementen alleen voor het team of een klant die het overzicht mag goedkeuren. Vraagt het onderdeel Product.\n\n**Wie:** Iedereen in de workspace; een klant ziet alleen zijn eigen projecten.\n\n**Toegang:** Sessie of API-sleutel (lezen of schrijven)","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","parameters":[{"name":"project_id","in":"query","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"apps":{"type":"array","items":{"type":"object"},"description":"account_id, app_id, name, roles, sections, versions, testflight (builds, groups, feedback), reviews (items, count, average, per_rating, open, territories), performance (versions, metrics, insights, diagnostics), subscriptions (events_30d, active, trials, proceeds_30d, days, catalog) of null, store (current, changes), ci, game_center"},"can_reply":{"type":"boolean"},"team":{"type":"boolean"}}}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}},"post":{"tags":["Bronnen en koppelingen"],"operationId":"post_app_store","summary":"Reviews beantwoorden, crash als prompt, nu ophalen","description":"**Wie:** Eigenaar of lid; kijkers en klanten krijgen 403.\n\n**Toegang:** Sessie of API-sleutel met schrijfrecht","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"action":{"const":"reply"},"project_id":{"type":"integer"},"review_id":{"type":"integer","description":"Het `id` uit reviews.items."},"body":{"type":"string","description":"Hooguit 5970 tekens."}},"required":["action","project_id","review_id","body"],"title":"reply","description":"Plaatst of vervangt het antwoord bij Apple. Vraagt een sleutel met de rol Customer Support of App Manager."},{"type":"object","properties":{"action":{"const":"delete_reply"},"project_id":{"type":"integer"},"review_id":{"type":"integer"}},"required":["action","project_id","review_id"],"title":"delete_reply"},{"type":"object","properties":{"action":{"const":"suggest_reply"},"project_id":{"type":"integer"},"review_id":{"type":"integer"}},"required":["action","project_id","review_id"],"title":"suggest_reply","description":"Claude schrijft een voorstel in de merkstem; het staat daarna als `suggestion` bij de review. Nooit automatisch geplaatst."},{"type":"object","properties":{"action":{"const":"prompt"},"project_id":{"type":"integer"},"feedback_id":{"type":"integer"}},"required":["action","project_id","feedback_id"],"title":"prompt","description":"Prompt voor een Claude Code-sessie in de repo van de app, met de crashlog."},{"type":"object","properties":{"action":{"const":"sync"},"project_id":{"type":"integer"}},"required":["action","project_id"],"title":"sync","description":"Hooguit eens per minuut (429)."}]}}}},"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"ok":{"const":true},"response":{"type":"object","description":"id, body, state, modified"}},"title":"reply"},{"type":"object","properties":{"ok":{"const":true}},"title":"delete_reply"},{"type":"object","properties":{"ok":{"const":true},"task_id":{"type":"integer"}},"title":"suggest_reply"},{"type":"object","properties":{"ok":{"const":true},"prompt":{"type":"string"}},"title":"prompt"},{"type":"object","properties":{"ok":{"const":true},"started":{"type":"boolean"}},"title":"sync"}]}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/modules":{"get":{"tags":["Bronnen en koppelingen"],"operationId":"get_modules","summary":"Modules en hun stand","description":"Catalogus van modules met per module of hij in het plan zit, aan staat voor de werkruimte en (met `project_id`) voor het project, en of de bron die nodig is gekoppeld is. `status`: `aan`, `uit`, `plan`, `project_uit` of `nodig`.\n\n**Wie:** Team; een klant alleen met project_id, en dan alleen aan of uit per module.\n\n**Toegang:** Sessie of API-sleutel (lezen of schrijven)","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","parameters":[{"name":"project_id","in":"query","required":false,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"modules":{"type":"array","items":{"type":"object"},"description":"key, label, uitleg, icon, min_plan, needs_label, scope, plan_allows, workspace_on, project_on, needs_met, projects_ready, status"},"can_manage":{"type":"boolean"}}}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}},"post":{"tags":["Bronnen en koppelingen"],"operationId":"post_modules","summary":"Module aan- of uitzetten","description":"**Wie:** Eigenaar of lid; kijkers en klanten krijgen 403.\n\n**Toegang:** Sessie of API-sleutel met schrijfrecht","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"action":{"const":"workspace"},"module":{"type":"string"},"enabled":{"type":"boolean"}},"required":["action","module","enabled"],"title":"workspace","description":"`402 plan_limit` als de module niet in het plan zit."},{"type":"object","properties":{"action":{"const":"project"},"project_id":{"type":"integer"},"module":{"type":"string"},"enabled":{"type":"boolean"}},"required":["action","project_id","module","enabled"],"title":"project","description":"Een project kan een module alleen uitzetten; aan volgt de werkruimte."}]}}}},"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"ok":{"const":true},"modules":{"type":"array","items":{"type":"object"}}},"title":"workspace"},{"type":"object","properties":{"ok":{"const":true},"modules":{"type":"array","items":{"type":"object"}}},"title":"project"}]}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/orders":{"get":{"tags":["Bronnen en koppelingen"],"operationId":"get_orders","summary":"Bestellingen","description":"Losse bestellingen uit Shopify, WooCommerce en eigen systemen, zonder gegevens van de klant, met een link naar de order in de winkel. Alleen als de module Bestellingen aan staat; alleen voor het team of een klant die het overzicht mag goedkeuren. Met `scope=today` per project de bestellingen van vandaag.\n\n**Wie:** Team; klanten met toegang tot het onderdeel Overzicht.\n\n**Toegang:** Sessie of API-sleutel (lezen of schrijven)","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","parameters":[{"name":"project_id","in":"query","required":false,"schema":{"type":"integer"}},{"name":"scope","in":"query","required":false,"schema":{"type":"string","enum":["today"]}},{"name":"days","in":"query","required":false,"schema":{"type":"integer"}},{"name":"status","in":"query","required":false,"schema":{"type":"string","enum":["open","betaald","verzonden","afgerond","geannuleerd","terugbetaald","mislukt"]}},{"name":"q","in":"query","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"orders":{"type":"array","items":{"type":"object"},"description":"id, source, number, ordered_at, status, total_cents, currency, items (name, qty), admin_url"},"counts":{"type":"object"},"sold":{"type":"integer"},"total_cents":{"type":"integer"},"module":{"type":["object","null"]},"synced_at":{"type":["string","null"],"format":"date-time"},"projects":{"type":"array","items":{"type":"object"},"description":"Alleen bij scope=today: project_id, name, count, total_cents, currency, latest."}}}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}},"post":{"tags":["Bronnen en koppelingen"],"operationId":"post_orders","summary":"Bestellingen nu ophalen","description":"**Wie:** Eigenaar of lid; kijkers en klanten krijgen 403.\n\n**Toegang:** Sessie of API-sleutel met schrijfrecht","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"action":{"const":"refresh"},"project_id":{"type":"integer"}},"required":["action","project_id"],"title":"refresh"}]}}}},"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"ok":{"const":true},"orders":{"type":"integer"},"errors":{"type":"array","items":{"type":"string"}}},"title":"refresh"}]}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/landing-pages":{"get":{"tags":["Bronnen en koppelingen"],"operationId":"get_landing_pages","summary":"Module Landingspagina's","description":"Aangewezen landingspagina's met bezoek (GA4, anders het sitescript), conversie, advertentiekosten van gekoppelde Ads-campagnes, formulieren, scrolldiepte (Clarity), Search Console en snelheid, plus A/B-vergelijkingen met de kans dat B beter converteert (Beta-Binomiaal, vanaf 100 bezoeken per variant). Alleen als de module aan staat. Advertentiekosten alleen voor het team of een klant die het overzicht mag goedkeuren. Met `page_id` één pagina met kanalen, zoektermen en verloop.\n\n**Wie:** Team; klanten met toegang tot het onderdeel Website.\n\n**Toegang:** Sessie of API-sleutel (lezen of schrijven)","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","parameters":[{"name":"project_id","in":"query","required":true,"schema":{"type":"integer"},"description":"Project-id."},{"name":"days","in":"query","required":false,"schema":{"type":"integer"},"description":"Periode in dagen, 7–365; standaard 28."},{"name":"page_id","in":"query","required":false,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"pages":{"type":"array","items":{"type":"object"},"description":"id, url, path, name, status, utm_campaign, ads_campaign_ids, thumbnail, visits, visits_source, conversions, conversion_source, conversion_rate, ads, cost_per_conversion_cents, funnel, forms, scroll_depth, search, speed"},"tests":{"type":"array","items":{"type":"object"},"description":"id, name, page_a_id, page_b_id, started_on, ended_on, prob_b_better, min_sessions, verdict"},"suggestions":{"type":"array","items":{"type":"object"},"description":"path, sessions, key_events"},"campaigns":{"type":"array","items":{"type":"object"},"description":"id, name, channel"},"module":{"type":"object"},"can_manage":{"type":"boolean"},"money":{"type":"boolean"},"base_url":{"type":["string","null"],"format":"uri"},"page":{"type":"object","description":"Alleen met page_id: de pagina met channels, queries en series."}}}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}},"post":{"tags":["Bronnen en koppelingen"],"operationId":"post_landing_pages","summary":"Landingspagina's aanwijzen en vergelijken","description":"**Wie:** Eigenaar of lid (beheer van Website); anderen krijgen 404.\n\n**Toegang:** Sessie of API-sleutel met schrijfrecht","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"action":{"const":"create"},"project_id":{"type":"integer"},"url":{"type":"string","description":"Pad (/offerte) of volledig adres op de site van het project."},"name":{"type":"string"},"status":{"type":"string","enum":["live","concept","gestopt"]},"utm_campaign":{"type":"string"},"ads_campaign_ids":{"type":"array","items":{"type":"string"}}},"required":["action","project_id","url"],"title":"create"},{"type":"object","properties":{"action":{"const":"update"},"project_id":{"type":"integer"},"page_id":{"type":"integer"},"name":{"type":"string"},"status":{"type":"string","enum":["live","concept","gestopt"]},"utm_campaign":{"type":"string"},"ads_campaign_ids":{"type":"array","items":{"type":"string"}}},"required":["action","project_id","page_id"],"title":"update"},{"type":"object","properties":{"action":{"const":"delete"},"project_id":{"type":"integer"},"page_id":{"type":"integer"}},"required":["action","project_id","page_id"],"title":"delete"},{"type":"object","properties":{"action":{"const":"test_create"},"project_id":{"type":"integer"},"page_a_id":{"type":"integer"},"page_b_id":{"type":"integer"},"name":{"type":"string"}},"required":["action","project_id","page_a_id","page_b_id"],"title":"test_create"},{"type":"object","properties":{"action":{"const":"test_end"},"project_id":{"type":"integer"},"test_id":{"type":"integer"}},"required":["action","project_id","test_id"],"title":"test_end"},{"type":"object","properties":{"action":{"const":"test_delete"},"project_id":{"type":"integer"},"test_id":{"type":"integer"}},"required":["action","project_id","test_id"],"title":"test_delete"}]}}}},"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"ok":{"const":true},"id":{"type":"integer"}},"title":"create"},{"type":"object","properties":{"ok":{"const":true}},"title":"update"},{"type":"object","properties":{"ok":{"const":true}},"title":"delete"},{"type":"object","properties":{"ok":{"const":true},"id":{"type":"integer"}},"title":"test_create"},{"type":"object","properties":{"ok":{"const":true}},"title":"test_end"},{"type":"object","properties":{"ok":{"const":true}},"title":"test_delete"}]}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/submissions":{"get":{"tags":["Bronnen en koppelingen"],"operationId":"get_submissions","summary":"Formulierinzendingen","description":"Welk formulier wanneer is verstuurd, op welke pagina, met een link naar de inzending in het CMS of de formuliertool. Nooit wat er is ingevuld. Alleen als de module Inzendingen aan staat. `admin_url` alleen voor het team of een klant met Website op goedkeuren; anders `null`. `new`: na de laatst bekeken inzending van deze gebruiker en van de laatste 30 dagen. Met `scope=new` de nieuwe inzendingen per project.\n\n**Wie:** Team; klanten met toegang tot het onderdeel Website.\n\n**Toegang:** Sessie of API-sleutel (lezen of schrijven)","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","parameters":[{"name":"project_id","in":"query","required":false,"schema":{"type":"integer"}},{"name":"scope","in":"query","required":false,"schema":{"type":"string","enum":["new"]}},{"name":"days","in":"query","required":false,"schema":{"type":"integer"},"description":"Periode in dagen, 1–396; standaard 30."},{"name":"form","in":"query","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"submissions":{"type":"array","items":{"type":"object"},"description":"id, source, source_label, form, page, submitted_at, new, admin_url"},"forms":{"type":"array","items":{"type":"object"},"description":"form, count, latest_at"},"total":{"type":"integer"},"unread":{"type":"integer"},"can_open":{"type":"boolean"},"module":{"type":"object"},"projects":{"type":"array","items":{"type":"object"},"description":"Alleen bij scope=new: project_id, name, count, last_id, latest_at."}}}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}},"post":{"tags":["Bronnen en koppelingen"],"operationId":"post_submissions","summary":"Inzendingen als gezien markeren","description":"**Wie:** Team; klanten met toegang tot het onderdeel Website.\n\n**Toegang:** Sessie of API-sleutel met schrijfrecht","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"action":{"const":"seen"},"project_id":{"type":"integer"}},"required":["action","project_id"],"title":"seen","description":"Per gebruiker: alles tot nu toe in dit project telt niet meer als nieuw."}]}}}},"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"ok":{"const":true},"seen_id":{"type":"integer"}},"title":"seen"}]}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/reputation":{"get":{"tags":["Bronnen en koppelingen"],"operationId":"get_reputation","summary":"Reputatie: reviews van alle bronnen","description":"Reviews van het Google Bedrijfsprofiel, Trustpilot, Kiyoh en de App Store samen. `summary.average` en `count` komen van de platforms zelf waar die bekend zijn (Kiyoh omgerekend van 10 naar 5), de rest uit de bewaarde reviews (de laatste 50 tot 100 per bron). `trend` per maand over twaalf maanden. Voorstellen van Claude (`suggestion`) alleen voor het team. Zonder `project_id`: per project dat je onder Vindbaarheid mag zien.\n\n**Wie:** Team; klanten met toegang tot het onderdeel Zoeken.\n\n**Toegang:** Sessie of API-sleutel (lezen of schrijven)","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","parameters":[{"name":"project_id","in":"query","required":false,"schema":{"type":"integer"}},{"name":"source","in":"query","required":false,"schema":{"type":"string","enum":["gbp","trustpilot","kiyoh","appstore","google_play"]}},{"name":"rating","in":"query","required":false,"schema":{"type":"integer"},"description":"Alleen dit aantal sterren, 1–5."},{"name":"open","in":"query","required":false,"schema":{"type":"boolean"},"description":"Alleen zonder antwoord."}],"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"summary":{"type":"object","description":"average, count, new_this_month, answered_pct, open_low, stored"},"sources":{"type":"array","items":{"type":"object"},"description":"source, label, average, count, stored, platform, can_reply"},"trend":{"type":"array","items":{"type":"object"},"description":"month, count, average"},"items":{"type":"array","items":{"type":"object"},"description":"id, source, source_label, rating, score, title, body, author, language, country, url, reviewed_at, reply, can_reply, suggestion"},"can_reply":{"type":"boolean"},"team":{"type":"boolean"},"projects":{"type":"array","items":{"type":"object"},"description":"Alleen zonder project_id: project_id, project, sources, average, count, new_this_month, answered_pct, open_low."}}}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}},"post":{"tags":["Bronnen en koppelingen"],"operationId":"post_reputation","summary":"Reviews beantwoorden","description":"**Wie:** Eigenaar of lid; kijkers en klanten krijgen 403.\n\n**Toegang:** Sessie of API-sleutel met schrijfrecht","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"action":{"const":"reply"},"project_id":{"type":"integer"},"review_id":{"type":"integer","description":"Het `id` uit items."},"body":{"type":"string","description":"Google hooguit 4096 tekens, de App Store 5970."}},"required":["action","project_id","review_id","body"],"title":"reply","description":"Alleen Google en de App Store; Trustpilot en Kiyoh geven `422`. Google vraagt \"Koppel met Google\" met het onderdeel Reviews beantwoorden aan."},{"type":"object","properties":{"action":{"const":"delete_reply"},"project_id":{"type":"integer"},"review_id":{"type":"integer"}},"required":["action","project_id","review_id"],"title":"delete_reply"},{"type":"object","properties":{"action":{"const":"suggest_reply"},"project_id":{"type":"integer"},"review_id":{"type":"integer"}},"required":["action","project_id","review_id"],"title":"suggest_reply","description":"Claude schrijft een voorstel in de merkstem; het staat daarna als `suggestion` bij de review. Nooit automatisch geplaatst."}]}}}},"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"ok":{"const":true},"reply":{"type":"object","description":"body, at, state"}},"title":"reply"},{"type":"object","properties":{"ok":{"const":true}},"title":"delete_reply"},{"type":"object","properties":{"ok":{"const":true},"task_id":{"type":"integer"}},"title":"suggest_reply"}]}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/campaigns":{"get":{"tags":["Bronnen en koppelingen"],"operationId":"get_campaigns","summary":"Campagnes: UTM, advertenties en mailings bij elkaar","description":"Module Campagnes (vanaf Copiloot). Een campagne telt op wat bij haar regels past: GA4 per UTM-campagne, bron en medium, aanmeldingen en betalingen uit het eigen systeem met dezelfde UTM, Google Ads-, Meta- en LinkedIn-campagnes en mailings uit Mailchimp en Brevo. Regels van dezelfde soort: één moet kloppen; verschillende UTM-soorten: allemaal. `previous` is een even lange periode direct ervoor. Gebruikers zijn per dag opgeteld. Kosten, omzet, budget, CPC, CPA en ROAS alleen voor het team of een klant die het overzicht mag goedkeuren. Zonder `project_id`: alle projecten met de module die je mag zien. Met `campaign_id` ook `series`, `channels`, `sources`, `pages`, `ads` en `mailings`.\n\n**Wie:** Team; klanten met toegang tot het onderdeel Website.\n\n**Toegang:** Sessie of API-sleutel (lezen of schrijven)","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","parameters":[{"name":"project_id","in":"query","required":false,"schema":{"type":"integer"}},{"name":"campaign_id","in":"query","required":false,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"campaigns":{"type":"array","items":{"type":"object"},"description":"id, project_id, name, starts_on, ends_on, budget, goal, rules, period, current, previous, derived, mail"},"suggestions":{"type":"array","items":{"type":"object"},"description":"UTM-campagnes zonder campagne (90 dagen): value, sessions, sources. Alleen met beheerrecht."},"ignored":{"type":"array","items":{"type":"string"}},"linkables":{"type":"array","items":{"type":"object"},"description":"Wat je als regel kunt koppelen: kind, value, label."},"module":{"type":"object"},"money":{"type":"boolean"},"can_manage":{"type":"boolean"},"base_url":{"type":["string","null"]},"campaign":{"type":"object","description":"Met campaign_id."},"projects":{"type":"array","items":{"type":"object"},"description":"Zonder project_id: project_id, name, campaigns."}}}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}},"post":{"tags":["Bronnen en koppelingen"],"operationId":"post_campaigns","summary":"Campagnes beheren","description":"Versturen kan hier niet: dat doe je in Brevo of Mailchimp; instnt studio leest de resultaten.\n\n**Wie:** Eigenaar of lid (beheer van Website); anderen krijgen 404.\n\n**Toegang:** Sessie of API-sleutel met schrijfrecht","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"action":{"const":"create"},"project_id":{"type":"integer"},"name":{"type":"string"},"starts_on":{"type":["string","null"],"format":"date"},"ends_on":{"type":["string","null"],"format":"date"},"budget":{"type":["number","null"],"description":"In euro's."},"goal":{"type":["string","null"]},"rules":{"type":"array","items":{"type":"object"},"description":"kind (utm_campaign|utm_source|utm_medium|google_ads|meta_ads|linkedin_ads|mail), match (exact|prefix|contains, alleen UTM), value. Een Ads-campagne of mailing moet bij het project horen. Hooguit 30."}},"required":["action","project_id","name"],"title":"create","description":"De eerste campagne van een project haalt de GA4-cijfers per campagne meteen op (een half jaar terug)."},{"type":"object","properties":{"action":{"const":"update"},"project_id":{"type":"integer"},"campaign_id":{"type":"integer"},"name":{"type":"string"},"starts_on":{"type":["string","null"],"format":"date"},"ends_on":{"type":["string","null"],"format":"date"},"budget":{"type":["number","null"]},"goal":{"type":["string","null"]},"rules":{"type":"array","items":{"type":"object"},"description":"Vervangt alle regels."}},"required":["action","project_id","campaign_id"],"title":"update"},{"type":"object","properties":{"action":{"const":"delete"},"project_id":{"type":"integer"},"campaign_id":{"type":"integer"}},"required":["action","project_id","campaign_id"],"title":"delete"},{"type":"object","properties":{"action":{"const":"ignore"},"project_id":{"type":"integer"},"value":{"type":"string"}},"required":["action","project_id","value"],"title":"ignore","description":"Deze UTM-campagne niet meer voorstellen."},{"type":"object","properties":{"action":{"const":"unignore"},"project_id":{"type":"integer"},"value":{"type":"string"}},"required":["action","project_id","value"],"title":"unignore"}]}}}},"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"ok":{"const":true},"id":{"type":"integer"}},"title":"create"},{"type":"object","properties":{"ok":{"const":true}},"title":"update"},{"type":"object","properties":{"ok":{"const":true}},"title":"delete"},{"type":"object","properties":{"ok":{"const":true}},"title":"ignore"},{"type":"object","properties":{"ok":{"const":true}},"title":"unignore"}]}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/journey":{"get":{"tags":["Bronnen en koppelingen"],"operationId":"get_journey","summary":"Klantreis: fasen, kanalen en paden als totalen","description":"Module Klantreis (vanaf Inzicht). Elke nacht opgeteld uit GA4, het sitescript, leads, aanmeldingen uit het eigen systeem en bestellingen; geen reis per persoon. `stages`: bezoek, betrokken, lead en klant met de bronnen die meetellen (per projecttype, of zoals ingesteld), de vorige even lange periode en `from_previous` (verhouding van totalen, geen gevolgde groep). `channels`: kanaal × fase; een fase zonder kanaalinformatie staat in `missing`. `paths`: stappen van pagina naar pagina, pagina's met een lead en landingspagina's met belangrijke acties, alleen met minstens `k` keer; `hidden` telt wat daaronder bleef. `ttc`: dagen van aanmelding tot abonnement, alleen met minstens `k` abonnementen. Zonder module: `journey` is null.\n\n**Wie:** Team; klanten met toegang tot het onderdeel Website.\n\n**Toegang:** Sessie of API-sleutel (lezen of schrijven)","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","parameters":[{"name":"project_id","in":"query","required":true,"schema":{"type":"integer"},"description":"Project-id."},{"name":"period","in":"query","required":false,"schema":{"type":"integer"},"description":"28 of 90; standaard 28."}],"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"module":{"type":"object"},"can_manage":{"type":"boolean"},"journey":{"type":["object","null"],"description":"type, type_label, period, range, stages, trend, channels, paths, ttc, sources, custom, stage_labels, computed_at, k"}}}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}},"post":{"tags":["Bronnen en koppelingen"],"operationId":"post_journey","summary":"Klantreis instellen","description":"**Wie:** Eigenaar of lid (beheer van Website); anderen krijgen 404.\n\n**Toegang:** Sessie of API-sleutel met schrijfrecht","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"action":{"const":"settings"},"project_id":{"type":"integer"},"stages":{"type":["object","null"],"description":"Per fase (bezoek, betrokken, lead, klant) een lijst bronnen uit `sources`; null zet de standaard voor het projecttype terug."}},"required":["action","project_id"],"title":"settings"},{"type":"object","properties":{"action":{"const":"recompute"},"project_id":{"type":"integer"}},"required":["action","project_id"],"title":"recompute","description":"Opnieuw optellen in de wachtrij; hooguit eens per vijf minuten (`429 too_soon`)."}]}}}},"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"ok":{"const":true},"stages":{"type":"object"}},"title":"settings"},{"type":"object","properties":{"ok":{"const":true},"queued":{"type":"boolean"}},"title":"recompute"}]}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/traffic":{"get":{"tags":["Bronnen en koppelingen"],"operationId":"get_traffic","summary":"AI-verkeer en klikken tegenover sessies, per dag","description":"Uit de feitentabellen, elke nacht bijgewerkt. `view=ai`: sessies uit AI-assistenten (ChatGPT, Perplexity, Gemini, Copilot, Claude …) uit GA4, of zonder GA4 bezoekers uit het sitescript (`unit`); `previous` is de even lange periode ervoor. `view=search`: Search Console-klikken tegenover organische GA4-sessies per dag. Search Console loopt een paar dagen achter; die dagen hebben `clicks: null`. `totals` telt alleen dagen waarop beide er zijn.\n\n**Wie:** `view=ai`: Bezoek (website) bekijken; `view=search`: Vindbaarheid (search) bekijken. Anderen krijgen 404.\n\n**Toegang:** Sessie of API-sleutel (lezen of schrijven)","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","parameters":[{"name":"project_id","in":"query","required":true,"schema":{"type":"integer"},"description":"Project-id."},{"name":"view","in":"query","required":false,"schema":{"type":"string","enum":["ai","search"]}},{"name":"days","in":"query","required":false,"schema":{"type":"integer"},"description":"7, 28 of 90; standaard 28."}],"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"days":{"type":"integer"},"source":{"type":["string","null"],"description":"Alleen bij `ai`: ga4, script of null."},"unit":{"type":"string"},"current":{"type":"integer"},"previous":{"type":"integer"},"series":{"type":"array","items":{"type":"object"},"description":"day, value (ai) of day, clicks, sessions (search)"},"sources":{"type":"array","items":{"type":"object"},"description":"key, value, previous"},"has_search":{"type":"boolean"},"has_ga":{"type":"boolean"},"search_until":{"type":["string","null"],"format":"date"},"ga_until":{"type":["string","null"],"format":"date","description":"Laatste dag met GA4-cijfers; daarna `sessions: null`."},"totals":{"type":"object","description":"clicks, sessions, ratio"}}}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/not-found":{"get":{"tags":["Bronnen en koppelingen"],"operationId":"get_not_found","summary":"404-monitor","description":"Pagina's die niet bestaan maar bezoek of links krijgen, elke ochtend samengevoegd uit GA4 (titel of pad van de foutpagina), het sitescript, de crawler en URL-inspectie van Search Console. De API van Search Console heeft geen lijst met 404's; alleen per inspectie. Een pagina die zeven dagen niet meer is gezien, staat op opgelost; krijgt hij weer bezoek, dan is hij weer nieuw.\n\n**Wie:** Team; klanten met toegang tot het onderdeel Zoeken.\n\n**Toegang:** Sessie of API-sleutel (lezen of schrijven)","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","parameters":[{"name":"project_id","in":"query","required":true,"schema":{"type":"integer"},"description":"Project-id."},{"name":"status","in":"query","required":false,"schema":{"type":"string","enum":["nieuw","opgelost","genegeerd"]}}],"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"status":{"type":"string"},"counts":{"type":"object","description":"nieuw, opgelost, genegeerd"},"pages":{"type":"array","items":{"type":"object"},"description":"id, path, status, hits, sources, referrers, first_seen, last_seen, resolved_at"},"settings":{"type":"object","description":"titles, paths, min_hits"},"can_manage":{"type":"boolean"}}}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}},"post":{"tags":["Bronnen en koppelingen"],"operationId":"post_not_found","summary":"404-monitor bijwerken","description":"**Wie:** Eigenaar of lid (beheer van Zoeken); anderen krijgen 404.\n\n**Toegang:** Sessie of API-sleutel met schrijfrecht","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"action":{"const":"ignore"},"project_id":{"type":"integer"},"id":{"type":"integer"}},"required":["action","project_id","id"],"title":"ignore"},{"type":"object","properties":{"action":{"const":"reopen"},"project_id":{"type":"integer"},"id":{"type":"integer"}},"required":["action","project_id","id"],"title":"reopen"},{"type":"object","properties":{"action":{"const":"resolve"},"project_id":{"type":"integer"},"id":{"type":"integer"}},"required":["action","project_id","id"],"title":"resolve"},{"type":"object","properties":{"action":{"const":"settings"},"project_id":{"type":"integer"},"titles":{"type":"array","items":{"type":"string"},"description":"Woorden in de titel van de foutpagina, hooguit 10."},"paths":{"type":"array","items":{"type":"string"},"description":"Paden die altijd als foutpagina tellen, zoals /404."},"min_hits":{"type":"integer","description":"Vanaf zoveel weergaven in 28 dagen telt een nieuwe 404 als melding."}},"required":["action","project_id"],"title":"settings"}]}}}},"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"ok":{"const":true},"id":{"type":"integer"},"status":{"type":"string"}},"title":"ignore"},{"type":"object","properties":{"ok":{"const":true},"id":{"type":"integer"},"status":{"type":"string"}},"title":"reopen"},{"type":"object","properties":{"ok":{"const":true},"id":{"type":"integer"},"status":{"type":"string"}},"title":"resolve"},{"type":"object","properties":{"ok":{"const":true},"settings":{"type":"object"}},"title":"settings"}]}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/extra-sources":{"get":{"tags":["Bronnen en koppelingen"],"operationId":"get_extra_sources","summary":"Kengetallen uit de aanvullende diensten","description":"Met verloop over 30 dagen. Geld, deals en fouten (Moneybird, Sentry, winkels, CRM, advertenties, App Store Connect) alleen voor het team of klanten met goedkeurrecht. `analytics` staat er alleen bij App Store Connect: of App Analytics is aangevraagd.\n\n**Wie:** Team; klanten met toegang tot het onderdeel Website.\n\n**Toegang:** Sessie of API-sleutel (lezen of schrijven)","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","parameters":[{"name":"project_id","in":"query","required":true,"schema":{"type":"integer"},"description":"Project-id."}],"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"can_manage":{"type":"boolean"},"sources":{"type":"array","items":{"type":"object"},"description":"id, kind, name, status, metrics, items, analytics"}}}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/conversion-sources":{"get":{"tags":["Bronnen en koppelingen"],"operationId":"get_conversion_sources","summary":"Bronnen voor conversie-events","description":"**Wie:** Alleen het team (eigenaar, lid of kijker); klanten krijgen 403.\n\n**Toegang:** Sessie of API-sleutel (lezen of schrijven)","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","parameters":[{"name":"project_id","in":"query","required":true,"schema":{"type":"integer"},"description":"Project-id."}],"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"sources":{"type":"array","items":{"type":"object"},"description":"id, app_source_id, name, retention_days"}}}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}},"post":{"tags":["Bronnen en koppelingen"],"operationId":"post_conversion_sources","summary":"Conversiesleutel maken","description":"**Wie:** Eigenaar of lid; kijkers en klanten krijgen 403.\n\n**Toegang:** Sessie of API-sleutel met schrijfrecht","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"action":{"const":"create"},"app_source_id":{"type":"integer"}},"required":["action","app_source_id"],"title":"create","description":"`409 already_exists` als de bron al een sleutel heeft."}]}}}},"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"ok":{"const":true},"app_source_id":{"type":"integer"},"token":{"type":"string","description":"Voor POST /api/events; één keer te zien."},"webhook_url":{"type":"string","format":"uri"}},"title":"create"}]}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/inbound":{"get":{"tags":["Bronnen en koppelingen"],"operationId":"get_inbound","summary":"Inkomende formulieren en afspraken","description":"**Wie:** Eigenaar of lid; kijkers en klanten krijgen 403.\n\n**Toegang:** Sessie of API-sleutel (lezen of schrijven)","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","parameters":[{"name":"project_id","in":"query","required":true,"schema":{"type":"integer"},"description":"Project-id."}],"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"hooks":{"type":"array","items":{"type":"object"},"description":"id, provider, label, signed, received, last_at, url"},"providers":{"type":"object"}}}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}},"post":{"tags":["Bronnen en koppelingen"],"operationId":"post_inbound","summary":"Inkomend adres maken of weghalen","description":"**Wie:** Eigenaar of lid; kijkers en klanten krijgen 403.\n\n**Toegang:** Sessie of API-sleutel met schrijfrecht","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"action":{"const":"create"},"project_id":{"type":"integer"},"provider":{"type":"string","enum":["typeform","calendly","gravityforms","overig","github","belmeting"]},"secret":{"type":"string","description":"Om de handtekening te controleren; verplicht voor GitHub."}},"required":["action","project_id","provider"],"title":"create"},{"type":"object","properties":{"action":{"const":"delete"},"id":{"type":"integer"}},"required":["action","id"],"title":"delete"}]}}}},"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"ok":{"const":true}},"title":"create"},{"type":"object","properties":{"ok":{"const":true}},"title":"delete"}]}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/clarity":{"get":{"tags":["Bronnen en koppelingen"],"operationId":"get_clarity","summary":"Microsoft Clarity: samenvatting van drie dagen","description":"Drie uur gecachet, want Clarity staat tien verzoeken per dag toe. `422 setup_required` zonder token, `502 clarity_unavailable` als Clarity faalt.\n\n**Wie:** Team; klanten met toegang tot het onderdeel Website.\n\n**Toegang:** Sessie of API-sleutel (lezen of schrijven)","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","parameters":[{"name":"integration_id","in":"query","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"summary":{"type":"object","description":"sessions, users, rage_clicks"},"days":{"type":"integer"}}}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/clarity/pages":{"get":{"tags":["Bronnen en koppelingen"],"operationId":"get_clarity_pages","summary":"Clarity: frictie per pagina over 28 dagen","description":"**Wie:** Team; klanten met toegang tot het onderdeel Website.\n\n**Toegang:** Sessie of API-sleutel (lezen of schrijven)","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","parameters":[{"name":"project_id","in":"query","required":true,"schema":{"type":"integer"},"description":"Project-id."}],"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"pages":{"type":"array","items":{"type":"object"},"description":"url, sessions, dead, rage, quickback, error_clicks, script_errors, scroll, active_seconds, friction"},"days":{"type":"integer"}}}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/feed":{"get":{"tags":["Bronnen en koppelingen"],"operationId":"get_feed","summary":"Staat de datafeed aan","description":"**Wie:** Eigenaar of lid; kijkers en klanten krijgen 403.\n\n**Toegang:** Sessie of API-sleutel (lezen of schrijven)","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","parameters":[{"name":"project_id","in":"query","required":true,"schema":{"type":"integer"},"description":"Project-id."}],"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"active":{"type":"boolean"},"created_at":{"type":["string","null"],"format":"date-time"},"last_used_at":{"type":["string","null"],"format":"date-time"}}}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}},"post":{"tags":["Bronnen en koppelingen"],"operationId":"post_feed","summary":"Datafeed (CSV) maken of intrekken","description":"**Wie:** Eigenaar of lid; kijkers en klanten krijgen 403.\n\n**Toegang:** Sessie of API-sleutel met schrijfrecht","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"action":{"const":"create"},"project_id":{"type":"integer"}},"required":["action","project_id"],"title":"create","description":"Een nieuwe feed maakt het oude adres ongeldig."},{"type":"object","properties":{"action":{"const":"revoke"},"project_id":{"type":"integer"}},"required":["action","project_id"],"title":"revoke"}]}}}},"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"ok":{"const":true},"url":{"type":"string","format":"uri"},"formula":{"type":"string","description":"Voor Google Sheets: =IMPORTDATA(\"…\")."}},"title":"create"},{"type":"object","properties":{"ok":{"const":true}},"title":"revoke"}]}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/data":{"get":{"tags":["Cijfers"],"operationId":"get_data","summary":"GA4, Search Console en eigen systemen","description":"`scope=overview`: per site totalen en dagreeks. `realtime`: actieve bezoekers per property. `detail`: één property (`property=properties/123`). `project`: web, zoeken en product van een project (`project=5`). `503 no_connections` zonder werkende Google-koppeling.\n\n**Wie:** Iedereen in de workspace; een klant ziet alleen zijn eigen projecten.\n\n**Toegang:** Sessie of API-sleutel (lezen of schrijven)","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","parameters":[{"name":"scope","in":"query","required":false,"schema":{"type":"string","enum":["overview","realtime","detail","project"]}},{"name":"property","in":"query","required":false,"schema":{"type":"string"}},{"name":"project","in":"query","required":false,"schema":{"type":"integer"}},{"name":"days","in":"query","required":false,"schema":{"type":"integer","enum":[7,28,90]},"description":"Periode in dagen; standaard 28."}],"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"generated":{"type":"integer"},"days":{"type":"integer"},"sites":{"type":"array","items":{"type":"object"}},"apps":{"type":"array","items":{"type":"object"}},"live":{"type":"object"}},"additionalProperties":true}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"},"502":{"$ref":"#/components/responses/502"},"503":{"$ref":"#/components/responses/503"}}}},"/api/landing":{"get":{"tags":["Cijfers"],"operationId":"get_landing","summary":"Landingspagina's met conversie","description":"**Wie:** Team; klanten met toegang tot het onderdeel Website.\n\n**Toegang:** Sessie of API-sleutel (lezen of schrijven)","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","parameters":[{"name":"project_id","in":"query","required":true,"schema":{"type":"integer"},"description":"Project-id."},{"name":"days","in":"query","required":false,"schema":{"type":"integer","enum":[7,28,90]},"description":"Periode in dagen; standaard 28."},{"name":"channel","in":"query","required":false,"schema":{"type":"string"},"description":"Bijvoorbeeld Organic Search."}],"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"pages":{"type":"array","items":{"type":"object"}},"days":{"type":"integer"},"channel":{"type":["string","null"]}}}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/revenue":{"get":{"tags":["Cijfers"],"operationId":"get_revenue","summary":"Omzet, MRR, churn en betaalsucces","description":"**Wie:** Team; klanten met goedkeurrecht op Overzicht (anders `hidden: true`).\n\n**Toegang:** Sessie of API-sleutel (lezen of schrijven)","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","parameters":[{"name":"project_id","in":"query","required":true,"schema":{"type":"integer"},"description":"Project-id."}],"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"revenue":{"type":["object","null"]},"hidden":{"type":"boolean"}}}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/attribution":{"get":{"tags":["Cijfers"],"operationId":"get_attribution","summary":"Kanaal tot betaling, LTV en CAC","description":"**Wie:** Team; klanten met goedkeurrecht op Overzicht (anders `hidden: true`).\n\n**Toegang:** Sessie of API-sleutel (lezen of schrijven)","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","parameters":[{"name":"project_id","in":"query","required":true,"schema":{"type":"integer"},"description":"Project-id."}],"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"attribution":{"type":["object","null"]},"hidden":{"type":"boolean"},"can_manage":{"type":"boolean"}}}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}},"post":{"tags":["Cijfers"],"operationId":"post_attribution","summary":"Kosten per kanaal per maand","description":"**Wie:** Eigenaar of lid; kijkers en klanten krijgen 403.\n\n**Toegang:** Sessie of API-sleutel met schrijfrecht","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"action":{"const":"cost"},"project_id":{"type":"integer"},"month":{"type":"string","pattern":"^\\d{4}-(0[1-9]|1[0-2])$"},"channel":{"type":"string"},"amount":{"type":"number","description":"In euro; 0 haalt de kosten weg."},"note":{"type":"string"}},"required":["action","project_id","month","channel","amount"],"title":"cost"}]}}}},"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"ok":{"const":true}},"title":"cost"}]}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/brand":{"get":{"tags":["Cijfers"],"operationId":"get_brand","summary":"Merkzoekopdrachten tegenover de rest","description":"**Wie:** Team; klanten met toegang tot het onderdeel Zoeken.\n\n**Toegang:** Sessie of API-sleutel (lezen of schrijven)","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","parameters":[{"name":"project_id","in":"query","required":true,"schema":{"type":"integer"},"description":"Project-id."},{"name":"days","in":"query","required":false,"schema":{"type":"integer","enum":[7,28,90]},"description":"Periode in dagen; standaard 28."}],"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"days":{"type":"integer"},"visibility":{"type":"array","items":{"type":"object"}}},"additionalProperties":true}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/cause":{"get":{"tags":["Cijfers"],"operationId":"get_cause","summary":"Oorzaak van een verandering","description":"Geeft `disabled: true` als de functie uitstaat voor de workspace.\n\n**Wie:** Team; klanten met Website (of Zoeken bij klikken).\n\n**Toegang:** Sessie of API-sleutel (lezen of schrijven)","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","parameters":[{"name":"project_id","in":"query","required":true,"schema":{"type":"integer"},"description":"Project-id."},{"name":"metric","in":"query","required":false,"schema":{"type":"string","enum":["sessions","key_events","clicks"]}},{"name":"days","in":"query","required":false,"schema":{"type":"integer","enum":[7,14,28,90]}}],"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"cause":{"type":["object","null"]},"disabled":{"type":"boolean"}}}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/cookieless":{"get":{"tags":["Cijfers"],"operationId":"get_cookieless","summary":"Cookieloze meting over 28 dagen","description":"**Wie:** Team; klanten met toegang tot het onderdeel Website.\n\n**Toegang:** Sessie of API-sleutel (lezen of schrijven)","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","parameters":[{"name":"project_id","in":"query","required":true,"schema":{"type":"integer"},"description":"Project-id."}],"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"days":{"type":"array","items":{"type":"object"},"description":"day, pageviews, visitors"},"pages":{"type":"array","items":{"type":"object"},"description":"label, pageviews, visitors"},"sources":{"type":"array","items":{"type":"object"},"description":"label, pageviews, visitors"},"refs":{"type":"array","items":{"type":"object"},"description":"label, pageviews, visitors; waarden van ?ref= of ?source= in het adres"},"referrers":{"type":"array","items":{"type":"object"},"description":"label (domein), pageviews, visitors"},"consent":{"type":"object","description":"alles, statistieken, advertenties, geweigerd → bezoekers (28 dagen)"},"ga4_users":{"type":["integer","null"],"description":"som van GA4-gebruikers per dag over dezelfde 28 dagen"},"totals":{"type":"object","description":"pageviews, visitors"}}}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/vitals":{"get":{"tags":["Cijfers"],"operationId":"get_vitals","summary":"Web Vitals van echte bezoekers","description":"**Wie:** Team; klanten met toegang tot het onderdeel Website.\n\n**Toegang:** Sessie of API-sleutel (lezen of schrijven)","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","parameters":[{"name":"project_id","in":"query","required":true,"schema":{"type":"integer"},"description":"Project-id."}],"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"has_script":{"type":"boolean"}},"additionalProperties":true}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/forms":{"get":{"tags":["Cijfers"],"operationId":"get_forms","summary":"Formulieranalyse, leads en cohorten","description":"**Wie:** Team; klanten met toegang tot het onderdeel Website.\n\n**Toegang:** Sessie of API-sleutel (lezen of schrijven)","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","parameters":[{"name":"project_id","in":"query","required":true,"schema":{"type":"integer"},"description":"Project-id."},{"name":"days","in":"query","required":false,"schema":{"type":"integer"},"description":"7 tot 90; standaard 28."}],"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"forms":{"type":"array","items":{"type":"object"},"description":"page, form, starts, submits, rate, fields, worst"},"has_script":{"type":"boolean"},"leads":{"type":"object"},"cohorts":{"type":"object"}}}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/speed":{"get":{"tags":["Cijfers"],"operationId":"get_speed","summary":"PageSpeed per pagina: mobiel en desktop, vier categorieën, verloop en verbeterpunten met tips","description":"**Wie:** Team; klanten met toegang tot het onderdeel Website.\n\n**Toegang:** Sessie of API-sleutel (lezen of schrijven)","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","parameters":[{"name":"project_id","in":"query","required":true,"schema":{"type":"integer"},"description":"Project-id."}],"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"pages":{"type":"array","items":{"type":"object"},"description":"url, path, planned, mobile, desktop (scores, lab, field, origin_field, audits), mobile_history, desktop_history, mobile_error, desktop_error"},"summary":{"type":"object","description":"average, worst, opportunities, issues, origin_field"},"tips":{"type":"object","description":"Tip per audit-id voor de stack van het project."},"quota":{"type":"object","description":"used, budget, blocked_until, source"},"measuring":{"type":"boolean"},"can_manage":{"type":"boolean"},"pages_limit":{"type":"integer"},"setup":{"type":["object","null"],"description":"Waarom er niets gemeten wordt (error), een link om het op te lossen (enable_url) en fix: steps, links, copy."}}}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}},"post":{"tags":["Cijfers"],"operationId":"post_speed","summary":"Pagina's nu meten met PageSpeed Insights","description":"**Wie:** Eigenaar of lid; kijkers en klanten krijgen 403.\n\n**Toegang:** Sessie of API-sleutel met schrijfrecht","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"action":{"const":"measure"},"project_id":{"type":"integer"},"url":{"type":"string","format":"uri","description":"Leeg: alle gemeten pagina's van het project."}},"required":["action","project_id"],"title":"measure","description":"Meet op de achtergrond, mobiel en desktop; hooguit eens per twee minuten per project (429)."}]}}}},"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"ok":{"const":true},"pages":{"type":"integer"}},"title":"measure"}]}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/seo":{"get":{"tags":["Zoeken en SEO"],"operationId":"get_seo","summary":"Werkblad zoektermen en meta","description":"**Wie:** Team; klanten met toegang tot het onderdeel Zoeken.\n\n**Toegang:** Sessie of API-sleutel (lezen of schrijven)","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","parameters":[{"name":"project_id","in":"query","required":true,"schema":{"type":"integer"},"description":"Project-id."},{"name":"days","in":"query","required":false,"schema":{"type":"integer","enum":[7,28,90]},"description":"Periode in dagen; standaard 28."}],"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"days":{"type":"integer"},"sites":{"type":"array","items":{"type":"object"}},"errors":{"type":"array","items":{"type":"object"}},"pages":{"type":"array","items":{"type":"object"},"description":"Hooguit 300, met open adviezen en indexstatus."},"page_count":{"type":"integer"},"ctr_curve":{"type":"array","items":{"type":"object"},"description":"position, ctr"}}}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"},"502":{"$ref":"#/components/responses/502"}}}},"/api/keywords":{"get":{"tags":["Zoeken en SEO"],"operationId":"get_keywords","summary":"Gevolgde zoekwoorden","description":"**Wie:** Team; klanten met toegang tot het onderdeel Zoeken.\n\n**Toegang:** Sessie of API-sleutel (lezen of schrijven)","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","parameters":[{"name":"project_id","in":"query","required":true,"schema":{"type":"integer"},"description":"Project-id."}],"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"keywords":{"type":"array","items":{"type":"object"}},"suggestions":{"type":"array","items":{"type":"object"}},"can_manage":{"type":"boolean"},"ads_candidates":{"type":"array","items":{"type":"object"}},"clusters":{"type":"array","items":{"type":"object"}},"seasons":{"type":"object"},"title_tests":{"type":"array","items":{"type":"object"}}}}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}},"post":{"tags":["Zoeken en SEO"],"operationId":"post_keywords","summary":"Zoekwoorden toevoegen, koppelen of weghalen","description":"**Wie:** Eigenaar of lid (beheer van Zoeken); anderen krijgen 404.\n\n**Toegang:** Sessie of API-sleutel met schrijfrecht","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"action":{"const":"add"},"project_id":{"type":"integer"},"keywords":{"type":"string","description":"Eén per regel of komma-gescheiden; hooguit 200 per project."}},"required":["action","project_id","keywords"],"title":"add"},{"type":"object","properties":{"action":{"const":"target"},"project_id":{"type":"integer"},"id":{"type":"integer"},"target_url":{"type":"string","format":"uri"}},"required":["action","project_id","id"],"title":"target"},{"type":"object","properties":{"action":{"const":"delete"},"project_id":{"type":"integer"},"id":{"type":"integer"}},"required":["action","project_id","id"],"title":"delete"}]}}}},"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"ok":{"const":true},"keywords":{"type":"array","items":{"type":"object"}},"suggestions":{"type":"array","items":{"type":"object"}}},"title":"add"},{"type":"object","properties":{"ok":{"const":true},"keywords":{"type":"array","items":{"type":"object"}},"suggestions":{"type":"array","items":{"type":"object"}}},"title":"target"},{"type":"object","properties":{"ok":{"const":true},"keywords":{"type":"array","items":{"type":"object"}},"suggestions":{"type":"array","items":{"type":"object"}}},"title":"delete"}]}}}},"401":{"$ref":"#/components/responses/401"},"402":{"$ref":"#/components/responses/402"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/competition":{"get":{"tags":["Zoeken en SEO"],"operationId":"get_competition","summary":"Concurrenten, contentgaten, backlinks en kaartposities","description":"`source` zegt welke bron actief is: DataForSEO of de gratis bronnen (Bing, Brave, eigen crawler).\n\n**Wie:** Team; klanten met toegang tot het onderdeel Zoeken.\n\n**Toegang:** Sessie of API-sleutel (lezen of schrijven)","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","parameters":[{"name":"project_id","in":"query","required":true,"schema":{"type":"integer"},"description":"Project-id."}],"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"enabled":{"type":"boolean"},"source":{"type":"string"},"free":{"type":"object"},"backlinks_source":{"type":["string","null"]},"gaps_source":{"type":"string"},"competitors":{"type":"array","items":{"type":"string"}},"keywords":{"type":"array","items":{"type":"object"}},"gaps":{"type":"array","items":{"type":"object"}},"backlinks":{"type":["object","null"]},"grid":{"type":"object"},"spent":{"type":["number","null"]},"can_manage":{"type":"boolean"}}}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}},"post":{"tags":["Zoeken en SEO"],"operationId":"post_competition","summary":"Concurrenten en kaartraster instellen","description":"**Wie:** Eigenaar of lid (beheer van Zoeken); anderen krijgen 404.\n\n**Toegang:** Sessie of API-sleutel met schrijfrecht","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"action":{"const":"add"},"project_id":{"type":"integer"},"domain":{"type":"string","description":"Hooguit vijf per project."}},"required":["action","project_id","domain"],"title":"add"},{"type":"object","properties":{"action":{"const":"remove"},"project_id":{"type":"integer"},"domain":{"type":"string"}},"required":["action","project_id","domain"],"title":"remove"},{"type":"object","properties":{"action":{"const":"grid"},"project_id":{"type":"integer"},"business_name":{"type":"string"},"keyword":{"type":"string"},"lat":{"type":"number"},"lng":{"type":"number"},"radius_km":{"type":"number","description":"0,5 tot 25; standaard 3."}},"required":["action","project_id","business_name","keyword","lat","lng"],"title":"grid"},{"type":"object","properties":{"action":{"const":"brave"},"project_id":{"type":"integer"}},"required":["action","project_id"],"title":"brave","description":"Posities in Brave Search, live en niet bewaard; hooguit eens per tien minuten per project (`429 too_many`)."}]}}}},"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"ok":{"const":true}},"title":"add"},{"type":"object","properties":{"ok":{"const":true}},"title":"remove"},{"type":"object","properties":{"ok":{"const":true}},"title":"grid"},{"type":"object","properties":{"ok":{"const":true},"live":{"type":"array","items":{"type":"object"}}},"title":"brave"}]}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/audit":{"get":{"tags":["Zoeken en SEO"],"operationId":"get_audit","summary":"Site-audit uit de laatste crawl","description":"**Wie:** Team; klanten met toegang tot het onderdeel Zoeken.\n\n**Toegang:** Sessie of API-sleutel (lezen of schrijven)","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","parameters":[{"name":"project_id","in":"query","required":true,"schema":{"type":"integer"},"description":"Project-id."}],"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"crawled_at":{"type":["string","null"],"format":"date-time"},"pages":{"type":"integer"},"working":{"type":"integer"},"redirects":{"type":"integer"},"errors":{"type":"integer"},"links":{"type":"integer"},"issues":{"type":"array","items":{"type":"object"}},"suggestions":{"type":"array","items":{"type":"object"}},"can_crawl":{"type":"boolean"},"llms_txt":{"type":["object","null"]},"budget":{"type":["object","null"]},"indexnow":{"type":"object","description":"key, verified_at"},"text":{"type":["object","null"]}}}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}},"post":{"tags":["Zoeken en SEO"],"operationId":"post_audit","summary":"Crawl starten of IndexNow instellen","description":"**Wie:** Eigenaar of lid (beheer van Zoeken); anderen krijgen 404.\n\n**Toegang:** Sessie of API-sleutel met schrijfrecht","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"action":{"const":"crawl"},"project_id":{"type":"integer"}},"required":["action","project_id"],"title":"crawl"},{"type":"object","properties":{"action":{"const":"indexnow"},"project_id":{"type":"integer"}},"required":["action","project_id"],"title":"indexnow"}]}}}},"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"ok":{"const":true},"task_id":{"type":"string","description":"Volg de taak met GET /api/task?id=…"}},"title":"crawl"},{"type":"object","properties":{"ok":{"const":true},"key":{"type":"string"},"location":{"type":"string","format":"uri"},"verified":{"type":"boolean"}},"title":"indexnow"}]}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/schema":{"get":{"tags":["Zoeken en SEO"],"operationId":"get_schema","summary":"Schema-wizard: soorten en wat al bekend is","description":"**Wie:** Team; klanten met toegang tot het onderdeel Zoeken.\n\n**Toegang:** Sessie of API-sleutel (lezen of schrijven)","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","parameters":[{"name":"project_id","in":"query","required":true,"schema":{"type":"integer"},"description":"Project-id."}],"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"types":{"type":"object"},"prefill":{"type":"object","description":"name, url"},"present":{"type":"array","items":{"type":"string"}}}}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}},"post":{"tags":["Zoeken en SEO"],"operationId":"post_schema","summary":"JSON-LD opstellen","description":"Zonder `action`. Geeft de JSON-LD, of welke velden ontbreken.\n\n**Wie:** Team; klanten met toegang tot het onderdeel Zoeken.\n\n**Toegang:** Sessie of API-sleutel met schrijfrecht","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"project_id":{"type":"integer"},"type":{"type":"string"},"fields":{"type":"object"}},"required":["project_id","type"]}}}},"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true}},"additionalProperties":true}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/logs":{"get":{"tags":["Zoeken en SEO"],"operationId":"get_logs","summary":"Analyse van het laatste logbestand","description":"**Wie:** Team; klanten met toegang tot het onderdeel Zoeken.\n\n**Toegang:** Sessie of API-sleutel (lezen of schrijven)","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","parameters":[{"name":"project_id","in":"query","required":true,"schema":{"type":"integer"},"description":"Project-id."}],"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"report":{"type":["object","null"]},"can_upload":{"type":"boolean"},"from_server":{"type":"boolean"}}}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}},"post":{"tags":["Zoeken en SEO"],"operationId":"post_logs","summary":"Access-log uploaden","description":"Multipart, zonder `action`. Combined-formaat, ook .gz, hooguit 100 MB.\n\n**Wie:** Eigenaar of lid (beheer van Zoeken); anderen krijgen 404.\n\n**Toegang:** Sessie of API-sleutel met schrijfrecht","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"type":"object","properties":{"project_id":{"type":"integer"},"file":{"type":"string","format":"binary"}},"required":["project_id","file"]}}}},"responses":{"201":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"lines":{"type":"integer"},"bot_lines":{"type":"integer"}}}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/content":{"get":{"tags":["Zoeken en SEO"],"operationId":"get_content","summary":"Contentkalender","description":"**Wie:** Team; klanten met toegang tot het onderdeel Zoeken.\n\n**Toegang:** Sessie of API-sleutel (lezen of schrijven)","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","parameters":[{"name":"project_id","in":"query","required":true,"schema":{"type":"integer"},"description":"Project-id."}],"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"items":{"type":"array","items":{"type":"object"}},"suggestions":{"type":"array","items":{"type":"object"}},"can_manage":{"type":"boolean"}}}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}},"post":{"tags":["Zoeken en SEO"],"operationId":"post_content","summary":"Content plannen, nieuwsbrief en socials","description":"**Wie:** Eigenaar of lid (beheer van Zoeken); anderen krijgen 404.\n\n**Toegang:** Sessie of API-sleutel met schrijfrecht","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"action":{"const":"add"},"project_id":{"type":"integer"},"title":{"type":"string"},"query":{"type":"string"},"publish_on":{"type":"string","format":"date"},"reason":{"type":"string"},"url":{"type":"string","format":"uri"}},"required":["action","project_id","title"],"title":"add"},{"type":"object","properties":{"action":{"const":"update"},"id":{"type":"integer"},"title":{"type":"string"},"query":{"type":"string"},"publish_on":{"type":["string","null"],"format":"date"},"status":{"type":"string","enum":["idee","schrijven","klaar","live"]},"url":{"type":"string","format":"uri"},"reason":{"type":"string"}},"required":["action","id"],"title":"update","description":"Op `live` komt het stuk op de tijdlijn."},{"type":"object","properties":{"action":{"const":"delete"},"id":{"type":"integer"}},"required":["action","id"],"title":"delete"},{"type":"object","properties":{"action":{"const":"newsletter"},"project_id":{"type":"integer"},"days":{"type":"integer"},"intro":{"type":"string"},"skip":{"type":"array","items":{"type":"string"}}},"required":["action","project_id"],"title":"newsletter"},{"type":"object","properties":{"action":{"const":"newsletter_draft"},"project_id":{"type":"integer"},"target":{"type":"string","enum":["mailchimp","brevo"]},"subject":{"type":"string"},"list_id":{"type":"string"},"from_name":{"type":"string"},"reply_to":{"type":"string","format":"email"},"days":{"type":"integer"},"intro":{"type":"string"},"skip":{"type":"array","items":{"type":"string"}}},"required":["action","project_id","target","subject","list_id","from_name","reply_to"],"title":"newsletter_draft"},{"type":"object","properties":{"action":{"const":"social_drafts"},"project_id":{"type":"integer"},"skip":{"type":"array","items":{"type":"string"}}},"required":["action","project_id"],"title":"social_drafts","description":"Zet concepten klaar in socials.instnt.studio."}]}}}},"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"ok":{"const":true},"id":{"type":"integer"}},"title":"add"},{"type":"object","properties":{"ok":{"const":true}},"title":"update"},{"type":"object","properties":{"ok":{"const":true}},"title":"delete"},{"type":"object","properties":{"ok":{"const":true},"items":{"type":"array","items":{"type":"object"}},"html":{"type":"string"}},"title":"newsletter"},{"type":"object","properties":{"ok":{"const":true},"draft_id":{"type":"string"}},"title":"newsletter_draft"},{"type":"object","properties":{"ok":{"const":true}},"title":"social_drafts"}]}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/writeback":{"post":{"tags":["Zoeken en SEO"],"operationId":"post_writeback","summary":"Terugschrijfsleutel voor WordPress of Drupal","description":"**Wie:** Eigenaar of lid (beheer van Zoeken); anderen krijgen 404.\n\n**Toegang:** Sessie of API-sleutel met schrijfrecht","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"action":{"const":"token"},"project_id":{"type":"integer"}},"required":["action","project_id"],"title":"token"}]}}}},"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"ok":{"const":true},"token":{"type":"string","description":"wb_…; één keer te zien, vervangt de vorige."}},"title":"token"}]}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/advice":{"get":{"tags":["Advies, vragen en AI"],"operationId":"get_advice","summary":"Adviezen van een project","description":"Met `scope=workspace` (alleen team) de tien belangrijkste acties over alle projecten. Elk advies heeft `why`: de delen van de rangorde (klikken, betrouwbaarheid, moeite, wat het team leerde).\n\n**Wie:** Team; klanten met toegang tot het onderdeel Advies.\n\n**Toegang:** Sessie of API-sleutel (lezen of schrijven)","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","parameters":[{"name":"project_id","in":"query","required":true,"schema":{"type":"integer"},"description":"Project-id."},{"name":"status","in":"query","required":false,"schema":{"type":"string","enum":["open","planned","done","bevestiging","dismissed","expired","all","actief","archief"]},"description":"Standaard open. `bevestiging`: gedaan, maar nog niet bevestigd door de bron. `actief`: open en in behandeling. `archief`: gedaan, afgewezen en verlopen, nieuwste eerst."},{"name":"group","in":"query","required":false,"schema":{"type":"string","enum":["page"]},"description":"Met `status=actief`: ook `pages`, de adviezen per pagina."},{"name":"scope","in":"query","required":false,"schema":{"type":"string","enum":["workspace"]}}],"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"items":{"type":"array","items":{"type":"object"},"description":"Hooguit 500, belangrijkste eerst, met impact_euros en confirmation (state confirmed of waiting, by, at, waits_on, overdue, note)."},"euro_basis":{"type":["object","null"]},"counts":{"type":"object"},"tip":{"type":["object","null"]},"last_refresh":{"type":["string","null"],"format":"date-time"},"thresholds":{"type":"object"},"learned":{"type":"array","items":{"type":"object"}},"effect_days":{"type":"integer"},"can_manage":{"type":"boolean"},"has_github":{"type":"boolean"},"progress":{"type":"array","items":{"type":"object"},"description":"Per categorie: category, done, total (zonder verlopen)."},"effect":{"type":["object","null"],"description":"Alleen bij `archief`: done, measured, clicks, impressions (na min vóór, over de gemeten adviezen)."},"pages":{"type":["array","null"],"items":{"type":"object"},"description":"Alleen bij `status=actief&group=page`: url, path, ids, count, impact_clicks, categories."}}}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}},"post":{"tags":["Advies, vragen en AI"],"operationId":"post_advice","summary":"Status, toewijzen, GitHub-issue, opnieuw controleren, prompt maken","description":"**Wie:** Eigenaar of lid; kijkers en klanten krijgen 403.\n\n**Toegang:** Sessie of API-sleutel met schrijfrecht","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"action":{"const":"status"},"id":{"type":"integer"},"status":{"type":"string","enum":["open","planned","done","dismissed"]},"note":{"type":"string"},"task_url":{"type":"string","format":"uri"}},"required":["action","id","status"],"title":"status","description":"Bij `done` legt Studio de stand van nu vast om het effect na 14 dagen te meten, en zet het op de tijdlijn. Het advies wacht daarna op bevestiging door de bron (Google, live controle, lockbestand, meting)."},{"type":"object","properties":{"action":{"const":"assign"},"id":{"type":"integer"},"assignee_id":{"type":["integer","null"]},"due_date":{"type":["string","null"],"format":"date"}},"required":["action","id"],"title":"assign","description":"Toewijzen plant een open advies."},{"type":"object","properties":{"action":{"const":"issue"},"id":{"type":"integer"}},"required":["action","id"],"title":"issue","description":"Maakt een issue in de GitHub-repo van het project (`502 github` als GitHub weigert)."},{"type":"object","properties":{"action":{"const":"recheck"},"id":{"type":"integer"}},"required":["action","id"],"title":"recheck"},{"type":"object","properties":{"action":{"const":"refresh"},"project_id":{"type":"integer"}},"required":["action","project_id"],"title":"refresh","description":"Draait alle regels opnieuw."},{"type":"object","properties":{"action":{"const":"prompt"},"project_id":{"type":"integer"},"ids":{"type":"array","items":{"type":"integer"},"description":"Hooguit 30; alleen adviezen met `fixable: true` tellen mee."},"mode":{"type":"string","enum":["claude","algemeen"]},"mark":{"type":"boolean","description":"Standaard true: zet de punten op planned met een notitie."}},"required":["action","project_id","ids"],"title":"prompt","description":"Alleen het eigen team. Maakt van adviezen die in code of configuratie op te lossen zijn één opdracht, met bewijs, wanneer het klaar is en hoe je het controleert. URL's zonder querystring; geen persoonsgegevens of sleutels."}]}}}},"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"ok":{"const":true},"item":{"type":"object"}},"title":"status"},{"type":"object","properties":{"ok":{"const":true},"item":{"type":"object"}},"title":"assign"},{"type":"object","properties":{"ok":{"const":true},"url":{"type":"string","format":"uri"}},"title":"issue"},{"type":"object","properties":{"ok":{"const":true},"task_id":{"type":"string","description":"Volg de taak met GET /api/task?id=…"}},"title":"recheck"},{"type":"object","properties":{"ok":{"const":true},"task_id":{"type":"string","description":"Volg de taak met GET /api/task?id=…"}},"title":"refresh"},{"type":"object","properties":{"ok":{"const":true},"prompt":{"type":"string","description":"Markdown, klaar om in een AI-sessie te plakken."},"filename":{"type":"string"},"items":{"type":"array","items":{"type":"integer"}}},"title":"prompt"}]}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/playbooks":{"get":{"tags":["Advies, vragen en AI"],"operationId":"get_playbooks","summary":"Playbooks van een project","description":"**Wie:** Team; klanten met toegang tot het onderdeel Advies.\n\n**Toegang:** Sessie of API-sleutel (lezen of schrijven)","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","parameters":[{"name":"project_id","in":"query","required":true,"schema":{"type":"integer"},"description":"Project-id."}],"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"runs":{"type":"array","items":{"type":"object"}},"available":{"type":"object"},"can_manage":{"type":"boolean"}}}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}},"post":{"tags":["Advies, vragen en AI"],"operationId":"post_playbooks","summary":"Playbook starten en afvinken","description":"**Wie:** Eigenaar of lid (beheer van Advies); anderen krijgen 404.\n\n**Toegang:** Sessie of API-sleutel met schrijfrecht","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"action":{"const":"start"},"project_id":{"type":"integer"},"playbook":{"type":"string"}},"required":["action","project_id","playbook"],"title":"start"},{"type":"object","properties":{"action":{"const":"step"},"id":{"type":"integer"},"step":{"type":"string"},"done":{"type":"boolean"}},"required":["action","id","step"],"title":"step"},{"type":"object","properties":{"action":{"const":"finish"},"id":{"type":"integer"}},"required":["action","id"],"title":"finish"}]}}}},"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"ok":{"const":true},"id":{"type":"integer"}},"title":"start"},{"type":"object","properties":{"ok":{"const":true}},"title":"step"},{"type":"object","properties":{"ok":{"const":true}},"title":"finish"}]}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/experiments":{"get":{"tags":["Advies, vragen en AI"],"operationId":"get_experiments","summary":"Testlog en hypothesekaarten","description":"**Wie:** Team; klanten met toegang tot het onderdeel Advies.\n\n**Toegang:** Sessie of API-sleutel (lezen of schrijven)","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","parameters":[{"name":"project_id","in":"query","required":true,"schema":{"type":"integer"},"description":"Project-id."}],"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"experiments":{"type":"array","items":{"type":"object"}},"cards":{"type":"array","items":{"type":"object"}},"can_manage":{"type":"boolean"}}}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}},"post":{"tags":["Advies, vragen en AI"],"operationId":"post_experiments","summary":"Test vastleggen of verwijderen","description":"**Wie:** Eigenaar of lid (beheer van Advies); anderen krijgen 404.\n\n**Toegang:** Sessie of API-sleutel met schrijfrecht","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"action":{"const":"save"},"project_id":{"type":"integer"},"id":{"type":"integer","description":"Zonder id: nieuw."},"title":{"type":"string"},"hypothesis":{"type":"string"},"metric":{"type":"string"},"page_url":{"type":"string","format":"uri"},"starts_on":{"type":"string","format":"date"},"ends_on":{"type":"string","format":"date"},"outcome":{"type":"string","enum":["won","lost","neutral"]},"result":{"type":"string"}},"required":["action","project_id","title"],"title":"save"},{"type":"object","properties":{"action":{"const":"delete"},"project_id":{"type":"integer"},"id":{"type":"integer"}},"required":["action","project_id","id"],"title":"delete"}]}}}},"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"ok":{"const":true},"id":{"type":"integer"}},"title":"save"},{"type":"object","properties":{"ok":{"const":true}},"title":"delete"}]}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/questions":{"get":{"tags":["Advies, vragen en AI"],"operationId":"get_questions","summary":"Vragen bij een rapport, advies of project","description":"Geeft `disabled: true` als vragen uitstaan voor de workspace.\n\n**Wie:** Team en klanten met toegang tot het onderwerp; `open=1` alleen het team.\n\n**Toegang:** Sessie of API-sleutel (lezen of schrijven)","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","parameters":[{"name":"project_id","in":"query","required":false,"schema":{"type":"integer"}},{"name":"subject_type","in":"query","required":false,"schema":{"type":"string","enum":["report","advice","project"]}},{"name":"subject_id","in":"query","required":false,"schema":{"type":"integer"}},{"name":"open","in":"query","required":false,"schema":{"type":"boolean"},"description":"Alle open vragen over alle klanten."}],"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"questions":{"type":"array","items":{"type":"object"},"description":"id, label, project_id, project_name, subject_type, subject_id, subject_title, anchor, status (open|wacht_ons|wacht_klant|opgelost|gesloten), link, created_by, updated_at, messages (body, from_team, internal, name, at)"},"disabled":{"type":"boolean"}}}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}},"post":{"tags":["Advies, vragen en AI"],"operationId":"post_questions","summary":"Vraag stellen, antwoorden of sluiten","description":"**Wie:** Team en klanten met toegang tot het onderwerp.\n\n**Toegang:** Sessie of API-sleutel met schrijfrecht","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"action":{"const":"ask"},"project_id":{"type":"integer"},"subject_type":{"type":"string","enum":["report","advice","project"]},"subject_id":{"type":"integer"},"anchor":{"type":"string"},"body":{"type":"string","description":"Hooguit 4000 tekens."}},"required":["action","project_id","subject_type","subject_id","body"],"title":"ask"},{"type":"object","properties":{"action":{"const":"reply"},"question_id":{"type":"integer"},"body":{"type":"string"}},"required":["action","question_id","body"],"title":"reply"},{"type":"object","properties":{"action":{"const":"close"},"question_id":{"type":"integer"}},"required":["action","question_id"],"title":"close","description":"Het team, of wie de vraag stelde."}]}}}},"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"ok":{"const":true},"question_id":{"type":"integer"}},"title":"ask"},{"type":"object","properties":{"ok":{"const":true}},"title":"reply"},{"type":"object","properties":{"ok":{"const":true}},"title":"close"}]}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/support":{"get":{"tags":["Advies, vragen en AI"],"operationId":"get_support","summary":"Support: tickets","description":"Klantvragen aan het bureau (`deel=klant`, module Support, vanaf Copiloot) en vragen aan instnt (`deel=instnt`). Een vraag bij een rapport of advies is ook een ticket. Zonder `id` een lijst met tellers per status; met `id` één ticket met het gesprek, bijlagen en voor de behandelaar de projectcontext, interne notities, het team en vaste antwoorden. Een ticket van een andere werkruimte geeft 404.\n\n**Wie:** Klant: eigen tickets (met de module Support). Team: alle klanttickets; kijkers alleen lezen. `deel=instnt`: eigenaar of lid. `admin=1`: alleen platformbeheerders.\n\n**Toegang:** Sessie of API-sleutel (lezen of schrijven)","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","parameters":[{"name":"deel","in":"query","required":false,"schema":{"type":"string","enum":["klant","instnt"]}},{"name":"admin","in":"query","required":false,"schema":{"type":"boolean"}},{"name":"id","in":"query","required":false,"schema":{"type":"integer"}},{"name":"sets","in":"query","required":false,"schema":{"type":"boolean"},"description":"Alleen de sets vaste antwoorden om in te laden (team, 13-10-2026)."},{"name":"lang","in":"query","required":false,"schema":{"type":"string","enum":["nl","en"]}},{"name":"status","in":"query","required":false,"schema":{"type":"string","enum":["actief","te_laat","open","wacht_ons","wacht_klant","opgelost","gesloten"]},"description":"Standaard actief: alles behalve opgelost en gesloten. Leeg voor alles."},{"name":"q","in":"query","required":false,"schema":{"type":"string"},"description":"Zoekt in onderwerp, nummer en berichten."},{"name":"project_id","in":"query","required":false,"schema":{"type":"integer"}},{"name":"mine","in":"query","required":false,"schema":{"type":"boolean"},"description":"Alleen aan mij toegewezen."}],"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"tickets":{"type":"array","items":{"type":"object"},"description":"id, label, number, scope, title, subject_type, anchor, project, requester, status, priority, channel, assigned, due_at, overdue, messages, last_from_team, created_at, updated_at, workspace"},"counts":{"type":"object"},"overdue":{"type":"integer"},"module":{"type":"object"},"statuses":{"type":"object"},"priorities":{"type":"object"},"can_create":{"type":"boolean"},"sets":{"type":"array","items":{"type":"object"},"description":"Met sets=1: key, label, description, count, titles."},"template_sets":{"type":"array","items":{"type":"object"},"description":"Voor het team: dezelfde sets."},"settings":{"type":"object","description":"Alleen voor het team: sla, sla_default, inbound_available, inbound_on, address, can_manage."},"ticket":{"type":"object","description":"Met id: het ticket plus thread, link, role, can, en voor de behandelaar context, team, templates en projects."}}}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}},"post":{"tags":["Advies, vragen en AI"],"operationId":"post_support","summary":"Support: vragen stellen en behandelen","description":"Bijlagen als multipart `files[]`: hooguit 5 per bericht en 10 MB per bestand; afbeeldingen (geen SVG), pdf, tekst, csv en Office-bestanden. Het soort volgt uit de inhoud, niet uit de naam.\n\n**Wie:** Per actie: een klant maakt en beantwoordt zijn eigen tickets; eigenaar en lid behandelen en stellen in; met `admin: true` behandelen platformbeheerders vragen aan instnt.\n\n**Toegang:** Sessie of API-sleutel met schrijfrecht","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"action":{"const":"create"},"deel":{"type":"string","enum":["klant","instnt"]},"title":{"type":"string","description":"Hooguit 160 tekens."},"body":{"type":"string","description":"Hooguit 10.000 tekens."},"project_id":{"type":"integer","description":"Klant met meer dan één project: verplicht."},"priority":{"type":"string","enum":["laag","normaal","hoog","urgent"],"description":"Alleen bij deel=instnt."},"files":{"type":"string","format":"binary"}},"required":["action","deel","title","body"],"title":"create"},{"type":"object","properties":{"action":{"const":"reply"},"id":{"type":"integer"},"template_id":{"type":"integer","description":"Het vaste antwoord waar dit uit kwam; heeft het acties (macro, 13-10-2026), dan voert Studio die na versturen uit."},"body":{"type":"string"},"files":{"type":"string","format":"binary"},"admin":{"type":"boolean"}},"required":["action","id","body"],"title":"reply","description":"Op een gesloten ticket alleen de behandelaar."},{"type":"object","properties":{"action":{"const":"note"},"id":{"type":"integer"},"body":{"type":"string"},"files":{"type":"string","format":"binary"},"admin":{"type":"boolean"}},"required":["action","id","body"],"title":"note","description":"Interne notitie: de aanvrager ziet hem nooit, ook de bijlagen niet."},{"type":"object","properties":{"action":{"const":"status"},"id":{"type":"integer"},"status":{"type":"string","enum":["open","wacht_ons","wacht_klant","opgelost","gesloten"]},"admin":{"type":"boolean"}},"required":["action","id","status"],"title":"status","description":"De aanvrager kan alleen sluiten."},{"type":"object","properties":{"action":{"const":"assign"},"id":{"type":"integer"},"user_id":{"type":["integer","null"]},"admin":{"type":"boolean"}},"required":["action","id"],"title":"assign"},{"type":"object","properties":{"action":{"const":"priority"},"id":{"type":"integer"},"priority":{"type":"string","enum":["laag","normaal","hoog","urgent"]},"admin":{"type":"boolean"}},"required":["action","id","priority"],"title":"priority","description":"Rekent een lopende deadline opnieuw uit."},{"type":"object","properties":{"action":{"const":"project"},"id":{"type":"integer"},"project_id":{"type":["integer","null"]},"admin":{"type":"boolean"}},"required":["action","id"],"title":"project"},{"type":"object","properties":{"action":{"const":"settings"},"sla":{"type":"object","description":"Uren per prioriteit (laag, normaal, hoog, urgent), elk 1–720."},"inbound_on":{"type":"boolean"}},"required":["action"],"title":"settings"},{"type":"object","properties":{"action":{"const":"rotate_address"}},"required":["action"],"title":"rotate_address","description":"Nieuw adres voor mail naar support; het oude werkt meteen niet meer."},{"type":"object","properties":{"action":{"const":"template_save"},"id":{"type":"integer"},"project_id":{"type":["integer","null"],"description":"Alleen voor dit project (13-10-2026); leeg is voor alle projecten. Hooguit 50 per project en 50 algemeen."},"category":{"type":"string","description":"Categorie, hooguit 40 tekens (13-10-2026)."},"actions":{"type":"object","description":"Macro (13-10-2026): status (wacht|afgesloten), tags (hooguit vijf), assign_me; na versturen in de chat."},"title":{"type":"string"},"shortcut":{"type":"string","description":"Sneltoets voor de chat, zonder schuine streep: kleine letters, cijfers en streepjes, hooguit 30."},"body":{"type":"string"},"buttons":{"type":"array","items":{"type":"string"},"description":"Knoppen in de chat, hooguit vier (22-10-2026)."},"admin":{"type":"boolean"}},"required":["action","title","body"],"title":"template_save","description":"Dezelfde vaste antwoorden gelden in Support en in de chat."},{"type":"object","properties":{"action":{"const":"template_delete"},"id":{"type":"integer"},"admin":{"type":"boolean"}},"required":["action","id"],"title":"template_delete"},{"type":"object","properties":{"action":{"const":"template_import"},"set":{"type":"string","enum":["basis","webshop","diensten","horeca","software"]},"project_id":{"type":"integer","description":"In dit project in plaats van algemeen."},"sets":{"type":"array","items":{"type":"string"},"description":"Meerdere sets tegelijk (13-10-2026)."},"only":{"type":"array","items":{"type":"string"},"description":"Alleen deze antwoorden, op naam."},"lang":{"type":"string","enum":["nl","en"]}},"required":["action"],"title":"template_import","description":"Een set vaste antwoorden inladen (13-10-2026). Voegt toe en overschrijft niets: dezelfde naam of sneltoets wordt overgeslagen, boven de 50 stopt het. Eigenaar of lid."}]}}}},"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"ok":{"const":true},"ticket":{"type":"object"}},"title":"create"},{"type":"object","properties":{"ok":{"const":true},"ticket":{"type":"object"}},"title":"reply"},{"type":"object","properties":{"ok":{"const":true},"ticket":{"type":"object"}},"title":"note"},{"type":"object","properties":{"ok":{"const":true},"ticket":{"type":"object"}},"title":"status"},{"type":"object","properties":{"ok":{"const":true},"ticket":{"type":"object"}},"title":"assign"},{"type":"object","properties":{"ok":{"const":true},"ticket":{"type":"object"}},"title":"priority"},{"type":"object","properties":{"ok":{"const":true},"ticket":{"type":"object"}},"title":"project"},{"type":"object","properties":{"ok":{"const":true},"settings":{"type":"object"}},"title":"settings"},{"type":"object","properties":{"ok":{"const":true},"settings":{"type":"object"}},"title":"rotate_address"},{"type":"object","properties":{"ok":{"const":true},"templates":{"type":"array","items":{"type":"object"}}},"title":"template_save"},{"type":"object","properties":{"ok":{"const":true},"templates":{"type":"array","items":{"type":"object"}}},"title":"template_delete"},{"type":"object","properties":{"ok":{"const":true},"templates":{"type":"array","items":{"type":"object"}},"imported":{"type":"object","description":"added, skipped, full"}},"title":"template_import"}]}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/support/attachment":{"get":{"tags":["Advies, vragen en AI"],"operationId":"get_support_attachment","summary":"Bijlage van een ticket","description":"Altijd als download, met `X-Content-Type-Options: nosniff`.\n\n**Wie:** Wie het ticket mag zien; een bijlage bij een interne notitie alleen de behandelaar.\n\n**Toegang:** Sessie of API-sleutel (lezen of schrijven)","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","parameters":[{"name":"id","in":"query","required":true,"schema":{"type":"integer"}},{"name":"admin","in":"query","required":false,"schema":{"type":"boolean"}}],"responses":{"200":{"description":"Gelukt.","content":{"application/octet-stream":{"schema":{"type":"string","format":"binary"}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/livechat":{"get":{"tags":["Advies, vragen en AI"],"operationId":"get_livechat","summary":"Chat: gesprekken met bezoekers","description":"De inbox van de chat op de site (module Chat, vanaf Copiloot). Zonder `id` een lijst met tellers; met `id` één gesprek met berichten, interne notities, bezoekerscontext (pagina, taal, toestel, eerdere gesprekken), het team en vaste antwoorden met ingevulde variabelen. Een gesprek openen markeert het als gelezen. Met `since` alleen berichten na dat id, voor polling. Wie de inbox opent, telt anderhalve minuut als online voor het widget. Een gesprek van een ander project of een andere werkruimte geeft 404.\n\n**Wie:** Team: gesprekken van projecten met de module Chat; kijkers alleen lezen. Klant: alleen bij een project waar hij Website op goedkeuren heeft. `settings`: eigenaar of lid.\n\n**Toegang:** Sessie of API-sleutel (lezen of schrijven)","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","parameters":[{"name":"view","in":"query","required":false,"schema":{"type":"string","enum":["open","wachtend","mijn","niet_toegewezen","buiten_tijden","afgesloten","alle"]},"description":"Standaard open: alles wat niet is afgesloten. wachtend: het team is aan zet."},{"name":"project_id","in":"query","required":false,"schema":{"type":"integer"}},{"name":"label","in":"query","required":false,"schema":{"type":"string"},"description":"Alleen gesprekken met dit label."},{"name":"sort","in":"query","required":false,"schema":{"type":"string","enum":["wachtend","nieuwste","activiteit"]},"description":"Standaard wachtend: wie het langst op het team wacht bovenaan."},{"name":"q","in":"query","required":false,"schema":{"type":"string"},"description":"Zoekt in naam, e-mail en berichten."},{"name":"id","in":"query","required":false,"schema":{"type":"integer"}},{"name":"since","in":"query","required":false,"schema":{"type":"integer"}},{"name":"teller","in":"query","required":false,"schema":{"type":"boolean"},"description":"Alleen de tellers, voor de navigatie en het app-icoon."},{"name":"settings","in":"query","required":false,"schema":{"type":"integer"},"description":"Project-id: de instellingen van de chat en de installatiecode."}],"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"conversations":{"type":"array","items":{"type":"object"},"description":"id, project, name, email, status, offline, assigned, last, unread, tags, page_url, visitor_online, rating, ticket_id, created_at, last_message_at, waiting_since"},"counts":{"type":"object","description":"open, mijn, niet_toegewezen, wachtend, ongelezen; zonder teller ook buiten_tijden, afgesloten, oudste_wacht, per_project (per project-id: open, wachtend) en labels (de vijf meest gebruikte: label, count); met teller=1 ook projects (aantal sites met chat voor deze gebruiker)."},"projects":{"type":"array","items":{"type":"object"},"description":"id, name, enabled, can_reply, notify_after"},"sort":{"type":"string"},"module":{"type":"object"},"can_manage":{"type":"boolean"},"statuses":{"type":"object"},"conversation":{"type":"object","description":"Met id: het gesprek plus messages, visitor, visitor_typing, rating_comment, ticket, can, team, templates en me (het eigen gebruikers-id). Sinds 11-10-2026 heeft visitor ook route (path, title, at: de pagina's van dit bezoek, zonder querystring, hooguit twintig, na 30 dagen zonder bericht weg), read_upto en read_at (tot welk bericht de bezoeker het venster zag); een bericht kan faq (id, title) hebben. Sinds 12-10-2026 bevat visitor.previous (id, status, created_at, last_at, rating, ticket, preview: de eerste zin) ook gesprekken van de andere browsers van de bezoeker, gekoppeld met een code of StudioChat.identify(). Sinds 13-10-2026 viewers (id, name, typing): collega's die dit gesprek ook open hebben."},"settings":{"type":"object","description":"Met settings: enabled, greeting, offline_message, color, position, hours, allowed_origins, allowed_hosts, prechat, proactive, notify_after, notify_users, snippet, token. Berichten hebben `files` (bijlagen met een URL die een half uur geldig is); visitor heeft `consent_at`."}}}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}},"post":{"tags":["Advies, vragen en AI"],"operationId":"post_livechat","summary":"Chat: antwoorden en instellen","description":"**Wie:** Wie mag antwoorden: eigenaar, lid, of een klant met Website op goedkeuren. Instellingen en verwijderen: eigenaar of lid.\n\n**Toegang:** Sessie of API-sleutel met schrijfrecht","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"action":{"const":"reply"},"id":{"type":"integer"},"faq_id":{"type":"integer","description":"Een gepubliceerde veelgestelde vraag van dit project als kaart onder het bericht (11-10-2026); body mag dan leeg."},"buttons":{"type":"array","items":{"type":"string"},"description":"Hooguit vier knoppen van 1 tot 40 tekens onder het bericht (22-10-2026); in multipart als JSON-tekst. De bezoeker kiest er één."},"file":{"type":"string","format":"binary","description":"Bijlage (21-10-2026): afbeelding (jpg, png, webp, gif) of pdf, hooguit 10 MB; de inhoud bepaalt het type. Dan als multipart/form-data; body mag leeg. Ook bij note."},"body":{"type":"string","description":"Hooguit 2.000 tekens. {naam}, {voornaam}, {project}, {bureau} en {medewerker} worden ingevuld."}},"required":["action","id","body"],"title":"reply","description":"Wie antwoordt op een gesprek zonder behandelaar, krijgt het. Niet bij een gesprek dat een ticket werd."},{"type":"object","properties":{"action":{"const":"note"},"id":{"type":"integer"},"body":{"type":"string"}},"required":["action","id","body"],"title":"note","description":"Interne notitie: de bezoeker ziet hem nooit."},{"type":"object","properties":{"action":{"const":"status"},"id":{"type":"integer"},"status":{"type":"string","enum":["open","wacht","afgesloten"]}},"required":["action","id","status"],"title":"status"},{"type":"object","properties":{"action":{"const":"assign"},"id":{"type":"integer"},"user_id":{"type":["integer","null"]}},"required":["action","id"],"title":"assign"},{"type":"object","properties":{"action":{"const":"tags"},"id":{"type":"integer"},"tags":{"type":"array","items":{"type":"string"},"description":"Hooguit tien, elk hooguit 30 tekens."}},"required":["action","id","tags"],"title":"tags"},{"type":"object","properties":{"action":{"const":"files"},"id":{"type":"integer"},"allow":{"type":"boolean"},"limit":{"type":["integer","null"],"description":"Hoeveel bijlagen de bezoeker mag sturen voor het weer dicht gaat (13-10-2026); zonder geldt de instelling van de site."}},"required":["action","id","allow"],"title":"files","description":"Bijlagen van de bezoeker in dit gesprek toestaan of weer uitzetten. Standaard uit; de bezoeker krijgt een systeembericht en ziet pas daarna de paperclip."},{"type":"object","properties":{"action":{"const":"ticket"},"id":{"type":"integer"}},"required":["action","id"],"title":"ticket","description":"Zet het gesprek om naar een ticket in Support (module nodig) en sluit het. Met het e-mailadres van de bezoeker gaat het antwoord per mail."},{"type":"object","properties":{"action":{"const":"typing"},"id":{"type":"integer"}},"required":["action","id"],"title":"typing","description":"De bezoeker ziet acht seconden \"typt…\"."},{"type":"object","properties":{"action":{"const":"read"},"id":{"type":"integer"}},"required":["action","id"],"title":"read"},{"type":"object","properties":{"action":{"const":"activity"},"id":{"type":"integer"},"token":{"type":"string","description":"Pushtoken van de Live Activity (hex)."},"environment":{"type":"string","enum":["sandbox","production"]},"end":{"type":"boolean","description":"Token weghalen: de app volgt dit gesprek niet meer."}},"required":["action","id","token"],"title":"activity","description":"Live Activity op de iPhone (12-10-2026): alleen vanuit een app-sessie (anders 403 app_only). Studio werkt de activiteit bij per push bij een nieuw bericht, een antwoord, toewijzen en afsluiten; bij afsluiten of een ticket eindigt hij."},{"type":"object","properties":{"action":{"const":"delete"},"id":{"type":"integer"}},"required":["action","id"],"title":"delete","description":"Gesprek met alle berichten weg, bijvoorbeeld op verzoek van de bezoeker."},{"type":"object","properties":{"action":{"const":"identity_secret"},"project_id":{"type":"integer"},"remove":{"type":"boolean"}},"required":["action","project_id"],"title":"identity_secret","description":"Sleutel voor StudioChat.identify() maken of vernieuwen (64 hex-tekens), of met remove weghalen. Oude handtekeningen werken daarna niet meer."},{"type":"object","properties":{"action":{"const":"mute"},"id":{"type":"integer"},"muted":{"type":"boolean"}},"required":["action","id","muted"],"title":"mute","description":"Stil zetten: geen push meer voor dit gesprek, alleen voor jou (13-10-2026). Het gesprek geeft muted."},{"type":"object","properties":{"action":{"const":"settings"},"project_id":{"type":"integer"},"enabled":{"type":"boolean"},"auto_close_minutes":{"type":["integer","null"],"description":"Gesprek vanzelf dicht na zoveel minuten zonder reactie van de bezoeker nadat het team antwoordde (5 tot 10080); leeg is nooit (13-10-2026)."},"rating_aspects":{"type":"boolean","description":"Naast sterren ook vriendelijkheid, snelheid en deskundigheid laten beoordelen."},"file_types":{"type":"array","items":{"type":"string"},"description":"Wat een bezoeker mag sturen (13-10-2026): afbeeldingen, pdf en/of documenten."},"file_max_mb":{"type":"integer","description":"1 tot 10."},"file_limit":{"type":["integer","null"],"description":"Na zoveel bijlagen gaan bijlagen in dat gesprek weer dicht; leeg is geen grens."},"greeting":{"type":"string"},"offline_message":{"type":"string"},"color":{"type":["string","null"]},"position":{"type":"string","enum":["rechts","links"]},"greeting_buttons":{"type":"array","items":{"type":"string"},"description":"Hooguit vier knoppen onder de groet; een klik begint het gesprek met die tekst."},"hide_branding":{"type":"boolean","description":"Venster zonder instnt studio; alleen met white-label in het plan."},"hours":{"type":["object","null"],"description":"Per dag (1 = maandag) een lijst blokken [\"09:00\",\"17:00\"], in de tijdzone van de werkruimte; leeg is altijd open."},"allowed_origins":{"type":"string","description":"Extra adressen die het widget mogen laden, naast de domeinen van het project. Over http alleen wat hier staat."},"prechat":{"type":"object","description":"Formulier vóór het eerste bericht: when (nooit|offline|altijd), name/email/topic (uit|optioneel|verplicht), topics (hooguit tien), privacy (bool) en privacy_url (https). Buiten openingstijden is e-mail altijd verplicht. Vervangt ask_email (21-10-2026)."},"proactive":{"type":"array","items":{"type":"object"},"description":"Hooguit vijf: match (bevat|is), path, delay (0–600 s), message (hooguit 300 tekens), every_days (0–365; 0 = één keer), only_new, only_open."},"notify_after":{"type":"integer","description":"Mail na zoveel minuten zonder antwoord, 1–240."},"notify_users":{"type":"array","items":{"type":"integer"}},"widget":{"type":"object","description":"Het venster (10-10-2026), per groep; wat ontbreekt blijft zoals het was. home: mode (zoeken|samen|chat), contact (altijd|na_zoeken), featured_count (0–8), categories, conversation_card, logo. contact: offline (bericht|faq), alternatives (hooguit drie: type telefoon|email|whatsapp, value, label, text, when altijd|offline), links (hooguit drie: label, https-url). faq: enabled, suggest, feedback, log_misses. team: names (voornaam|volledig|voornaam_foto|bureau), queue. visibility: paths (hooguit tien: match bevat|is, path met /), mobile, offline. launcher: offset_x, offset_y (0–200), label_mobile. texts: per taal (nl, en) greeting, offline, home_title, home_intro, search, contact, reply_time, launcher."}},"required":["action","project_id"],"title":"settings"},{"type":"object","properties":{"action":{"const":"refused_allow"},"project_id":{"type":"integer"},"origin":{"type":"string"}},"required":["action","project_id","origin"],"title":"refused_allow","description":"Een geweigerd adres toestaan: het komt bij allowed_origins en verdwijnt uit de lijst."},{"type":"object","properties":{"action":{"const":"refused_ignore"},"project_id":{"type":"integer"},"origin":{"type":"string"}},"required":["action","project_id","origin"],"title":"refused_ignore","description":"Een geweigerd adres verbergen; na 7 dagen gaat het vanzelf weg."},{"type":"object","properties":{"action":{"const":"rotate_token"},"project_id":{"type":"integer"}},"required":["action","project_id"],"title":"rotate_token","description":"Nieuw widget-token; de oude installatiecode werkt meteen niet meer."}]}}}},"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"ok":{"const":true},"conversation":{"type":"object"}},"title":"reply"},{"type":"object","properties":{"ok":{"const":true},"conversation":{"type":"object"}},"title":"note"},{"type":"object","properties":{"ok":{"const":true},"conversation":{"type":"object"}},"title":"status"},{"type":"object","properties":{"ok":{"const":true},"conversation":{"type":"object"}},"title":"assign"},{"type":"object","properties":{"ok":{"const":true},"conversation":{"type":"object"}},"title":"tags"},{"type":"object","properties":{"ok":{"const":true},"conversation":{"type":"object"}},"title":"files"},{"type":"object","properties":{"ok":{"const":true},"conversation":{"type":"object"}},"title":"ticket"},{"type":"object","properties":{"ok":{"const":true}},"title":"typing"},{"type":"object","properties":{"ok":{"const":true}},"title":"read"},{"type":"object","properties":{"ok":{"const":true},"state":{"type":"object","description":"status, lastMessage, lastFromVisitor, lastAt, waitingSince, assigned (tijden in Unix-seconden)"}},"title":"activity"},{"type":"object","properties":{"ok":{"const":true}},"title":"delete"},{"type":"object","properties":{"ok":{"const":true},"settings":{"type":"object"}},"title":"identity_secret"},{"type":"object","properties":{"ok":{"const":true},"conversation":{"type":"object"}},"title":"mute"},{"type":"object","properties":{"ok":{"const":true},"settings":{"type":"object","description":"… plus widget, refused (geweigerde adressen van de laatste 7 dagen) en branding"},"widget_options":{"type":"object"}},"title":"settings"},{"type":"object","properties":{"ok":{"const":true},"settings":{"type":"object"}},"title":"refused_allow"},{"type":"object","properties":{"ok":{"const":true},"settings":{"type":"object"}},"title":"refused_ignore"},{"type":"object","properties":{"ok":{"const":true},"settings":{"type":"object"}},"title":"rotate_token"}]}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/faq":{"get":{"tags":["Advies, vragen en AI"],"operationId":"get_faq","summary":"Veelgestelde vragen","description":"Artikelen die de bezoeker in het chatvenster doorzoekt. Markdown; `html` is opgeschoond (geen ruwe HTML, geen afbeeldingen, alleen http(s)- en mailto-links). Met `suggest` hooguit drie gepubliceerde treffers voor een vraag van de bezoeker, met `plain` om als antwoord in te voegen.\n\n**Wie:** Zoals de chat: team bij Website op bekijken (concepten alleen voor eigenaar en lid), een klant alleen gepubliceerde artikelen en alleen bij Website op goedkeuren.\n\n**Toegang:** Sessie of API-sleutel (lezen of schrijven)","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","parameters":[{"name":"project_id","in":"query","required":false,"schema":{"type":"integer"}},{"name":"q","in":"query","required":false,"schema":{"type":"string"},"description":"Zoeken in titel, categorie en tekst."},{"name":"suggest","in":"query","required":false,"schema":{"type":"string"},"description":"Vraag van de bezoeker."},{"name":"stats","in":"query","required":false,"schema":{"type":"integer"},"description":"Cijfers over zelfhulp over 7, 30 of 90 dagen; alleen wie beheert."},{"name":"id","in":"query","required":false,"schema":{"type":"integer"},"description":"Eén artikel met body, html en plain."}],"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"stats":{"type":"object","description":"Met stats: articles (per id views, yes, no, helpful_pct), views, yes, no, misses (zoektermen zonder resultaat: term, count), conversations_after (gesprekken na zelfhulp), deflection_pct."},"articles":{"type":"array","items":{"type":"object"},"description":"id, project_id, title, category, language, published, featured, position, views, updated_at, excerpt (met suggest ook body, html, plain)"},"article":{"type":"object"},"can_manage":{"type":"boolean"},"languages":{"type":"object"},"max_body":{"type":"integer"}}}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}},"post":{"tags":["Advies, vragen en AI"],"operationId":"post_faq","summary":"Veelgestelde vragen beheren","description":"**Wie:** Eigenaar of lid (Website op beheren); `preview` iedereen die de chat ziet.\n\n**Toegang:** Sessie of API-sleutel met schrijfrecht","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"action":{"const":"create"},"project_id":{"type":"integer"},"title":{"type":"string","description":"Hooguit 200 tekens."},"body":{"type":"string","description":"Markdown, hooguit 20.000 tekens."},"category":{"type":"string"},"language":{"type":"string","enum":["nl","en"]},"published":{"type":"boolean"}},"required":["action","project_id","title","body"],"title":"create"},{"type":"object","properties":{"action":{"const":"update"},"id":{"type":"integer"},"title":{"type":"string"},"body":{"type":"string"},"category":{"type":["string","null"]},"language":{"type":"string","enum":["nl","en"]},"published":{"type":"boolean"},"featured":{"type":"boolean","description":"Uitgelicht op het startscherm van het venster."}},"required":["action","id"],"title":"update"},{"type":"object","properties":{"action":{"const":"delete"},"id":{"type":"integer"}},"required":["action","id"],"title":"delete"},{"type":"object","properties":{"action":{"const":"reorder"},"project_id":{"type":"integer"},"ids":{"type":"array","items":{"type":"integer"},"description":"Alle artikelen van het project in de nieuwe volgorde."}},"required":["action","project_id","ids"],"title":"reorder"},{"type":"object","properties":{"action":{"const":"preview"},"body":{"type":"string"}},"required":["action","body"],"title":"preview","description":"Dezelfde HTML als het widget toont."}]}}}},"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"ok":{"const":true},"article":{"type":"object"}},"title":"create"},{"type":"object","properties":{"ok":{"const":true},"article":{"type":"object"}},"title":"update"},{"type":"object","properties":{"ok":{"const":true}},"title":"delete"},{"type":"object","properties":{"ok":{"const":true}},"title":"reorder"},{"type":"object","properties":{"ok":{"const":true},"html":{"type":"string"}},"title":"preview"}]}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/chat-team":{"get":{"tags":["Advies, vragen en AI"],"operationId":"get_chat_team","summary":"Chat: rapportage en beschikbaarheid","description":"Met `view=report` (standaard): gesprekken per dag, per weekdag en uur, eerste reactietijd en afhandeltijd (mediaan en p90, in seconden, alleen binnen de openingstijden), gemist (na 15 minuten zonder antwoord en geen ticket), tickets, tevredenheid (4 of 5 van 5 telt als tevreden), drukste pagina's en per teamlid. Met `view=team`: de eigen status, het team met status en lopende gesprekken, en per project de verdeling.\n\n**Wie:** Zoals de inbox. Per teamlid en de verdeling alleen voor het team; de verdeling aanpassen: eigenaar of lid.\n\n**Toegang:** Sessie of API-sleutel (lezen of schrijven)","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","parameters":[{"name":"view","in":"query","required":false,"schema":{"type":"string","enum":["report","team"]}},{"name":"from","in":"query","required":false,"schema":{"type":"string","format":"date"},"description":"Standaard 27 dagen voor to."},{"name":"to","in":"query","required":false,"schema":{"type":"string","format":"date"},"description":"Standaard vandaag."},{"name":"project_id","in":"query","required":false,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"report":{"type":"object","description":"from, to, timezone, totals, days, heatmap, pages, comments, agents, truncated"},"projects":{"type":"array","items":{"type":"object"},"description":"id, name"},"me":{"type":"object","description":"Met view=team: status, chosen, max_chats, open, can_set."},"team":{"type":"array","items":{"type":"object"},"description":"id, name, status, open, max_chats"},"routing":{"type":"array","items":{"type":"object"},"description":"project_id, name, assign_mode, report_block"}}}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}},"post":{"tags":["Advies, vragen en AI"],"operationId":"post_chat_team","summary":"Chat: status en verdeling","description":"**Wie:** Status: wie ergens mag antwoorden. Verdeling: eigenaar of lid.\n\n**Toegang:** Sessie of API-sleutel met schrijfrecht","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"action":{"const":"availability"},"status":{"type":"string","enum":["beschikbaar","afwezig","offline"]},"max_chats":{"type":["integer","null"],"description":"Hooguit zoveel lopende gesprekken tegelijk, 1–50; leeg is geen maximum."}},"required":["action","status"],"title":"availability","description":"Wie op beschikbaar staat maar de inbox anderhalve minuut niet opvroeg, telt als afwezig; na een kwartier als offline. Offline: je automatisch verdeelde gesprekken gaan naar een ander of worden vrij."},{"type":"object","properties":{"action":{"const":"routing"},"project_id":{"type":"integer"},"assign_mode":{"type":"string","enum":["handmatig","rondgang","minst_bezet"],"description":"Handmatig: niemand krijgt automatisch een gesprek. Rondgang: om de beurt onder wie beschikbaar is. Minst bezet: wie de minste lopende gesprekken heeft."},"report_block":{"type":"boolean","description":"Chat in het maandrapport van dit project."}},"required":["action","project_id"],"title":"routing"}]}}}},"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"ok":{"const":true}},"title":"availability"},{"type":"object","properties":{"ok":{"const":true}},"title":"routing"}]}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/ai":{"get":{"tags":["Advies, vragen en AI"],"operationId":"get_ai","summary":"AI-taken, teksten, merkstem en AI-zichtbaarheid","description":"**Wie:** Alleen het team (eigenaar, lid of kijker); klanten krijgen 403.\n\n**Toegang:** Sessie of API-sleutel (lezen of schrijven)","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","parameters":[{"name":"project_id","in":"query","required":true,"schema":{"type":"integer"},"description":"Project-id."}],"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"kinds":{"type":"object"},"usage":{"type":"object","description":"used, limit, cost_usd"},"worker_seen":{"type":["string","null"],"format":"date-time"},"tasks":{"type":"array","items":{"type":"object"}},"texts":{"type":"array","items":{"type":"object"}},"voice":{"type":["object","null"]},"opportunities":{"type":"array","items":{"type":"object"}},"advice":{"type":"array","items":{"type":"object"}},"reports":{"type":"array","items":{"type":"object"}},"content":{"type":"array","items":{"type":"object"}},"geo":{"type":"object","description":"questions"}}}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}},"post":{"tags":["Advies, vragen en AI"],"operationId":"post_ai","summary":"AI-taak aanvragen en teksten beoordelen","description":"**Wie:** Eigenaar of lid; kijkers en klanten krijgen 403.\n\n**Toegang:** Sessie of API-sleutel met schrijfrecht","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"action":{"const":"request"},"kind":{"type":"string","enum":["title_meta","advice_plain","report_intro","content_brief","draft_text","week_analysis","data_question","share_of_answer","ad_texts"]},"recommendation_id":{"type":"integer","description":"Bij title_meta en advice_plain."},"report_id":{"type":"integer","description":"Bij report_intro."},"content_id":{"type":"integer","description":"Bij content_brief en draft_text."},"project_id":{"type":"integer","description":"Bij de overige."},"question":{"type":"string","description":"Bij data_question."},"keyword":{"type":"string","description":"Bij ad_texts."},"landing":{"type":"string","format":"uri"}},"required":["action","kind"],"title":"request"},{"type":"object","properties":{"action":{"const":"decide"},"text_id":{"type":"integer"},"decision":{"type":"string","enum":["overgenomen","aangepast","afgewezen"]},"final":{"type":"string","description":"Verplicht bij aangepast."}},"required":["action","text_id","decision"],"title":"decide"},{"type":"object","properties":{"action":{"const":"voice"},"project_id":{"type":"integer"},"tone":{"type":"string"},"do_words":{"type":"string"},"dont_words":{"type":"string"},"forbidden_claims":{"type":"string"}},"required":["action","project_id"],"title":"voice"},{"type":"object","properties":{"action":{"const":"geo_add"},"project_id":{"type":"integer"},"question":{"type":"string","description":"Hooguit tien per project."}},"required":["action","project_id","question"],"title":"geo_add"},{"type":"object","properties":{"action":{"const":"geo_remove"},"project_id":{"type":"integer"},"id":{"type":"integer"}},"required":["action","project_id","id"],"title":"geo_remove"}]}}}},"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"ok":{"const":true},"task_id":{"type":"integer"}},"title":"request"},{"type":"object","properties":{"ok":{"const":true}},"title":"decide"},{"type":"object","properties":{"ok":{"const":true}},"title":"voice"},{"type":"object","properties":{"ok":{"const":true}},"title":"geo_add"},{"type":"object","properties":{"ok":{"const":true}},"title":"geo_remove"}]}}}},"401":{"$ref":"#/components/responses/401"},"402":{"$ref":"#/components/responses/402"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/ai/worker":{"get":{"tags":["Advies, vragen en AI"],"operationId":"get_ai_worker","summary":"AI-worker: volgende taak claimen","description":"Let op: deze GET claimt de taak (zet hem op running). Alleen voor de worker van instnt.\n\n**Wie:** Alleen platformbeheerders van instnt; anderen krijgen 404 of 403.\n\n**Toegang:** Sessie of API-sleutel (lezen of schrijven)","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"task":{"type":["object","null"],"description":"id, kind, prompt, schema, model"}}}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}},"post":{"tags":["Advies, vragen en AI"],"operationId":"post_ai_worker","summary":"AI-worker: resultaat inleveren","description":"**Wie:** Alleen platformbeheerders van instnt; anderen krijgen 404 of 403.\n\n**Toegang:** Sessie of API-sleutel met schrijfrecht","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"integer"},"result":{"type":"object"}},"required":["id","result"]}}}},"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true}}}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/uptime":{"get":{"tags":["Uptime en techniek"],"operationId":"get_uptime","summary":"Uptime, fouten, back-ups en onderhoud","description":"**Wie:** Team; klanten met toegang tot het onderdeel Website.\n\n**Toegang:** Sessie of API-sleutel (lezen of schrijven)","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","parameters":[{"name":"project_id","in":"query","required":true,"schema":{"type":"integer"},"description":"Project-id."}],"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"monitors":{"type":"array","items":{"type":"object"},"description":"id, url, expect_status, expect_text, interval_minutes, enabled, state, last_checked_at, last_response_ms, last_error, ssl_expires_at, safe_browsing, uptime_24h, uptime_30d, avg_ms_24h, recent, incidents"},"errors":{"type":"array","items":{"type":"object"},"description":"id, message, source, line, col, page, browser, stack, occurrences, first_seen, last_seen, status, last_14_days"},"error_key":{"type":["string","null"]},"snippet":{"type":["string","null"]},"script_tag":{"type":["string","null"]},"status_page":{"type":"boolean"},"alert_emails":{"type":["string","null"]},"backups":{"type":"array","items":{"type":"object"}},"maintenance":{"type":"array","items":{"type":"object"}},"can_manage":{"type":"boolean"},"suggested_url":{"type":["string","null"],"format":"uri"}}}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}},"post":{"tags":["Uptime en techniek"],"operationId":"post_uptime","summary":"Controles, statuspagina, onderhoud en back-ups beheren","description":"**Wie:** Eigenaar of lid; kijkers en klanten krijgen 403.\n\n**Toegang:** Sessie of API-sleutel met schrijfrecht","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"action":{"const":"create"},"project_id":{"type":"integer"},"url":{"type":"string","format":"uri"},"expect_status":{"type":"integer","description":"Standaard 200."},"expect_text":{"type":"string"},"interval_minutes":{"type":"integer","enum":[1,5,15]}},"required":["action","project_id","url"],"title":"create","description":"Controleert meteen één keer."},{"type":"object","properties":{"action":{"const":"update"},"monitor_id":{"type":"integer"},"url":{"type":"string","format":"uri"},"expect_status":{"type":"integer"},"expect_text":{"type":"string"},"interval_minutes":{"type":"integer","enum":[1,5,15]},"enabled":{"type":"boolean"}},"required":["action","monitor_id","url"],"title":"update"},{"type":"object","properties":{"action":{"const":"delete"},"monitor_id":{"type":"integer"}},"required":["action","monitor_id"],"title":"delete"},{"type":"object","properties":{"action":{"const":"check"},"monitor_id":{"type":"integer"}},"required":["action","monitor_id"],"title":"check"},{"type":"object","properties":{"action":{"const":"status_page"},"project_id":{"type":"integer"},"revoke":{"type":"boolean"}},"required":["action","project_id"],"title":"status_page"},{"type":"object","properties":{"action":{"const":"alert_emails"},"project_id":{"type":"integer"},"emails":{"type":"string","description":"Komma-gescheiden."}},"required":["action","project_id"],"title":"alert_emails"},{"type":"object","properties":{"action":{"const":"maintenance_create"},"project_id":{"type":"integer"},"starts_at":{"type":"string","format":"date-time"},"ends_at":{"type":"string","format":"date-time","description":"Hooguit een week na het begin."},"note":{"type":"string"}},"required":["action","project_id","starts_at","ends_at"],"title":"maintenance_create"},{"type":"object","properties":{"action":{"const":"maintenance_delete"},"id":{"type":"integer"}},"required":["action","id"],"title":"maintenance_delete"},{"type":"object","properties":{"action":{"const":"backup_create"},"project_id":{"type":"integer"},"name":{"type":"string"},"max_hours":{"type":"integer","description":"1 tot 744; standaard 26."}},"required":["action","project_id","name"],"title":"backup_create"},{"type":"object","properties":{"action":{"const":"backup_delete"},"id":{"type":"integer"}},"required":["action","id"],"title":"backup_delete"},{"type":"object","properties":{"action":{"const":"error_key"},"project_id":{"type":"integer"}},"required":["action","project_id"],"title":"error_key","description":"Maakt de sleutel voor het sitescript als die er nog niet is."},{"type":"object","properties":{"action":{"const":"error_status"},"error_id":{"type":"integer"},"status":{"type":"string","enum":["open","resolved","ignored"]}},"required":["action","error_id","status"],"title":"error_status"}]}}}},"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"ok":{"const":true},"monitor_id":{"type":"integer"}},"title":"create"},{"type":"object","properties":{"ok":{"const":true}},"title":"update"},{"type":"object","properties":{"ok":{"const":true}},"title":"delete"},{"type":"object","properties":{"ok":{"const":true}},"title":"check"},{"type":"object","properties":{"ok":{"const":true},"link":{"type":"string","format":"uri"}},"title":"status_page"},{"type":"object","properties":{"ok":{"const":true}},"title":"alert_emails"},{"type":"object","properties":{"ok":{"const":true}},"title":"maintenance_create"},{"type":"object","properties":{"ok":{"const":true}},"title":"maintenance_delete"},{"type":"object","properties":{"ok":{"const":true}},"title":"backup_create"},{"type":"object","properties":{"ok":{"const":true}},"title":"backup_delete"},{"type":"object","properties":{"ok":{"const":true}},"title":"error_key"},{"type":"object","properties":{"ok":{"const":true}},"title":"error_status"}]}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/site-checks":{"get":{"tags":["Uptime en techniek"],"operationId":"get_site_checks","summary":"Sitecontroles per host","description":"Headers, blootgestelde bestanden, cookievlaggen, CMS, domein, DNSSEC en CAA, mail, tags, derde partijen, robots, AI-crawlers en sitemap.\n\n**Wie:** Team; klanten met toegang tot het onderdeel Website.\n\n**Toegang:** Sessie of API-sleutel (lezen of schrijven)","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","parameters":[{"name":"project_id","in":"query","required":true,"schema":{"type":"integer"},"description":"Project-id."}],"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"hosts":{"type":"array","items":{"type":"object"},"description":"host, checks"}}}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}},"post":{"tags":["Uptime en techniek"],"operationId":"post_site_checks","summary":"Sitecontroles nu opnieuw","description":"**Wie:** Team; klanten met toegang tot het onderdeel Website.\n\n**Toegang:** Sessie of API-sleutel met schrijfrecht","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"action":{"const":"run"},"project_id":{"type":"integer"}},"required":["action","project_id"],"title":"run","description":"Controleert de hosts van het project meteen opnieuw, ook het certificaat van de bewaakte adressen, en berekent de beveiligingsscore opnieuw. Hooguit twee keer per vijf minuten per project; daarna 429."}]}}}},"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"ok":{"const":true},"hosts":{"type":"array","items":{"type":"object"},"description":"host, checks"}},"title":"run"}]}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/security-score":{"get":{"tags":["Uptime en techniek"],"operationId":"get_security_score","summary":"Beveiligingsscore","description":"Score 0–100 uit zes onderdelen met een vast gewicht (versleuteling, headers, blootstelling, software, mail en DNS, reputatie), berekend uit de laatste sitecontrole, certificaten, lekken en Safe Browsing. Niet gemeten onderdelen tellen niet mee (`score` per onderdeel is dan `null`); met minder dan twee gemeten onderdelen is `score` zelf `null`. `trend` is de dagelijkse score van de laatste 30 dagen. `domains` zegt per domein of het geverifieerd is en hoe (`dns` of `plugin`); het TXT-record staat bij /api/domains.\n\n**Wie:** Team; klanten met toegang tot het onderdeel Website.\n\n**Toegang:** Sessie of API-sleutel (lezen of schrijven)","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","parameters":[{"name":"project_id","in":"query","required":true,"schema":{"type":"integer"},"description":"Project-id."}],"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"score":{"type":["integer","null"]},"previous":{"type":["integer","null"]},"trend":{"type":"array","items":{"type":"object"},"description":"day, score"},"categories":{"type":"array","items":{"type":"object"},"description":"key, label, weight, description, score (?int), points (status, label, detail)"},"method":{"type":"string"},"domains":{"type":"array","items":{"type":"object"},"description":"domain, verified, via"}}}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}},"post":{"tags":["Uptime en techniek"],"operationId":"post_security_score","summary":"Beveiligingsscore opnieuw berekenen","description":"**Wie:** Eigenaar of lid (beheer van Website); anderen krijgen 404.\n\n**Toegang:** Sessie of API-sleutel met schrijfrecht","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"action":{"const":"recompute"},"project_id":{"type":"integer"}},"required":["action","project_id"],"title":"recompute","description":"Telt opnieuw uit de laatste metingen en bewaart de score van vandaag; haalt niets op. De controles zelf lopen elke ochtend om 05:50."}]}}}},"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"ok":{"const":true},"score":{"type":["integer","null"]}},"title":"recompute"}]}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/tech-stack":{"get":{"tags":["Uptime en techniek"],"operationId":"get_tech_stack","summary":"Wat draait er op de site","description":"Herkende techniek per categorie uit de homepage en de headers (CMS, winkel, framework, meten, advertenties, toestemming, betalen, reviews, chat, hosting, lettertypen), wat er de laatste 90 dagen bij kwam of verdween, herkende diensten die nog niet gekoppeld zijn, punten die niet goed staan en gratis voorstellen. Regelwerk; `summary` is een optionele AI-alinea.\n\n**Wie:** Team; klanten met toegang tot het onderdeel Website.\n\n**Toegang:** Sessie of API-sleutel (lezen of schrijven)","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","parameters":[{"name":"project_id","in":"query","required":true,"schema":{"type":"integer"},"description":"Project-id."}],"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"hosts":{"type":"array","items":{"type":"string"}},"checked_at":{"type":["string","null"],"format":"date-time"},"detected":{"type":"array","items":{"type":"object"},"description":"category, label, items (tech, label, version, evidence, host, since, last_seen, connector, connected)"},"changes":{"type":"array","items":{"type":"object"},"description":"type (added|removed), label, host, at"},"connect":{"type":"array","items":{"type":"object"},"description":"tech, label, connector, url"},"gaps":{"type":"array","items":{"type":"object"},"description":"key, tone, title, detail, url, action"},"suggestions":{"type":"array","items":{"type":"object"},"description":"key, title, detail, url, action"},"summary":{"type":["object","null"],"description":"status, text, at"},"can_manage":{"type":"boolean"},"can_ai":{"type":"boolean"}}}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}},"post":{"tags":["Uptime en techniek"],"operationId":"post_tech_stack","summary":"Opnieuw bekijken of een samenvatting laten schrijven","description":"**Wie:** Eigenaar of lid; kijkers en klanten krijgen 403.\n\n**Toegang:** Sessie of API-sleutel met schrijfrecht","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"action":{"const":"scan"},"project_id":{"type":"integer"}},"required":["action","project_id"],"title":"scan","description":"Bekijkt de homepage(s) nu opnieuw. Hooguit eens per minuut (429)."},{"type":"object","properties":{"action":{"const":"summary"},"project_id":{"type":"integer"}},"required":["action","project_id"],"title":"summary","description":"Alleen het eigen team. Claude schrijft één alinea over de herkenning; die staat daarna als `summary` in de GET."}]}}}},"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"ok":{"const":true}},"title":"scan"},{"type":"object","properties":{"ok":{"const":true},"task_id":{"type":"integer"}},"title":"summary"}]}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/components":{"get":{"tags":["Uptime en techniek"],"operationId":"get_components","summary":"Versies en open lekken","description":"**Wie:** Team; klanten met toegang tot het onderdeel Website.\n\n**Toegang:** Sessie of API-sleutel (lezen of schrijven)","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","parameters":[{"name":"project_id","in":"query","required":true,"schema":{"type":"integer"},"description":"Project-id."}],"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"components":{"type":"array","items":{"type":"object"},"description":"ecosystem, name, version, type, dev, active, reported_at"},"reported":{"type":"object"},"vulns":{"type":"array","items":{"type":"object"},"description":"ecosystem, name, version, vuln_id, aliases, severity, summary, fixed_in, url, first_seen_at"},"resolved_30d":{"type":"integer"},"wordfence":{"type":"boolean"}}}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}},"post":{"tags":["Server naar server"],"operationId":"post_components","summary":"Lockbestanden voor de lekkencontrole","description":"Met een deploysleutel die bij een project hoort. Elke rapportage vervangt de vorige set van dat ecosysteem. Samen hooguit 5 MB.\n\n**Toegang:** Deploysleutel: `Authorization: Bearer <sleutel>`","security":[{"deployToken":[]}],"x-studio-auth":"deploy","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"files":{"type":"object","description":"Bestandsnaam naar inhoud: composer.lock, package-lock.json, Package.resolved, Cargo.lock."}},"required":["files"]}}}},"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"counts":{"type":"object"}}}}}},"401":{"$ref":"#/components/responses/401"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/cookiescan":{"get":{"tags":["Uptime en techniek"],"operationId":"get_cookiescan","summary":"Laatste cookiescan met verschil","description":"**Wie:** Team; klanten met toegang tot het onderdeel Website.\n\n**Toegang:** Sessie of API-sleutel (lezen of schrijven)","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","parameters":[{"name":"project_id","in":"query","required":true,"schema":{"type":"integer"},"description":"Project-id."}],"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"latest":{"type":["object","null"]},"last_error":{"type":["object","null"]},"findings":{"type":"array","items":{"type":"object"}},"gone":{"type":"array","items":{"type":"string"}},"has_previous":{"type":"boolean"},"history":{"type":"array","items":{"type":"object"}},"can_scan":{"type":"boolean"}}}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}},"post":{"tags":["Uptime en techniek"],"operationId":"post_cookiescan","summary":"Nu scannen","description":"**Wie:** Eigenaar of lid (beheer van Website); anderen krijgen 404.\n\n**Toegang:** Sessie of API-sleutel met schrijfrecht","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"action":{"const":"scan"},"project_id":{"type":"integer"}},"required":["action","project_id"],"title":"scan","description":"Hooguit eens per vijf minuten per project."}]}}}},"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"ok":{"const":true},"task_id":{"type":"string","description":"Volg de taak met GET /api/task?id=…"}},"title":"scan"}]}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/reports":{"get":{"tags":["Rapporten"],"operationId":"get_reports","summary":"Rapporten van een project","description":"Zonder `period`: de lijst. Met `period`: één rapport met de gegevens. Met `range`: een kwartaal (`2026-Q3`) of jaar (`2026`) uit de maandrapporten.\n\n**Wie:** Team; klanten met toegang tot het onderdeel Overzicht.\n\n**Toegang:** Sessie of API-sleutel (lezen of schrijven)","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","parameters":[{"name":"project_id","in":"query","required":true,"schema":{"type":"integer"},"description":"Project-id."},{"name":"period","in":"query","required":false,"schema":{"type":"string","pattern":"^\\d{4}-(0[1-9]|1[0-2])$"}},{"name":"range","in":"query","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"reports":{"type":"array","items":{"type":"object"},"description":"id, period, label, status, intro, generated_at, published_at"},"report":{"type":"object"},"period_report":{"type":"object"},"suggested_period":{"type":"string","pattern":"^\\d{4}-(0[1-9]|1[0-2])$"},"can_manage":{"type":"boolean"},"project":{"type":"string"},"branding":{"type":"object"},"shares":{"type":"array","items":{"type":"object"}}}}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}},"post":{"tags":["Rapporten"],"operationId":"post_reports","summary":"Rapport maken, publiceren of delen","description":"**Wie:** Eigenaar of lid; kijkers en klanten krijgen 403.\n\n**Toegang:** Sessie of API-sleutel met schrijfrecht","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"action":{"const":"generate"},"project_id":{"type":"integer"},"period":{"type":"string","pattern":"^\\d{4}-(0[1-9]|1[0-2])$","description":"Een afgelopen maand; standaard de vorige."}},"required":["action","project_id"],"title":"generate","description":"Maakt het rapport of ververst de cijfers; de toelichting blijft."},{"type":"object","properties":{"action":{"const":"intro"},"id":{"type":"integer"},"intro":{"type":"string"}},"required":["action","id"],"title":"intro"},{"type":"object","properties":{"action":{"const":"publish"},"id":{"type":"integer"}},"required":["action","id"],"title":"publish","description":"Start de automatisering die de klant mailt."},{"type":"object","properties":{"action":{"const":"unpublish"},"id":{"type":"integer"}},"required":["action","id"],"title":"unpublish"},{"type":"object","properties":{"action":{"const":"delete"},"id":{"type":"integer"}},"required":["action","id"],"title":"delete"},{"type":"object","properties":{"action":{"const":"share"},"id":{"type":"integer"},"days":{"type":"integer","description":"1 tot 90; standaard 30."}},"required":["action","id"],"title":"share","description":"Alleen gepubliceerde rapporten."},{"type":"object","properties":{"action":{"const":"unshare"},"id":{"type":"integer"},"share_id":{"type":"integer"}},"required":["action","id","share_id"],"title":"unshare"}]}}}},"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"ok":{"const":true},"task_id":{"type":"string","description":"Volg de taak met GET /api/task?id=…"},"period":{"type":"string","pattern":"^\\d{4}-(0[1-9]|1[0-2])$"}},"title":"generate"},{"type":"object","properties":{"ok":{"const":true}},"title":"intro"},{"type":"object","properties":{"ok":{"const":true},"notified":{"type":"integer"}},"title":"publish"},{"type":"object","properties":{"ok":{"const":true}},"title":"unpublish"},{"type":"object","properties":{"ok":{"const":true}},"title":"delete"},{"type":"object","properties":{"ok":{"const":true},"link":{"type":"string","format":"uri"},"expires_at":{"type":"string","format":"date"}},"title":"share"},{"type":"object","properties":{"ok":{"const":true}},"title":"unshare"}]}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/reports/pdf":{"get":{"tags":["Rapporten"],"operationId":"get_reports_pdf","summary":"Rapport als PDF","description":"**Wie:** Team; klanten met toegang tot het onderdeel Overzicht.\n\n**Toegang:** Sessie of API-sleutel (lezen of schrijven)","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","parameters":[{"name":"id","in":"query","required":true,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Gelukt.","content":{"application/pdf":{"schema":{"type":"string","format":"binary"}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/ads":{"get":{"tags":["Google Ads"],"operationId":"get_ads","summary":"Google Ads van een project","description":"**Wie:** Team; klanten met toegang tot het onderdeel Ads.\n\n**Toegang:** Sessie of API-sleutel (lezen of schrijven)","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","parameters":[{"name":"project_id","in":"query","required":true,"schema":{"type":"integer"},"description":"Project-id."}],"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"summary":{"type":["object","null"]},"pacing":{"type":"array","items":{"type":"object"}},"ngrams":{"type":["object","null"]},"quality":{"type":["object","null"]},"budget":{"type":["object","null"]},"ad_tests":{"type":"array","items":{"type":"object"}},"pmax":{"type":"array","items":{"type":"object"}},"can_manage":{"type":"boolean"},"autopilot":{"type":["object","null"],"description":"Alleen voor wie beheert: mode, max_change_pct, max_daily_budget, max_changes_per_day, max_week_change_pct, allowed_kinds, excluded_campaigns, quiet_from, quiet_until, enabled_at, enabled_by, stopped_at, killed_at, auto_apply, campaigns, me (two_factor, owner, reauth), proposals (met effect, reversible, can_revert, auto_blocked) en changes (het logboek: action, result, before, after, request_id, user)."}}}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}},"post":{"tags":["Google Ads"],"operationId":"post_ads","summary":"Doelen, ideeën en de Ads-piloot","description":"**Wie:** Eigenaar of lid; kijkers en klanten krijgen 403.\n\n**Toegang:** Sessie of API-sleutel met schrijfrecht","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"action":{"const":"targets"},"project_id":{"type":"integer"},"target_cpa":{"type":"number"},"order_value":{"type":"number"},"margin_pct":{"type":"number"}},"required":["action","project_id"],"title":"targets"},{"type":"object","properties":{"action":{"const":"ideas"},"project_id":{"type":"integer"},"seeds":{"type":"array","items":{"type":"string"},"description":"Hooguit tien."}},"required":["action","project_id","seeds"],"title":"ideas","description":"Via Keyword Planner; een week gecachet."},{"type":"object","properties":{"action":{"const":"mode"},"project_id":{"type":"integer"},"mode":{"type":"string","enum":["uit","lezen","voorstellen","automatisch"]},"max_change_pct":{"type":"integer","description":"1 tot 100; standaard 20."},"max_daily_budget":{"type":"number"},"max_changes_per_day":{"type":"integer","description":"1 tot 50; standaard 5."},"max_week_change_pct":{"type":"integer","description":"Hoeveel een budget in zeven dagen mag schuiven; standaard 30."},"allowed_kinds":{"type":"array","items":{"type":"string"},"description":"budget, negative en/of pause_keyword; standaard budget en negative."},"excluded_campaigns":{"type":"array","items":{"type":"integer"}},"quiet_from":{"type":["integer","null"],"description":"Uur 0–23; samen met quiet_until."},"quiet_until":{"type":["integer","null"]},"password":{"type":"string"},"code":{"type":"string"}},"required":["action","project_id","mode"],"title":"mode","description":"`automatisch` en ruimere grenzen alleen door de eigenaar, met tweestap aan en de `code` uit de authenticator (telt tien minuten; een wachtwoord is niet genoeg, sinds 11-10-2026). Zonder geldige code 422 `reauth`. Niet met een API-sleutel (403); `stop` en `kill` wel."},{"type":"object","properties":{"action":{"const":"propose"},"project_id":{"type":"integer"}},"required":["action","project_id"],"title":"propose"},{"type":"object","properties":{"action":{"const":"apply"},"project_id":{"type":"integer"},"proposal_id":{"type":"integer"},"confirm_irreversible":{"type":"boolean","description":"Verplicht voor wat niet terug te draaien is (Googles aanbevelingen)."},"password":{"type":"string"},"code":{"type":"string"}},"required":["action","project_id","proposal_id"],"title":"apply","description":"Met tweestap. Eerst met validateOnly naar Google, dan echt; elke uitkomst komt in het logboek."},{"type":"object","properties":{"action":{"const":"reject"},"project_id":{"type":"integer"},"proposal_id":{"type":"integer"},"reason":{"type":"string"}},"required":["action","project_id","proposal_id"],"title":"reject"},{"type":"object","properties":{"action":{"const":"revert"},"project_id":{"type":"integer"},"proposal_id":{"type":"integer"},"password":{"type":"string"},"code":{"type":"string"}},"required":["action","project_id","proposal_id"],"title":"revert","description":"Met tweestap; mag ook met de noodstop aan."},{"type":"object","properties":{"action":{"const":"stop"},"project_id":{"type":"integer"}},"required":["action","project_id"],"title":"stop","description":"Noodstop voor dit project: terug naar lezen."},{"type":"object","properties":{"action":{"const":"kill"},"project_id":{"type":"integer"}},"required":["action","project_id"],"title":"kill","description":"Noodstop voor alle projecten van de workspace; zonder tweestap, zodat stoppen altijd snel kan."},{"type":"object","properties":{"action":{"const":"release"},"project_id":{"type":"integer"},"password":{"type":"string"},"code":{"type":"string"}},"required":["action","project_id"],"title":"release","description":"Noodstop van de workspace uit: alleen de eigenaar, met tweestap."}]}}}},"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"ok":{"const":true}},"title":"targets"},{"type":"object","properties":{"ok":{"const":true},"ideas":{"type":"array","items":{"type":"object"}},"seeds":{"type":"array","items":{"type":"string"}}},"title":"ideas"},{"type":"object","properties":{"ok":{"const":true}},"title":"mode"},{"type":"object","properties":{"ok":{"const":true}},"title":"propose"},{"type":"object","properties":{"ok":{"const":true},"proposal":{"type":"object"}},"title":"apply"},{"type":"object","properties":{"ok":{"const":true}},"title":"reject"},{"type":"object","properties":{"ok":{"const":true}},"title":"revert"},{"type":"object","properties":{"ok":{"const":true}},"title":"stop"},{"type":"object","properties":{"ok":{"const":true}},"title":"kill"},{"type":"object","properties":{"ok":{"const":true}},"title":"release"}]}}}},"401":{"$ref":"#/components/responses/401"},"402":{"$ref":"#/components/responses/402"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/automations":{"get":{"tags":["Automatiseringen en meldingen"],"operationId":"get_automations","summary":"Automatiseringen, catalogus, logboek en goedkeuringen","description":"Zonder parameters: de lijst plus de catalogus van triggers en acties. `runs=1`: het logboek (25 per pagina). `run=ID`: één uitvoering. `approvals=1`: wat op goedkeuring wacht.\n\n**Wie:** Alleen het team (eigenaar, lid of kijker); klanten krijgen 403.\n\n**Toegang:** Sessie of API-sleutel (lezen of schrijven)","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","parameters":[{"name":"runs","in":"query","required":false,"schema":{"type":"boolean"}},{"name":"run","in":"query","required":false,"schema":{"type":"integer"}},{"name":"approvals","in":"query","required":false,"schema":{"type":"boolean"}},{"name":"automation_id","in":"query","required":false,"schema":{"type":"integer"}},{"name":"status","in":"query","required":false,"schema":{"type":"string"}},{"name":"project_id","in":"query","required":false,"schema":{"type":"integer"}},{"name":"page","in":"query","required":false,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"automations":{"type":"array","items":{"type":"object"},"description":"id, name, enabled, is_default, trigger_type, trigger_params, project_id, filters, actions, rate_limit, requires_approval, fired, fired_30d, last_run, hook_url, schedule, can_run"},"catalog":{"type":"object"},"action_catalog":{"type":"object"},"templates":{"type":"array","items":{"type":"object"}},"triggers":{"type":"array","items":{"type":"object"}},"runs":{"type":"array","items":{"type":"object"}},"total":{"type":"integer"},"pages":{"type":"integer"},"run":{"type":"object"},"approvals":{"type":"array","items":{"type":"object"}},"limit":{"type":["integer","null"]},"used":{"type":"integer"},"timezone":{"type":"string"}}}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}},"post":{"tags":["Automatiseringen en meldingen"],"operationId":"post_automations","summary":"Automatiseringen opslaan, testen en uitvoeren","description":"**Wie:** Eigenaar of lid; kijkers en klanten krijgen 403.\n\n**Toegang:** Sessie of API-sleutel met schrijfrecht","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"action":{"const":"save"},"id":{"type":"integer","description":"Zonder id: nieuw."},"name":{"type":"string"},"trigger_type":{"type":"string","description":"Uit `catalog`."},"trigger_params":{"type":"object"},"project_id":{"type":["integer","null"]},"filters":{"type":"array","items":{"type":"object"}},"actions":{"type":"array","items":{"type":"object"},"description":"Elk {type, params}; als-dan-anders is type branch met then en else."},"rate_limit":{"type":"object"},"requires_approval":{"type":"boolean","description":"Uitzetten kan alleen de eigenaar."},"enabled":{"type":"boolean"}},"required":["action","name","trigger_type","actions"],"title":"save","description":"Fouten komen per veld terug in `fields`."},{"type":"object","properties":{"action":{"const":"test"},"id":{"type":"integer"},"run_id":{"type":"integer","description":"Gegevens van een eerdere uitvoering in plaats van het voorbeeld."}},"required":["action"],"title":"test","description":"Droogloop met dezelfde velden als save, of alleen een id; controleert, maar schrijft en verstuurt niets."},{"type":"object","properties":{"action":{"const":"timezone"},"timezone":{"type":"string","description":"Een IANA-naam, zoals Europe/Amsterdam."}},"required":["action","timezone"],"title":"timezone"},{"type":"object","properties":{"action":{"const":"toggle"},"id":{"type":"integer"}},"required":["action","id"],"title":"toggle"},{"type":"object","properties":{"action":{"const":"delete"},"id":{"type":"integer"}},"required":["action","id"],"title":"delete","description":"Een standaardautomatisering gaat uit in plaats van weg."},{"type":"object","properties":{"action":{"const":"run"},"id":{"type":"integer"}},"required":["action","id"],"title":"run","description":"Alleen bij een handmatige trigger of een schema."},{"type":"object","properties":{"action":{"const":"rotate_hook"},"id":{"type":"integer"}},"required":["action","id"],"title":"rotate_hook","description":"Nieuw adres voor een inkomende webhook; het oude werkt meteen niet meer."},{"type":"object","properties":{"action":{"const":"reset"},"id":{"type":"integer"}},"required":["action","id"],"title":"reset"},{"type":"object","properties":{"action":{"const":"retry"},"run_id":{"type":"integer"},"action_index":{"type":"integer"}},"required":["action","run_id","action_index"],"title":"retry"},{"type":"object","properties":{"action":{"const":"approve"},"approval_id":{"type":"integer"}},"required":["action","approval_id"],"title":"approve"},{"type":"object","properties":{"action":{"const":"reject"},"approval_id":{"type":"integer"}},"required":["action","approval_id"],"title":"reject"}]}}}},"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"ok":{"const":true},"id":{"type":"integer"}},"title":"save"},{"type":"object","properties":{"ok":{"const":true},"source":{"type":"string"},"data":{"type":"object"}},"additionalProperties":true,"title":"test"},{"type":"object","properties":{"ok":{"const":true},"timezone":{"type":"string"}},"title":"timezone"},{"type":"object","properties":{"ok":{"const":true}},"title":"toggle"},{"type":"object","properties":{"ok":{"const":true}},"title":"delete"},{"type":"object","properties":{"ok":{"const":true},"run_id":{"type":["integer","null"]}},"title":"run"},{"type":"object","properties":{"ok":{"const":true}},"title":"rotate_hook"},{"type":"object","properties":{"ok":{"const":true}},"title":"reset"},{"type":"object","properties":{"ok":{"const":true}},"title":"retry"},{"type":"object","properties":{"ok":{"const":true}},"title":"approve"},{"type":"object","properties":{"ok":{"const":true}},"title":"reject"}]}}}},"401":{"$ref":"#/components/responses/401"},"402":{"$ref":"#/components/responses/402"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/alerts":{"get":{"tags":["Automatiseringen en meldingen"],"operationId":"get_alerts","summary":"Meldingsregels en wat er verstuurd is","description":"**Wie:** Alleen het team (eigenaar, lid of kijker); klanten krijgen 403.\n\n**Toegang:** Sessie of API-sleutel (lezen of schrijven)","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"emails":{"type":"array","items":{"type":"string"}},"rules":{"type":"array","items":{"type":"object"}},"automatic":{"type":"array","items":{"type":"object"}},"log":{"type":"array","items":{"type":"object"}},"approvals_open":{"type":"integer"},"actions":{"type":"object"},"recipients":{"type":"object"},"channels":{"type":"array","items":{"type":"object"}},"webhooks":{"type":"array","items":{"type":"object"}},"team":{"type":"array","items":{"type":"object"}},"can_edit":{"type":"boolean"},"is_owner":{"type":"boolean"}}}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}},"post":{"tags":["Automatiseringen en meldingen"],"operationId":"post_alerts","summary":"Meldingsregel maken of wijzigen","description":"**Wie:** Eigenaar of lid; kijkers en klanten krijgen 403.\n\n**Toegang:** Sessie of API-sleutel met schrijfrecht","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"action":{"const":"create"},"kind":{"type":"string","enum":["threshold_live","milestone","event"]},"project_id":{"type":["integer","null"],"description":"Verplicht bij event."},"metric":{"type":"string"},"threshold":{"type":"integer","description":"Minstens 1."},"name":{"type":"string"},"actions":{"type":"array","items":{"type":"object"}}},"required":["action","kind","threshold"],"title":"create"},{"type":"object","properties":{"action":{"const":"update"},"rule_id":{"type":"integer"},"threshold":{"type":"integer"},"metric":{"type":"string"},"project_id":{"type":["integer","null"]},"name":{"type":"string"},"actions":{"type":"array","items":{"type":"object"}},"requires_approval":{"type":"boolean"},"enabled":{"type":"boolean"}},"required":["action","rule_id"],"title":"update"},{"type":"object","properties":{"action":{"const":"delete"},"rule_id":{"type":"integer"}},"required":["action","rule_id"],"title":"delete"},{"type":"object","properties":{"action":{"const":"toggle"},"rule_id":{"type":"integer"},"enabled":{"type":"boolean"}},"required":["action","rule_id","enabled"],"title":"toggle"}]}}}},"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"ok":{"const":true},"rule_id":{"type":"integer"}},"title":"create"},{"type":"object","properties":{"ok":{"const":true}},"title":"update"},{"type":"object","properties":{"ok":{"const":true}},"title":"delete"},{"type":"object","properties":{"ok":{"const":true}},"title":"toggle"}]}}}},"401":{"$ref":"#/components/responses/401"},"402":{"$ref":"#/components/responses/402"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/webhooks":{"get":{"tags":["Automatiseringen en meldingen"],"operationId":"get_webhooks","summary":"Uitgaande webhooks","description":"**Wie:** Eigenaar of lid; kijkers en klanten krijgen 403.\n\n**Toegang:** Sessie of API-sleutel (lezen of schrijven)","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"webhooks":{"type":"array","items":{"type":"object"},"description":"id, url, events, last_status, last_error, last_at, created_at"},"events":{"type":"object"}}}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}},"post":{"tags":["Automatiseringen en meldingen"],"operationId":"post_webhooks","summary":"Webhook toevoegen, testen of weghalen","description":"**Wie:** Eigenaar of lid; kijkers en klanten krijgen 403.\n\n**Toegang:** Sessie of API-sleutel met schrijfrecht","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"action":{"const":"create"},"url":{"type":"string","format":"uri","description":"Een openbaar https-adres."},"events":{"type":"array","items":{"type":"string"},"description":"advice.created, incident.opened, incident.resolved, report.published, anomaly.detected, question.asked, vulnerability.found."}},"required":["action","url","events"],"title":"create","description":"Hooguit tien per workspace."},{"type":"object","properties":{"action":{"const":"delete"},"id":{"type":"integer"}},"required":["action","id"],"title":"delete"},{"type":"object","properties":{"action":{"const":"test"},"id":{"type":"integer"}},"required":["action","id"],"title":"test","description":"Stuurt `{\"event\": \"test\"}`."}]}}}},"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"ok":{"const":true},"id":{"type":"integer"},"secret":{"type":"string","description":"Eén keer te zien."}},"title":"create"},{"type":"object","properties":{"ok":{"const":true}},"title":"delete"},{"type":"object","properties":{"ok":{"const":true}},"title":"test"}]}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/chat":{"get":{"tags":["Automatiseringen en meldingen"],"operationId":"get_chat","summary":"Slack- en Teams-kanalen","description":"**Wie:** Eigenaar of lid; kijkers en klanten krijgen 403.\n\n**Toegang:** Sessie of API-sleutel (lezen of schrijven)","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"channels":{"type":"array","items":{"type":"object"},"description":"id, kind, name, events, last_status, last_at"},"events":{"type":"object"}}}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}},"post":{"tags":["Automatiseringen en meldingen"],"operationId":"post_chat","summary":"Kanaal toevoegen, testen of weghalen","description":"**Wie:** Eigenaar of lid; kijkers en klanten krijgen 403.\n\n**Toegang:** Sessie of API-sleutel met schrijfrecht","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"action":{"const":"create"},"kind":{"type":"string","enum":["slack","teams"]},"name":{"type":"string"},"url":{"type":"string","format":"uri","description":"Webhook-adres uit Slack of Teams."},"events":{"type":"array","items":{"type":"string"}}},"required":["action","kind","url","events"],"title":"create"},{"type":"object","properties":{"action":{"const":"delete"},"id":{"type":"integer"}},"required":["action","id"],"title":"delete"},{"type":"object","properties":{"action":{"const":"test"},"id":{"type":"integer"}},"required":["action","id"],"title":"test"}]}}}},"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"ok":{"const":true}},"title":"create"},{"type":"object","properties":{"ok":{"const":true}},"title":"delete"},{"type":"object","properties":{"ok":{"const":true},"status":{"type":["string","null"]}},"title":"test"}]}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/slack":{"get":{"tags":["Automatiseringen en meldingen"],"operationId":"get_slack","summary":"Slack-bot: instellingen zonder geheimen","description":"**Wie:** Eigenaar of lid; kijkers en klanten krijgen 403.\n\n**Toegang:** Sessie of API-sleutel (lezen of schrijven)","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"app":{"type":["object","null"],"description":"channel, events, last_status, last_at"},"events":{"type":"array","items":{"type":"string"}},"interactivity_url":{"type":"string","format":"uri"}}}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}},"post":{"tags":["Automatiseringen en meldingen"],"operationId":"post_slack","summary":"Slack-bot instellen","description":"**Wie:** Eigenaar of lid; kijkers en klanten krijgen 403.\n\n**Toegang:** Sessie of API-sleutel met schrijfrecht","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"action":{"const":"save"},"bot_token":{"type":"string","description":"xoxb-…; leeg houdt het bestaande."},"signing_secret":{"type":"string"},"channel":{"type":"string","description":"Kanaal-ID (C…)."},"events":{"type":"array","items":{"type":"string"}}},"required":["action","channel"],"title":"save"},{"type":"object","properties":{"action":{"const":"remove"}},"required":["action"],"title":"remove"},{"type":"object","properties":{"action":{"const":"test"}},"required":["action"],"title":"test"}]}}}},"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"ok":{"const":true}},"title":"save"},{"type":"object","properties":{"ok":{"const":true}},"title":"remove"},{"type":"object","properties":{"ok":{"const":true},"status":{"type":["string","null"]}},"title":"test"}]}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/contacts":{"get":{"tags":["Studio Mail"],"operationId":"get_contacts","summary":"Contacten, lijsten, formulieren, sjablonen en domeinen","description":"Zonder parameters: het overzicht. `list=contacten`: contacten met filters (50 per pagina). `contact_id=…`: één contact met tijdlijn, lijsten en funnels.\n\n**Wie:** Alleen het team (eigenaar, lid of kijker); klanten krijgen 403.\n\n**Toegang:** Sessie of API-sleutel (lezen of schrijven)","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","parameters":[{"name":"list","in":"query","required":false,"schema":{"type":"string","enum":["contacten"]}},{"name":"contact_id","in":"query","required":false,"schema":{"type":"integer"}},{"name":"status","in":"query","required":false,"schema":{"type":"string","enum":["unconfirmed","subscribed","unsubscribed","bounced","complained"]}},{"name":"project_id","in":"query","required":false,"schema":{"type":"integer"}},{"name":"list_id","in":"query","required":false,"schema":{"type":"integer"}},{"name":"tag","in":"query","required":false,"schema":{"type":"string"}},{"name":"min_score","in":"query","required":false,"schema":{"type":"number"}},{"name":"segment_id","in":"query","required":false,"schema":{"type":"integer"}},{"name":"q","in":"query","required":false,"schema":{"type":"string"}},{"name":"sort","in":"query","required":false,"schema":{"type":"string","enum":["score"]}},{"name":"page","in":"query","required":false,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"providers":{"type":"array","items":{"type":"object"}},"counts":{"type":"object"},"tags":{"type":"array","items":{"type":"string"}},"open_tracking":{"type":"boolean"},"segments":{"type":"array","items":{"type":"object"}},"lists":{"type":"array","items":{"type":"object"}},"forms":{"type":"array","items":{"type":"object"}},"templates":{"type":"array","items":{"type":"object"}},"domains":{"type":"array","items":{"type":"object"}},"accounts":{"type":"array","items":{"type":"object"}},"regions":{"type":"object"},"contacts":{"type":"array","items":{"type":"object"},"description":"id, email, name, status, source, project_id, tags, consent_at, created_at, score"},"total":{"type":"integer"},"page":{"type":"integer"},"contact":{"type":"object"}}}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}},"post":{"tags":["Studio Mail"],"operationId":"post_contacts","summary":"Contacten, formulieren, sjablonen, domeinen en accounts beheren","description":"**Wie:** Eigenaar of lid; kijkers en klanten krijgen 403.\n\n**Toegang:** Sessie of API-sleutel met schrijfrecht","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"action":{"const":"contact.update"},"id":{"type":"integer"},"name":{"type":"string"},"language":{"type":"string","enum":["nl","en"],"description":"Taal van de bevestigings- en afmeldpagina's en -mails."},"tags":{"type":"array","items":{"type":"string"}},"project_id":{"type":"integer"},"list_ids":{"type":"array","items":{"type":"integer"}}},"required":["action","id"],"title":"contact.update"},{"type":"object","properties":{"action":{"const":"contact.unsubscribe"},"id":{"type":"integer"}},"required":["action","id"],"title":"contact.unsubscribe"},{"type":"object","properties":{"action":{"const":"contact.delete"},"id":{"type":"integer"}},"required":["action","id"],"title":"contact.delete","description":"Wist ook de meetgegevens van het contact."},{"type":"object","properties":{"action":{"const":"list.save"},"id":{"type":"integer"},"name":{"type":"string"}},"required":["action","name"],"title":"list.save"},{"type":"object","properties":{"action":{"const":"list.delete"},"id":{"type":"integer"}},"required":["action","id"],"title":"list.delete"},{"type":"object","properties":{"action":{"const":"form.save"},"id":{"type":"integer"},"name":{"type":"string"},"language":{"type":"string","enum":["nl","en"],"description":"Taal van het formulier en de embedcode; standaard nl."},"consent_text":{"type":"string"},"list_id":{"type":"integer"},"domain_id":{"type":"integer"},"project_id":{"type":"integer"},"redirect_url":{"type":"string","format":"uri","description":"Bedankpagina, https."}},"required":["action","name","consent_text"],"title":"form.save"},{"type":"object","properties":{"action":{"const":"form.delete"},"id":{"type":"integer"}},"required":["action","id"],"title":"form.delete"},{"type":"object","properties":{"action":{"const":"import"},"list_id":{"type":"integer"},"confirmed":{"type":"boolean","description":"Bevestiging dat iedereen toestemming gaf."},"csv":{"type":"string","description":"E-mailadres en naam per regel, optioneel een derde kolom met de taal (nl of en); hooguit 2 MB."},"declaration":{"type":"string"}},"required":["action","confirmed","csv","declaration"],"title":"import","description":"Weigert de import als meer dan 20% van de regels ongeldig is; rol-adressen (info@, sales@ …) worden overgeslagen."},{"type":"object","properties":{"action":{"const":"template.save"},"id":{"type":"integer"},"name":{"type":"string"},"subject":{"type":"string"},"mjml":{"type":"string"},"html":{"type":"string"},"text":{"type":"string"}},"required":["action","name","subject","html"],"title":"template.save"},{"type":"object","properties":{"action":{"const":"template.delete"},"id":{"type":"integer"}},"required":["action","id"],"title":"template.delete"},{"type":"object","properties":{"action":{"const":"template.test"},"id":{"type":"integer"},"confirmed":{"type":"boolean"},"domain_id":{"type":"integer"}},"required":["action","id","confirmed"],"title":"template.test","description":"Testmail naar jezelf."},{"type":"object","properties":{"action":{"const":"domain.add"},"domain":{"type":"string"},"from_local":{"type":"string","description":"Standaard nieuws."},"from_name":{"type":"string"},"provider":{"type":"string","enum":["ses","resend"]},"account_id":{"type":"integer","description":"Eigen verzendaccount; dan volgt de verzender daaruit."},"project_id":{"type":"integer"}},"required":["action","domain"],"title":"domain.add"},{"type":"object","properties":{"action":{"const":"domain.check"},"id":{"type":"integer"}},"required":["action","id"],"title":"domain.check"},{"type":"object","properties":{"action":{"const":"domain.resume"},"id":{"type":"integer"}},"required":["action","id"],"title":"domain.resume","description":"Haalt een automatische pauze weg."},{"type":"object","properties":{"action":{"const":"domain.delete"},"id":{"type":"integer"}},"required":["action","id"],"title":"domain.delete"},{"type":"object","properties":{"action":{"const":"account.save"},"id":{"type":"integer"},"provider":{"type":"string","enum":["ses","resend"]},"name":{"type":"string"},"project_id":{"type":"integer"},"credentials":{"type":"object","description":"Resend: key, webhook_secret, region. SES: key, secret, region, configuration_set, sns_topic_arn. Leeg houdt de bestaande waarde."}},"required":["action","name"],"title":"account.save","description":"Test de sleutel meteen. Sleutels komen nooit terug; alleen de laatste vier tekens."},{"type":"object","properties":{"action":{"const":"account.test"},"id":{"type":"integer"}},"required":["action","id"],"title":"account.test"},{"type":"object","properties":{"action":{"const":"account.delete"},"id":{"type":"integer"}},"required":["action","id"],"title":"account.delete","description":"Pas als er geen domeinen meer aan hangen."},{"type":"object","properties":{"action":{"const":"settings"},"open_tracking":{"type":"boolean"}},"required":["action"],"title":"settings"}]}}}},"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"ok":{"const":true}},"title":"contact.update"},{"type":"object","properties":{"ok":{"const":true}},"title":"contact.unsubscribe"},{"type":"object","properties":{"ok":{"const":true}},"title":"contact.delete"},{"type":"object","properties":{"ok":{"const":true},"id":{"type":"integer"}},"title":"list.save"},{"type":"object","properties":{"ok":{"const":true}},"title":"list.delete"},{"type":"object","properties":{"ok":{"const":true},"id":{"type":"integer"}},"title":"form.save"},{"type":"object","properties":{"ok":{"const":true}},"title":"form.delete"},{"type":"object","properties":{"ok":{"const":true},"imported":{"type":"boolean"},"added":{"type":"integer"},"updated":{"type":"integer"},"invalid":{"type":"integer"},"role":{"type":"integer"},"duplicates":{"type":"integer"},"suppressed":{"type":"integer"}},"title":"import"},{"type":"object","properties":{"ok":{"const":true},"id":{"type":"integer"}},"title":"template.save"},{"type":"object","properties":{"ok":{"const":true}},"title":"template.delete"},{"type":"object","properties":{"ok":{"const":true},"sent_to":{"type":"string","format":"email"}},"title":"template.test"},{"type":"object","properties":{"ok":{"const":true},"domain":{"type":"object"}},"title":"domain.add"},{"type":"object","properties":{"ok":{"const":true},"domain":{"type":"object"}},"title":"domain.check"},{"type":"object","properties":{"ok":{"const":true}},"title":"domain.resume"},{"type":"object","properties":{"ok":{"const":true}},"title":"domain.delete"},{"type":"object","properties":{"ok":{"const":true},"account":{"type":"object"}},"title":"account.save"},{"type":"object","properties":{"ok":{"const":true},"account":{"type":"object"}},"title":"account.test"},{"type":"object","properties":{"ok":{"const":true}},"title":"account.delete"},{"type":"object","properties":{"ok":{"const":true}},"title":"settings"}]}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/mail":{"get":{"tags":["Studio Mail"],"operationId":"get_mail","summary":"Funnels, campagnes en segmenten","description":"`funnel=ID`: trechter en mails van één funnel; met `contacts=1` (en `step`, `status`, `page`) de contacten erin. `campaign=ID`: één campagne met resultaten.\n\n**Wie:** Alleen het team (eigenaar, lid of kijker); klanten krijgen 403.\n\n**Toegang:** Sessie of API-sleutel (lezen of schrijven)","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","parameters":[{"name":"funnel","in":"query","required":false,"schema":{"type":"integer"}},{"name":"contacts","in":"query","required":false,"schema":{"type":"boolean"}},{"name":"step","in":"query","required":false,"schema":{"type":"integer"}},{"name":"status","in":"query","required":false,"schema":{"type":"string"}},{"name":"page","in":"query","required":false,"schema":{"type":"integer"}},{"name":"campaign","in":"query","required":false,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"providers":{"type":"array","items":{"type":"object"}},"attribution":{"type":"boolean"},"funnels":{"type":"array","items":{"type":"object"}},"campaigns":{"type":"array","items":{"type":"object"}},"segments":{"type":"array","items":{"type":"object"}},"segment_fields":{"type":"array","items":{"type":"object"}},"segment_ops":{"type":"object"},"goals":{"type":"object"},"funnel":{"type":"object"},"campaign":{"type":"object"}}}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}},"post":{"tags":["Studio Mail"],"operationId":"post_mail","summary":"Segmenten en campagnes","description":"**Wie:** Eigenaar of lid; kijkers en klanten krijgen 403.\n\n**Toegang:** Sessie of API-sleutel met schrijfrecht","security":[{"session":[]},{"apiKey":[]}],"x-studio-auth":"key","requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"action":{"const":"segment.preview"},"definition":{"type":"object","description":"{match: all|any, rules: [{field, op, value}]}, hooguit 20 regels."}},"required":["action","definition"],"title":"segment.preview"},{"type":"object","properties":{"action":{"const":"segment.save"},"id":{"type":"integer"},"name":{"type":"string"},"definition":{"type":"object"}},"required":["action","name","definition"],"title":"segment.save"},{"type":"object","properties":{"action":{"const":"segment.delete"},"id":{"type":"integer"}},"required":["action","id"],"title":"segment.delete"},{"type":"object","properties":{"action":{"const":"campaign.save"},"id":{"type":"integer"},"name":{"type":"string"},"template_id":{"type":"integer"},"domain_id":{"type":"integer"},"list_id":{"type":"integer"},"segment_id":{"type":"integer"},"subject_b":{"type":"string","description":"Tweede onderwerp voor een A/B-test."},"ab_percent":{"type":"integer","description":"5 tot 50."},"ab_hours":{"type":"integer","description":"1 tot 72."}},"required":["action","name"],"title":"campaign.save","description":"Alleen een concept kan nog wijzigen."},{"type":"object","properties":{"action":{"const":"campaign.schedule"},"id":{"type":"integer"},"confirmed":{"type":"boolean"},"now":{"type":"boolean"},"scheduled_at":{"type":"string","format":"date-time"}},"required":["action","id","confirmed"],"title":"campaign.schedule"},{"type":"object","properties":{"action":{"const":"campaign.cancel"},"id":{"type":"integer"}},"required":["action","id"],"title":"campaign.cancel"},{"type":"object","properties":{"action":{"const":"campaign.delete"},"id":{"type":"integer"}},"required":["action","id"],"title":"campaign.delete"},{"type":"object","properties":{"action":{"const":"campaign.preview"},"id":{"type":"integer"}},"required":["action","id"],"title":"campaign.preview"},{"type":"object","properties":{"action":{"const":"campaign.test"},"id":{"type":"integer"},"confirmed":{"type":"boolean"},"variant":{"type":"string","enum":["a","b"]}},"required":["action","id","confirmed"],"title":"campaign.test"},{"type":"object","properties":{"action":{"const":"settings"},"attribution":{"type":"boolean","description":"Klikattributie aan of uit."}},"required":["action"],"title":"settings"}]}}}},"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"ok":{"const":true},"count":{"type":"integer"},"subscribed":{"type":"integer"},"sample":{"type":"array","items":{"type":"object"}}},"title":"segment.preview"},{"type":"object","properties":{"ok":{"const":true},"id":{"type":"integer"}},"title":"segment.save"},{"type":"object","properties":{"ok":{"const":true}},"title":"segment.delete"},{"type":"object","properties":{"ok":{"const":true},"id":{"type":"integer"},"audience":{"type":"integer"}},"title":"campaign.save"},{"type":"object","properties":{"ok":{"const":true},"campaign":{"type":"object"}},"title":"campaign.schedule"},{"type":"object","properties":{"ok":{"const":true}},"title":"campaign.cancel"},{"type":"object","properties":{"ok":{"const":true}},"title":"campaign.delete"},{"type":"object","properties":{"ok":{"const":true},"subject_a":{"type":"string"},"subject_b":{"type":["string","null"]},"html":{"type":"string"}},"title":"campaign.preview"},{"type":"object","properties":{"ok":{"const":true},"sent_to":{"type":"string","format":"email"}},"title":"campaign.test"},{"type":"object","properties":{"ok":{"const":true}},"title":"settings"}]}}}},"401":{"$ref":"#/components/responses/401"},"403":{"$ref":"#/components/responses/403"},"404":{"$ref":"#/components/responses/404"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/events":{"post":{"tags":["Server naar server"],"operationId":"post_events","summary":"Conversie-event vanuit je eigen backend","description":"Het project volgt uit de sleutel. `event_id` is een UUID v4 en moet gelijk zijn aan de header `Idempotency-Key`; hetzelfde event nog eens sturen geeft `200` met `duplicate: true`. Hooguit 8 kB.\n\n**Toegang:** Conversiesleutel van de bron: `Authorization: Bearer <sleutel>`","security":[{"conversionToken":[]}],"x-studio-auth":"conversion","parameters":[{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string"},"description":"Gelijk aan event_id."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"event_id":{"type":"string"},"event":{"type":"string","enum":["website_visited","signup_started","account_created","email_verified","onboarding_completed","activated","subscription_started","payment_succeeded","subscription_canceled"]},"occurred_at":{"type":"string","format":"date-time","description":"ISO 8601; niet meer dan 5 minuten in de toekomst."},"account_ref":{"type":"string","description":"UUID, geen e-mailadres."},"visitor_id":{"type":"string"},"session_id":{"type":"string"},"properties":{"type":"object","description":"source, plan, amount (als \"25.00\"), currency."},"attribution":{"type":"object","description":"landing_page, referrer, utm_source, utm_medium, utm_campaign, utm_term, utm_content, gclid, fbclid, msclkid, studio_ref."}},"required":["event_id","event","occurred_at"]},"example":{"event_id":"0b6f1c1e-6f0a-4c51-9d2b-3c1f6f7a8e90","event":"payment_succeeded","occurred_at":"2026-10-05T14:03:00+02:00","account_ref":"6f1d2c3b-1a2b-4c3d-8e9f-0a1b2c3d4e5f","properties":{"plan":"pro","amount":"25.00","currency":"EUR"}}}}},"responses":{"201":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"duplicate":{"type":"boolean"}}},"example":{"ok":true,"duplicate":false}}}},"401":{"$ref":"#/components/responses/401"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/deploys":{"post":{"tags":["Server naar server"],"operationId":"post_deploys","summary":"Deploy op de tijdlijn","description":"Dezelfde commit twee keer is één gebeurtenis; alleen een nieuwe deploy start automatiseringen.\n\n**Toegang:** Deploysleutel: `Authorization: Bearer <sleutel>`","security":[{"deployToken":[]}],"x-studio-auth":"deploy","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"title":{"type":"string"},"commit":{"type":"string"},"url":{"type":"string","format":"uri"}}}}}},"responses":{"201":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true}}}}}},"401":{"$ref":"#/components/responses/401"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/mcp":{"post":{"tags":["Server naar server"],"operationId":"post_mcp","summary":"MCP-server voor Claude en andere assistenten","description":"JSON-RPC 2.0 over HTTP (Streamable HTTP zonder SSE), alleen lezen: `initialize`, `ping`, `tools/list`, `tools/call`. Tools: projecten, stand_van_project, adviezen, belangrijkste_acties, zoektermen. Elke persoonlijke sleutel werkt, ook lezen of schrijven. Koppelen: `claude mcp add --transport http studio https://instnt.studio/api/mcp --header \"Authorization: Bearer <sleutel>\"`.\n\n**Toegang:** Elke persoonlijke API-sleutel (MCP, lezen of schrijven)","security":[{"apiKey":[]}],"x-studio-auth":"apitoken","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"jsonrpc":{"type":"string"},"id":{"type":"integer"},"method":{"type":"string"},"params":{"type":"object"}},"required":["jsonrpc","method"]}}}},"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"jsonrpc":{"type":"string"},"id":{"type":"integer"},"result":{"type":"object"},"error":{"type":"object"}}}}}},"401":{"$ref":"#/components/responses/401"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/hooks/appstore/{token}":{"post":{"tags":["Server naar server"],"operationId":"post_hooks_appstore_token","summary":"Melding van App Store Connect (webhook)","description":"Met de header `x-apple-signature: hmacsha256=<hex>` (HMAC-SHA256 van de body met het geheim). Studio haalt de app daarna meteen opnieuw op, hooguit eens per minuut per account. Verkeerde handtekening 401, onbekend adres 404.\n\n**Toegang:** Geen inlog; het geheim zit in het adres","security":[],"x-studio-auth":"url","parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","description":"Het bericht van Apple."}}}},"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"received":{"type":"boolean"}}}}}},"404":{"$ref":"#/components/responses/404"},"429":{"$ref":"#/components/responses/429"}}}},"/api/hooks/{token}":{"post":{"tags":["Server naar server"],"operationId":"post_hooks_token","summary":"Inkomende webhook van een automatisering","description":"Het adres is het geheim. Velden uit de JSON-body (één niveau diep, hooguit 50, tot 500 tekens) zijn variabelen in de acties, zoals `{{klant}}`. Een onbekend of uitgezet adres geeft 404.\n\n**Toegang:** Geen inlog; het geheim zit in het adres","security":[],"x-studio-auth":"url","parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","description":"Vrije velden."}}}},"responses":{"202":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"run":{"type":"boolean"}}}}}},"404":{"$ref":"#/components/responses/404"},"429":{"$ref":"#/components/responses/429"}}}},"/api/inbound/{token}":{"post":{"tags":["Server naar server"],"operationId":"post_inbound_token","summary":"Formulier, afspraak, belmeting of GitHub als lead of tijdlijn","description":"Met een geheim controleert Studio de handtekening: Typeform-Signature, Calendly-Webhook-Signature, X-Hub-Signature-256 (GitHub) of anders de header X-Studio-Secret. GitHub zonder geheim wordt geweigerd.\n\n**Toegang:** Geen inlog; het geheim zit in het adres","security":[],"x-studio-auth":"url","parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","description":"Het bericht van de dienst."}}}},"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"noted":{"type":"boolean"}}}}}},"404":{"$ref":"#/components/responses/404"},"429":{"$ref":"#/components/responses/429"}}}},"/api/backup/{key}":{"get":{"tags":["Server naar server"],"operationId":"get_backup_key","summary":"Back-up gelukt (ping)","description":"GET of POST, zodat `curl -fsS` in een cronregel volstaat. Met `size` in bytes ziet Studio ook een back-up die ineens veel kleiner is.\n\n**Toegang:** Geen inlog; het geheim zit in het adres","security":[],"x-studio-auth":"url","parameters":[{"name":"key","in":"path","required":true,"schema":{"type":"string"}},{"name":"size","in":"query","required":false,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true}}}}}},"404":{"$ref":"#/components/responses/404"},"429":{"$ref":"#/components/responses/429"}}},"post":{"tags":["Server naar server"],"operationId":"post_backup_key","summary":"Back-up gelukt (ping)","description":"**Toegang:** Geen inlog; het geheim zit in het adres","security":[],"x-studio-auth":"url","parameters":[{"name":"key","in":"path","required":true,"schema":{"type":"string"}},{"name":"size","in":"query","required":false,"schema":{"type":"integer"}}],"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true}}}}}},"404":{"$ref":"#/components/responses/404"},"429":{"$ref":"#/components/responses/429"}}}},"/api/titles":{"get":{"tags":["Server naar server"],"operationId":"get_titles","summary":"Goedgekeurde titels om door te voeren","description":"Voor de WordPress- of Drupal-module.\n\n**Toegang:** Terugschrijfsleutel: `Authorization: Bearer wb_…`","security":[{"writebackToken":[]}],"x-studio-auth":"writeback","responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"titles":{"type":"array","items":{"type":"object"},"description":"id, url, title, description"}}}}}},"401":{"$ref":"#/components/responses/401"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}},"post":{"tags":["Server naar server"],"operationId":"post_titles","summary":"Titels doorgevoerd","description":"**Toegang:** Terugschrijfsleutel: `Authorization: Bearer wb_…`","security":[{"writebackToken":[]}],"x-studio-auth":"writeback","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"applied":{"type":"array","items":{"type":"integer"}}},"required":["applied"]}}}},"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"applied":{"type":"integer"}}}}}},"401":{"$ref":"#/components/responses/401"},"422":{"$ref":"#/components/responses/422"},"429":{"$ref":"#/components/responses/429"}}}},"/api/errors/{key}":{"post":{"tags":["Server naar server"],"operationId":"post_errors_key","summary":"JavaScript-fout van het sitescript","description":"De sleutel is openbaar (staat in de HTML). Zonder persoonsgegevens: geen IP, geen querystrings. Antwoordt altijd 204.\n\n**Toegang:** Geen inlog","security":[],"x-studio-auth":"public","parameters":[{"name":"key","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"},"source":{"type":"string"},"line":{"type":"integer"},"col":{"type":"integer"},"stack":{"type":"string"},"page":{"type":"string"}},"required":["message"]}}}},"responses":{"204":{"description":"Leeg antwoord."}}}},"/api/vitals/{key}":{"post":{"tags":["Server naar server"],"operationId":"post_vitals_key","summary":"Web Vitals-meting van het sitescript","description":"**Toegang:** Geen inlog","security":[],"x-studio-auth":"public","parameters":[{"name":"key","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"lcp":{"type":"number"},"inp":{"type":"number"},"cls":{"type":"number"},"page":{"type":"string"},"device":{"type":"string","enum":["mobile","desktop"]}}}}}},"responses":{"204":{"description":"Leeg antwoord."}}}},"/api/forms/{key}":{"post":{"tags":["Server naar server"],"operationId":"post_forms_key","summary":"Formulier of lead-klik van het sitescript","description":"Alleen veldnamen, nooit wat er is ingevuld. Of `lead` (telefoon, email, whatsapp) voor een klik op een link.\n\n**Toegang:** Geen inlog","security":[],"x-studio-auth":"public","parameters":[{"name":"key","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"page":{"type":"string"},"form":{"type":"string"},"fields":{"type":"array","items":{"type":"string"}},"submitted":{"type":"boolean"},"lead":{"type":"string","enum":["telefoon","email","whatsapp"]},"sr":{"type":"string"}}}}}},"responses":{"204":{"description":"Leeg antwoord."}}}},"/api/pageviews/{key}":{"post":{"tags":["Server naar server"],"operationId":"post_pageviews_key","summary":"Cookieloze paginaweergave","description":"Zonder cookies of opslag; een bezoeker is één dag te herkennen aan een hash met een dagelijks wisselend zout. Bots tellen niet.\n\n**Toegang:** Geen inlog","security":[],"x-studio-auth":"public","parameters":[{"name":"key","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"page":{"type":"string"},"ref":{"type":"string","format":"uri"},"qref":{"type":"string","description":"Waarde van ?ref= of ?source=."},"utm_source":{"type":"string"},"utm_medium":{"type":"string"},"utm_campaign":{"type":"string"},"gclid":{"type":"string"},"sr":{"type":"string"}},"required":["page"]}}}},"responses":{"204":{"description":"Leeg antwoord."}}}},"/api/site-events/{token}":{"post":{"tags":["Server naar server"],"operationId":"post_site_events_token","summary":"Sitegebeurtenis ontvangen","description":"Ondertekend met het geheim van het project: X-Studio-Timestamp (Unix-tijd, hooguit 5 minuten afwijking) en X-Studio-Signature = sha256=<hex hmac_sha256(geheim, timestamp + \".\" + body)>. `data` mag Studio bewaren en tellen (per `ref`); `private` gebruikt Studio alleen tijdens de afhandeling. Met `id` telt een herhaalde gebeurtenis niet dubbel. 502 als een actie mislukte en Studio het niet zelf opnieuw probeert: probeer het dan later opnieuw.\n\n**Toegang:** Geen inlog","security":[],"x-studio-auth":"public","parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"event":{"type":"string","description":"Kleine letters, cijfers en . _ -, zoals tester.aangemeld."},"id":{"type":"string"},"data":{"type":"object"},"private":{"type":"object"}},"required":["event"]}}}},"responses":{"202":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"runs":{"type":"integer"},"duplicate":{"type":"boolean"}}}}}}}}},"/api/consent/{key}":{"post":{"tags":["Server naar server"],"operationId":"post_consent_key","summary":"Keuze in de cookiebanner","description":"Uit de Consent Mode-update die de banner aan Google doorgeeft. Eén keuze per bezoeker per dag, met dezelfde dagelijkse hash als de weergaven; een latere keuze vervangt de eerdere.\n\n**Toegang:** Geen inlog","security":[],"x-studio-auth":"public","parameters":[{"name":"key","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"a":{"type":"string","enum":["granted","denied"],"description":"analytics_storage"},"d":{"type":"string","enum":["granted","denied"],"description":"ad_storage"}}}}}},"responses":{"204":{"description":"Leeg antwoord."}}}},"/api/site-script/{key}.js":{"get":{"tags":["Server naar server"],"operationId":"get_site_script_key_js","summary":"Het sitescript","description":"Fouten, Web Vitals, formulieren, leads en cookieloze meting in één bestand. Plaats `<script src=\"…/api/site-script/<sleutel>.js\" defer></script>`.\n\n**Toegang:** Geen inlog","security":[],"x-studio-auth":"public","parameters":[{"name":"key","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Gelukt.","content":{"application/javascript":{"schema":{"type":"string"}}}}}}},"/api/chat-widget.js":{"get":{"tags":["Server naar server"],"operationId":"get_chat_widget_js","summary":"Het chatwidget","description":"Plaats `<script src=\"…/api/chat-widget.js?p=<widget-token>\" defer></script>`. Het widget toont zich alleen met de module Chat aan en vanaf een toegestaan domein.\n\n**Toegang:** Geen inlog","security":[],"x-studio-auth":"public","parameters":[{"name":"p","in":"query","required":true,"schema":{"type":"string"},"description":"Widget-token uit de instellingen van de chat."}],"responses":{"200":{"description":"Gelukt.","content":{"application/javascript":{"schema":{"type":"string"}}}}}}},"/api/chat-widget-home.js":{"get":{"tags":["Server naar server"],"operationId":"get_chat_widget_home_js","summary":"Het startscherm van het chatwidget","description":"Laadt het widget zelf als het project zelfhulp, eigen links of andere contactmogelijkheden gebruikt.\n\n**Toegang:** Geen inlog","security":[],"x-studio-auth":"public","responses":{"200":{"description":"Gelukt.","content":{"application/javascript":{"schema":{"type":"string"}}}}}}},"/api/chat-widget/{token}/beeld/{kind}":{"get":{"tags":["Server naar server"],"operationId":"get_chat_widget_token_beeld_kind","summary":"Logo of teamfoto voor het venster","description":"kind: logo (als de kop het logo toont) of team-<id> (alleen bij \"voornaam met foto\" en alleen van het team van dat project). Anders 404.\n\n**Toegang:** Geen inlog","security":[],"x-studio-auth":"public","parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string"}},{"name":"kind","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Gelukt.","content":{"application/octet-stream":{"schema":{"type":"string","format":"binary"}}}}}}},"/api/chat-widget/{token}":{"post":{"tags":["Server naar server"],"operationId":"post_chat_widget_token","summary":"Het chatwidget: berichten van de bezoeker","description":"Voor het widget zelf. JSON als `text/plain`, zodat er geen preflight is. Alleen met een `Origin` van een domein van het project (of een toegevoegd adres); anders 403 `origin_not_allowed`. Onbekend token of geen `Origin`: 404. `visitor` is een willekeurig id uit de browser (20–64 tekens); Studio bewaart alleen een HMAC daarvan en geen IP-adres. Het veld `website` is een honeypot. Hooguit 15 berichten per minuut per bezoeker en 10 nieuwe gesprekken per uur per IP.\n\n**Toegang:** Geen inlog","security":[],"x-studio-auth":"public","parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"text/plain":{"schema":{"type":"object","properties":{"action":{"type":"string","enum":["hallo","poll","stuur","gegevens","beoordeel","transcript","nieuw","vergeet","geschiedenis","gesprek","kies","koppel","bevestig","identificeer","uitloggen"]},"visitor":{"type":"string"},"since":{"type":"integer","description":"Alleen berichten na dit id."},"body":{"type":"string","description":"Bij stuur; hooguit 2.000 tekens."},"name":{"type":"string"},"email":{"type":"string","format":"email"},"page":{"type":"string","format":"uri"},"title":{"type":"string"},"typing":{"type":"boolean"},"rating":{"type":"integer","description":"Bij beoordeel: 1–5, alleen na afsluiten."},"website":{"type":"string","description":"Leeg laten."},"topic":{"type":"string","description":"Bij een nieuw gesprek: een onderwerp uit de instellingen; wordt een label."},"consent":{"type":"boolean","description":"Akkoord met de privacyverklaring, als het formulier daarom vraagt."},"seen":{"type":"integer","description":"Bij poll: het laatste bericht-id dat de bezoeker in het open, zichtbare venster zag; voor \"Gelezen\" in de inbox. Gaat nooit terug."},"route":{"type":"array","items":{"type":"object"},"description":"Bij het eerste stuur: de pagina's die de bezoeker in het laatste half uur bekeek (p = pad, t = titel, at = tijd in ms), hooguit tien; tot dan bleven ze in zijn browser."},"proactive":{"type":"string","description":"De tekst van het proactieve bericht waarop de bezoeker antwoordt; alleen als die in de regels staat."},"id":{"type":"integer","description":"Bij gesprek: een eerder gesprek van dezelfde bezoeker. Bij kies: het bericht met de knoppen."},"label":{"type":"string","description":"Bij kies: een van de knoppen onder dat bericht; één keer per bericht, en gaat als bericht van de bezoeker."},"code":{"type":"string","description":"Bij bevestig: de acht cijfers uit de mail na koppel, alleen geldig in dezelfde browser (visitor), een kwartier en één keer; na vijf foute pogingen vervalt hij. Daarna hangt deze browser aan het adres. Tot 11-10-2026 een link die de aanvrager koppelde aan wie klikte."},"user_id":{"type":"string","description":"Bij identificeer: het id van de ingelogde gebruiker op de site."},"signature":{"type":"string","description":"Bij identificeer: HMAC-SHA256 van user_id met de sleutel uit de chatinstellingen, op de server van de site berekend."},"email_signature":{"type":"string","description":"Bij identificeer: HMAC-SHA256 van \"user_id|adres\" (adres in kleine letters). Alleen dan telt `email` als bevestigd. `uitloggen` maakt de koppeling van deze browser ongedaan."},"file":{"type":"string","format":"binary","description":"Bij stuur als multipart (payload = de JSON hierboven): afbeelding of pdf, hooguit 10 MB, tien per uur."},"selfhelp":{"type":"object","description":"Bij een nieuw gesprek: articles (ids die de bezoeker las), searched, unhelpful (id van een artikel met \"Nee, hielp niet\"). Alleen gepubliceerde artikelen van dit project tellen; het team ziet het als notitie."}},"required":["action","visitor"]}}}},"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"enabled":{"type":"boolean"},"config":{"type":"object","description":"name, color, position, widget (de instellingen van het venster, teksten in beide talen, contactmogelijkheden als link), greeting, buttons (onder de groet), offline_message, prechat, proactive, files, known, status, privacy (null bij white-label zonder eigen verklaring), identify"},"status":{"type":"string","enum":["online","open","gesloten"]},"conversation":{"type":["object","null"],"description":"status, name, email, rated, ticket, agent_typing, read (tot welk bericht het team las), files (mag de bezoeker bijlagen sturen), agent (name, initials, photo, of null), queue (plek in de rij zolang het team nog niet antwoordde)"},"messages":{"type":"array","items":{"type":"object"},"description":"id, from, body, at, name, files, buttons, choice, faq (id, title van een gepubliceerd artikel)"},"history":{"type":"array","items":{"type":"object"},"description":"Bij geschiedenis: id, at, last_at, status, ticket, preview."},"error":{"type":"string","description":"Bij 403: files_not_allowed als het team bijlagen niet toestond, closed als het buiten openingstijden alleen zelfhulp is. Bij 422: validation, email, unverified (transcript: eerst het adres bevestigen met koppel/bevestig), code, file (met detail) of prechat (met field: name, email, topic of consent)."}}}}}}}}},"/api/chat-file/{id}":{"get":{"tags":["Server naar server"],"operationId":"get_chat_file_id","summary":"Bijlage uit de chat","description":"Alleen met de ondertekende URL uit `files` (`expires` en `signature`), een half uur geldig; anders 403. Afbeeldingen inline, een pdf als download, altijd met `nosniff`.\n\n**Toegang:** Geen inlog","security":[],"x-studio-auth":"public","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Gelukt.","content":{"application/octet-stream":{"schema":{"type":"string","format":"binary"}}}}}}},"/api/chat-widget/{token}/faq":{"post":{"tags":["Server naar server"],"operationId":"post_chat_widget_token_faq","summary":"Het chatwidget: veelgestelde vragen","description":"Voor het widget zelf, met dezelfde herkomstregels als `chat-widget/{token}`. Alleen gepubliceerde artikelen van dat project; taal eerst die van de pagina, anders alles. Met de module of het widget uit `enabled: false`. Hooguit 60 verzoeken per minuut per bezoeker.\n\n**Toegang:** Geen inlog","security":[],"x-studio-auth":"public","parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"text/plain":{"schema":{"type":"object","properties":{"action":{"type":"string","enum":["lijst","zoek","categorie","artikel","feedback"]},"q":{"type":"string","description":"Bij zoek; hooguit 120 tekens. Zonder resultaat bewaart Studio de term zonder bezoeker, 90 dagen (uit te zetten)."},"lang":{"type":"string","enum":["nl","en"]},"id":{"type":"integer","description":"Bij artikel en feedback."},"name":{"type":"string","description":"Bij categorie."},"helpful":{"type":"boolean","description":"Bij feedback: \"Hielp dit?\". Eén stem per artikel per dag per IP-hash."}},"required":["action"]}}}},"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"enabled":{"type":"boolean"},"total":{"type":"integer"},"results":{"type":"array","items":{"type":"object"},"description":"id, title, category, excerpt (bij lijst eerst de uitgelichte)"},"categories":{"type":"array","items":{"type":"object"},"description":"name, count (bij lijst)"},"article":{"type":"object","description":"id, title, category, html, updated_at"}}}}}}}}},"/api/optin/{formKey}":{"post":{"tags":["Server naar server"],"operationId":"post_optin_formKey","summary":"Aanmelden via een formulier op de site van de klant","description":"JSON of een gewoon HTML-formulier. Stuurt een bevestigingsmail (dubbele opt-in). Het veld `website` is een honeypot. Hooguit 5 per minuut per bezoeker.\n\n**Toegang:** Geen inlog","security":[],"x-studio-auth":"public","parameters":[{"name":"formKey","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/x-www-form-urlencoded":{"schema":{"type":"object","properties":{"email":{"type":"string","format":"email"},"naam":{"type":"string"},"toestemming":{"type":"string","description":"1, on, true of ja."},"taal":{"type":"string","enum":["nl","en"],"description":"Taal van de aanmelding; zonder die van het formulier."},"website":{"type":"string","description":"Leeg laten."}},"required":["email","toestemming"]}},"application/json":{"schema":{"type":"object","properties":{"email":{"type":"string","format":"email"},"naam":{"type":"string"},"toestemming":{"type":"string","description":"1, on, true of ja."},"taal":{"type":"string","enum":["nl","en"],"description":"Taal van de aanmelding; zonder die van het formulier."},"website":{"type":"string","description":"Leeg laten."}},"required":["email","toestemming"]}}}},"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"message":{"type":"string"},"error":{"type":"string"}}}}}}}}},"/api/shared":{"get":{"tags":["Openbaar"],"operationId":"get_shared","summary":"Gedeeld rapport","description":"**Toegang:** Geen inlog; het geheim zit in het adres","security":[],"x-studio-auth":"url","parameters":[{"name":"token","in":"query","required":true,"schema":{"type":"string"},"description":"Uit de deellink."}],"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"report":{"type":"object"},"project":{"type":"string"},"shared":{"type":"boolean"},"expires_at":{"type":"string","format":"date-time"},"branding":{"type":"object"}}}}}},"404":{"$ref":"#/components/responses/404"},"429":{"$ref":"#/components/responses/429"}}}},"/api/status":{"get":{"tags":["Openbaar"],"operationId":"get_status","summary":"Openbare statuspagina van een project","description":"**Toegang:** Geen inlog; het geheim zit in het adres","security":[],"x-studio-auth":"url","parameters":[{"name":"token","in":"query","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"name":{"type":"string"},"monitors":{"type":"array","items":{"type":"object"},"description":"name, state, uptime_30d, incidents"},"maintenance":{"type":"array","items":{"type":"object"}},"branding":{"type":"object"},"checked_at":{"type":"string","format":"date-time"}}}}}},"404":{"$ref":"#/components/responses/404"},"429":{"$ref":"#/components/responses/429"}}}},"/api/public-stats":{"get":{"tags":["Openbaar"],"operationId":"get_public_stats","summary":"Totalen over alle workspaces","description":"Voor de marketingsite; niets herleidbaar naar een klant. Een uur gecachet, CORS open.\n\n**Toegang:** Geen inlog","security":[],"x-studio-auth":"public","responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"projects":{"type":"integer"},"pages_crawled":{"type":"integer"},"advice_given":{"type":"integer"},"advice_done":{"type":"integer"},"uptime_checks_30d":{"type":"integer"},"incidents_30d":{"type":"integer"},"updated_at":{"type":"string","format":"date-time"}}}}}}}}},"/api/feed/{token}.csv":{"get":{"tags":["Openbaar"],"operationId":"get_feed_token_csv","summary":"Datafeed als CSV","description":"Per dag: datum, gebruikers, sessies, paginaweergaven, conversies, klikken, vertoningen en positie in Google. Voor =IMPORTDATA in Google Sheets.\n\n**Toegang:** Geen inlog; het geheim zit in het adres","security":[],"x-studio-auth":"url","parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string"}},{"name":"days","in":"query","required":false,"schema":{"type":"integer"},"description":"7 tot 480; standaard 90."}],"responses":{"200":{"description":"Gelukt.","content":{"text/csv":{"schema":{"type":"string"}}}},"404":{"$ref":"#/components/responses/404"},"429":{"$ref":"#/components/responses/429"}}}},"/api/openapi.json":{"get":{"tags":["Openbaar"],"operationId":"get_openapi_json","summary":"Deze referentie als OpenAPI 3.1","description":"**Toegang:** Geen inlog","security":[],"x-studio-auth":"public","parameters":[{"name":"lang","in":"query","required":false,"schema":{"type":"string","enum":["nl","en"]},"description":"Standaard nl."}],"responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true}}}}}}}}},"/api/ses/sns":{"post":{"tags":["Intern"],"operationId":"post_ses_sns","summary":"Amazon SES via SNS (gedeeld account)","description":"Bounces, klachten en aflevering. Alleen berichten met een geldige SNS-handtekening van het ingestelde topic.\n\n**Toegang:** Ondertekend door de afzender","security":[],"x-studio-auth":"signature","responses":{"200":{"description":"Leeg antwoord."}}}},"/api/ses/sns/{token}":{"post":{"tags":["Intern"],"operationId":"post_ses_sns_token","summary":"Amazon SES via SNS (eigen account van een klant)","description":"Het token wijst het verzendaccount aan, en daarmee het topic. Telt alleen voor verzendingen van dat account.\n\n**Toegang:** Ondertekend door de afzender","security":[],"x-studio-auth":"signature","parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Leeg antwoord."}}}},"/api/resend/webhook":{"post":{"tags":["Intern"],"operationId":"post_resend_webhook","summary":"Resend-meldingen (gedeeld account)","description":"Met een geldige Svix-handtekening; tijdstempels van meer dan vijf minuten oud worden geweigerd.\n\n**Toegang:** Ondertekend door de afzender","security":[],"x-studio-auth":"signature","responses":{"200":{"description":"Leeg antwoord."}}}},"/api/resend/webhook/{token}":{"post":{"tags":["Intern"],"operationId":"post_resend_webhook_token","summary":"Resend-meldingen (eigen account van een klant)","description":"**Toegang:** Ondertekend door de afzender","security":[],"x-studio-auth":"signature","parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Leeg antwoord."}}}},"/api/support/inbound":{"post":{"tags":["Intern"],"operationId":"post_support_inbound","summary":"Mail naar support (Resend Inbound)","description":"Mail aan <token>@SUPPORT_INBOUND_DOMAIN wordt een ticket, of een antwoord als het onderwerp [#nummer] bevat. Alleen van bekende afzenders van die werkruimte, met de module en mail naar support aan. Met een geldige Svix-handtekening; anders 403. Een genegeerde mail geeft ook 200, met de reden.\n\n**Toegang:** Ondertekend door de afzender","security":[],"x-studio-auth":"signature","responses":{"200":{"description":"Gelukt.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"status":{"type":"string","enum":["nieuw","antwoord","genegeerd"]},"ticket_id":{"type":"integer"},"reason":{"type":"string"}}}}}}}}},"/api/slack/interactions/{workspace}":{"post":{"tags":["Intern"],"operationId":"post_slack_interactions_workspace","summary":"Knoppen in Slack-berichten","description":"Ondertekend met het signing secret van de Slack-app.\n\n**Toegang:** Ondertekend door de afzender","security":[],"x-studio-auth":"signature","parameters":[{"name":"workspace","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Leeg antwoord."}}}},"/api/mollie/webhook":{"post":{"tags":["Intern"],"operationId":"post_mollie_webhook","summary":"Betaalstatus van Mollie","description":"Mollie stuurt alleen het betaal-id; Studio haalt de status zelf op bij Mollie, ook terugbetalingen en storneringen. 200 bij een onbekend id, 503 als ophalen bij Mollie mislukt (Mollie probeert het dan opnieuw).\n\n**Toegang:** Geen inlog","security":[],"x-studio-auth":"public","responses":{"200":{"description":"Leeg antwoord."}}}}},"components":{"securitySchemes":{"apiKey":{"type":"http","scheme":"bearer","description":"Persoonlijke API-sleutel (studio_…) uit Instellingen → API-sleutels."},"session":{"type":"apiKey","in":"cookie","name":"studio_session","description":"Sessiecookie van de app."},"deployToken":{"type":"http","scheme":"bearer","description":"Deploysleutel (Tijdlijn → deploysleutel)."},"conversionToken":{"type":"http","scheme":"bearer","description":"Conversiesleutel van een bron."},"writebackToken":{"type":"http","scheme":"bearer","description":"Terugschrijfsleutel (wb_…) van een project."}},"schemas":{"Error":{"type":"object","required":["ok","error"],"properties":{"ok":{"const":false},"error":{"type":"string"},"detail":{"type":"string"},"fields":{"type":"object","additionalProperties":{"type":"string"}}}}},"responses":{"401":{"description":"Geen of ongeldige sleutel of sessie (`unauthorized`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Het plan staat dit niet toe (`plan_limit`, `plan_feature`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Geen recht (`forbidden`, `token_read_only`, `token_not_allowed`, `viewing_as_readonly`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Bestaat niet of niet zichtbaar voor deze gebruiker (`not_found`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Conflict met wat er al is.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"410":{"description":"Verlopen of al gebruikt.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"422":{"description":"Ongeldige invoer (`validation`, `unknown_action`); `detail` en `fields` zeggen wat.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Te veel verzoeken (`too_many_requests`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Een externe dienst faalde.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Nog geen werkende koppeling (`no_connections`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}