API

Everything the app does, also through the API.

JSON over HTTPS, API keys with read or write scope and the same permissions as in the app. Generated from the same source the server checks its routes against, so it describes what is live.

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.

GET/api/me

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?objectid, email, name, is_admin, role, can_manage, is_client, two_factor
workspacesobject[]id, slug, name, role
featuresobject
modulesobjectPer module whether it is on for the workspace (plan and setting).
plan?objectkey, label, limits, usage, trial_ends_at, active, cancel_from, data_delete_on
approvals_openint
terms?objectalleen voor de eigenaar / owner only: version, required, deadline, blocking
start_page?string
viewed_by?object
google_connectbool
setup_requiredbool
google_loginbool
signup_openbool
brand?object
POST/api/login

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
clientappThe app only.
device_namestringName under Account → Devices; without one "iPhone van <first name>".
device_modelstringiPhone, iPad or Mac.

Response

two_factorbool
challengestring
tokenstringOnly with client: app, shown once.
device_namestring
POST/api/login/two-factor

Second 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

challengestringFrom the /api/login response; after Google it is in a cookie.
code*string

Response

token?string
device_name?string
GET/api/login/google

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
POST/api/login/app

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*stringWhose S256 hash the app sent at the start.

Response

tokenstring
device_namestring
GET/api/login/google/callback

Return from Google

Google sends the browser here. A small page sets the session and returns to the app.

Access
No sign-in
POST/api/logout

Sign out

Ends the session and clears the cookie.

Access
App session only, not with an API key
POST/api/setup

Create the first user

Only works while there are no users yet (installation); afterwards 403 already_installed.

Access
No sign-in

Body

email*email
namestring
password*stringAt least 10 characters.
POST/api/signup

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*stringAt least 10 characters.
partnerstringPartner code.
terms*boolAcceptance of the terms and data processing agreement; version and time are recorded.

Response

sentbool
POST/api/signup/confirm

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

Body

token*string
GET/api/invitation

View an invitation

Access
No sign-in

Query parameters

token*string

Response

emailemail
workspacestring
project?string
existing_userbool
POST/api/invitation

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
namestring
POST/api/password/forgot

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

Body

email*email
POST/api/password/reset

Set a new password

Ends all other sessions and starts a new one.

Access
No sign-in

Body

token*string
password*stringAt least 10 characters, at most 72 bytes, not from a known breach.
POST/api/password/change

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*stringAt least 10 characters, at most 72 bytes, not from a known breach.
POST/api/two-factor

Manage two-factor authentication

Access
App session only, not with an API key
Who
The signed-in user.

Actions (action)

  • status

    Response: enabled, required, enforced, has_password, recovery_codes_left.

  • setup

    New 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, code

    Response: recovery_codes.

    • password string · Required when you have a password.
    • code string · Required without a password.
GET/api/tokens

Your API keys

Access
App session only, not with an API key
Who
The signed-in user.

Response

tokensobject[]id, name, scope, last_used_at, created_at, archived_at, workspace_id, workspace
POST/api/tokens

Create or revoke an API key

Access
App session only, not with an API key
Who
The signed-in user.

Actions (action)

  • createname, scope

    The key only works in the workspace it was created in. An older key without a workspace picks one with the header X-Workspace: <id>. Subject to the plan's limits. Response: token.

    • scope mcp | read | write · Defaults to mcp.
  • deleteid*
GET/api/devices

Devices for push notifications

Access
Session or API key (read or write)
Who
The signed-in user.

Response

devicesobject[]id, environment, created_at, last_sent_at
POST/api/devices

Register or remove a push device

Access
Session or API key with write access
Who
The signed-in user.

Actions (action)

  • registertoken*, environment
    • token string · APNs device token, hex.
    • environment sandbox | production
  • removetoken*
POST/api/view-as

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
GET/api/profile

Your own account

Access
App session only, not with an API key
Who
The signed-in user.

Response

profileobjectname, email, timezone, avatar, has_password, google, created_at
pending_email?objectemail, expires_at
reauthpassword | code | google | noneHow you confirm your identity for a sensitive action.
notifyobject[]key, label, on
quiet_hours?objectQuiet hours for push: from and to, HH:MM in your own time zone.
sessionsobject[]key, kind (browser|app), device, network, via, created_at, last_used_at, last_used_label, current
workspacesobject[]id, name, role, suspended_at
delete_blockersstring[]Workspaces you own; while there are any, your account can't be deleted.
timezonesstring[]
POST/api/profile

Change your account

Access
App session only, not with an API key
Who
The signed-in user.

Actions (action)

  • profilename*, timezone
    • timezone ?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_delete
  • emailemail*, password, code

    Sends 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_cancel
  • notifyprefs*

    Response: prefs.

    • prefs object · Per kind on or off: alerts, anomalies, digest, automations. Invoices and security can't be turned off.
  • quiet_hoursfrom, to

    Push 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_others

    Response: revoked, sessions.

  • reauthpassword, code

    Confirms 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, code

    Anonymises 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.
POST/api/email/confirm

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

Body

token*string

Response

emailemail
POST/api/email/undo

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

Body

token*string

Response

emailemail

Workspace, team and billing

Who has access, invitations, branding, invoices and instnt's admin.

GET/api/access

Team, clients and invitations

Access
App session only, not with an API key
Who
Owner or member; viewers and clients get 403.

Query parameters

project_idintWith a project: that project's clients. Without: the team.

Response

teamobject[]id, email, name, role, last_login_at, two_factor, avatar, archived
clientsobject[]id, email, name, last_login_at, projects
require_two_factorbool
is_ownerbool
meint
peopleobject[]id, email, name, preset, permissions, last_login_at, since
invitationsobject[]id, email, role, preset, expires_at, created_at
presetsobject[]id, label, permissions
POST/api/access

Invite people and manage access

Access
App session only, not with an API key
Who
Owner or member; viewers and clients get 403.

Actions (action)

  • inviteemail*, role, project_id, preset

    Someone who already belongs to another agency can be invited too; they then switch between workspaces. Subject to the plan's limits. Response: invitation_id, link, mailed, granted.

    • role client | member | viewer · Defaults to client. Only the owner can invite members or viewers.
    • project_id int · Required for a client.
    • preset client_readonly | client_approver | client_limited
  • updateproject_id*, user_id*, preset*
    • preset client_readonly | client_approver | client_limited
  • removeproject_id*, user_id*

    The client loses access to this project.

  • revokeinvitation_id*
  • resendinvitation_id*

    New link (the old one stops working), valid for 14 days again. Response: link, mailed.

  • remove_memberuser_id*

    Removes someone from the workspace, with an email. The owner for team members; owner or member for clients.

  • change_roleuser_id*, role*

    Workspace owner only.

    • role member | viewer
  • transferuser_id*, password, code

    One owner per workspace: the new owner takes over, you become a member. Both get an email. Workspace owner only.

    • user_id int · A team member.
    • password string · Your password; without one (Google only) a code from the app, or sign in with Google again first.
  • require_two_factoron*

    Team members without two-factor can then only set it up. Enable it yourself first. Workspace owner only.

GET/api/workspace/export

Export all workspace data

A JSON file download. Also works with an owner's read key.

Access
App session only, not with an API key
Who
Workspace owner only.

Response

…objectAll workspace tables.
POST/api/workspace/delete

Delete the workspace

Requires the workspace name and your identity. 409 has_invoices while there are invoices (retention duty).

Access
App session only, not with an API key
Who
Workspace owner only.

Body

name*string
passwordstringYour password; without one (Google only) a code from the app, or sign in with Google again first.
codestring
POST/api/workspace/switch

Switch workspace

Applies to this session and is remembered for the next sign-in. Only a workspace you belong to.

Access
App session only, not with an API key
Who
The signed-in user.

Body

workspace_id*int

Response

workspace_idint
POST/api/workspace/create

New workspace

You become the owner. With a trial, unless you already had one as an owner; then you choose a plan straight away.

Access
App session only, not with an API key
Who
The signed-in user.

Body

name*string

Response

workspace_idint
trialbool
POST/api/workspace/rename

Rename the workspace

Owner only, not with an API key.

Access
App session only, not with an API key
Who
Workspace owner only.

Body

name*string

Response

namestring
GET/api/logboek

Workspace audit log

Who did what, two years back. With format=csv as a file (at most 10,000 rows).

Access
App session only, not with an API key
Who
Workspace owner only.

Query parameters

user_idint
grouptoegang | account | abonnement | werk | koppelingen | mail
fromdate
todate
pageint
formatcsv

Response

entriesobject[]id, at, action, label, subject, user, details
totalint
pageint
per_pageint
retention_daysint
groupsobject[]key, label
peopleobject[]id, name, email
GET/api/branding

Branding of the agency and a project

Access
Session or API key (read or write)
Who
Team only (owner, member or viewer); clients get 403.

Query parameters

project_idint

Response

workspaceobjectlogo, color, custom_domain, domain_status
project?objectlogo, color
POST/api/branding

Set branding and a custom domain

Access
Session or API key with write access
Who
Owner or member; viewers and clients get 403.

Actions (action)

  • saveproject_id, logo, color, remove_logo
    • project_id int · Without a project: the agency (owner only).
    • logo string · PNG, JPEG or WebP as base64 or data URL, at most 300 kB.
  • domaindomain

    Workspace owner only. Subject to the plan's limits. Response: domain, status, target.

    • domain string · A subdomain of your own domain; empty removes it.
  • domain_check

    Workspace owner only. Response: domain, status, target.

GET/api/billing

Subscription, billing details and invoices

Access
App session only, not with an API key
Who
Workspace owner only.

Response

details?objectname, address, postcode, city, country, vat_number, email, cc_email, reference
intervalstring
yearly_from?date
price?objectmonth, year, label
exemptbool
vat?objectverified, checked_at
paymentsobjectonline, mode (off, test, live, wrong)
mandateobjectactive, method (directdebit, creditcard), details (gemaskeerd / masked), status, methods
suspended?string
invoicesobject[]id, number, period, period_label, issued_on, due_on, gross_cents, refunded_cents, credited_cents, due_cents, status (open, paid, refunded, chargeback, credited, credit), last_payment_status, credit_of, credit_of_number, paid_at, pay_url
subscriptionobjectstate (proef, actief, opzegging, opgezegd, verlopen, geschorst, gepauzeerd), plan, label, interval, trial_ends_at, paid_until, term, cancel_from, pending, data_delete_on, data_purged_at, pause (?object: since, until, cancelled), pause_blocked (?string), pause_max_months
plansobject[]key, label, price, price_year, price_next (?object: from, price, price_year), pitch, limits, ads_modes, white_label, over (wat niet past / what does not fit)
usageobject
addonsobject[]key, label, price (euro per maand per stuk / euro per month each), limit, amount, quantity, available
archivedobjectprojects, team, keywords, dashboards, api_tokens, automations
upcomingobject[]date, period_label, lines, net_cents, vat_cents, gross_cents
historyobject[]id, text, kind, pending, note, created_at
termsobjectversion, accepted_version, accepted_at, required, deadline, blocking, terms_url, dpa_url
has_passwordbool
POST/api/billing

