A Python API wrapper for paperless-ngx
Project description
easypaperless
⚠️ Alpha Release This project is under active development. Breaking changes might occur, but will be documented in the changelog.
easypaperless is a high-level easy-to-use Python API wrapper for Paperless-ngx.
Unlike other wrappers that simply mirror REST endpoints, easypaperless is designed for humans. It provides a true abstraction layer, allowing you to interact with your document management system using intuitive Python methods and objects. You don't need to understand the underlying REST API to be productive.
✨ Key Features
- True Abstraction: Focus on your logic, not on HTTP methods or JSON payloads.
- Developer Experience (DX): Full Type Hinting support. Your IDE (VS Code, PyCharm, etc.) will provide perfect autocompletion and documentation as you type.
- Extensive Coverage: Currently covers a lot of essential workflows from document management to complex bulk operations.
- Async-First with Sync Support: Built on top of httpx, easypaperless is fully asynchronous by default for high-performance applications. But it also offers a synchronous wrapper for a classic blocking workflow.
- Built-in Bulk Tools: Easily manage hundreds of tags, correspondents, or documents with single-method calls.
- Structured Logging: The library emits structured log records under the
easypaperlesslogger hierarchy. Attach any standard Python logging handler to capture API calls, responses, and errors. - Intuitive Error Hierarchy: easypaperless provides descriptive, custom exceptions that tell you exactly what went wrong.
📋 Requirements
- Python: 3.11 or higher
- Paperless-ngx: 2.18 or higher (only tested with 2.18 so far)
Core Dependencies:
- httpx>=0.27
- Pydantic>=2.0
🚀 Installation
Install the package via pip:
pip install easypaperless
🛠 Quickstart
Get up and running in seconds. No API deep-dive required.
Create a API Authentification token in your paperless-ngx user profile and replace "YOUR_TOKEN" in following code examples by your actual token. Replace url with your actual url. Consider to create a dedicated paperless-ngx user for the api usage and limit the permissions to your needs.
async Client
import asyncio
from easypaperless import PaperlessClient
async def main():
# create a paperless client
# we encourage you to use .env files to store your credentials
url = "http://localhost:8000"
api_token = "YOUR_TOKEN"
async with PaperlessClient(url=url, api_token=api_token) as client:
# List documents — full-text search across title and OCR content, return the last 3 docs
# list() returns a PagedResult; use .results for the items and .count for the total
docs = await client.documents.list(
search="test", max_results=3, ordering="added", descending=True
)
print(f"Total matching: {docs.count}")
for doc in docs.results:
print(f"Id: {doc.id} \nTitle: {doc.title} \nadded: {doc.added}\n")
# Fetch a single document
doc = await client.documents.get(id=1)
print(doc.title, doc.created)
# check if a "API_edited" tag already exists - otherwise create it.
tags = await client.tags.list(name_exact="API_edited")
if not tags.results:
await client.tags.create(name="API_edited", color="#40bfb7")
# Update metadata — string names are resolved to IDs automatically
await client.documents.update(id=1, tags=["API_edited"])
# Upload and wait for processing to complete
# doc = await client.documents.upload("path/scan.pdf", title="your title here", wait=True)
# print("Processed:", doc.id)
asyncio.run(main())
sync Client
from easypaperless import SyncPaperlessClient
# same example with the sync client:
# we encourage you to use .env files to store your credentials
url = "http://localhost:8000"
api_token = "YOUR_TOKEN"
with SyncPaperlessClient(url=url, api_token=api_token) as client:
# List documents — full-text search across title and OCR content, return the last 3 docs
# list() returns a PagedResult; use .results for the items and .count for the total
docs = client.documents.list(search="test", max_results=3, ordering="added", descending=True)
print(f"Total matching: {docs.count}")
for doc in docs.results:
print(f"Id: {doc.id} \nTitle: {doc.title} \nadded: {doc.added}\n")
# Fetch a single document
doc1 = client.documents.get(id=1)
print(doc1.title, doc1.created)
# check if a "API_edited" tag already exists - otherwise create it.
tags = client.tags.list(name_exact="API_edited")
if not tags.results:
client.tags.create(name="API_edited", color="#40bfb7")
# Update metadata — string names are resolved to IDs automatically
doc_after_update = client.documents.update(id=1, tags=["API_edited"])
print(doc_after_update.title, doc_after_update.created, doc_after_update.tags)
📖 Functional Overview
All functionality is accessed through resource attributes on the client (e.g. client.documents, client.tags). Both PaperlessClient (async) and SyncPaperlessClient (sync) expose the same resources and methods.
All list() methods return a PagedResult[T] containing .results (the items), .count (total matches from the server), .next / .previous (raw page URLs when requesting a single page), and .all (all matching IDs when provided by the API).
The UNSET sentinel (importable from easypaperless) allows you to distinguish "not provided" from explicit None in optional parameters. Omitting a parameter or passing UNSET leaves the field unchanged; passing None explicitly clears a nullable field.
Client
- PaperlessClient / SyncPaperlessClient Token-based authentication. Configurable timeout, poll interval, and poll timeout for slow instances.
client.documents — Documents
- list() Search and filter documents by title, content, tags, dates, correspondent, and more. The workhorse of the wrapper.
- get() Fetch a single document's data; optionally includes extended file metadata.
- get_metadata() Retrieve file-level technical metadata (checksums, sizes, MIME types) for a specific document.
- update() Partially update document fields like title, tags, or dates using PATCH semantics. Supports
UNSETto distinguish "not provided" from explicitNone. - delete() Permanently remove a document from your Paperless-ngx instance.
- download() Download the binary content of a document — either the archived PDF or the original file.
- thumbnail() Download the thumbnail image of a document as raw bytes.
- upload() Upload a new file to Paperless-ngx and optionally wait for the processing task to complete.
Document Bulk Operations
- bulk_add_tag() Add a single tag to a collection of documents in one request.
- bulk_remove_tag() Strip a specific tag from multiple documents simultaneously.
- bulk_modify_tags() Atomically add and remove multiple tags across a set of documents.
- bulk_delete() Permanently delete a list of documents in a single batch.
- bulk_set_correspondent() Assign or clear the correspondent for multiple documents at once.
- bulk_set_document_type() Change the document type for a group of documents in one go.
- bulk_set_storage_path() Update the storage path for multiple documents simultaneously.
- bulk_modify_custom_fields() Batch update or remove custom field values across multiple documents.
- bulk_set_permissions() Manage ownership and access permissions for a list of documents.
- bulk_download() Download multiple documents as a single ZIP archive. Supports choosing the file variant (
archive,originals, orboth), compression algorithm, and optional filename formatting.
client.documents.notes — Document Notes
- list() Retrieve all text notes attached to a specific document.
- create() Add a new text note to an existing document.
- delete() Remove a specific note from a document.
client.tags — Tags
- list() / get() / create() / update() / delete() Full CRUD for document tags, supporting colors and matching algorithms.
- bulk_delete() Batch delete tags.
- bulk_set_permissions() Batch update access control and ownership for tags.
client.correspondents — Correspondents
- list() / get() / create() / update() / delete() Full CRUD for document authors, senders, or recipients.
- bulk_delete() Batch delete correspondents.
- bulk_set_permissions() Batch update access control and ownership for correspondents.
client.document_types — Document Types
- list() / get() / create() / update() / delete() Full CRUD for categories like "Invoice," "Letter," or "Contract."
- bulk_delete() Batch delete document types.
- bulk_set_permissions() Batch update access control and ownership for document types.
client.storage_paths — Storage Paths
- list() / get() / create() / update() / delete() Full CRUD for the physical directory structure where files are stored.
- bulk_delete() Batch delete storage paths.
- bulk_set_permissions() Batch update access control and ownership for storage paths.
client.custom_fields — Custom Fields
- list() / get() / create() / update() / delete() Full CRUD for user-defined metadata fields for advanced document tracking.
client.users — Users
- list() / get() / create() / update() / delete() Full CRUD for Paperless-ngx user accounts. Supports filtering by username and paginated results.
- Use
PaperlessPermission(a typedLiteralalias) for type-safe permission checks againstuser.user_permissionsoruser.inherited_permissions.
client.trash — Trash
- list() List all documents currently in the Paperless-ngx trash bin. Returns
PagedResult[Document]. - restore() Recover one or more trashed documents back to active status.
- empty() Permanently and irreversibly delete trashed documents. This operation cannot be undone.
📚 Documentation
See the 👉 Full API Reference (pdoc)
🤝 Contributing
Contributions are welcome! If you find a bug or have a feature request, please open an issue.
📄 License
This project is licensed under the MIT License.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file easypaperless-0.5.1.tar.gz.
File metadata
- Download URL: easypaperless-0.5.1.tar.gz
- Upload date:
- Size: 515.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
52873487cb7e5c16857d0035e582b83f91dad711db7ed59f18bbf5387ad6b97b
|
|
| MD5 |
78e20b604ac1f9d3d34679897493b785
|
|
| BLAKE2b-256 |
21f0193a0df45987d3245bc2aeec4388c84e8ce4ad7519e514bbfad9c76b0003
|
File details
Details for the file easypaperless-0.5.1-py3-none-any.whl.
File metadata
- Download URL: easypaperless-0.5.1-py3-none-any.whl
- Upload date:
- Size: 68.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4cf762772fd25ed44972f92c483d1b2c6c62f3e5bc208ea676c5822109607f54
|
|
| MD5 |
339ed4004082e018718cfa0d50e7cc04
|
|
| BLAKE2b-256 |
ad1f6dd81f6cf72603f1319c4e24f74e27f2ace0320cc49e5a20f31c75af5788
|