API Reference¶
Base path: /api/v1
Conventions¶
Standard Envelope¶
Most endpoints return:
metais optional (pagination, recalculation counts, etc.).
Errors return:
details is optional (usually validation details).
Endpoints That Do Not Use the Envelope¶
GET /api/v1/jobs/:jobId/progress(SSE stream)GET /api/v1/export/duplicates.csv(raw CSV download)GET /api/v1/export/config.json(raw JSON download)GET /api/v1/paperless/documents/:paperlessId/preview(proxied binary stream)GET /api/v1/paperless/documents/:paperlessId/thumb(proxied binary stream)
Error Codes¶
| Code | Status | Meaning |
|---|---|---|
BAD_REQUEST |
400 | Invalid path/query input |
VALIDATION_FAILED |
400 | Invalid request body or params |
UNAUTHORIZED |
401 | Auth failed/missing |
NOT_FOUND |
404 | Resource not found |
CONFLICT |
409 | State conflict |
JOB_ALREADY_RUNNING |
409 | Same-type job already running/pending |
BAD_GATEWAY |
502 | Upstream Paperless request failed |
NOT_READY |
503 | Readiness checks failed |
INTERNAL_ERROR |
500 | Unexpected server error |
Pagination¶
Common pagination params:
| Param | Default | Range |
|---|---|---|
limit |
50 |
1..100 |
offset |
0 |
>=0 |
GET /api/v1/jobs uses limit range 1..200.
Health¶
GET /api/v1/health¶
Returns process liveness.
GET /api/v1/ready¶
Returns readiness checks (database + Paperless reachability).
{
"data": {
"status": "ready",
"checks": {
"database": { "status": "ok" },
"paperless": { "status": "ok" }
}
}
}
If any check fails, returns HTTP 503 with NOT_READY.
Dashboard¶
GET /api/v1/dashboard¶
Returns summary cards and top correspondents.
Sync and Analysis¶
POST /api/v1/sync¶
Starts sync job.
Optional JSON body:
Response (202):
GET /api/v1/sync/status¶
Returns last sync metadata plus active sync job status.
POST /api/v1/analysis¶
Starts analysis job.
Optional JSON body:
Response (202):
GET /api/v1/analysis/status¶
Returns last analysis metadata plus active analysis job status.
Jobs¶
GET /api/v1/jobs¶
List jobs.
Query params:
type:sync | analysis | batch_operationstatus:pending | running | completed | failed | cancelledlimit:1..200
GET /api/v1/jobs/:jobId¶
Get one job.
Job object fields:
{
"id": "...",
"type": "sync",
"status": "running",
"progress": 0.42,
"progressMessage": "...",
"startedAt": "...",
"completedAt": null,
"errorMessage": null,
"resultJson": null,
"createdAt": "..."
}
progress is 0..1.
GET /api/v1/jobs/:jobId/progress¶
SSE stream.
Events:
progresscomplete
Event data shape:
POST /api/v1/jobs/:jobId/cancel¶
Cancels a pending/running job.
Configuration¶
GET /api/v1/config¶
Returns app config key/value map from DB.
PUT /api/v1/config¶
Accepts either:
or:
Returns full config map.
POST /api/v1/config/test-connection¶
Tests Paperless connectivity.
- If body includes
url, validates explicit body config. - Otherwise uses current runtime env config.
Body shape when explicit:
or
Success:
GET /api/v1/config/dedup¶
Returns effective dedup config.
PUT /api/v1/config/dedup¶
Updates dedup config (partial).
- Requires
Content-Type: application/json - Weight fields must sum to 100
If weight keys change, meta.recalculatedGroups is included.
{
"data": {
"numPermutations": 256,
"numBands": 32,
"ngramSize": 3,
"minWords": 20,
"similarityThreshold": 0.75,
"confidenceWeightJaccard": 55,
"confidenceWeightFuzzy": 45,
"fuzzySampleSize": 10000,
"autoAnalyze": true
},
"meta": {
"recalculatedGroups": 42
}
}
Documents¶
GET /api/v1/documents¶
Lists documents.
Query params:
limit,offsetcorrespondentdocumentTypetagprocessingStatus(pending | completed)search(title match)
GET /api/v1/documents/:id¶
Returns one document, plus content and group memberships.
GET /api/v1/documents/stats¶
Returns aggregate document analytics.
Duplicates¶
GET /api/v1/duplicates¶
Lists duplicate groups.
Query params:
limit,offsetminConfidence,maxConfidence(0..1)status(comma-separated:pending,false_positive,ignored,deleted)sortBy(confidence | created_at | member_count)sortOrder(asc | desc)
GET /api/v1/duplicates/:id¶
Returns group details.
Optional query:
light=trueto omit full member text content.
DELETE /api/v1/duplicates/:id¶
Deletes group record and memberships (does not delete documents in Paperless).
GET /api/v1/duplicates/:id/content¶
Returns text content for two members in a group.
Required query params:
docAdocB
PUT /api/v1/duplicates/:id/status¶
Request:
Valid statuses: pending, false_positive, ignored, deleted.
PUT /api/v1/duplicates/:id/primary¶
Request:
GET /api/v1/duplicates/stats¶
Returns totals by status, confidence buckets, and top correspondents.
GET /api/v1/duplicates/graph¶
Returns graph nodes/edges for visualization.
Query params:
minConfidence,maxConfidencestatus(comma-separated)maxGroups(1..500, default100)
Batch Operations¶
POST /api/v1/batch/status¶
Updates status for many groups.
groupIds must contain 1..1000 ids.
Response:
POST /api/v1/batch/delete-non-primary¶
Starts destructive batch delete in Paperless (background job).
Rules:
confirmmust betrue- all groups must currently be
pending
Response (202):
Export / Import¶
GET /api/v1/export/duplicates.csv¶
Downloads CSV. Supports same filter params as GET /api/v1/duplicates.
GET /api/v1/export/config.json¶
Downloads config backup JSON.
POST /api/v1/import/config¶
Imports config backup JSON.
Response:
Paperless Proxy Endpoints¶
GET /api/v1/paperless/documents/:paperlessId/preview¶
Proxies Paperless preview stream.
GET /api/v1/paperless/documents/:paperlessId/thumb¶
Proxies Paperless thumbnail stream.
GET /api/v1/paperless/trash¶
Returns recycle bin count.
POST /api/v1/paperless/trash¶
Request:
Response: