REST API, version 1
JSON over HTTPS. Each request names the account by the key, not by the subdomain. demo.ervazo.com and ervazo.com respond the same as long as the key belongs to that account.
Base address
Production: https://ervazo.com. The path is always /api/v1, with or without a trailing slash. An unknown path returns 404 with {"error":"Onbekend pad."}.
curl -s https://ervazo.com/api/v1 \
-H "Authorization: Bearer nal_jouw_sleutel"The response is application/json and is not cached. There is no version other than 1.
Turn on
Only the owner of the place. In the workspace: Settings, Public API, Turn API on. Without that flag a valid key is refused with 403 and the text that the public API is off.
A paused account also receives 403, with the text that the account is paused. Revoking a key makes it invalid at once. Turning the flag off leaves the keys in place, but every request stops until you turn it on again.
Key
Create it on the same settings page. Give it a name of at least two characters. The full key appears once. After that we keep only a hash and a prefix, so that you recognise it in the list as nal_ followed by twelve characters.
Send it as a bearer token. No query parameter, no cookie.
Authorization: Bearer nal_…The key must start with nal_ and be between 20 and 200 characters long. Otherwise 401. A wrong or revoked key is the same 401, so that someone guessing cannot tell which of the two it was.
At most eight keys that have not yet been revoked. The ninth attempt fails in the workspace until you revoke one. last_used_at is updated on every successful request.
Limits
120 requests per key per minute, counted in the process that handles the request. Above that, 429: too many requests, wait a minute. The counter is not in the database, so after a restart it starts again.
A POST body may be 20,000 bytes. Larger is 413. The body must be JSON if you send one. Empty is allowed, but a task or a note still needs a field.
A dossier id in the path is 1 to 80 characters: letters, digits, underscore or hyphen. A dossier of another account does not exist for this key and returns 404.
Errors
Errors are JSON with one field error. No stack trace.
- 401 — The key is missing or invalid.
- 403 — The API is off, or the account is paused.
- 404 — Unknown path, or this dossier does not belong to the key.
- 400 — No valid JSON, the title is missing, or the note is empty.
- 409 — The dossier is closed. Reading is allowed, writing is not.
- 413 — The body is larger than 20,000 bytes.
- 429 — More than 120 requests in a minute.
GET /api/v1
Who you are for this key, and which paths there are.
{
"name": "Ervazo",
"version": "1",
"account": "kantoor-id",
"mcp": "/api/mcp",
"endpoints": [
"GET /api/v1/dossiers",
"GET /api/v1/dossiers/{id}",
"POST /api/v1/dossiers/{id}/tasks",
"POST /api/v1/dossiers/{id}/notes"
]
}The list in that response does not name every read path. People involved, assets, debts and the task list are below and do work.
GET /api/v1/dossiers
All dossiers of the account that are not in the trash, newest change first. Closed dossiers are included.
{
"dossiers": [
{
"id": "…",
"reference": "2026-014",
"line": "nalatenschap",
"phase": "boedel",
"status": "open",
"name": "A. de Vries",
"death": "2026-03-02"
}
]
}line is nalatenschap or leven. status is open or closed. death can be empty on a life file. name is the first name and last name joined.
GET /api/v1/dossiers/{id}
Use the id from the list, not the reference number.
{
"dossier": {
"id": "…",
"reference": "2026-014",
"line": "nalatenschap",
"phase": "boedel",
"status": "open",
"firstName": "A.",
"lastName": "de Vries",
"birth": "1948-11-04",
"death": "2026-03-02",
"residence": "Haarlem"
}
}GET /api/v1/dossiers/{id}/parties
People involved. portal says whether that person has the portal turned on. A private note on the person is not included.
{
"parties": [
{
"id": "…",
"type": "heir",
"name": "M. de Vries",
"email": "[email protected]",
"relation": "kind",
"portal": true
}
]
}GET /api/v1/dossiers/{id}/assets
Assets. valueMinor is the amount at death in cents. An empty currency becomes EUR.
{
"assets": [
{
"id": "…",
"category": "bank",
"description": "Betaalrekening",
"valueMinor": 1250000,
"currency": "EUR",
"status": "known"
}
]
}GET /api/v1/dossiers/{id}/liabilities
Debts. amountMinor is cents. creditor is the name as it stands in the dossier.
{
"liabilities": [
{
"id": "…",
"category": "lening",
"description": "Doorlopend krediet",
"amountMinor": 240000,
"currency": "EUR",
"creditor": "Bank",
"status": "open"
}
]
}Read and add tasks
GET /api/v1/dossiers/{id}/tasks — every task with id, title, due and status.
POST /api/v1/dossiers/{id}/tasks
{ "title": "Bankafschriften opvragen", "due": "2026-11-01" }title is required, at most 200 characters after trim. due is optional and must be YYYY-MM-DD. Any other form becomes today. The task comes in open, assigned to the user who created the key, and does not count as a playbook step.
{ "id": "…", "title": "Bankafschriften opvragen", "due": "2026-11-01", "status": "open" }On a closed dossier this is 409. The write is recorded in the audit log as actor API, action api.task.
POST /api/v1/dossiers/{id}/notes
An internal note. The heirs' portal does not show it. The field is called body, not text.
{ "body": "Bank gebeld. Afschriften volgen per post." }At most 4,000 characters after trim. Empty is 400. The response is only the id. In the dossier the author is API and the visibility is internal. The audit log receives api.note with the first 80 characters.
{ "id": "…" }Amounts
All amounts from the API are integers in the smallest currency unit. € 12,500.00 is 1250000. There is no decimal number, so rounding does not differ per client. The currency is stated separately.
What is not included
No document download, no upload, no BSN, no private notes of staff, no deleting, no changing the phase, no inviting an heir and no writing a division. You do those things in the workspace. MCP uses the same limits.