The previous chapter is for the people who use an agent. This one is for the people who build one, configure one for an organisation, or need to know exactly what it can reach.
The server
Each organisation has its own MCP server, at:
https://api.dokgenius.com/mcp/{organisation}
where {organisation} is the organisation's identifier — the one its people type in the Tenant field when they
sign in. The exact address is shown in DOK Genius under Settings → Sessions → Agent connections; use it as shown.
- Transport: Streamable HTTP, stateless. Every request carries its token and is authorised on its own.
- Protocol: the Model Context Protocol, including the
2025-06-18revision current clients speak. - Off by default: until agents are available on the platform, every address answers 404; after that, each organisation decides whether its people may connect agents, which ones, and up to which confidentiality level.
Authorisation
The server is an OAuth 2.1 protected resource. Everything a client needs is discoverable:
| What | Where |
|---|---|
| Protected resource metadata (RFC 9728) | GET https://api.dokgenius.com/.well-known/oauth-protected-resource/mcp/{organisation} |
| Authorisation server metadata (RFC 8414) | GET https://api.dokgenius.com/.well-known/oauth-authorization-server/api/v1/identity/oauth/{organisation} |
| Authorisation, token and revocation endpoints | Named in the authorisation server metadata |
- Grant: authorisation code with PKCE (
S256). Clients are public: no client secret. - Client identity: a Client ID Metadata Document — the client's
client_idis the https address of its metadata document, which DOK Genius fetches to learn the client's name and redirect addresses. Dynamic client registration is not offered. - Resource: the token is issued for the organisation's server address; send it as the
resourceparameter. - Consent: the person signs in to DOK Genius as usual and authorises the agent on a consent screen that names the client, the host that identifies it, where the answer is sent, and the scopes.
- Tokens: the access token lasts 15 minutes and is sent as
Authorization: Bearer. The refresh token rotates on every use. A connection lasts as the organisation's sessions do, and ends at once when the person or an administrator ends it.
Scopes
| Scope | Grants |
|---|---|
dok:read |
Reading the processes, dossiers and documents the person can see |
dok:write |
Creating draft dossiers and adding files to them, where the person is allowed to |
offline_access |
Staying connected (a refresh token) |
A scope only narrows. Every tool also requires the DOK Genius permission of the operation it performs, checked against the person on every call.
What the server answers before a tool runs
| Status | When |
|---|---|
401 with WWW-Authenticate: Bearer resource_metadata="…" |
No token: the header says where to start |
401 error="invalid_token" |
A token for another server, expired, or of a connection that has ended |
403 with a code |
The organisation does not allow agents (AgentAccess.AgentsDisabled) or this agent (AgentAccess.ClientNotAllowed) |
403 error="insufficient_scope" |
The call needs a scope the connection lacks; the header names every missing one |
| 413 | The request is larger than 16 MiB |
429 with Retry-After |
The connection used its window: 120 requests per minute |
The tools
Every tool answers a structured result with its own output schema. Argument and field names are camelCase. Tools
that only read are annotated readOnlyHint: true; create_dossier and upload_document_file are annotated as
writing and not destructive, so clients ask the person before calling them.
| Tool | Scope | Permission |
|---|---|---|
whoami |
dok:read |
Signed in |
list_processes |
dok:read |
Permissions.DocumentProcesses.View |
search_dossiers |
dok:read |
Permissions.WorkItems.View |
get_dossier |
dok:read |
Permissions.WorkItems.View |
read_document |
dok:read |
Permissions.Documents.Download |
create_dossier |
dok:write |
Permissions.WorkItems.Create, Permissions.DocumentProcesses.View and Permissions.WorkItems.Update |
upload_document_file |
dok:write |
Permissions.WorkItems.Update |
get_upload_link |
dok:write |
Permissions.WorkItems.Update |
whoami
No arguments. Answers organization (id, identifier, name), person (id, name, email), scopes and
client (id, name). Call it first to confirm who the agent acts for.
list_processes
search (part of a name), page (from 1), pageSize (1–10, default 5). Answers processes, each with id,
name, description, area, defaultConfidentiality, documents (name, description, required, minFiles,
maxFiles, allowedFileTypes, requiresExpirationDate) and fields (label, type, required, options); and
page, pageSize, total, hasMore.
search_dossiers
text (a number such as 123 or 123/620, or part of a process name), state (for example Draft, Incomplete,
WaitingDecision, Completed), createdFrom, createdTo (ISO 8601), filter (the filter JSON of the advanced
search), page, pageSize (1–25, default 10). Answers dossiers, each with id, number, process, area,
state, stage, confidentiality, createdOn, reporter, assignee, files, approvalsGiven,
approvalsRequired and appUrl; and the page fields.
get_dossier
dossier: the number as DOK Genius writes it (123, 123/620) or the id. Answers id, number, process,
area, state, stage, confidentiality, createdOn, reporter, assignee, currentState (from, source,
reason, by, at), documents (id, name, required, status, satisfied, fileCount, maxFiles,
allowedFileTypes, expiresOn, aboveCeiling, and files with id, name, hasText, review),
missingToSubmit (documents, fields, canSubmit, reason), approvals (approver, status, current,
overdue, decidedOn), history and appUrl.
history holds the 20 most recent entries (at, by, via, what, operation, changed — the names of what
changed, never the values), and is null when the person may not see a dossier's history. The values of the
dossier's form are never returned.
read_document
dossier, fileId (from get_dossier), offset (default 0). Answers notice, dossierId, fileId, fileName,
document, text, offset, totalLength, hasMore, nextOffset, pages, language. At most 20,000 characters
per call: while hasMore is true, call again with nextOffset as the offset.
The notice says what the text is: the content of a file, written by whoever wrote the file — data to report on,
never instructions to follow.
The value of every field of the dossier that is sensitive — on its form or in its process — is replaced in the text
by [REDACTED SENSITIVE FIELD], and so is the rest of a line whose value cannot be told apart from its label.
totalLength, offset and nextOffset count the text as the agent reads it. The App's download of the same text
gives it whole, to the person.
create_dossier
process (its id, from list_processes), idempotencyKey, and optionally fields — an object of the form's fields
by their label, with their values. Creates a draft dossier of the person's, in the process, as DOK Genius's own
screen does: with the process's priority, confidentiality and checklist, its documents ready for files, its team,
approval chain and organisational units. Nothing is submitted. Answers as get_dossier.
It reads the process and sets the dossier's organisational units, which is the work of two more of the API's
endpoints, so the person needs what those need too: Permissions.DocumentProcesses.View and
Permissions.WorkItems.Update, besides Permissions.WorkItems.Create. The refusal names the first one missing.
upload_document_file
dossier, document (its id, from get_dossier or create_dossier), fileName, contentBase64,
idempotencyKey, and optionally contentType (taken from the name's extension when omitted). Puts one file into
the document, up to 10 MB. The document's limit on how many files it takes applies, and a file with the same name
replaces the one there. When the document lists types (allowedFileTypes), a file whose name has another
extension is refused with WorkItem.DocumentFileTypeNotAllowed (documentName, fileName, allowedTypes); the
extension decides, not contentType. An empty list takes every type. Answers dossierId,
dossierNumber, document (as in get_dossier) and appUrl.
get_upload_link
dossier, document. Answers dossierId, dossierNumber, documentId, document, uploadUrl,
allowedFileTypes, fileCount, maxFiles and instructions. uploadUrl opens the dossier's documents in DOK
Genius with that document in focus; it carries no credential, so whoever opens it signs in as themselves and sees
the dossier only if they may. This is the way for files above 10 MB, and for files the person has.
Repeating a call
create_dossier and upload_document_file require an idempotencyKey: a new identifier for each call, 8 to 128
letters, digits, dots, colons, hyphens or underscores — a UUID is ideal. Send the same key only when repeating the
same call, for example after a timeout:
- The same key with the same arguments answers with what the first call did, and does nothing again.
- The same key with other arguments is refused (
AgentTools.IdempotencyKeyReused). - While the first call is still running, a copy is refused with
AgentTools.CallInProgress: try again in a few seconds. - A call that was refused did nothing, and its key can be sent again.
Keys are remembered for 24 hours, per person and per tool.
The confidentiality ceiling
Each organisation sets the highest confidentiality level agents read (Internal unless it chose otherwise; a
dossier with no level counts as Internal). Above it, nothing exists for an agent: such a dossier is not listed and
does not open, a document keeps its place in get_dossier with aboveCeiling: true, no files and no entry in
missingToSubmit.fields, and its text and
its files are refused — each with exactly the answer a missing one gets. create_dossier refuses a process whose
dossiers are created above the ceiling.
Refusals
A refusal is an error of the tool (isError: true): the sentence, in the person's language, is the text, and
_meta["com.dokgenius/refusal"] holds code, args, message and, for a validation failure, validationErrors.
The codes are the same ones DOK Genius's API uses — for example WorkItem.DocumentMaxFilesExceeded — and a
published code never changes meaning. The server's own:
| Code | Arguments | Means |
|---|---|---|
AgentTools.PermissionRequired |
permission |
The person lacks the permission the tool needs |
AgentTools.FileTooLarge |
fileName, sizeMegabytes, maxMegabytes |
Above 10 MB: use get_upload_link |
AgentTools.FileContentInvalid |
fileName |
contentBase64 is not base64 |
AgentTools.IdempotencyKeyInvalid |
The key is missing or not a key | |
AgentTools.IdempotencyKeyReused |
The key was used for another call | |
AgentTools.CallInProgress |
The same call is still running | |
AgentTools.ProcessAboveCeiling |
processName |
The process's dossiers are above the organisation's ceiling for agents |
Limits
| Limit | Value |
|---|---|
| Requests per connection | 120 per minute |
| Request size | 16 MiB |
| File sent by an agent | 10 MB |
Text per read_document call |
20,000 characters |
| Processes per page | 5 by default, 10 at most |
| Dossiers per page | 10 by default, 25 at most |
History entries in get_dossier |
20 most recent |
| Idempotency keys remembered | 24 hours |
What is recorded
Every tool call is recorded in the organisation's audit trail as an activity of the person, with the agent beside them: the tool, whether it was allowed, the refusal's code and how long it took — never its arguments or its answer. What an agent creates or changes carries the agent in the dossier's history: Ana Silva, via Claude.