Change or cancel the subscription, billing details

Larger plan: immediately, per day or the difference for the rest of the year. Smaller plan or back to monthly: after the paid period. A smaller plan, cancelling and pausing require re-authentication: password, or without a password a code from the authenticator or a fresh Google login (at most ten minutes old).

Access
App session only, not with an API key
Who
Workspace owner only.

Actions (action)

  • detailsname*, address*, postcode*, city*, country, vat_number, email*, cc_email, reference

    Response: vat, message.

    • country string · Country code, defaults to NL.
    • vat_number string · Outside NL within the EU checked with VIES; only then is VAT reverse-charged.
    • cc_email email · Receives a copy of every invoice and reminder.
    • reference string · Own reference (purchase order) on the invoice.
  • yearly

    Pay yearly from the first of next month. Response: yearly_from, message.

  • previewplan*, interval*

    What would happen, without changing anything. Response: preview.

    • plan solo | inzicht | copiloot | begeleid
    • interval maand | jaar
  • changeplan*, interval*, archive, password, code

    Response: message, effective_from.

    • plan solo | inzicht | copiloot | begeleid
    • interval maand | jaar
    • archive object · Per kind the ids to set aside (projects, team, clients, api_tokens, automations, keywords:<project>, dashboards:<project>).
    • password string · For a smaller plan: your password, or without one a code from the app (or sign in with Google again first).
  • cancelpassword, code

    Cancel at the end of the paid period. Response: ends_on, message.

    • password string · Your password, or without one a code from the app (or sign in with Google again first).
  • resume

    Withdraw a cancellation that has not taken effect. Response: message.

  • withdraw

    Withdraw a scheduled change (smaller plan, other billing interval); everything stays as it is. Not for a cancellation, a pause or a change made by the admin. Response: message.

  • restorekind*, id*

    Restore something that was set aside, if the plan has room. Response: message.

    • kind projects | team | keywords | dashboards | api_tokens | automations
  • terms

    Accept the current terms and data processing agreement. Response: terms.

  • mandate_setupmethod*

    Automatic payment: a first payment at Mollie creates a mandate. With an open invoice that is the first payment; otherwise € 0.00 (credit card) or € 0.01 that is refunded immediately. Response: checkout_url.

    • method ideal | bancontact | creditcard
  • mandate_revoke

    Turn off automatic payment; invoices come with a pay link again. Response: message.

  • pausemonths*, password

    Pause from today: no charges, read-only, no background work. Monthly billing only, once per twelve months. Response: until, message.

    • months int · 1 to 3.
    • password string · Or code / a fresh Google login, see re-authentication.
  • end_pause

    End the pause now; the subscription resumes today. Response: message.

  • addonaddon*, quantity*

    Extra room on top of the plan, billed per day on the monthly invoice from today. Lowering only if everything still fits. Response: message, addons.

    • addon string · Key from addons.
    • quantity int · 0 to 20; 0 removes it.
GET/api/billing/pdf

Invoice as PDF

Access
App session only, not with an API key
Who
Workspace owner only.

Query parameters

id*int
GET/api/partner

Partner programme: code, referred agencies and commission

Access
App session only, not with an API key
Who
Workspace owner only.

Response

partner?objectcode, commission_pct, discount_pct, active, link, referred, commission
GET/api/werkwijzen

The team's own standards

Access
Session or API key (read or write)
Who
Team only (owner, member or viewer); clients get 403.

Query parameters

slugstringOne standard as HTML.

Response

standardsobject[]
standardobject
GET/api/admin

Admin: workspaces, users, queue, plans

Access
App session only, not with an API key
Who
instnt platform admins only; others get 404 or 403.

Response

workspacesobject[]
usersobject[]
queueobjectpending, oldest, failed
tablesobject[]
flagsobject
plansobject
backup?object
pleskobject
partnersobject[]
GET/api/admin/invoices

Admin: all invoices and credit notes

Access
App session only, not with an API key
Who
instnt platform admins only; others get 404 or 403.

Query parameters

statusstringopen, paid, credit, … or te_laat (overdue).
periodstringyyyy or yyyy-mm (invoice date).
workspace_idint
qstring

Response

invoicesobject[]
totalsobjectcount, net_cents, vat_cents, gross_cents, open_cents, late_cents
workspacesobject[]
GET/api/admin/invoice/pdf

Admin: invoice or credit note as PDF

Access
App session only, not with an API key
Who
instnt platform admins only; others get 404 or 403.

Query parameters

id*int
GET/api/admin/export

Admin: CSV for bookkeeping, EC sales list, partner payout

Access
App session only, not with an API key
Who
instnt platform admins only; others get 404 or 403.

Query parameters

kind*invoices | icp | payout
fromdate
todate
quarterstringAs 2026-Q3.
idintPayout.
POST/api/admin

Admin actions

Access
App session only, not with an API key
Who
instnt platform admins only; others get 404 or 403.

Actions (action)

  • featureworkspace_id*, feature*, state*
    • state aan | uit | standaard
  • retryid*
    • id int · Failed job.
  • forgetid*
  • planworkspace_id*, plan*, trial_days
  • intervalworkspace_id*, interval*, from
    • interval maand | jaar
    • from date · The first of a month.
  • trial_extendworkspace_id*, days

    Response: trial_ends_at.

    • days int · 1–90, default 7; from the current end date.
  • data_holdworkspace_id*, until
    • until ?date · Postpone the clean-up until this date; empty lifts it.
  • partnerworkspace_id*, code*, commission_pct, discount_pct, active
  • commission_paidinvoice_id*

    Response: updated.

  • mark_paidinvoice_id*, paid_on, reference

    Paid by bank transfer; lifts a suspension.

    • paid_on date · Between invoice date and today.
  • creditinvoice_id*, amount_cents, reason*, refund

    Response: number, gross_cents.

    • amount_cents int · Excluding VAT; empty credits the whole invoice.
    • refund bool · Also refund through Mollie.
  • remindinvoice_id*
  • discountworkspace_id*, kind*, value*, months, note*, starts_on
    • kind pct | fixed
    • value int · Percent (1–100) or cents per invoice.
  • discount_endid*
  • close_workspaceworkspace_id*, reason
  • unsuspendworkspace_id*
  • end_pauseworkspace_id*

    End a pause; the customer gets an email.

  • price_scheduleplan*, price*, price_year*, from*

    Response: announced.

    • from date · At least 30 days ahead; paying customers on that plan get an email.
  • price_cancelid*
  • partner_payout_infoworkspace_id*, name, iban
  • payout

    All open commission of paid invoices in one payout. Response: id.

  • payout_paidid*
  • plesk_addurl*, api_key*, name

    Response: id, domains, error.

  • plesk_checkid*

    Response: domains.

  • plesk_removeid*

Projects and overview

Projects, the cross-client overviews, dashboards, goals, the timeline and hours.

GET/api/projects

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

projectsobject[]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
templatesobject

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": {}
}
POST/api/projects

Create, edit and organise projects

Access
Session or API key with write access
Who
Owner or member; viewers and clients get 403.

Actions (action)

  • createname*, template*

    Subject to the plan's limits. Response: project_id.

    • template webshop | saas | lokaal | b2b | content · Required since 2026-10-06: the overview picks its key figures by project type.
  • renameproject_id*, name*
  • updateproject_id*, name*, color*, conversion_value, template, brand_terms, website

    Response: website.

    • color string · As #rrggbb.
    • brand_terms string · Comma-separated.
    • website string · Site address; empty clears it. A different domain moves uptime checks and site checks along.
  • deleteproject_id*

    Sources remain and become unassigned.

  • assignproperty_id*, project_id
    • property_id int · GA4 property.
  • rename_propertyproperty_id*, name
    • name string · Empty restores the name from Google.
GET/api/glance

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

projectsobject[]id, name, monitored, down, uptime_30d, live, visitors_today, visitors_yesterday, leads_today, open_advice, open_questions
totalsobjectsites_total, sites_up, uptime_30d, visitors_today, visitors_yesterday, leads_today, open_advice, last_deploy, approvals
live?object[]project, live
live_total?int
downobject[]project, url, since
open_questions?int
new_adviceint
proposalsobject[]
studiourl
POST/api/extension/connect

Create 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.

Response

tokenstring
studiourl
GET/api/extension/sites

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

projectsobject[]id, name, domains
studiourl
GET/api/extension/site

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.

Query parameters

url*url

Response

project?objectid, name, link
visitors_today?int
visitors_yesterday?int
uptimeobjectmonitored, down, uptime_30d
security_score?objectscore, previous
open_advice?int
last_deploy?objecttitle, at
refs_todayobject[]ref, visitors
GET/api/extension/post

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*urlLink to a post on Reddit, Hacker News, Bluesky or Mastodon.

Response

platformstring
followedobject[]id, project (id, name), ref, score, comments, last_checked_at, last_error
projectsobject[]id, name; waar je hem kunt volgen
POST/api/extension/post

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.

Actions (action)

  • snapshoturl*, score*, comments*, title, author

    404 when nobody in this workspace follows the post. Response: updated.

  • followurl*, project_id*, ref, score, comments, title, author

    Response: id, updated.

GET/api/runtime

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

cvestringA CVE, e.g. CVE-2026-1234: vulnerabilities Studio already found plus the affected versions from the NVD.
productphp | nginx | apache | litespeed | mysql | mariadb | postgresql | wordpress | drupal
belowstring
fromstring

Response

projectsobject[]project_id, project, items (per product: label, version, source site|header|plesk, detail, state ok|update|eol|onbekend, cycle, latest, eol), vulnerabilities (serious, total)
productsobject
checked_at?string
lookupobjectcve, summary, severity, ranges, projects (project_id, project, product, version, certain, fixed_in, resolved), source nvd|studio|onbekend
POST/api/runtime

Check versions now

Access
Session or API key with write access
Who
Owner or member.

Actions (action)

  • check

    Fetches the releases, takes over what headers and Plesk know and checks plugins and packages for vulnerabilities in the background. At most once a minute. Response: projects.

GET/api/tech-overview

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

kpisobjectprojects, 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)
sourcesobject[]bronnen met status error, stale of unknown, met project_name (zie GET /api/inventory)
projectsobject[]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
appsobject[]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": []
}
GET/api/source-catalog

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

recommendedobjectsoort → object[]: project_id, project, host, label
capabilitiesobjectsoort → object[]: key, label, needs, why, write
GET/api/app-downloads

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.

Query parameters

project_id*int

Response

appsobject[]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/total

Downloads 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_archivedboolAlso count archived apps; by default per the workspace setting.

Response

appsint
total?int
d7?int
d30?int
prev30?int
archived_excludedint
include_archivedbool
GET/api/project-overview

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
days7 | 28 | 90Defaults to 28.

Response

type?string
suggested?objecttype, reason
has_appbool
daysint
typesobject
can_managebool
attentionobjectitems (key, tone, text, tab), actions (id, title), checked_at
kpisobject[]key, label, value, previous, unit (count|pct|eur|ratio|stars|text), series, tone, hint, invert, of missing en connect (label, kind, tab of href)
trendobjectvisitors, 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"
      }
    }
  ]
}
GET/api/work

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

assigneestringme or a user id.

Response

columnsobjectopen, planned, done
workloadobject[]project_id, name, open, planned, overdue, done_30
teamobject[]
meint
todaydate
healthobject[]
GET/api/portfolio

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

days7 | 28 | 90Defaults to 28.

Response

projectsobject[]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
kpisobjectprojects, attention, visitors, downloads_7d, open_advice
unassigned_sourcesint
templatesobject
daysint
GET/api/portfolio-trend

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

days7 | 28 | 90Defaults to 28.

Response

daysint
metricsobjectvisitors, conversions, revenue — elk null of { unit, total, previous, series (day, value), by_project (id, name, color, value) }
GET/api/benchmarks

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_idint
period28 | 90Defaults to 28.
scopewerkruimte | gedeeldDefaults to werkruimte.
groupstringKey from groups, e.g. soort:webshop or tech:drupal. Without: the most specific group with the most usable metrics.

Response

periodint
scopestring
groupstring
groupsobject[]key, label, usable
metricsobject[]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
settingsobjectOnly without project_id: share, show_clients.
computed_at?string
hiddenbool
POST/api/benchmarks

Configure benchmarks

Access
Session or API key with write access
Who
Owner or member; viewers and clients get 403.

Actions (action)

  • settingsshare, show_clients

    Response: 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.
GET/api/report-overview

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

periodstringA closed month like 2026-09; defaults to last month.

Response

periodstring
labelstring
periodsobject[]period, label
rowsobject[]project_id, project, color, clients, tags, report_id, status, errors, generated_at, published_at, views, first_viewed_at
countsobjectontbreekt, concept, klaar, verstuurd, geopend
can_managebool
POST/api/report-overview

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_missingperiod

    A draft for every project without a report, in the background (202). Response: queued, tasks.

  • publish_readyperiod, ids

    Only 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.
GET/api/today

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

itemsobject[]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")
groupsobject
countsobjectbad, 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
  }
}
GET/api/tags

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_idintOnly this project.
hiddenboolAlso switched-off automatic tags.

Response

tagsobject[]id, project_id, kind (platform|tech|own), slug, key, label, color, auto, hidden, origin, origin_at
POST/api/tags

Add, switch off and re-detect tags

Access
Session or API key with write access
Who
Owner or member; viewers and clients get 403.

Actions (action)

  • addproject_id*, label*, color

    Response: tag.

    • label string · At most 40 characters.
    • color string · As #rrggbb.
  • removetag_id*

    An own tag is deleted; an automatic tag is switched off and does not come back on the next detection.

  • restoretag_id*

    Response: tag.

  • detectproject_id

    Response: tags.

    • project_id int · Without: all projects.
GET/api/views

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

viewsobject[]id, name, filters (client, type, tags, attention)
POST/api/views

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_id

    Response: 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*
GET/api/preferences

Your personal preferences

Access
Session or API key (read or write)
Who
Team only (owner, member or viewer); clients get 403.

Response

start_page?stringje eigen keuze, null is de standaard
start_page_defaultstring
optionsobject
POST/api/preferences

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_page

    Null 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.

    • locale nl | en
  • 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.
GET/api/portal

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

monthstring
days_so_farint
projectsobject[]id, name, numbers, series (day, value: bezoeken per dag deze maand), goals, done, next, report, weekly_update
POST/api/portal

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.

GET/api/notifications

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

countboolOnly the unread count.

Response

itemsobject[]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
unreadint
kindsobject
POST/api/notifications

Mark notifications as read

Access
Session or API key with write access
Who
Everyone in the workspace; a client only sees their own projects.

Actions (action)

  • readkeys*

    Response: unread.

    • keys string[] · Keys from items[].key, at most 200.
  • read_all

    Everything currently in the bell; anything after that is new again. Response: marked, unread.

GET/api/start-checklist

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?objectsteps (object[]: key, done, title, why, to, action), done (int), total (int), complete (bool), hidden (bool)
POST/api/start-checklist

Hide or show the start checklist

Access
Session or API key with write access
Who
Owner and team members.

Actions (action)

  • hide

    Per person and per workspace. Response: checklist.

  • show

    Response: checklist.

GET/api/task

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.

Query parameters

id*string

Response

statusqueued | running | done | failed
result?object
error?string
GET/api/inventory

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_idintOnly this project's sources; then without projects.

Response

itemsobject[]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)
projectsobject[]id, name, color, sources, problems, unchecked, clients, open_advice, monitors_down, latest_report
countsobjecterror, waiting, ok
POST/api/inventory

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.
GET/api/discovery

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

newobject[]key, type (ga|search|apple|gbp|plesk), ref, name, detail, project_id, project_name, state, decided_at, data_deleted, suggestion {name, template}
ignoredobject[]
archivedobject[]
linkedobject[]
archived_projectsobject[]id, name, archived_at
hiddenint
notifyint
settingsobjectmodes {ga, search, apple, gbp, plesk: melden|stil|verbergen}, include_archived
can_managebool
projectsobject[]id, name
templatesobject[]key, label
POST/api/discovery

Link, ignore, archive or restore

Access
Session or API key with write access
Who
Owner or member; viewers and clients get 403.

Actions (action)

  • linkkey*, project_id*
  • new_projectkey*, name*, template*

    Response: project_id.

  • ignorekeys*

    Response: count.

  • archivekeys*, delete_data

    Studio then fetches nothing and leaves the source out of totals. A linked Analytics or Search Console source is detached from its project (remembered for restoring); a linked app or location stays attached. Response: count.

    • delete_data bool · Also delete the fetched data; kept by default.
  • restorekeys*

    Response: count.

  • settingsmodes, include_archived

    Response: settings.

  • search_locations

    Response: found.

GET/api/capabilities

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*stringapple, google, integration, slack or chat.
subject_id*intId of the Apple account, Google connection, project integration, workspace (slack) or channel.

Response

typestring
namestring
itemsobject[]cap, label, needs, why, write, enabled, have (ja|nee|onbekend), detail, state (aan|uit|niet mogelijk|niet gemeten)
measured_at?string
warningsstring[]
fix?objectWhere to lower the rights: steps, links (label, url), copy (label, value).
keysobject[]key_id, role, role_label, account_key, allowed (alleen Apple)
minimal?string
can_managebool
POST/api/capabilities

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.

Actions (action)

  • togglesubject_type*, subject_id*, cap*, enabled*

    Response: items.

  • measuresubject_type*, subject_id*

    Read-only requests to the service; a capability that would change something is never tried. At most once a minute (429). Response: items.

GET/api/dashboards

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

dashboardsobject[]id, name, goal, project_id, project_name, tiles (aantal), scope
can_editbool
limit?int
workspace_countint
GET/api/dashboard

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_idintEmpty for a dashboard across projects.
dashboard_idintDefaults to the first.

Response

dashboardsobject[]id, name, goal
currentobjectid, name, goal
tilesobject[]
chosenstring[]
catalogobject
goalsobject
can_editbool
limit?int
POST/api/dashboard

Create, edit and delete dashboards

Access
Session or API key with write access
Who
Owner or member; viewers and clients get 403.

Actions (action)

  • createproject_id, goal, name

    Subject to the plan's limits. Response: id.

    • project_id int · Empty: a dashboard across projects.
    • goal string · A goal from goals; defaults to custom.
  • savedashboard_id*, tiles, name, scope
    • tiles json · At most twelve, from catalog; across projects also {key, project_id} for one project.
    • scope object · Across projects only: {tags: ["platform:ios"], project_ids: [3]}; empty means all projects.
  • deletedashboard_id*

    A project keeps its last dashboard.

GET/api/goals

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*intProject id.

Response

goalsobject[]metric, label, target, value, projected, status
metricsobject
can_managebool
suggested?object
forecast?object
languages?object
benchmark?object
signals?object
POST/api/goals

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 | clicks
    • target int · At least 1.
  • deleteproject_id*, metric*

    Response: goals.

    • metric sessions | key_events | new_users | clicks
GET/api/annotations

Project timeline

Access
Session or API key (read or write)
Who
Team; clients with access to the Overview module.

Query parameters

project_id*intProject id.
daysint1 to 800; defaults to 28.

Response

annotationsobject[]id, kind, title, detail, url, happened_at
can_managebool
POST/api/annotations

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, url
    • project_id ?int · Null: for all projects.
    • kind notitie | google | meting | deploy
  • deleteid*
  • deploy_tokenproject_id

    Response: token, url.

GET/api/checklist

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*intProject id.

Response

sectionsobject[]
can_managebool
POST/api/checklist

Tick off a checklist item or recheck

Access
Session or API key with write access
Who
Owner or member; viewers and clients get 403.

Actions (action)

  • setproject_id*, key*, state, note

    Response: sections.

    • state ?done | na · Null resets the item.
  • recheckproject_id*

    Status 202. Response: task_id.

GET/api/hours

Hour budget per client

Access
Session or API key (read or write)
Who
Team only (owner, member or viewer); clients get 403.

Query parameters

monthmonthDefaults to this month.

Response

monthmonth
projectsobject[]project_id, name, budget, spent, pace
entriesobject[]id, project_id, project, day, minutes, note, user, advice
can_managebool
POST/api/hours

Log hours and set budgets

Access
Session or API key with write access
Who
Team only (owner, member or viewer); clients get 403.

Actions (action)

  • budgetproject_id*, hours

    Workspace owner only.

    • hours ?number · Per month; empty means no agreement.
  • logproject_id*, day, minutes*, note, recommendation_id

    Status 201. Response: id.

    • day date · Not in the future.
    • minutes int · 1 to 1440.
  • deleteid*

    Your own hours, or as owner anyone's.

GET/api/page-insight

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.

Query parameters

url*url

Response

project?objectid, name
pathstring
crawl?object
queriesobject[]
adviceobject[]
speed?object
linkurl
GET/api/domains

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*intProject id.

Response

domainsobject[]id, domain, record, verified, via (dns|plugin), plugin, primary, source (auto|manual), verified_at, checked_at
POST/api/domains

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*, move

    Response: website, domains.

    • move bool · Default true: uptime checks move along and the old main domain is removed.
GET/api/mail-funnels

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_idint
days7 | 30 | 90

Response

daysint
funnelsobject[]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)
GET/api/social-posts

Followed social media posts

Access
Session or API key (read or write)
Who
Anyone who may view the project website.

Query parameters

project_id*intProject id.

Response

postsobject[]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_managebool
POST/api/social-posts

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*, ref

    Response: id, error.

    • url url · Link to a post on Reddit, Hacker News, Bluesky or Mastodon.
  • updateid*, ref
  • refreshid*
  • deleteid*
GET/api/site-events

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*intProject id.
statusok | opnieuw | dubbel | mislukt | geweigerd | ongeldig
entryintOne log entry, with runs_detail (automation, filters, actions).

Response

logobject[]id, event, event_id, data, private_keys (alleen namen), status, reason, http_status, runs, duration_ms, received_at; de laatste 100
hook?objectreceived, last_at, created_at
eventsobject[]event, total, refs (ref, n), days (day, n); 30 dagen
automationsobject[]id, name, enabled, event
retryingint
can_managebool
POST/api/site-events

Create or remove the site events address

Access
Session or API key with write access
Who
Owner or member; viewers and clients get 403.

Actions (action)

  • createproject_id*

    A new address replaces the old one. The secret is shown once. Response: url, secret.

  • deleteproject_id*
GET/api/project-tips

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*intProject id.
allboolInclude dismissed ones.

Response

tipsobject[]key, source (basis|gezien|soortgelijk), title, why, action {label, to}, peers (?object: count, total, template), dismissed
POST/api/project-tips

Dismiss or restore a tip

Access
Session or API key with write access
Who
Team only (owner, member or viewer); clients get 403.

Actions (action)

  • dismissproject_id*, key*

    For the whole team. Response: tips.

  • restoreproject_id*, key*

    Response: tips.

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.

GET/api/connections

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

connectionsobject[]id, kind, google_email, status, own_key, usable, created_at, properties
POST/api/connections

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*
  • refresh

    Clears the workspace caches, for example after granting new Analytics access.

  • deleteconnection_id*
GET/api/connections/google

Start 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/callback

Return 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*intAn integration of kind teamleader or microsoft_ads, created first with POST /api/integrations.
GET/api/connections/oauth/{provider}/callback

Return from Teamleader or Microsoft after connecting

Access
No sign-in
GET/api/search-console

Search Console properties

Access
Session or API key (read or write)
Who
Team only (owner, member or viewer); clients get 403.

Response

sitesobject[]id, project_id, connection_id, site_url, display_name, status
POST/api/search-console

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_name
  • assignsite_id*, project_id
  • deletesite_id*
GET/api/sources

Own systems (instnt-metrics)

Access
Session or API key (read or write)
Who
Team only (owner, member or viewer); clients get 403.

Response

sourcesobject[]id, project_id, name, url, status
POST/api/sources

Connect or change an own system

Access
Session or API key with write access
Who
Owner or member; viewers and clients get 403.

Actions (action)

  • createname*, url*, token*, project_id

    Tested against the instnt-metrics contract immediately; 422 source_rejected with the reason when it fails. Response: source_id, preview.

    • url url · https; http only for localhost.
  • updatesource_id*, name*, url, token
    • token string · Empty keeps the current token.
  • assignsource_id*, project_id
  • deletesource_id*
GET/api/integrations

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*intProject id.

Response

integrationsobject[]id, project_id, kind, name, status, config, oauth
POST/api/integrations

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*, name

    Response: 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-accounts

Apple 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

accountsobject[]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)
projectsobject[]id, name
POST/api/appstore-accounts

Add 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, name

    Tests 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_key
    • issuer_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_id

    An 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_ids

    Requests 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-accounts

Google 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

accountsobject[]id, name, client_email, bucket, status, status_message, checked_at, apps (package_name, title, installs_total, installs_30d, project_id, project_name, state)
projectsobject[]id, name
can_managebool
POST/api/google-play-accounts

Add 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, name

    Tests 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, key
    • key 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_id

    An 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.

GET/api/google-play

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.

Query parameters

project_id*int

Response

appsobject[]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
GET/api/app-store

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.

Query parameters

project_id*int

Response

appsobject[]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_replybool
teambool
POST/api/app-store

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.

GET/api/modules

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.

Query parameters

project_idint

Response

modulesobject[]key, label, uitleg, icon, min_plan, needs_label, scope, plan_allows, workspace_on, project_on, needs_met, projects_ready, status
can_managebool
POST/api/modules

Turn a module on or off

Access
Session or API key with write access
Who
Owner or member; viewers and clients get 403.

Actions (action)

  • workspacemodule*, enabled*

    402 plan_limit when the module is not in the plan. Response: modules.

  • projectproject_id*, module*, enabled*

    A project can only turn a module off; on follows the workspace. Response: modules.

GET/api/orders

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_idint
scopetoday
daysint
statusopen | betaald | verzonden | afgerond | geannuleerd | terugbetaald | mislukt
qstring

Response

ordersobject[]id, source, number, ordered_at, status, total_cents, currency, items (name, qty), admin_url
countsobject
soldint
total_centsint
module?object
synced_at?datetime
projectsobject[]Only with scope=today: project_id, name, count, total_cents, currency, latest.
POST/api/orders

Fetch orders now

Access
Session or API key with write access
Who
Owner or member; viewers and clients get 403.

Actions (action)

  • refreshproject_id*

    Response: orders, errors.

GET/api/landing-pages

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*intProject id.
daysintPeriod in days, 7–365; defaults to 28.
page_idint

Response

pagesobject[]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
testsobject[]id, name, page_a_id, page_b_id, started_on, ended_on, prob_b_better, min_sessions, verdict
suggestionsobject[]path, sessions, key_events
campaignsobject[]id, name, channel
moduleobject
can_managebool
moneybool
base_url?url
pageobjectOnly with page_id: the page with channels, queries and series.
POST/api/landing-pages

Designate and compare landing pages

Access
Session or API key with write access
Who
Owner or member (manages Website); others get 404.

Actions (action)

  • createproject_id*, url*, name, status, utm_campaign, ads_campaign_ids

    Status 201. Response: id.

    • url string · Path (/offerte) or full address on the project site.
    • status live | concept | gestopt
  • updateproject_id*, page_id*, name, status, utm_campaign, ads_campaign_ids
    • status live | concept | gestopt
  • deleteproject_id*, page_id*
  • test_createproject_id*, page_a_id*, page_b_id*, name

    Status 201. Response: id.

  • test_endproject_id*, test_id*
  • test_deleteproject_id*, test_id*
GET/api/submissions

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_idint
scopenew
daysintPeriod in days, 1–396; defaults to 30.
formstring

Response

submissionsobject[]id, source, source_label, form, page, submitted_at, new, admin_url
formsobject[]form, count, latest_at
totalint
unreadint
can_openbool
moduleobject
projectsobject[]Only with scope=new: project_id, name, count, last_id, latest_at.
POST/api/submissions

Mark submissions as seen

Access
Session or API key with write access
Who
Team; clients with access to the Website module.

Actions (action)

  • seenproject_id*

    Per user: everything so far in this project no longer counts as new. Response: seen_id.

GET/api/reputation

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_idint
sourcegbp | trustpilot | kiyoh | appstore | google_play
ratingintOnly this number of stars, 1–5.
openboolOnly without a reply.

Response

summaryobjectaverage, count, new_this_month, answered_pct, open_low, stored
sourcesobject[]source, label, average, count, stored, platform, can_reply
trendobject[]month, count, average
itemsobject[]id, source, source_label, rating, score, title, body, author, language, country, url, reviewed_at, reply, can_reply, suggestion
can_replybool
teambool
projectsobject[]Only without project_id: project_id, project, sources, average, count, new_this_month, answered_pct, open_low.
POST/api/reputation

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.

GET/api/campaigns

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_idint
campaign_idint

Response

campaignsobject[]id, project_id, name, starts_on, ends_on, budget, goal, rules, period, current, previous, derived, mail
suggestionsobject[]UTM campaigns without a campaign (90 days): value, sessions, sources. Manage rights only.
ignoredstring[]
linkablesobject[]What you can link as a rule: kind, value, label.
moduleobject
moneybool
can_managebool
base_url?string
campaignobjectWith campaign_id.
projectsobject[]Without project_id: project_id, name, campaigns.
POST/api/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.

Actions (action)

  • createproject_id*, name*, starts_on, ends_on, budget, goal, rules

    The first campaign of a project fetches the GA4 figures per campaign right away (half a year back). Response: id.

    • budget ?number · In euros.
    • rules object[] · kind (utm_campaign|utm_source|utm_medium|google_ads|meta_ads|linkedin_ads|mail), match (exact|prefix|contains, UTM only), value. An ad campaign or mailing must belong to the project. At most 30.
  • updateproject_id*, campaign_id*, name, starts_on, ends_on, budget, goal, rules
    • rules object[] · Replaces all rules.
  • deleteproject_id*, campaign_id*
  • ignoreproject_id*, value*

    Stop suggesting this UTM campaign.

  • unignoreproject_id*, value*
GET/api/journey

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*intProject id.
periodint28 or 90; defaults to 28.

Response

moduleobject
can_managebool
journey?objecttype, type_label, period, range, stages, trend, channels, paths, ttc, sources, custom, stage_labels, computed_at, k
POST/api/journey

Configure the customer journey

Access
Session or API key with write access
Who
Owner or member (manages Website); others get 404.

Actions (action)

  • settingsproject_id*, stages

    Response: stages.

    • stages ?object · Per stage (bezoek, betrokken, lead, klant) a list of sources from sources; null restores the default for the project type.
  • recomputeproject_id*

    Queue a recount; at most once every five minutes (429 too_soon). Response: queued.

GET/api/traffic

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*intProject id.
viewai | search
daysint7, 28 or 90; defaults to 28.

Response

daysint
source?stringOnly with ai: ga4, script or null.
unitstring
currentint
previousint
seriesobject[]day, value (ai) of day, clicks, sessions (search)
sourcesobject[]key, value, previous
has_searchbool
has_gabool
search_until?date
ga_until?dateLast day with GA4 figures; after it sessions: null.
totalsobjectclicks, sessions, ratio
GET/api/not-found

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*intProject id.
statusnieuw | opgelost | genegeerd

Response

statusstring
countsobjectnieuw, opgelost, genegeerd
pagesobject[]id, path, status, hits, sources, referrers, first_seen, last_seen, resolved_at
settingsobjecttitles, paths, min_hits
can_managebool
POST/api/not-found

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_hits

    Response: 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/extra-sources

Metrics from the extra services

With a 30-day history. Money, deals and errors (Moneybird, Sentry, shops, CRM, ads, App Store Connect) only for the team or clients with approval rights. analytics only appears for App Store Connect: whether App Analytics has been requested.

Access
Session or API key (read or write)
Who
Team; clients with access to the Website module.

Query parameters

project_id*intProject id.

Response

can_managebool
sourcesobject[]id, kind, name, status, metrics, items, analytics
GET/api/conversion-sources

Conversion event sources

Access
Session or API key (read or write)
Who
Team only (owner, member or viewer); clients get 403.

Query parameters

project_id*intProject id.

Response

sourcesobject[]id, app_source_id, name, retention_days
POST/api/conversion-sources

Create a conversion key

Access
Session or API key with write access
Who
Owner or member; viewers and clients get 403.

Actions (action)

  • createapp_source_id*

    409 already_exists when the source already has a key. Status 201. Response: app_source_id, token, webhook_url.

GET/api/inbound

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*intProject id.

Response

hooksobject[]id, provider, label, signed, received, last_at, url
providersobject
POST/api/inbound

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*, secret

    Status 201.

    • provider typeform | calendly | gravityforms | overig | github | belmeting
    • secret string · To verify the signature; required for GitHub.
  • deleteid*
GET/api/clarity

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.

Query parameters

integration_id*int

Response

summaryobjectsessions, users, rage_clicks
daysint
GET/api/clarity/pages

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*intProject id.

Response

