From 81a2b89a3be7c4bd8ab6922cc35c5c3476c4d5b6 Mon Sep 17 00:00:00 2001 From: tb1337 Date: Mon, 16 Mar 2026 07:28:36 +0000 Subject: [PATCH 1/2] Refine concepts --- docs/concepts/custom_field_query.md | 4 +- docs/concepts/custom_fields.md | 27 +++--- docs/concepts/documents.md | 122 +++++++++------------------- docs/concepts/permissions.md | 12 +-- docs/migrating-v5-to-v6.md | 10 +-- docs/resources/status.md | 48 +++++------ 6 files changed, 89 insertions(+), 134 deletions(-) diff --git a/docs/concepts/custom_field_query.md b/docs/concepts/custom_field_query.md index 0cebb11..000523c 100644 --- a/docs/concepts/custom_field_query.md +++ b/docs/concepts/custom_field_query.md @@ -10,7 +10,7 @@ The `custom_field_query` filter lets you search documents by custom field values | ------------------------------------ | ----------------- | ---------------------- | | `CustomFieldQuery(field, op, value)` | — | `[field, op, value]` | | `CustomFieldQueryAnd(q1, q2, …)` | `q1 & q2` | `["AND", [q1, q2, …]]` | -| `CustomFieldQueryOr(q1, q2, …)` | `q1 | q2` | `["OR", [q1, q2, …]]` | +| `CustomFieldQueryOr(q1, q2, …)` | `q1 \| q2` | `["OR", [q1, q2, …]]` | | `CustomFieldQueryNot(q)` | `~q` | `["NOT", q]` | Import from `pypaperless.models.custom_field_query` (or via `pypaperless.models.types`): @@ -136,3 +136,5 @@ Paperless-ngx enforces: - Maximum number of atoms: **20** Exceeding these limits returns a HTTP 400 validation error. + +The full filter specification is in the [Paperless-ngx API reference](https://docs.paperless-ngx.com/api/#filtering-by-custom-fields). diff --git a/docs/concepts/custom_fields.md b/docs/concepts/custom_fields.md index 8b3c8d8..4020ee3 100644 --- a/docs/concepts/custom_fields.md +++ b/docs/concepts/custom_fields.md @@ -18,7 +18,7 @@ Each custom field has a `data_type` which determines the type of its value: | `INTEGER` | `int` | Integer number | | `FLOAT` | `float` | Floating point number | | `MONETARY` | `str` | Currency amount, e.g. `"EUR12.50"` | -| `SELECT` | `int | str` | Selection from predefined options | +| `SELECT` | `int` or `str` | Selection from predefined options | | `DOCUMENT_LINK` | `list[int]` | Links to other documents by ID | --- @@ -91,8 +91,7 @@ print(value.value) Use `default()` to return `None` instead of raising when the field is absent: ```python -value = document.custom_fields.default(8) -if value is not None: +if value := document.custom_fields.default(8): print(value.value) ``` @@ -115,17 +114,17 @@ A `TypeError` is raised if the actual type does not match `expected_type`. When the cache is active, pypaperless instantiates the right subclass automatically: -| Class | `data_type` | `value` type | -| ------------------------------ | -------------------- | ---------------- | -| `CustomFieldStringValue` | `STRING`, `LONGTEXT` | `str` | -| `CustomFieldURLValue` | `URL` | `str` | -| `CustomFieldDateValue` | `DATE` | `datetime.date` | -| `CustomFieldBooleanValue` | `BOOLEAN` | `bool` | -| `CustomFieldIntegerValue` | `INTEGER` | `int` | -| `CustomFieldFloatValue` | `FLOAT` | `float` | -| `CustomFieldMonetaryValue` | `MONETARY` | `str` | -| `CustomFieldSelectValue` | `SELECT` | `int | str` | -| `CustomFieldDocumentLinkValue` | `DOCUMENT_LINK` | `list[int]` | +| Class | `data_type` | `value` type | +| ------------------------------ | -------------------- | --------------- | +| `CustomFieldStringValue` | `STRING`, `LONGTEXT` | `str` | +| `CustomFieldURLValue` | `URL` | `str` | +| `CustomFieldDateValue` | `DATE` | `datetime.date` | +| `CustomFieldBooleanValue` | `BOOLEAN` | `bool` | +| `CustomFieldIntegerValue` | `INTEGER` | `int` | +| `CustomFieldFloatValue` | `FLOAT` | `float` | +| `CustomFieldMonetaryValue` | `MONETARY` | `str` | +| `CustomFieldSelectValue` | `SELECT` | `int` or `str` | +| `CustomFieldDocumentLinkValue` | `DOCUMENT_LINK` | `list[int]` | ### `CustomFieldMonetaryValue` extras diff --git a/docs/concepts/documents.md b/docs/concepts/documents.md index 1f74406..4f124d8 100644 --- a/docs/concepts/documents.md +++ b/docs/concepts/documents.md @@ -11,11 +11,11 @@ document = await paperless.documents(42) print(document.id) print(document.title) -print(document.correspondent) # int (id) or None -print(document.document_type) # int (id) or None -print(document.tags) # list[int] -print(document.created) # datetime.date | None -print(document.content) # extracted text content +print(document.correspondent) +print(document.document_type) +print(document.tags) +print(document.created) +print(document.content) print(document.page_count) print(document.mime_type) print(document.archive_serial_number) @@ -43,15 +43,16 @@ preview = await doc.get_preview() thumbnail = await doc.get_thumbnail() ``` -The `DownloadedDocument` holds: +`DownloadedDocument` gives you the raw bytes plus everything from the response headers you'd need to save or serve the file: -| Attribute | Description | -| ---------------------- | --------------------------------------------- | -| `content` | Raw binary file data | -| `content_type` | MIME type, e.g. `"application/pdf"` | -| `disposition_type` | `"attachment"` or `"inline"` | -| `disposition_filename` | Suggested filename from `Content-Disposition` | -| `original` | Whether the original file was requested | +```python +# save to disk using the filename suggested by the API +with open(download.disposition_filename, "wb") as f: + f.write(download.content) + +print(download.content_type) # e.g. "application/pdf" +print(download.disposition_type) # "attachment" or "inline" +``` ### Requesting the original file @@ -79,30 +80,27 @@ async for document in paperless.documents.search(query="annual report"): ... ``` -### Custom field query - -```python -async for document in paperless.documents.search( - custom_field_query='["amount", "gte", 10000]' -): - ... -``` - -Custom field query syntax is documented in the [Paperless-ngx API reference](https://docs.paperless-ngx.com/api/#filtering-by-custom-fields). - ### Search hits -When a document was returned from a search, it carries a `DocumentSearchHit`: +When a document was returned from a search, it carries a `DocumentSearchHit`. Use `has_search_hit` to branch on it, or the walrus operator to check and bind in one step: ```python if document.has_search_hit: - hit = document.search_hit + print(f"{document.title} matched the query") + +if hit := document.search_hit: print(hit.score) print(hit.highlights) print(hit.note_highlights) print(hit.rank) ``` +`search_hit` is `None` for documents fetched directly (e.g. `paperless.documents(42)`). + +### Custom field query + +For building expressions in a type-safe way, see [Custom field query](custom_field_query.md). + --- ## More-like search @@ -146,11 +144,11 @@ suggestions = await paperless.documents.suggestions(42) doc = await paperless.documents(42) suggestions = await doc.get_suggestions() -print(suggestions.correspondents) # list[int] -print(suggestions.document_types) # list[int] -print(suggestions.tags) # list[int] -print(suggestions.storage_paths) # list[int] -print(suggestions.dates) # list[datetime.date] +print(suggestions.correspondents) +print(suggestions.document_types) +print(suggestions.tags) +print(suggestions.storage_paths) +print(suggestions.dates) ``` --- @@ -209,21 +207,23 @@ print(f"Next ASN: {next_asn}") ## Uploading a document -Use `draft()` to construct a document upload and `save()` to submit it. The document content must be provided as `bytes`. +Use `draft()` to construct a document upload and `save()` to submit it. The document content must be provided as `bytes`. All fields except `document` are optional. ```python with open("invoice.pdf", "rb") as f: content = f.read() draft = paperless.documents.draft( - document=content, - filename="invoice.pdf", + document=content, # required — raw file bytes + filename="invoice.pdf", # original filename title="Invoice 2024-01", created=datetime.datetime(2024, 1, 15), - correspondent=3, - document_type=2, - tags=[1, 5], + correspondent=3, # correspondent ID + document_type=2, # document type ID + storage_path=1, # storage path ID + tags=[1, 5], # tag IDs archive_serial_number=1042, + custom_fields=[3, 8], # custom field IDs (Paperless assigns null values) ) task_id = await paperless.documents.save(draft) @@ -233,35 +233,9 @@ print(f"Upload queued as task: {task_id}") !!! note Unlike other resources, `save()` for documents returns a **task ID string**, not an integer ID. The document is processed asynchronously by Paperless-ngx. Use `paperless.tasks` to monitor the task. -### Document draft fields - -| Field | Description | -| ----------------------- | ------------------------------ | -| `document` | **Required.** Raw file content | -| `filename` | Optional original filename | -| `title` | Document title | -| `created` | Document creation date | -| `correspondent` | Correspondent ID | -| `document_type` | Document type ID | -| `storage_path` | Storage path ID | -| `tags` | Tag IDs | -| `archive_serial_number` | Archive serial number | -| `custom_fields` | Custom field assignments | - -### Uploading with custom fields - -You can attach custom fields in two ways: - -**As a list of field IDs** (Paperless assigns `null` as value): - -```python -draft = paperless.documents.draft( - document=content, - custom_fields=[3, 8], -) -``` +### Uploading with custom field values -**As a `DocumentCustomFieldList`** (with explicit values): +To set explicit values on custom fields at upload time, use `DocumentCustomFieldList`: ```python from pypaperless.models.documents import DocumentCustomFieldList @@ -365,21 +339,3 @@ for entry in entries: # Via the service, passing the document pk explicitly entries = await paperless.documents.history(42) ``` - -### `DocumentHistory` fields - -| Field | Description | -| ----------- | ----------------------------------------------------- | -| `id` | Entry id | -| `document` | Document pk (injected by the service layer) | -| `timestamp` | When the change occurred | -| `action` | `"create"` or `"update"` (`DocumentHistoryAction`) | -| `changes` | Dict mapping field names to `[old, new]` pairs | -| `actor` | The user who made the change (`DocumentHistoryActor`) | - -### `DocumentHistoryActor` fields - -| Field | Description | -| ---------- | --------------- | -| `id` | User id | -| `username` | Username string | diff --git a/docs/concepts/permissions.md b/docs/concepts/permissions.md index 608a05c..b908dcd 100644 --- a/docs/concepts/permissions.md +++ b/docs/concepts/permissions.md @@ -33,8 +33,8 @@ print(doc.owner) print(doc.user_can_change) if doc.has_permissions: - print(doc.permissions.view.users) # list[int] - print(doc.permissions.view.groups) # list[int] + print(doc.permissions.view.users) + print(doc.permissions.view.groups) print(doc.permissions.change.users) print(doc.permissions.change.groups) ``` @@ -164,10 +164,10 @@ Permissions(view_users=[2, 3], change_users=[2], change_groups=[1]) # Read individual scopes perms = doc.permissions -perms.view.users # list[int] -perms.view.groups # list[int] -perms.change.users # list[int] -perms.change.groups # list[int] +perms.view.users +perms.view.groups +perms.change.users +perms.change.groups ``` --- diff --git a/docs/migrating-v5-to-v6.md b/docs/migrating-v5-to-v6.md index fb44e3f..601635f 100644 --- a/docs/migrating-v5-to-v6.md +++ b/docs/migrating-v5-to-v6.md @@ -1,12 +1,10 @@ # Migrating from v5 to v6 -v6 is a full rewrite of pypaperless, motivated by three concrete problems with v5: +v6 is almost a full rewrite of pypaperless. Three things drove it: -- **Tight coupling between models and the HTTP layer.** In v5, every model instance held a reference to the `Paperless` client and called it directly for `update()`, `delete()`, and `save()`. This made models hard to construct in tests and impossible to pass between different client contexts. v6 makes models pure data containers — all I/O goes through service objects. -- **Runtime type safety.** v5 used plain dataclasses with manual dict-to-object conversion. v6 uses Pydantic v2, which validates all incoming API data against the declared field types at parse time. The Pydantic team's own benchmarks show v2 parses 5–17× faster than v1 and catches malformed payloads that would previously have silently produced wrong values. -- **HTTP client ergonomics.** `aiohttp` requires an explicit session lifecycle and has no built-in sync support. `httpx` has a unified sync/async API, ships with a `MockTransport` for testing without a live server, and handles connection pooling transparently. - -The changes are mechanical at call sites but the reasoning is architectural. +- **Models were too tightly coupled to the HTTP layer.** In v5, every model instance carried a reference to the client and called it directly. That made testing awkward and sharing models between contexts impossible. v6 models are plain data — all I/O goes through services. +- **No runtime type safety.** v5 used dataclasses with manual dict conversion, so bad API responses would silently produce wrong values. v6 uses Pydantic v2, which validates every response at parse time. +- **`aiohttp` got removed.** `httpx` is modern, has a cleaner sync/async API and a built-in mock transport that makes testing easier. --- diff --git a/docs/resources/status.md b/docs/resources/status.md index d5fcb06..c6d8043 100644 --- a/docs/resources/status.md +++ b/docs/resources/status.md @@ -22,40 +22,40 @@ The `status` resource reports the health of the Paperless-ngx server — databas ### `StatusDatabase` -| Field | Description | -| ------------------ | ------------------------------------------------------ | -| `type` | Database engine | -| `url` | Connection URL | -| `status` | `"OK"` / `"ERROR"` | -| `error` | Error message if unhealthy | -| `migration_status` | `StatusDatabaseMigration` object (see below) | +| Field | Description | +| ------------------ | -------------------------------------------- | +| `type` | Database engine | +| `url` | Connection URL | +| `status` | `"OK"` / `"ERROR"` | +| `error` | Error message if unhealthy | +| `migration_status` | `StatusDatabaseMigration` object (see below) | ### `StatusDatabaseMigration` -| Field | Description | -| ---------------------- | --------------------------------- | +| Field | Description | +| ---------------------- | ------------------------------------ | | `latest_migration` | Name of the latest applied migration | -| `unapplied_migrations` | List of pending migration names | +| `unapplied_migrations` | List of pending migration names | ### `StatusTasks` | Field | Description | | ------------------------- | --------------------------------------------- | | `redis_url` | Redis connection URL | -| `redis_status` | Redis health (`"OK"` / `"ERROR"`) | +| `redis_status` | Redis health (`"OK"` / `"ERROR"`) | | `redis_error` | Redis error message if unhealthy | | `celery_url` | Celery broker URL | -| `celery_status` | Celery worker health (`"OK"` / `"ERROR"`) | +| `celery_status` | Celery worker health (`"OK"` / `"ERROR"`) | | `celery_error` | Celery error message if unhealthy | | `index_status` | Full-text index health (`"OK"` / `"ERROR"`) | -| `index_last_modified` | Timestamp of last index modification | +| `index_last_modified` | Timestamp of last index modification | | `index_error` | Index error message if unhealthy | | `classifier_status` | ML classifier health (`"OK"` / `"ERROR"`) | -| `classifier_last_trained` | Last classifier training timestamp | -| `classifier_error` | Classifier error message if unhealthy | +| `classifier_last_trained` | Last classifier training timestamp | +| `classifier_error` | Classifier error message if unhealthy | | `sanity_check_status` | Last sanity check result (`"OK"` / `"ERROR"`) | -| `sanity_check_last_run` | Timestamp of last sanity check | -| `sanity_check_error` | Sanity check error message if unhealthy | +| `sanity_check_last_run` | Timestamp of last sanity check | +| `sanity_check_error` | Sanity check error message if unhealthy | ## Fetch @@ -68,18 +68,18 @@ print(status.pngx_version) # "2.13.5" print(status.server_os) # "Linux" # Check storage -if status.storage: - gb_free = status.storage.available / 1024**3 +if storage := status.storage: + gb_free = storage.available / 1024**3 print(f"{gb_free:.1f} GB free") # Check database health -if status.database: - print(status.database.status) # "OK" +if database := status.database: + print(database.status) # "OK" # Check background workers -if status.tasks: - print(status.tasks.celery_status) # "OK" - print(status.tasks.redis_status) # "OK" +if tasks := status.tasks: + print(tasks.celery_status) # "OK" + print(tasks.redis_status) # "OK" # Convenience method for any errors present if status.has_errors(): From 9aba63e3176f6d6a4b5131a97656608a57a967b6 Mon Sep 17 00:00:00 2001 From: tb1337 Date: Mon, 16 Mar 2026 07:53:34 +0000 Subject: [PATCH 2/2] Refine resources --- docs/resources/config.md | 21 +-------- docs/resources/correspondents.md | 20 ++------- docs/resources/custom_fields.md | 23 ++-------- docs/resources/document_types.md | 20 ++------- docs/resources/documents.md | 37 +-------------- docs/resources/groups.md | 10 ++--- docs/resources/mail_accounts.md | 13 +----- docs/resources/mail_rules.md | 29 +----------- docs/resources/processed_mail.md | 15 +------ docs/resources/profile.md | 30 +------------ docs/resources/remote_version.md | 5 +-- docs/resources/saved_views.md | 22 +-------- docs/resources/share_links.md | 23 +--------- docs/resources/statistics.md | 21 +-------- docs/resources/status.md | 53 +--------------------- docs/resources/storage_paths.md | 22 ++------- docs/resources/tags.md | 30 +------------ docs/resources/tasks.md | 22 +-------- docs/resources/trash.md | 8 +--- docs/resources/users.md | 21 +-------- docs/resources/workflows.md | 77 +------------------------------- 21 files changed, 38 insertions(+), 484 deletions(-) diff --git a/docs/resources/config.md b/docs/resources/config.md index 26f3508..6306294 100644 --- a/docs/resources/config.md +++ b/docs/resources/config.md @@ -4,26 +4,7 @@ The `config` resource exposes the Paperless-ngx application configuration. It is ## Model -| Field | Description | -| ------------------------ | ----------------------------------- | -| `id` | Always `1` | -| `user_args` | Extra arguments passed to Tesseract | -| `output_type` | OCR output format (e.g. `"pdf"`) | -| `pages` | Number of pages to OCR (0 = all) | -| `language` | OCR language code | -| `mode` | OCR mode | -| `skip_archive_file` | Archive-skip policy | -| `image_dpi` | DPI for rasterized images | -| `deskew` | Enable deskew | -| `rotate_pages` | Enable automatic page rotation | -| `rotate_pages_threshold` | Rotation confidence threshold | -| `max_image_pixels` | Maximum image size in pixels | -| `app_title` | Paperless web UI title | -| `app_logo` | Paperless web UI logo path | -| `barcodes_enabled` | Enable barcode processing | -| `barcode_string` | Custom barcode separator string | -| `barcode_enable_asn` | Detect ASN from barcodes | -| `barcode_asn_prefix` | Expected ASN barcode prefix | +See [`pypaperless/models/config.py`](https://github.com/tb1337/paperless-api/blob/main/pypaperless/models/config.py) for all fields and types, and the [Paperless-ngx API docs](https://docs.paperless-ngx.com/api/) for the upstream schema. ## Fetch diff --git a/docs/resources/correspondents.md b/docs/resources/correspondents.md index f55d65d..3045664 100644 --- a/docs/resources/correspondents.md +++ b/docs/resources/correspondents.md @@ -4,27 +4,13 @@ Correspondents represent the senders or recipients that Paperless-ngx associates ## Models -### `Correspondent` - -| Field | Description | -| --------------------- | ----------------------------------------- | -| `id` | Primary key | -| `slug` | URL-safe identifier | -| `name` | Display name | -| `document_count` | Number of assigned documents | -| `last_correspondence` | Date of the most recent matching document | - -### `CorrespondentDraft` - -| Field | Description | -| ------ | --------------------------------- | -| `name` | Display name *(required on save)* | +See [`pypaperless/models/correspondents.py`](https://github.com/tb1337/paperless-api/blob/main/pypaperless/models/correspondents.py) for all fields and types, and the [Paperless-ngx API docs](https://docs.paperless-ngx.com/api/) for the upstream schema. ## Fetch one ```python correspondent = await paperless.correspondents(7) -print(correspondent.name) # "ACME Corp" +print(correspondent.name) # "ACME Corp" print(correspondent.document_count) # 42 ``` @@ -39,7 +25,7 @@ all_correspondents = await paperless.correspondents.as_list() # Fetch only a subset matching a filter filtered = [ - c async for c in paperless.correspondents.filter() + c async for c in paperless.correspondents if c.document_count and c.document_count > 0 ] ``` diff --git a/docs/resources/custom_fields.md b/docs/resources/custom_fields.md index 7679764..63937d3 100644 --- a/docs/resources/custom_fields.md +++ b/docs/resources/custom_fields.md @@ -4,24 +4,7 @@ Custom fields let you attach arbitrary typed metadata to documents. This page co ## Models -### `CustomField` - -| Field | Description | -| ------------ | --------------------------- | -| `id` | Primary key | -| `name` | Display name | -| `data_type` | Field type (see below) | -| `extra_data` | Type-specific configuration | - -**`CustomFieldType` values:** `string`, `longtext`, `url`, `date`, `boolean`, `integer`, `float`, `monetary`, `documentlink`, `select` - -### `CustomFieldDraft` - -| Field | Description | -| ------------ | --------------------------------- | -| `name` | Display name *(required on save)* | -| `data_type` | Field type *(required on save)* | -| `extra_data` | Type-specific extras | +See [`pypaperless/models/custom_fields.py`](https://github.com/tb1337/paperless-api/blob/main/pypaperless/models/custom_fields.py) for all fields and types, and the [Paperless-ngx API docs](https://docs.paperless-ngx.com/api/) for the upstream schema. ## Fetch one @@ -37,8 +20,8 @@ print(field.data_type) # CustomFieldType.MONETARY async for field in paperless.custom_fields: print(field.id, field.name, field.data_type) -# Build a name → id lookup -field_map = {f.name: f.id async for f in paperless.custom_fields.filter()} +# Keyed by id +fields = await paperless.custom_fields.as_dict() ``` ## Create diff --git a/docs/resources/document_types.md b/docs/resources/document_types.md index 1ad5552..0133f61 100644 --- a/docs/resources/document_types.md +++ b/docs/resources/document_types.md @@ -4,21 +4,7 @@ Document types classify documents into categories (e.g. *Invoice*, *Contract*, * ## Models -### `DocumentType` - -| Field | Description | -| ---------------- | ---------------------------- | -| `id` | Primary key | -| `slug` | URL-safe identifier | -| `name` | Display name | -| `document_count` | Number of assigned documents | - -### `DocumentTypeDraft` - -| Field | Description | -| ------- | --------------------------------- | -| `name` | Display name *(required on save)* | -| `owner` | Owner user id | +See [`pypaperless/models/document_types.py`](https://github.com/tb1337/paperless-api/blob/main/pypaperless/models/document_types.py) for all fields and types, and the [Paperless-ngx API docs](https://docs.paperless-ngx.com/api/) for the upstream schema. ## Fetch one @@ -34,8 +20,8 @@ print(document_type.document_count) # 17 async for dt in paperless.document_types: print(dt.id, dt.name) -# Map id → name -type_map = {dt.id: dt.name async for dt in paperless.document_types.filter()} +# Keyed by id +types = await paperless.document_types.as_dict() ``` ## Create diff --git a/docs/resources/documents.md b/docs/resources/documents.md index a3f9032..23615ae 100644 --- a/docs/resources/documents.md +++ b/docs/resources/documents.md @@ -4,42 +4,7 @@ Documents are the core resource in Paperless-ngx. This page shows the essential ## Models -### `Document` - -| Field | Description | -| ------------------------ | ------------------------------------- | -| `id` | Primary key | -| `title` | Document title | -| `content` | Full-text content (OCR result) | -| `document_type` | Assigned document type id | -| `correspondent` | Assigned correspondent id | -| `storage_path` | Assigned storage path id | -| `tags` | Assigned tag ids | -| `created` | Creation date (`datetime.date`) | -| `created_date` | Creation date — date-only property | -| `modified` | Last modified timestamp | -| `added` | Date added to Paperless | -| `archive_serial_number` | Archive serial number | -| `original_file_name` | Original uploaded filename | -| `archived_file_name` | Filename of the archived version | -| `page_count` | Number of pages | -| `mime_type` | MIME type of the document | -| `is_shared_by_requester` | Whether the document is shared by you | -| `is_deleted` | `True` when the document is in trash | -| `custom_fields` | Custom field values | - -### `DocumentDraft` - -| Field | Description | -| ----------------------- | --------------------- | -| `title` | Document title | -| `document_type` | Document type id | -| `correspondent` | Correspondent id | -| `storage_path` | Storage path id | -| `tags` | Tag ids | -| `created` | Created date | -| `archive_serial_number` | Archive serial number | -| `custom_fields` | Custom field values | +See [`pypaperless/models/documents.py`](https://github.com/tb1337/paperless-api/blob/main/pypaperless/models/documents.py) for all fields and types, and the [Paperless-ngx API docs](https://docs.paperless-ngx.com/api/) for the upstream schema. ## Fetch one diff --git a/docs/resources/groups.md b/docs/resources/groups.md index d02908a..fa27953 100644 --- a/docs/resources/groups.md +++ b/docs/resources/groups.md @@ -4,11 +4,7 @@ Groups are Paperless-ngx user groups used for permission management. They are re ## Model -| Field | Description | -| ------------- | ------------------------------------------------ | -| `id` | Primary key | -| `name` | Group name | -| `permissions` | Django permission codenames granted to the group | +See [`pypaperless/models/permissions.py`](https://github.com/tb1337/paperless-api/blob/main/pypaperless/models/permissions.py) for all fields and types, and the [Paperless-ngx API docs](https://docs.paperless-ngx.com/api/) for the upstream schema. ## Fetch one @@ -24,6 +20,6 @@ print(group.permissions) # ["view_document", "change_document", ...] async for group in paperless.groups: print(group.id, group.name) -# Build a name → id lookup -group_map = {g.name: g.id async for g in paperless.groups.filter()} +# Keyed by id +groups = await paperless.groups.as_dict() ``` diff --git a/docs/resources/mail_accounts.md b/docs/resources/mail_accounts.md index 91ae536..3ee3f19 100644 --- a/docs/resources/mail_accounts.md +++ b/docs/resources/mail_accounts.md @@ -4,18 +4,7 @@ Mail accounts are the IMAP mailbox configurations that Paperless-ngx polls for i ## Model -| Field | Description | -| --------------- | ------------------------------------- | -| `id` | Primary key | -| `name` | Display name | -| `imap_server` | IMAP hostname | -| `imap_port` | IMAP port | -| `imap_security` | Security mode (None / SSL / STARTTLS) | -| `username` | IMAP username | -| `character_set` | Mailbox character set | -| `is_token` | Whether OAuth token auth is used | -| `account_type` | Account type identifier | -| `expiration` | Token expiry date | +See [`pypaperless/models/mails.py`](https://github.com/tb1337/paperless-api/blob/main/pypaperless/models/mails.py) for all fields and types, and the [Paperless-ngx API docs](https://docs.paperless-ngx.com/api/) for the upstream schema. ## Fetch one diff --git a/docs/resources/mail_rules.md b/docs/resources/mail_rules.md index f03ec76..f0f8547 100644 --- a/docs/resources/mail_rules.md +++ b/docs/resources/mail_rules.md @@ -4,32 +4,7 @@ Mail rules define how Paperless-ngx processes incoming emails from a mail accoun ## Model -| Field | Description | -| ------------------------------------ | ------------------------------------- | -| `id` | Primary key | -| `name` | Display name | -| `account` | Associated mail account id | -| `enabled` | Whether the rule is active | -| `folder` | IMAP folder to watch | -| `filter_from` | Filter by sender address | -| `filter_to` | Filter by recipient address | -| `filter_subject` | Filter by subject line | -| `filter_body` | Filter by body content | -| `filter_attachment_filename_include` | Attachment name include filter | -| `filter_attachment_filename_exclude` | Attachment name exclude filter | -| `maximum_age` | Max age of emails to process (days) | -| `action` | Action to take on matched emails | -| `action_parameter` | Action parameter (e.g. target folder) | -| `assign_title_from` | How to derive the document title | -| `assign_tags` | Tags to assign to imported documents | -| `assign_correspondent` | Correspondent id to assign | -| `assign_correspondent_from` | How to derive the correspondent | -| `assign_document_type` | Document type id to assign | -| `assign_owner_from_rule` | Assign rule owner to the document | -| `order` | Processing order | -| `attachment_type` | Which attachments to import | -| `consumption_scope` | What to consume from the email | -| `pdf_layout` | PDF layout mode for imported email | +See [`pypaperless/models/mails.py`](https://github.com/tb1337/paperless-api/blob/main/pypaperless/models/mails.py) for all fields and types, and the [Paperless-ngx API docs](https://docs.paperless-ngx.com/api/) for the upstream schema. ## Fetch one @@ -48,7 +23,7 @@ async for rule in paperless.mail_rules: print(rule.id, rule.name, "enabled:", rule.enabled) # Only active rules -active = [r async for r in paperless.mail_rules.filter() if r.enabled] +active = [r async for r in paperless.mail_rules if r.enabled] ``` ## Permissions diff --git a/docs/resources/processed_mail.md b/docs/resources/processed_mail.md index ecd62f9..6c6e282 100644 --- a/docs/resources/processed_mail.md +++ b/docs/resources/processed_mail.md @@ -4,18 +4,7 @@ The `processed_mail` resource is a read-only log of emails that have already bee ## Model -| Field | Description | -| ----------- | ------------------------------------------------ | -| `id` | Primary key | -| `owner` | User id of the rule owner | -| `rule` | Mail rule id that processed this email | -| `folder` | IMAP folder the email was found in | -| `uid` | IMAP UID of the email | -| `subject` | Email subject line | -| `received` | When the email was received | -| `processed` | When Paperless processed the email | -| `status` | Processing status (e.g. `"success"`, `"failed"`) | -| `error` | Error message if processing failed | +See [`pypaperless/models/mails.py`](https://github.com/tb1337/paperless-api/blob/main/pypaperless/models/mails.py) for all fields and types, and the [Paperless-ngx API docs](https://docs.paperless-ngx.com/api/) for the upstream schema. ## Fetch one @@ -35,7 +24,7 @@ async for entry in paperless.processed_mail: # Collect all failures failures = [ - e async for e in paperless.processed_mail.filter() + e async for e in paperless.processed_mail if e.status == "failed" ] ``` diff --git a/docs/resources/profile.md b/docs/resources/profile.md index 342edf0..c056122 100644 --- a/docs/resources/profile.md +++ b/docs/resources/profile.md @@ -4,26 +4,7 @@ The `profile` resource exposes the Paperless-ngx user profile for the currently ## Model -### `Profile` - -| Field | Description | -| --------------------- | ---------------------------------------------------------- | -| `email` | User e-mail address | -| `password` | Password placeholder (masked by the API) | -| `first_name` | First name | -| `last_name` | Last name | -| `auth_token` | The API token for the current user (read-only) | -| `social_accounts` | Linked social / OAuth accounts | -| `has_usable_password` | Whether a usable password is set (read-only) | -| `is_mfa_enabled` | Whether multi-factor authentication is enabled (read-only) | - -### `ProfileSocialAccount` - -| Field | Description | -| ---------- | ---------------------------------- | -| `id` | Social account id | -| `provider` | OAuth provider identifier string | -| `name` | Display name of the linked account | +See [`pypaperless/models/profile.py`](https://github.com/tb1337/paperless-api/blob/main/pypaperless/models/profile.py) for all fields and types, and the [Paperless-ngx API docs](https://docs.paperless-ngx.com/api/) for the upstream schema. ## Fetch @@ -56,13 +37,4 @@ updated = await paperless.profile.update( print(updated.first_name) # "Jane" ``` -Supported keyword arguments: - -| Argument | Description | -| ------------ | ----------------------- | -| `email` | New e-mail address | -| `password` | New plain-text password | -| `first_name` | New first name | -| `last_name` | New last name | - `update()` returns a refreshed `Profile` instance reflecting the server response. diff --git a/docs/resources/remote_version.md b/docs/resources/remote_version.md index 4d12585..b2955e2 100644 --- a/docs/resources/remote_version.md +++ b/docs/resources/remote_version.md @@ -4,10 +4,7 @@ The `remote_version` resource reports the latest available version of Paperless- ## Model -| Field | Description | -| ------------------ | ----------- | -| `version` | Latest available version string | -| `update_available` | `True` if a newer version exists | +See [`pypaperless/models/remote_version.py`](https://github.com/tb1337/paperless-api/blob/main/pypaperless/models/remote_version.py) for all fields and types, and the [Paperless-ngx API docs](https://docs.paperless-ngx.com/api/) for the upstream schema. ## Fetch diff --git a/docs/resources/saved_views.md b/docs/resources/saved_views.md index 8cec736..baaa9f5 100644 --- a/docs/resources/saved_views.md +++ b/docs/resources/saved_views.md @@ -4,25 +4,7 @@ Saved views are named document filter presets that can be pinned to the dashboar ## Model -| Field | Description | -| ------------------- | ----------------------------------------------- | -| `id` | Primary key | -| `name` | Display name | -| `show_on_dashboard` | Pin to web UI dashboard | -| `show_in_sidebar` | Show in web UI sidebar | -| `sort_field` | Field to sort results by | -| `sort_reverse` | Sort in descending order | -| `filter_rules` | Active filter rules | -| `page_size` | Number of documents per page | -| `display_mode` | Layout mode (`"table"` / `"smallCards"` / etc.) | -| `display_fields` | Visible column field names | - -### `SavedViewFilterRule` - -| Field | Description | -| ----------- | ---------------------- | -| `rule_type` | Filter type identifier | -| `value` | Filter value | +See [`pypaperless/models/saved_views.py`](https://github.com/tb1337/paperless-api/blob/main/pypaperless/models/saved_views.py) for all fields and types, and the [Paperless-ngx API docs](https://docs.paperless-ngx.com/api/) for the upstream schema. ## Fetch one @@ -41,7 +23,7 @@ async for view in paperless.saved_views: # Only views shown in the sidebar sidebar_views = [ - v async for v in paperless.saved_views.filter() + v async for v in paperless.saved_views if v.show_in_sidebar ] ``` diff --git a/docs/resources/share_links.md b/docs/resources/share_links.md index 7609672..f36ba0f 100644 --- a/docs/resources/share_links.md +++ b/docs/resources/share_links.md @@ -4,26 +4,7 @@ Share links create publicly accessible URLs for individual documents without req ## Models -### `ShareLink` - -| Field | Description | -| -------------- | ----------------------------------------- | -| `id` | Primary key | -| `created` | Creation timestamp | -| `expiration` | Expiry timestamp (`None` = never expires) | -| `slug` | URL slug included in the public link | -| `document` | Associated document id | -| `file_version` | Which file version to share | - -### `ShareLinkDraft` - -| Field | Description | -| -------------- | --------------------------------- | -| `document` | Document id *(required on save)* | -| `file_version` | File version *(required on save)* | -| `expiration` | Optional expiry timestamp | - -**`ShareLinkFileVersion` values:** `"archive"`, `"original"` +See [`pypaperless/models/share_links.py`](https://github.com/tb1337/paperless-api/blob/main/pypaperless/models/share_links.py) for all fields and types, and the [Paperless-ngx API docs](https://docs.paperless-ngx.com/api/) for the upstream schema. ## Fetch one @@ -42,7 +23,7 @@ async for link in paperless.share_links: # Find links for a specific document doc_links = [ - lnk async for lnk in paperless.share_links.filter() + lnk async for lnk in paperless.share_links if lnk.document == 42 ] ``` diff --git a/docs/resources/statistics.md b/docs/resources/statistics.md index d7b81cc..67edd36 100644 --- a/docs/resources/statistics.md +++ b/docs/resources/statistics.md @@ -4,26 +4,7 @@ The `statistics` resource returns aggregate counts and metadata about the Paperl ## Model -| Field | Description | -| --------------------------- | -------------------------------------- | -| `documents_total` | Total number of documents | -| `documents_inbox` | Documents in the inbox | -| `inbox_tag` | Primary inbox tag id | -| `inbox_tags` | All inbox tag ids | -| `document_file_type_counts` | MIME type breakdown | -| `character_count` | Total characters across all documents | -| `tag_count` | Number of tags | -| `correspondent_count` | Number of correspondents | -| `document_type_count` | Number of document types | -| `storage_path_count` | Number of storage paths | -| `current_asn` | Highest assigned archive serial number | - -### `StatisticDocumentFileTypeCount` - -| Field | Description | -| ----------------- | ---------------------------------- | -| `mime_type` | MIME type string | -| `mime_type_count` | Number of documents with this type | +See [`pypaperless/models/statistics.py`](https://github.com/tb1337/paperless-api/blob/main/pypaperless/models/statistics.py) for all fields and types, and the [Paperless-ngx API docs](https://docs.paperless-ngx.com/api/) for the upstream schema. ## Fetch diff --git a/docs/resources/status.md b/docs/resources/status.md index c6d8043..13941f7 100644 --- a/docs/resources/status.md +++ b/docs/resources/status.md @@ -4,58 +4,7 @@ The `status` resource reports the health of the Paperless-ngx server — databas ## Model -| Field | Description | -| -------------- | ----------------------------- | -| `pngx_version` | Running Paperless-ngx version | -| `server_os` | Host operating system | -| `install_type` | Installation method | -| `storage` | Storage usage info | -| `database` | Database status | -| `tasks` | Background task worker status | - -### `StatusStorage` - -| Field | Description | -| ----------- | -------------------------- | -| `total` | Total storage in bytes | -| `available` | Available storage in bytes | - -### `StatusDatabase` - -| Field | Description | -| ------------------ | -------------------------------------------- | -| `type` | Database engine | -| `url` | Connection URL | -| `status` | `"OK"` / `"ERROR"` | -| `error` | Error message if unhealthy | -| `migration_status` | `StatusDatabaseMigration` object (see below) | - -### `StatusDatabaseMigration` - -| Field | Description | -| ---------------------- | ------------------------------------ | -| `latest_migration` | Name of the latest applied migration | -| `unapplied_migrations` | List of pending migration names | - -### `StatusTasks` - -| Field | Description | -| ------------------------- | --------------------------------------------- | -| `redis_url` | Redis connection URL | -| `redis_status` | Redis health (`"OK"` / `"ERROR"`) | -| `redis_error` | Redis error message if unhealthy | -| `celery_url` | Celery broker URL | -| `celery_status` | Celery worker health (`"OK"` / `"ERROR"`) | -| `celery_error` | Celery error message if unhealthy | -| `index_status` | Full-text index health (`"OK"` / `"ERROR"`) | -| `index_last_modified` | Timestamp of last index modification | -| `index_error` | Index error message if unhealthy | -| `classifier_status` | ML classifier health (`"OK"` / `"ERROR"`) | -| `classifier_last_trained` | Last classifier training timestamp | -| `classifier_error` | Classifier error message if unhealthy | -| `sanity_check_status` | Last sanity check result (`"OK"` / `"ERROR"`) | -| `sanity_check_last_run` | Timestamp of last sanity check | -| `sanity_check_error` | Sanity check error message if unhealthy | +See [`pypaperless/models/status.py`](https://github.com/tb1337/paperless-api/blob/main/pypaperless/models/status.py) for all fields and types, and the [Paperless-ngx API docs](https://docs.paperless-ngx.com/api/) for the upstream schema. ## Fetch diff --git a/docs/resources/storage_paths.md b/docs/resources/storage_paths.md index 33d34bf..c21983f 100644 --- a/docs/resources/storage_paths.md +++ b/docs/resources/storage_paths.md @@ -4,23 +4,7 @@ Storage paths define directory templates that control where Paperless-ngx stores ## Models -### `StoragePath` - -| Field | Description | -| ---------------- | ----------------------------------- | -| `id` | Primary key | -| `slug` | URL-safe identifier | -| `name` | Display name | -| `path` | Directory path template | -| `document_count` | Number of documents using this path | - -### `StoragePathDraft` - -| Field | Description | -| ------- | --------------------------------------------------------------------------- | -| `name` | Display name *(required on save)* | -| `path` | Path template, e.g. `"{created_year}/{correspondent}"` *(required on save)* | -| `owner` | Owner user id | +See [`pypaperless/models/storage_paths.py`](https://github.com/tb1337/paperless-api/blob/main/pypaperless/models/storage_paths.py) for all fields and types, and the [Paperless-ngx API docs](https://docs.paperless-ngx.com/api/) for the upstream schema. ## Fetch one @@ -36,8 +20,8 @@ print(sp.path) # "{created_year}/{correspondent}/{title}" async for sp in paperless.storage_paths: print(sp.id, sp.name, sp.path) -# Build a name → path mapping -path_map = {sp.name: sp.path async for sp in paperless.storage_paths.filter()} +# Keyed by id +paths = await paperless.storage_paths.as_dict() ``` ## Create diff --git a/docs/resources/tags.md b/docs/resources/tags.md index b933a35..f618541 100644 --- a/docs/resources/tags.md +++ b/docs/resources/tags.md @@ -4,30 +4,7 @@ Tags are labels that can be applied to documents for classification and filterin ## Models -### `Tag` - -| Field | Description | -| ---------------- | ------------------------------------- | -| `id` | Primary key | -| `slug` | URL-safe identifier | -| `name` | Display name | -| `color` | Hex color string (e.g. `"#a6cee3"`) | -| `text_color` | Text color for contrast | -| `is_inbox_tag` | Whether this is the inbox tag | -| `document_count` | Number of documents with this tag | -| `parent` | Parent tag id (for hierarchical tags) | -| `children` | Child tags | - -### `TagDraft` - -| Field | Description | -| -------------- | -------------------------------------- | -| `name` | Display name *(required on save)* | -| `color` | Hex color string *(required on save)* | -| `text_color` | Text color | -| `is_inbox_tag` | Mark as inbox tag *(required on save)* | -| `parent` | Parent tag id | -| `owner` | Owner user id | +See [`pypaperless/models/tags.py`](https://github.com/tb1337/paperless-api/blob/main/pypaperless/models/tags.py) for all fields and types, and the [Paperless-ngx API docs](https://docs.paperless-ngx.com/api/) for the upstream schema. ## Fetch one @@ -44,12 +21,9 @@ print(tag.document_count) # 38 async for tag in paperless.tags: print(tag.id, tag.name, tag.color) -# Name → id lookup -tag_map = {t.name: t.id async for t in paperless.tags.filter()} - # Find the inbox tag inbox = next( - (t async for t in paperless.tags.filter() if t.is_inbox_tag), + (t async for t in paperless.tags if t.is_inbox_tag), None, ) ``` diff --git a/docs/resources/tasks.md b/docs/resources/tasks.md index a106e1b..319eded 100644 --- a/docs/resources/tasks.md +++ b/docs/resources/tasks.md @@ -4,20 +4,7 @@ Tasks represent Celery background jobs — primarily document consumption jobs. ## Model -| Field | Description | -| ------------------ | ----------------------------------------------------- | -| `id` | Integer primary key | -| `task_id` | Celery UUID string | -| `task_name` | Internal task name | -| `task_file_name` | File that triggered this task | -| `date_created` | When the task was queued | -| `date_done` | When the task finished | -| `type` | Task type | -| `status` | `"PENDING"` / `"STARTED"` / `"SUCCESS"` / `"FAILURE"` / `"REVOKED"` | -| `result` | Result or error message | -| `acknowledged` | Whether the task has been dismissed | -| `related_document` | Document id created by this task | -| `owner` | Owner user id | +See [`pypaperless/models/tasks.py`](https://github.com/tb1337/paperless-api/blob/main/pypaperless/models/tasks.py) for all fields and types, and the [Paperless-ngx API docs](https://docs.paperless-ngx.com/api/) for the upstream schema. ## Fetch by UUID @@ -79,10 +66,3 @@ async for task in paperless.tasks.filter(status="SUCCESS"): async for task in paperless.tasks.filter(acknowledged=False, type="ConsumptionTask"): print(task.task_id) ``` - -| Parameter | Type | Description | -| -------------- | ------ | ---------------------------------------- | -| `acknowledged` | `bool` | Filter by whether the task is dismissed | -| `status` | `str` | Filter by status string | -| `task_name` | `str` | Filter by internal task name | -| `type` | `str` | Filter by task type | diff --git a/docs/resources/trash.md b/docs/resources/trash.md index 07d082f..1914838 100644 --- a/docs/resources/trash.md +++ b/docs/resources/trash.md @@ -4,13 +4,7 @@ The `trash` resource exposes documents that have been soft-deleted in Paperless- ## Model -Trashed documents use the same `Document` model. The only additional field populated in the trash context is: - -| Field | Description | -| ------------ | -------------------------------------------------- | -| `deleted_at` | Timestamp when the document was moved to the trash | - -All other `Document` fields are present as usual. +Trashed documents use the same `Document` model — see [`pypaperless/models/documents.py`](https://github.com/tb1337/paperless-api/blob/main/pypaperless/models/documents.py). In the trash context, `deleted_at` is additionally populated with the timestamp when the document was moved to the trash. ## Iterate diff --git a/docs/resources/users.md b/docs/resources/users.md index 669031e..dbc0bd8 100644 --- a/docs/resources/users.md +++ b/docs/resources/users.md @@ -4,21 +4,7 @@ Users are the Paperless-ngx user accounts. They are read-only from the API persp ## Model -| Field | Description | -| ----------------------- | -------------------------------------- | -| `id` | Primary key | -| `username` | Login username | -| `email` | Email address | -| `first_name` | First name | -| `last_name` | Last name | -| `date_joined` | Account creation date | -| `is_staff` | Staff user flag | -| `is_active` | Account active flag | -| `is_superuser` | Superuser flag | -| `groups` | Group ids the user belongs to | -| `user_permissions` | Directly assigned permission codenames | -| `inherited_permissions` | Permissions inherited from groups | -| `is_mfa_enabled` | Whether MFA is enabled | +See [`pypaperless/models/permissions.py`](https://github.com/tb1337/paperless-api/blob/main/pypaperless/models/permissions.py) for all fields and types, and the [Paperless-ngx API docs](https://docs.paperless-ngx.com/api/) for the upstream schema. ## Fetch one @@ -35,9 +21,6 @@ print(user.groups) # [2, 5] async for user in paperless.users: print(user.id, user.username, user.email) -# Username → id lookup -user_map = {u.username: u.id async for u in paperless.users.filter()} - # Find all superusers -admins = [u async for u in paperless.users.filter() if u.is_superuser] +admins = [u async for u in paperless.users if u.is_superuser] ``` diff --git a/docs/resources/workflows.md b/docs/resources/workflows.md index eede126..f1954af 100644 --- a/docs/resources/workflows.md +++ b/docs/resources/workflows.md @@ -4,80 +4,7 @@ Workflows automate document processing in Paperless-ngx. Each workflow has one o ## Models -### `Workflow` - -| Field | Description | -| ---------- | ------------------------------ | -| `id` | Primary key | -| `name` | Display name | -| `order` | Execution priority | -| `enabled` | Whether the workflow is active | -| `triggers` | Trigger ids / objects | -| `actions` | Action ids / objects | - -### `WorkflowTrigger` - -| Field | Description | -| ---------------------------------- | ----------------------------------------------- | -| `id` | Primary key | -| `type` | Trigger type | -| `sources` | Consumption sources | -| `filter_filename` | Filename pattern filter | -| `filter_path` | Path pattern filter | -| `filter_mailrule` | Mail rule id filter | -| `filter_has_tags` | Required tags (document must have all of these) | -| `filter_has_all_tags` | Required tags (all must match) | -| `filter_has_not_tags` | Excluded tags (none may match) | -| `filter_custom_field_query` | Custom field query expression | -| `filter_has_correspondent` | Required correspondent id | -| `filter_has_not_correspondents` | Excluded correspondent ids | -| `filter_has_document_type` | Required document type id | -| `filter_has_not_document_types` | Excluded document type ids | -| `filter_has_storage_path` | Required storage path id | -| `filter_has_not_storage_paths` | Excluded storage path ids | -| `schedule_offset_days` | Scheduled trigger day offset | -| `schedule_is_recurring` | Whether the schedule repeats | -| `schedule_recurring_interval_days` | Interval in days for recurring schedules | -| `schedule_date_field` | Date field used for schedule evaluation | -| `schedule_date_custom_field` | Custom field id used as the schedule date | - -### `WorkflowAction` - -| Field | Description | -| ----------------------------- | ------------------------------------------ | -| `id` | Primary key | -| `type` | Action type | -| `assign_title` | Title template to assign | -| `assign_tags` | Tags to assign | -| `assign_correspondent` | Correspondent id to assign | -| `assign_document_type` | Document type id to assign | -| `assign_storage_path` | Storage path id to assign | -| `assign_owner` | Owner user id to assign | -| `assign_view_users` | User ids to grant view permission | -| `assign_view_groups` | Group ids to grant view permission | -| `assign_change_users` | User ids to grant change permission | -| `assign_change_groups` | Group ids to grant change permission | -| `assign_custom_fields` | Custom field ids to assign | -| `assign_custom_fields_values` | Values for the assigned custom fields | -| `remove_all_tags` | Remove all existing tags | -| `remove_tags` | Tag ids to remove | -| `remove_all_correspondents` | Remove all existing correspondents | -| `remove_correspondents` | Correspondent ids to remove | -| `remove_all_document_types` | Remove all existing document types | -| `remove_document_types` | Document type ids to remove | -| `remove_all_storage_paths` | Remove all existing storage paths | -| `remove_storage_paths` | Storage path ids to remove | -| `remove_all_custom_fields` | Remove all existing custom fields | -| `remove_custom_fields` | Custom field ids to remove | -| `remove_all_owners` | Remove all existing owners | -| `remove_owners` | Owner ids to remove | -| `remove_all_permissions` | Remove all existing permissions | -| `remove_view_users` | User ids to revoke view permission from | -| `remove_view_groups` | Group ids to revoke view permission from | -| `remove_change_users` | User ids to revoke change permission from | -| `remove_change_groups` | Group ids to revoke change permission from | -| `email` | Email notification config | -| `webhook` | Webhook notification config | +See [`pypaperless/models/workflows.py`](https://github.com/tb1337/paperless-api/blob/main/pypaperless/models/workflows.py) for all fields and types, and the [Paperless-ngx API docs](https://docs.paperless-ngx.com/api/) for the upstream schema. ## Workflows @@ -96,7 +23,7 @@ async for wf in paperless.workflows: print(wf.id, wf.name, "enabled:", wf.enabled) # Only active workflows -active = [wf async for wf in paperless.workflows.filter() if wf.enabled] +active = [wf async for wf in paperless.workflows if wf.enabled] ``` ## Triggers