Basics
Everything lives under https://instnt.studio/api/. Requests and responses are UTF-8 JSON unless stated otherwise below (CSV, PDF, JavaScript). The app uses the same API; what the app can do, the API can do, within the user's permissions.
Every route also works with .php appended (/api/events.php). That keeps addresses from the old PHP API working; use the short form yourself.
Authenticating with an API key
Create a key under Settings → API keys and send it as Authorization: Bearer studio_…. Studio shows the key once and stores only a hash. A key carries the permissions of whoever created it, plus a scope: read (GET only), read and write (POST too) or MCP (/api/mcp only). The number of keys depends on the plan.
A few routes are for people and never accept a key: tokens, two-factor, changing the password, deleting the workspace, viewing as a client, logging out and instnt's admin. They return 403 token_not_allowed. Writing with a read key returns 403 token_read_only. GET /api/me only looks at the session and returns user: null for a key.
Workspace and permissions
A user belongs to exactly one workspace, so a key always works in that workspace; there is no header to choose another. The team has three roles: owner and member can manage, viewer can only read. A client only sees the projects they were given, per module (Overview, Website, Search, Product, Advice, Ads) with a level. When a client asks for a project or module that isn't theirs, Studio answers 404 rather than 403: a client doesn't need to know it exists.
An owner viewing as a client cannot change anything (403 viewing_as_readonly).
Reading and writing
Most topics have one address: GET to read, with parameters in the query string (often project_id), and POST with a JSON body to write. The body has an action field saying what to do, for example {"action": "status", "id": 12, "status": "done"}. Unknown actions return 422 unknown_action.
Long-running work (crawl, report, refreshing advice, cookie scan) runs in the background: the answer is 202 with a task_id, and GET /api/task?id=… returns queued, running, done or failed.
Lists usually have a fixed cap (for example 500 recommendations or 300 pages). Paging only exists where noted below, via page: contacts (50 per page), the automation log (25) and the contacts in a funnel.
Responses and errors
A successful response has "ok": true with the data next to it. An error has "ok": false, a fixed code in error, sometimes a readable explanation in detail (Dutch) and, for forms, a message per field in fields.
Common codes: 401 unauthorized (missing or invalid key), 402 plan_limit or plan_feature (the plan doesn't allow it), 403 forbidden, 404 not_found, 410 (expired link or invitation), 422 validation or unknown_action, 429 too_many_requests and 502 when an external service (Google, GitHub) fails.
Rate limits
Per API key 120 requests per minute. Public addresses have their own limits: login 5 per minute per email address and 20 per IP, share links and status pages 30 per minute per IP, server-to-server events 600 per minute per IP, site script measurements 60 per minute per visitor, incoming automation webhooks 30 per minute per address, site events 120 per minute per address.
Other credentials
Besides the personal API key there are single-purpose credentials: a deploy key (POST /api/deploys and /api/components), a conversion key per source (POST /api/events), a write-back key for the WordPress or Drupal module (/api/titles) and addresses with the secret in them (incoming webhooks, backup pings, data feeds). They are described with the routes.
This reference is also available as OpenAPI 3.1: GET /api/openapi.json (Dutch) or ?lang=en.
Example: Home Assistant
GET /api/tech-overview returns the state of every site in one response. Create a key with the read scope and put this in configuration.yaml:
rest:
- resource: https://instnt.studio/api/tech-overview
headers:
Authorization: !secret studio_token
scan_interval: 300
sensor:
- name: Studio sites offline
value_template: "{{ value_json.kpis.down }}"
- name: Studio certificaten binnen 14 dagen
value_template: "{{ value_json.kpis.certs_14d }}"
- name: Studio projecten met kritiek of hoog lek
value_template: "{{ value_json.kpis.vulns_critical_high }}"
- name: Studio bronnen met aandacht
value_template: "{{ value_json.kpis.sources_error }}"
- name: Studio app-downloads 7 dagen
value_template: "{{ value_json.kpis.app_downloads_7d }}"
In secrets.yaml: studio_token: "Bearer studio_…". Note that certs_14d, vulns_critical_high and php_outdated count projects, not certificates or vulnerabilities; vulns_open does count vulnerabilities.
Account and sign-in
Sign-in, invitations, passwords, two-factor and personal keys. Most of these are for people, not scripts.
Who is signed in
With a session: the user, workspace, role, features, plan and pending approvals. Without one: user: null and what the login screen needs. Ignores API keys.
- Access
- No sign-in
Response
user | ?object | id, email, name, is_admin, role, can_manage, is_client, two_factor |
workspaces | object[] | id, slug, name, role |
features | object | |
modules | object | Per module whether it is on for the workspace (plan and setting). |
plan | ?object | key, label, limits, usage, trial_ends_at, active, cancel_from, data_delete_on |
approvals_open | int | |
terms | ?object | alleen voor de eigenaar / owner only: version, required, deadline, blocking |
start_page | ?string | |
viewed_by | ?object | |
google_connect | bool | |
setup_required | bool | |
google_login | bool | |
signup_open | bool | |
brand | ?object | |
Sign in with email and password
Sets the session cookie. With two-factor enabled, a challenge comes back first for /api/login/two-factor. The iOS and macOS app sends client: app and gets a token in the response instead of a cookie; it is sent as Authorization: Bearer studioapp_… and is listed under Account → Devices.
- Access
- No sign-in
Body
email* | email | |
password* | string | |
client | app | The app only. |
device_name | string | Name under Account → Devices; without one "iPhone van <first name>". |
device_model | string | iPhone, iPad or Mac. |
Response
two_factor | bool | |
challenge | string | |
token | string | Only with client: app, shown once. |
device_name | string | |
POST/api/login/two-factorSecond step: authenticator code or recovery code
The challenge expires after five wrong codes. When the sign-in started in the app, a token comes back instead of a cookie.
- Access
- No sign-in
Body
challenge | string | From the /api/login response; after Google it is in a cookie. |
code* | string | |
Response
token | ?string | |
device_name | ?string | |
Start Google sign-in
Redirects the browser to Google (OpenID Connect with PKCE). Existing users only. 404 when Google sign-in isn't configured. The app starts with ?client=app&code_challenge=… (S256, at least 43 characters) and returns to instntstudio://login?code=…, ?challenge=… (two-factor) or ?error=….
- Access
- No sign-in
- Status
- 302
App: exchange the code from after Google
Single use and valid for two minutes; a wrong verifier also uses up the code.
- Access
- No sign-in
Body
code* | string | |
code_verifier* | string | Whose S256 hash the app sent at the start. |
Response
token | string | |
device_name | string | |
GET/api/login/google/callbackReturn from Google
Google sends the browser here. A small page sets the session and returns to the app.
- Access
- No sign-in
Sign out
Ends the session and clears the cookie.
- Access
- App session only, not with an API key
Create the first user
Only works while there are no users yet (installation); afterwards 403 already_installed.
- Access
- No sign-in
Body
email* | email | |
name | string | |
password* | string | At least 10 characters. |
Sign up as an agency (trial)
Sends a confirmation email. Always returns sent: true, also when the address exists. 404 while sign-up is closed.
- Access
- No sign-in
Body
email* | email | |
name* | string | |
agency* | string | |
password* | string | At least 10 characters. |
partner | string | Partner code. |
terms* | bool | Acceptance of the terms and data processing agreement; version and time are recorded. |
Confirm a sign-up
Creates the user and workspace and starts a session. 410 signup_expired after 24 hours, 409 exists when the address already has an account.
- Access
- No sign-in
View an invitation
- Access
- No sign-in
Response
email | email | |
workspace | string | |
project | ?string | |
existing_user | bool | |
Accept an invitation
New user: choose a name and password. Existing user: confirm with your own password, or without when already signed in as that user. You can belong to several workspaces. Starts a session in the inviting workspace.
- Access
- No sign-in
Body
token* | string | |
password* | string | |
name | string | |
Request a reset link
Always answers the same, so it doesn't reveal which addresses have an account. The link works for 60 minutes.
- Access
- No sign-in
Set a new password
Ends all other sessions and starts a new one.
- Access
- No sign-in
Body
token* | string | |
password* | string | At least 10 characters, at most 72 bytes, not from a known breach. |
Change password
Other sessions end; this one stays valid.
- Access
- App session only, not with an API key
- Who
- The signed-in user.
Body
current* | string | |
password* | string | At least 10 characters, at most 72 bytes, not from a known breach. |
Manage two-factor authentication
- Access
- App session only, not with an API key
- Who
- The signed-in user.
Actions (action)
statusResponse: enabled, required, enforced, has_password, recovery_codes_left.
setupNew secret; inactive until confirm. Response: secret, uri.
confirmcode*Enables two-factor and ends other sessions. Response: recovery_codes.
disablepassword, code*Not possible when two-factor is mandatory.
password string · Required when you have a password.
recovery_codespassword, codeResponse: recovery_codes.
password string · Required when you have a password.code string · Required without a password.
Your API keys
- Access
- App session only, not with an API key
- Who
- The signed-in user.
Response
tokens | object[] | id, name, scope, last_used_at, created_at, archived_at, workspace_id, workspace |
Create or revoke an API key
- Access
- App session only, not with an API key
- Who
- The signed-in user.
Devices for push notifications
- Access
- Session or API key (read or write)
- Who
- The signed-in user.
Response
devices | object[] | id, environment, created_at, last_sent_at |
Register or remove a push device
- Access
- Session or API key with write access
- Who
- The signed-in user.
Actions (action)
registertoken*, environmenttoken string · APNs device token, hex.environment sandbox | production
removetoken*
View as a client
While viewing, nothing can be changed.
- Access
- App session only, not with an API key
- Who
- Workspace owner only.
Actions (action)
startuser_id*user_id int · A client of your own workspace.
stop
Your own account
- Access
- App session only, not with an API key
- Who
- The signed-in user.
Response
profile | object | name, email, timezone, avatar, has_password, google, created_at |
pending_email | ?object | email, expires_at |
reauth | password | code | google | none | How you confirm your identity for a sensitive action. |
notify | object[] | key, label, on |
quiet_hours | ?object | Quiet hours for push: from and to, HH:MM in your own time zone. |
sessions | object[] | key, kind (browser|app), device, network, via, created_at, last_used_at, last_used_label, current |
workspaces | object[] | id, name, role, suspended_at |
delete_blockers | string[] | Workspaces you own; while there are any, your account can't be deleted. |
timezones | string[] | |
Change your account
- Access
- App session only, not with an API key
- Who
- The signed-in user.
Actions (action)
profilename*, timezonetimezone ?string · IANA name, e.g. Europe/Amsterdam. Used for times in emails and lists.
avataravatar*Multipart form. Response: avatar.
avatar file · JPG, PNG, WebP or GIF up to 3 MB; becomes a 160 × 160 WebP without metadata.
avatar_deleteemailemail*, password, codeSends a link to the new address; until it is opened, the old one stays. Response: mailed, pending_email.
password string · Your password; without one (Google only) a code from the app, or sign in with Google again first.
email_cancelnotifyprefs*Response: prefs.
prefs object · Per kind on or off: alerts, anomalies, digest, automations. Invoices and security can't be turned off.
quiet_hoursfrom, toPush notifications then arrive silently. Response: quiet_hours.
from string · HH:MM; without from and to, quiet hours are off.
session_revokekey*For an app, also the push notifications to that device. Response: sessions.
sessions_revoke_othersResponse: revoked, sessions.
reauthpassword, codeConfirms your identity for ten minutes.
password string · Your password; without one (Google only) a code from the app, or sign in with Google again first.
leaveworkspace_id*Not as owner: transfer ownership first.
delete_accountpassword, codeAnonymises your account and signs you out. Not while you own a workspace.
password string · Your password; without one (Google only) a code from the app, or sign in with Google again first.
Confirm a new email address
The link from the email to the new address (24 hours). The old address gets an email with a link to undo.
- Access
- No sign-in; the secret is in the address
Undo an email change
The link from the email to the old address (24 hours). Restores the old address, ends all sessions and revokes API keys.
- Access
- No sign-in; the secret is in the address
Projects and overview
Projects, the cross-client overviews, dashboards, goals, the timeline and hours.
Projects with source counts
- Access
- Session or API key (read or write)
- Who
- Everyone in the workspace; a client only sees their own projects.
Response
projects | object[] | 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 | object | |
Example: Response
{
"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": {}
}
Create, edit and organise projects
- Access
- Session or API key with write access
- Who
- Owner or member; viewers and clients get 403.
Everything at a glance (menu bar and widgets)
Small enough to poll every minute. live is null when Google is unreachable.
- Access
- Session or API key (read or write)
- Who
- Everyone in the workspace; a client only sees their own projects.
Response
projects | object[] | id, name, monitored, down, uptime_30d, live, visitors_today, visitors_yesterday, leads_today, open_advice, open_questions |
totals | object | sites_total, sites_up, uptime_30d, visitors_today, visitors_yesterday, leads_today, open_advice, last_deploy, approvals |
live | ?object[] | project, live |
live_total | ?int | |
down | object[] | project, url, since |
open_questions | ?int | |
new_advice | int | |
proposals | object[] | |
studio | url | |
POST/api/extension/connectCreate a key for the browser extension
A key with scope extension: it may only use /api/extension/*. Studio hands it to the extension through the page; it then appears under API keys, where it can be revoked.
- Access
- App session only, not with an API key
- Who
- The signed-in user.
Projects with their domains (extension)
Registrable domains per project whose website you may view. The extension leaves your own visits out there, if you turn that on.
- Access
- Session or API key (read or write)
- Who
- Everyone in the workspace; a client only sees their own projects.
Response
projects | object[] | id, name, domains |
studio | url | |
The project for an address, with figures (extension)
- Access
- Session or API key (read or write)
- Who
- Everyone in the workspace; a client only sees their own projects.
Response
project | ?object | id, name, link |
visitors_today | ?int | |
visitors_yesterday | ?int | |
uptime | object | monitored, down, uptime_30d |
security_score | ?object | score, previous |
open_advice | ?int | |
last_deploy | ?object | title, at |
refs_today | object[] | ref, visitors |
Who follows a post (extension)
- Access
- Session or API key (read or write)
- Who
- Everyone in the workspace; a client only sees their own projects.
Query parameters
url* | url | Link to a post on Reddit, Hacker News, Bluesky or Mastodon. |
Response
platform | string | |
followed | object[] | id, project (id, name), ref, score, comments, last_checked_at, last_error |
projects | object[] | id, name; waar je hem kunt volgen |
Send the figures of a post you are viewing to Studio (extension)
For Reddit, which refuses servers: the extension reads score and comments from the page you have open yourself, after a click.
- Access
- Session or API key with write access
- Who
- Anyone who may manage the project website.
Versions and vulnerabilities across all projects
PHP, web server, database, operating system and CMS per project (21-10-2026), best source first: the site itself (plugin, module, package), then headers, then Plesk. With the status from endoflife.date: ok, update (a newer release exists in the same line), eol (no more security updates) or onbekend. With cve or product + below you see which projects a vulnerability affects; certain is false when only 8.3 is known (Plesk).
- Access
- Session or API key (read or write)
- Who
- Team only (owner, member or viewer); clients get 403.
Query parameters
cve | string | A CVE, e.g. CVE-2026-1234: vulnerabilities Studio already found plus the affected versions from the NVD. |
product | php | nginx | apache | litespeed | mysql | mariadb | postgresql | wordpress | drupal | |
below | string | |
from | string | |
Response
projects | object[] | 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 | object | |
checked_at | ?string | |
lookup | object | cve, summary, severity, ranges, projects (project_id, project, product, version, certain, fixed_in, resolved), source nvd|studio|onbekend |
Check versions now
- Access
- Session or API key with write access
- Who
- Owner or member.
Technical overview across all projects
Per project a score with what needs attention: downtime, certificate, domain, vulnerabilities, PHP, Web Vitals, headers, backups and JavaScript errors. See the Home Assistant example above.
- Access
- Session or API key (read or write)
- Who
- Team only (owner, member or viewer); clients get 403.
Response
kpis | object | 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 | object[] | bronnen met status error, stale of unknown, met project_name (zie GET /api/inventory) |
projects | object[] | 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 | object[] | project_id, project, connect, downloads_total, downloads_7d, downloads_30d, downloads_prev_30d, crashes_7d, rating, reviews, version |
Example: Response
{
"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": []
}
Source catalogue: recommended and what is needed
For the catalogue under Sources. recommended: per kind the projects where Studio saw the service on the site (What runs) without a connection. capabilities: per kind the parts with the minimal rights needed. The state per source is in GET /api/inventory.
- Access
- Session or API key (read or write)
- Who
- Team only (owner, member or viewer); clients get 403.
Response
recommended | object | soort → object[]: project_id, project, host, label |
capabilities | object | soort → object[]: key, label, needs, why, write |
Downloads of a project’s app
From the App Store Connect sales reports that Studio keeps, completed with App Analytics: first-time downloads per day (365 days), per month (24) and per year, the total since launch, countries and the comparison with last year. For a day covered by App Analytics that value counts, as in App Store Connect; analytics_differs signals that the sales report says otherwise (often a missing vendor number). acquisition is the App Store Connect overview by date: impressions (including product pages), product page views, first-time downloads, redownloads, updates, conversion (downloads ÷ unique impressions), sources, and sessions and crashes (opt-in only), for the last day, 7 and 30 days. Redownloads and updates are separate. null means unknown, not zero. Requires the Product module.
- Access
- Session or API key (read or write)
- Who
- Everyone in the workspace; a client only sees their own projects.
Response
apps | object[] | 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: Response
{
"ok": true,
"apps": [
{
"app_id": "6818309309",
"name": "Kenteken Spel",
"total": {
"downloads": 412,
"redownloads": 37,
"updates": 220,
"complete": true
},
"d7": 58,
"d30": 190,
"prev30": 164
}
]
}
GET/api/app-downloads/totalDownloads of all apps combined
The top level: all apps of all Apple accounts in the workspace, including apps not linked to a project.
- Access
- Session or API key (read or write)
- Who
- Team only (owner, member or viewer); clients get 403.
Query parameters
include_archived | bool | Also count archived apps; by default per the workspace setting. |
Response
apps | int | |
total | ?int | |
d7 | ?int | |
d30 | ?int | |
prev30 | ?int | |
archived_excluded | int | |
include_archived | bool | |
Overview of one project: what needs attention and the key figures for its type
At most six key figures, picked by project type (webshop, SaaS, local, B2B, content); with an app the last two become downloads and rating. A figure without a source has missing: true and connect naming what to link. What the viewer may not see per module is left out; revenue and ROAS only for the team or a client who may approve the overview. Downloads are a count and follow the Product module. Without a chosen type, suggested holds a proposal; Studio never saves it by itself.
- Access
- Session or API key (read or write)
- Who
- Everyone in the workspace; a client only sees their own projects.
Query parameters
project_id* | int | |
days | 7 | 28 | 90 | Defaults to 28. |
Response
type | ?string | |
suggested | ?object | type, reason |
has_app | bool | |
days | int | |
types | object | |
can_manage | bool | |
attention | object | items (key, tone, text, tab), actions (id, title), checked_at |
kpis | object[] | 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 | object | visitors, leads, clicks — elk null of een reeks (day, value) met elke dag van de periode |
funnel | ?object[] | label, value — bezoeken, formulier begonnen en verstuurd, leads; alleen stappen met gegevens |
Example: Response
{
"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"
}
}
]
}
Work board: recommendations across clients and workload
- Access
- Session or API key (read or write)
- Who
- Team only (owner, member or viewer); clients get 403.
Query parameters
assignee | string | me or a user id. |
Response
columns | object | open, planned, done |
workload | object[] | project_id, name, open, planned, overdue, done_30 |
team | object[] | |
me | int | |
today | date | |
health | object[] | |
Project list: one row per project
The team start page: per project status (ok, warn, bad) with what needs attention, uptime, tags, clients, visitors and the result that fits the project type, the app and the latest report. The same figures as Techniek and the project overview.
- Access
- Session or API key (read or write)
- Who
- Team only (owner, member or viewer); clients get 403.
Query parameters
days | 7 | 28 | 90 | Defaults to 28. |
Response
projects | object[] | 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 | object | projects, attention, visitors, downloads_7d, open_advice |
unassigned_sources | int | |
templates | object | |
days | int | |
Trend across all projects
Visitors, conversions (GA4 key events plus leads from the site script) and revenue (paid minus refunded, plus shop revenue) per day across all projects, with the total, the previous period and the split per project. A metric without any source is null.
- Access
- Session or API key (read or write)
- Who
- Team only (owner, member or viewer); clients get 403.
Query parameters
days | 7 | 28 | 90 | Defaults to 28. |
Response
days | int | |
metrics | object | visitors, conversions, revenue — elk null of { unit, total, previous, series (day, value), by_project (id, name, color, value) } |
Benchmarks: a project next to similar projects
Median, 25th and 75th percentile and the number of projects per metric, plus this project's value and position (better_than of others). Computed nightly. Figures only with at least 5 projects in the group (enough); shared across workspaces also from at least 3 workspaces, and only when your own workspace shares. Never names or values of other projects. Without project_id: per metric across all projects of the workspace, with the projects in the weakest quarter (team only). A client gets hidden: true unless the team turns benchmarks on for clients; clients never see custom tags or shared figures.
- Access
- Session or API key (read or write)
- Who
- Team; clients with access to the Overview module.
Query parameters
project_id | int | |
period | 28 | 90 | Defaults to 28. |
scope | werkruimte | gedeeld | Defaults to werkruimte. |
group | string | Key from groups, e.g. soort:webshop or tech:drupal. Without: the most specific group with the most usable metrics. |
Response
period | int | |
scope | string | |
group | string | |
groups | object[] | key, label, usable |
metrics | object[] | 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 | object | Only without project_id: share, show_clients. |
computed_at | ?string | |
hidden | bool | |
Configure benchmarks
- Access
- Session or API key with write access
- Who
- Owner or member; viewers and clients get 403.
Actions (action)
settingsshare, show_clientsResponse: settings.
share bool · Take part anonymously in the comparison across workspaces. Off by default.show_clients bool · Clients see their own project's position. Off by default.
Monthly reports across all projects
Per project the state of one month's report: missing, draft (fetch errors), ready, sent or opened (by a client, in Studio or via a share link; only a count, not who).
- Access
- Session or API key (read or write)
- Who
- Team only (owner, member or viewer); clients get 403.
Query parameters
period | string | A closed month like 2026-09; defaults to last month. |
Response
period | string | |
label | string | |
periods | object[] | period, label |
rows | object[] | project_id, project, color, clients, tags, report_id, status, errors, generated_at, published_at, views, first_viewed_at |
counts | object | ontbreekt, concept, klaar, verstuurd, geopend |
can_manage | bool | |
Create drafts and send ready reports
- Access
- Session or API key with write access
- Who
- Owner or member; viewers and clients get 403.
Actions (action)
generate_missingperiodA draft for every project without a report, in the background (202). Response: queued, tasks.
publish_readyperiod, idsOnly ready reports; a draft with errors stays. Clients get the report mail through the default automation. Response: published, notified.
ids int[] · Only these reports; defaults to all that are ready.
Today: what needs attention across all projects
Outages, critical and high vulnerabilities (per package and version across all projects), certificates and domains expiring within 14 days, sources that fail, new errors after a deploy, a drop in the App Store rating, actions waiting for you and last month's reports still in draft. Each item has a to pointing to where you fix it.
- Access
- Session or API key (read or write)
- Who
- Team only (owner, member or viewer); clients get 403.
Response
items | object[] | 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 | object | |
counts | object | bad, total |
Example: Response
{
"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
}
}
Project tags
Platform (Web, iOS) and technology (Drupal 11, Laravel 13, PHP 8.4) are detected by Studio from integrations, lockfiles, the Drupal module or WordPress plugin, the site check and Plesk; origin and origin_at say where and when. Own tags are made by the team.
- Access
- Session or API key (read or write)
- Who
- Team only (owner, member or viewer); clients get 403.
Query parameters
project_id | int | Only this project. |
hidden | bool | Also switched-off automatic tags. |
Response
tags | object[] | id, project_id, kind (platform|tech|own), slug, key, label, color, auto, hidden, origin, origin_at |
Add, switch off and re-detect tags
- Access
- Session or API key with write access
- Who
- Owner or member; viewers and clients get 403.
Your saved views of the project list
- Access
- Session or API key (read or write)
- Who
- Team only (owner, member or viewer); clients get 403.
Response
views | object[] | id, name, filters (client, type, tags, attention) |
Save and delete views
- Access
- Session or API key with write access
- Who
- Team only (owner, member or viewer); clients get 403.
Actions (action)
savename*, filters, view_idResponse: view_id.
filters object · client (?int), type (?string), tags (string[], as kind:slug, e.g. tech:drupal), attention (bool).view_id int · With id: update.
deleteview_id*
Your personal preferences
- Access
- Session or API key (read or write)
- Who
- Team only (owner, member or viewer); clients get 403.
Response
start_page | ?string | je eigen keuze, null is de standaard |
start_page_default | string | |
options | object | |
Choose your start page, mark What's new as read, app language
- Access
- Session or API key with write access
- Who
- Everyone for
locale; the rest team only.
Actions (action)
start_pagestart_pageNull restores the default: Vandaag for a team of one, Projecten for a team. Response: start_page.
start_page ?overzicht | vandaag | projecten | techniek
changelog_seenversion*Never moves back in time; /api/me returns changelog_seen. Response: changelog_seen.
version string · Date of the newest version, yyyy-mm-dd.
localelocale*App language for this user; /api/me returns it as user.locale. Defaults to nl. Response: locale.
project_orderids*Per user; clients too. Projects you can't see are skipped. GET /api/projects and /api/portfolio sort by it. Response: ids.
ids int[] · Project ids in the desired order.
Client start page
Per project this month's results against the same days last month, goals, what was done and what's next.
- Access
- Session or API key (read or write)
- Who
- Everyone in the workspace; a client only sees their own projects.
Response
month | string | |
days_so_far | int | |
projects | object[] | id, name, numbers, series (day, value: bezoeken per dag deze maand), goals, done, next, report, weekly_update |
Turn the weekly update on or off
- Access
- Session or API key with write access
- Who
- Clients with access to the project.
Actions (action)
weeklyproject_id*, on*Response: weekly_update.
Notification centre: what happened
The bell in the app, per user and workspace, for the last 30 days: outages and recoveries, anomalies, newly found sources, approvals, client questions, rejected app versions, confirmed advice and new form submissions. A client only sees outages of their own projects, answers to their questions and submissions when allowed to view Website. Outages and anomalies follow the account's notification preferences.
- Access
- Session or API key (read or write)
- Who
- Everyone in the workspace; a client only sees their own projects.
Query parameters
count | bool | Only the unread count. |
Response
items | object[] | 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 | int | |
kinds | object | |
Mark notifications as read
- Access
- Session or API key with write access
- Who
- Everyone in the workspace; a client only sees their own projects.
Start checklist for a workspace
The steps that get a workspace going, computed from the current state: Google, first project, type, uptime, script, Search Console, client, and for the owner two-factor and billing details.
- Access
- Session or API key (read or write)
- Who
- Owner and team members; null for everyone else.
Response
checklist | ?object | steps (object[]: key, done, title, why, to, action), done (int), total (int), complete (bool), hidden (bool) |
Hide or show the start checklist
- Access
- Session or API key with write access
- Who
- Owner and team members.
Search projects, recommendations, queries and pages
- Access
- Session or API key (read or write)
- Who
- Everyone in the workspace; a client only sees their own projects.
Query parameters
q* | string | At least two characters. |
Response
results | object[] | kind, title, subtitle, project_id, tab, filter |
Status of a background task
- Access
- Session or API key (read or write)
- Who
- Everyone in the workspace; a client only sees their own projects.
Response
status | queued | running | done | failed | |
result | ?object | |
error | ?string | |
All sources with their status
GA4, Search Console, own systems, extra services and uptime checks, with whether each one works.
- Access
- Session or API key (read or write)
- Who
- Team only (owner, member or viewer); clients get 403.
Query parameters
project_id | int | Only this project's sources; then without projects. |
Response
items | object[] | 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 | object[] | id, name, color, sources, problems, unchecked, clients, open_advice, monitors_down, latest_report |
counts | object | error, waiting, ok |
Fetch a source now, or stop expecting a missing figure
- Access
- Session or API key with write access
- Who
- Owner or member; viewers and clients get 403.
Actions (action)
fetchtype*, id*Single-request sources (most integrations, own systems) right away; GA4, Search Console, payments, Ads and App Store Connect through the queue, with fetching: true until done. At most once a minute per source (429). Response: item.
type ga | search | app | integration
ignore_metricid*The figure was removed on purpose: no more signal. If it comes back later, it counts again. Response: ignored.
id int · The id from missing.
Newly found sources
What Studio sees through a connection but is not linked anywhere (Analytics properties, Search Console sites, apps, business profiles and, for admins, Plesk domains), plus what was ignored or archived. Studio never decides on its own. Types set to "hide" only count in hidden.
- Access
- Session or API key (read or write)
- Who
- Team only (owner, member or viewer); clients get 403.
Response
new | object[] | key, type (ga|search|apple|gbp|plesk), ref, name, detail, project_id, project_name, state, decided_at, data_deleted, suggestion {name, template} |
ignored | object[] | |
archived | object[] | |
linked | object[] | |
archived_projects | object[] | id, name, archived_at |
hidden | int | |
notify | int | |
settings | object | modes {ga, search, apple, gbp, plesk: melden|stil|verbergen}, include_archived |
can_manage | bool | |
projects | object[] | id, name |
templates | object[] | key, label |
Link, ignore, archive or restore
- Access
- Session or API key with write access
- Who
- Owner or member; viewers and clients get 403.
What Studio can do with a connection
Per capability what is minimally needed, what the key may do according to the last measurement (yes, no, unknown) and whether it is on. Off means Studio does not fetch it at all. minimal says which rights suffice for what is on; warnings lists keys with more rights than needed.
- Access
- Session or API key (read or write)
- Who
- Team only (owner, member or viewer); clients get 403.
Query parameters
subject_type* | string | apple, google, integration, slack or chat. |
subject_id* | int | Id of the Apple account, Google connection, project integration, workspace (slack) or channel. |
Response
type | string | |
name | string | |
items | object[] | cap, label, needs, why, write, enabled, have (ja|nee|onbekend), detail, state (aan|uit|niet mogelijk|niet gemeten) |
measured_at | ?string | |
warnings | string[] | |
fix | ?object | Where to lower the rights: steps, links (label, url), copy (label, value). |
keys | object[] | key_id, role, role_label, account_key, allowed (alleen Apple) |
minimal | ?string | |
can_manage | bool | |
Turn a capability on or off, or measure again
- Access
- Session or API key with write access
- Who
- Owner or member; viewers and clients get 403.
All dashboards of the workspace
Dashboards across projects (without project_id) first, then the per-project ones.
- Access
- Session or API key (read or write)
- Who
- Team only (owner, member or viewer); clients get 403.
Response
dashboards | object[] | id, name, goal, project_id, project_name, tiles (aantal), scope |
can_edit | bool | |
limit | ?int | |
workspace_count | int | |
A project dashboard, or one across projects
With project_id a project dashboard. Only dashboard_id without project_id returns a dashboard across projects (team only): tiles over the projects in scope, plus single-project tiles; catalog and project_catalog are the choices.
- Access
- Session or API key (read or write)
- Who
- Team; clients with access to the Overview module.
Query parameters
project_id | int | Empty for a dashboard across projects. |
dashboard_id | int | Defaults to the first. |
Response
dashboards | object[] | id, name, goal |
current | object | id, name, goal |
tiles | object[] | |
chosen | string[] | |
catalog | object | |
goals | object | |
can_edit | bool | |
limit | ?int | |
Create, edit and delete dashboards
- Access
- Session or API key with write access
- Who
- Owner or member; viewers and clients get 403.
Monthly goals, forecast and benchmark
- Access
- Session or API key (read or write)
- Who
- Team; clients with access to the Overview module.
Query parameters
project_id* | int | Project id. |
Response
goals | object[] | metric, label, target, value, projected, status |
metrics | object | |
can_manage | bool | |
suggested | ?object | |
forecast | ?object | |
languages | ?object | |
benchmark | ?object | |
signals | ?object | |
Set or remove a monthly goal
- Access
- Session or API key with write access
- Who
- Owner or member (manages Overview); others get 404.
Actions (action)
setproject_id*, metric*, target*Response: goals.
metric sessions | key_events | new_users | clickstarget int · At least 1.
deleteproject_id*, metric*Response: goals.
metric sessions | key_events | new_users | clicks
Project timeline
- Access
- Session or API key (read or write)
- Who
- Team; clients with access to the Overview module.
Query parameters
project_id* | int | Project id. |
days | int | 1 to 800; defaults to 28. |
Response
annotations | object[] | id, kind, title, detail, url, happened_at |
can_manage | bool | |
Timeline event or deploy key
- Access
- Session or API key with write access
- Who
- Owner or member; viewers and clients get 403.
Actions (action)
createproject_id, date, kind, title*, detail, urlproject_id ?int · Null: for all projects.kind notitie | google | meting | deploy
deleteid*deploy_tokenproject_idResponse: token, url.
Project setup checklist
- Access
- Session or API key (read or write)
- Who
- Team only (owner, member or viewer); clients get 403.
Query parameters
project_id* | int | Project id. |
Response
sections | object[] | |
can_manage | bool | |
Tick off a checklist item or recheck
- Access
- Session or API key with write access
- Who
- Owner or member; viewers and clients get 403.
Hour budget per client
- Access
- Session or API key (read or write)
- Who
- Team only (owner, member or viewer); clients get 403.
Query parameters
month | month | Defaults to this month. |
Response
month | month | |
projects | object[] | project_id, name, budget, spent, pace |
entries | object[] | id, project_id, project, day, minutes, note, user, advice |
can_manage | bool | |
Log hours and set budgets
- Access
- Session or API key with write access
- Who
- Team only (owner, member or viewer); clients get 403.
What Studio knows about one page
For the browser extension: finds the project by domain and returns crawl, queries, recommendations and speed for that path, per module you can access.
- Access
- Session or API key (read or write)
- Who
- Everyone in the workspace; a client only sees their own projects.
Response
project | ?object | id, name |
path | string | |
crawl | ?object | |
queries | object[] | |
advice | object[] | |
speed | ?object | |
link | url | |
Domains of a project
- Access
- Session or API key (read or write)
- Who
- Owner or member (manages Website); others get 404.
Query parameters
project_id* | int | Project id. |
Response
domains | object[] | id, domain, record, verified, via (dns|plugin), plugin, primary, source (auto|manual), verified_at, checked_at |
Verify, add, remove or make a domain the main one
- Access
- Session or API key with write access
- Who
- Owner or member (manages Website); others get 404.
Actions (action)
checkproject_id*, domain*Response: verified, domains.
addproject_id*, domain*Response: verified, domains.
domain string · A domain or address; Studio keeps the domain itself (without www).
removeproject_id*, domain*The domain does not come back, not even through an old Search Console property. Site checks on it go too. Response: left, domains.
primaryproject_id*, domain*, moveResponse: website, domains.
move bool · Default true: uptime checks move along and the old main domain is removed.
Mail funnels from other systems
What a site sends itself (field mail_funnels in the metrics contract), later also Mailchimp and Brevo. Counts only. Without project_id all projects (team only).
- Access
- Session or API key (read or write)
- Who
- The team; with
project_id also clients with Mail funnels.
Query parameters
project_id | int | |
days | 7 | 30 | 90 | |
Response
days | int | |
funnels | object[] | 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) |
Followed social media posts
- Access
- Session or API key (read or write)
- Who
- Anyone who may view the project website.
Query parameters
project_id* | int | Project id. |
Response
posts | object[] | 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 | bool | |
Follow, update or stop following a post
- Access
- Session or API key with write access
- Who
- Anyone who may manage the project website.
Actions (action)
addproject_id*, url*, refResponse: id, error.
url url · Link to a post on Reddit, Hacker News, Bluesky or Mastodon.
updateid*, refrefreshid*deleteid*
Site events of a project
- Access
- Session or API key (read or write)
- Who
- Team only (owner, member or viewer); clients get 403.
Query parameters
project_id* | int | Project id. |
status | ok | opnieuw | dubbel | mislukt | geweigerd | ongeldig | |
entry | int | One log entry, with runs_detail (automation, filters, actions). |
Response
log | object[] | id, event, event_id, data, private_keys (alleen namen), status, reason, http_status, runs, duration_ms, received_at; de laatste 100 |
hook | ?object | received, last_at, created_at |
events | object[] | event, total, refs (ref, n), days (day, n); 30 dagen |
automations | object[] | id, name, enabled, event |
retrying | int | |
can_manage | bool | |
Create or remove the site events address
- Access
- Session or API key with write access
- Who
- Owner or member; viewers and clients get 403.
What you could still set up for a project
From the basics, what Studio sees on the site but is not connected, and what at least half of the projects of the same type have.
- Access
- Session or API key (read or write)
- Who
- Team only (owner, member or viewer); clients get 403.
Query parameters
project_id* | int | Project id. |
all | bool | Include dismissed ones. |
Response
tips | object[] | key, source (basis|gezien|soortgelijk), title, why, action {label, to}, peers (?object: count, total, template), dismissed |
Dismiss or restore a tip
- Access
- Session or API key with write access
- Who
- Team only (owner, member or viewer); clients get 403.
Sources and connections
Google connections, Search Console, own systems (instnt-metrics), extra services and inbound forms. Secrets never go back to the browser; a stored secret shows as <field>_configured: true.
Google connections with their GA4 properties
- Access
- Session or API key (read or write)
- Who
- Team only (owner, member or viewer); clients get 403.
Response
connections | object[] | id, kind, google_email, status, own_key, usable, created_at, properties |
Add, replace or remove a service account
- Access
- Session or API key with write access
- Who
- Owner or member; viewers and clients get 403.
Actions (action)
createkey*Response: connection_id, google_email, property_count.
key json · The service account JSON, as object or text. Tested with Google immediately.
replace_keyconnection_id*, key*Keeps the connection and its assignments; the old key stays active if the new one fails. Response: google_email, property_count.
toggleproperty_id*, enabled*refreshClears the workspace caches, for example after granting new Analytics access.
deleteconnection_id*
GET/api/connections/googleStart connecting with Google (OAuth)
Redirects the browser to Google for read access to Analytics, Search Console and Business Profile. Meant for the browser.
- Access
- Session or API key (read or write)
- Who
- Owner or member; viewers and clients get 403.
- Status
- 302
GET/api/connections/google/callbackReturn from Google after connecting
- Access
- No sign-in
GET/api/connections/oauth/{provider}Start connecting with Teamleader or Microsoft Advertising (OAuth)
provider is teamleader or microsoft_ads. Redirects the browser to the service; on return instnt studio stores the refresh token encrypted with the integration. Without an app on the server (client ID and secret in .env) the browser returns with oauth=niet-ingericht.
- Access
- Session or API key (read or write)
- Who
- Owner or member; viewers and clients get 403.
- Status
- 302
Query parameters
integration_id* | int | An integration of kind teamleader or microsoft_ads, created first with POST /api/integrations. |
GET/api/connections/oauth/{provider}/callbackReturn from Teamleader or Microsoft after connecting
- Access
- No sign-in
Search Console properties
- Access
- Session or API key (read or write)
- Who
- Team only (owner, member or viewer); clients get 403.
Response
sites | object[] | id, project_id, connection_id, site_url, display_name, status |
Add and assign Search Console properties
- Access
- Session or API key with write access
- Who
- Owner or member; viewers and clients get 403.
Actions (action)
availableconnection_id*Response: sites.
createproject_id*, connection_id*, site_url*Response: site_id.
updatesite_id*, display_nameassignsite_id*, project_iddeletesite_id*
Own systems (instnt-metrics)
- Access
- Session or API key (read or write)
- Who
- Team only (owner, member or viewer); clients get 403.
Response
sources | object[] | id, project_id, name, url, status |
Connect or change an own system
- Access
- Session or API key with write access
- Who
- Owner or member; viewers and clients get 403.
Extra services of a project
oauth only appears for teamleader and microsoft_ads: connected (a token exists) and available (the server can connect).
- Access
- Session or API key (read or write)
- Who
- Team; clients with access to the Website module.
Query parameters
project_id* | int | Project id. |
Response
integrations | object[] | id, project_id, kind, name, status, config, oauth |
Connect, test or change a service
- Access
- Session or API key with write access
- Who
- Owner or member; viewers and clients get 403.
Actions (action)
createproject_id*, kind*, config*, nameResponse: integration_id.
kind string · For example clarity, sentry, umami, posthog, mollie, stripe, github, bing, dataforseo, shopify, woocommerce, appstore_connect. The full list is in the source marketplace.config object · For appstore_connect: account_id and app_id (see /api/appstore-accounts). A config with issuer_id, key_id and private_key becomes an Apple account.
updateintegration_id*, config*config object · An empty secret field keeps the current secret.
testintegration_id*Fetches once right away. Response: testable, passed, metrics, items, error.
appstore_analyticsintegration_id*, key_id*, private_key*Only for an App Store Connect integration: requests App Analytics from Apple once. The Admin key is used only for this request and is not stored. Response: analytics.
key_id string · Key ID of an App Store Connect key with the Admin role.private_key string · Contents of that key’s .p8 file.
deleteintegration_id*
GET/api/appstore-accountsApple accounts for App Store Connect
Per account the team’s apps and which project each app belongs to. The .p8 key is never returned.
- Access
- Session or API key (read or write)
- Who
- Team only (owner, member or viewer); clients get 403.
Response
accounts | object[] | 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 | object[] | id, name |
POST/api/appstore-accountsAdd an Apple account, link apps or turn on App Analytics
- Access
- Session or API key with write access
- Who
- Owner or member; viewers and clients get 403.
Actions (action)
createissuer_id*, key_id*, private_key*, vendor_number, nameTests the key with Apple first by fetching the apps; a key Apple rejects is not stored. The same issuer and key ID update the existing account. Status 201. Response: account_id, apps.
private_key string · Contents of the .p8 file (Sales and Reports role).vendor_number string · One or more vendor numbers, separated by commas.
updateaccount_id*, name, issuer_id, key_id, vendor_number, private_keyissuer_id string · A changed ID is tested at Apple first.key_id string · A changed ID is tested at Apple first.vendor_number string · One or more, separated by commas. A different number fetches the history again.private_key string · Empty keeps the current key.
refreshaccount_id*Fetches the apps from Apple again. Response: apps.
linkaccount_id*, app_id*, project_idAn app belongs to at most one project, and a project has one App Store Connect source: a new link replaces the old one. Response: integration_id.
project_id ?int · Empty or null unlinks the app.
historyaccount_id*Fetches the missing sales reports: years (ten years back), months and days (one year). Also happens automatically after adding and twice a day; Studio never requests a closed period again. Response: started, pending.
analyticsaccount_id*, key_id*, private_key*, app_idsRequests App Analytics per app. The Admin key is used only for these requests and is not stored. Response: enabled, failed.
key_id string · Key ID of a key with the Admin role.app_ids string[] · Empty means all apps of the account.
deleteaccount_id*409 in_use while apps are linked to projects.
key_addaccount_id*, role*, key_id*, private_key*Extra key with its own role, from the same team (same issuer ID). Tested with Apple first. Studio picks per section the least-privileged key that is allowed, and remembers a refusal (403) for a week. Developer opens build details, TestFlight feedback, diagnostics, Xcode Cloud, Game Center and purchases; Customer Support review replies and the store page name and subtitle. Status 201.
role sales | developer | customer_support | marketing | app_manager | admin
key_deleteaccount_id*, key_id*key_id int · The id from keys, not Apple's key ID.
webhookaccount_id*New address and secret for App Store Connect notifications (Users and Access → Integrations → Webhooks). An old address stops working. Response: webhook.
GET/api/google-play-accountsGoogle Play accounts
Per account the apps the service account can see, with installs and which project each app belongs to. The key is never returned, only the service account email.
- Access
- Session or API key (read or write)
- Who
- Team only (owner, member or viewer); clients get 403.
Response
accounts | object[] | id, name, client_email, bucket, status, status_message, checked_at, apps (package_name, title, installs_total, installs_30d, project_id, project_name, state) |
projects | object[] | id, name |
can_manage | bool | |
POST/api/google-play-accountsAdd a Google Play account or link apps
- Access
- Session or API key with write access
- Who
- Owner or member; viewers and clients get 403.
Actions (action)
createkey*, bucket, nameTests the key with Google first by fetching the apps; a key that is not allowed anything is not stored. The same service account updates the existing account. Status 201. Response: account_id, apps.
key string · The JSON key of a Google Cloud service account invited in Play Console.bucket string · Cloud Storage URI of the reports (gs://pubsite_prod_…). Without a bucket no installs.
updateaccount_id*, name, bucket, keykey string · Only a new key of the same service account.
refreshaccount_id*Fetch apps and install reports again; at most once a minute. Response: apps, files.
linkaccount_id*, package_name*, project_idAn app belongs to at most one project; a first fetch (installs, vitals, reviews, versions) follows immediately. Response: linked, integration_id.
project_id ?int · Empty or null unlinks the app.
deleteaccount_id*Also removes the app links to projects. The fetched installs go too.
Google Play: installs, vitals and versions of an app
Per Google Play app of the project: user installs per day (365 days) and month from the monthly reports in Cloud Storage, active devices, rating, Android vitals (user-perceived crashes and ANR, averaged over 28 days, with Google's threshold) and the versions per track. A part switched off on the account returns null. null for a day means unknown, not zero. Reviews are under /api/reputation. Requires the Product module.
- Access
- Session or API key (read or write)
- Who
- Everyone in the workspace; a client only sees their own projects.
Response
apps | object[] | 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 |
App Store for makers: versions, TestFlight, reviews, performance, subscriptions and store page
Per app of the project what App Store Connect knows, fetched every half hour (versions, builds, beta groups, feedback, reviews) and once a day (the rest). sections gives the state per section: ok, leeg (empty), fout (error), or sleutel with the needed role in message. Subscriptions only for the team or a client allowed to approve the overview. Requires the Product module.
- Access
- Session or API key (read or write)
- Who
- Everyone in the workspace; a client only sees their own projects.
Response
apps | object[] | 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 | bool | |
team | bool | |
Reply to reviews, crash as prompt, fetch now
- Access
- Session or API key with write access
- Who
- Owner or member; viewers and clients get 403.
Actions (action)
replyproject_id*, review_id*, body*Posts or replaces the reply at Apple. Requires a key with the Customer Support or App Manager role. Response: response.
review_id int · The id from reviews.items.body string · At most 5970 characters.
delete_replyproject_id*, review_id*suggest_replyproject_id*, review_id*Claude drafts a reply in the brand voice; it then appears as suggestion on the review. Never posted automatically. Response: task_id.
promptproject_id*, feedback_id*Prompt for a Claude Code session in the app repository, with the crash log. Response: prompt.
syncproject_id*At most once a minute (429). Status 202. Response: started.
Modules and their state
Module catalogue with, per module, whether it is in the plan, on for the workspace and (with project_id) for the project, and whether the required source is connected. status: aan (on), uit (off), plan, project_uit (off for the project) or nodig (source needed).
- Access
- Session or API key (read or write)
- Who
- Team; a client only with project_id, and then only on or off per module.
Response
modules | object[] | key, label, uitleg, icon, min_plan, needs_label, scope, plan_allows, workspace_on, project_on, needs_met, projects_ready, status |
can_manage | bool | |
Turn a module on or off
- Access
- Session or API key with write access
- Who
- Owner or member; viewers and clients get 403.
Orders
Individual orders from Shopify, WooCommerce and own systems, without customer data, with a link to the order in the shop. Only when the Orders module is on; only for the team or a client allowed to approve the overview. With scope=today the orders of today per project.
- Access
- Session or API key (read or write)
- Who
- Team; clients with access to the Overview module.
Query parameters
project_id | int | |
scope | today | |
days | int | |
status | open | betaald | verzonden | afgerond | geannuleerd | terugbetaald | mislukt | |
q | string | |
Response
orders | object[] | id, source, number, ordered_at, status, total_cents, currency, items (name, qty), admin_url |
counts | object | |
sold | int | |
total_cents | int | |
module | ?object | |
synced_at | ?datetime | |
projects | object[] | Only with scope=today: project_id, name, count, total_cents, currency, latest. |
Fetch orders now
- Access
- Session or API key with write access
- Who
- Owner or member; viewers and clients get 403.
Landing pages module
Designated landing pages with visits (GA4, else the site script), conversion, ad costs of linked Ads campaigns, forms, scroll depth (Clarity), Search Console and speed, plus A/B comparisons with the probability that B converts better (Beta-Binomial, from 100 visits per variant). Only when the module is on. Ad costs only for the team or a client allowed to approve the overview. With page_id one page with channels, queries and a daily series.
- Access
- Session or API key (read or write)
- Who
- Team; clients with access to the Website module.
Query parameters
project_id* | int | Project id. |
days | int | Period in days, 7–365; defaults to 28. |
page_id | int | |
Response
pages | object[] | 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 | object[] | id, name, page_a_id, page_b_id, started_on, ended_on, prob_b_better, min_sessions, verdict |
suggestions | object[] | path, sessions, key_events |
campaigns | object[] | id, name, channel |
module | object | |
can_manage | bool | |
money | bool | |
base_url | ?url | |
page | object | Only with page_id: the page with channels, queries and series. |
Designate and compare landing pages
- Access
- Session or API key with write access
- Who
- Owner or member (manages Website); others get 404.
Form submissions
Which form was submitted when, on which page, with a link to the submission in the CMS or form tool. Never what was filled in. Only when the Submissions module is on. admin_url only for the team or a client with Website on approve; otherwise null. new: after the last submission this user viewed and within the last 30 days. With scope=new the new submissions per project.
- Access
- Session or API key (read or write)
- Who
- Team; clients with access to the Website module.
Query parameters
project_id | int | |
scope | new | |
days | int | Period in days, 1–396; defaults to 30. |
form | string | |
Response
submissions | object[] | id, source, source_label, form, page, submitted_at, new, admin_url |
forms | object[] | form, count, latest_at |
total | int | |
unread | int | |
can_open | bool | |
module | object | |
projects | object[] | Only with scope=new: project_id, name, count, last_id, latest_at. |
Mark submissions as seen
- Access
- Session or API key with write access
- Who
- Team; clients with access to the Website module.
Reputation: reviews from all sources
Reviews from the Google Business Profile, Trustpilot, Kiyoh and the App Store together. summary.average and count come from the platforms themselves where known (Kiyoh converted from 10 to 5), the rest from stored reviews (the latest 50 to 100 per source). trend per month over twelve months. Claude suggestions (suggestion) only for the team. Without project_id: per project you can see under Findability.
- Access
- Session or API key (read or write)
- Who
- Team; clients with access to the Search module.
Query parameters
project_id | int | |
source | gbp | trustpilot | kiyoh | appstore | google_play | |
rating | int | Only this number of stars, 1–5. |
open | bool | Only without a reply. |
Response
summary | object | average, count, new_this_month, answered_pct, open_low, stored |
sources | object[] | source, label, average, count, stored, platform, can_reply |
trend | object[] | month, count, average |
items | object[] | id, source, source_label, rating, score, title, body, author, language, country, url, reviewed_at, reply, can_reply, suggestion |
can_reply | bool | |
team | bool | |
projects | object[] | Only without project_id: project_id, project, sources, average, count, new_this_month, answered_pct, open_low. |
Reply to reviews
- Access
- Session or API key with write access
- Who
- Owner or member; viewers and clients get 403.
Actions (action)
replyproject_id*, review_id*, body*Google and the App Store only; Trustpilot and Kiyoh return 422. Google requires "Connect with Google" with Reply to reviews enabled. Response: reply.
review_id int · The id from items.body string · Google at most 4096 characters, the App Store 5970.
delete_replyproject_id*, review_id*suggest_replyproject_id*, review_id*Claude drafts a reply in the brand voice; it then appears as suggestion on the review. Never posted automatically. Response: task_id.
Campaigns: UTM, ads and mailings together
Campaigns module (from Copiloot). A campaign adds up what matches its rules: GA4 per UTM campaign, source and medium, sign-ups and payments from your own system with the same UTM, Google Ads, Meta and LinkedIn campaigns, and mailings from Mailchimp and Brevo. Rules of the same kind: one must match; different UTM kinds: all. previous is an equally long period directly before. Users are summed per day. Cost, revenue, budget, CPC, CPA and ROAS only for the team or a client who may approve the overview. Without project_id: all projects with the module that you can see. With campaign_id also series, channels, sources, pages, ads and mailings.
- Access
- Session or API key (read or write)
- Who
- Team; clients with access to the Website module.
Query parameters
project_id | int | |
campaign_id | int | |
Response
campaigns | object[] | id, project_id, name, starts_on, ends_on, budget, goal, rules, period, current, previous, derived, mail |
suggestions | object[] | UTM campaigns without a campaign (90 days): value, sessions, sources. Manage rights only. |
ignored | string[] | |
linkables | object[] | What you can link as a rule: kind, value, label. |
module | object | |
money | bool | |
can_manage | bool | |
base_url | ?string | |
campaign | object | With campaign_id. |
projects | object[] | Without project_id: project_id, name, campaigns. |
Manage campaigns
Sending is not possible here: do that in Brevo or Mailchimp; instnt studio reads the results.
- Access
- Session or API key with write access
- Who
- Owner or member (manages Website); others get 404.
Customer journey: stages, channels and paths as totals
Customer journey module (from Inzicht). Added up nightly from GA4, the site script, leads, sign-ups from your own system and orders; no journey per person. stages: visit, engaged, lead and customer with the sources that count (per project type, or as configured), the previous equally long period and from_previous (a ratio of totals, not a tracked group). channels: channel × stage; a stage without channel information is listed in missing. paths: steps from page to page, pages with a lead and landing pages with key events, only at least k times; hidden counts what stayed below. ttc: days from sign-up to subscription, only with at least k subscriptions. Without the module: journey is null.
- Access
- Session or API key (read or write)
- Who
- Team; clients with access to the Website module.
Query parameters
project_id* | int | Project id. |
period | int | 28 or 90; defaults to 28. |
Response
module | object | |
can_manage | bool | |
journey | ?object | type, type_label, period, range, stages, trend, channels, paths, ttc, sources, custom, stage_labels, computed_at, k |
Configure the customer journey
- Access
- Session or API key with write access
- Who
- Owner or member (manages Website); others get 404.
AI traffic and clicks against sessions, per day
From the fact tables, updated nightly. view=ai: sessions from AI assistants (ChatGPT, Perplexity, Gemini, Copilot, Claude …) from GA4, or without GA4 visitors from the site script (unit); previous is the equally long period before. view=search: Search Console clicks against organic GA4 sessions per day. Search Console lags a few days; those days have clicks: null. totals only counts days where both exist.
- Access
- Session or API key (read or write)
- Who
view=ai: view Visits (website); view=search: view Findability (search). Others get 404.
Query parameters
project_id* | int | Project id. |
view | ai | search | |
days | int | 7, 28 or 90; defaults to 28. |
Response
days | int | |
source | ?string | Only with ai: ga4, script or null. |
unit | string | |
current | int | |
previous | int | |
series | object[] | day, value (ai) of day, clicks, sessions (search) |
sources | object[] | key, value, previous |
has_search | bool | |
has_ga | bool | |
search_until | ?date | |
ga_until | ?date | Last day with GA4 figures; after it sessions: null. |
totals | object | clicks, sessions, ratio |
404 monitor
Pages that do not exist but get visits or links, merged every morning from GA4 (title or path of the error page), the site script, the crawler and Search Console URL inspection. The Search Console API has no list of 404s; only per inspection. A page not seen for seven days is marked resolved; when it gets visits again, it is new again.
- Access
- Session or API key (read or write)
- Who
- Team; clients with access to the Search module.
Query parameters
project_id* | int | Project id. |
status | nieuw | opgelost | genegeerd | |
Response
status | string | |
counts | object | nieuw, opgelost, genegeerd |
pages | object[] | id, path, status, hits, sources, referrers, first_seen, last_seen, resolved_at |
settings | object | titles, paths, min_hits |
can_manage | bool | |
Update the 404 monitor
- Access
- Session or API key with write access
- Who
- Owner or member (manages Search); others get 404.
Actions (action)
ignoreproject_id*, id*Response: id, status.
reopenproject_id*, id*Response: id, status.
resolveproject_id*, id*Response: id, status.
settingsproject_id*, titles, paths, min_hitsResponse: settings.
titles string[] · Words in the title of the error page, at most 10.paths string[] · Paths that always count as an error page, such as /404.min_hits int · From this many views in 28 days a new 404 triggers a notification.
GET/api/conversion-sourcesConversion event sources
- Access
- Session or API key (read or write)
- Who
- Team only (owner, member or viewer); clients get 403.
Query parameters
project_id* | int | Project id. |
Response
sources | object[] | id, app_source_id, name, retention_days |
POST/api/conversion-sourcesCreate a conversion key
- Access
- Session or API key with write access
- Who
- Owner or member; viewers and clients get 403.
Inbound forms and bookings
- Access
- Session or API key (read or write)
- Who
- Owner or member; viewers and clients get 403.
Query parameters
project_id* | int | Project id. |
Response
hooks | object[] | id, provider, label, signed, received, last_at, url |
providers | object | |
Create or remove an inbound address
- Access
- Session or API key with write access
- Who
- Owner or member; viewers and clients get 403.
Actions (action)
createproject_id*, provider*, secretStatus 201.
provider typeform | calendly | gravityforms | overig | github | belmetingsecret string · To verify the signature; required for GitHub.
deleteid*
Microsoft Clarity: three-day summary
Cached for three hours because Clarity allows ten requests per day. 422 setup_required without a token, 502 clarity_unavailable when Clarity fails.
- Access
- Session or API key (read or write)
- Who
- Team; clients with access to the Website module.
Response
summary | object | sessions, users, rage_clicks |
days | int | |
Clarity: friction per page over 28 days
- Access
- Session or API key (read or write)
- Who
- Team; clients with access to the Website module.
Query parameters
project_id* | int | Project id. |
Response
pages | object[] | url, sessions, dead, rage, quickback, error_clicks, script_errors, scroll, active_seconds, friction |
days | int | |
Is the data feed on
- Access
- Session or API key (read or write)
- Who
- Owner or member; viewers and clients get 403.
Query parameters
project_id* | int | Project id. |
Response
active | bool | |
created_at | ?datetime | |
last_used_at | ?datetime | |
Create or revoke the data feed (CSV)
- Access
- Session or API key with write access
- Who
- Owner or member; viewers and clients get 403.
Advice, questions and AI
Recommendations and their status, playbooks, experiments, client questions and AI tasks.
Recommendations for a project
With scope=workspace (team only) the ten most important actions across projects. Each item has why: the parts of its ranking (clicks, confidence, effort, what the team learned).
- Access
- Session or API key (read or write)
- Who
- Team; clients with access to the Advice module.
Query parameters
project_id* | int | Project id. |
status | open | planned | done | bevestiging | dismissed | expired | all | actief | archief | Defaults to open. bevestiging: done, but not yet confirmed by the source. actief: open and planned. archief: done, dismissed and expired, newest first. |
group | page | With status=actief: also pages, the recommendations per page. |
scope | workspace | |
Response
items | object[] | At most 500, most important first, with impact_euros and confirmation (state confirmed or waiting, by, at, waits_on, overdue, note). |
euro_basis | ?object | |
counts | object | |
tip | ?object | |
last_refresh | ?datetime | |
thresholds | object | |
learned | object[] | |
effect_days | int | |
can_manage | bool | |
has_github | bool | |
progress | object[] | Per category: category, done, total (excluding expired). |
effect | ?object | Only with archief: done, measured, clicks, impressions (after minus before, over measured recommendations). |
pages | ?object[] | Only with status=actief&group=page: url, path, ids, count, impact_clicks, categories. |
Status, assign, GitHub issue, recheck, make prompt
- Access
- Session or API key with write access
- Who
- Owner or member; viewers and clients get 403.
Actions (action)
statusid*, status*, note, task_urlOn done Studio records the current figures to measure the effect after 14 days, and adds it to the timeline. The advice then waits for confirmation by its source (Google, live check, lockfile, measurement). Response: item.
status open | planned | done | dismissed
assignid*, assignee_id, due_dateAssigning plans an open recommendation. Response: item.
issueid*Creates an issue in the project's GitHub repo (502 github when GitHub refuses). Response: url.
recheckid*Status 202. Response: task_id.
refreshproject_id*Re-runs all rules. Status 202. Response: task_id.
promptproject_id*, ids*, mode, markTeam only. Turns recommendations that can be fixed in code or configuration into one task, with evidence, definition of done and how to verify. URLs without query string; no personal data or keys. Response: prompt, filename, items.
ids int[] · At most 30; only recommendations with fixable: true count.mode claude | algemeenmark bool · Defaults to true: sets the items to planned with a note.
Example: Request
{
"action": "status",
"id": 812,
"status": "done",
"note": "Titel aangepast"
}
Project playbooks
- Access
- Session or API key (read or write)
- Who
- Team; clients with access to the Advice module.
Query parameters
project_id* | int | Project id. |
Response
runs | object[] | |
available | object | |
can_manage | bool | |
Start and tick off a playbook
- Access
- Session or API key with write access
- Who
- Owner or member (manages Advice); others get 404.
Experiment log and hypothesis cards
- Access
- Session or API key (read or write)
- Who
- Team; clients with access to the Advice module.
Query parameters
project_id* | int | Project id. |
Response
experiments | object[] | |
cards | object[] | |
can_manage | bool | |
Record or delete an experiment
- Access
- Session or API key with write access
- Who
- Owner or member (manages Advice); others get 404.
Actions (action)
saveproject_id*, id, title*, hypothesis, metric, page_url, starts_on, ends_on, outcome, resultResponse: id.
id int · Without id: new.outcome won | lost | neutral
deleteproject_id*, id*
Questions about a report, recommendation or project
Returns disabled: true when questions are off for the workspace.
- Access
- Session or API key (read or write)
- Who
- Team and clients with access to the subject;
open=1 team only.
Query parameters
project_id | int | |
subject_type | report | advice | project | |
subject_id | int | |
open | bool | All open questions across clients. |
Response
questions | object[] | 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 | bool | |
Ask, reply or close a question
- Access
- Session or API key with write access
- Who
- Team and clients with access to the subject.
Support: tickets
Client questions to the agency (deel=klant, Support module, from Copiloot) and questions to instnt (deel=instnt). A question about a report or recommendation is a ticket too. Without id a list with counts per status; with id one ticket with the conversation, attachments and, for the handler, project context, internal notes, the team and saved replies. A ticket of another workspace returns 404.
- Access
- Session or API key (read or write)
- Who
- Client: own tickets (with the Support module). Team: all client tickets; viewers read only.
deel=instnt: owner or member. admin=1: platform admins only.
Query parameters
deel | klant | instnt | |
admin | bool | |
id | int | |
sets | bool | Only the sets of saved replies to load (team, 13-10-2026). |
lang | nl | en | |
status | actief | te_laat | open | wacht_ons | wacht_klant | opgelost | gesloten | Defaults to actief: everything except resolved and closed. Empty for all. |
q | string | Searches subject, number and messages. |
project_id | int | |
mine | bool | Only assigned to me. |
Response
tickets | object[] | 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 | object | |
overdue | int | |
module | object | |
statuses | object | |
priorities | object | |
can_create | bool | |
sets | object[] | With sets=1: key, label, description, count, titles. |
template_sets | object[] | For the team: the same sets. |
settings | object | Team only: sla, sla_default, inbound_available, inbound_on, address, can_manage. |
ticket | object | With id: the ticket plus thread, link, role, can, and for the handler context, team, templates and projects. |
Support: ask and handle questions
Attachments as multipart files[]: at most 5 per message and 10 MB per file; images (no SVG), pdf, text, csv and Office files. The type follows from the content, not the name.
- Access
- Session or API key with write access
- Who
- Per action: a client creates and answers their own tickets; owner and member handle and configure; with
admin: true platform admins handle questions to instnt.
Actions (action)
createdeel*, title*, body*, project_id, priority, filesStatus 201. Response: ticket.
deel klant | instnttitle string · At most 160 characters.body string · At most 10,000 characters.project_id int · Client with more than one project: required.priority laag | normaal | hoog | urgent · Only with deel=instnt.
replyid*, template_id, body*, files, adminOn a closed ticket only the handler. Response: ticket.
template_id int · The saved reply this came from; if it has actions (macro, 13-10-2026), Studio runs them after sending.
noteid*, body*, files, adminInternal note: the requester never sees it, nor its attachments. Response: ticket.
statusid*, status*, adminThe requester can only close. Response: ticket.
status open | wacht_ons | wacht_klant | opgelost | gesloten
assignid*, user_id, adminResponse: ticket.
priorityid*, priority*, adminRecalculates a running deadline. Response: ticket.
priority laag | normaal | hoog | urgent
projectid*, project_id, adminResponse: ticket.
settingssla, inbound_onResponse: settings.
sla object · Hours per priority (laag, normaal, hoog, urgent), each 1–720.
rotate_addressNew address for mail to support; the old one stops working at once. Response: settings.
template_saveid, project_id, category, actions, title*, shortcut, body*, buttons, adminThe same saved replies apply to Support and to chat. Response: templates.
project_id ?int · Only for this project (13-10-2026); empty means all projects. At most 50 per project and 50 general.category string · Category, at most 40 characters (13-10-2026).actions object · Macro (13-10-2026): status (wacht|afgesloten), tags (at most five), assign_me; applied after sending in chat.shortcut string · Shortcut for chat, without the slash: lowercase letters, digits and hyphens, at most 30.buttons string[] · Buttons in chat, at most four (22-10-2026).
template_deleteid*, adminResponse: templates.
template_importset, project_id, sets, only, langLoad a set of saved replies (13-10-2026). Adds without overwriting: the same name or shortcut is skipped, it stops above 50. Owner or member. Response: templates, imported.
set basis | webshop | diensten | horeca | softwareproject_id int · Into this project instead of general.sets string[] · Several sets at once (13-10-2026).only string[] · Only these replies, by title.lang nl | en
GET/api/support/attachmentTicket attachment
Always as a download, with X-Content-Type-Options: nosniff.
- Access
- Session or API key (read or write)
- Who
- Whoever may see the ticket; an attachment on an internal note only the handler.
Chat: conversations with visitors
The inbox for the on-site chat (Chat module, from Copiloot). Without id a list with counts; with id one conversation with messages, internal notes, visitor context (page, language, device, earlier conversations), the team and saved replies with variables filled in. Opening a conversation marks it read. With since only messages after that id, for polling. Opening the inbox counts as online for the widget for ninety seconds. A conversation of another project or workspace returns 404.
- Access
- Session or API key (read or write)
- Who
- Team: conversations of projects with the Chat module; viewers read only. Client: only for a project where they have Website on approve.
settings: owner or member.
Query parameters
view | open | wachtend | mijn | niet_toegewezen | buiten_tijden | afgesloten | alle | Defaults to open: everything not closed. wachtend: the team is up. |
project_id | int | |
label | string | Only conversations with this label. |
sort | wachtend | nieuwste | activiteit | Defaults to wachtend: whoever has waited longest on the team first. |
q | string | Searches name, email and messages. |
id | int | |
since | int | |
teller | bool | Counts only, for the navigation and the app icon. |
settings | int | Project id: the chat settings and the install snippet. |
Response
conversations | object[] | 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 | object | open, mijn, niet_toegewezen, wachtend, ongelezen; without teller also buiten_tijden, afgesloten, oudste_wacht, per_project (per project id: open, wachtend) and labels (the five most used: label, count); with teller=1 also projects (number of sites with chat for this user). |
projects | object[] | id, name, enabled, can_reply, notify_after |
sort | string | |
module | object | |
can_manage | bool | |
statuses | object | |
conversation | object | With id: the conversation plus messages, visitor, visitor_typing, rating_comment, ticket, can, team, templates and me (your own user id). Since 11-10-2026 visitor also has route (path, title, at: the pages of this visit, without query string, at most twenty, removed after 30 days without a message), read_upto and read_at (up to which message the visitor saw the window); a message can have faq (id, title). Since 12-10-2026 visitor.previous (id, status, created_at, last_at, rating, ticket, preview: the first sentence) also holds conversations from other browsers of the visitor, linked by code or StudioChat.identify(). Since 13-10-2026 viewers (id, name, typing): colleagues who also have this conversation open. |
settings | object | With settings: enabled, greeting, offline_message, color, position, hours, allowed_origins, allowed_hosts, prechat, proactive, notify_after, notify_users, snippet, token. Messages have files (attachments with a URL valid for half an hour); visitor has consent_at. |
Chat: reply and configure
- Access
- Session or API key with write access
- Who
- Whoever may reply: owner, member, or a client with Website on approve. Settings and deleting: owner or member.
Actions (action)
replyid*, faq_id, buttons, file, body*Replying to an unassigned conversation assigns it to you. Not on a conversation that became a ticket. Response: conversation.
faq_id int · A published FAQ article of this project as a card under the message (11-10-2026); body may then be empty.buttons string[] · At most four buttons of 1 to 40 characters under the message (22-10-2026); as a JSON string in multipart. The visitor picks one.file file · Attachment (21-10-2026): image (jpg, png, webp, gif) or PDF, at most 10 MB; the content decides the type. Then as multipart/form-data; body may be empty. Also with note.body string · At most 2,000 characters. {naam}, {voornaam}, {project}, {bureau} and {medewerker} are filled in.
noteid*, body*Internal note: the visitor never sees it. Response: conversation.
statusid*, status*Response: conversation.
status open | wacht | afgesloten
assignid*, user_idResponse: conversation.
tagsid*, tags*Response: conversation.
tags string[] · At most ten, each at most 30 characters.
filesid*, allow*, limitAllow or disallow attachments from the visitor in this conversation. Off by default; the visitor gets a system message and only then sees the paperclip. Response: conversation.
limit ?int · How many attachments the visitor may send before it closes again (13-10-2026); without it the site setting applies.
ticketid*Converts the conversation to a Support ticket (module required) and closes it. With the visitor's email address, the reply goes by email. Response: conversation.
typingid*The visitor sees "typing…" for eight seconds.
readid*activityid*, token*, environment, endLive Activity on the iPhone (12-10-2026): only from an app session (otherwise 403 app_only). Studio updates the activity by push on a new message, a reply, assignment and closing; closing or a ticket ends it. Response: state.
token string · Push token of the Live Activity (hex).environment sandbox | productionend bool · Remove the token: the app no longer follows this conversation.
deleteid*Deletes the conversation with all messages, for example at the visitor's request.
identity_secretproject_id*, removeCreate or renew the key for StudioChat.identify() (64 hex characters), or remove it with remove. Old signatures stop working. Response: settings.
muteid*, muted*Mute: no more push for this conversation, only for you (13-10-2026). The conversation returns muted. Response: conversation.
settingsproject_id*, enabled, auto_close_minutes, rating_aspects, file_types, file_max_mb, file_limit, greeting, offline_message, color, position, greeting_buttons, hide_branding, hours, allowed_origins, prechat, proactive, notify_after, notify_users, widgetResponse: settings, widget_options.
auto_close_minutes ?int · Close a conversation automatically after this many minutes without a visitor reply after the team answered (5 to 10080); empty means never (13-10-2026).rating_aspects bool · Also let visitors rate friendliness, speed and expertise.file_types string[] · What a visitor may send (13-10-2026): afbeeldingen (images), pdf and/or documenten (documents).file_max_mb int · 1 to 10.file_limit ?int · After this many attachments, attachments close again in that conversation; empty means no limit.position rechts | linksgreeting_buttons string[] · At most four buttons under the greeting; a click starts the conversation with that text.hide_branding bool · Window without instnt studio; only with white-label in the plan.hours ?object · Per day (1 = Monday) a list of blocks ["09:00","17:00"], in the workspace time zone; empty means always open.allowed_origins string · Extra origins allowed to load the widget, besides the project domains. Over http only what is listed here.prechat object · Form before the first message: when (nooit|offline|altijd), name/email/topic (uit|optioneel|verplicht), topics (at most ten), privacy (bool) and privacy_url (https). Outside opening hours email is always required. Replaces ask_email (21-10-2026).proactive object[] · At most five: match (bevat|is), path, delay (0–600 s), message (at most 300 characters), every_days (0–365; 0 = once), only_new, only_open.notify_after int · Email after this many minutes without a reply, 1–240.widget object · The window (10-10-2026), per group; what is missing stays as it was. home: mode (zoeken|samen|chat), contact (altijd|na_zoeken), featured_count (0–8), categories, conversation_card, logo. contact: offline (bericht|faq), alternatives (at most three: type telefoon|email|whatsapp, value, label, text, when altijd|offline), links (at most three: label, https URL). faq: enabled, suggest, feedback, log_misses. team: names (voornaam|volledig|voornaam_foto|bureau), queue. visibility: paths (at most ten: match bevat|is, path starting with /), mobile, offline. launcher: offset_x, offset_y (0–200), label_mobile. texts: per language (nl, en) greeting, offline, home_title, home_intro, search, contact, reply_time, launcher.
refused_allowproject_id*, origin*Allow a refused origin: it is added to allowed_origins and leaves the list. Response: settings.
refused_ignoreproject_id*, origin*Hide a refused origin; it is removed after 7 days. Response: settings.
rotate_tokenproject_id*New widget token; the old snippet stops working at once. Response: settings.
Frequently asked questions
Articles the visitor searches in the chat window. Markdown; html is sanitised (no raw HTML, no images, only http(s) and mailto links). With suggest at most three published matches for a visitor's question, with plain to insert as a reply.
- Access
- Session or API key (read or write)
- Who
- Like the chat: team with Website on view (drafts only for owner and member), a client only published articles and only with Website on approve.
Query parameters
project_id | int | |
q | string | Search title, category and body. |
suggest | string | The visitor's question. |
stats | int | Self-service figures over 7, 30 or 90 days; managers only. |
id | int | One article with body, html and plain. |
Response
stats | object | With stats: articles (per id views, yes, no, helpful_pct), views, yes, no, misses (searches without results: term, count), conversations_after, deflection_pct. |
articles | object[] | id, project_id, title, category, language, published, featured, position, views, updated_at, excerpt (met suggest ook body, html, plain) |
article | object | |
can_manage | bool | |
languages | object | |
max_body | int | |
Manage frequently asked questions
- Access
- Session or API key with write access
- Who
- Owner or member (Website on manage);
preview anyone who sees the chat.
Chat: reporting and availability
With view=report (default): conversations per day, per weekday and hour, first response and resolution time (median and p90, in seconds, only within opening hours), missed (15 minutes without a reply and no ticket), tickets, satisfaction (4 or 5 out of 5 counts as satisfied), busiest pages and per team member. With view=team: your own status, the team with status and open conversations, and the routing per project.
- Access
- Session or API key (read or write)
- Who
- Like the inbox. Per team member and the routing only for the team; changing the routing: owner or member.
Query parameters
view | report | team | |
from | date | Defaults to 27 days before to. |
to | date | Defaults to today. |
project_id | int | |
Response
report | object | from, to, timezone, totals, days, heatmap, pages, comments, agents, truncated |
projects | object[] | id, name |
me | object | With view=team: status, chosen, max_chats, open, can_set. |
team | object[] | id, name, status, open, max_chats |
routing | object[] | project_id, name, assign_mode, report_block |
Chat: status and routing
- Access
- Session or API key with write access
- Who
- Status: whoever may reply somewhere. Routing: owner or member.
AI tasks, texts, brand voice and AI visibility
- Access
- Session or API key (read or write)
- Who
- Team only (owner, member or viewer); clients get 403.
Query parameters
project_id* | int | Project id. |
Response
kinds | object | |
usage | object | used, limit, cost_usd |
worker_seen | ?datetime | |
tasks | object[] | |
texts | object[] | |
voice | ?object | |
opportunities | object[] | |
advice | object[] | |
reports | object[] | |
content | object[] | |
geo | object | questions |
Request AI tasks and review texts
- Access
- Session or API key with write access
- Who
- Owner or member; viewers and clients get 403.
AI worker: claim the next task
Note: this GET claims the task (sets it to running). For instnt's worker only.
- Access
- Session or API key (read or write)
- Who
- instnt platform admins only; others get 404 or 403.
Response
task | ?object | id, kind, prompt, schema, model |
AI worker: submit a result
- Access
- Session or API key with write access
- Who
- instnt platform admins only; others get 404 or 403.
Uptime and technical
Uptime checks, JavaScript errors, backups, maintenance, site checks, versions with known vulnerabilities and the cookie scan.
Uptime, errors, backups and maintenance
- Access
- Session or API key (read or write)
- Who
- Team; clients with access to the Website module.
Query parameters
project_id* | int | Project id. |
Response
monitors | object[] | 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 | object[] | id, message, source, line, col, page, browser, stack, occurrences, first_seen, last_seen, status, last_14_days |
error_key | ?string | |
snippet | ?string | |
script_tag | ?string | |
status_page | bool | |
alert_emails | ?string | |
backups | object[] | |
maintenance | object[] | |
can_manage | bool | |
suggested_url | ?url | |
Manage checks, status page, maintenance and backups
- Access
- Session or API key with write access
- Who
- Owner or member; viewers and clients get 403.
Site checks per host
Headers, exposed files, cookie flags, CMS, domain, DNSSEC and CAA, mail, tags, third parties, robots, AI crawlers and sitemap.
- Access
- Session or API key (read or write)
- Who
- Team; clients with access to the Website module.
Query parameters
project_id* | int | Project id. |
Response
hosts | object[] | host, checks |
Run site checks now
- Access
- Session or API key with write access
- Who
- Team; clients with access to the Website module.
Actions (action)
runproject_id*Re-runs the checks for the project's hosts right away, including the certificate of monitored addresses, and recomputes the security score. At most twice per five minutes per project; after that 429. Response: hosts.
Security score
Score 0–100 from six weighted parts (encryption, headers, exposure, software, mail and DNS, reputation), computed from the latest site check, certificates, vulnerabilities and Safe Browsing. Parts that were not measured do not count (their score is null); with fewer than two measured parts score itself is null. trend is the daily score of the last 30 days. domains tells per domain whether it is verified and how (dns or plugin); the TXT record is at /api/domains.
- Access
- Session or API key (read or write)
- Who
- Team; clients with access to the Website module.
Query parameters
project_id* | int | Project id. |
Response
score | ?int | |
previous | ?int | |
trend | object[] | day, score |
categories | object[] | key, label, weight, description, score (?int), points (status, label, detail) |
method | string | |
domains | object[] | domain, verified, via |
Recompute the security score
- Access
- Session or API key with write access
- Who
- Owner or member (manages Website); others get 404.
What runs on the site
Detected technology per category from the homepage and headers (CMS, shop, framework, analytics, ads, consent, payments, reviews, chat, hosting, fonts), what was added or removed in the last 90 days, detected services that are not connected yet, setup gaps and free suggestions. Rule-based; summary is an optional AI paragraph.
- Access
- Session or API key (read or write)
- Who
- Team; clients with access to the Website module.
Query parameters
project_id* | int | Project id. |
Response
hosts | string[] | |
checked_at | ?datetime | |
detected | object[] | category, label, items (tech, label, version, evidence, host, since, last_seen, connector, connected) |
changes | object[] | type (added|removed), label, host, at |
connect | object[] | tech, label, connector, url |
gaps | object[] | key, tone, title, detail, url, action |
suggestions | object[] | key, title, detail, url, action |
summary | ?object | status, text, at |
can_manage | bool | |
can_ai | bool | |
Scan again or request a summary
- Access
- Session or API key with write access
- Who
- Owner or member; viewers and clients get 403.
Versions and open vulnerabilities
- Access
- Session or API key (read or write)
- Who
- Team; clients with access to the Website module.
Query parameters
project_id* | int | Project id. |
Response
components | object[] | ecosystem, name, version, type, dev, active, reported_at |
reported | object | |
vulns | object[] | ecosystem, name, version, vuln_id, aliases, severity, summary, fixed_in, url, first_seen_at |
resolved_30d | int | |
wordfence | bool | |
Latest cookie scan with changes
- Access
- Session or API key (read or write)
- Who
- Team; clients with access to the Website module.
Query parameters
project_id* | int | Project id. |
Response
latest | ?object | |
last_error | ?object | |
findings | object[] | |
gone | string[] | |
has_previous | bool | |
history | object[] | |
can_scan | bool | |
Scan now
- Access
- Session or API key with write access
- Who
- Owner or member (manages Website); others get 404.
Server to server
Addresses for other systems: conversion events, deploys, lock files, MCP, incoming webhooks and the site script. Each has its own credential or a secret address.
Conversion event from your own backend
The project follows from the key. event_id is a UUID v4 and must equal the Idempotency-Key header; sending the same event again returns 200 with duplicate: true. At most 8 kB.
- Access
- The source's conversion key:
Authorization: Bearer <key> - Status
- 201
Headers
Idempotency-Key* | string | Equal to event_id. |
Body
event_id* | string | |
event* | website_visited | signup_started | account_created | email_verified | onboarding_completed | activated | subscription_started | payment_succeeded | subscription_canceled | |
occurred_at* | datetime | ISO 8601; no more than 5 minutes in the future. |
account_ref | string | UUID, not an email address. |
visitor_id | string | |
session_id | string | |
properties | object | source, plan, amount (as "25.00"), currency. |
attribution | object | landing_page, referrer, utm_source, utm_medium, utm_campaign, utm_term, utm_content, gclid, fbclid, msclkid, studio_ref. |
Example: Request
{
"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"
}
}
Example: Response
{
"ok": true,
"duplicate": false
}
Deploy on the timeline
The same commit twice is one event; only a new deploy starts automations.
- Access
- Deploy key:
Authorization: Bearer <key> - Status
- 201
Body
title | string | |
commit | string | |
url | url | |
Lock files for the vulnerability check
With a deploy key that belongs to a project. Each report replaces the previous set for that ecosystem. At most 5 MB in total.
- Access
- Deploy key:
Authorization: Bearer <key>
Body
files* | object | File name to contents: composer.lock, package-lock.json, Package.resolved, Cargo.lock. |
MCP server for Claude and other assistants
JSON-RPC 2.0 over HTTP (Streamable HTTP without SSE), read-only: initialize, ping, tools/list, tools/call. Tools: projecten, stand_van_project, adviezen, belangrijkste_acties, zoektermen. Any personal key works, including read or write. Connect with: claude mcp add --transport http studio https://instnt.studio/api/mcp --header "Authorization: Bearer <key>".
- Access
- Any personal API key (MCP, read or write)
Body
jsonrpc* | string | |
id | int | |
method* | string | |
params | object | |
Response
jsonrpc | string | |
id | int | |
result | object | |
error | object | |
POST/api/hooks/appstore/{token}App Store Connect notification (webhook)
With the header x-apple-signature: hmacsha256=<hex> (HMAC-SHA256 of the body with the secret). Studio then fetches the app again right away, at most once a minute per account. Wrong signature 401, unknown address 404.
- Access
- No sign-in; the secret is in the address
Incoming webhook for an automation
The address is the secret. Fields from the JSON body (one level deep, at most 50, up to 500 characters) become variables in the actions, such as {{klant}}. An unknown or disabled address returns 404.
- Access
- No sign-in; the secret is in the address
- Status
- 202
Form, booking, call tracking or GitHub as lead or timeline
With a secret Studio verifies the signature: Typeform-Signature, Calendly-Webhook-Signature, X-Hub-Signature-256 (GitHub) or else the X-Studio-Secret header. GitHub without a secret is refused.
- Access
- No sign-in; the secret is in the address
Body
… | object | The service's payload. |
Backup succeeded (ping)
GET or POST, so curl -fsS in a cron line is enough. With size in bytes Studio also spots a backup that is suddenly much smaller.
- Access
- No sign-in; the secret is in the address
Backup succeeded (ping)
- Access
- No sign-in; the secret is in the address
Approved titles to apply
For the WordPress or Drupal module.
- Access
- Write-back key:
Authorization: Bearer wb_…
Response
titles | object[] | id, url, title, description |
Titles applied
- Access
- Write-back key:
Authorization: Bearer wb_…
JavaScript error from the site script
The key is public (it is in the HTML). No personal data: no IP, no query strings. Always answers 204.
- Access
- No sign-in
- Status
- 204
Body
message* | string | |
source | string | |
line | int | |
col | int | |
stack | string | |
page | string | |
Web Vitals measurement from the site script
- Access
- No sign-in
- Status
- 204
Body
lcp | number | |
inp | number | |
cls | number | |
page | string | |
device | mobile | desktop | |
Form or lead click from the site script
Field names only, never what was entered. Or lead (telefoon, email, whatsapp) for a link click.
- Access
- No sign-in
- Status
- 204
Body
page | string | |
form | string | |
fields | string[] | |
submitted | bool | |
lead | telefoon | email | whatsapp | |
sr | string | |
Cookieless pageview
No cookies or storage; a visitor is recognisable for one day through a hash with a daily rotating salt. Bots don't count.
- Access
- No sign-in
- Status
- 204
Body
page* | string | |
ref | url | |
qref | string | Value of ?ref= or ?source=. |
utm_source | string | |
utm_medium | string | |
utm_campaign | string | |
gclid | string | |
sr | string | |
POST/api/site-events/{token}Receive a site event
Signed with the project secret: X-Studio-Timestamp (Unix time, at most 5 minutes off) and X-Studio-Signature = sha256=<hex hmac_sha256(secret, timestamp + "." + body)>. Studio may store and count data (per ref); private is only used while handling. With id a repeated event does not count twice. 502 when an action failed and Studio does not retry it itself: retry later.
- Access
- No sign-in
- Status
- 202
Body
event* | string | Lowercase, digits and . _ -, e.g. tester.signed_up. |
id | string | |
data | object | |
private | object | |
Cookie banner choice
From the Consent Mode update the banner passes to Google. One choice per visitor per day, using the same daily hash as pageviews; a later choice replaces the earlier one.
- Access
- No sign-in
- Status
- 204
Body
a | granted | denied | analytics_storage |
d | granted | denied | ad_storage |
GET/api/site-script/{key}.jsThe site script
Errors, Web Vitals, forms, leads and cookieless measurement in one file. Include <script src="…/api/site-script/<key>.js" defer></script>.
- Access
- No sign-in
The chat widget
Include <script src="…/api/chat-widget.js?p=<widget-token>" defer></script>. The widget only shows with the Chat module on and from an allowed domain.
- Access
- No sign-in
Query parameters
p* | string | Widget token from the chat settings. |
GET/api/chat-widget-home.jsThe chat widget start screen
Loaded by the widget itself when the project uses self-service, own links or other contact options.
- Access
- No sign-in
GET/api/chat-widget/{token}/beeld/{kind}Logo or team photo for the window
kind: logo (if the header shows the logo) or team-<id> (only with "first name with photo" and only for that project's team). Otherwise 404.
- Access
- No sign-in
POST/api/chat-widget/{token}The chat widget: visitor messages
For the widget itself. JSON as text/plain, so there is no preflight. Only with an Origin of a project domain (or an added origin); otherwise 404. visitor is a random id from the browser (20–64 characters); Studio stores only an HMAC of it and no IP address. The website field is a honeypot. At most 15 messages per minute per visitor and 10 new conversations per hour per IP.
- Access
- No sign-in
Body
action* | hallo | poll | stuur | gegevens | beoordeel | transcript | nieuw | vergeet | geschiedenis | gesprek | kies | koppel | bevestig | identificeer | uitloggen | |
visitor* | string | |
since | int | Only messages after this id. |
body | string | With stuur; at most 2,000 characters. |
name | string | |
email | email | |
page | url | |
title | string | |
typing | bool | |
rating | int | With beoordeel: 1–5, only after closing. |
website | string | Leave empty. |
topic | string | For a new conversation: a topic from the settings; becomes a tag. |
consent | bool | Agreed to the privacy statement, if the form asks for it. |
seen | int | With poll: the last message id the visitor saw in the open, visible window; for "Read" in the inbox. Never goes back. |
route | object[] | With the first stuur: the pages the visitor viewed in the last half hour (p = path, t = title, at = time in ms), at most ten; until then they stayed in their browser. |
proactive | string | The text of the proactive message the visitor replies to; only if it is in the rules. |
id | int | With gesprek: an earlier conversation of the same visitor. With kies: the message with the buttons. |
label | string | With kies: one of the buttons under that message; once per message, and is sent as the visitor's message. |
code | string | With bevestig: the eight digits from the email after koppel, only valid in the same browser (visitor), for fifteen minutes and once; five wrong attempts void it. This browser then belongs to the address. Until 11-10-2026 a link that linked the requester to whoever clicked. |
user_id | string | With identificeer: the id of the signed-in user on the site. |
signature | string | With identificeer: HMAC-SHA256 of user_id with the key from the chat settings, computed on the site's server. |
email_signature | string | With identificeer: HMAC-SHA256 of "user_id|address" (address lower-cased). Only then does email count as verified. uitloggen undoes this browser's link. |
file | file | With stuur as multipart (payload = the JSON above): image or PDF, at most 10 MB, ten per hour. |
selfhelp | object | For a new conversation: articles (ids the visitor read), searched, unhelpful (id of an article marked "No, didn't help"). Only published articles of this project count; the team sees it as a note. |
Response
enabled | bool | |
config | object | 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 | online | open | gesloten | |
conversation | ?object | 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 | object[] | id, from, body, at, name, files, buttons, choice, faq (id, title van een gepubliceerd artikel) |
history | object[] | With geschiedenis: id, at, last_at, status, ticket, preview. |
error | string | On 403: files_not_allowed when the team did not allow attachments. On 422: validation, email, unverified (transcript: confirm the address first with koppel/bevestig), code, file (with detail) or prechat (with field: name, email, topic or consent). |
Chat attachment
Only with the signed URL from files (expires and signature), valid for half an hour; otherwise 403. Images inline, a PDF as a download, always with nosniff.
- Access
- No sign-in
POST/api/chat-widget/{token}/faqThe chat widget: frequently asked questions
For the widget itself, with the same origin rules as chat-widget/{token}. Only published articles of that project; the page's language first, otherwise all. With the module or widget off enabled: false. At most 60 requests per minute per visitor.
- Access
- No sign-in
Body
action* | lijst | zoek | categorie | artikel | feedback | |
q | string | With zoek; at most 120 characters. Without results Studio keeps the term without the visitor, for 90 days (can be turned off). |
lang | nl | en | |
id | int | With artikel and feedback. |
name | string | With categorie. |
helpful | bool | With feedback: "Did this help?". One vote per article per day per IP hash. |
Response
enabled | bool | |
total | int | |
results | object[] | id, title, category, excerpt (bij lijst eerst de uitgelichte) |
categories | object[] | name, count (bij lijst) |
article | object | id, title, category, html, updated_at |
Sign up through a form on the client's site
JSON or a plain HTML form. Sends a confirmation email (double opt-in). The website field is a honeypot. At most 5 per minute per visitor.
- Access
- No sign-in
Body (JSON or an HTML form)
email* | email | |
naam | string | |
toestemming* | string | 1, on, true or ja. |
taal | nl | en | Language of the sign-up; without it, the form's language. |
website | string | Leave empty. |