pagesobject[]url, sessions, dead, rage, quickback, error_clicks, script_errors, scroll, active_seconds, friction
daysint
GET/api/feed

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*intProject id.

Response

activebool
created_at?datetime
last_used_at?datetime
POST/api/feed

Create or revoke the data feed (CSV)

Access
Session or API key with write access
Who
Owner or member; viewers and clients get 403.

Actions (action)

  • createproject_id*

    A new feed invalidates the old address. Response: url, formula.

  • revokeproject_id*

Metrics

Traffic, conversion, revenue and the site script's own measurements. GA4 and Search Console come live from Google (cached); the rest from Studio's own fact tables.

GET/api/data

GA4, Search Console and own systems

scope=overview: totals and daily series per site. realtime: active users per property. detail: one property (property=properties/123). project: web, search and product for one project (project=5). 503 no_connections without a working Google connection.

Access
Session or API key (read or write)
Who
Everyone in the workspace; a client only sees their own projects.

Query parameters

scopeoverview | realtime | detail | project
propertystring
projectint
days7 | 28 | 90Period in days; defaults to 28.

Response

generatedint
daysint
sitesobject[]
appsobject[]
liveobject
…objectOther fields depend on scope.
GET/api/landing

Landing pages with conversion

Access
Session or API key (read or write)
Who
Team; clients with access to the Website module.

Query parameters

project_id*intProject id.
days7 | 28 | 90Period in days; defaults to 28.
channelstringFor example Organic Search.

Response

pagesobject[]
daysint
channel?string
GET/api/revenue

Revenue, MRR, churn and payment success

Access
Session or API key (read or write)
Who
Team; clients with approval rights on Overview (otherwise hidden: true).

Query parameters

project_id*intProject id.

Response

revenue?object
hiddenbool
GET/api/attribution

Channel to payment, LTV and CAC

Access
Session or API key (read or write)
Who
Team; clients with approval rights on Overview (otherwise hidden: true).

Query parameters

project_id*intProject id.

Response

attribution?object
hiddenbool
can_managebool
POST/api/attribution

Costs per channel per month

Access
Session or API key with write access
Who
Owner or member; viewers and clients get 403.

Actions (action)

  • costproject_id*, month*, channel*, amount*, note
    • amount number · In euros; 0 removes the costs.
GET/api/brand

Branded versus non-branded search

Access
Session or API key (read or write)
Who
Team; clients with access to the Search module.

Query parameters

project_id*intProject id.
days7 | 28 | 90Period in days; defaults to 28.

Response

daysint
visibilityobject[]
…objectBranded and non-branded figures.
GET/api/cause

Cause of a change

Returns disabled: true when the feature is off for the workspace.

Access
Session or API key (read or write)
Who
Team; clients with Website (or Search for clicks).

Query parameters

project_id*intProject id.
metricsessions | key_events | clicks
days7 | 14 | 28 | 90

Response

cause?object
disabledbool
GET/api/cookieless

Cookieless measurement over 28 days

Access
Session or API key (read or write)
Who
Team; clients with access to the Website module.

Query parameters

project_id*intProject id.

Response

daysobject[]day, pageviews, visitors
pagesobject[]label, pageviews, visitors
sourcesobject[]label, pageviews, visitors
refsobject[]label, pageviews, visitors; waarden van ?ref= of ?source= in het adres
referrersobject[]label (domein), pageviews, visitors
consentobjectalles, statistieken, advertenties, geweigerd → bezoekers (28 dagen)
ga4_users?intsom van GA4-gebruikers per dag over dezelfde 28 dagen
totalsobjectpageviews, visitors
GET/api/vitals

Web Vitals from real visitors

Access
Session or API key (read or write)
Who
Team; clients with access to the Website module.

Query parameters

project_id*intProject id.

Response

has_scriptbool
…objectLCP, INP and CLS per page and device.
GET/api/forms

Form analytics, leads and cohorts

Access
Session or API key (read or write)
Who
Team; clients with access to the Website module.

Query parameters

project_id*intProject id.
daysint7 to 90; defaults to 28.

Response

formsobject[]page, form, starts, submits, rate, fields, worst
has_scriptbool
leadsobject
cohortsobject
GET/api/speed

PageSpeed per page: mobile and desktop, four categories, history and audits with tips

Access
Session or API key (read or write)
Who
Team; clients with access to the Website module.

Query parameters

project_id*intProject id.

Response

pagesobject[]url, path, planned, mobile, desktop (scores, lab, field, origin_field, audits), mobile_history, desktop_history, mobile_error, desktop_error
summaryobjectaverage, worst, opportunities, issues, origin_field
tipsobjectTip per audit id for the project's stack.
quotaobjectused, budget, blocked_until, source
measuringbool
can_managebool
pages_limitint
setup?objectWhy nothing is measured (error), a link to fix it (enable_url) and fix: steps, links, copy.
POST/api/speed

Measure pages now with PageSpeed Insights

Access
Session or API key with write access
Who
Owner or member; viewers and clients get 403.

Actions (action)

  • measureproject_id*, url

    Measures in the background, mobile and desktop; at most once every two minutes per project (429). Response: pages.

    • url url · Empty: all measured pages of the project.

Search and SEO

The query worksheet, tracked keywords, competition, the site audit, log files and content.

GET/api/seo

Query and meta worksheet

Access
Session or API key (read or write)
Who
Team; clients with access to the Search module.

Query parameters

project_id*intProject id.
days7 | 28 | 90Period in days; defaults to 28.

Response

daysint
sitesobject[]
errorsobject[]
pagesobject[]At most 300, with open recommendations and index status.
page_countint
ctr_curveobject[]position, ctr
GET/api/keywords

Tracked keywords

Access
Session or API key (read or write)
Who
Team; clients with access to the Search module.

Query parameters

project_id*intProject id.

Response

keywordsobject[]
suggestionsobject[]
can_managebool
ads_candidatesobject[]
clustersobject[]
seasonsobject
title_testsobject[]
POST/api/keywords

Add, target or remove keywords

Access
Session or API key with write access
Who
Owner or member (manages Search); others get 404.

Actions (action)

  • addproject_id*, keywords*

    Subject to the plan's limits. Response: keywords, suggestions.

    • keywords string · One per line or comma-separated; at most 200 per project.
  • targetproject_id*, id*, target_url

    Response: keywords, suggestions.

  • deleteproject_id*, id*

    Response: keywords, suggestions.

GET/api/competition

Competitors, content gaps, backlinks and map rankings

source says which source is active: DataForSEO or the free sources (Bing, Brave, own crawler).

Access
Session or API key (read or write)
Who
Team; clients with access to the Search module.

Query parameters

project_id*intProject id.

Response

enabledbool
sourcestring
freeobject
backlinks_source?string
gaps_sourcestring
competitorsstring[]
keywordsobject[]
gapsobject[]
backlinks?object
gridobject
spent?number
can_managebool
POST/api/competition

Set competitors and the map grid

Access
Session or API key with write access
Who
Owner or member (manages Search); others get 404.

Actions (action)

  • addproject_id*, domain*
    • domain string · At most five per project.
  • removeproject_id*, domain*
  • gridproject_id*, business_name*, keyword*, lat*, lng*, radius_km
    • radius_km number · 0.5 to 25; defaults to 3.
  • braveproject_id*

    Brave Search positions, live and not stored; at most once per ten minutes per project (429 too_many). Response: live.

GET/api/audit

Site audit from the latest crawl

Access
Session or API key (read or write)
Who
Team; clients with access to the Search module.

Query parameters

project_id*intProject id.

Response

crawled_at?datetime
pagesint
workingint
redirectsint
errorsint
linksint
issuesobject[]
suggestionsobject[]
can_crawlbool
llms_txt?object
budget?object
indexnowobjectkey, verified_at
text?object
POST/api/audit

Start a crawl or set up IndexNow

Access
Session or API key with write access
Who
Owner or member (manages Search); others get 404.

Actions (action)

  • crawlproject_id*

    Status 202. Response: task_id.

  • indexnowproject_id*

    Response: key, location, verified.

GET/api/schema

Schema wizard: types and what is known

Access
Session or API key (read or write)
Who
Team; clients with access to the Search module.

Query parameters

project_id*intProject id.

Response

typesobject
prefillobjectname, url
presentstring[]
POST/api/schema

Build JSON-LD

No action. Returns the JSON-LD, or which fields are missing.

Access
Session or API key with write access
Who
Team; clients with access to the Search module.

Body

project_id*int
type*string
fieldsobject

Response

…objectJSON-LD or missing fields.
GET/api/logs

Analysis of the latest log file

Access
Session or API key (read or write)
Who
Team; clients with access to the Search module.

Query parameters

project_id*intProject id.

Response

report?object
can_uploadbool
from_serverbool
POST/api/logs

Upload an access log

Multipart, no action. Combined format, .gz allowed, at most 100 MB.

Access
Session or API key with write access
Who
Owner or member (manages Search); others get 404.
Status
201

Body (multipart/form-data)

project_id*int
file*file

Response

linesint
bot_linesint
GET/api/content

Content calendar

Access
Session or API key (read or write)
Who
Team; clients with access to the Search module.

Query parameters

project_id*intProject id.

Response

itemsobject[]
suggestionsobject[]
can_managebool
POST/api/content

Plan content, newsletter and socials

Access
Session or API key with write access
Who
Owner or member (manages Search); others get 404.

Actions (action)

  • addproject_id*, title*, query, publish_on, reason, url

    Status 201. Response: id.

  • updateid*, title, query, publish_on, status, url, reason

    Setting live adds it to the timeline.

    • status idee | schrijven | klaar | live
  • deleteid*
  • newsletterproject_id*, days, intro, skip

    Response: items, html.

  • newsletter_draftproject_id*, target*, subject*, list_id*, from_name*, reply_to*, days, intro, skip

    Response: draft_id.

    • target mailchimp | brevo
  • social_draftsproject_id*, skip

    Creates drafts in socials.instnt.studio.

POST/api/writeback

Write-back key for WordPress or Drupal

Access
Session or API key with write access
Who
Owner or member (manages Search); others get 404.

Actions (action)

  • tokenproject_id*

    Response: token.

Advice, questions and AI

Recommendations and their status, playbooks, experiments, client questions and AI tasks.

GET/api/advice

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*intProject id.
statusopen | planned | done | bevestiging | dismissed | expired | all | actief | archiefDefaults to open. bevestiging: done, but not yet confirmed by the source. actief: open and planned. archief: done, dismissed and expired, newest first.
grouppageWith status=actief: also pages, the recommendations per page.
scopeworkspace

Response

itemsobject[]At most 500, most important first, with impact_euros and confirmation (state confirmed or waiting, by, at, waits_on, overdue, note).
euro_basis?object
countsobject
tip?object
last_refresh?datetime
thresholdsobject
learnedobject[]
effect_daysint
can_managebool
has_githubbool
progressobject[]Per category: category, done, total (excluding expired).
effect?objectOnly 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.
POST/api/advice

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_url

    On 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_date

    Assigning 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, mark

    Team 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 | algemeen
    • mark bool · Defaults to true: sets the items to planned with a note.

