REST API
Secretary exposes a JSON REST API used by the Web UI and available for programmatic control.
Authentication
Routes are split into three authentication tiers:
| Tier | Auth required | Routes |
|---|---|---|
| Public | None | GET /api/health, POST /api/auth, POST /api/logout |
| UI (session) | Session cookie (secretary_session JWT) |
GET /api/ui/* |
| Shared | Session cookie or Authorization: Bearer <token> |
POST /api/run, POST /api/reload, GET /api/traces |
| Webhook | Authorization: Bearer <SECRETARY_API_TOKEN> |
POST /api/webhook/paperless |
Public routes
GET /api/health
Health check. Returns HTTP 200 when the service is running.
POST /api/auth
Exchange admin credentials for an HttpOnly session cookie.
Request body:
Response: Sets secretary_session cookie on success. Returns HTTP 403 for invalid credentials or if no admin account is configured.
POST /api/logout
Clears the session cookie.
UI routes (/api/ui/*)
All UI routes require a valid session cookie.
GET /api/ui/me
Returns the authenticated admin username.
GET /api/ui/config
Returns non-secret configuration values needed by the frontend.
GET /api/ui/schema
Returns the Rule JSON schema and the editor vocabulary used for the YAML editor autocomplete.
GET /api/ui/rules
Lists all rule files in the rules.d directory with their metadata.
{
"files": [
{
"id": "<file-id>",
"name": "invoices.yml",
"path": "invoices.yml",
"package": null,
"is_vars": false,
"has_draft": false
}
],
"loaded": {
"invoice_acme_title": "Sets the title for ACME invoices.",
"tag_inbox": null
}
}
GET /api/ui/rules/{file_id}
Returns the raw YAML content of a rule file.
PUT /api/ui/rules/{file_id}
Validates and saves the content of a rule file. The request body must be raw UTF-8 YAML. Max 512 KB.
On validation error:
On success:
DELETE /api/ui/rules/{file_id}
Deletes the rule file.
POST /api/ui/rules
Creates a new empty rule file.
Request body:
Response:
POST /api/ui/rules/{file_id}/preview
Renders a _vars.yml file and returns the resulting YAML. Only available for _vars.yml files.
Request body: raw YAML content to preview.
Response:
Shared routes
POST /api/reload
Forces an immediate reload of all rule files from disk.
POST /api/run
Runs rules against documents. Accepts query parameters:
| Parameter | Type | Description |
|---|---|---|
document |
int |
Paperless document ID |
rule_id |
string |
Rule ID to execute |
dry_run |
bool |
Default true |
Dispatch table:
document |
rule_id |
Behaviour |
|---|---|---|
| ✅ | — | All rules against one document (synchronous, returns traces) |
| — | ✅ | One rule against all documents (background task, returns event ID) |
| ✅ | ✅ | One rule against one document (synchronous, returns traces) |
| — | — | HTTP 400 |
Example — dry-run a single document:
Response (synchronous):
{
"ok": true,
"queued": false,
"document": 42,
"rule_id": null,
"dry_run": true,
"traces": [ ... ]
}
Response (background task):
GET /api/traces
Returns recent execution records from the SQLite history.
| Parameter | Default | Description |
|---|---|---|
limit |
100 |
Maximum number of records to return |