Authentication
API keys, scopes, and the per-template allowlist.
Every API call carries an organization-scoped API key as a bearer token. Keys belong to an organization, never to a person, so nothing you do with a key depends on a user still being employed.
Using a key
curl https://thedocdealer.com/api/templates \
-H "Authorization: Bearer dd_live_xxxxxxxxxxxx"The key carries its own organization, so there is no tenant header to send. The prefix marks the
environment: dd_live_, dd_staging_ or dd_dev_.
Creating a key
An organization admin creates keys at /admin/api-keys: name it, tick the scopes it needs, and
optionally restrict it to specific templates.
The plaintext is shown exactly once, in the creation dialog. Only a SHA-256 hash is stored, so it cannot be recovered — if you lose it, revoke the key and make a new one. Store it the way you would store a password.
Revoking (or toggling a key off) takes effect immediately: calls start returning 401.
Scopes
A key may only do what its scopes allow. Two of them spend money — documents:generate and
attachments:analyze both run AI calls, so leave them off a key that only needs to read.
| Scope | Allows |
|---|---|
documents:read | List and read documents, and read a document's context. |
documents:write | Create, update and delete documents. |
documents:generate | Spend AI credit: generate sections, titles, and validation. |
templates:read | List templates and read their form schemas. |
templates:write | Reserved. Template authoring is not reachable with an API key today. |
attachments:read | List, read and download attachments and their analyses. |
attachments:write | Upload and delete attachments; edit analyses. |
attachments:analyze | Spend AI credit: run OCR / extraction over an attachment. |
mcp:tools | Call MCP tools over the JSON-RPC endpoint. |
Two caveats worth knowing rather than discovering. POST /api/documents/generate and POST /api/documents/export currently check only that your key can reach the document — they do not
require documents:generate. And templates:write is declared but unenforced, because template
authoring lives on admin routes an API key cannot reach.
Template allowlist
Scopes say what a key can do; the allowlist says which templates it may do it to. Both must pass.
- Empty (the default) means no restriction — every template in the organization.
- Non-empty restricts the key to those template ids. Documents built from any other template
return
403, and template listings hide them.
A restricted key also cannot reach documents with no template at all, since there is no id to match.
What API keys cannot do
- Manage API keys, or reach any admin route. Those authorize against a real user's organization role, and a key has no user.
Listing documents with a key
GET /api/documents is organization-scoped for an API key, not user-scoped: it returns every
document in the key's organization, newest first, including ones created through the UI by a
person. A key has no user, so "my documents" is not a question it can answer.
A key with a template allowlist sees only documents built from those templates, matching what it would be allowed to fetch.
Auth errors
| Status | Means |
|---|---|
401 | Missing, malformed, disabled, deleted or expired key. |
403 | Valid key, but a missing scope or a template outside its allowlist. |
404 | The resource does not exist — or belongs to another organization, reported the same way on purpose. |
Error bodies are always { "error": "…" }.
Other credentials
Two flows use short-lived tokens instead of your key, so you never have to hand it to a browser or an agent: embed sessions for the iframed editor, and MCP OAuth for agents that authenticate as a person.