Example: Request

{
  "action": "status",
  "id": 812,
  "status": "done",
  "note": "Titel aangepast"
}
GET/api/playbooks

Project playbooks

Access
Session or API key (read or write)
Who
Team; clients with access to the Advice module.

Query parameters

project_id*intProject id.

Response

runsobject[]
availableobject
can_managebool
POST/api/playbooks

Start and tick off a playbook

Access
Session or API key with write access
Who
Owner or member (manages Advice); others get 404.

Actions (action)

  • startproject_id*, playbook*

    Status 201. Response: id.

  • stepid*, step*, done
  • finishid*
GET/api/experiments

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*intProject id.

Response

experimentsobject[]
cardsobject[]
can_managebool
POST/api/experiments

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, result

    Response: id.

    • id int · Without id: new.
    • outcome won | lost | neutral
  • deleteproject_id*, id*
GET/api/questions

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_idint
subject_typereport | advice | project
subject_idint
openboolAll open questions across clients.

Response

questionsobject[]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)
disabledbool
POST/api/questions

Ask, reply or close a question

Access
Session or API key with write access
Who
Team and clients with access to the subject.

Actions (action)

  • askproject_id*, subject_type*, subject_id*, anchor, body*

    Status 201. Response: question_id.

    • subject_type report | advice | project
    • body string · At most 4000 characters.
  • replyquestion_id*, body*
  • closequestion_id*

    The team, or whoever asked.

GET/api/support

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

deelklant | instnt
adminbool
idint
setsboolOnly the sets of saved replies to load (team, 13-10-2026).
langnl | en
statusactief | te_laat | open | wacht_ons | wacht_klant | opgelost | geslotenDefaults to actief: everything except resolved and closed. Empty for all.
qstringSearches subject, number and messages.
project_idint
mineboolOnly assigned to me.

Response

ticketsobject[]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
countsobject
overdueint
moduleobject
statusesobject
prioritiesobject
can_createbool
setsobject[]With sets=1: key, label, description, count, titles.
template_setsobject[]For the team: the same sets.
settingsobjectTeam only: sla, sla_default, inbound_available, inbound_on, address, can_manage.
ticketobjectWith id: the ticket plus thread, link, role, can, and for the handler context, team, templates and projects.
POST/api/support

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, files

    Status 201. Response: ticket.

    • deel klant | instnt
    • title 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, admin

    On 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, admin

    Internal note: the requester never sees it, nor its attachments. Response: ticket.

  • statusid*, status*, admin

    The requester can only close. Response: ticket.

    • status open | wacht_ons | wacht_klant | opgelost | gesloten
  • assignid*, user_id, admin

    Response: ticket.

  • priorityid*, priority*, admin

    Recalculates a running deadline. Response: ticket.

    • priority laag | normaal | hoog | urgent
  • projectid*, project_id, admin

    Response: ticket.

  • settingssla, inbound_on

    Response: settings.

    • sla object · Hours per priority (laag, normaal, hoog, urgent), each 1–720.
  • rotate_address

    New address for mail to support; the old one stops working at once. Response: settings.

  • template_saveid, project_id, category, actions, title*, shortcut, body*, buttons, admin

    The 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*, admin

    Response: templates.

  • template_importset, project_id, sets, only, lang

    Load 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 | software
    • project_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/attachment

Ticket 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.

Query parameters

id*int
adminbool
GET/api/livechat

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

viewopen | wachtend | mijn | niet_toegewezen | buiten_tijden | afgesloten | alleDefaults to open: everything not closed. wachtend: the team is up.
project_idint
labelstringOnly conversations with this label.
sortwachtend | nieuwste | activiteitDefaults to wachtend: whoever has waited longest on the team first.
qstringSearches name, email and messages.
idint
sinceint
tellerboolCounts only, for the navigation and the app icon.
settingsintProject id: the chat settings and the install snippet.

Response

conversationsobject[]id, project, name, email, status, offline, assigned, last, unread, tags, page_url, visitor_online, rating, ticket_id, created_at, last_message_at, waiting_since
countsobjectopen, 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).
projectsobject[]id, name, enabled, can_reply, notify_after
sortstring
moduleobject
can_managebool
statusesobject
conversationobjectWith 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.
settingsobjectWith 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.
POST/api/livechat

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_id

    Response: conversation.

  • tagsid*, tags*

    Response: conversation.

    • tags string[] · At most ten, each at most 30 characters.
  • filesid*, allow*, limit

    Allow 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, end

    Live 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 | production
    • end 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*, remove

    Create 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, widget

    Response: 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 | links
    • greeting_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.

GET/api/faq

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_idint
qstringSearch title, category and body.
suggeststringThe visitor's question.
statsintSelf-service figures over 7, 30 or 90 days; managers only.
idintOne article with body, html and plain.

Response

statsobjectWith stats: articles (per id views, yes, no, helpful_pct), views, yes, no, misses (searches without results: term, count), conversations_after, deflection_pct.
articlesobject[]id, project_id, title, category, language, published, featured, position, views, updated_at, excerpt (met suggest ook body, html, plain)
articleobject
can_managebool
languagesobject
max_bodyint
POST/api/faq

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.

Actions (action)

  • createproject_id*, title*, body*, category, language, published

    Response: article.

    • title string · At most 200 characters.
    • body string · Markdown, at most 20,000 characters.
    • language nl | en
  • updateid*, title, body, category, language, published, featured

    Response: article.

    • language nl | en
    • featured bool · Featured on the window's start screen.
  • deleteid*
  • reorderproject_id*, ids*
    • ids int[] · All articles of the project in the new order.
  • previewbody*

    The same HTML the widget shows. Response: html.

GET/api/chat-team

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

viewreport | team
fromdateDefaults to 27 days before to.
todateDefaults to today.
project_idint

Response

reportobjectfrom, to, timezone, totals, days, heatmap, pages, comments, agents, truncated
projectsobject[]id, name
meobjectWith view=team: status, chosen, max_chats, open, can_set.
teamobject[]id, name, status, open, max_chats
routingobject[]project_id, name, assign_mode, report_block
POST/api/chat-team

Chat: status and routing

Access
Session or API key with write access
Who
Status: whoever may reply somewhere. Routing: owner or member.

Actions (action)

  • availabilitystatus*, max_chats

    Anyone set to available who has not fetched the inbox for ninety seconds counts as away; after fifteen minutes as offline. Offline: your automatically routed conversations go to someone else or become unassigned.

    • status beschikbaar | afwezig | offline
    • max_chats ?int · At most this many open conversations at once, 1–50; empty means no limit.
  • routingproject_id*, assign_mode, report_block
    • assign_mode handmatig | rondgang | minst_bezet · Manual: nobody is assigned automatically. Rondgang: round robin among available members. Minst bezet: whoever has the fewest open conversations.
    • report_block bool · Chat in this project's monthly report.
GET/api/ai

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*intProject id.

Response

kindsobject
usageobjectused, limit, cost_usd
worker_seen?datetime
tasksobject[]
textsobject[]
voice?object
opportunitiesobject[]
adviceobject[]
reportsobject[]
contentobject[]
geoobjectquestions
POST/api/ai

Request AI tasks and review texts

Access
Session or API key with write access
Who
Owner or member; viewers and clients get 403.

Actions (action)

  • requestkind*, recommendation_id, report_id, content_id, project_id, question, keyword, landing

    Subject to the plan's limits. Response: task_id.

    • kind title_meta | advice_plain | report_intro | content_brief | draft_text | week_analysis | data_question | share_of_answer | ad_texts
    • recommendation_id int · For title_meta and advice_plain.
    • report_id int · For report_intro.
    • content_id int · For content_brief and draft_text.
    • project_id int · For the others.
    • question string · For data_question.
    • keyword string · For ad_texts.
  • decidetext_id*, decision*, final
    • decision overgenomen | aangepast | afgewezen
    • final string · Required for aangepast.
  • voiceproject_id*, tone, do_words, dont_words, forbidden_claims
  • geo_addproject_id*, question*
    • question string · At most ten per project.
  • geo_removeproject_id*, id*
GET/api/ai/worker

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?objectid, kind, prompt, schema, model
POST/api/ai/worker

AI worker: submit a result

Access
Session or API key with write access
Who
instnt platform admins only; others get 404 or 403.

Body

id*int
result*object

Uptime and technical

Uptime checks, JavaScript errors, backups, maintenance, site checks, versions with known vulnerabilities and the cookie scan.

GET/api/uptime

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*intProject id.

Response

monitorsobject[]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
errorsobject[]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_pagebool
alert_emails?string
backupsobject[]
maintenanceobject[]
can_managebool
suggested_url?url
POST/api/uptime

Manage checks, status page, maintenance and backups

Access
Session or API key with write access
Who
Owner or member; viewers and clients get 403.

Actions (action)

  • createproject_id*, url*, expect_status, expect_text, interval_minutes

    Checks once right away. Response: monitor_id.

    • expect_status int · Defaults to 200.
    • interval_minutes 1 | 5 | 15
  • updatemonitor_id*, url*, expect_status, expect_text, interval_minutes, enabled
    • interval_minutes 1 | 5 | 15
  • deletemonitor_id*
  • checkmonitor_id*
  • status_pageproject_id*, revoke

    Response: link.

  • alert_emailsproject_id*, emails
    • emails string · Comma-separated.
  • maintenance_createproject_id*, starts_at*, ends_at*, note
    • ends_at datetime · At most a week after the start.
  • maintenance_deleteid*
  • backup_createproject_id*, name*, max_hours
    • max_hours int · 1 to 744; defaults to 26.
  • backup_deleteid*
  • error_keyproject_id*

    Creates the site script key if there isn't one.

  • error_statuserror_id*, status*
    • status open | resolved | ignored
GET/api/site-checks

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*intProject id.

Response

hostsobject[]host, checks
POST/api/site-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.

GET/api/security-score

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*intProject id.

Response

score?int
previous?int
trendobject[]day, score
categoriesobject[]key, label, weight, description, score (?int), points (status, label, detail)
methodstring
domainsobject[]domain, verified, via
POST/api/security-score

Recompute the security score

Access
Session or API key with write access
Who
Owner or member (manages Website); others get 404.

Actions (action)

  • recomputeproject_id*

    Recounts from the latest measurements and stores today's score; fetches nothing. The checks themselves run every morning at 05:50. Response: score.

GET/api/tech-stack

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*intProject id.

Response

hostsstring[]
checked_at?datetime
detectedobject[]category, label, items (tech, label, version, evidence, host, since, last_seen, connector, connected)
changesobject[]type (added|removed), label, host, at
connectobject[]tech, label, connector, url
gapsobject[]key, tone, title, detail, url, action
suggestionsobject[]key, title, detail, url, action
summary?objectstatus, text, at
can_managebool
can_aibool
POST/api/tech-stack

Scan again or request a summary

Access
Session or API key with write access
Who
Owner or member; viewers and clients get 403.

Actions (action)

  • scanproject_id*

    Looks at the homepage(s) again now. At most once a minute (429).

  • summaryproject_id*

    Own team only. Claude writes one paragraph about the detection; it then appears as summary in the GET. Status 202. Response: task_id.

