Skip to content

REST API

The schakl. web app never talks to the database directly — every screen fetches its data through the same REST API. That API is open to you too. Mint a key, tick what the key may do, and your script, your n8n flow or your integration with another package can get to work, under the same permissions and the same tenant isolation as an employee on screen.

Settings → API and MCP: where you mint a personal key and tick what it may do.

  • The endpoint list: API reference — every endpoint on this site, grouped by area, each with the permission it requires. Readable without an instance.
  • The interactive reference: https://<your-host>/api/docs (Swagger UI), plus https://<your-host>/api/redoc and the document itself at https://<your-host>/api/openapi.json.
  • Personal keys: Instellingen → Mijn account (Settings → My account), the API en MCP block.
  • Keys for automation: Instellingen → Service-accounts (Settings → Service accounts), in the “Team & toegang” (Team & access) group.

Use both, for different questions. The reference here is the map — what exists, and what your key has to hold to call it — and it never needs a running server. The one on your instance is the authority: it is generated from the code that is actually running, it knows which modules you switched on, and you can call an endpoint straight from the page.

The instance reference sits under /api/ on purpose: the reverse proxy routes only /api/ and /mcp to the API container and everything else to the web app. At /docs you land on the app’s 404 page.

Personal keyService account
WhereInstellingen → Mijn accountInstellingen → Service-accounts
Acts asyouan account of its own, with no person behind it
Permissionsyour live permissions intersected with the key’s scopesexactly the scopes ticked
When your role changesthe key shrinks with youunchanged
When its creator leavesthe key stops workingkeeps working

For something you need yourself for an afternoon, a personal key is fine. Anything that keeps running (n8n, a nightly script, an integration) belongs in a service account: that outlives the employee who once switched it on.

  1. Go to Instellingen → Mijn account and find the API-sleutels block. For automation, go to Instellingen → Service-accounts instead, create an account with Service-account toevoegen (Add service account), then click Nieuwe sleutel (New key).
  2. Fill in a Naam (Name) — for example “n8n-automatisering”. That name is the only thing you will recognise the key by later.
  3. Pick a date under Verloopt op (Expires on), or leave it empty for a key that never expires. A date may be at most a year ahead, and never in the past.
  4. Tick what the key may do under Scopes. At least one is required. The list only offers permissions you hold yourself: a key can never grant more than its creator has.
  5. Press Sleutel aanmaken (Create key) and copy the key immediately.

Send the key as Authorization: Bearer … or as X-API-Key: …. Every endpoint lives under /api/v1/.

Terminal window
curl -H "Authorization: Bearer schakl_…" \
"https://<your-host>/api/v1/companies?limit=50"

Use your organisation’s own address: your linked domain, or <slug>.<base domain>. Keys belong to one organisation — a key presented on another organisation’s hostname simply does not exist there.

List endpoints take limit and offset and answer with { "items": [...], "total": 0, "limit": 50, "offset": 0 }. If you do not need the total, pass count=false and save a count per call.

Every error has the same shape:

{ "error": { "code": "not_found", "message": "errors.not_found" } }

message is a translation key, not an English or Dutch sentence — the app translates it itself. A validation failure adds fields, with one such key per field.

StatusWhat it means
401Unknown, revoked or expired key, or the wrong hostname. Never a 403, so the answer never confirms that a key exists
403The key lacks the scope this endpoint declares
404Does not exist, or falls outside what this key may see
422Validation failure, with fields alongside
429More than 600 calls in a minute on the same key
402A write against a module whose licence no longer covers it

n8n needs no separate connector: this is the connector. An HTTP Request node with the header Authorization: Bearer schakl_… pointed at https://<your-host>/api/v1/… does everything a screen does. Use a service account for it, not the personal key of whoever built the flow.

The other direction — schakl. calling your flow — is the Webhook aanroepen (Call webhook) action in Automation.

PermissionWhat it opensDefault
apikeys.personal.manageManage own API keysAdministrator, Member
apikeys.service_account.manageManage service accountsAdministrator

On top of that, the key itself decides what it may do: every ticked scope is an ordinary permission from the same catalogue as Instellingen → Rollen (Settings → Roles).

  • A key never sees more than its owner. If someone works with a restricted client selection, that restriction applies to their key too.
  • Intrekken (Revoke) stops a key immediately. Deleting a service account revokes all of its keys. If the owner of a personal key loses their membership, the key stops working.
  • 600 calls per minute per key. Generous for automation, and a ceiling if a key ever leaks.
  • /api/docs and /api/redoc load their assets from a public CDN. On a server without internet access that page stays blank; /api/openapi.json still works.
  • To not serve the reference at all, set SCHAKL_API_DOCS_ENABLED=false on the server. The API itself keeps working in full.
  • On licensed modules, reading and exporting always keep working; only writes answer 402 once the licence stops covering them. See Licenses.