GET/api/components

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*intProject id.

Response

componentsobject[]ecosystem, name, version, type, dev, active, reported_at
reportedobject
vulnsobject[]ecosystem, name, version, vuln_id, aliases, severity, summary, fixed_in, url, first_seen_at
resolved_30dint
wordfencebool
GET/api/cookiescan

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*intProject id.

Response

latest?object
last_error?object
findingsobject[]
gonestring[]
has_previousbool
historyobject[]
can_scanbool
POST/api/cookiescan

Scan now

Access
Session or API key with write access
Who
Owner or member (manages Website); others get 404.

Actions (action)

  • scanproject_id*

    At most once per five minutes per project. Status 202. Response: task_id.

Reports

Monthly reports, quarterly and yearly overviews, share links and PDF. Clients only see published reports.

GET/api/reports

Reports of a project

Without period: the list. With period: one report with data. With range: a quarter (2026-Q3) or year (2026) built from the monthly reports.

Access
Session or API key (read or write)
Who
Team; clients with access to the Overview module.

Query parameters

project_id*intProject id.
periodmonth
rangestring

Response

reportsobject[]id, period, label, status, intro, generated_at, published_at
reportobject
period_reportobject
suggested_periodmonth
can_managebool
projectstring
brandingobject
sharesobject[]
POST/api/reports

Generate, publish or share a report

Access
Session or API key with write access
Who
Owner or member; viewers and clients get 403.

Actions (action)

  • generateproject_id*, period

    Creates the report or refreshes its figures; the introduction stays. Status 202. Response: task_id, period.

    • period month · A past month; defaults to the previous one.
  • introid*, intro
  • publishid*

    Triggers the automation that emails the client. Response: notified.

  • unpublishid*
  • deleteid*
  • shareid*, days

    Published reports only. Response: link, expires_at.

    • days int · 1 to 90; defaults to 30.
  • unshareid*, share_id*
GET/api/reports/pdf

Report as PDF

Access
Session or API key (read or write)
Who
Team; clients with access to the Overview module.

Query parameters

id*int

Google Ads

Insights, targets, keyword ideas and the Ads pilot with proposals.

GET/api/ads

Google Ads for a project

Access
Session or API key (read or write)
Who
Team; clients with access to the Ads module.

Query parameters

project_id*intProject id.

Response

summary?object
pacingobject[]
ngrams?object
quality?object
budget?object
ad_testsobject[]
pmaxobject[]
can_managebool
autopilot?objectOnly for those who manage: mode, max_change_pct, max_daily_budget, max_changes_per_day, max_week_change_pct, allowed_kinds, excluded_campaigns, quiet_from, quiet_until, enabled_at, enabled_by, stopped_at, killed_at, auto_apply, campaigns, me (two_factor, owner, reauth), proposals (with effect, reversible, can_revert, auto_blocked) and changes (the log: action, result, before, after, request_id, user).
POST/api/ads

Targets, ideas and the Ads pilot

Access
Session or API key with write access
Who
Owner or member; viewers and clients get 403.

Actions (action)

  • targetsproject_id*, target_cpa, order_value, margin_pct
  • ideasproject_id*, seeds*

    Via Keyword Planner; cached for a week. Response: ideas, seeds.

    • seeds string[] · At most ten.
  • modeproject_id*, mode*, max_change_pct, max_daily_budget, max_changes_per_day, max_week_change_pct, allowed_kinds, excluded_campaigns, quiet_from, quiet_until, password, code

    automatisch and wider limits only by the owner, with two-factor on and the code from the authenticator (valid ten minutes; a password is not enough since 11-10-2026). Without a valid code 422 reauth. Not with an API key (403); stop and kill are allowed. Subject to the plan's limits.

    • mode uit | lezen | voorstellen | automatisch
    • max_change_pct int · 1 to 100; defaults to 20.
    • max_changes_per_day int · 1 to 50; defaults to 5.
    • max_week_change_pct int · How far a budget may move in seven days; defaults to 30.
    • allowed_kinds string[] · budget, negative and/or pause_keyword; defaults to budget and negative.
    • quiet_from ?int · Hour 0–23; together with quiet_until.
  • proposeproject_id*
  • applyproject_id*, proposal_id*, confirm_irreversible, password, code

    Requires two-factor. Sent to Google with validateOnly first, then for real; every outcome goes into the log. Response: proposal.

    • confirm_irreversible bool · Required for what cannot be undone (Google's recommendations).
  • rejectproject_id*, proposal_id*, reason
  • revertproject_id*, proposal_id*, password, code

    Requires two-factor; allowed even with the kill switch on.

  • stopproject_id*

    Emergency stop for this project: back to read.

  • killproject_id*

    Kill switch for every project in the workspace; no two-factor, so stopping is always quick.

  • releaseproject_id*, password, code

    Turn the workspace kill switch off: owner only, with two-factor.

Automations and alerts

Automations (trigger, filters, actions), the log, approvals, alert rules and the channels: outgoing webhooks, Slack and Teams. Outgoing webhooks have the shape {"event", "sent_at", "data"} with the header X-Studio-Signature: sha256=<HMAC-SHA256 of the body with the secret>, plus X-Studio-Timestamp, X-Studio-Delivery and X-Studio-Signature-V2 (HMAC of <timestamp>.<delivery>.<body>) to reject old or replayed messages.

GET/api/automations

Automations, catalogue, log and approvals

Without parameters: the list plus the trigger and action catalogue. runs=1: the log (25 per page). run=ID: one run. approvals=1: what awaits approval.

Access
Session or API key (read or write)
Who
Team only (owner, member or viewer); clients get 403.

Query parameters

runsbool
runint
approvalsbool
automation_idint
statusstring
project_idint
pageint

Response

automationsobject[]id, name, enabled, is_default, trigger_type, trigger_params, project_id, filters, actions, rate_limit, requires_approval, fired, fired_30d, last_run, hook_url, schedule, can_run
catalogobject
action_catalogobject
templatesobject[]
triggersobject[]
runsobject[]
totalint
pagesint
runobject
approvalsobject[]
limit?int
usedint
timezonestring
POST/api/automations

Save, test and run automations

Access
Session or API key with write access
Who
Owner or member; viewers and clients get 403.

Actions (action)

  • saveid, name*, trigger_type*, trigger_params, project_id, filters, actions*, rate_limit, requires_approval, enabled

    Errors come back per field in fields. Subject to the plan's limits. Response: id.

    • id int · Without id: new.
    • trigger_type string · From catalog.
    • actions object[] · Each {type, params}; if-then-else is type branch with then and else.
    • requires_approval bool · Only the owner can turn this off.
  • testid, run_id

    Dry run with the same fields as save, or just an id; validates, but writes and sends nothing. Response: source, data, *.

    • run_id int · Data from an earlier run instead of the example.
  • timezonetimezone*

    Response: timezone.

    • timezone string · An IANA name, such as Europe/Amsterdam.
  • toggleid*
  • deleteid*

    A default automation is switched off instead of deleted.

  • runid*

    Only for a manual trigger or a schedule. Response: run_id.

  • rotate_hookid*

    New address for an incoming webhook; the old one stops working at once.

  • resetid*
  • retryrun_id*, action_index*
  • approveapproval_id*
  • rejectapproval_id*
GET/api/alerts

Alert rules and what was sent

Access
Session or API key (read or write)
Who
Team only (owner, member or viewer); clients get 403.

Response

emailsstring[]
rulesobject[]
automaticobject[]
logobject[]
approvals_openint
actionsobject
recipientsobject
channelsobject[]
webhooksobject[]
teamobject[]
can_editbool
is_ownerbool
POST/api/alerts

Create or change an alert rule

Access
Session or API key with write access
Who
Owner or member; viewers and clients get 403.

Actions (action)

  • createkind*, project_id, metric, threshold*, name, actions

    Subject to the plan's limits. Response: rule_id.

    • kind threshold_live | milestone | event
    • project_id ?int · Required for event.
    • threshold int · At least 1.
  • updaterule_id*, threshold, metric, project_id, name, actions, requires_approval, enabled
  • deleterule_id*
  • togglerule_id*, enabled*
GET/api/webhooks

Outgoing webhooks

Access
Session or API key (read or write)
Who
Owner or member; viewers and clients get 403.

Response

webhooksobject[]id, url, events, last_status, last_error, last_at, created_at
eventsobject
POST/api/webhooks

Add, test or remove a webhook

Access
Session or API key with write access
Who
Owner or member; viewers and clients get 403.

Actions (action)

  • createurl*, events*

    At most ten per workspace. Status 201. Response: id, secret.

    • url url · A public https address.
    • events string[] · advice.created, incident.opened, incident.resolved, report.published, anomaly.detected, question.asked, vulnerability.found.
  • deleteid*
  • testid*

    Sends {"event": "test"}.

GET/api/chat

Slack and Teams channels

Access
Session or API key (read or write)
Who
Owner or member; viewers and clients get 403.

Response

channelsobject[]id, kind, name, events, last_status, last_at
eventsobject
POST/api/chat

Add, test or remove a channel

Access
Session or API key with write access
Who
Owner or member; viewers and clients get 403.

Actions (action)

  • createkind*, name, url*, events*

    Status 201.

    • kind slack | teams
    • url url · Webhook address from Slack or Teams.
  • deleteid*
  • testid*

    Response: status.

GET/api/slack

Slack bot: settings without secrets

Access
Session or API key (read or write)
Who
Owner or member; viewers and clients get 403.

Response

app?objectchannel, events, last_status, last_at
eventsstring[]
interactivity_urlurl
POST/api/slack

Configure the Slack bot

Access
Session or API key with write access
Who
Owner or member; viewers and clients get 403.

Actions (action)

  • savebot_token, signing_secret, channel*, events
    • bot_token string · xoxb-…; empty keeps the current one.
    • channel string · Channel ID (C…).
  • remove
  • test

    Response: status.

Studio Mail

Contacts, lists, opt-in forms, templates, sending domains and accounts (/api/contacts), and funnels, campaigns and segments (/api/mail). An unknown action returns 422 validation here.

GET/api/contacts

Contacts, lists, forms, templates and domains

Without parameters: the overview. list=contacten: contacts with filters (50 per page). contact_id=…: one contact with timeline, lists and funnels.

Access
Session or API key (read or write)
Who
Team only (owner, member or viewer); clients get 403.

Query parameters

listcontacten
contact_idint
statusunconfirmed | subscribed | unsubscribed | bounced | complained
project_idint
list_idint
tagstring
min_scorenumber
segment_idint
qstring
sortscore
pageint

Response

providersobject[]
countsobject
tagsstring[]
open_trackingbool
segmentsobject[]
listsobject[]
formsobject[]
templatesobject[]
domainsobject[]
accountsobject[]
regionsobject
contactsobject[]id, email, name, status, source, project_id, tags, consent_at, created_at, score
totalint
pageint
contactobject
POST/api/contacts

Manage contacts, forms, templates, domains and accounts

Access
Session or API key with write access
Who
Owner or member; viewers and clients get 403.

Actions (action)

  • contact.updateid*, name, language, tags, project_id, list_ids
    • language nl | en · Language of the confirmation and unsubscribe pages and emails.
  • contact.unsubscribeid*
  • contact.deleteid*

    Also erases the contact's tracking data.

  • list.saveid, name*

    Response: id.

  • list.deleteid*
  • form.saveid, name*, language, consent_text*, list_id, domain_id, project_id, redirect_url

    Response: id.

    • language nl | en · Language of the form and embed code; defaults to nl.
    • redirect_url url · Thank-you page, https.
  • form.deleteid*
  • importlist_id, confirmed*, csv*, declaration*

    Rejects the import when more than 20% of rows are invalid; role addresses (info@, sales@ …) are skipped. Response: imported, added, updated, invalid, role, duplicates, suppressed.

    • confirmed bool · Confirmation that everyone consented.
    • csv string · Email address and name per line, optionally a third column with the language (nl or en); at most 2 MB.
  • template.saveid, name*, subject*, mjml, html*, text

    Response: id.

  • template.deleteid*
  • template.testid*, confirmed*, domain_id

    Test email to yourself. Response: sent_to.

  • domain.adddomain*, from_local, from_name, provider, account_id, project_id

    Status 201. Response: domain.

    • from_local string · Defaults to nieuws.
    • provider ses | resend
    • account_id int · Own sending account; the provider follows from it.
  • domain.checkid*

    Response: domain.

  • domain.resumeid*

    Lifts an automatic pause.

  • domain.deleteid*
  • account.saveid, provider, name*, project_id, credentials

    Tests the key right away. Keys never come back; only the last four characters. Response: account.

    • provider ses | resend
    • credentials object · Resend: key, webhook_secret, region. SES: key, secret, region, configuration_set, sns_topic_arn. Empty keeps the current value.
  • account.testid*

    Response: account.

  • account.deleteid*

    Only once no domains use it.

  • settingsopen_tracking
GET/api/mail

Funnels, campaigns and segments

funnel=ID: the funnel and its emails; with contacts=1 (and step, status, page) the contacts in it. campaign=ID: one campaign with results.

Access
Session or API key (read or write)
Who
Team only (owner, member or viewer); clients get 403.

Query parameters

funnelint
contactsbool
stepint
statusstring
pageint
campaignint

Response

providersobject[]
attributionbool
funnelsobject[]
campaignsobject[]
segmentsobject[]
segment_fieldsobject[]
segment_opsobject
goalsobject
funnelobject
campaignobject
POST/api/mail

Segments and campaigns

Access
Session or API key with write access
Who
Owner or member; viewers and clients get 403.

Actions (action)

  • segment.previewdefinition*

    Response: count, subscribed, sample.

    • definition object · {match: all|any, rules: [{field, op, value}]}, at most 20 rules.
  • segment.saveid, name*, definition*

    Response: id.

  • segment.deleteid*
  • campaign.saveid, name*, template_id, domain_id, list_id, segment_id, subject_b, ab_percent, ab_hours

    Only a draft can still change. Response: id, audience.

    • subject_b string · Second subject for an A/B test.
    • ab_percent int · 5 to 50.
    • ab_hours int · 1 to 72.
  • campaign.scheduleid*, confirmed*, now, scheduled_at

    Response: campaign.

  • campaign.cancelid*
  • campaign.deleteid*
  • campaign.previewid*

    Response: subject_a, subject_b, html.

  • campaign.testid*, confirmed*, variant

    Response: sent_to.

    • variant a | b
  • settingsattribution
    • attribution bool · Click attribution on or off.

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.

POST/api/events

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*stringEqual 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*datetimeISO 8601; no more than 5 minutes in the future.
account_refstringUUID, not an email address.
visitor_idstring
session_idstring
propertiesobjectsource, plan, amount (as "25.00"), currency.
attributionobjectlanding_page, referrer, utm_source, utm_medium, utm_campaign, utm_term, utm_content, gclid, fbclid, msclkid, studio_ref.

Response

duplicatebool

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
}
POST/api/deploys

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

titlestring
commitstring
urlurl
POST/api/components

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*objectFile name to contents: composer.lock, package-lock.json, Package.resolved, Cargo.lock.

Response

countsobject
POST/api/mcp

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
idint
method*string
paramsobject

Response

jsonrpcstring
idint
resultobject
errorobject
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

Body

…objectApple's payload.

Response

receivedbool
POST/api/hooks/{token}

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

Body

…objectFree-form fields.

Response

runbool
POST/api/inbound/{token}

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

…objectThe service's payload.

Response

notedbool
GET/api/backup/{key}

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

Query parameters

sizeint
POST/api/backup/{key}

Backup succeeded (ping)

Access
No sign-in; the secret is in the address

Query parameters

sizeint
GET/api/titles

Approved titles to apply

For the WordPress or Drupal module.

Access
Write-back key: Authorization: Bearer wb_…

Response

titlesobject[]id, url, title, description
POST/api/titles

Titles applied

Access
Write-back key: Authorization: Bearer wb_…

Body

applied*int[]

Response

appliedint
POST/api/errors/{key}

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
sourcestring
lineint
colint
stackstring
pagestring
POST/api/vitals/{key}

Web Vitals measurement from the site script

Access
No sign-in
Status
204

Body

lcpnumber
inpnumber
clsnumber
pagestring
devicemobile | desktop
POST/api/forms/{key}

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

pagestring
formstring
fieldsstring[]
submittedbool
leadtelefoon | email | whatsapp
srstring
POST/api/pageviews/{key}

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
refurl
qrefstringValue of ?ref= or ?source=.
utm_sourcestring
utm_mediumstring
utm_campaignstring
gclidstring
srstring
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*stringLowercase, digits and . _ -, e.g. tester.signed_up.
idstring
dataobject
privateobject

Response

runsint
duplicatebool
POST/api/consent/{key}

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

agranted | deniedanalytics_storage
dgranted | deniedad_storage
GET/api/site-script/{key}.js

The 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
GET/api/chat-widget.js

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*stringWidget token from the chat settings.
GET/api/chat-widget-home.js

The 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
sinceintOnly messages after this id.
bodystringWith stuur; at most 2,000 characters.
namestring
emailemail
pageurl
titlestring
typingbool
ratingintWith beoordeel: 1–5, only after closing.
websitestringLeave empty.
topicstringFor a new conversation: a topic from the settings; becomes a tag.
consentboolAgreed to the privacy statement, if the form asks for it.
seenintWith poll: the last message id the visitor saw in the open, visible window; for "Read" in the inbox. Never goes back.
routeobject[]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.
proactivestringThe text of the proactive message the visitor replies to; only if it is in the rules.
idintWith gesprek: an earlier conversation of the same visitor. With kies: the message with the buttons.
labelstringWith kies: one of the buttons under that message; once per message, and is sent as the visitor's message.
codestringWith 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_idstringWith identificeer: the id of the signed-in user on the site.
signaturestringWith identificeer: HMAC-SHA256 of user_id with the key from the chat settings, computed on the site's server.
email_signaturestringWith identificeer: HMAC-SHA256 of "user_id|address" (address lower-cased). Only then does email count as verified. uitloggen undoes this browser's link.
filefileWith stuur as multipart (payload = the JSON above): image or PDF, at most 10 MB, ten per hour.
selfhelpobjectFor 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

enabledbool
configobjectname, 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
statusonline | open | gesloten
conversation?objectstatus, 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)
messagesobject[]id, from, body, at, name, files, buttons, choice, faq (id, title van een gepubliceerd artikel)
historyobject[]With geschiedenis: id, at, last_at, status, ticket, preview.
errorstringOn 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).
GET/api/chat-file/{id}

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}/faq

The 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
qstringWith zoek; at most 120 characters. Without results Studio keeps the term without the visitor, for 90 days (can be turned off).
langnl | en
idintWith artikel and feedback.
namestringWith categorie.
helpfulboolWith feedback: "Did this help?". One vote per article per day per IP hash.

Response

enabledbool
totalint
resultsobject[]id, title, category, excerpt (bij lijst eerst de uitgelichte)
categoriesobject[]name, count (bij lijst)
articleobjectid, title, category, html, updated_at
POST/api/optin/{formKey}

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
naamstring
toestemming*string1, on, true or ja.
taalnl | enLanguage of the sign-up; without it, the form's language.
websitestringLeave empty.

Response

messagestring
errorstring

Public

Without sign-in: shared reports, status pages, data feeds and Studio's own figures on the site.

GET/api/shared

Shared report

Access
No sign-in; the secret is in the address

Query parameters

token*stringFrom the share link.

Response

reportobject
projectstring
sharedbool
expires_atdatetime
brandingobject
GET/api/status

Public status page of a project

Access
No sign-in; the secret is in the address

Query parameters

token*string

Response

namestring
monitorsobject[]name, state, uptime_30d, incidents
maintenanceobject[]
brandingobject
checked_atdatetime
GET/api/public-stats

Totals across all workspaces

For the marketing site; nothing traceable to a client. Cached for an hour, CORS open.

Access
No sign-in

Response

projectsint
pages_crawledint
advice_givenint
advice_doneint
uptime_checks_30dint
incidents_30dint
updated_atdatetime
GET/api/feed/{token}.csv

Data feed as CSV

Per day: date, users, sessions, pageviews, conversions, clicks, impressions and position in Google. For =IMPORTDATA in Google Sheets.

Access
No sign-in; the secret is in the address

Query parameters

daysint7 to 480; defaults to 90.
GET/api/openapi.json

This reference as OpenAPI 3.1

Access
No sign-in

Query parameters

langnl | enDefaults to nl.

Internal

Addresses for services Studio talks to. They verify the sender's signature and aren't meant to be called yourself.

POST/api/ses/sns

Amazon SES via SNS (shared account)

Bounces, complaints and delivery. Only messages with a valid SNS signature from the configured topic.

Access
Signed by the sender
POST/api/ses/sns/{token}

Amazon SES via SNS (a client's own account)

The token selects the sending account, and with it the topic. Only counts for that account's sends.

Access
Signed by the sender
POST/api/resend/webhook

Resend events (shared account)

With a valid Svix signature; timestamps older than five minutes are refused.

Access
Signed by the sender
POST/api/resend/webhook/{token}

Resend events (a client's own account)

Access
Signed by the sender
POST/api/support/inbound

Mail to support (Resend Inbound)

Mail to <token>@SUPPORT_INBOUND_DOMAIN becomes a ticket, or a reply when the subject contains [#number]. Only from known senders of that workspace, with the module and mail to support on. With a valid Svix signature; otherwise 403. An ignored mail also returns 200, with the reason.

Access
Signed by the sender

Response

statusnieuw | antwoord | genegeerd
ticket_idint
reasonstring
POST/api/slack/interactions/{workspace}

Buttons in Slack messages

Signed with the Slack app's signing secret.

Access
Signed by the sender
POST/api/mollie/webhook

Payment status from Mollie

Mollie only sends the payment id; Studio fetches the status from Mollie itself, including refunds and chargebacks. 200 for an unknown id, 503 when fetching from Mollie fails (Mollie then retries).

Access
No sign-in