easypaperless.resources
Resource Classes
The following resource classes are _internal classes. Methods can be accessed via the instance of
easypaperless.PaperlessClient or easypaperless.SyncPaperlessClient
Example:
async with PaperlessClient(url="http://localhost:8000", api_token="abc") as client: docs = await client.documents.list(max_results=10)
1"""Resource Classes 2 3The following resource classes are _internal classes. Methods can be accessed via the instance of 4`easypaperless.PaperlessClient` or `easypaperless.SyncPaperlessClient` 5 6Example: 7 async with PaperlessClient(url="http://localhost:8000", api_token="abc") as client: 8 docs = await client.documents.list(max_results=10) 9 10""" 11 12# internal comment: the doc string above is also rendered in the pdoc documentation. 13# 14# original was: 15# 16# Public resource classes — for type annotations and IDE support. 17# 18# Re-exports all async and sync resource classes from the internal modules 19# so that pdoc can document them as a full page with all methods. 20# 21# Example: 22# from easypaperless.resources import DocumentsResource 23 24 25from easypaperless._internal.resources.correspondents import CorrespondentsResource 26from easypaperless._internal.resources.custom_fields import CustomFieldsResource 27from easypaperless._internal.resources.document_types import DocumentTypesResource 28from easypaperless._internal.resources.documents import DocumentsResource, NotesResource 29from easypaperless._internal.resources.storage_paths import StoragePathsResource 30from easypaperless._internal.resources.tags import TagsResource 31from easypaperless._internal.sync_resources.correspondents import SyncCorrespondentsResource 32from easypaperless._internal.sync_resources.custom_fields import SyncCustomFieldsResource 33from easypaperless._internal.sync_resources.document_types import SyncDocumentTypesResource 34from easypaperless._internal.sync_resources.documents import ( 35 SyncDocumentsResource, 36 SyncNotesResource, 37) 38from easypaperless._internal.sync_resources.storage_paths import SyncStoragePathsResource 39from easypaperless._internal.sync_resources.tags import SyncTagsResource 40 41__all__ = [ 42 "CorrespondentsResource", 43 "CustomFieldsResource", 44 "DocumentTypesResource", 45 "DocumentsResource", 46 "NotesResource", 47 "StoragePathsResource", 48 "TagsResource", 49 "SyncCorrespondentsResource", 50 "SyncCustomFieldsResource", 51 "SyncDocumentTypesResource", 52 "SyncDocumentsResource", 53 "SyncNotesResource", 54 "SyncStoragePathsResource", 55 "SyncTagsResource", 56]
21class CorrespondentsResource: 22 """Accessor for correspondents: ``client.correspondents``.""" 23 24 def __init__(self, core: _ClientCore) -> None: 25 self._core = core 26 27 async def list( 28 self, 29 *, 30 ids: List[int] | None = None, 31 name_contains: str | None = None, 32 name_exact: str | None = None, 33 page: int | None = None, 34 page_size: int | None = None, 35 ordering: str | None = None, 36 descending: bool = False, 37 ) -> PagedResult[Correspondent]: 38 """Return correspondents defined in paperless-ngx. 39 40 When ``page`` is ``None`` (the default), all pages are fetched 41 automatically and ``next`` / ``previous`` in the result are always 42 ``None``. When ``page`` is set, only that page is fetched and 43 ``next`` / ``previous`` reflect the raw API values. 44 45 Args: 46 ids: Return only correspondents whose ID is in this list. 47 name_contains: Case-insensitive substring filter on name. 48 name_exact: Case-insensitive exact match on name. 49 page: Return only this specific page (1-based). 50 page_size: Number of results per page. 51 ordering: Field to sort by. 52 descending: When ``True``, reverses the sort direction. 53 54 Returns: 55 :class:`~easypaperless.models.paged_result.PagedResult` of 56 :class:`~easypaperless.models.correspondents.Correspondent` objects. 57 """ 58 logger.info("Listing correspondents") 59 params: dict[str, Any] = {} 60 if ids is not None: 61 params["id__in"] = ",".join(str(i) for i in ids) 62 if name_contains is not None: 63 params["name__icontains"] = name_contains 64 if name_exact is not None: 65 params["name__iexact"] = name_exact 66 if page is not None: 67 params["page"] = page 68 if page_size is not None: 69 params["page_size"] = page_size 70 if ordering is not None: 71 params["ordering"] = f"-{ordering}" if descending else ordering 72 return cast( 73 PagedResult[Correspondent], 74 await self._core._list_resource("correspondents", Correspondent, params or None), 75 ) 76 77 async def get(self, id: int) -> Correspondent: 78 """Fetch a single correspondent by its ID. 79 80 Args: 81 id: Numeric correspondent ID. 82 83 Returns: 84 The :class:`~easypaperless.models.correspondents.Correspondent` with the given ID. 85 86 Raises: 87 ~easypaperless.exceptions.NotFoundError: If no correspondent exists with that ID. 88 """ 89 logger.info("Getting correspondent id=%d", id) 90 return cast( 91 Correspondent, await self._core._get_resource("correspondents", id, Correspondent) 92 ) 93 94 async def create( 95 self, 96 *, 97 name: str, 98 match: str | Unset = UNSET, 99 matching_algorithm: MatchingAlgorithm | Unset = UNSET, 100 is_insensitive: bool = True, 101 owner: int | None | Unset = UNSET, 102 set_permissions: SetPermissions | None | Unset = UNSET, 103 ) -> Correspondent: 104 """Create a new correspondent. 105 106 Args: 107 name: Correspondent name. Must be unique. 108 match: Auto-matching pattern. 109 matching_algorithm: Controls how ``match`` is applied. 110 E.g. ``matching_algorithm=MatchingAlgorithm.REGEX`` for 111 regular-expression matching. 112 is_insensitive: When ``True``, ``match`` is case-insensitive. 113 Defaults to ``True``, matching the paperless-ngx API default. 114 owner: Numeric user ID to assign as owner. 115 set_permissions: Explicit view/change permission sets. 116 Pass ``None`` to create with empty permissions. 117 118 Returns: 119 The newly created :class:`~easypaperless.models.correspondents.Correspondent`. 120 """ 121 logger.info("Creating correspondent name=%r", name) 122 return cast( 123 Correspondent, 124 await self._core._create_resource( 125 "correspondents", 126 Correspondent, 127 owner=owner, 128 set_permissions=set_permissions, 129 name=name, 130 match=match, 131 matching_algorithm=matching_algorithm, 132 is_insensitive=is_insensitive, 133 ), 134 ) 135 136 async def update( 137 self, 138 id: int, 139 *, 140 name: str | Unset = UNSET, 141 match: str | Unset = UNSET, 142 matching_algorithm: MatchingAlgorithm | Unset = UNSET, 143 is_insensitive: bool | Unset = UNSET, 144 owner: int | None | Unset = UNSET, 145 set_permissions: SetPermissions | None | Unset = UNSET, 146 ) -> Correspondent: 147 """Partially update a correspondent (PATCH semantics). 148 149 Args: 150 id: Numeric ID of the correspondent to update. 151 name: Correspondent name. 152 match: Auto-matching pattern. 153 matching_algorithm: Controls how ``match`` is applied. 154 E.g. ``matching_algorithm=MatchingAlgorithm.REGEX`` for 155 regular-expression matching. 156 is_insensitive: When ``True``, ``match`` is case-insensitive. 157 owner: Numeric user ID to assign as owner. 158 Pass ``None`` to clear the owner. 159 Omit (or pass :data:`~easypaperless.UNSET`) to leave unchanged. 160 set_permissions: Explicit view/change permission sets. 161 Pass ``None`` to clear all permissions (overwrite with empty). 162 Omit (or pass :data:`~easypaperless.UNSET`) to leave unchanged. 163 164 Returns: 165 The updated :class:`~easypaperless.models.correspondents.Correspondent`. 166 """ 167 logger.info("Updating correspondent id=%d", id) 168 return cast( 169 Correspondent, 170 await self._core._update_resource( 171 "correspondents", 172 id, 173 Correspondent, 174 name=name, 175 match=match, 176 matching_algorithm=matching_algorithm, 177 is_insensitive=is_insensitive, 178 owner=owner, 179 set_permissions=set_permissions, 180 ), 181 ) 182 183 async def delete(self, id: int) -> None: 184 """Delete a correspondent. 185 186 Args: 187 id: Numeric ID of the correspondent to delete. 188 189 Raises: 190 ~easypaperless.exceptions.NotFoundError: If no correspondent exists with that ID. 191 """ 192 logger.info("Deleting correspondent id=%d", id) 193 await self._core._delete_resource("correspondents", id) 194 195 async def bulk_delete(self, ids: List[int]) -> None: 196 """Permanently delete multiple correspondents in a single request. 197 198 Args: 199 ids: List of correspondent IDs to delete. 200 """ 201 logger.info("Bulk deleting %d correspondents", len(ids)) 202 await self._core._bulk_edit_objects("correspondents", ids, "delete") 203 204 async def bulk_set_permissions( 205 self, 206 ids: List[int], 207 *, 208 set_permissions: SetPermissions | Unset = UNSET, 209 owner: int | None | Unset = UNSET, 210 merge: bool = False, 211 ) -> None: 212 """Set permissions and/or owner on multiple correspondents. 213 214 Args: 215 ids: List of correspondent IDs to modify. 216 set_permissions: Explicit view/change permission sets. 217 Omit (or pass :data:`~easypaperless.UNSET`) to leave unchanged. 218 owner: Numeric user ID to assign as owner. 219 Pass ``None`` to clear the owner. 220 Omit (or pass :data:`~easypaperless.UNSET`) to leave unchanged. 221 merge: When ``True``, new permissions are merged with existing ones. 222 """ 223 logger.info("Bulk setting permissions on %d correspondents", len(ids)) 224 params: dict[str, Any] = {"merge": merge} 225 if not isinstance(set_permissions, Unset): 226 params["permissions"] = set_permissions.model_dump() 227 if not isinstance(owner, Unset): 228 params["owner"] = owner 229 await self._core._bulk_edit_objects("correspondents", ids, "set_permissions", **params)
Accessor for correspondents: client.correspondents.
27 async def list( 28 self, 29 *, 30 ids: List[int] | None = None, 31 name_contains: str | None = None, 32 name_exact: str | None = None, 33 page: int | None = None, 34 page_size: int | None = None, 35 ordering: str | None = None, 36 descending: bool = False, 37 ) -> PagedResult[Correspondent]: 38 """Return correspondents defined in paperless-ngx. 39 40 When ``page`` is ``None`` (the default), all pages are fetched 41 automatically and ``next`` / ``previous`` in the result are always 42 ``None``. When ``page`` is set, only that page is fetched and 43 ``next`` / ``previous`` reflect the raw API values. 44 45 Args: 46 ids: Return only correspondents whose ID is in this list. 47 name_contains: Case-insensitive substring filter on name. 48 name_exact: Case-insensitive exact match on name. 49 page: Return only this specific page (1-based). 50 page_size: Number of results per page. 51 ordering: Field to sort by. 52 descending: When ``True``, reverses the sort direction. 53 54 Returns: 55 :class:`~easypaperless.models.paged_result.PagedResult` of 56 :class:`~easypaperless.models.correspondents.Correspondent` objects. 57 """ 58 logger.info("Listing correspondents") 59 params: dict[str, Any] = {} 60 if ids is not None: 61 params["id__in"] = ",".join(str(i) for i in ids) 62 if name_contains is not None: 63 params["name__icontains"] = name_contains 64 if name_exact is not None: 65 params["name__iexact"] = name_exact 66 if page is not None: 67 params["page"] = page 68 if page_size is not None: 69 params["page_size"] = page_size 70 if ordering is not None: 71 params["ordering"] = f"-{ordering}" if descending else ordering 72 return cast( 73 PagedResult[Correspondent], 74 await self._core._list_resource("correspondents", Correspondent, params or None), 75 )
Return correspondents defined in paperless-ngx.
When page is None (the default), all pages are fetched
automatically and next / previous in the result are always
None. When page is set, only that page is fetched and
next / previous reflect the raw API values.
Arguments:
- ids: Return only correspondents whose ID is in this list.
- name_contains: Case-insensitive substring filter on name.
- name_exact: Case-insensitive exact match on name.
- page: Return only this specific page (1-based).
- page_size: Number of results per page.
- ordering: Field to sort by.
- descending: When
True, reverses the sort direction.
Returns:
~easypaperless.models.paged_result.PagedResultof~easypaperless.models.correspondents.Correspondentobjects.
77 async def get(self, id: int) -> Correspondent: 78 """Fetch a single correspondent by its ID. 79 80 Args: 81 id: Numeric correspondent ID. 82 83 Returns: 84 The :class:`~easypaperless.models.correspondents.Correspondent` with the given ID. 85 86 Raises: 87 ~easypaperless.exceptions.NotFoundError: If no correspondent exists with that ID. 88 """ 89 logger.info("Getting correspondent id=%d", id) 90 return cast( 91 Correspondent, await self._core._get_resource("correspondents", id, Correspondent) 92 )
Fetch a single correspondent by its ID.
Arguments:
- id: Numeric correspondent ID.
Returns:
The
~easypaperless.models.correspondents.Correspondentwith the given ID.
Raises:
- ~easypaperless.exceptions.NotFoundError: If no correspondent exists with that ID.
94 async def create( 95 self, 96 *, 97 name: str, 98 match: str | Unset = UNSET, 99 matching_algorithm: MatchingAlgorithm | Unset = UNSET, 100 is_insensitive: bool = True, 101 owner: int | None | Unset = UNSET, 102 set_permissions: SetPermissions | None | Unset = UNSET, 103 ) -> Correspondent: 104 """Create a new correspondent. 105 106 Args: 107 name: Correspondent name. Must be unique. 108 match: Auto-matching pattern. 109 matching_algorithm: Controls how ``match`` is applied. 110 E.g. ``matching_algorithm=MatchingAlgorithm.REGEX`` for 111 regular-expression matching. 112 is_insensitive: When ``True``, ``match`` is case-insensitive. 113 Defaults to ``True``, matching the paperless-ngx API default. 114 owner: Numeric user ID to assign as owner. 115 set_permissions: Explicit view/change permission sets. 116 Pass ``None`` to create with empty permissions. 117 118 Returns: 119 The newly created :class:`~easypaperless.models.correspondents.Correspondent`. 120 """ 121 logger.info("Creating correspondent name=%r", name) 122 return cast( 123 Correspondent, 124 await self._core._create_resource( 125 "correspondents", 126 Correspondent, 127 owner=owner, 128 set_permissions=set_permissions, 129 name=name, 130 match=match, 131 matching_algorithm=matching_algorithm, 132 is_insensitive=is_insensitive, 133 ), 134 )
Create a new correspondent.
Arguments:
- name: Correspondent name. Must be unique.
- match: Auto-matching pattern.
- matching_algorithm: Controls how
matchis applied. E.g.matching_algorithm=MatchingAlgorithm.REGEXfor regular-expression matching. - is_insensitive: When
True,matchis case-insensitive. Defaults toTrue, matching the paperless-ngx API default. - owner: Numeric user ID to assign as owner.
- set_permissions: Explicit view/change permission sets.
Pass
Noneto create with empty permissions.
Returns:
The newly created
~easypaperless.models.correspondents.Correspondent.
136 async def update( 137 self, 138 id: int, 139 *, 140 name: str | Unset = UNSET, 141 match: str | Unset = UNSET, 142 matching_algorithm: MatchingAlgorithm | Unset = UNSET, 143 is_insensitive: bool | Unset = UNSET, 144 owner: int | None | Unset = UNSET, 145 set_permissions: SetPermissions | None | Unset = UNSET, 146 ) -> Correspondent: 147 """Partially update a correspondent (PATCH semantics). 148 149 Args: 150 id: Numeric ID of the correspondent to update. 151 name: Correspondent name. 152 match: Auto-matching pattern. 153 matching_algorithm: Controls how ``match`` is applied. 154 E.g. ``matching_algorithm=MatchingAlgorithm.REGEX`` for 155 regular-expression matching. 156 is_insensitive: When ``True``, ``match`` is case-insensitive. 157 owner: Numeric user ID to assign as owner. 158 Pass ``None`` to clear the owner. 159 Omit (or pass :data:`~easypaperless.UNSET`) to leave unchanged. 160 set_permissions: Explicit view/change permission sets. 161 Pass ``None`` to clear all permissions (overwrite with empty). 162 Omit (or pass :data:`~easypaperless.UNSET`) to leave unchanged. 163 164 Returns: 165 The updated :class:`~easypaperless.models.correspondents.Correspondent`. 166 """ 167 logger.info("Updating correspondent id=%d", id) 168 return cast( 169 Correspondent, 170 await self._core._update_resource( 171 "correspondents", 172 id, 173 Correspondent, 174 name=name, 175 match=match, 176 matching_algorithm=matching_algorithm, 177 is_insensitive=is_insensitive, 178 owner=owner, 179 set_permissions=set_permissions, 180 ), 181 )
Partially update a correspondent (PATCH semantics).
Arguments:
- id: Numeric ID of the correspondent to update.
- name: Correspondent name.
- match: Auto-matching pattern.
- matching_algorithm: Controls how
matchis applied. E.g.matching_algorithm=MatchingAlgorithm.REGEXfor regular-expression matching. - is_insensitive: When
True,matchis case-insensitive. - owner: Numeric user ID to assign as owner.
Pass
Noneto clear the owner. Omit (or pass~easypaperless.UNSET) to leave unchanged. - set_permissions: Explicit view/change permission sets.
Pass
Noneto clear all permissions (overwrite with empty). Omit (or pass~easypaperless.UNSET) to leave unchanged.
Returns:
The updated
~easypaperless.models.correspondents.Correspondent.
183 async def delete(self, id: int) -> None: 184 """Delete a correspondent. 185 186 Args: 187 id: Numeric ID of the correspondent to delete. 188 189 Raises: 190 ~easypaperless.exceptions.NotFoundError: If no correspondent exists with that ID. 191 """ 192 logger.info("Deleting correspondent id=%d", id) 193 await self._core._delete_resource("correspondents", id)
Delete a correspondent.
Arguments:
- id: Numeric ID of the correspondent to delete.
Raises:
- ~easypaperless.exceptions.NotFoundError: If no correspondent exists with that ID.
195 async def bulk_delete(self, ids: List[int]) -> None: 196 """Permanently delete multiple correspondents in a single request. 197 198 Args: 199 ids: List of correspondent IDs to delete. 200 """ 201 logger.info("Bulk deleting %d correspondents", len(ids)) 202 await self._core._bulk_edit_objects("correspondents", ids, "delete")
Permanently delete multiple correspondents in a single request.
Arguments:
- ids: List of correspondent IDs to delete.
204 async def bulk_set_permissions( 205 self, 206 ids: List[int], 207 *, 208 set_permissions: SetPermissions | Unset = UNSET, 209 owner: int | None | Unset = UNSET, 210 merge: bool = False, 211 ) -> None: 212 """Set permissions and/or owner on multiple correspondents. 213 214 Args: 215 ids: List of correspondent IDs to modify. 216 set_permissions: Explicit view/change permission sets. 217 Omit (or pass :data:`~easypaperless.UNSET`) to leave unchanged. 218 owner: Numeric user ID to assign as owner. 219 Pass ``None`` to clear the owner. 220 Omit (or pass :data:`~easypaperless.UNSET`) to leave unchanged. 221 merge: When ``True``, new permissions are merged with existing ones. 222 """ 223 logger.info("Bulk setting permissions on %d correspondents", len(ids)) 224 params: dict[str, Any] = {"merge": merge} 225 if not isinstance(set_permissions, Unset): 226 params["permissions"] = set_permissions.model_dump() 227 if not isinstance(owner, Unset): 228 params["owner"] = owner 229 await self._core._bulk_edit_objects("correspondents", ids, "set_permissions", **params)
Set permissions and/or owner on multiple correspondents.
Arguments:
- ids: List of correspondent IDs to modify.
- set_permissions: Explicit view/change permission sets.
Omit (or pass
~easypaperless.UNSET) to leave unchanged. - owner: Numeric user ID to assign as owner.
Pass
Noneto clear the owner. Omit (or pass~easypaperless.UNSET) to leave unchanged. - merge: When
True, new permissions are merged with existing ones.
20class CustomFieldsResource: 21 """Accessor for custom fields: ``client.custom_fields``.""" 22 23 def __init__(self, core: _ClientCore) -> None: 24 self._core = core 25 26 async def list( 27 self, 28 *, 29 name_contains: str | None = None, 30 name_exact: str | None = None, 31 page: int | None = None, 32 page_size: int | None = None, 33 ordering: str | None = None, 34 descending: bool = False, 35 ) -> PagedResult[CustomField]: 36 """Return all custom fields defined in paperless-ngx. 37 38 When ``page`` is ``None`` (the default), all pages are fetched 39 automatically and ``next`` / ``previous`` in the result are always 40 ``None``. When ``page`` is set, only that page is fetched and 41 ``next`` / ``previous`` reflect the raw API values. 42 43 Args: 44 name_contains: Case-insensitive substring filter on name. 45 name_exact: Case-insensitive exact match on name. 46 page: Return only this specific page (1-based). 47 page_size: Number of results per page. 48 ordering: Field to sort by. 49 descending: When ``True``, reverses the sort direction. 50 51 Returns: 52 :class:`~easypaperless.models.paged_result.PagedResult` of 53 :class:`~easypaperless.models.custom_fields.CustomField` objects. 54 """ 55 logger.info("Listing custom fields") 56 params: dict[str, Any] = {} 57 if name_contains is not None: 58 params["name__icontains"] = name_contains 59 if name_exact is not None: 60 params["name__iexact"] = name_exact 61 if page is not None: 62 params["page"] = page 63 if page_size is not None: 64 params["page_size"] = page_size 65 if ordering is not None: 66 params["ordering"] = f"-{ordering}" if descending else ordering 67 return cast( 68 PagedResult[CustomField], 69 await self._core._list_resource("custom_fields", CustomField, params or None), 70 ) 71 72 async def get(self, id: int) -> CustomField: 73 """Fetch a single custom field by its ID. 74 75 Args: 76 id: Numeric custom-field ID. 77 78 Returns: 79 The :class:`~easypaperless.models.custom_fields.CustomField` with the given ID. 80 81 Raises: 82 ~easypaperless.exceptions.NotFoundError: If no custom field exists with that ID. 83 """ 84 logger.info("Getting custom field id=%d", id) 85 return cast(CustomField, await self._core._get_resource("custom_fields", id, CustomField)) 86 87 async def create( 88 self, 89 *, 90 name: str, 91 data_type: str, 92 extra_data: Any | None = None, 93 owner: int | None | Unset = UNSET, 94 set_permissions: SetPermissions | None | Unset = UNSET, 95 ) -> CustomField: 96 """Create a new custom field. 97 98 Args: 99 name: Field name shown in the UI. Must be unique. 100 data_type: Value type. One of ``"string"``, ``"boolean"``, 101 ``"integer"``, ``"float"``, ``"monetary"``, ``"date"``, 102 ``"url"``, ``"documentlink"``, ``"select"``. 103 extra_data: Additional configuration for the field type. 104 owner: Numeric user ID to assign as owner. 105 set_permissions: Explicit view/change permission sets. 106 Pass ``None`` to create with empty permissions. 107 108 Returns: 109 The newly created :class:`~easypaperless.models.custom_fields.CustomField`. 110 """ 111 logger.info("Creating custom field name=%r data_type=%r", name, data_type) 112 return cast( 113 CustomField, 114 await self._core._create_resource( 115 "custom_fields", 116 CustomField, 117 owner=owner, 118 set_permissions=set_permissions, 119 name=name, 120 data_type=data_type, 121 extra_data=extra_data, 122 ), 123 ) 124 125 async def update( 126 self, 127 id: int, 128 *, 129 name: str | Unset = UNSET, 130 data_type: str | Unset = UNSET, 131 extra_data: Any | None | Unset = UNSET, 132 owner: int | None | Unset = UNSET, 133 set_permissions: SetPermissions | None | Unset = UNSET, 134 ) -> CustomField: 135 """Partially update a custom field (PATCH semantics). 136 137 Args: 138 id: Numeric ID of the custom field to update. 139 name: Field name shown in the UI. 140 data_type: Value type (e.g. ``"string"``, ``"boolean"``, ``"integer"``). 141 Omit (or pass :data:`~easypaperless.UNSET`) to leave unchanged. 142 extra_data: Additional configuration for the field type. 143 owner: Numeric user ID to assign as owner. 144 Pass ``None`` to clear the owner. 145 Omit (or pass :data:`~easypaperless.UNSET`) to leave unchanged. 146 set_permissions: Explicit view/change permission sets. 147 Pass ``None`` to clear all permissions (overwrite with empty). 148 Omit (or pass :data:`~easypaperless.UNSET`) to leave unchanged. 149 150 Returns: 151 The updated :class:`~easypaperless.models.custom_fields.CustomField`. 152 """ 153 logger.info("Updating custom field id=%d", id) 154 return cast( 155 CustomField, 156 await self._core._update_resource( 157 "custom_fields", 158 id, 159 CustomField, 160 name=name, 161 data_type=data_type, 162 extra_data=extra_data, 163 owner=owner, 164 set_permissions=set_permissions, 165 ), 166 ) 167 168 async def delete(self, id: int) -> None: 169 """Delete a custom field. 170 171 Args: 172 id: Numeric ID of the custom field to delete. 173 174 Raises: 175 ~easypaperless.exceptions.NotFoundError: If no custom field exists with that ID. 176 """ 177 logger.info("Deleting custom field id=%d", id) 178 await self._core._delete_resource("custom_fields", id)
Accessor for custom fields: client.custom_fields.
26 async def list( 27 self, 28 *, 29 name_contains: str | None = None, 30 name_exact: str | None = None, 31 page: int | None = None, 32 page_size: int | None = None, 33 ordering: str | None = None, 34 descending: bool = False, 35 ) -> PagedResult[CustomField]: 36 """Return all custom fields defined in paperless-ngx. 37 38 When ``page`` is ``None`` (the default), all pages are fetched 39 automatically and ``next`` / ``previous`` in the result are always 40 ``None``. When ``page`` is set, only that page is fetched and 41 ``next`` / ``previous`` reflect the raw API values. 42 43 Args: 44 name_contains: Case-insensitive substring filter on name. 45 name_exact: Case-insensitive exact match on name. 46 page: Return only this specific page (1-based). 47 page_size: Number of results per page. 48 ordering: Field to sort by. 49 descending: When ``True``, reverses the sort direction. 50 51 Returns: 52 :class:`~easypaperless.models.paged_result.PagedResult` of 53 :class:`~easypaperless.models.custom_fields.CustomField` objects. 54 """ 55 logger.info("Listing custom fields") 56 params: dict[str, Any] = {} 57 if name_contains is not None: 58 params["name__icontains"] = name_contains 59 if name_exact is not None: 60 params["name__iexact"] = name_exact 61 if page is not None: 62 params["page"] = page 63 if page_size is not None: 64 params["page_size"] = page_size 65 if ordering is not None: 66 params["ordering"] = f"-{ordering}" if descending else ordering 67 return cast( 68 PagedResult[CustomField], 69 await self._core._list_resource("custom_fields", CustomField, params or None), 70 )
Return all custom fields defined in paperless-ngx.
When page is None (the default), all pages are fetched
automatically and next / previous in the result are always
None. When page is set, only that page is fetched and
next / previous reflect the raw API values.
Arguments:
- name_contains: Case-insensitive substring filter on name.
- name_exact: Case-insensitive exact match on name.
- page: Return only this specific page (1-based).
- page_size: Number of results per page.
- ordering: Field to sort by.
- descending: When
True, reverses the sort direction.
Returns:
~easypaperless.models.paged_result.PagedResultof~easypaperless.models.custom_fields.CustomFieldobjects.
72 async def get(self, id: int) -> CustomField: 73 """Fetch a single custom field by its ID. 74 75 Args: 76 id: Numeric custom-field ID. 77 78 Returns: 79 The :class:`~easypaperless.models.custom_fields.CustomField` with the given ID. 80 81 Raises: 82 ~easypaperless.exceptions.NotFoundError: If no custom field exists with that ID. 83 """ 84 logger.info("Getting custom field id=%d", id) 85 return cast(CustomField, await self._core._get_resource("custom_fields", id, CustomField))
Fetch a single custom field by its ID.
Arguments:
- id: Numeric custom-field ID.
Returns:
The
~easypaperless.models.custom_fields.CustomFieldwith the given ID.
Raises:
- ~easypaperless.exceptions.NotFoundError: If no custom field exists with that ID.
87 async def create( 88 self, 89 *, 90 name: str, 91 data_type: str, 92 extra_data: Any | None = None, 93 owner: int | None | Unset = UNSET, 94 set_permissions: SetPermissions | None | Unset = UNSET, 95 ) -> CustomField: 96 """Create a new custom field. 97 98 Args: 99 name: Field name shown in the UI. Must be unique. 100 data_type: Value type. One of ``"string"``, ``"boolean"``, 101 ``"integer"``, ``"float"``, ``"monetary"``, ``"date"``, 102 ``"url"``, ``"documentlink"``, ``"select"``. 103 extra_data: Additional configuration for the field type. 104 owner: Numeric user ID to assign as owner. 105 set_permissions: Explicit view/change permission sets. 106 Pass ``None`` to create with empty permissions. 107 108 Returns: 109 The newly created :class:`~easypaperless.models.custom_fields.CustomField`. 110 """ 111 logger.info("Creating custom field name=%r data_type=%r", name, data_type) 112 return cast( 113 CustomField, 114 await self._core._create_resource( 115 "custom_fields", 116 CustomField, 117 owner=owner, 118 set_permissions=set_permissions, 119 name=name, 120 data_type=data_type, 121 extra_data=extra_data, 122 ), 123 )
Create a new custom field.
Arguments:
- name: Field name shown in the UI. Must be unique.
- data_type: Value type. One of
"string","boolean","integer","float","monetary","date","url","documentlink","select". - extra_data: Additional configuration for the field type.
- owner: Numeric user ID to assign as owner.
- set_permissions: Explicit view/change permission sets.
Pass
Noneto create with empty permissions.
Returns:
The newly created
~easypaperless.models.custom_fields.CustomField.
125 async def update( 126 self, 127 id: int, 128 *, 129 name: str | Unset = UNSET, 130 data_type: str | Unset = UNSET, 131 extra_data: Any | None | Unset = UNSET, 132 owner: int | None | Unset = UNSET, 133 set_permissions: SetPermissions | None | Unset = UNSET, 134 ) -> CustomField: 135 """Partially update a custom field (PATCH semantics). 136 137 Args: 138 id: Numeric ID of the custom field to update. 139 name: Field name shown in the UI. 140 data_type: Value type (e.g. ``"string"``, ``"boolean"``, ``"integer"``). 141 Omit (or pass :data:`~easypaperless.UNSET`) to leave unchanged. 142 extra_data: Additional configuration for the field type. 143 owner: Numeric user ID to assign as owner. 144 Pass ``None`` to clear the owner. 145 Omit (or pass :data:`~easypaperless.UNSET`) to leave unchanged. 146 set_permissions: Explicit view/change permission sets. 147 Pass ``None`` to clear all permissions (overwrite with empty). 148 Omit (or pass :data:`~easypaperless.UNSET`) to leave unchanged. 149 150 Returns: 151 The updated :class:`~easypaperless.models.custom_fields.CustomField`. 152 """ 153 logger.info("Updating custom field id=%d", id) 154 return cast( 155 CustomField, 156 await self._core._update_resource( 157 "custom_fields", 158 id, 159 CustomField, 160 name=name, 161 data_type=data_type, 162 extra_data=extra_data, 163 owner=owner, 164 set_permissions=set_permissions, 165 ), 166 )
Partially update a custom field (PATCH semantics).
Arguments:
- id: Numeric ID of the custom field to update.
- name: Field name shown in the UI.
- data_type: Value type (e.g.
"string","boolean","integer"). Omit (or pass~easypaperless.UNSET) to leave unchanged. - extra_data: Additional configuration for the field type.
- owner: Numeric user ID to assign as owner.
Pass
Noneto clear the owner. Omit (or pass~easypaperless.UNSET) to leave unchanged. - set_permissions: Explicit view/change permission sets.
Pass
Noneto clear all permissions (overwrite with empty). Omit (or pass~easypaperless.UNSET) to leave unchanged.
Returns:
The updated
~easypaperless.models.custom_fields.CustomField.
168 async def delete(self, id: int) -> None: 169 """Delete a custom field. 170 171 Args: 172 id: Numeric ID of the custom field to delete. 173 174 Raises: 175 ~easypaperless.exceptions.NotFoundError: If no custom field exists with that ID. 176 """ 177 logger.info("Deleting custom field id=%d", id) 178 await self._core._delete_resource("custom_fields", id)
Delete a custom field.
Arguments:
- id: Numeric ID of the custom field to delete.
Raises:
- ~easypaperless.exceptions.NotFoundError: If no custom field exists with that ID.
21class DocumentTypesResource: 22 """Accessor for document types: ``client.document_types``.""" 23 24 def __init__(self, core: _ClientCore) -> None: 25 self._core = core 26 27 async def list( 28 self, 29 *, 30 ids: List[int] | None = None, 31 name_contains: str | None = None, 32 name_exact: str | None = None, 33 page: int | None = None, 34 page_size: int | None = None, 35 ordering: str | None = None, 36 descending: bool = False, 37 ) -> PagedResult[DocumentType]: 38 """Return document types defined in paperless-ngx. 39 40 When ``page`` is ``None`` (the default), all pages are fetched 41 automatically and ``next`` / ``previous`` in the result are always 42 ``None``. When ``page`` is set, only that page is fetched and 43 ``next`` / ``previous`` reflect the raw API values. 44 45 Args: 46 ids: Return only document types whose ID is in this list. 47 name_contains: Case-insensitive substring filter on name. 48 name_exact: Case-insensitive exact match on name. 49 page: Return only this specific page (1-based). 50 page_size: Number of results per page. 51 ordering: Field to sort by. 52 descending: When ``True``, reverses the sort direction. 53 54 Returns: 55 :class:`~easypaperless.models.paged_result.PagedResult` of 56 :class:`~easypaperless.models.document_types.DocumentType` objects. 57 """ 58 logger.info("Listing document types") 59 params: dict[str, Any] = {} 60 if ids is not None: 61 params["id__in"] = ",".join(str(i) for i in ids) 62 if name_contains is not None: 63 params["name__icontains"] = name_contains 64 if name_exact is not None: 65 params["name__iexact"] = name_exact 66 if page is not None: 67 params["page"] = page 68 if page_size is not None: 69 params["page_size"] = page_size 70 if ordering is not None: 71 params["ordering"] = f"-{ordering}" if descending else ordering 72 return cast( 73 PagedResult[DocumentType], 74 await self._core._list_resource("document_types", DocumentType, params or None), 75 ) 76 77 async def get(self, id: int) -> DocumentType: 78 """Fetch a single document type by its ID. 79 80 Args: 81 id: Numeric document-type ID. 82 83 Returns: 84 The :class:`~easypaperless.models.document_types.DocumentType` with the given ID. 85 86 Raises: 87 ~easypaperless.exceptions.NotFoundError: If no document type exists with that ID. 88 """ 89 logger.info("Getting document type id=%d", id) 90 return cast( 91 DocumentType, await self._core._get_resource("document_types", id, DocumentType) 92 ) 93 94 async def create( 95 self, 96 *, 97 name: str, 98 match: str | Unset = UNSET, 99 matching_algorithm: MatchingAlgorithm | Unset = UNSET, 100 is_insensitive: bool = True, 101 owner: int | None | Unset = UNSET, 102 set_permissions: SetPermissions | None | Unset = UNSET, 103 ) -> DocumentType: 104 """Create a new document type. 105 106 Args: 107 name: Document-type name. Must be unique. 108 match: Auto-matching pattern. 109 matching_algorithm: Controls how ``match`` is applied. 110 E.g. ``matching_algorithm=MatchingAlgorithm.REGEX`` for 111 regular-expression matching. 112 is_insensitive: When ``True``, ``match`` is case-insensitive. 113 Defaults to ``True``, matching the paperless-ngx API default. 114 owner: Numeric user ID to assign as owner. 115 set_permissions: Explicit view/change permission sets. 116 Pass ``None`` to create with empty permissions. 117 118 Returns: 119 The newly created :class:`~easypaperless.models.document_types.DocumentType`. 120 """ 121 logger.info("Creating document type name=%r", name) 122 return cast( 123 DocumentType, 124 await self._core._create_resource( 125 "document_types", 126 DocumentType, 127 owner=owner, 128 set_permissions=set_permissions, 129 name=name, 130 match=match, 131 matching_algorithm=matching_algorithm, 132 is_insensitive=is_insensitive, 133 ), 134 ) 135 136 async def update( 137 self, 138 id: int, 139 *, 140 name: str | Unset = UNSET, 141 match: str | Unset = UNSET, 142 matching_algorithm: MatchingAlgorithm | Unset = UNSET, 143 is_insensitive: bool | Unset = UNSET, 144 owner: int | None | Unset = UNSET, 145 set_permissions: SetPermissions | None | Unset = UNSET, 146 ) -> DocumentType: 147 """Partially update a document type (PATCH semantics). 148 149 Args: 150 id: Numeric ID of the document type to update. 151 name: Document-type name. 152 match: Auto-matching pattern. 153 matching_algorithm: Controls how ``match`` is applied. 154 E.g. ``matching_algorithm=MatchingAlgorithm.REGEX`` for 155 regular-expression matching. 156 is_insensitive: When ``True``, ``match`` is case-insensitive. 157 owner: Numeric user ID to assign as owner. 158 Pass ``None`` to clear the owner. 159 Omit (or pass :data:`~easypaperless.UNSET`) to leave unchanged. 160 set_permissions: Explicit view/change permission sets. 161 Pass ``None`` to clear all permissions (overwrite with empty). 162 Omit (or pass :data:`~easypaperless.UNSET`) to leave unchanged. 163 164 Returns: 165 The updated :class:`~easypaperless.models.document_types.DocumentType`. 166 """ 167 logger.info("Updating document type id=%d", id) 168 return cast( 169 DocumentType, 170 await self._core._update_resource( 171 "document_types", 172 id, 173 DocumentType, 174 name=name, 175 match=match, 176 matching_algorithm=matching_algorithm, 177 is_insensitive=is_insensitive, 178 owner=owner, 179 set_permissions=set_permissions, 180 ), 181 ) 182 183 async def delete(self, id: int) -> None: 184 """Delete a document type. 185 186 Args: 187 id: Numeric ID of the document type to delete. 188 189 Raises: 190 ~easypaperless.exceptions.NotFoundError: If no document type exists with that ID. 191 """ 192 logger.info("Deleting document type id=%d", id) 193 await self._core._delete_resource("document_types", id) 194 195 async def bulk_delete(self, ids: List[int]) -> None: 196 """Permanently delete multiple document types in a single request. 197 198 Args: 199 ids: List of document type IDs to delete. 200 """ 201 logger.info("Bulk deleting %d document types", len(ids)) 202 await self._core._bulk_edit_objects("document_types", ids, "delete") 203 204 async def bulk_set_permissions( 205 self, 206 ids: List[int], 207 *, 208 set_permissions: SetPermissions | Unset = UNSET, 209 owner: int | None | Unset = UNSET, 210 merge: bool = False, 211 ) -> None: 212 """Set permissions and/or owner on multiple document types. 213 214 Args: 215 ids: List of document type IDs to modify. 216 set_permissions: Explicit view/change permission sets. 217 Omit (or pass :data:`~easypaperless.UNSET`) to leave unchanged. 218 owner: Numeric user ID to assign as owner. 219 Pass ``None`` to clear the owner. 220 Omit (or pass :data:`~easypaperless.UNSET`) to leave unchanged. 221 merge: When ``True``, new permissions are merged with existing ones. 222 """ 223 logger.info("Bulk setting permissions on %d document types", len(ids)) 224 params: dict[str, Any] = {"merge": merge} 225 if not isinstance(set_permissions, Unset): 226 params["permissions"] = set_permissions.model_dump() 227 if not isinstance(owner, Unset): 228 params["owner"] = owner 229 await self._core._bulk_edit_objects("document_types", ids, "set_permissions", **params)
Accessor for document types: client.document_types.
27 async def list( 28 self, 29 *, 30 ids: List[int] | None = None, 31 name_contains: str | None = None, 32 name_exact: str | None = None, 33 page: int | None = None, 34 page_size: int | None = None, 35 ordering: str | None = None, 36 descending: bool = False, 37 ) -> PagedResult[DocumentType]: 38 """Return document types defined in paperless-ngx. 39 40 When ``page`` is ``None`` (the default), all pages are fetched 41 automatically and ``next`` / ``previous`` in the result are always 42 ``None``. When ``page`` is set, only that page is fetched and 43 ``next`` / ``previous`` reflect the raw API values. 44 45 Args: 46 ids: Return only document types whose ID is in this list. 47 name_contains: Case-insensitive substring filter on name. 48 name_exact: Case-insensitive exact match on name. 49 page: Return only this specific page (1-based). 50 page_size: Number of results per page. 51 ordering: Field to sort by. 52 descending: When ``True``, reverses the sort direction. 53 54 Returns: 55 :class:`~easypaperless.models.paged_result.PagedResult` of 56 :class:`~easypaperless.models.document_types.DocumentType` objects. 57 """ 58 logger.info("Listing document types") 59 params: dict[str, Any] = {} 60 if ids is not None: 61 params["id__in"] = ",".join(str(i) for i in ids) 62 if name_contains is not None: 63 params["name__icontains"] = name_contains 64 if name_exact is not None: 65 params["name__iexact"] = name_exact 66 if page is not None: 67 params["page"] = page 68 if page_size is not None: 69 params["page_size"] = page_size 70 if ordering is not None: 71 params["ordering"] = f"-{ordering}" if descending else ordering 72 return cast( 73 PagedResult[DocumentType], 74 await self._core._list_resource("document_types", DocumentType, params or None), 75 )
Return document types defined in paperless-ngx.
When page is None (the default), all pages are fetched
automatically and next / previous in the result are always
None. When page is set, only that page is fetched and
next / previous reflect the raw API values.
Arguments:
- ids: Return only document types whose ID is in this list.
- name_contains: Case-insensitive substring filter on name.
- name_exact: Case-insensitive exact match on name.
- page: Return only this specific page (1-based).
- page_size: Number of results per page.
- ordering: Field to sort by.
- descending: When
True, reverses the sort direction.
Returns:
~easypaperless.models.paged_result.PagedResultof~easypaperless.models.document_types.DocumentTypeobjects.
77 async def get(self, id: int) -> DocumentType: 78 """Fetch a single document type by its ID. 79 80 Args: 81 id: Numeric document-type ID. 82 83 Returns: 84 The :class:`~easypaperless.models.document_types.DocumentType` with the given ID. 85 86 Raises: 87 ~easypaperless.exceptions.NotFoundError: If no document type exists with that ID. 88 """ 89 logger.info("Getting document type id=%d", id) 90 return cast( 91 DocumentType, await self._core._get_resource("document_types", id, DocumentType) 92 )
Fetch a single document type by its ID.
Arguments:
- id: Numeric document-type ID.
Returns:
The
~easypaperless.models.document_types.DocumentTypewith the given ID.
Raises:
- ~easypaperless.exceptions.NotFoundError: If no document type exists with that ID.
94 async def create( 95 self, 96 *, 97 name: str, 98 match: str | Unset = UNSET, 99 matching_algorithm: MatchingAlgorithm | Unset = UNSET, 100 is_insensitive: bool = True, 101 owner: int | None | Unset = UNSET, 102 set_permissions: SetPermissions | None | Unset = UNSET, 103 ) -> DocumentType: 104 """Create a new document type. 105 106 Args: 107 name: Document-type name. Must be unique. 108 match: Auto-matching pattern. 109 matching_algorithm: Controls how ``match`` is applied. 110 E.g. ``matching_algorithm=MatchingAlgorithm.REGEX`` for 111 regular-expression matching. 112 is_insensitive: When ``True``, ``match`` is case-insensitive. 113 Defaults to ``True``, matching the paperless-ngx API default. 114 owner: Numeric user ID to assign as owner. 115 set_permissions: Explicit view/change permission sets. 116 Pass ``None`` to create with empty permissions. 117 118 Returns: 119 The newly created :class:`~easypaperless.models.document_types.DocumentType`. 120 """ 121 logger.info("Creating document type name=%r", name) 122 return cast( 123 DocumentType, 124 await self._core._create_resource( 125 "document_types", 126 DocumentType, 127 owner=owner, 128 set_permissions=set_permissions, 129 name=name, 130 match=match, 131 matching_algorithm=matching_algorithm, 132 is_insensitive=is_insensitive, 133 ), 134 )
Create a new document type.
Arguments:
- name: Document-type name. Must be unique.
- match: Auto-matching pattern.
- matching_algorithm: Controls how
matchis applied. E.g.matching_algorithm=MatchingAlgorithm.REGEXfor regular-expression matching. - is_insensitive: When
True,matchis case-insensitive. Defaults toTrue, matching the paperless-ngx API default. - owner: Numeric user ID to assign as owner.
- set_permissions: Explicit view/change permission sets.
Pass
Noneto create with empty permissions.
Returns:
The newly created
~easypaperless.models.document_types.DocumentType.
136 async def update( 137 self, 138 id: int, 139 *, 140 name: str | Unset = UNSET, 141 match: str | Unset = UNSET, 142 matching_algorithm: MatchingAlgorithm | Unset = UNSET, 143 is_insensitive: bool | Unset = UNSET, 144 owner: int | None | Unset = UNSET, 145 set_permissions: SetPermissions | None | Unset = UNSET, 146 ) -> DocumentType: 147 """Partially update a document type (PATCH semantics). 148 149 Args: 150 id: Numeric ID of the document type to update. 151 name: Document-type name. 152 match: Auto-matching pattern. 153 matching_algorithm: Controls how ``match`` is applied. 154 E.g. ``matching_algorithm=MatchingAlgorithm.REGEX`` for 155 regular-expression matching. 156 is_insensitive: When ``True``, ``match`` is case-insensitive. 157 owner: Numeric user ID to assign as owner. 158 Pass ``None`` to clear the owner. 159 Omit (or pass :data:`~easypaperless.UNSET`) to leave unchanged. 160 set_permissions: Explicit view/change permission sets. 161 Pass ``None`` to clear all permissions (overwrite with empty). 162 Omit (or pass :data:`~easypaperless.UNSET`) to leave unchanged. 163 164 Returns: 165 The updated :class:`~easypaperless.models.document_types.DocumentType`. 166 """ 167 logger.info("Updating document type id=%d", id) 168 return cast( 169 DocumentType, 170 await self._core._update_resource( 171 "document_types", 172 id, 173 DocumentType, 174 name=name, 175 match=match, 176 matching_algorithm=matching_algorithm, 177 is_insensitive=is_insensitive, 178 owner=owner, 179 set_permissions=set_permissions, 180 ), 181 )
Partially update a document type (PATCH semantics).
Arguments:
- id: Numeric ID of the document type to update.
- name: Document-type name.
- match: Auto-matching pattern.
- matching_algorithm: Controls how
matchis applied. E.g.matching_algorithm=MatchingAlgorithm.REGEXfor regular-expression matching. - is_insensitive: When
True,matchis case-insensitive. - owner: Numeric user ID to assign as owner.
Pass
Noneto clear the owner. Omit (or pass~easypaperless.UNSET) to leave unchanged. - set_permissions: Explicit view/change permission sets.
Pass
Noneto clear all permissions (overwrite with empty). Omit (or pass~easypaperless.UNSET) to leave unchanged.
Returns:
The updated
~easypaperless.models.document_types.DocumentType.
183 async def delete(self, id: int) -> None: 184 """Delete a document type. 185 186 Args: 187 id: Numeric ID of the document type to delete. 188 189 Raises: 190 ~easypaperless.exceptions.NotFoundError: If no document type exists with that ID. 191 """ 192 logger.info("Deleting document type id=%d", id) 193 await self._core._delete_resource("document_types", id)
Delete a document type.
Arguments:
- id: Numeric ID of the document type to delete.
Raises:
- ~easypaperless.exceptions.NotFoundError: If no document type exists with that ID.
195 async def bulk_delete(self, ids: List[int]) -> None: 196 """Permanently delete multiple document types in a single request. 197 198 Args: 199 ids: List of document type IDs to delete. 200 """ 201 logger.info("Bulk deleting %d document types", len(ids)) 202 await self._core._bulk_edit_objects("document_types", ids, "delete")
Permanently delete multiple document types in a single request.
Arguments:
- ids: List of document type IDs to delete.
204 async def bulk_set_permissions( 205 self, 206 ids: List[int], 207 *, 208 set_permissions: SetPermissions | Unset = UNSET, 209 owner: int | None | Unset = UNSET, 210 merge: bool = False, 211 ) -> None: 212 """Set permissions and/or owner on multiple document types. 213 214 Args: 215 ids: List of document type IDs to modify. 216 set_permissions: Explicit view/change permission sets. 217 Omit (or pass :data:`~easypaperless.UNSET`) to leave unchanged. 218 owner: Numeric user ID to assign as owner. 219 Pass ``None`` to clear the owner. 220 Omit (or pass :data:`~easypaperless.UNSET`) to leave unchanged. 221 merge: When ``True``, new permissions are merged with existing ones. 222 """ 223 logger.info("Bulk setting permissions on %d document types", len(ids)) 224 params: dict[str, Any] = {"merge": merge} 225 if not isinstance(set_permissions, Unset): 226 params["permissions"] = set_permissions.model_dump() 227 if not isinstance(owner, Unset): 228 params["owner"] = owner 229 await self._core._bulk_edit_objects("document_types", ids, "set_permissions", **params)
Set permissions and/or owner on multiple document types.
Arguments:
- ids: List of document type IDs to modify.
- set_permissions: Explicit view/change permission sets.
Omit (or pass
~easypaperless.UNSET) to leave unchanged. - owner: Numeric user ID to assign as owner.
Pass
Noneto clear the owner. Omit (or pass~easypaperless.UNSET) to leave unchanged. - merge: When
True, new permissions are merged with existing ones.
138class DocumentsResource: 139 """Accessor for documents: ``client.documents``.""" 140 141 def __init__(self, core: _ClientCore) -> None: 142 self._core = core 143 self.notes = NotesResource(core) 144 145 @staticmethod 146 def _format_date_value(value: date | datetime | str) -> str: 147 if isinstance(value, datetime): 148 return value.isoformat() 149 if isinstance(value, date): 150 return value.isoformat() 151 return value 152 153 @staticmethod 154 def _is_datetime(value: date | datetime | str) -> bool: 155 if isinstance(value, datetime): 156 return True 157 if isinstance(value, str): 158 return bool(_DATETIME_STR_RE.match(value)) 159 return False 160 161 async def get(self, id: int, *, include_metadata: bool = False) -> Document: 162 """Fetch a single document by its ID. 163 164 Args: 165 id: Numeric paperless-ngx document ID. 166 include_metadata: When ``True``, the extended file-level metadata 167 is fetched concurrently and attached to the document. 168 Default: ``False``. 169 170 Returns: 171 The :class:`~easypaperless.models.documents.Document` with the 172 given ID. 173 174 Raises: 175 ~easypaperless.exceptions.NotFoundError: If no document exists 176 with that ID. 177 """ 178 logger.info("Getting document id=%d", id) 179 if include_metadata: 180 doc_resp, meta_resp = await asyncio.gather( 181 self._core._session.get(f"/documents/{id}/"), 182 self._core._session.get(f"/documents/{id}/metadata/"), 183 ) 184 data = doc_resp.json() 185 data["metadata"] = meta_resp.json() 186 else: 187 resp = await self._core._session.get(f"/documents/{id}/") 188 data = resp.json() 189 return Document.model_validate(data) 190 191 async def get_metadata(self, id: int) -> DocumentMetadata: 192 """Fetch the extended file-level metadata for a document. 193 194 Args: 195 id: Numeric paperless-ngx document ID. 196 197 Returns: 198 A :class:`~easypaperless.models.documents.DocumentMetadata` instance. 199 200 Raises: 201 ~easypaperless.exceptions.NotFoundError: If no document exists 202 with that ID. 203 """ 204 logger.info("Getting metadata for document id=%d", id) 205 resp = await self._core._session.get(f"/documents/{id}/metadata/") 206 return DocumentMetadata.model_validate(resp.json()) 207 208 async def list( 209 self, 210 *, 211 search: str | None = None, 212 search_mode: str = "title_or_content", 213 ids: List[int] | None = None, 214 tags: List[int | str] | None = None, 215 any_tags: List[int | str] | None = None, 216 exclude_tags: List[int | str] | None = None, 217 correspondent: int | str | None | Unset = UNSET, 218 any_correspondent: List[int | str] | None = None, 219 exclude_correspondents: List[int | str] | None = None, 220 document_type: int | str | None | Unset = UNSET, 221 document_type_name_contains: str | None = None, 222 document_type_name_exact: str | None = None, 223 any_document_type: List[int | str] | None = None, 224 exclude_document_types: List[int | str] | None = None, 225 storage_path: int | str | None | Unset = UNSET, 226 any_storage_paths: List[int | str] | None = None, 227 exclude_storage_paths: List[int | str] | None = None, 228 owner: int | None | Unset = UNSET, 229 exclude_owners: List[int] | None = None, 230 custom_fields: List[int | str] | None = None, 231 any_custom_fields: List[int | str] | None = None, 232 exclude_custom_fields: List[int | str] | None = None, 233 custom_field_query: List[Any] | None = None, 234 archive_serial_number: int | None | Unset = UNSET, 235 archive_serial_number_from: int | None = None, 236 archive_serial_number_till: int | None = None, 237 created_after: date | str | None = None, 238 created_before: date | str | None = None, 239 added_after: date | datetime | str | None = None, 240 added_from: date | datetime | str | None = None, 241 added_before: date | datetime | str | None = None, 242 added_until: date | datetime | str | None = None, 243 modified_after: date | datetime | str | None = None, 244 modified_from: date | datetime | str | None = None, 245 modified_before: date | datetime | str | None = None, 246 modified_until: date | datetime | str | None = None, 247 checksum: str | None = None, 248 page_size: int = 25, 249 page: int | None = None, 250 ordering: str | None = None, 251 descending: bool = False, 252 max_results: int | None = None, 253 on_page: Callable[[int, int | None], None] | None = None, 254 ) -> PagedResult[Document]: 255 """Return a filtered list of documents. 256 257 All tag, correspondent, document-type, storage-path, and custom-field 258 parameters accept either integer IDs or string names. 259 260 When ``page`` is ``None`` (the default), all pages are fetched 261 automatically and ``next`` / ``previous`` in the returned 262 :class:`~easypaperless.models.paged_result.PagedResult` are always 263 ``None`` — even if ``max_results`` truncates the final result set. 264 ``count`` always reflects the server total, not the truncated length. 265 When ``page`` is set to a specific integer, only that one page is 266 fetched and ``next`` / ``previous`` contain the raw API values. 267 268 Args: 269 search: Search string. Behaviour depends on ``search_mode``. 270 search_mode: How ``search`` is applied. One of: 271 ``"title_or_content"`` *(default)*, ``"title"``, ``"query"``, 272 ``"original_filename"``. 273 ids: Return only documents whose ID is in this list. 274 tags: Documents must have **all** of these tags (AND semantics). 275 any_tags: Documents must have **at least one** of these tags. 276 exclude_tags: Documents must have **none** of these tags. 277 correspondent: Filter to documents assigned to this correspondent. 278 Pass ``None`` to return only documents with no correspondent set. 279 any_correspondent: Filter to documents assigned to any of these. 280 exclude_correspondents: Exclude documents assigned to any of these. 281 document_type: Filter to documents of exactly this type. 282 Pass ``None`` to return only documents with no document type set. 283 document_type_name_contains: Case-insensitive substring filter on document type name. 284 document_type_name_exact: Case-insensitive exact match on document type name. 285 any_document_type: Filter to documents whose type is any of these. 286 exclude_document_types: Exclude documents whose type is any of these. 287 storage_path: Filter to documents assigned to this storage path. 288 Pass ``None`` to return only documents with no storage path set. 289 any_storage_paths: Filter to documents assigned to any of these paths. 290 exclude_storage_paths: Exclude documents assigned to any of these paths. 291 owner: Filter to documents owned by this user ID. 292 Pass ``None`` to return only documents with no owner set. 293 exclude_owners: Exclude documents owned by any of these user IDs. 294 custom_fields: Documents must have **all** of these custom fields set. 295 any_custom_fields: Documents must have **at least one** of these fields. 296 exclude_custom_fields: Documents must have **none** of these fields. 297 custom_field_query: Filter documents by custom field values using a nested 298 query structure. See the `paperless-ngx API docs 299 <https://docs.paperless-ngx.com/api/#filtering-by-custom-fields>`_ for 300 the query format. 301 archive_serial_number: Filter by exact archive serial number. 302 Pass ``None`` to return only documents with no ASN set. 303 archive_serial_number_from: Filter by ASN >= this value. 304 archive_serial_number_till: Filter by ASN <= this value. 305 created_after: Only documents created after this date. 306 String input must be ISO-8601: ``"YYYY-MM-DD"``. 307 created_before: Only documents created before this date. 308 String input must be ISO-8601: ``"YYYY-MM-DD"``. 309 added_after: Only documents added after this date/time. 310 String input must be ISO-8601: ``"YYYY-MM-DD"`` for date precision or 311 ``"YYYY-MM-DDTHH:MM:SS"`` for datetime precision. 312 added_from: Only documents added on or after this date/time. 313 String input must be ISO-8601: ``"YYYY-MM-DD"`` or ``"YYYY-MM-DDTHH:MM:SS"``. 314 added_before: Only documents added before this date/time. 315 String input must be ISO-8601: ``"YYYY-MM-DD"`` or ``"YYYY-MM-DDTHH:MM:SS"``. 316 added_until: Only documents added on or before this date/time. 317 String input must be ISO-8601: ``"YYYY-MM-DD"`` or ``"YYYY-MM-DDTHH:MM:SS"``. 318 modified_after: Only documents modified after this date/time. 319 String input must be ISO-8601: ``"YYYY-MM-DD"`` or ``"YYYY-MM-DDTHH:MM:SS"``. 320 modified_from: Only documents modified on or after this date/time. 321 String input must be ISO-8601: ``"YYYY-MM-DD"`` or ``"YYYY-MM-DDTHH:MM:SS"``. 322 modified_before: Only documents modified before this date/time. 323 String input must be ISO-8601: ``"YYYY-MM-DD"`` or ``"YYYY-MM-DDTHH:MM:SS"``. 324 modified_until: Only documents modified on or before this date/time. 325 String input must be ISO-8601: ``"YYYY-MM-DD"`` or ``"YYYY-MM-DDTHH:MM:SS"``. 326 checksum: MD5 checksum of the original file (exact match). 327 page_size: Number of results per API page. Default: ``25``. 328 page: Return only this specific page (1-based). 329 ordering: Field name to sort by. 330 descending: When ``True``, reverses the sort direction. 331 max_results: Stop after collecting this many documents. 332 on_page: Callback invoked after each page fetch. 333 334 Returns: 335 :class:`~easypaperless.models.paged_result.PagedResult` of 336 :class:`~easypaperless.models.documents.Document` objects. 337 """ 338 logger.info("Listing documents") 339 resolver = self._core._resolver 340 params: dict[str, Any] = {"page_size": page_size} 341 342 if search is not None: 343 api_param = _SEARCH_MODE_MAP.get(search_mode, "search") 344 params[api_param] = search 345 346 if ids is not None: 347 params["id__in"] = ",".join(str(i) for i in ids) 348 349 if tags is not None: 350 resolved = await resolver.resolve_list("tags", tags) 351 params["tags__id__all"] = ",".join(str(t) for t in resolved) 352 353 if any_tags is not None: 354 resolved = await resolver.resolve_list("tags", any_tags) 355 params["tags__id__in"] = ",".join(str(t) for t in resolved) 356 357 if exclude_tags is not None: 358 resolved = await resolver.resolve_list("tags", exclude_tags) 359 params["tags__id__none"] = ",".join(str(t) for t in resolved) 360 361 if any_correspondent is not None: 362 resolved = await resolver.resolve_list("correspondents", any_correspondent) 363 params["correspondent__id__in"] = ",".join(str(c) for c in resolved) 364 elif not isinstance(correspondent, Unset): 365 if correspondent is None: 366 params["correspondent__isnull"] = "true" 367 else: 368 resolved_id = await resolver.resolve("correspondents", correspondent) 369 params["correspondent__id__in"] = resolved_id 370 371 if exclude_correspondents is not None: 372 resolved = await resolver.resolve_list("correspondents", exclude_correspondents) 373 params["correspondent__id__none"] = ",".join(str(c) for c in resolved) 374 375 if document_type_name_contains is not None: 376 params["document_type__name__icontains"] = document_type_name_contains 377 if document_type_name_exact is not None: 378 params["document_type__name__iexact"] = document_type_name_exact 379 380 if any_document_type is not None: 381 resolved = await resolver.resolve_list("document_types", any_document_type) 382 params["document_type__id__in"] = ",".join(str(d) for d in resolved) 383 elif not isinstance(document_type, Unset): 384 if document_type is None: 385 params["document_type__isnull"] = "true" 386 else: 387 resolved_id = await resolver.resolve("document_types", document_type) 388 params["document_type"] = resolved_id 389 390 if exclude_document_types is not None: 391 resolved = await resolver.resolve_list("document_types", exclude_document_types) 392 params["document_type__id__none"] = ",".join(str(d) for d in resolved) 393 394 if any_storage_paths is not None: 395 resolved = await resolver.resolve_list("storage_paths", any_storage_paths) 396 params["storage_path__id__in"] = ",".join(str(s) for s in resolved) 397 elif not isinstance(storage_path, Unset): 398 if storage_path is None: 399 params["storage_path__isnull"] = "true" 400 else: 401 resolved_id = await resolver.resolve("storage_paths", storage_path) 402 params["storage_path__id__in"] = resolved_id 403 404 if exclude_storage_paths is not None: 405 resolved = await resolver.resolve_list("storage_paths", exclude_storage_paths) 406 params["storage_path__id__none"] = ",".join(str(s) for s in resolved) 407 408 if not isinstance(owner, Unset): 409 if owner is None: 410 params["owner__isnull"] = "true" 411 else: 412 params["owner__id__in"] = owner 413 414 if exclude_owners is not None: 415 params["owner__id__none"] = ",".join(str(o) for o in exclude_owners) 416 417 if custom_fields is not None: 418 resolved = await resolver.resolve_list("custom_fields", custom_fields) 419 params["custom_fields__id__all"] = ",".join(str(f) for f in resolved) 420 421 if any_custom_fields is not None: 422 resolved = await resolver.resolve_list("custom_fields", any_custom_fields) 423 params["custom_fields__id__in"] = ",".join(str(f) for f in resolved) 424 425 if exclude_custom_fields is not None: 426 resolved = await resolver.resolve_list("custom_fields", exclude_custom_fields) 427 params["custom_fields__id__none"] = ",".join(str(f) for f in resolved) 428 429 if custom_field_query is not None: 430 params["custom_field_query"] = json.dumps(custom_field_query) 431 432 if not isinstance(archive_serial_number, Unset): 433 if archive_serial_number is None: 434 params["archive_serial_number__isnull"] = "true" 435 else: 436 params["archive_serial_number"] = archive_serial_number 437 438 if archive_serial_number_from is not None: 439 params["archive_serial_number__gte"] = archive_serial_number_from 440 441 if archive_serial_number_till is not None: 442 params["archive_serial_number__lte"] = archive_serial_number_till 443 444 if created_after is not None: 445 params["created__date__gt"] = self._format_date_value(created_after) 446 447 if created_before is not None: 448 params["created__date__lt"] = self._format_date_value(created_before) 449 450 if added_after is not None: 451 key = "added__gt" if self._is_datetime(added_after) else "added__date__gt" 452 params[key] = self._format_date_value(added_after) 453 454 if added_from is not None: 455 key = "added__gte" if self._is_datetime(added_from) else "added__date__gte" 456 params[key] = self._format_date_value(added_from) 457 458 if added_before is not None: 459 key = "added__lt" if self._is_datetime(added_before) else "added__date__lt" 460 params[key] = self._format_date_value(added_before) 461 462 if added_until is not None: 463 key = "added__lte" if self._is_datetime(added_until) else "added__date__lte" 464 params[key] = self._format_date_value(added_until) 465 466 if modified_after is not None: 467 key = "modified__gt" if self._is_datetime(modified_after) else "modified__date__gt" 468 params[key] = self._format_date_value(modified_after) 469 470 if modified_from is not None: 471 key = "modified__gte" if self._is_datetime(modified_from) else "modified__date__gte" 472 params[key] = self._format_date_value(modified_from) 473 474 if modified_before is not None: 475 key = "modified__lt" if self._is_datetime(modified_before) else "modified__date__lt" 476 params[key] = self._format_date_value(modified_before) 477 478 if modified_until is not None: 479 key = "modified__lte" if self._is_datetime(modified_until) else "modified__date__lte" 480 params[key] = self._format_date_value(modified_until) 481 482 if checksum is not None: 483 params["checksum__iexact"] = checksum 484 485 if ordering is not None: 486 params["ordering"] = f"-{ordering}" if descending else ordering 487 488 if page is not None: 489 params["page"] = page 490 raw = await self._core._session.get_page("/documents/", params=params) 491 items = raw.items 492 if max_results is not None: 493 items = items[:max_results] 494 return PagedResult( 495 count=raw.count, 496 next=raw.next, 497 previous=raw.previous, 498 all=raw.all_ids, 499 results=[Document.model_validate(item) for item in items], 500 ) 501 502 raw = await self._core._session.get_all_pages_paged( 503 "/documents/", params, max_results=max_results, on_page=on_page 504 ) 505 return PagedResult( 506 count=raw.count, 507 next=raw.next, 508 previous=raw.previous, 509 all=raw.all_ids, 510 results=[Document.model_validate(item) for item in raw.items], 511 ) 512 513 async def update( 514 self, 515 id: int, 516 *, 517 title: str | Unset = UNSET, 518 content: str | Unset = UNSET, 519 created: date | str | None | Unset = UNSET, 520 correspondent: int | str | None | Unset = UNSET, 521 document_type: int | str | None | Unset = UNSET, 522 storage_path: int | str | None | Unset = UNSET, 523 tags: List[int | str] | None | Unset = UNSET, 524 archive_serial_number: int | None | Unset = UNSET, 525 custom_fields: List[dict[str, Any]] | None | Unset = UNSET, 526 owner: int | None | Unset = UNSET, 527 set_permissions: SetPermissions | None | Unset = UNSET, 528 remove_inbox_tags: bool | None | Unset = UNSET, 529 ) -> Document: 530 """Partially update a document (PATCH semantics). 531 532 Args: 533 id: Numeric ID of the document to update. 534 title: New document title. 535 content: OCR text content of the document. 536 created: Creation date as an ISO-8601 string (``"YYYY-MM-DD"``) or a 537 :class:`~datetime.date` object. 538 correspondent: Correspondent to assign, as an ID or name. 539 Pass ``None`` to clear the correspondent. 540 document_type: Document type to assign, as an ID or name. 541 Pass ``None`` to clear the document type. 542 storage_path: Storage path to assign, as an ID or name. 543 Pass ``None`` to clear the storage path. 544 tags: Full replacement list of tags (IDs or names). 545 archive_serial_number: Archive serial number to assign. 546 Pass ``None`` to clear the archive serial number. 547 custom_fields: List of ``{"field": <field_id>, "value": ...}`` dicts. 548 owner: Numeric user ID to assign as document owner. 549 Pass ``None`` to clear the owner. 550 set_permissions: Explicit view/change permission sets. 551 Pass ``None`` to clear all permissions (overwrite with empty). 552 Omit (or pass :data:`~easypaperless.UNSET`) to leave unchanged. 553 remove_inbox_tags: When ``True``, removes all inbox tags from the document. 554 555 Returns: 556 The updated :class:`~easypaperless.models.documents.Document`. 557 """ 558 logger.info("Updating document id=%d", id) 559 resolver = self._core._resolver 560 payload: dict[str, Any] = {} 561 562 if not isinstance(title, Unset): 563 payload["title"] = title 564 if not isinstance(content, Unset): 565 payload["content"] = content 566 if not isinstance(created, Unset): 567 payload["created"] = self._format_date_value(created) if created is not None else None 568 if not isinstance(correspondent, Unset): 569 payload["correspondent"] = ( 570 None 571 if correspondent is None 572 else await resolver.resolve("correspondents", correspondent) 573 ) 574 if not isinstance(document_type, Unset): 575 payload["document_type"] = ( 576 None 577 if document_type is None 578 else await resolver.resolve("document_types", document_type) 579 ) 580 if not isinstance(storage_path, Unset): 581 payload["storage_path"] = ( 582 None 583 if storage_path is None 584 else await resolver.resolve("storage_paths", storage_path) 585 ) 586 if not isinstance(tags, Unset): 587 payload["tags"] = await resolver.resolve_list("tags", tags or []) 588 if not isinstance(archive_serial_number, Unset): 589 payload["archive_serial_number"] = archive_serial_number 590 if not isinstance(custom_fields, Unset): 591 payload["custom_fields"] = custom_fields 592 if not isinstance(owner, Unset): 593 payload["owner"] = owner 594 if not isinstance(set_permissions, Unset): 595 payload["set_permissions"] = ( 596 SetPermissions().model_dump() 597 if set_permissions is None 598 else set_permissions.model_dump() 599 ) 600 if not isinstance(remove_inbox_tags, Unset): 601 payload["remove_inbox_tags"] = remove_inbox_tags 602 603 resp = await self._core._session.patch(f"/documents/{id}/", json=payload) 604 return Document.model_validate(resp.json()) 605 606 async def delete(self, id: int) -> None: 607 """Permanently delete a document. 608 609 Args: 610 id: Numeric ID of the document to delete. 611 612 Raises: 613 ~easypaperless.exceptions.NotFoundError: If no document exists 614 with that ID. 615 """ 616 logger.info("Deleting document id=%d", id) 617 await self._core._session.delete(f"/documents/{id}/") 618 619 async def download(self, id: int, *, original: bool = False) -> bytes: 620 """Download the binary content of a document. 621 622 Args: 623 id: Numeric ID of the document to download. 624 original: If ``False`` *(default)*, returns the archived PDF. 625 If ``True``, returns the original uploaded file. 626 627 Returns: 628 Raw file bytes. 629 """ 630 logger.info("Downloading document id=%d (original=%s)", id, original) 631 endpoint = "download" if original else "archive" 632 resp = await self._core._session.get_download(f"/documents/{id}/{endpoint}/") 633 content_type = resp.headers.get("content-type", "") 634 if "text/html" in content_type or resp.content[:9].lower().startswith(b"<!doctype"): 635 raise ServerError( 636 f"Download returned an HTML page (content-type: {content_type!r}). " 637 "The server redirected to a login page even after re-attaching auth.", 638 status_code=None, 639 ) 640 return resp.content 641 642 async def upload( 643 self, 644 file: str | Path, 645 *, 646 title: str | Unset = UNSET, 647 created: date | str | None = None, 648 correspondent: int | str | None | Unset = UNSET, 649 document_type: int | str | None | Unset = UNSET, 650 storage_path: int | str | None | Unset = UNSET, 651 tags: List[int | str] | None = None, 652 archive_serial_number: int | None | Unset = UNSET, 653 custom_fields: List[dict[str, Any]] | None = None, 654 wait: bool = False, 655 poll_interval: float | None = None, 656 poll_timeout: float | None = None, 657 ) -> str | Document: 658 """Upload a document to paperless-ngx. 659 660 Args: 661 file: Path to the file to upload. 662 title: Title to assign to the document. 663 created: Creation date as an ISO-8601 string (``"YYYY-MM-DD"``) or a 664 :class:`~datetime.date` object. 665 correspondent: Correspondent to assign, as an ID or name. 666 document_type: Document type to assign, as an ID or name. 667 storage_path: Storage path to assign, as an ID or name. 668 tags: Tags to assign, as IDs or names. 669 archive_serial_number: Archive serial number to assign. 670 custom_fields: List of ``{"field": <field_id>, "value": ...}`` dicts. 671 wait: If ``False`` *(default)*, returns immediately with the task ID. 672 If ``True``, polls until processing completes. 673 poll_interval: Seconds between task-status checks while waiting for 674 processing to complete (requires ``wait=True``). Overrides the 675 client-level default. When omitted, falls back to the client-level 676 ``poll_interval`` (``2.0`` s unless changed at construction). 677 poll_timeout: Maximum seconds to wait before raising 678 :exc:`~easypaperless.exceptions.TaskTimeoutError` (requires 679 ``wait=True``). Overrides the client-level default. When omitted, 680 falls back to the client-level ``poll_timeout`` (``60.0`` s unless 681 changed at construction). 682 683 Returns: 684 The Celery task ID string when ``wait=False``, or the fully 685 processed :class:`~easypaperless.models.documents.Document` 686 when ``wait=True``. 687 688 Raises: 689 ~easypaperless.exceptions.UploadError: If processing fails. 690 ~easypaperless.exceptions.TaskTimeoutError: If timeout is exceeded. 691 """ 692 resolver = self._core._resolver 693 file_path = Path(file) 694 file_bytes = file_path.read_bytes() 695 logger.info("Uploading %r (%d bytes)", file_path.name, len(file_bytes)) 696 697 data: dict[str, Any] = {} 698 if not isinstance(title, Unset): 699 data["title"] = title 700 if created is not None: 701 data["created"] = self._format_date_value(created) 702 if not isinstance(correspondent, Unset) and correspondent is not None: 703 data["correspondent"] = await resolver.resolve("correspondents", correspondent) 704 if not isinstance(document_type, Unset) and document_type is not None: 705 data["document_type"] = await resolver.resolve("document_types", document_type) 706 if not isinstance(storage_path, Unset) and storage_path is not None: 707 data["storage_path"] = await resolver.resolve("storage_paths", storage_path) 708 if tags is not None: 709 resolved = await resolver.resolve_list("tags", tags) 710 data["tags"] = resolved 711 if not isinstance(archive_serial_number, Unset) and archive_serial_number is not None: 712 data["archive_serial_number"] = archive_serial_number 713 if custom_fields is not None: 714 data["custom_fields"] = json.dumps(custom_fields) 715 716 files = {"document": (file_path.name, file_bytes)} 717 resp = await self._core._session.post("/documents/post_document/", data=data, files=files) 718 task_id: str = resp.text.strip('"') 719 logger.debug("Upload accepted, task_id=%r", task_id) 720 721 if not wait: 722 return task_id 723 724 interval = poll_interval if poll_interval is not None else self._core._poll_interval 725 timeout = poll_timeout if poll_timeout is not None else self._core._poll_timeout 726 return await self._poll_task(task_id, poll_interval=interval, poll_timeout=timeout) 727 728 async def _poll_task( 729 self, task_id: str, *, poll_interval: float, poll_timeout: float 730 ) -> Document: 731 start = time.monotonic() 732 deadline = start + poll_timeout 733 while time.monotonic() < deadline: 734 resp = await self._core._session.get("/tasks/", params={"task_id": task_id}) 735 tasks = resp.json() 736 if not tasks: 737 await asyncio.sleep(poll_interval) 738 continue 739 740 task = Task.model_validate(tasks[0]) 741 elapsed = time.monotonic() - start 742 logger.debug( 743 "Polling task %r (status=%s, elapsed=%.1fs)", 744 task_id, 745 task.status.value if task.status is not None else "unknown", 746 elapsed, 747 ) 748 if task.status == TaskStatus.SUCCESS: 749 if task.related_document is None: 750 raise UploadError(f"Task {task_id!r} succeeded but returned no document ID") 751 doc_id = int(task.related_document) 752 logger.info("Task %r succeeded, document_id=%d", task_id, doc_id) 753 return await self.get(doc_id) 754 elif task.status == TaskStatus.FAILURE: 755 logger.warning("Task %r failed: %s", task_id, task.result) 756 raise UploadError(f"Document processing failed: {task.result}") 757 elif task.status == TaskStatus.REVOKED: 758 logger.warning("Task %r was revoked", task_id) 759 raise UploadError(f"Task {task_id!r} was revoked") 760 await asyncio.sleep(poll_interval) 761 762 elapsed = time.monotonic() - start 763 logger.warning("Task %r timed out after %.1fs", task_id, elapsed) 764 raise TaskTimeoutError(f"Task {task_id!r} did not complete within {poll_timeout}s") 765 766 # ------------------------------------------------------------------------- 767 # Document bulk operations 768 # ------------------------------------------------------------------------- 769 770 async def _bulk_edit(self, document_ids: List[int], method: str, **parameters: Any) -> None: 771 """Execute a bulk-edit operation on a list of documents. 772 773 Args: 774 document_ids: List of document IDs to operate on. 775 method: Bulk-edit method name (e.g. ``"add_tag"``, ``"delete"``). 776 **parameters: Additional keyword arguments forwarded to the API. 777 """ 778 payload = {"documents": document_ids, "method": method, "parameters": parameters} 779 await self._core._session.post("/documents/bulk_edit/", json=payload, timeout=120.0) 780 781 async def bulk_add_tag(self, document_ids: List[int], tag: int | str) -> None: 782 """Add a tag to multiple documents in a single request. 783 784 Args: 785 document_ids: List of document IDs to tag. 786 tag: Tag to add, as an ID or name. 787 """ 788 logger.info("Bulk adding tag %r to %d documents", tag, len(document_ids)) 789 tag_id = await self._core._resolver.resolve("tags", tag) 790 await self._bulk_edit(document_ids, "add_tag", tag=tag_id) 791 792 async def bulk_remove_tag(self, document_ids: List[int], tag: int | str) -> None: 793 """Remove a tag from multiple documents in a single request. 794 795 Args: 796 document_ids: List of document IDs to un-tag. 797 tag: Tag to remove, as an ID or name. 798 """ 799 logger.info("Bulk removing tag %r from %d documents", tag, len(document_ids)) 800 tag_id = await self._core._resolver.resolve("tags", tag) 801 await self._bulk_edit(document_ids, "remove_tag", tag=tag_id) 802 803 async def bulk_modify_tags( 804 self, 805 document_ids: List[int], 806 *, 807 add_tags: List[int | str] | None = None, 808 remove_tags: List[int | str] | None = None, 809 ) -> None: 810 """Add and/or remove tags on multiple documents atomically. 811 812 Args: 813 document_ids: List of document IDs to modify. 814 add_tags: Tags to add, as IDs or names. 815 remove_tags: Tags to remove, as IDs or names. 816 """ 817 logger.info("Bulk modifying tags on %d documents", len(document_ids)) 818 resolver = self._core._resolver 819 add_ids = await resolver.resolve_list("tags", add_tags or []) 820 remove_ids = await resolver.resolve_list("tags", remove_tags or []) 821 await self._bulk_edit(document_ids, "modify_tags", add_tags=add_ids, remove_tags=remove_ids) 822 823 async def bulk_delete(self, document_ids: List[int]) -> None: 824 """Permanently delete multiple documents in a single request. 825 826 Args: 827 document_ids: List of document IDs to delete. 828 """ 829 logger.info("Bulk deleting %d documents", len(document_ids)) 830 await self._bulk_edit(document_ids, "delete") 831 832 async def bulk_set_correspondent( 833 self, document_ids: List[int], correspondent: int | str | None 834 ) -> None: 835 """Assign a correspondent to multiple documents in a single request. 836 837 Args: 838 document_ids: List of document IDs to modify. 839 correspondent: Correspondent to assign, as an ID or name. 840 Pass ``None`` to clear. 841 """ 842 logger.info( 843 "Bulk setting correspondent %r on %d documents", correspondent, len(document_ids) 844 ) 845 cor_id: int | None = None 846 if correspondent is not None: 847 cor_id = await self._core._resolver.resolve("correspondents", correspondent) 848 await self._bulk_edit(document_ids, "set_correspondent", correspondent=cor_id) 849 850 async def bulk_set_document_type( 851 self, document_ids: List[int], document_type: int | str | None 852 ) -> None: 853 """Assign a document type to multiple documents in a single request. 854 855 Args: 856 document_ids: List of document IDs to modify. 857 document_type: Document type to assign, as an ID or name. 858 Pass ``None`` to clear. 859 """ 860 logger.info( 861 "Bulk setting document type %r on %d documents", document_type, len(document_ids) 862 ) 863 dt_id: int | None = None 864 if document_type is not None: 865 dt_id = await self._core._resolver.resolve("document_types", document_type) 866 await self._bulk_edit(document_ids, "set_document_type", document_type=dt_id) 867 868 async def bulk_set_storage_path( 869 self, document_ids: List[int], storage_path: int | str | None 870 ) -> None: 871 """Assign a storage path to multiple documents in a single request. 872 873 Args: 874 document_ids: List of document IDs to modify. 875 storage_path: Storage path to assign, as an ID or name. 876 Pass ``None`` to clear. 877 """ 878 logger.info("Bulk setting storage path %r on %d documents", storage_path, len(document_ids)) 879 sp_id: int | None = None 880 if storage_path is not None: 881 sp_id = await self._core._resolver.resolve("storage_paths", storage_path) 882 await self._bulk_edit(document_ids, "set_storage_path", storage_path=sp_id) 883 884 async def bulk_modify_custom_fields( 885 self, 886 document_ids: List[int], 887 *, 888 add_fields: List[dict[str, Any]] | None = None, 889 remove_fields: List[int] | None = None, 890 ) -> None: 891 """Add and/or remove custom field values on multiple documents. 892 893 Args: 894 document_ids: List of document IDs to modify. 895 add_fields: Custom-field value dicts to add. 896 remove_fields: Custom-field IDs whose values should be removed. 897 """ 898 logger.info("Bulk modifying custom fields on %d documents", len(document_ids)) 899 await self._bulk_edit( 900 document_ids, 901 "modify_custom_fields", 902 add_custom_fields=add_fields or [], 903 remove_custom_fields=remove_fields or [], 904 ) 905 906 async def bulk_set_permissions( 907 self, 908 document_ids: List[int], 909 *, 910 set_permissions: SetPermissions | Unset = UNSET, 911 owner: int | None | Unset = UNSET, 912 merge: bool = False, 913 ) -> None: 914 """Set permissions and/or owner on multiple documents. 915 916 Args: 917 document_ids: List of document IDs to modify. 918 set_permissions: Explicit view/change permission sets. 919 Omit (or pass :data:`~easypaperless.UNSET`) to leave unchanged. 920 owner: Numeric user ID to assign as document owner. 921 Pass ``None`` to clear the owner. 922 Omit (or pass :data:`~easypaperless.UNSET`) to leave unchanged. 923 merge: When ``True``, new permissions are merged with existing ones. 924 """ 925 logger.info("Bulk setting permissions on %d documents", len(document_ids)) 926 params: dict[str, Any] = {"merge": merge} 927 if not isinstance(set_permissions, Unset): 928 params["set_permissions"] = set_permissions.model_dump() 929 if not isinstance(owner, Unset): 930 params["owner"] = owner 931 await self._bulk_edit(document_ids, "set_permissions", **params)
Accessor for documents: client.documents.
161 async def get(self, id: int, *, include_metadata: bool = False) -> Document: 162 """Fetch a single document by its ID. 163 164 Args: 165 id: Numeric paperless-ngx document ID. 166 include_metadata: When ``True``, the extended file-level metadata 167 is fetched concurrently and attached to the document. 168 Default: ``False``. 169 170 Returns: 171 The :class:`~easypaperless.models.documents.Document` with the 172 given ID. 173 174 Raises: 175 ~easypaperless.exceptions.NotFoundError: If no document exists 176 with that ID. 177 """ 178 logger.info("Getting document id=%d", id) 179 if include_metadata: 180 doc_resp, meta_resp = await asyncio.gather( 181 self._core._session.get(f"/documents/{id}/"), 182 self._core._session.get(f"/documents/{id}/metadata/"), 183 ) 184 data = doc_resp.json() 185 data["metadata"] = meta_resp.json() 186 else: 187 resp = await self._core._session.get(f"/documents/{id}/") 188 data = resp.json() 189 return Document.model_validate(data)
Fetch a single document by its ID.
Arguments:
- id: Numeric paperless-ngx document ID.
- include_metadata: When
True, the extended file-level metadata is fetched concurrently and attached to the document. Default:False.
Returns:
The
~easypaperless.models.documents.Documentwith the given ID.
Raises:
- ~easypaperless.exceptions.NotFoundError: If no document exists with that ID.
191 async def get_metadata(self, id: int) -> DocumentMetadata: 192 """Fetch the extended file-level metadata for a document. 193 194 Args: 195 id: Numeric paperless-ngx document ID. 196 197 Returns: 198 A :class:`~easypaperless.models.documents.DocumentMetadata` instance. 199 200 Raises: 201 ~easypaperless.exceptions.NotFoundError: If no document exists 202 with that ID. 203 """ 204 logger.info("Getting metadata for document id=%d", id) 205 resp = await self._core._session.get(f"/documents/{id}/metadata/") 206 return DocumentMetadata.model_validate(resp.json())
Fetch the extended file-level metadata for a document.
Arguments:
- id: Numeric paperless-ngx document ID.
Returns:
A
~easypaperless.models.documents.DocumentMetadatainstance.
Raises:
- ~easypaperless.exceptions.NotFoundError: If no document exists with that ID.
208 async def list( 209 self, 210 *, 211 search: str | None = None, 212 search_mode: str = "title_or_content", 213 ids: List[int] | None = None, 214 tags: List[int | str] | None = None, 215 any_tags: List[int | str] | None = None, 216 exclude_tags: List[int | str] | None = None, 217 correspondent: int | str | None | Unset = UNSET, 218 any_correspondent: List[int | str] | None = None, 219 exclude_correspondents: List[int | str] | None = None, 220 document_type: int | str | None | Unset = UNSET, 221 document_type_name_contains: str | None = None, 222 document_type_name_exact: str | None = None, 223 any_document_type: List[int | str] | None = None, 224 exclude_document_types: List[int | str] | None = None, 225 storage_path: int | str | None | Unset = UNSET, 226 any_storage_paths: List[int | str] | None = None, 227 exclude_storage_paths: List[int | str] | None = None, 228 owner: int | None | Unset = UNSET, 229 exclude_owners: List[int] | None = None, 230 custom_fields: List[int | str] | None = None, 231 any_custom_fields: List[int | str] | None = None, 232 exclude_custom_fields: List[int | str] | None = None, 233 custom_field_query: List[Any] | None = None, 234 archive_serial_number: int | None | Unset = UNSET, 235 archive_serial_number_from: int | None = None, 236 archive_serial_number_till: int | None = None, 237 created_after: date | str | None = None, 238 created_before: date | str | None = None, 239 added_after: date | datetime | str | None = None, 240 added_from: date | datetime | str | None = None, 241 added_before: date | datetime | str | None = None, 242 added_until: date | datetime | str | None = None, 243 modified_after: date | datetime | str | None = None, 244 modified_from: date | datetime | str | None = None, 245 modified_before: date | datetime | str | None = None, 246 modified_until: date | datetime | str | None = None, 247 checksum: str | None = None, 248 page_size: int = 25, 249 page: int | None = None, 250 ordering: str | None = None, 251 descending: bool = False, 252 max_results: int | None = None, 253 on_page: Callable[[int, int | None], None] | None = None, 254 ) -> PagedResult[Document]: 255 """Return a filtered list of documents. 256 257 All tag, correspondent, document-type, storage-path, and custom-field 258 parameters accept either integer IDs or string names. 259 260 When ``page`` is ``None`` (the default), all pages are fetched 261 automatically and ``next`` / ``previous`` in the returned 262 :class:`~easypaperless.models.paged_result.PagedResult` are always 263 ``None`` — even if ``max_results`` truncates the final result set. 264 ``count`` always reflects the server total, not the truncated length. 265 When ``page`` is set to a specific integer, only that one page is 266 fetched and ``next`` / ``previous`` contain the raw API values. 267 268 Args: 269 search: Search string. Behaviour depends on ``search_mode``. 270 search_mode: How ``search`` is applied. One of: 271 ``"title_or_content"`` *(default)*, ``"title"``, ``"query"``, 272 ``"original_filename"``. 273 ids: Return only documents whose ID is in this list. 274 tags: Documents must have **all** of these tags (AND semantics). 275 any_tags: Documents must have **at least one** of these tags. 276 exclude_tags: Documents must have **none** of these tags. 277 correspondent: Filter to documents assigned to this correspondent. 278 Pass ``None`` to return only documents with no correspondent set. 279 any_correspondent: Filter to documents assigned to any of these. 280 exclude_correspondents: Exclude documents assigned to any of these. 281 document_type: Filter to documents of exactly this type. 282 Pass ``None`` to return only documents with no document type set. 283 document_type_name_contains: Case-insensitive substring filter on document type name. 284 document_type_name_exact: Case-insensitive exact match on document type name. 285 any_document_type: Filter to documents whose type is any of these. 286 exclude_document_types: Exclude documents whose type is any of these. 287 storage_path: Filter to documents assigned to this storage path. 288 Pass ``None`` to return only documents with no storage path set. 289 any_storage_paths: Filter to documents assigned to any of these paths. 290 exclude_storage_paths: Exclude documents assigned to any of these paths. 291 owner: Filter to documents owned by this user ID. 292 Pass ``None`` to return only documents with no owner set. 293 exclude_owners: Exclude documents owned by any of these user IDs. 294 custom_fields: Documents must have **all** of these custom fields set. 295 any_custom_fields: Documents must have **at least one** of these fields. 296 exclude_custom_fields: Documents must have **none** of these fields. 297 custom_field_query: Filter documents by custom field values using a nested 298 query structure. See the `paperless-ngx API docs 299 <https://docs.paperless-ngx.com/api/#filtering-by-custom-fields>`_ for 300 the query format. 301 archive_serial_number: Filter by exact archive serial number. 302 Pass ``None`` to return only documents with no ASN set. 303 archive_serial_number_from: Filter by ASN >= this value. 304 archive_serial_number_till: Filter by ASN <= this value. 305 created_after: Only documents created after this date. 306 String input must be ISO-8601: ``"YYYY-MM-DD"``. 307 created_before: Only documents created before this date. 308 String input must be ISO-8601: ``"YYYY-MM-DD"``. 309 added_after: Only documents added after this date/time. 310 String input must be ISO-8601: ``"YYYY-MM-DD"`` for date precision or 311 ``"YYYY-MM-DDTHH:MM:SS"`` for datetime precision. 312 added_from: Only documents added on or after this date/time. 313 String input must be ISO-8601: ``"YYYY-MM-DD"`` or ``"YYYY-MM-DDTHH:MM:SS"``. 314 added_before: Only documents added before this date/time. 315 String input must be ISO-8601: ``"YYYY-MM-DD"`` or ``"YYYY-MM-DDTHH:MM:SS"``. 316 added_until: Only documents added on or before this date/time. 317 String input must be ISO-8601: ``"YYYY-MM-DD"`` or ``"YYYY-MM-DDTHH:MM:SS"``. 318 modified_after: Only documents modified after this date/time. 319 String input must be ISO-8601: ``"YYYY-MM-DD"`` or ``"YYYY-MM-DDTHH:MM:SS"``. 320 modified_from: Only documents modified on or after this date/time. 321 String input must be ISO-8601: ``"YYYY-MM-DD"`` or ``"YYYY-MM-DDTHH:MM:SS"``. 322 modified_before: Only documents modified before this date/time. 323 String input must be ISO-8601: ``"YYYY-MM-DD"`` or ``"YYYY-MM-DDTHH:MM:SS"``. 324 modified_until: Only documents modified on or before this date/time. 325 String input must be ISO-8601: ``"YYYY-MM-DD"`` or ``"YYYY-MM-DDTHH:MM:SS"``. 326 checksum: MD5 checksum of the original file (exact match). 327 page_size: Number of results per API page. Default: ``25``. 328 page: Return only this specific page (1-based). 329 ordering: Field name to sort by. 330 descending: When ``True``, reverses the sort direction. 331 max_results: Stop after collecting this many documents. 332 on_page: Callback invoked after each page fetch. 333 334 Returns: 335 :class:`~easypaperless.models.paged_result.PagedResult` of 336 :class:`~easypaperless.models.documents.Document` objects. 337 """ 338 logger.info("Listing documents") 339 resolver = self._core._resolver 340 params: dict[str, Any] = {"page_size": page_size} 341 342 if search is not None: 343 api_param = _SEARCH_MODE_MAP.get(search_mode, "search") 344 params[api_param] = search 345 346 if ids is not None: 347 params["id__in"] = ",".join(str(i) for i in ids) 348 349 if tags is not None: 350 resolved = await resolver.resolve_list("tags", tags) 351 params["tags__id__all"] = ",".join(str(t) for t in resolved) 352 353 if any_tags is not None: 354 resolved = await resolver.resolve_list("tags", any_tags) 355 params["tags__id__in"] = ",".join(str(t) for t in resolved) 356 357 if exclude_tags is not None: 358 resolved = await resolver.resolve_list("tags", exclude_tags) 359 params["tags__id__none"] = ",".join(str(t) for t in resolved) 360 361 if any_correspondent is not None: 362 resolved = await resolver.resolve_list("correspondents", any_correspondent) 363 params["correspondent__id__in"] = ",".join(str(c) for c in resolved) 364 elif not isinstance(correspondent, Unset): 365 if correspondent is None: 366 params["correspondent__isnull"] = "true" 367 else: 368 resolved_id = await resolver.resolve("correspondents", correspondent) 369 params["correspondent__id__in"] = resolved_id 370 371 if exclude_correspondents is not None: 372 resolved = await resolver.resolve_list("correspondents", exclude_correspondents) 373 params["correspondent__id__none"] = ",".join(str(c) for c in resolved) 374 375 if document_type_name_contains is not None: 376 params["document_type__name__icontains"] = document_type_name_contains 377 if document_type_name_exact is not None: 378 params["document_type__name__iexact"] = document_type_name_exact 379 380 if any_document_type is not None: 381 resolved = await resolver.resolve_list("document_types", any_document_type) 382 params["document_type__id__in"] = ",".join(str(d) for d in resolved) 383 elif not isinstance(document_type, Unset): 384 if document_type is None: 385 params["document_type__isnull"] = "true" 386 else: 387 resolved_id = await resolver.resolve("document_types", document_type) 388 params["document_type"] = resolved_id 389 390 if exclude_document_types is not None: 391 resolved = await resolver.resolve_list("document_types", exclude_document_types) 392 params["document_type__id__none"] = ",".join(str(d) for d in resolved) 393 394 if any_storage_paths is not None: 395 resolved = await resolver.resolve_list("storage_paths", any_storage_paths) 396 params["storage_path__id__in"] = ",".join(str(s) for s in resolved) 397 elif not isinstance(storage_path, Unset): 398 if storage_path is None: 399 params["storage_path__isnull"] = "true" 400 else: 401 resolved_id = await resolver.resolve("storage_paths", storage_path) 402 params["storage_path__id__in"] = resolved_id 403 404 if exclude_storage_paths is not None: 405 resolved = await resolver.resolve_list("storage_paths", exclude_storage_paths) 406 params["storage_path__id__none"] = ",".join(str(s) for s in resolved) 407 408 if not isinstance(owner, Unset): 409 if owner is None: 410 params["owner__isnull"] = "true" 411 else: 412 params["owner__id__in"] = owner 413 414 if exclude_owners is not None: 415 params["owner__id__none"] = ",".join(str(o) for o in exclude_owners) 416 417 if custom_fields is not None: 418 resolved = await resolver.resolve_list("custom_fields", custom_fields) 419 params["custom_fields__id__all"] = ",".join(str(f) for f in resolved) 420 421 if any_custom_fields is not None: 422 resolved = await resolver.resolve_list("custom_fields", any_custom_fields) 423 params["custom_fields__id__in"] = ",".join(str(f) for f in resolved) 424 425 if exclude_custom_fields is not None: 426 resolved = await resolver.resolve_list("custom_fields", exclude_custom_fields) 427 params["custom_fields__id__none"] = ",".join(str(f) for f in resolved) 428 429 if custom_field_query is not None: 430 params["custom_field_query"] = json.dumps(custom_field_query) 431 432 if not isinstance(archive_serial_number, Unset): 433 if archive_serial_number is None: 434 params["archive_serial_number__isnull"] = "true" 435 else: 436 params["archive_serial_number"] = archive_serial_number 437 438 if archive_serial_number_from is not None: 439 params["archive_serial_number__gte"] = archive_serial_number_from 440 441 if archive_serial_number_till is not None: 442 params["archive_serial_number__lte"] = archive_serial_number_till 443 444 if created_after is not None: 445 params["created__date__gt"] = self._format_date_value(created_after) 446 447 if created_before is not None: 448 params["created__date__lt"] = self._format_date_value(created_before) 449 450 if added_after is not None: 451 key = "added__gt" if self._is_datetime(added_after) else "added__date__gt" 452 params[key] = self._format_date_value(added_after) 453 454 if added_from is not None: 455 key = "added__gte" if self._is_datetime(added_from) else "added__date__gte" 456 params[key] = self._format_date_value(added_from) 457 458 if added_before is not None: 459 key = "added__lt" if self._is_datetime(added_before) else "added__date__lt" 460 params[key] = self._format_date_value(added_before) 461 462 if added_until is not None: 463 key = "added__lte" if self._is_datetime(added_until) else "added__date__lte" 464 params[key] = self._format_date_value(added_until) 465 466 if modified_after is not None: 467 key = "modified__gt" if self._is_datetime(modified_after) else "modified__date__gt" 468 params[key] = self._format_date_value(modified_after) 469 470 if modified_from is not None: 471 key = "modified__gte" if self._is_datetime(modified_from) else "modified__date__gte" 472 params[key] = self._format_date_value(modified_from) 473 474 if modified_before is not None: 475 key = "modified__lt" if self._is_datetime(modified_before) else "modified__date__lt" 476 params[key] = self._format_date_value(modified_before) 477 478 if modified_until is not None: 479 key = "modified__lte" if self._is_datetime(modified_until) else "modified__date__lte" 480 params[key] = self._format_date_value(modified_until) 481 482 if checksum is not None: 483 params["checksum__iexact"] = checksum 484 485 if ordering is not None: 486 params["ordering"] = f"-{ordering}" if descending else ordering 487 488 if page is not None: 489 params["page"] = page 490 raw = await self._core._session.get_page("/documents/", params=params) 491 items = raw.items 492 if max_results is not None: 493 items = items[:max_results] 494 return PagedResult( 495 count=raw.count, 496 next=raw.next, 497 previous=raw.previous, 498 all=raw.all_ids, 499 results=[Document.model_validate(item) for item in items], 500 ) 501 502 raw = await self._core._session.get_all_pages_paged( 503 "/documents/", params, max_results=max_results, on_page=on_page 504 ) 505 return PagedResult( 506 count=raw.count, 507 next=raw.next, 508 previous=raw.previous, 509 all=raw.all_ids, 510 results=[Document.model_validate(item) for item in raw.items], 511 )
Return a filtered list of documents.
All tag, correspondent, document-type, storage-path, and custom-field parameters accept either integer IDs or string names.
When page is None (the default), all pages are fetched
automatically and next / previous in the returned
~easypaperless.models.paged_result.PagedResult are always
None — even if max_results truncates the final result set.
count always reflects the server total, not the truncated length.
When page is set to a specific integer, only that one page is
fetched and next / previous contain the raw API values.
Arguments:
- search: Search string. Behaviour depends on
search_mode. - search_mode: How
searchis applied. One of:"title_or_content"(default),"title","query","original_filename". - ids: Return only documents whose ID is in this list.
- tags: Documents must have all of these tags (AND semantics).
- any_tags: Documents must have at least one of these tags.
- exclude_tags: Documents must have none of these tags.
- correspondent: Filter to documents assigned to this correspondent.
Pass
Noneto return only documents with no correspondent set. - any_correspondent: Filter to documents assigned to any of these.
- exclude_correspondents: Exclude documents assigned to any of these.
- document_type: Filter to documents of exactly this type.
Pass
Noneto return only documents with no document type set. - document_type_name_contains: Case-insensitive substring filter on document type name.
- document_type_name_exact: Case-insensitive exact match on document type name.
- any_document_type: Filter to documents whose type is any of these.
- exclude_document_types: Exclude documents whose type is any of these.
- storage_path: Filter to documents assigned to this storage path.
Pass
Noneto return only documents with no storage path set. - any_storage_paths: Filter to documents assigned to any of these paths.
- exclude_storage_paths: Exclude documents assigned to any of these paths.
- owner: Filter to documents owned by this user ID.
Pass
Noneto return only documents with no owner set. - exclude_owners: Exclude documents owned by any of these user IDs.
- custom_fields: Documents must have all of these custom fields set.
- any_custom_fields: Documents must have at least one of these fields.
- exclude_custom_fields: Documents must have none of these fields.
- custom_field_query: Filter documents by custom field values using a nested query structure. See the paperless-ngx API docs for the query format.
- archive_serial_number: Filter by exact archive serial number.
Pass
Noneto return only documents with no ASN set. - archive_serial_number_from: Filter by ASN >= this value.
- archive_serial_number_till: Filter by ASN <= this value.
- created_after: Only documents created after this date.
String input must be ISO-8601:
"YYYY-MM-DD". - created_before: Only documents created before this date.
String input must be ISO-8601:
"YYYY-MM-DD". - added_after: Only documents added after this date/time.
String input must be ISO-8601:
"YYYY-MM-DD"for date precision or"YYYY-MM-DDTHH:MM:SS"for datetime precision. - added_from: Only documents added on or after this date/time.
String input must be ISO-8601:
"YYYY-MM-DD"or"YYYY-MM-DDTHH:MM:SS". - added_before: Only documents added before this date/time.
String input must be ISO-8601:
"YYYY-MM-DD"or"YYYY-MM-DDTHH:MM:SS". - added_until: Only documents added on or before this date/time.
String input must be ISO-8601:
"YYYY-MM-DD"or"YYYY-MM-DDTHH:MM:SS". - modified_after: Only documents modified after this date/time.
String input must be ISO-8601:
"YYYY-MM-DD"or"YYYY-MM-DDTHH:MM:SS". - modified_from: Only documents modified on or after this date/time.
String input must be ISO-8601:
"YYYY-MM-DD"or"YYYY-MM-DDTHH:MM:SS". - modified_before: Only documents modified before this date/time.
String input must be ISO-8601:
"YYYY-MM-DD"or"YYYY-MM-DDTHH:MM:SS". - modified_until: Only documents modified on or before this date/time.
String input must be ISO-8601:
"YYYY-MM-DD"or"YYYY-MM-DDTHH:MM:SS". - checksum: MD5 checksum of the original file (exact match).
- page_size: Number of results per API page. Default:
25. - page: Return only this specific page (1-based).
- ordering: Field name to sort by.
- descending: When
True, reverses the sort direction. - max_results: Stop after collecting this many documents.
- on_page: Callback invoked after each page fetch.
Returns:
~easypaperless.models.paged_result.PagedResultof~easypaperless.models.documents.Documentobjects.
513 async def update( 514 self, 515 id: int, 516 *, 517 title: str | Unset = UNSET, 518 content: str | Unset = UNSET, 519 created: date | str | None | Unset = UNSET, 520 correspondent: int | str | None | Unset = UNSET, 521 document_type: int | str | None | Unset = UNSET, 522 storage_path: int | str | None | Unset = UNSET, 523 tags: List[int | str] | None | Unset = UNSET, 524 archive_serial_number: int | None | Unset = UNSET, 525 custom_fields: List[dict[str, Any]] | None | Unset = UNSET, 526 owner: int | None | Unset = UNSET, 527 set_permissions: SetPermissions | None | Unset = UNSET, 528 remove_inbox_tags: bool | None | Unset = UNSET, 529 ) -> Document: 530 """Partially update a document (PATCH semantics). 531 532 Args: 533 id: Numeric ID of the document to update. 534 title: New document title. 535 content: OCR text content of the document. 536 created: Creation date as an ISO-8601 string (``"YYYY-MM-DD"``) or a 537 :class:`~datetime.date` object. 538 correspondent: Correspondent to assign, as an ID or name. 539 Pass ``None`` to clear the correspondent. 540 document_type: Document type to assign, as an ID or name. 541 Pass ``None`` to clear the document type. 542 storage_path: Storage path to assign, as an ID or name. 543 Pass ``None`` to clear the storage path. 544 tags: Full replacement list of tags (IDs or names). 545 archive_serial_number: Archive serial number to assign. 546 Pass ``None`` to clear the archive serial number. 547 custom_fields: List of ``{"field": <field_id>, "value": ...}`` dicts. 548 owner: Numeric user ID to assign as document owner. 549 Pass ``None`` to clear the owner. 550 set_permissions: Explicit view/change permission sets. 551 Pass ``None`` to clear all permissions (overwrite with empty). 552 Omit (or pass :data:`~easypaperless.UNSET`) to leave unchanged. 553 remove_inbox_tags: When ``True``, removes all inbox tags from the document. 554 555 Returns: 556 The updated :class:`~easypaperless.models.documents.Document`. 557 """ 558 logger.info("Updating document id=%d", id) 559 resolver = self._core._resolver 560 payload: dict[str, Any] = {} 561 562 if not isinstance(title, Unset): 563 payload["title"] = title 564 if not isinstance(content, Unset): 565 payload["content"] = content 566 if not isinstance(created, Unset): 567 payload["created"] = self._format_date_value(created) if created is not None else None 568 if not isinstance(correspondent, Unset): 569 payload["correspondent"] = ( 570 None 571 if correspondent is None 572 else await resolver.resolve("correspondents", correspondent) 573 ) 574 if not isinstance(document_type, Unset): 575 payload["document_type"] = ( 576 None 577 if document_type is None 578 else await resolver.resolve("document_types", document_type) 579 ) 580 if not isinstance(storage_path, Unset): 581 payload["storage_path"] = ( 582 None 583 if storage_path is None 584 else await resolver.resolve("storage_paths", storage_path) 585 ) 586 if not isinstance(tags, Unset): 587 payload["tags"] = await resolver.resolve_list("tags", tags or []) 588 if not isinstance(archive_serial_number, Unset): 589 payload["archive_serial_number"] = archive_serial_number 590 if not isinstance(custom_fields, Unset): 591 payload["custom_fields"] = custom_fields 592 if not isinstance(owner, Unset): 593 payload["owner"] = owner 594 if not isinstance(set_permissions, Unset): 595 payload["set_permissions"] = ( 596 SetPermissions().model_dump() 597 if set_permissions is None 598 else set_permissions.model_dump() 599 ) 600 if not isinstance(remove_inbox_tags, Unset): 601 payload["remove_inbox_tags"] = remove_inbox_tags 602 603 resp = await self._core._session.patch(f"/documents/{id}/", json=payload) 604 return Document.model_validate(resp.json())
Partially update a document (PATCH semantics).
Arguments:
- id: Numeric ID of the document to update.
- title: New document title.
- content: OCR text content of the document.
- created: Creation date as an ISO-8601 string (
"YYYY-MM-DD") or a~datetime.dateobject. - correspondent: Correspondent to assign, as an ID or name.
Pass
Noneto clear the correspondent. - document_type: Document type to assign, as an ID or name.
Pass
Noneto clear the document type. - storage_path: Storage path to assign, as an ID or name.
Pass
Noneto clear the storage path. - tags: Full replacement list of tags (IDs or names).
- archive_serial_number: Archive serial number to assign.
Pass
Noneto clear the archive serial number. - custom_fields: List of
{"field": <field_id>, "value": ...}dicts. - owner: Numeric user ID to assign as document owner.
Pass
Noneto clear the owner. - set_permissions: Explicit view/change permission sets.
Pass
Noneto clear all permissions (overwrite with empty). Omit (or pass~easypaperless.UNSET) to leave unchanged. - remove_inbox_tags: When
True, removes all inbox tags from the document.
Returns:
The updated
~easypaperless.models.documents.Document.
606 async def delete(self, id: int) -> None: 607 """Permanently delete a document. 608 609 Args: 610 id: Numeric ID of the document to delete. 611 612 Raises: 613 ~easypaperless.exceptions.NotFoundError: If no document exists 614 with that ID. 615 """ 616 logger.info("Deleting document id=%d", id) 617 await self._core._session.delete(f"/documents/{id}/")
Permanently delete a document.
Arguments:
- id: Numeric ID of the document to delete.
Raises:
- ~easypaperless.exceptions.NotFoundError: If no document exists with that ID.
619 async def download(self, id: int, *, original: bool = False) -> bytes: 620 """Download the binary content of a document. 621 622 Args: 623 id: Numeric ID of the document to download. 624 original: If ``False`` *(default)*, returns the archived PDF. 625 If ``True``, returns the original uploaded file. 626 627 Returns: 628 Raw file bytes. 629 """ 630 logger.info("Downloading document id=%d (original=%s)", id, original) 631 endpoint = "download" if original else "archive" 632 resp = await self._core._session.get_download(f"/documents/{id}/{endpoint}/") 633 content_type = resp.headers.get("content-type", "") 634 if "text/html" in content_type or resp.content[:9].lower().startswith(b"<!doctype"): 635 raise ServerError( 636 f"Download returned an HTML page (content-type: {content_type!r}). " 637 "The server redirected to a login page even after re-attaching auth.", 638 status_code=None, 639 ) 640 return resp.content
Download the binary content of a document.
Arguments:
- id: Numeric ID of the document to download.
- original: If
False(default), returns the archived PDF. IfTrue, returns the original uploaded file.
Returns:
Raw file bytes.
642 async def upload( 643 self, 644 file: str | Path, 645 *, 646 title: str | Unset = UNSET, 647 created: date | str | None = None, 648 correspondent: int | str | None | Unset = UNSET, 649 document_type: int | str | None | Unset = UNSET, 650 storage_path: int | str | None | Unset = UNSET, 651 tags: List[int | str] | None = None, 652 archive_serial_number: int | None | Unset = UNSET, 653 custom_fields: List[dict[str, Any]] | None = None, 654 wait: bool = False, 655 poll_interval: float | None = None, 656 poll_timeout: float | None = None, 657 ) -> str | Document: 658 """Upload a document to paperless-ngx. 659 660 Args: 661 file: Path to the file to upload. 662 title: Title to assign to the document. 663 created: Creation date as an ISO-8601 string (``"YYYY-MM-DD"``) or a 664 :class:`~datetime.date` object. 665 correspondent: Correspondent to assign, as an ID or name. 666 document_type: Document type to assign, as an ID or name. 667 storage_path: Storage path to assign, as an ID or name. 668 tags: Tags to assign, as IDs or names. 669 archive_serial_number: Archive serial number to assign. 670 custom_fields: List of ``{"field": <field_id>, "value": ...}`` dicts. 671 wait: If ``False`` *(default)*, returns immediately with the task ID. 672 If ``True``, polls until processing completes. 673 poll_interval: Seconds between task-status checks while waiting for 674 processing to complete (requires ``wait=True``). Overrides the 675 client-level default. When omitted, falls back to the client-level 676 ``poll_interval`` (``2.0`` s unless changed at construction). 677 poll_timeout: Maximum seconds to wait before raising 678 :exc:`~easypaperless.exceptions.TaskTimeoutError` (requires 679 ``wait=True``). Overrides the client-level default. When omitted, 680 falls back to the client-level ``poll_timeout`` (``60.0`` s unless 681 changed at construction). 682 683 Returns: 684 The Celery task ID string when ``wait=False``, or the fully 685 processed :class:`~easypaperless.models.documents.Document` 686 when ``wait=True``. 687 688 Raises: 689 ~easypaperless.exceptions.UploadError: If processing fails. 690 ~easypaperless.exceptions.TaskTimeoutError: If timeout is exceeded. 691 """ 692 resolver = self._core._resolver 693 file_path = Path(file) 694 file_bytes = file_path.read_bytes() 695 logger.info("Uploading %r (%d bytes)", file_path.name, len(file_bytes)) 696 697 data: dict[str, Any] = {} 698 if not isinstance(title, Unset): 699 data["title"] = title 700 if created is not None: 701 data["created"] = self._format_date_value(created) 702 if not isinstance(correspondent, Unset) and correspondent is not None: 703 data["correspondent"] = await resolver.resolve("correspondents", correspondent) 704 if not isinstance(document_type, Unset) and document_type is not None: 705 data["document_type"] = await resolver.resolve("document_types", document_type) 706 if not isinstance(storage_path, Unset) and storage_path is not None: 707 data["storage_path"] = await resolver.resolve("storage_paths", storage_path) 708 if tags is not None: 709 resolved = await resolver.resolve_list("tags", tags) 710 data["tags"] = resolved 711 if not isinstance(archive_serial_number, Unset) and archive_serial_number is not None: 712 data["archive_serial_number"] = archive_serial_number 713 if custom_fields is not None: 714 data["custom_fields"] = json.dumps(custom_fields) 715 716 files = {"document": (file_path.name, file_bytes)} 717 resp = await self._core._session.post("/documents/post_document/", data=data, files=files) 718 task_id: str = resp.text.strip('"') 719 logger.debug("Upload accepted, task_id=%r", task_id) 720 721 if not wait: 722 return task_id 723 724 interval = poll_interval if poll_interval is not None else self._core._poll_interval 725 timeout = poll_timeout if poll_timeout is not None else self._core._poll_timeout 726 return await self._poll_task(task_id, poll_interval=interval, poll_timeout=timeout)
Upload a document to paperless-ngx.
Arguments:
- file: Path to the file to upload.
- title: Title to assign to the document.
- created: Creation date as an ISO-8601 string (
"YYYY-MM-DD") or a~datetime.dateobject. - correspondent: Correspondent to assign, as an ID or name.
- document_type: Document type to assign, as an ID or name.
- storage_path: Storage path to assign, as an ID or name.
- tags: Tags to assign, as IDs or names.
- archive_serial_number: Archive serial number to assign.
- custom_fields: List of
{"field": <field_id>, "value": ...}dicts. - wait: If
False(default), returns immediately with the task ID. IfTrue, polls until processing completes. - poll_interval: Seconds between task-status checks while waiting for
processing to complete (requires
wait=True). Overrides the client-level default. When omitted, falls back to the client-levelpoll_interval(2.0s unless changed at construction). - poll_timeout: Maximum seconds to wait before raising
~easypaperless.exceptions.TaskTimeoutError(requireswait=True). Overrides the client-level default. When omitted, falls back to the client-levelpoll_timeout(60.0s unless changed at construction).
Returns:
The Celery task ID string when
wait=False, or the fully processed~easypaperless.models.documents.Documentwhenwait=True.
Raises:
- ~easypaperless.exceptions.UploadError: If processing fails.
- ~easypaperless.exceptions.TaskTimeoutError: If timeout is exceeded.
781 async def bulk_add_tag(self, document_ids: List[int], tag: int | str) -> None: 782 """Add a tag to multiple documents in a single request. 783 784 Args: 785 document_ids: List of document IDs to tag. 786 tag: Tag to add, as an ID or name. 787 """ 788 logger.info("Bulk adding tag %r to %d documents", tag, len(document_ids)) 789 tag_id = await self._core._resolver.resolve("tags", tag) 790 await self._bulk_edit(document_ids, "add_tag", tag=tag_id)
Add a tag to multiple documents in a single request.
Arguments:
- document_ids: List of document IDs to tag.
- tag: Tag to add, as an ID or name.
792 async def bulk_remove_tag(self, document_ids: List[int], tag: int | str) -> None: 793 """Remove a tag from multiple documents in a single request. 794 795 Args: 796 document_ids: List of document IDs to un-tag. 797 tag: Tag to remove, as an ID or name. 798 """ 799 logger.info("Bulk removing tag %r from %d documents", tag, len(document_ids)) 800 tag_id = await self._core._resolver.resolve("tags", tag) 801 await self._bulk_edit(document_ids, "remove_tag", tag=tag_id)
Remove a tag from multiple documents in a single request.
Arguments:
- document_ids: List of document IDs to un-tag.
- tag: Tag to remove, as an ID or name.
823 async def bulk_delete(self, document_ids: List[int]) -> None: 824 """Permanently delete multiple documents in a single request. 825 826 Args: 827 document_ids: List of document IDs to delete. 828 """ 829 logger.info("Bulk deleting %d documents", len(document_ids)) 830 await self._bulk_edit(document_ids, "delete")
Permanently delete multiple documents in a single request.
Arguments:
- document_ids: List of document IDs to delete.
832 async def bulk_set_correspondent( 833 self, document_ids: List[int], correspondent: int | str | None 834 ) -> None: 835 """Assign a correspondent to multiple documents in a single request. 836 837 Args: 838 document_ids: List of document IDs to modify. 839 correspondent: Correspondent to assign, as an ID or name. 840 Pass ``None`` to clear. 841 """ 842 logger.info( 843 "Bulk setting correspondent %r on %d documents", correspondent, len(document_ids) 844 ) 845 cor_id: int | None = None 846 if correspondent is not None: 847 cor_id = await self._core._resolver.resolve("correspondents", correspondent) 848 await self._bulk_edit(document_ids, "set_correspondent", correspondent=cor_id)
Assign a correspondent to multiple documents in a single request.
Arguments:
- document_ids: List of document IDs to modify.
- correspondent: Correspondent to assign, as an ID or name.
Pass
Noneto clear.
850 async def bulk_set_document_type( 851 self, document_ids: List[int], document_type: int | str | None 852 ) -> None: 853 """Assign a document type to multiple documents in a single request. 854 855 Args: 856 document_ids: List of document IDs to modify. 857 document_type: Document type to assign, as an ID or name. 858 Pass ``None`` to clear. 859 """ 860 logger.info( 861 "Bulk setting document type %r on %d documents", document_type, len(document_ids) 862 ) 863 dt_id: int | None = None 864 if document_type is not None: 865 dt_id = await self._core._resolver.resolve("document_types", document_type) 866 await self._bulk_edit(document_ids, "set_document_type", document_type=dt_id)
Assign a document type to multiple documents in a single request.
Arguments:
- document_ids: List of document IDs to modify.
- document_type: Document type to assign, as an ID or name.
Pass
Noneto clear.
868 async def bulk_set_storage_path( 869 self, document_ids: List[int], storage_path: int | str | None 870 ) -> None: 871 """Assign a storage path to multiple documents in a single request. 872 873 Args: 874 document_ids: List of document IDs to modify. 875 storage_path: Storage path to assign, as an ID or name. 876 Pass ``None`` to clear. 877 """ 878 logger.info("Bulk setting storage path %r on %d documents", storage_path, len(document_ids)) 879 sp_id: int | None = None 880 if storage_path is not None: 881 sp_id = await self._core._resolver.resolve("storage_paths", storage_path) 882 await self._bulk_edit(document_ids, "set_storage_path", storage_path=sp_id)
Assign a storage path to multiple documents in a single request.
Arguments:
- document_ids: List of document IDs to modify.
- storage_path: Storage path to assign, as an ID or name.
Pass
Noneto clear.
884 async def bulk_modify_custom_fields( 885 self, 886 document_ids: List[int], 887 *, 888 add_fields: List[dict[str, Any]] | None = None, 889 remove_fields: List[int] | None = None, 890 ) -> None: 891 """Add and/or remove custom field values on multiple documents. 892 893 Args: 894 document_ids: List of document IDs to modify. 895 add_fields: Custom-field value dicts to add. 896 remove_fields: Custom-field IDs whose values should be removed. 897 """ 898 logger.info("Bulk modifying custom fields on %d documents", len(document_ids)) 899 await self._bulk_edit( 900 document_ids, 901 "modify_custom_fields", 902 add_custom_fields=add_fields or [], 903 remove_custom_fields=remove_fields or [], 904 )
Add and/or remove custom field values on multiple documents.
Arguments:
- document_ids: List of document IDs to modify.
- add_fields: Custom-field value dicts to add.
- remove_fields: Custom-field IDs whose values should be removed.
906 async def bulk_set_permissions( 907 self, 908 document_ids: List[int], 909 *, 910 set_permissions: SetPermissions | Unset = UNSET, 911 owner: int | None | Unset = UNSET, 912 merge: bool = False, 913 ) -> None: 914 """Set permissions and/or owner on multiple documents. 915 916 Args: 917 document_ids: List of document IDs to modify. 918 set_permissions: Explicit view/change permission sets. 919 Omit (or pass :data:`~easypaperless.UNSET`) to leave unchanged. 920 owner: Numeric user ID to assign as document owner. 921 Pass ``None`` to clear the owner. 922 Omit (or pass :data:`~easypaperless.UNSET`) to leave unchanged. 923 merge: When ``True``, new permissions are merged with existing ones. 924 """ 925 logger.info("Bulk setting permissions on %d documents", len(document_ids)) 926 params: dict[str, Any] = {"merge": merge} 927 if not isinstance(set_permissions, Unset): 928 params["set_permissions"] = set_permissions.model_dump() 929 if not isinstance(owner, Unset): 930 params["owner"] = owner 931 await self._bulk_edit(document_ids, "set_permissions", **params)
Set permissions and/or owner on multiple documents.
Arguments:
- document_ids: List of document IDs to modify.
- set_permissions: Explicit view/change permission sets.
Omit (or pass
~easypaperless.UNSET) to leave unchanged. - owner: Numeric user ID to assign as document owner.
Pass
Noneto clear the owner. Omit (or pass~easypaperless.UNSET) to leave unchanged. - merge: When
True, new permissions are merged with existing ones.
43class NotesResource: 44 """Accessor for document notes: ``client.documents.notes``.""" 45 46 def __init__(self, core: _ClientCore) -> None: 47 self._core = core 48 49 async def list( 50 self, 51 document_id: int, 52 *, 53 page: int | None = None, 54 page_size: int | None = None, 55 ) -> PagedResult[DocumentNote]: 56 """Fetch notes attached to a document. 57 58 When ``page`` is ``None`` (the default), all pages are fetched 59 automatically and ``next`` / ``previous`` in the returned 60 :class:`~easypaperless.models.paged_result.PagedResult` are always 61 ``None``. When ``page`` is set to a specific integer, only that one 62 page is fetched and ``next`` / ``previous`` contain the raw API values. 63 64 Args: 65 document_id: Numeric ID of the document whose notes to retrieve. 66 page: Return only this specific page (1-based). 67 page_size: Number of results per page. 68 69 Returns: 70 :class:`~easypaperless.models.paged_result.PagedResult` of 71 :class:`~easypaperless.models.documents.DocumentNote` objects, 72 ordered by creation time. 73 74 Raises: 75 ~easypaperless.exceptions.NotFoundError: If no document exists 76 with that ID. 77 """ 78 logger.info("Listing notes for document id=%d", document_id) 79 path = f"/documents/{document_id}/notes/" 80 params: dict[str, Any] = {} 81 if page_size is not None: 82 params["page_size"] = page_size 83 if page is not None: 84 params["page"] = page 85 raw = await self._core._session.get_page(path, params=params) 86 else: 87 raw = await self._core._session.get_all_pages_paged(path, params or None) 88 return cast( 89 PagedResult[DocumentNote], 90 PagedResult( 91 count=raw.count, 92 next=raw.next, 93 previous=raw.previous, 94 all=raw.all_ids, 95 results=[DocumentNote.model_validate(item) for item in raw.items], 96 ), 97 ) 98 99 async def create(self, document_id: int, *, note: str) -> DocumentNote: 100 """Create a new note on a document. 101 102 Args: 103 document_id: Numeric ID of the document to annotate. 104 note: Text content of the note. 105 106 Returns: 107 The newly created :class:`~easypaperless.models.documents.DocumentNote`. 108 109 Raises: 110 ~easypaperless.exceptions.NotFoundError: If no document exists 111 with that ID. 112 """ 113 logger.info("Creating note for document id=%d", document_id) 114 resp = await self._core._session.post( 115 f"/documents/{document_id}/notes/", 116 json={"note": note}, 117 ) 118 data = resp.json() 119 if isinstance(data, list): 120 return DocumentNote.model_validate(data[-1]) 121 return DocumentNote.model_validate(data) 122 123 async def delete(self, document_id: int, note_id: int) -> None: 124 """Delete a note from a document. 125 126 Args: 127 document_id: Numeric ID of the document that owns the note. 128 note_id: Numeric ID of the note to delete. 129 130 Raises: 131 ~easypaperless.exceptions.NotFoundError: If no document or note 132 exists with the given IDs. 133 """ 134 logger.info("Deleting note id=%d from document id=%d", note_id, document_id) 135 await self._core._session.delete(f"/documents/{document_id}/notes/", params={"id": note_id})
Accessor for document notes: client.documents.notes.
49 async def list( 50 self, 51 document_id: int, 52 *, 53 page: int | None = None, 54 page_size: int | None = None, 55 ) -> PagedResult[DocumentNote]: 56 """Fetch notes attached to a document. 57 58 When ``page`` is ``None`` (the default), all pages are fetched 59 automatically and ``next`` / ``previous`` in the returned 60 :class:`~easypaperless.models.paged_result.PagedResult` are always 61 ``None``. When ``page`` is set to a specific integer, only that one 62 page is fetched and ``next`` / ``previous`` contain the raw API values. 63 64 Args: 65 document_id: Numeric ID of the document whose notes to retrieve. 66 page: Return only this specific page (1-based). 67 page_size: Number of results per page. 68 69 Returns: 70 :class:`~easypaperless.models.paged_result.PagedResult` of 71 :class:`~easypaperless.models.documents.DocumentNote` objects, 72 ordered by creation time. 73 74 Raises: 75 ~easypaperless.exceptions.NotFoundError: If no document exists 76 with that ID. 77 """ 78 logger.info("Listing notes for document id=%d", document_id) 79 path = f"/documents/{document_id}/notes/" 80 params: dict[str, Any] = {} 81 if page_size is not None: 82 params["page_size"] = page_size 83 if page is not None: 84 params["page"] = page 85 raw = await self._core._session.get_page(path, params=params) 86 else: 87 raw = await self._core._session.get_all_pages_paged(path, params or None) 88 return cast( 89 PagedResult[DocumentNote], 90 PagedResult( 91 count=raw.count, 92 next=raw.next, 93 previous=raw.previous, 94 all=raw.all_ids, 95 results=[DocumentNote.model_validate(item) for item in raw.items], 96 ), 97 )
Fetch notes attached to a document.
When page is None (the default), all pages are fetched
automatically and next / previous in the returned
~easypaperless.models.paged_result.PagedResult are always
None. When page is set to a specific integer, only that one
page is fetched and next / previous contain the raw API values.
Arguments:
- document_id: Numeric ID of the document whose notes to retrieve.
- page: Return only this specific page (1-based).
- page_size: Number of results per page.
Returns:
~easypaperless.models.paged_result.PagedResultof~easypaperless.models.documents.DocumentNoteobjects, ordered by creation time.
Raises:
- ~easypaperless.exceptions.NotFoundError: If no document exists with that ID.
99 async def create(self, document_id: int, *, note: str) -> DocumentNote: 100 """Create a new note on a document. 101 102 Args: 103 document_id: Numeric ID of the document to annotate. 104 note: Text content of the note. 105 106 Returns: 107 The newly created :class:`~easypaperless.models.documents.DocumentNote`. 108 109 Raises: 110 ~easypaperless.exceptions.NotFoundError: If no document exists 111 with that ID. 112 """ 113 logger.info("Creating note for document id=%d", document_id) 114 resp = await self._core._session.post( 115 f"/documents/{document_id}/notes/", 116 json={"note": note}, 117 ) 118 data = resp.json() 119 if isinstance(data, list): 120 return DocumentNote.model_validate(data[-1]) 121 return DocumentNote.model_validate(data)
Create a new note on a document.
Arguments:
- document_id: Numeric ID of the document to annotate.
- note: Text content of the note.
Returns:
The newly created
~easypaperless.models.documents.DocumentNote.
Raises:
- ~easypaperless.exceptions.NotFoundError: If no document exists with that ID.
123 async def delete(self, document_id: int, note_id: int) -> None: 124 """Delete a note from a document. 125 126 Args: 127 document_id: Numeric ID of the document that owns the note. 128 note_id: Numeric ID of the note to delete. 129 130 Raises: 131 ~easypaperless.exceptions.NotFoundError: If no document or note 132 exists with the given IDs. 133 """ 134 logger.info("Deleting note id=%d from document id=%d", note_id, document_id) 135 await self._core._session.delete(f"/documents/{document_id}/notes/", params={"id": note_id})
Delete a note from a document.
Arguments:
- document_id: Numeric ID of the document that owns the note.
- note_id: Numeric ID of the note to delete.
Raises:
- ~easypaperless.exceptions.NotFoundError: If no document or note exists with the given IDs.
21class StoragePathsResource: 22 """Accessor for storage paths: ``client.storage_paths``.""" 23 24 def __init__(self, core: _ClientCore) -> None: 25 self._core = core 26 27 async def list( 28 self, 29 *, 30 ids: List[int] | None = None, 31 name_contains: str | None = None, 32 name_exact: str | None = None, 33 path_contains: str | None = None, 34 path_exact: str | None = None, 35 page: int | None = None, 36 page_size: int | None = None, 37 ordering: str | None = None, 38 descending: bool = False, 39 ) -> PagedResult[StoragePath]: 40 """Return storage paths defined in paperless-ngx. 41 42 When ``page`` is ``None`` (the default), all pages are fetched 43 automatically and ``next`` / ``previous`` in the result are always 44 ``None``. When ``page`` is set, only that page is fetched and 45 ``next`` / ``previous`` reflect the raw API values. 46 47 Args: 48 ids: Return only storage paths whose ID is in this list. 49 name_contains: Case-insensitive substring filter on name. 50 name_exact: Case-insensitive exact match on name. 51 path_contains: Case-insensitive substring filter on path template. 52 path_exact: Case-insensitive exact match on path template. 53 page: Return only this specific page (1-based). 54 page_size: Number of results per page. 55 ordering: Field to sort by. 56 descending: When ``True``, reverses the sort direction. 57 58 Returns: 59 :class:`~easypaperless.models.paged_result.PagedResult` of 60 :class:`~easypaperless.models.storage_paths.StoragePath` objects. 61 """ 62 logger.info("Listing storage paths") 63 params: dict[str, Any] = {} 64 if ids is not None: 65 params["id__in"] = ",".join(str(i) for i in ids) 66 if name_contains is not None: 67 params["name__icontains"] = name_contains 68 if name_exact is not None: 69 params["name__iexact"] = name_exact 70 if path_contains is not None: 71 params["path__icontains"] = path_contains 72 if path_exact is not None: 73 params["path__iexact"] = path_exact 74 if page is not None: 75 params["page"] = page 76 if page_size is not None: 77 params["page_size"] = page_size 78 if ordering is not None: 79 params["ordering"] = f"-{ordering}" if descending else ordering 80 return cast( 81 PagedResult[StoragePath], 82 await self._core._list_resource("storage_paths", StoragePath, params or None), 83 ) 84 85 async def get(self, id: int) -> StoragePath: 86 """Fetch a single storage path by its ID. 87 88 Args: 89 id: Numeric storage-path ID. 90 91 Returns: 92 The :class:`~easypaperless.models.storage_paths.StoragePath` with the given ID. 93 94 Raises: 95 ~easypaperless.exceptions.NotFoundError: If no storage path exists with that ID. 96 """ 97 logger.info("Getting storage path id=%d", id) 98 return cast(StoragePath, await self._core._get_resource("storage_paths", id, StoragePath)) 99 100 async def create( 101 self, 102 *, 103 name: str, 104 path: str | Unset = UNSET, 105 match: str | Unset = UNSET, 106 matching_algorithm: MatchingAlgorithm | Unset = UNSET, 107 is_insensitive: bool = True, 108 owner: int | None | Unset = UNSET, 109 set_permissions: SetPermissions | None | Unset = UNSET, 110 ) -> StoragePath: 111 """Create a new storage path. 112 113 Args: 114 name: Storage-path name. Must be unique. 115 path: Template string for the archive file path. 116 match: Auto-matching pattern. 117 matching_algorithm: Controls how ``match`` is applied. 118 E.g. ``matching_algorithm=MatchingAlgorithm.REGEX`` for 119 regular-expression matching. 120 is_insensitive: When ``True``, ``match`` is case-insensitive. 121 Defaults to ``True``, matching the paperless-ngx API default. 122 owner: Numeric user ID to assign as owner. 123 set_permissions: Explicit view/change permission sets. 124 Pass ``None`` to create with empty permissions. 125 126 Returns: 127 The newly created :class:`~easypaperless.models.storage_paths.StoragePath`. 128 """ 129 logger.info("Creating storage path name=%r", name) 130 return cast( 131 StoragePath, 132 await self._core._create_resource( 133 "storage_paths", 134 StoragePath, 135 owner=owner, 136 set_permissions=set_permissions, 137 name=name, 138 path=path, 139 match=match, 140 matching_algorithm=matching_algorithm, 141 is_insensitive=is_insensitive, 142 ), 143 ) 144 145 async def update( 146 self, 147 id: int, 148 *, 149 name: str | Unset = UNSET, 150 path: str | Unset = UNSET, 151 match: str | Unset = UNSET, 152 matching_algorithm: MatchingAlgorithm | Unset = UNSET, 153 is_insensitive: bool | Unset = UNSET, 154 owner: int | None | Unset = UNSET, 155 set_permissions: SetPermissions | None | Unset = UNSET, 156 ) -> StoragePath: 157 """Partially update a storage path (PATCH semantics). 158 159 Args: 160 id: Numeric ID of the storage path to update. 161 name: Storage-path name. 162 path: Template string for the archive file path. 163 match: Auto-matching pattern. 164 matching_algorithm: Controls how ``match`` is applied. 165 E.g. ``matching_algorithm=MatchingAlgorithm.REGEX`` for 166 regular-expression matching. 167 is_insensitive: When ``True``, ``match`` is case-insensitive. 168 owner: Numeric user ID to assign as owner. 169 Pass ``None`` to clear the owner. 170 Omit (or pass :data:`~easypaperless.UNSET`) to leave unchanged. 171 set_permissions: Explicit view/change permission sets. 172 Pass ``None`` to clear all permissions (overwrite with empty). 173 Omit (or pass :data:`~easypaperless.UNSET`) to leave unchanged. 174 175 Returns: 176 The updated :class:`~easypaperless.models.storage_paths.StoragePath`. 177 """ 178 logger.info("Updating storage path id=%d", id) 179 return cast( 180 StoragePath, 181 await self._core._update_resource( 182 "storage_paths", 183 id, 184 StoragePath, 185 name=name, 186 path=path, 187 match=match, 188 matching_algorithm=matching_algorithm, 189 is_insensitive=is_insensitive, 190 owner=owner, 191 set_permissions=set_permissions, 192 ), 193 ) 194 195 async def delete(self, id: int) -> None: 196 """Delete a storage path. 197 198 Args: 199 id: Numeric ID of the storage path to delete. 200 201 Raises: 202 ~easypaperless.exceptions.NotFoundError: If no storage path exists with that ID. 203 """ 204 logger.info("Deleting storage path id=%d", id) 205 await self._core._delete_resource("storage_paths", id) 206 207 async def bulk_delete(self, ids: List[int]) -> None: 208 """Permanently delete multiple storage paths in a single request. 209 210 Args: 211 ids: List of storage path IDs to delete. 212 """ 213 logger.info("Bulk deleting %d storage paths", len(ids)) 214 await self._core._bulk_edit_objects("storage_paths", ids, "delete") 215 216 async def bulk_set_permissions( 217 self, 218 ids: List[int], 219 *, 220 set_permissions: SetPermissions | Unset = UNSET, 221 owner: int | None | Unset = UNSET, 222 merge: bool = False, 223 ) -> None: 224 """Set permissions and/or owner on multiple storage paths. 225 226 Args: 227 ids: List of storage path IDs to modify. 228 set_permissions: Explicit view/change permission sets. 229 Omit (or pass :data:`~easypaperless.UNSET`) to leave unchanged. 230 owner: Numeric user ID to assign as owner. 231 Pass ``None`` to clear the owner. 232 Omit (or pass :data:`~easypaperless.UNSET`) to leave unchanged. 233 merge: When ``True``, new permissions are merged with existing ones. 234 """ 235 logger.info("Bulk setting permissions on %d storage paths", len(ids)) 236 params: dict[str, Any] = {"merge": merge} 237 if not isinstance(set_permissions, Unset): 238 params["permissions"] = set_permissions.model_dump() 239 if not isinstance(owner, Unset): 240 params["owner"] = owner 241 await self._core._bulk_edit_objects("storage_paths", ids, "set_permissions", **params)
Accessor for storage paths: client.storage_paths.
27 async def list( 28 self, 29 *, 30 ids: List[int] | None = None, 31 name_contains: str | None = None, 32 name_exact: str | None = None, 33 path_contains: str | None = None, 34 path_exact: str | None = None, 35 page: int | None = None, 36 page_size: int | None = None, 37 ordering: str | None = None, 38 descending: bool = False, 39 ) -> PagedResult[StoragePath]: 40 """Return storage paths defined in paperless-ngx. 41 42 When ``page`` is ``None`` (the default), all pages are fetched 43 automatically and ``next`` / ``previous`` in the result are always 44 ``None``. When ``page`` is set, only that page is fetched and 45 ``next`` / ``previous`` reflect the raw API values. 46 47 Args: 48 ids: Return only storage paths whose ID is in this list. 49 name_contains: Case-insensitive substring filter on name. 50 name_exact: Case-insensitive exact match on name. 51 path_contains: Case-insensitive substring filter on path template. 52 path_exact: Case-insensitive exact match on path template. 53 page: Return only this specific page (1-based). 54 page_size: Number of results per page. 55 ordering: Field to sort by. 56 descending: When ``True``, reverses the sort direction. 57 58 Returns: 59 :class:`~easypaperless.models.paged_result.PagedResult` of 60 :class:`~easypaperless.models.storage_paths.StoragePath` objects. 61 """ 62 logger.info("Listing storage paths") 63 params: dict[str, Any] = {} 64 if ids is not None: 65 params["id__in"] = ",".join(str(i) for i in ids) 66 if name_contains is not None: 67 params["name__icontains"] = name_contains 68 if name_exact is not None: 69 params["name__iexact"] = name_exact 70 if path_contains is not None: 71 params["path__icontains"] = path_contains 72 if path_exact is not None: 73 params["path__iexact"] = path_exact 74 if page is not None: 75 params["page"] = page 76 if page_size is not None: 77 params["page_size"] = page_size 78 if ordering is not None: 79 params["ordering"] = f"-{ordering}" if descending else ordering 80 return cast( 81 PagedResult[StoragePath], 82 await self._core._list_resource("storage_paths", StoragePath, params or None), 83 )
Return storage paths defined in paperless-ngx.
When page is None (the default), all pages are fetched
automatically and next / previous in the result are always
None. When page is set, only that page is fetched and
next / previous reflect the raw API values.
Arguments:
- ids: Return only storage paths whose ID is in this list.
- name_contains: Case-insensitive substring filter on name.
- name_exact: Case-insensitive exact match on name.
- path_contains: Case-insensitive substring filter on path template.
- path_exact: Case-insensitive exact match on path template.
- page: Return only this specific page (1-based).
- page_size: Number of results per page.
- ordering: Field to sort by.
- descending: When
True, reverses the sort direction.
Returns:
~easypaperless.models.paged_result.PagedResultof~easypaperless.models.storage_paths.StoragePathobjects.
85 async def get(self, id: int) -> StoragePath: 86 """Fetch a single storage path by its ID. 87 88 Args: 89 id: Numeric storage-path ID. 90 91 Returns: 92 The :class:`~easypaperless.models.storage_paths.StoragePath` with the given ID. 93 94 Raises: 95 ~easypaperless.exceptions.NotFoundError: If no storage path exists with that ID. 96 """ 97 logger.info("Getting storage path id=%d", id) 98 return cast(StoragePath, await self._core._get_resource("storage_paths", id, StoragePath))
Fetch a single storage path by its ID.
Arguments:
- id: Numeric storage-path ID.
Returns:
The
~easypaperless.models.storage_paths.StoragePathwith the given ID.
Raises:
- ~easypaperless.exceptions.NotFoundError: If no storage path exists with that ID.
100 async def create( 101 self, 102 *, 103 name: str, 104 path: str | Unset = UNSET, 105 match: str | Unset = UNSET, 106 matching_algorithm: MatchingAlgorithm | Unset = UNSET, 107 is_insensitive: bool = True, 108 owner: int | None | Unset = UNSET, 109 set_permissions: SetPermissions | None | Unset = UNSET, 110 ) -> StoragePath: 111 """Create a new storage path. 112 113 Args: 114 name: Storage-path name. Must be unique. 115 path: Template string for the archive file path. 116 match: Auto-matching pattern. 117 matching_algorithm: Controls how ``match`` is applied. 118 E.g. ``matching_algorithm=MatchingAlgorithm.REGEX`` for 119 regular-expression matching. 120 is_insensitive: When ``True``, ``match`` is case-insensitive. 121 Defaults to ``True``, matching the paperless-ngx API default. 122 owner: Numeric user ID to assign as owner. 123 set_permissions: Explicit view/change permission sets. 124 Pass ``None`` to create with empty permissions. 125 126 Returns: 127 The newly created :class:`~easypaperless.models.storage_paths.StoragePath`. 128 """ 129 logger.info("Creating storage path name=%r", name) 130 return cast( 131 StoragePath, 132 await self._core._create_resource( 133 "storage_paths", 134 StoragePath, 135 owner=owner, 136 set_permissions=set_permissions, 137 name=name, 138 path=path, 139 match=match, 140 matching_algorithm=matching_algorithm, 141 is_insensitive=is_insensitive, 142 ), 143 )
Create a new storage path.
Arguments:
- name: Storage-path name. Must be unique.
- path: Template string for the archive file path.
- match: Auto-matching pattern.
- matching_algorithm: Controls how
matchis applied. E.g.matching_algorithm=MatchingAlgorithm.REGEXfor regular-expression matching. - is_insensitive: When
True,matchis case-insensitive. Defaults toTrue, matching the paperless-ngx API default. - owner: Numeric user ID to assign as owner.
- set_permissions: Explicit view/change permission sets.
Pass
Noneto create with empty permissions.
Returns:
The newly created
~easypaperless.models.storage_paths.StoragePath.
145 async def update( 146 self, 147 id: int, 148 *, 149 name: str | Unset = UNSET, 150 path: str | Unset = UNSET, 151 match: str | Unset = UNSET, 152 matching_algorithm: MatchingAlgorithm | Unset = UNSET, 153 is_insensitive: bool | Unset = UNSET, 154 owner: int | None | Unset = UNSET, 155 set_permissions: SetPermissions | None | Unset = UNSET, 156 ) -> StoragePath: 157 """Partially update a storage path (PATCH semantics). 158 159 Args: 160 id: Numeric ID of the storage path to update. 161 name: Storage-path name. 162 path: Template string for the archive file path. 163 match: Auto-matching pattern. 164 matching_algorithm: Controls how ``match`` is applied. 165 E.g. ``matching_algorithm=MatchingAlgorithm.REGEX`` for 166 regular-expression matching. 167 is_insensitive: When ``True``, ``match`` is case-insensitive. 168 owner: Numeric user ID to assign as owner. 169 Pass ``None`` to clear the owner. 170 Omit (or pass :data:`~easypaperless.UNSET`) to leave unchanged. 171 set_permissions: Explicit view/change permission sets. 172 Pass ``None`` to clear all permissions (overwrite with empty). 173 Omit (or pass :data:`~easypaperless.UNSET`) to leave unchanged. 174 175 Returns: 176 The updated :class:`~easypaperless.models.storage_paths.StoragePath`. 177 """ 178 logger.info("Updating storage path id=%d", id) 179 return cast( 180 StoragePath, 181 await self._core._update_resource( 182 "storage_paths", 183 id, 184 StoragePath, 185 name=name, 186 path=path, 187 match=match, 188 matching_algorithm=matching_algorithm, 189 is_insensitive=is_insensitive, 190 owner=owner, 191 set_permissions=set_permissions, 192 ), 193 )
Partially update a storage path (PATCH semantics).
Arguments:
- id: Numeric ID of the storage path to update.
- name: Storage-path name.
- path: Template string for the archive file path.
- match: Auto-matching pattern.
- matching_algorithm: Controls how
matchis applied. E.g.matching_algorithm=MatchingAlgorithm.REGEXfor regular-expression matching. - is_insensitive: When
True,matchis case-insensitive. - owner: Numeric user ID to assign as owner.
Pass
Noneto clear the owner. Omit (or pass~easypaperless.UNSET) to leave unchanged. - set_permissions: Explicit view/change permission sets.
Pass
Noneto clear all permissions (overwrite with empty). Omit (or pass~easypaperless.UNSET) to leave unchanged.
Returns:
The updated
~easypaperless.models.storage_paths.StoragePath.
195 async def delete(self, id: int) -> None: 196 """Delete a storage path. 197 198 Args: 199 id: Numeric ID of the storage path to delete. 200 201 Raises: 202 ~easypaperless.exceptions.NotFoundError: If no storage path exists with that ID. 203 """ 204 logger.info("Deleting storage path id=%d", id) 205 await self._core._delete_resource("storage_paths", id)
Delete a storage path.
Arguments:
- id: Numeric ID of the storage path to delete.
Raises:
- ~easypaperless.exceptions.NotFoundError: If no storage path exists with that ID.
207 async def bulk_delete(self, ids: List[int]) -> None: 208 """Permanently delete multiple storage paths in a single request. 209 210 Args: 211 ids: List of storage path IDs to delete. 212 """ 213 logger.info("Bulk deleting %d storage paths", len(ids)) 214 await self._core._bulk_edit_objects("storage_paths", ids, "delete")
Permanently delete multiple storage paths in a single request.
Arguments:
- ids: List of storage path IDs to delete.
216 async def bulk_set_permissions( 217 self, 218 ids: List[int], 219 *, 220 set_permissions: SetPermissions | Unset = UNSET, 221 owner: int | None | Unset = UNSET, 222 merge: bool = False, 223 ) -> None: 224 """Set permissions and/or owner on multiple storage paths. 225 226 Args: 227 ids: List of storage path IDs to modify. 228 set_permissions: Explicit view/change permission sets. 229 Omit (or pass :data:`~easypaperless.UNSET`) to leave unchanged. 230 owner: Numeric user ID to assign as owner. 231 Pass ``None`` to clear the owner. 232 Omit (or pass :data:`~easypaperless.UNSET`) to leave unchanged. 233 merge: When ``True``, new permissions are merged with existing ones. 234 """ 235 logger.info("Bulk setting permissions on %d storage paths", len(ids)) 236 params: dict[str, Any] = {"merge": merge} 237 if not isinstance(set_permissions, Unset): 238 params["permissions"] = set_permissions.model_dump() 239 if not isinstance(owner, Unset): 240 params["owner"] = owner 241 await self._core._bulk_edit_objects("storage_paths", ids, "set_permissions", **params)
Set permissions and/or owner on multiple storage paths.
Arguments:
- ids: List of storage path IDs to modify.
- set_permissions: Explicit view/change permission sets.
Omit (or pass
~easypaperless.UNSET) to leave unchanged. - owner: Numeric user ID to assign as owner.
Pass
Noneto clear the owner. Omit (or pass~easypaperless.UNSET) to leave unchanged. - merge: When
True, new permissions are merged with existing ones.
21class TagsResource: 22 """Accessor for tags: ``client.tags``.""" 23 24 def __init__(self, core: _ClientCore) -> None: 25 self._core = core 26 27 async def list( 28 self, 29 *, 30 ids: List[int] | None = None, 31 name_contains: str | None = None, 32 name_exact: str | None = None, 33 page: int | None = None, 34 page_size: int | None = None, 35 ordering: str | None = None, 36 descending: bool = False, 37 ) -> PagedResult[Tag]: 38 """Return tags defined in paperless-ngx. 39 40 When ``page`` is ``None`` (the default), all pages are fetched 41 automatically and ``next`` / ``previous`` in the result are always 42 ``None``. When ``page`` is set, only that page is fetched and 43 ``next`` / ``previous`` reflect the raw API values. 44 45 Args: 46 ids: Return only tags whose ID is in this list. 47 name_contains: Case-insensitive substring filter on tag name. 48 name_exact: Case-insensitive exact match on tag name. 49 page: Return only this specific page (1-based). 50 page_size: Number of results per page. 51 ordering: Field to sort by. 52 descending: When ``True``, reverses the sort direction. 53 54 Returns: 55 :class:`~easypaperless.models.paged_result.PagedResult` of 56 :class:`~easypaperless.models.tags.Tag` objects. 57 """ 58 logger.info("Listing tags") 59 params: dict[str, Any] = {} 60 if ids is not None: 61 params["id__in"] = ",".join(str(i) for i in ids) 62 if name_contains is not None: 63 params["name__icontains"] = name_contains 64 if name_exact is not None: 65 params["name__iexact"] = name_exact 66 if page is not None: 67 params["page"] = page 68 if page_size is not None: 69 params["page_size"] = page_size 70 if ordering is not None: 71 params["ordering"] = f"-{ordering}" if descending else ordering 72 return cast( 73 PagedResult[Tag], 74 await self._core._list_resource("tags", Tag, params or None), 75 ) 76 77 async def get(self, id: int) -> Tag: 78 """Fetch a single tag by its ID. 79 80 Args: 81 id: Numeric tag ID. 82 83 Returns: 84 The :class:`~easypaperless.models.tags.Tag` with the given ID. 85 86 Raises: 87 ~easypaperless.exceptions.NotFoundError: If no tag exists with 88 that ID. 89 """ 90 logger.info("Getting tag id=%d", id) 91 return cast(Tag, await self._core._get_resource("tags", id, Tag)) 92 93 async def create( 94 self, 95 *, 96 name: str, 97 color: str | Unset = UNSET, 98 is_inbox_tag: bool | Unset = UNSET, 99 match: str | Unset = UNSET, 100 matching_algorithm: MatchingAlgorithm | Unset = UNSET, 101 is_insensitive: bool = True, 102 parent: int | None | Unset = UNSET, 103 owner: int | None | Unset = UNSET, 104 set_permissions: SetPermissions | None | Unset = UNSET, 105 ) -> Tag: 106 """Create a new tag. 107 108 Args: 109 name: Tag name. Must be unique. 110 color: Background colour as a CSS hex string. 111 is_inbox_tag: When ``True``, newly ingested documents get this tag. 112 match: Auto-matching pattern. 113 matching_algorithm: Controls how ``match`` is applied. 114 E.g. ``matching_algorithm=MatchingAlgorithm.REGEX`` for 115 regular-expression matching. 116 is_insensitive: When ``True``, ``match`` is case-insensitive. 117 Defaults to ``True``, matching the paperless-ngx API default. 118 parent: ID of parent tag for hierarchical trees. 119 owner: Numeric user ID to assign as owner. 120 set_permissions: Explicit view/change permission sets. 121 Pass ``None`` to create with empty permissions. 122 123 Returns: 124 The newly created :class:`~easypaperless.models.tags.Tag`. 125 """ 126 logger.info("Creating tag name=%r", name) 127 return cast( 128 Tag, 129 await self._core._create_resource( 130 "tags", 131 Tag, 132 owner=owner, 133 set_permissions=set_permissions, 134 name=name, 135 color=color, 136 is_inbox_tag=is_inbox_tag, 137 match=match, 138 matching_algorithm=matching_algorithm, 139 is_insensitive=is_insensitive, 140 parent=parent, 141 ), 142 ) 143 144 async def update( 145 self, 146 id: int, 147 *, 148 name: str | Unset = UNSET, 149 color: str | Unset = UNSET, 150 is_inbox_tag: bool | Unset = UNSET, 151 match: str | Unset = UNSET, 152 matching_algorithm: MatchingAlgorithm | Unset = UNSET, 153 is_insensitive: bool | Unset = UNSET, 154 parent: int | None | Unset = UNSET, 155 owner: int | None | Unset = UNSET, 156 set_permissions: SetPermissions | None | Unset = UNSET, 157 ) -> Tag: 158 """Partially update a tag (PATCH semantics). 159 160 Args: 161 id: Numeric ID of the tag to update. 162 name: Tag name. 163 color: Background colour as a CSS hex string. 164 is_inbox_tag: When ``True``, newly ingested documents get this tag. 165 match: Auto-matching pattern. 166 matching_algorithm: Controls how ``match`` is applied. 167 E.g. ``matching_algorithm=MatchingAlgorithm.REGEX`` for 168 regular-expression matching. 169 is_insensitive: When ``True``, ``match`` is case-insensitive. 170 parent: ID of parent tag. 171 Pass ``None`` to clear (make root tag). 172 Omit (or pass :data:`~easypaperless.UNSET`) to leave unchanged. 173 owner: Numeric user ID to assign as owner. 174 Pass ``None`` to clear the owner. 175 Omit (or pass :data:`~easypaperless.UNSET`) to leave unchanged. 176 set_permissions: Explicit view/change permission sets. 177 Pass ``None`` to clear all permissions (overwrite with empty). 178 Omit (or pass :data:`~easypaperless.UNSET`) to leave unchanged. 179 180 Returns: 181 The updated :class:`~easypaperless.models.tags.Tag`. 182 """ 183 logger.info("Updating tag id=%d", id) 184 return cast( 185 Tag, 186 await self._core._update_resource( 187 "tags", 188 id, 189 Tag, 190 name=name, 191 color=color, 192 is_inbox_tag=is_inbox_tag, 193 match=match, 194 matching_algorithm=matching_algorithm, 195 is_insensitive=is_insensitive, 196 parent=parent, 197 owner=owner, 198 set_permissions=set_permissions, 199 ), 200 ) 201 202 async def delete(self, id: int) -> None: 203 """Delete a tag. 204 205 Args: 206 id: Numeric ID of the tag to delete. 207 208 Raises: 209 ~easypaperless.exceptions.NotFoundError: If no tag exists with 210 that ID. 211 """ 212 logger.info("Deleting tag id=%d", id) 213 await self._core._delete_resource("tags", id) 214 215 async def bulk_delete(self, ids: List[int]) -> None: 216 """Permanently delete multiple tags in a single request. 217 218 Args: 219 ids: List of tag IDs to delete. 220 """ 221 logger.info("Bulk deleting %d tags", len(ids)) 222 await self._core._bulk_edit_objects("tags", ids, "delete") 223 224 async def bulk_set_permissions( 225 self, 226 ids: List[int], 227 *, 228 set_permissions: SetPermissions | Unset = UNSET, 229 owner: int | None | Unset = UNSET, 230 merge: bool = False, 231 ) -> None: 232 """Set permissions and/or owner on multiple tags. 233 234 Args: 235 ids: List of tag IDs to modify. 236 set_permissions: Explicit view/change permission sets. 237 Omit (or pass :data:`~easypaperless.UNSET`) to leave unchanged. 238 owner: Numeric user ID to assign as owner. 239 Pass ``None`` to clear the owner. 240 Omit (or pass :data:`~easypaperless.UNSET`) to leave unchanged. 241 merge: When ``True``, new permissions are merged with existing ones. 242 """ 243 logger.info("Bulk setting permissions on %d tags", len(ids)) 244 params: dict[str, Any] = {"merge": merge} 245 if not isinstance(set_permissions, Unset): 246 params["permissions"] = set_permissions.model_dump() 247 if not isinstance(owner, Unset): 248 params["owner"] = owner 249 await self._core._bulk_edit_objects("tags", ids, "set_permissions", **params)
Accessor for tags: client.tags.
27 async def list( 28 self, 29 *, 30 ids: List[int] | None = None, 31 name_contains: str | None = None, 32 name_exact: str | None = None, 33 page: int | None = None, 34 page_size: int | None = None, 35 ordering: str | None = None, 36 descending: bool = False, 37 ) -> PagedResult[Tag]: 38 """Return tags defined in paperless-ngx. 39 40 When ``page`` is ``None`` (the default), all pages are fetched 41 automatically and ``next`` / ``previous`` in the result are always 42 ``None``. When ``page`` is set, only that page is fetched and 43 ``next`` / ``previous`` reflect the raw API values. 44 45 Args: 46 ids: Return only tags whose ID is in this list. 47 name_contains: Case-insensitive substring filter on tag name. 48 name_exact: Case-insensitive exact match on tag name. 49 page: Return only this specific page (1-based). 50 page_size: Number of results per page. 51 ordering: Field to sort by. 52 descending: When ``True``, reverses the sort direction. 53 54 Returns: 55 :class:`~easypaperless.models.paged_result.PagedResult` of 56 :class:`~easypaperless.models.tags.Tag` objects. 57 """ 58 logger.info("Listing tags") 59 params: dict[str, Any] = {} 60 if ids is not None: 61 params["id__in"] = ",".join(str(i) for i in ids) 62 if name_contains is not None: 63 params["name__icontains"] = name_contains 64 if name_exact is not None: 65 params["name__iexact"] = name_exact 66 if page is not None: 67 params["page"] = page 68 if page_size is not None: 69 params["page_size"] = page_size 70 if ordering is not None: 71 params["ordering"] = f"-{ordering}" if descending else ordering 72 return cast( 73 PagedResult[Tag], 74 await self._core._list_resource("tags", Tag, params or None), 75 )
Return tags defined in paperless-ngx.
When page is None (the default), all pages are fetched
automatically and next / previous in the result are always
None. When page is set, only that page is fetched and
next / previous reflect the raw API values.
Arguments:
- ids: Return only tags whose ID is in this list.
- name_contains: Case-insensitive substring filter on tag name.
- name_exact: Case-insensitive exact match on tag name.
- page: Return only this specific page (1-based).
- page_size: Number of results per page.
- ordering: Field to sort by.
- descending: When
True, reverses the sort direction.
Returns:
~easypaperless.models.paged_result.PagedResultof~easypaperless.models.tags.Tagobjects.
77 async def get(self, id: int) -> Tag: 78 """Fetch a single tag by its ID. 79 80 Args: 81 id: Numeric tag ID. 82 83 Returns: 84 The :class:`~easypaperless.models.tags.Tag` with the given ID. 85 86 Raises: 87 ~easypaperless.exceptions.NotFoundError: If no tag exists with 88 that ID. 89 """ 90 logger.info("Getting tag id=%d", id) 91 return cast(Tag, await self._core._get_resource("tags", id, Tag))
Fetch a single tag by its ID.
Arguments:
- id: Numeric tag ID.
Returns:
The
~easypaperless.models.tags.Tagwith the given ID.
Raises:
- ~easypaperless.exceptions.NotFoundError: If no tag exists with that ID.
93 async def create( 94 self, 95 *, 96 name: str, 97 color: str | Unset = UNSET, 98 is_inbox_tag: bool | Unset = UNSET, 99 match: str | Unset = UNSET, 100 matching_algorithm: MatchingAlgorithm | Unset = UNSET, 101 is_insensitive: bool = True, 102 parent: int | None | Unset = UNSET, 103 owner: int | None | Unset = UNSET, 104 set_permissions: SetPermissions | None | Unset = UNSET, 105 ) -> Tag: 106 """Create a new tag. 107 108 Args: 109 name: Tag name. Must be unique. 110 color: Background colour as a CSS hex string. 111 is_inbox_tag: When ``True``, newly ingested documents get this tag. 112 match: Auto-matching pattern. 113 matching_algorithm: Controls how ``match`` is applied. 114 E.g. ``matching_algorithm=MatchingAlgorithm.REGEX`` for 115 regular-expression matching. 116 is_insensitive: When ``True``, ``match`` is case-insensitive. 117 Defaults to ``True``, matching the paperless-ngx API default. 118 parent: ID of parent tag for hierarchical trees. 119 owner: Numeric user ID to assign as owner. 120 set_permissions: Explicit view/change permission sets. 121 Pass ``None`` to create with empty permissions. 122 123 Returns: 124 The newly created :class:`~easypaperless.models.tags.Tag`. 125 """ 126 logger.info("Creating tag name=%r", name) 127 return cast( 128 Tag, 129 await self._core._create_resource( 130 "tags", 131 Tag, 132 owner=owner, 133 set_permissions=set_permissions, 134 name=name, 135 color=color, 136 is_inbox_tag=is_inbox_tag, 137 match=match, 138 matching_algorithm=matching_algorithm, 139 is_insensitive=is_insensitive, 140 parent=parent, 141 ), 142 )
Create a new tag.
Arguments:
- name: Tag name. Must be unique.
- color: Background colour as a CSS hex string.
- is_inbox_tag: When
True, newly ingested documents get this tag. - match: Auto-matching pattern.
- matching_algorithm: Controls how
matchis applied. E.g.matching_algorithm=MatchingAlgorithm.REGEXfor regular-expression matching. - is_insensitive: When
True,matchis case-insensitive. Defaults toTrue, matching the paperless-ngx API default. - parent: ID of parent tag for hierarchical trees.
- owner: Numeric user ID to assign as owner.
- set_permissions: Explicit view/change permission sets.
Pass
Noneto create with empty permissions.
Returns:
The newly created
~easypaperless.models.tags.Tag.
144 async def update( 145 self, 146 id: int, 147 *, 148 name: str | Unset = UNSET, 149 color: str | Unset = UNSET, 150 is_inbox_tag: bool | Unset = UNSET, 151 match: str | Unset = UNSET, 152 matching_algorithm: MatchingAlgorithm | Unset = UNSET, 153 is_insensitive: bool | Unset = UNSET, 154 parent: int | None | Unset = UNSET, 155 owner: int | None | Unset = UNSET, 156 set_permissions: SetPermissions | None | Unset = UNSET, 157 ) -> Tag: 158 """Partially update a tag (PATCH semantics). 159 160 Args: 161 id: Numeric ID of the tag to update. 162 name: Tag name. 163 color: Background colour as a CSS hex string. 164 is_inbox_tag: When ``True``, newly ingested documents get this tag. 165 match: Auto-matching pattern. 166 matching_algorithm: Controls how ``match`` is applied. 167 E.g. ``matching_algorithm=MatchingAlgorithm.REGEX`` for 168 regular-expression matching. 169 is_insensitive: When ``True``, ``match`` is case-insensitive. 170 parent: ID of parent tag. 171 Pass ``None`` to clear (make root tag). 172 Omit (or pass :data:`~easypaperless.UNSET`) to leave unchanged. 173 owner: Numeric user ID to assign as owner. 174 Pass ``None`` to clear the owner. 175 Omit (or pass :data:`~easypaperless.UNSET`) to leave unchanged. 176 set_permissions: Explicit view/change permission sets. 177 Pass ``None`` to clear all permissions (overwrite with empty). 178 Omit (or pass :data:`~easypaperless.UNSET`) to leave unchanged. 179 180 Returns: 181 The updated :class:`~easypaperless.models.tags.Tag`. 182 """ 183 logger.info("Updating tag id=%d", id) 184 return cast( 185 Tag, 186 await self._core._update_resource( 187 "tags", 188 id, 189 Tag, 190 name=name, 191 color=color, 192 is_inbox_tag=is_inbox_tag, 193 match=match, 194 matching_algorithm=matching_algorithm, 195 is_insensitive=is_insensitive, 196 parent=parent, 197 owner=owner, 198 set_permissions=set_permissions, 199 ), 200 )
Partially update a tag (PATCH semantics).
Arguments:
- id: Numeric ID of the tag to update.
- name: Tag name.
- color: Background colour as a CSS hex string.
- is_inbox_tag: When
True, newly ingested documents get this tag. - match: Auto-matching pattern.
- matching_algorithm: Controls how
matchis applied. E.g.matching_algorithm=MatchingAlgorithm.REGEXfor regular-expression matching. - is_insensitive: When
True,matchis case-insensitive. - parent: ID of parent tag.
Pass
Noneto clear (make root tag). Omit (or pass~easypaperless.UNSET) to leave unchanged. - owner: Numeric user ID to assign as owner.
Pass
Noneto clear the owner. Omit (or pass~easypaperless.UNSET) to leave unchanged. - set_permissions: Explicit view/change permission sets.
Pass
Noneto clear all permissions (overwrite with empty). Omit (or pass~easypaperless.UNSET) to leave unchanged.
Returns:
The updated
~easypaperless.models.tags.Tag.
202 async def delete(self, id: int) -> None: 203 """Delete a tag. 204 205 Args: 206 id: Numeric ID of the tag to delete. 207 208 Raises: 209 ~easypaperless.exceptions.NotFoundError: If no tag exists with 210 that ID. 211 """ 212 logger.info("Deleting tag id=%d", id) 213 await self._core._delete_resource("tags", id)
Delete a tag.
Arguments:
- id: Numeric ID of the tag to delete.
Raises:
- ~easypaperless.exceptions.NotFoundError: If no tag exists with that ID.
215 async def bulk_delete(self, ids: List[int]) -> None: 216 """Permanently delete multiple tags in a single request. 217 218 Args: 219 ids: List of tag IDs to delete. 220 """ 221 logger.info("Bulk deleting %d tags", len(ids)) 222 await self._core._bulk_edit_objects("tags", ids, "delete")
Permanently delete multiple tags in a single request.
Arguments:
- ids: List of tag IDs to delete.
224 async def bulk_set_permissions( 225 self, 226 ids: List[int], 227 *, 228 set_permissions: SetPermissions | Unset = UNSET, 229 owner: int | None | Unset = UNSET, 230 merge: bool = False, 231 ) -> None: 232 """Set permissions and/or owner on multiple tags. 233 234 Args: 235 ids: List of tag IDs to modify. 236 set_permissions: Explicit view/change permission sets. 237 Omit (or pass :data:`~easypaperless.UNSET`) to leave unchanged. 238 owner: Numeric user ID to assign as owner. 239 Pass ``None`` to clear the owner. 240 Omit (or pass :data:`~easypaperless.UNSET`) to leave unchanged. 241 merge: When ``True``, new permissions are merged with existing ones. 242 """ 243 logger.info("Bulk setting permissions on %d tags", len(ids)) 244 params: dict[str, Any] = {"merge": merge} 245 if not isinstance(set_permissions, Unset): 246 params["permissions"] = set_permissions.model_dump() 247 if not isinstance(owner, Unset): 248 params["owner"] = owner 249 await self._core._bulk_edit_objects("tags", ids, "set_permissions", **params)
Set permissions and/or owner on multiple tags.
Arguments:
- ids: List of tag IDs to modify.
- set_permissions: Explicit view/change permission sets.
Omit (or pass
~easypaperless.UNSET) to leave unchanged. - owner: Numeric user ID to assign as owner.
Pass
Noneto clear the owner. Omit (or pass~easypaperless.UNSET) to leave unchanged. - merge: When
True, new permissions are merged with existing ones.
18class SyncCorrespondentsResource: 19 """Sync accessor for correspondents: ``client.correspondents``.""" 20 21 def __init__(self, async_correspondents: CorrespondentsResource, run: Any) -> None: 22 self._async_correspondents = async_correspondents 23 self._run = run 24 25 def list( 26 self, 27 *, 28 ids: List[int] | None = None, 29 name_contains: str | None = None, 30 name_exact: str | None = None, 31 page: int | None = None, 32 page_size: int | None = None, 33 ordering: str | None = None, 34 descending: bool = False, 35 ) -> PagedResult[Correspondent]: 36 """Return correspondents defined in paperless-ngx. 37 38 When ``page`` is ``None`` (the default), all pages are fetched 39 automatically and ``next`` / ``previous`` in the result are always 40 ``None``. When ``page`` is set, only that page is fetched and 41 ``next`` / ``previous`` reflect the raw API values. 42 43 Args: 44 ids: Return only correspondents whose ID is in this list. 45 name_contains: Case-insensitive substring filter on name. 46 name_exact: Case-insensitive exact match on name. 47 page: Return only this specific page (1-based). 48 page_size: Number of results per page. 49 ordering: Field to sort by. 50 descending: When ``True``, reverses the sort direction. 51 52 Returns: 53 :class:`~easypaperless.models.paged_result.PagedResult` of 54 :class:`~easypaperless.models.correspondents.Correspondent` objects. 55 """ 56 return cast( 57 PagedResult[Correspondent], 58 self._run( 59 self._async_correspondents.list( 60 ids=ids, 61 name_contains=name_contains, 62 name_exact=name_exact, 63 page=page, 64 page_size=page_size, 65 ordering=ordering, 66 descending=descending, 67 ) 68 ), 69 ) 70 71 def get(self, id: int) -> Correspondent: 72 """Fetch a single correspondent by its ID. 73 74 Args: 75 id: Numeric correspondent ID. 76 77 Returns: 78 The :class:`~easypaperless.models.correspondents.Correspondent` with the given ID. 79 80 Raises: 81 ~easypaperless.exceptions.NotFoundError: If no correspondent exists with that ID. 82 """ 83 return cast(Correspondent, self._run(self._async_correspondents.get(id))) 84 85 def create( 86 self, 87 *, 88 name: str, 89 match: str | Unset = UNSET, 90 matching_algorithm: MatchingAlgorithm | Unset = UNSET, 91 is_insensitive: bool = True, 92 owner: int | None | Unset = UNSET, 93 set_permissions: SetPermissions | None | Unset = UNSET, 94 ) -> Correspondent: 95 """Create a new correspondent. 96 97 Args: 98 name: Correspondent name. Must be unique. 99 match: Auto-matching pattern. 100 matching_algorithm: Controls how ``match`` is applied. 101 E.g. ``matching_algorithm=MatchingAlgorithm.REGEX`` for 102 regular-expression matching. 103 is_insensitive: When ``True``, ``match`` is case-insensitive. 104 Defaults to ``True``, matching the paperless-ngx API default. 105 owner: Numeric user ID to assign as owner. 106 set_permissions: Explicit view/change permission sets. 107 Pass ``None`` to create with empty permissions. 108 109 Returns: 110 The newly created :class:`~easypaperless.models.correspondents.Correspondent`. 111 """ 112 return cast( 113 Correspondent, 114 self._run( 115 self._async_correspondents.create( 116 name=name, 117 match=match, 118 matching_algorithm=matching_algorithm, 119 is_insensitive=is_insensitive, 120 owner=owner, 121 set_permissions=set_permissions, 122 ) 123 ), 124 ) 125 126 def update( 127 self, 128 id: int, 129 *, 130 name: str | Unset = UNSET, 131 match: str | Unset = UNSET, 132 matching_algorithm: MatchingAlgorithm | Unset = UNSET, 133 is_insensitive: bool | Unset = UNSET, 134 owner: int | None | Unset = UNSET, 135 set_permissions: SetPermissions | None | Unset = UNSET, 136 ) -> Correspondent: 137 """Partially update a correspondent (PATCH semantics). 138 139 Args: 140 id: Numeric ID of the correspondent to update. 141 name: Correspondent name. 142 match: Auto-matching pattern. 143 matching_algorithm: Controls how ``match`` is applied. 144 E.g. ``matching_algorithm=MatchingAlgorithm.REGEX`` for 145 regular-expression matching. 146 is_insensitive: When ``True``, ``match`` is case-insensitive. 147 owner: Numeric user ID to assign as owner. 148 Pass ``None`` to clear the owner. 149 Omit (or pass :data:`~easypaperless.UNSET`) to leave unchanged. 150 set_permissions: Explicit view/change permission sets. 151 Pass ``None`` to clear all permissions (overwrite with empty). 152 Omit (or pass :data:`~easypaperless.UNSET`) to leave unchanged. 153 154 Returns: 155 The updated :class:`~easypaperless.models.correspondents.Correspondent`. 156 """ 157 return cast( 158 Correspondent, 159 self._run( 160 self._async_correspondents.update( 161 id, 162 name=name, 163 match=match, 164 matching_algorithm=matching_algorithm, 165 is_insensitive=is_insensitive, 166 owner=owner, 167 set_permissions=set_permissions, 168 ) 169 ), 170 ) 171 172 def delete(self, id: int) -> None: 173 """Delete a correspondent. 174 175 Args: 176 id: Numeric ID of the correspondent to delete. 177 178 Raises: 179 ~easypaperless.exceptions.NotFoundError: If no correspondent exists with that ID. 180 """ 181 self._run(self._async_correspondents.delete(id)) 182 183 def bulk_delete(self, ids: List[int]) -> None: 184 """Permanently delete multiple correspondents in a single request. 185 186 Args: 187 ids: List of correspondent IDs to delete. 188 """ 189 self._run(self._async_correspondents.bulk_delete(ids)) 190 191 def bulk_set_permissions( 192 self, 193 ids: List[int], 194 *, 195 set_permissions: SetPermissions | Unset = UNSET, 196 owner: int | None | Unset = UNSET, 197 merge: bool = False, 198 ) -> None: 199 """Set permissions and/or owner on multiple correspondents. 200 201 Args: 202 ids: List of correspondent IDs to modify. 203 set_permissions: Explicit view/change permission sets. 204 Omit (or pass :data:`~easypaperless.UNSET`) to leave unchanged. 205 owner: Numeric user ID to assign as owner. 206 Pass ``None`` to clear the owner. 207 Omit (or pass :data:`~easypaperless.UNSET`) to leave unchanged. 208 merge: When ``True``, new permissions are merged with existing ones. 209 """ 210 self._run( 211 self._async_correspondents.bulk_set_permissions( 212 ids, set_permissions=set_permissions, owner=owner, merge=merge 213 ) 214 )
Sync accessor for correspondents: client.correspondents.
25 def list( 26 self, 27 *, 28 ids: List[int] | None = None, 29 name_contains: str | None = None, 30 name_exact: str | None = None, 31 page: int | None = None, 32 page_size: int | None = None, 33 ordering: str | None = None, 34 descending: bool = False, 35 ) -> PagedResult[Correspondent]: 36 """Return correspondents defined in paperless-ngx. 37 38 When ``page`` is ``None`` (the default), all pages are fetched 39 automatically and ``next`` / ``previous`` in the result are always 40 ``None``. When ``page`` is set, only that page is fetched and 41 ``next`` / ``previous`` reflect the raw API values. 42 43 Args: 44 ids: Return only correspondents whose ID is in this list. 45 name_contains: Case-insensitive substring filter on name. 46 name_exact: Case-insensitive exact match on name. 47 page: Return only this specific page (1-based). 48 page_size: Number of results per page. 49 ordering: Field to sort by. 50 descending: When ``True``, reverses the sort direction. 51 52 Returns: 53 :class:`~easypaperless.models.paged_result.PagedResult` of 54 :class:`~easypaperless.models.correspondents.Correspondent` objects. 55 """ 56 return cast( 57 PagedResult[Correspondent], 58 self._run( 59 self._async_correspondents.list( 60 ids=ids, 61 name_contains=name_contains, 62 name_exact=name_exact, 63 page=page, 64 page_size=page_size, 65 ordering=ordering, 66 descending=descending, 67 ) 68 ), 69 )
Return correspondents defined in paperless-ngx.
When page is None (the default), all pages are fetched
automatically and next / previous in the result are always
None. When page is set, only that page is fetched and
next / previous reflect the raw API values.
Arguments:
- ids: Return only correspondents whose ID is in this list.
- name_contains: Case-insensitive substring filter on name.
- name_exact: Case-insensitive exact match on name.
- page: Return only this specific page (1-based).
- page_size: Number of results per page.
- ordering: Field to sort by.
- descending: When
True, reverses the sort direction.
Returns:
~easypaperless.models.paged_result.PagedResultof~easypaperless.models.correspondents.Correspondentobjects.
71 def get(self, id: int) -> Correspondent: 72 """Fetch a single correspondent by its ID. 73 74 Args: 75 id: Numeric correspondent ID. 76 77 Returns: 78 The :class:`~easypaperless.models.correspondents.Correspondent` with the given ID. 79 80 Raises: 81 ~easypaperless.exceptions.NotFoundError: If no correspondent exists with that ID. 82 """ 83 return cast(Correspondent, self._run(self._async_correspondents.get(id)))
Fetch a single correspondent by its ID.
Arguments:
- id: Numeric correspondent ID.
Returns:
The
~easypaperless.models.correspondents.Correspondentwith the given ID.
Raises:
- ~easypaperless.exceptions.NotFoundError: If no correspondent exists with that ID.
85 def create( 86 self, 87 *, 88 name: str, 89 match: str | Unset = UNSET, 90 matching_algorithm: MatchingAlgorithm | Unset = UNSET, 91 is_insensitive: bool = True, 92 owner: int | None | Unset = UNSET, 93 set_permissions: SetPermissions | None | Unset = UNSET, 94 ) -> Correspondent: 95 """Create a new correspondent. 96 97 Args: 98 name: Correspondent name. Must be unique. 99 match: Auto-matching pattern. 100 matching_algorithm: Controls how ``match`` is applied. 101 E.g. ``matching_algorithm=MatchingAlgorithm.REGEX`` for 102 regular-expression matching. 103 is_insensitive: When ``True``, ``match`` is case-insensitive. 104 Defaults to ``True``, matching the paperless-ngx API default. 105 owner: Numeric user ID to assign as owner. 106 set_permissions: Explicit view/change permission sets. 107 Pass ``None`` to create with empty permissions. 108 109 Returns: 110 The newly created :class:`~easypaperless.models.correspondents.Correspondent`. 111 """ 112 return cast( 113 Correspondent, 114 self._run( 115 self._async_correspondents.create( 116 name=name, 117 match=match, 118 matching_algorithm=matching_algorithm, 119 is_insensitive=is_insensitive, 120 owner=owner, 121 set_permissions=set_permissions, 122 ) 123 ), 124 )
Create a new correspondent.
Arguments:
- name: Correspondent name. Must be unique.
- match: Auto-matching pattern.
- matching_algorithm: Controls how
matchis applied. E.g.matching_algorithm=MatchingAlgorithm.REGEXfor regular-expression matching. - is_insensitive: When
True,matchis case-insensitive. Defaults toTrue, matching the paperless-ngx API default. - owner: Numeric user ID to assign as owner.
- set_permissions: Explicit view/change permission sets.
Pass
Noneto create with empty permissions.
Returns:
The newly created
~easypaperless.models.correspondents.Correspondent.
126 def update( 127 self, 128 id: int, 129 *, 130 name: str | Unset = UNSET, 131 match: str | Unset = UNSET, 132 matching_algorithm: MatchingAlgorithm | Unset = UNSET, 133 is_insensitive: bool | Unset = UNSET, 134 owner: int | None | Unset = UNSET, 135 set_permissions: SetPermissions | None | Unset = UNSET, 136 ) -> Correspondent: 137 """Partially update a correspondent (PATCH semantics). 138 139 Args: 140 id: Numeric ID of the correspondent to update. 141 name: Correspondent name. 142 match: Auto-matching pattern. 143 matching_algorithm: Controls how ``match`` is applied. 144 E.g. ``matching_algorithm=MatchingAlgorithm.REGEX`` for 145 regular-expression matching. 146 is_insensitive: When ``True``, ``match`` is case-insensitive. 147 owner: Numeric user ID to assign as owner. 148 Pass ``None`` to clear the owner. 149 Omit (or pass :data:`~easypaperless.UNSET`) to leave unchanged. 150 set_permissions: Explicit view/change permission sets. 151 Pass ``None`` to clear all permissions (overwrite with empty). 152 Omit (or pass :data:`~easypaperless.UNSET`) to leave unchanged. 153 154 Returns: 155 The updated :class:`~easypaperless.models.correspondents.Correspondent`. 156 """ 157 return cast( 158 Correspondent, 159 self._run( 160 self._async_correspondents.update( 161 id, 162 name=name, 163 match=match, 164 matching_algorithm=matching_algorithm, 165 is_insensitive=is_insensitive, 166 owner=owner, 167 set_permissions=set_permissions, 168 ) 169 ), 170 )
Partially update a correspondent (PATCH semantics).
Arguments:
- id: Numeric ID of the correspondent to update.
- name: Correspondent name.
- match: Auto-matching pattern.
- matching_algorithm: Controls how
matchis applied. E.g.matching_algorithm=MatchingAlgorithm.REGEXfor regular-expression matching. - is_insensitive: When
True,matchis case-insensitive. - owner: Numeric user ID to assign as owner.
Pass
Noneto clear the owner. Omit (or pass~easypaperless.UNSET) to leave unchanged. - set_permissions: Explicit view/change permission sets.
Pass
Noneto clear all permissions (overwrite with empty). Omit (or pass~easypaperless.UNSET) to leave unchanged.
Returns:
The updated
~easypaperless.models.correspondents.Correspondent.
172 def delete(self, id: int) -> None: 173 """Delete a correspondent. 174 175 Args: 176 id: Numeric ID of the correspondent to delete. 177 178 Raises: 179 ~easypaperless.exceptions.NotFoundError: If no correspondent exists with that ID. 180 """ 181 self._run(self._async_correspondents.delete(id))
Delete a correspondent.
Arguments:
- id: Numeric ID of the correspondent to delete.
Raises:
- ~easypaperless.exceptions.NotFoundError: If no correspondent exists with that ID.
183 def bulk_delete(self, ids: List[int]) -> None: 184 """Permanently delete multiple correspondents in a single request. 185 186 Args: 187 ids: List of correspondent IDs to delete. 188 """ 189 self._run(self._async_correspondents.bulk_delete(ids))
Permanently delete multiple correspondents in a single request.
Arguments:
- ids: List of correspondent IDs to delete.
191 def bulk_set_permissions( 192 self, 193 ids: List[int], 194 *, 195 set_permissions: SetPermissions | Unset = UNSET, 196 owner: int | None | Unset = UNSET, 197 merge: bool = False, 198 ) -> None: 199 """Set permissions and/or owner on multiple correspondents. 200 201 Args: 202 ids: List of correspondent IDs to modify. 203 set_permissions: Explicit view/change permission sets. 204 Omit (or pass :data:`~easypaperless.UNSET`) to leave unchanged. 205 owner: Numeric user ID to assign as owner. 206 Pass ``None`` to clear the owner. 207 Omit (or pass :data:`~easypaperless.UNSET`) to leave unchanged. 208 merge: When ``True``, new permissions are merged with existing ones. 209 """ 210 self._run( 211 self._async_correspondents.bulk_set_permissions( 212 ids, set_permissions=set_permissions, owner=owner, merge=merge 213 ) 214 )
Set permissions and/or owner on multiple correspondents.
Arguments:
- ids: List of correspondent IDs to modify.
- set_permissions: Explicit view/change permission sets.
Omit (or pass
~easypaperless.UNSET) to leave unchanged. - owner: Numeric user ID to assign as owner.
Pass
Noneto clear the owner. Omit (or pass~easypaperless.UNSET) to leave unchanged. - merge: When
True, new permissions are merged with existing ones.
17class SyncCustomFieldsResource: 18 """Sync accessor for custom fields: ``client.custom_fields``.""" 19 20 def __init__(self, async_custom_fields: CustomFieldsResource, run: Any) -> None: 21 self._async_custom_fields = async_custom_fields 22 self._run = run 23 24 def list( 25 self, 26 *, 27 name_contains: str | None = None, 28 name_exact: str | None = None, 29 page: int | None = None, 30 page_size: int | None = None, 31 ordering: str | None = None, 32 descending: bool = False, 33 ) -> PagedResult[CustomField]: 34 """Return all custom fields defined in paperless-ngx. 35 36 When ``page`` is ``None`` (the default), all pages are fetched 37 automatically and ``next`` / ``previous`` in the result are always 38 ``None``. When ``page`` is set, only that page is fetched and 39 ``next`` / ``previous`` reflect the raw API values. 40 41 Args: 42 name_contains: Case-insensitive substring filter on name. 43 name_exact: Case-insensitive exact match on name. 44 page: Return only this specific page (1-based). 45 page_size: Number of results per page. 46 ordering: Field to sort by. 47 descending: When ``True``, reverses the sort direction. 48 49 Returns: 50 :class:`~easypaperless.models.paged_result.PagedResult` of 51 :class:`~easypaperless.models.custom_fields.CustomField` objects. 52 """ 53 return cast( 54 PagedResult[CustomField], 55 self._run( 56 self._async_custom_fields.list( 57 name_contains=name_contains, 58 name_exact=name_exact, 59 page=page, 60 page_size=page_size, 61 ordering=ordering, 62 descending=descending, 63 ) 64 ), 65 ) 66 67 def get(self, id: int) -> CustomField: 68 """Fetch a single custom field by its ID. 69 70 Args: 71 id: Numeric custom-field ID. 72 73 Returns: 74 The :class:`~easypaperless.models.custom_fields.CustomField` with the given ID. 75 76 Raises: 77 ~easypaperless.exceptions.NotFoundError: If no custom field exists with that ID. 78 """ 79 return cast(CustomField, self._run(self._async_custom_fields.get(id))) 80 81 def create( 82 self, 83 *, 84 name: str, 85 data_type: str, 86 extra_data: Any | None = None, 87 owner: int | None | Unset = UNSET, 88 set_permissions: SetPermissions | None | Unset = UNSET, 89 ) -> CustomField: 90 """Create a new custom field. 91 92 Args: 93 name: Field name shown in the UI. Must be unique. 94 data_type: Value type. One of ``"string"``, ``"boolean"``, 95 ``"integer"``, ``"float"``, ``"monetary"``, ``"date"``, 96 ``"url"``, ``"documentlink"``, ``"select"``. 97 extra_data: Additional configuration for the field type. 98 owner: Numeric user ID to assign as owner. 99 set_permissions: Explicit view/change permission sets. 100 Pass ``None`` to create with empty permissions. 101 102 Returns: 103 The newly created :class:`~easypaperless.models.custom_fields.CustomField`. 104 """ 105 return cast( 106 CustomField, 107 self._run( 108 self._async_custom_fields.create( 109 name=name, 110 data_type=data_type, 111 extra_data=extra_data, 112 owner=owner, 113 set_permissions=set_permissions, 114 ) 115 ), 116 ) 117 118 def update( 119 self, 120 id: int, 121 *, 122 name: str | Unset = UNSET, 123 data_type: str | Unset = UNSET, 124 extra_data: Any | None | Unset = UNSET, 125 owner: int | None | Unset = UNSET, 126 set_permissions: SetPermissions | None | Unset = UNSET, 127 ) -> CustomField: 128 """Partially update a custom field (PATCH semantics). 129 130 Args: 131 id: Numeric ID of the custom field to update. 132 name: Field name shown in the UI. 133 data_type: Value type (e.g. ``"string"``, ``"boolean"``, ``"integer"``). 134 Omit (or pass :data:`~easypaperless.UNSET`) to leave unchanged. 135 extra_data: Additional configuration for the field type. 136 owner: Numeric user ID to assign as owner. 137 Pass ``None`` to clear the owner. 138 Omit (or pass :data:`~easypaperless.UNSET`) to leave unchanged. 139 set_permissions: Explicit view/change permission sets. 140 Pass ``None`` to clear all permissions (overwrite with empty). 141 Omit (or pass :data:`~easypaperless.UNSET`) to leave unchanged. 142 143 Returns: 144 The updated :class:`~easypaperless.models.custom_fields.CustomField`. 145 """ 146 return cast( 147 CustomField, 148 self._run( 149 self._async_custom_fields.update( 150 id, 151 name=name, 152 data_type=data_type, 153 extra_data=extra_data, 154 owner=owner, 155 set_permissions=set_permissions, 156 ) 157 ), 158 ) 159 160 def delete(self, id: int) -> None: 161 """Delete a custom field. 162 163 Args: 164 id: Numeric ID of the custom field to delete. 165 166 Raises: 167 ~easypaperless.exceptions.NotFoundError: If no custom field exists with that ID. 168 """ 169 self._run(self._async_custom_fields.delete(id))
Sync accessor for custom fields: client.custom_fields.
24 def list( 25 self, 26 *, 27 name_contains: str | None = None, 28 name_exact: str | None = None, 29 page: int | None = None, 30 page_size: int | None = None, 31 ordering: str | None = None, 32 descending: bool = False, 33 ) -> PagedResult[CustomField]: 34 """Return all custom fields defined in paperless-ngx. 35 36 When ``page`` is ``None`` (the default), all pages are fetched 37 automatically and ``next`` / ``previous`` in the result are always 38 ``None``. When ``page`` is set, only that page is fetched and 39 ``next`` / ``previous`` reflect the raw API values. 40 41 Args: 42 name_contains: Case-insensitive substring filter on name. 43 name_exact: Case-insensitive exact match on name. 44 page: Return only this specific page (1-based). 45 page_size: Number of results per page. 46 ordering: Field to sort by. 47 descending: When ``True``, reverses the sort direction. 48 49 Returns: 50 :class:`~easypaperless.models.paged_result.PagedResult` of 51 :class:`~easypaperless.models.custom_fields.CustomField` objects. 52 """ 53 return cast( 54 PagedResult[CustomField], 55 self._run( 56 self._async_custom_fields.list( 57 name_contains=name_contains, 58 name_exact=name_exact, 59 page=page, 60 page_size=page_size, 61 ordering=ordering, 62 descending=descending, 63 ) 64 ), 65 )
Return all custom fields defined in paperless-ngx.
When page is None (the default), all pages are fetched
automatically and next / previous in the result are always
None. When page is set, only that page is fetched and
next / previous reflect the raw API values.
Arguments:
- name_contains: Case-insensitive substring filter on name.
- name_exact: Case-insensitive exact match on name.
- page: Return only this specific page (1-based).
- page_size: Number of results per page.
- ordering: Field to sort by.
- descending: When
True, reverses the sort direction.
Returns:
~easypaperless.models.paged_result.PagedResultof~easypaperless.models.custom_fields.CustomFieldobjects.
67 def get(self, id: int) -> CustomField: 68 """Fetch a single custom field by its ID. 69 70 Args: 71 id: Numeric custom-field ID. 72 73 Returns: 74 The :class:`~easypaperless.models.custom_fields.CustomField` with the given ID. 75 76 Raises: 77 ~easypaperless.exceptions.NotFoundError: If no custom field exists with that ID. 78 """ 79 return cast(CustomField, self._run(self._async_custom_fields.get(id)))
Fetch a single custom field by its ID.
Arguments:
- id: Numeric custom-field ID.
Returns:
The
~easypaperless.models.custom_fields.CustomFieldwith the given ID.
Raises:
- ~easypaperless.exceptions.NotFoundError: If no custom field exists with that ID.
81 def create( 82 self, 83 *, 84 name: str, 85 data_type: str, 86 extra_data: Any | None = None, 87 owner: int | None | Unset = UNSET, 88 set_permissions: SetPermissions | None | Unset = UNSET, 89 ) -> CustomField: 90 """Create a new custom field. 91 92 Args: 93 name: Field name shown in the UI. Must be unique. 94 data_type: Value type. One of ``"string"``, ``"boolean"``, 95 ``"integer"``, ``"float"``, ``"monetary"``, ``"date"``, 96 ``"url"``, ``"documentlink"``, ``"select"``. 97 extra_data: Additional configuration for the field type. 98 owner: Numeric user ID to assign as owner. 99 set_permissions: Explicit view/change permission sets. 100 Pass ``None`` to create with empty permissions. 101 102 Returns: 103 The newly created :class:`~easypaperless.models.custom_fields.CustomField`. 104 """ 105 return cast( 106 CustomField, 107 self._run( 108 self._async_custom_fields.create( 109 name=name, 110 data_type=data_type, 111 extra_data=extra_data, 112 owner=owner, 113 set_permissions=set_permissions, 114 ) 115 ), 116 )
Create a new custom field.
Arguments:
- name: Field name shown in the UI. Must be unique.
- data_type: Value type. One of
"string","boolean","integer","float","monetary","date","url","documentlink","select". - extra_data: Additional configuration for the field type.
- owner: Numeric user ID to assign as owner.
- set_permissions: Explicit view/change permission sets.
Pass
Noneto create with empty permissions.
Returns:
The newly created
~easypaperless.models.custom_fields.CustomField.
118 def update( 119 self, 120 id: int, 121 *, 122 name: str | Unset = UNSET, 123 data_type: str | Unset = UNSET, 124 extra_data: Any | None | Unset = UNSET, 125 owner: int | None | Unset = UNSET, 126 set_permissions: SetPermissions | None | Unset = UNSET, 127 ) -> CustomField: 128 """Partially update a custom field (PATCH semantics). 129 130 Args: 131 id: Numeric ID of the custom field to update. 132 name: Field name shown in the UI. 133 data_type: Value type (e.g. ``"string"``, ``"boolean"``, ``"integer"``). 134 Omit (or pass :data:`~easypaperless.UNSET`) to leave unchanged. 135 extra_data: Additional configuration for the field type. 136 owner: Numeric user ID to assign as owner. 137 Pass ``None`` to clear the owner. 138 Omit (or pass :data:`~easypaperless.UNSET`) to leave unchanged. 139 set_permissions: Explicit view/change permission sets. 140 Pass ``None`` to clear all permissions (overwrite with empty). 141 Omit (or pass :data:`~easypaperless.UNSET`) to leave unchanged. 142 143 Returns: 144 The updated :class:`~easypaperless.models.custom_fields.CustomField`. 145 """ 146 return cast( 147 CustomField, 148 self._run( 149 self._async_custom_fields.update( 150 id, 151 name=name, 152 data_type=data_type, 153 extra_data=extra_data, 154 owner=owner, 155 set_permissions=set_permissions, 156 ) 157 ), 158 )
Partially update a custom field (PATCH semantics).
Arguments:
- id: Numeric ID of the custom field to update.
- name: Field name shown in the UI.
- data_type: Value type (e.g.
"string","boolean","integer"). Omit (or pass~easypaperless.UNSET) to leave unchanged. - extra_data: Additional configuration for the field type.
- owner: Numeric user ID to assign as owner.
Pass
Noneto clear the owner. Omit (or pass~easypaperless.UNSET) to leave unchanged. - set_permissions: Explicit view/change permission sets.
Pass
Noneto clear all permissions (overwrite with empty). Omit (or pass~easypaperless.UNSET) to leave unchanged.
Returns:
The updated
~easypaperless.models.custom_fields.CustomField.
160 def delete(self, id: int) -> None: 161 """Delete a custom field. 162 163 Args: 164 id: Numeric ID of the custom field to delete. 165 166 Raises: 167 ~easypaperless.exceptions.NotFoundError: If no custom field exists with that ID. 168 """ 169 self._run(self._async_custom_fields.delete(id))
Delete a custom field.
Arguments:
- id: Numeric ID of the custom field to delete.
Raises:
- ~easypaperless.exceptions.NotFoundError: If no custom field exists with that ID.
18class SyncDocumentTypesResource: 19 """Sync accessor for document types: ``client.document_types``.""" 20 21 def __init__(self, async_document_types: DocumentTypesResource, run: Any) -> None: 22 self._async_document_types = async_document_types 23 self._run = run 24 25 def list( 26 self, 27 *, 28 ids: List[int] | None = None, 29 name_contains: str | None = None, 30 name_exact: str | None = None, 31 page: int | None = None, 32 page_size: int | None = None, 33 ordering: str | None = None, 34 descending: bool = False, 35 ) -> PagedResult[DocumentType]: 36 """Return document types defined in paperless-ngx. 37 38 When ``page`` is ``None`` (the default), all pages are fetched 39 automatically and ``next`` / ``previous`` in the result are always 40 ``None``. When ``page`` is set, only that page is fetched and 41 ``next`` / ``previous`` reflect the raw API values. 42 43 Args: 44 ids: Return only document types whose ID is in this list. 45 name_contains: Case-insensitive substring filter on name. 46 name_exact: Case-insensitive exact match on name. 47 page: Return only this specific page (1-based). 48 page_size: Number of results per page. 49 ordering: Field to sort by. 50 descending: When ``True``, reverses the sort direction. 51 52 Returns: 53 :class:`~easypaperless.models.paged_result.PagedResult` of 54 :class:`~easypaperless.models.document_types.DocumentType` objects. 55 """ 56 return cast( 57 PagedResult[DocumentType], 58 self._run( 59 self._async_document_types.list( 60 ids=ids, 61 name_contains=name_contains, 62 name_exact=name_exact, 63 page=page, 64 page_size=page_size, 65 ordering=ordering, 66 descending=descending, 67 ) 68 ), 69 ) 70 71 def get(self, id: int) -> DocumentType: 72 """Fetch a single document type by its ID. 73 74 Args: 75 id: Numeric document-type ID. 76 77 Returns: 78 The :class:`~easypaperless.models.document_types.DocumentType` with the given ID. 79 80 Raises: 81 ~easypaperless.exceptions.NotFoundError: If no document type exists with that ID. 82 """ 83 return cast(DocumentType, self._run(self._async_document_types.get(id))) 84 85 def create( 86 self, 87 *, 88 name: str, 89 match: str | Unset = UNSET, 90 matching_algorithm: MatchingAlgorithm | Unset = UNSET, 91 is_insensitive: bool = True, 92 owner: int | None | Unset = UNSET, 93 set_permissions: SetPermissions | None | Unset = UNSET, 94 ) -> DocumentType: 95 """Create a new document type. 96 97 Args: 98 name: Document-type name. Must be unique. 99 match: Auto-matching pattern. 100 matching_algorithm: Controls how ``match`` is applied. 101 E.g. ``matching_algorithm=MatchingAlgorithm.REGEX`` for 102 regular-expression matching. 103 is_insensitive: When ``True``, ``match`` is case-insensitive. 104 Defaults to ``True``, matching the paperless-ngx API default. 105 owner: Numeric user ID to assign as owner. 106 set_permissions: Explicit view/change permission sets. 107 Pass ``None`` to create with empty permissions. 108 109 Returns: 110 The newly created :class:`~easypaperless.models.document_types.DocumentType`. 111 """ 112 return cast( 113 DocumentType, 114 self._run( 115 self._async_document_types.create( 116 name=name, 117 match=match, 118 matching_algorithm=matching_algorithm, 119 is_insensitive=is_insensitive, 120 owner=owner, 121 set_permissions=set_permissions, 122 ) 123 ), 124 ) 125 126 def update( 127 self, 128 id: int, 129 *, 130 name: str | Unset = UNSET, 131 match: str | Unset = UNSET, 132 matching_algorithm: MatchingAlgorithm | Unset = UNSET, 133 is_insensitive: bool | Unset = UNSET, 134 owner: int | None | Unset = UNSET, 135 set_permissions: SetPermissions | None | Unset = UNSET, 136 ) -> DocumentType: 137 """Partially update a document type (PATCH semantics). 138 139 Args: 140 id: Numeric ID of the document type to update. 141 name: Document-type name. 142 match: Auto-matching pattern. 143 matching_algorithm: Controls how ``match`` is applied. 144 E.g. ``matching_algorithm=MatchingAlgorithm.REGEX`` for 145 regular-expression matching. 146 is_insensitive: When ``True``, ``match`` is case-insensitive. 147 owner: Numeric user ID to assign as owner. 148 Pass ``None`` to clear the owner. 149 Omit (or pass :data:`~easypaperless.UNSET`) to leave unchanged. 150 set_permissions: Explicit view/change permission sets. 151 Pass ``None`` to clear all permissions (overwrite with empty). 152 Omit (or pass :data:`~easypaperless.UNSET`) to leave unchanged. 153 154 Returns: 155 The updated :class:`~easypaperless.models.document_types.DocumentType`. 156 """ 157 return cast( 158 DocumentType, 159 self._run( 160 self._async_document_types.update( 161 id, 162 name=name, 163 match=match, 164 matching_algorithm=matching_algorithm, 165 is_insensitive=is_insensitive, 166 owner=owner, 167 set_permissions=set_permissions, 168 ) 169 ), 170 ) 171 172 def delete(self, id: int) -> None: 173 """Delete a document type. 174 175 Args: 176 id: Numeric ID of the document type to delete. 177 178 Raises: 179 ~easypaperless.exceptions.NotFoundError: If no document type exists with that ID. 180 """ 181 self._run(self._async_document_types.delete(id)) 182 183 def bulk_delete(self, ids: List[int]) -> None: 184 """Permanently delete multiple document types in a single request. 185 186 Args: 187 ids: List of document type IDs to delete. 188 """ 189 self._run(self._async_document_types.bulk_delete(ids)) 190 191 def bulk_set_permissions( 192 self, 193 ids: List[int], 194 *, 195 set_permissions: SetPermissions | Unset = UNSET, 196 owner: int | None | Unset = UNSET, 197 merge: bool = False, 198 ) -> None: 199 """Set permissions and/or owner on multiple document types. 200 201 Args: 202 ids: List of document type IDs to modify. 203 set_permissions: Explicit view/change permission sets. 204 Omit (or pass :data:`~easypaperless.UNSET`) to leave unchanged. 205 owner: Numeric user ID to assign as owner. 206 Pass ``None`` to clear the owner. 207 Omit (or pass :data:`~easypaperless.UNSET`) to leave unchanged. 208 merge: When ``True``, new permissions are merged with existing ones. 209 """ 210 self._run( 211 self._async_document_types.bulk_set_permissions( 212 ids, set_permissions=set_permissions, owner=owner, merge=merge 213 ) 214 )
Sync accessor for document types: client.document_types.
25 def list( 26 self, 27 *, 28 ids: List[int] | None = None, 29 name_contains: str | None = None, 30 name_exact: str | None = None, 31 page: int | None = None, 32 page_size: int | None = None, 33 ordering: str | None = None, 34 descending: bool = False, 35 ) -> PagedResult[DocumentType]: 36 """Return document types defined in paperless-ngx. 37 38 When ``page`` is ``None`` (the default), all pages are fetched 39 automatically and ``next`` / ``previous`` in the result are always 40 ``None``. When ``page`` is set, only that page is fetched and 41 ``next`` / ``previous`` reflect the raw API values. 42 43 Args: 44 ids: Return only document types whose ID is in this list. 45 name_contains: Case-insensitive substring filter on name. 46 name_exact: Case-insensitive exact match on name. 47 page: Return only this specific page (1-based). 48 page_size: Number of results per page. 49 ordering: Field to sort by. 50 descending: When ``True``, reverses the sort direction. 51 52 Returns: 53 :class:`~easypaperless.models.paged_result.PagedResult` of 54 :class:`~easypaperless.models.document_types.DocumentType` objects. 55 """ 56 return cast( 57 PagedResult[DocumentType], 58 self._run( 59 self._async_document_types.list( 60 ids=ids, 61 name_contains=name_contains, 62 name_exact=name_exact, 63 page=page, 64 page_size=page_size, 65 ordering=ordering, 66 descending=descending, 67 ) 68 ), 69 )
Return document types defined in paperless-ngx.
When page is None (the default), all pages are fetched
automatically and next / previous in the result are always
None. When page is set, only that page is fetched and
next / previous reflect the raw API values.
Arguments:
- ids: Return only document types whose ID is in this list.
- name_contains: Case-insensitive substring filter on name.
- name_exact: Case-insensitive exact match on name.
- page: Return only this specific page (1-based).
- page_size: Number of results per page.
- ordering: Field to sort by.
- descending: When
True, reverses the sort direction.
Returns:
~easypaperless.models.paged_result.PagedResultof~easypaperless.models.document_types.DocumentTypeobjects.
71 def get(self, id: int) -> DocumentType: 72 """Fetch a single document type by its ID. 73 74 Args: 75 id: Numeric document-type ID. 76 77 Returns: 78 The :class:`~easypaperless.models.document_types.DocumentType` with the given ID. 79 80 Raises: 81 ~easypaperless.exceptions.NotFoundError: If no document type exists with that ID. 82 """ 83 return cast(DocumentType, self._run(self._async_document_types.get(id)))
Fetch a single document type by its ID.
Arguments:
- id: Numeric document-type ID.
Returns:
The
~easypaperless.models.document_types.DocumentTypewith the given ID.
Raises:
- ~easypaperless.exceptions.NotFoundError: If no document type exists with that ID.
85 def create( 86 self, 87 *, 88 name: str, 89 match: str | Unset = UNSET, 90 matching_algorithm: MatchingAlgorithm | Unset = UNSET, 91 is_insensitive: bool = True, 92 owner: int | None | Unset = UNSET, 93 set_permissions: SetPermissions | None | Unset = UNSET, 94 ) -> DocumentType: 95 """Create a new document type. 96 97 Args: 98 name: Document-type name. Must be unique. 99 match: Auto-matching pattern. 100 matching_algorithm: Controls how ``match`` is applied. 101 E.g. ``matching_algorithm=MatchingAlgorithm.REGEX`` for 102 regular-expression matching. 103 is_insensitive: When ``True``, ``match`` is case-insensitive. 104 Defaults to ``True``, matching the paperless-ngx API default. 105 owner: Numeric user ID to assign as owner. 106 set_permissions: Explicit view/change permission sets. 107 Pass ``None`` to create with empty permissions. 108 109 Returns: 110 The newly created :class:`~easypaperless.models.document_types.DocumentType`. 111 """ 112 return cast( 113 DocumentType, 114 self._run( 115 self._async_document_types.create( 116 name=name, 117 match=match, 118 matching_algorithm=matching_algorithm, 119 is_insensitive=is_insensitive, 120 owner=owner, 121 set_permissions=set_permissions, 122 ) 123 ), 124 )
Create a new document type.
Arguments:
- name: Document-type name. Must be unique.
- match: Auto-matching pattern.
- matching_algorithm: Controls how
matchis applied. E.g.matching_algorithm=MatchingAlgorithm.REGEXfor regular-expression matching. - is_insensitive: When
True,matchis case-insensitive. Defaults toTrue, matching the paperless-ngx API default. - owner: Numeric user ID to assign as owner.
- set_permissions: Explicit view/change permission sets.
Pass
Noneto create with empty permissions.
Returns:
The newly created
~easypaperless.models.document_types.DocumentType.
126 def update( 127 self, 128 id: int, 129 *, 130 name: str | Unset = UNSET, 131 match: str | Unset = UNSET, 132 matching_algorithm: MatchingAlgorithm | Unset = UNSET, 133 is_insensitive: bool | Unset = UNSET, 134 owner: int | None | Unset = UNSET, 135 set_permissions: SetPermissions | None | Unset = UNSET, 136 ) -> DocumentType: 137 """Partially update a document type (PATCH semantics). 138 139 Args: 140 id: Numeric ID of the document type to update. 141 name: Document-type name. 142 match: Auto-matching pattern. 143 matching_algorithm: Controls how ``match`` is applied. 144 E.g. ``matching_algorithm=MatchingAlgorithm.REGEX`` for 145 regular-expression matching. 146 is_insensitive: When ``True``, ``match`` is case-insensitive. 147 owner: Numeric user ID to assign as owner. 148 Pass ``None`` to clear the owner. 149 Omit (or pass :data:`~easypaperless.UNSET`) to leave unchanged. 150 set_permissions: Explicit view/change permission sets. 151 Pass ``None`` to clear all permissions (overwrite with empty). 152 Omit (or pass :data:`~easypaperless.UNSET`) to leave unchanged. 153 154 Returns: 155 The updated :class:`~easypaperless.models.document_types.DocumentType`. 156 """ 157 return cast( 158 DocumentType, 159 self._run( 160 self._async_document_types.update( 161 id, 162 name=name, 163 match=match, 164 matching_algorithm=matching_algorithm, 165 is_insensitive=is_insensitive, 166 owner=owner, 167 set_permissions=set_permissions, 168 ) 169 ), 170 )
Partially update a document type (PATCH semantics).
Arguments:
- id: Numeric ID of the document type to update.
- name: Document-type name.
- match: Auto-matching pattern.
- matching_algorithm: Controls how
matchis applied. E.g.matching_algorithm=MatchingAlgorithm.REGEXfor regular-expression matching. - is_insensitive: When
True,matchis case-insensitive. - owner: Numeric user ID to assign as owner.
Pass
Noneto clear the owner. Omit (or pass~easypaperless.UNSET) to leave unchanged. - set_permissions: Explicit view/change permission sets.
Pass
Noneto clear all permissions (overwrite with empty). Omit (or pass~easypaperless.UNSET) to leave unchanged.
Returns:
The updated
~easypaperless.models.document_types.DocumentType.
172 def delete(self, id: int) -> None: 173 """Delete a document type. 174 175 Args: 176 id: Numeric ID of the document type to delete. 177 178 Raises: 179 ~easypaperless.exceptions.NotFoundError: If no document type exists with that ID. 180 """ 181 self._run(self._async_document_types.delete(id))
Delete a document type.
Arguments:
- id: Numeric ID of the document type to delete.
Raises:
- ~easypaperless.exceptions.NotFoundError: If no document type exists with that ID.
183 def bulk_delete(self, ids: List[int]) -> None: 184 """Permanently delete multiple document types in a single request. 185 186 Args: 187 ids: List of document type IDs to delete. 188 """ 189 self._run(self._async_document_types.bulk_delete(ids))
Permanently delete multiple document types in a single request.
Arguments:
- ids: List of document type IDs to delete.
191 def bulk_set_permissions( 192 self, 193 ids: List[int], 194 *, 195 set_permissions: SetPermissions | Unset = UNSET, 196 owner: int | None | Unset = UNSET, 197 merge: bool = False, 198 ) -> None: 199 """Set permissions and/or owner on multiple document types. 200 201 Args: 202 ids: List of document type IDs to modify. 203 set_permissions: Explicit view/change permission sets. 204 Omit (or pass :data:`~easypaperless.UNSET`) to leave unchanged. 205 owner: Numeric user ID to assign as owner. 206 Pass ``None`` to clear the owner. 207 Omit (or pass :data:`~easypaperless.UNSET`) to leave unchanged. 208 merge: When ``True``, new permissions are merged with existing ones. 209 """ 210 self._run( 211 self._async_document_types.bulk_set_permissions( 212 ids, set_permissions=set_permissions, owner=owner, merge=merge 213 ) 214 )
Set permissions and/or owner on multiple document types.
Arguments:
- ids: List of document type IDs to modify.
- set_permissions: Explicit view/change permission sets.
Omit (or pass
~easypaperless.UNSET) to leave unchanged. - owner: Numeric user ID to assign as owner.
Pass
Noneto clear the owner. Omit (or pass~easypaperless.UNSET) to leave unchanged. - merge: When
True, new permissions are merged with existing ones.
91class SyncDocumentsResource: 92 """Sync accessor for documents: ``client.documents``.""" 93 94 def __init__(self, async_documents: DocumentsResource, run: Any) -> None: 95 self._async_documents = async_documents 96 self._run = run 97 self.notes = SyncNotesResource(async_documents.notes, run) 98 99 def get(self, id: int, *, include_metadata: bool = False) -> Document: 100 """Fetch a single document by its ID. 101 102 Args: 103 id: Numeric paperless-ngx document ID. 104 include_metadata: When ``True``, the extended file-level metadata 105 is fetched concurrently and attached to the document. 106 Default: ``False``. 107 108 Returns: 109 The :class:`~easypaperless.models.documents.Document` with the 110 given ID. 111 112 Raises: 113 ~easypaperless.exceptions.NotFoundError: If no document exists 114 with that ID. 115 """ 116 return cast( 117 Document, self._run(self._async_documents.get(id, include_metadata=include_metadata)) 118 ) 119 120 def get_metadata(self, id: int) -> DocumentMetadata: 121 """Fetch the extended file-level metadata for a document. 122 123 Args: 124 id: Numeric paperless-ngx document ID. 125 126 Returns: 127 A :class:`~easypaperless.models.documents.DocumentMetadata` instance. 128 129 Raises: 130 ~easypaperless.exceptions.NotFoundError: If no document exists 131 with that ID. 132 """ 133 return cast(DocumentMetadata, self._run(self._async_documents.get_metadata(id))) 134 135 def list( 136 self, 137 *, 138 search: str | None = None, 139 search_mode: str = "title_or_content", 140 ids: List[int] | None = None, 141 tags: List[int | str] | None = None, 142 any_tags: List[int | str] | None = None, 143 exclude_tags: List[int | str] | None = None, 144 correspondent: int | str | None | Unset = UNSET, 145 any_correspondent: List[int | str] | None = None, 146 exclude_correspondents: List[int | str] | None = None, 147 document_type: int | str | None | Unset = UNSET, 148 document_type_name_contains: str | None = None, 149 document_type_name_exact: str | None = None, 150 any_document_type: List[int | str] | None = None, 151 exclude_document_types: List[int | str] | None = None, 152 storage_path: int | str | None | Unset = UNSET, 153 any_storage_paths: List[int | str] | None = None, 154 exclude_storage_paths: List[int | str] | None = None, 155 owner: int | None | Unset = UNSET, 156 exclude_owners: List[int] | None = None, 157 custom_fields: List[int | str] | None = None, 158 any_custom_fields: List[int | str] | None = None, 159 exclude_custom_fields: List[int | str] | None = None, 160 custom_field_query: List[Any] | None = None, 161 archive_serial_number: int | None | Unset = UNSET, 162 archive_serial_number_from: int | None = None, 163 archive_serial_number_till: int | None = None, 164 created_after: date | str | None = None, 165 created_before: date | str | None = None, 166 added_after: date | datetime | str | None = None, 167 added_from: date | datetime | str | None = None, 168 added_before: date | datetime | str | None = None, 169 added_until: date | datetime | str | None = None, 170 modified_after: date | datetime | str | None = None, 171 modified_from: date | datetime | str | None = None, 172 modified_before: date | datetime | str | None = None, 173 modified_until: date | datetime | str | None = None, 174 checksum: str | None = None, 175 page_size: int = 25, 176 page: int | None = None, 177 ordering: str | None = None, 178 descending: bool = False, 179 max_results: int | None = None, 180 on_page: Callable[[int, int | None], None] | None = None, 181 ) -> PagedResult[Document]: 182 """Return a filtered list of documents. 183 184 All tag, correspondent, document-type, storage-path, and custom-field 185 parameters accept either integer IDs or string names. 186 187 When ``page`` is ``None`` (the default), all pages are fetched 188 automatically and ``next`` / ``previous`` in the returned 189 :class:`~easypaperless.models.paged_result.PagedResult` are always 190 ``None`` — even if ``max_results`` truncates the final result set. 191 ``count`` always reflects the server total, not the truncated length. 192 When ``page`` is set to a specific integer, only that one page is 193 fetched and ``next`` / ``previous`` contain the raw API values. 194 195 Args: 196 search: Search string. Behaviour depends on ``search_mode``. 197 search_mode: How ``search`` is applied. One of: 198 ``"title_or_content"`` *(default)*, ``"title"``, ``"query"``, 199 ``"original_filename"``. 200 ids: Return only documents whose ID is in this list. 201 tags: Documents must have **all** of these tags (AND semantics). 202 any_tags: Documents must have **at least one** of these tags. 203 exclude_tags: Documents must have **none** of these tags. 204 correspondent: Filter to documents assigned to this correspondent. 205 Pass ``None`` to return only documents with no correspondent set. 206 any_correspondent: Filter to documents assigned to any of these. 207 exclude_correspondents: Exclude documents assigned to any of these. 208 document_type: Filter to documents of exactly this type. 209 Pass ``None`` to return only documents with no document type set. 210 document_type_name_contains: Case-insensitive substring filter on document type name. 211 document_type_name_exact: Case-insensitive exact match on document type name. 212 any_document_type: Filter to documents whose type is any of these. 213 exclude_document_types: Exclude documents whose type is any of these. 214 storage_path: Filter to documents assigned to this storage path. 215 Pass ``None`` to return only documents with no storage path set. 216 any_storage_paths: Filter to documents assigned to any of these paths. 217 exclude_storage_paths: Exclude documents assigned to any of these paths. 218 owner: Filter to documents owned by this user ID. 219 Pass ``None`` to return only documents with no owner set. 220 exclude_owners: Exclude documents owned by any of these user IDs. 221 custom_fields: Documents must have **all** of these custom fields set. 222 any_custom_fields: Documents must have **at least one** of these fields. 223 exclude_custom_fields: Documents must have **none** of these fields. 224 custom_field_query: Filter documents by custom field values using a nested 225 query structure. See the `paperless-ngx API docs 226 <https://docs.paperless-ngx.com/api/#filtering-by-custom-fields>`_ for 227 the query format. 228 archive_serial_number: Filter by exact archive serial number. 229 Pass ``None`` to return only documents with no ASN set. 230 archive_serial_number_from: Filter by ASN >= this value. 231 archive_serial_number_till: Filter by ASN <= this value. 232 created_after: Only documents created after this date. 233 String input must be ISO-8601: ``"YYYY-MM-DD"``. 234 created_before: Only documents created before this date. 235 String input must be ISO-8601: ``"YYYY-MM-DD"``. 236 added_after: Only documents added after this date/time. 237 String input must be ISO-8601: ``"YYYY-MM-DD"`` for date precision or 238 ``"YYYY-MM-DDTHH:MM:SS"`` for datetime precision. 239 added_from: Only documents added on or after this date/time. 240 String input must be ISO-8601: ``"YYYY-MM-DD"`` or ``"YYYY-MM-DDTHH:MM:SS"``. 241 added_before: Only documents added before this date/time. 242 String input must be ISO-8601: ``"YYYY-MM-DD"`` or ``"YYYY-MM-DDTHH:MM:SS"``. 243 added_until: Only documents added on or before this date/time. 244 String input must be ISO-8601: ``"YYYY-MM-DD"`` or ``"YYYY-MM-DDTHH:MM:SS"``. 245 modified_after: Only documents modified after this date/time. 246 String input must be ISO-8601: ``"YYYY-MM-DD"`` or ``"YYYY-MM-DDTHH:MM:SS"``. 247 modified_from: Only documents modified on or after this date/time. 248 String input must be ISO-8601: ``"YYYY-MM-DD"`` or ``"YYYY-MM-DDTHH:MM:SS"``. 249 modified_before: Only documents modified before this date/time. 250 String input must be ISO-8601: ``"YYYY-MM-DD"`` or ``"YYYY-MM-DDTHH:MM:SS"``. 251 modified_until: Only documents modified on or before this date/time. 252 String input must be ISO-8601: ``"YYYY-MM-DD"`` or ``"YYYY-MM-DDTHH:MM:SS"``. 253 checksum: MD5 checksum of the original file (exact match). 254 page_size: Number of results per API page. Default: ``25``. 255 page: Return only this specific page (1-based). 256 ordering: Field name to sort by. 257 descending: When ``True``, reverses the sort direction. 258 max_results: Stop after collecting this many documents. 259 on_page: Callback invoked after each page fetch. 260 261 Returns: 262 :class:`~easypaperless.models.paged_result.PagedResult` of 263 :class:`~easypaperless.models.documents.Document` objects. 264 """ 265 return cast( 266 PagedResult[Document], 267 self._run( 268 self._async_documents.list( 269 search=search, 270 search_mode=search_mode, 271 ids=ids, 272 tags=tags, 273 any_tags=any_tags, 274 exclude_tags=exclude_tags, 275 correspondent=correspondent, 276 any_correspondent=any_correspondent, 277 exclude_correspondents=exclude_correspondents, 278 document_type=document_type, 279 document_type_name_contains=document_type_name_contains, 280 document_type_name_exact=document_type_name_exact, 281 any_document_type=any_document_type, 282 exclude_document_types=exclude_document_types, 283 storage_path=storage_path, 284 any_storage_paths=any_storage_paths, 285 exclude_storage_paths=exclude_storage_paths, 286 owner=owner, 287 exclude_owners=exclude_owners, 288 custom_fields=custom_fields, 289 any_custom_fields=any_custom_fields, 290 exclude_custom_fields=exclude_custom_fields, 291 custom_field_query=custom_field_query, 292 archive_serial_number=archive_serial_number, 293 archive_serial_number_from=archive_serial_number_from, 294 archive_serial_number_till=archive_serial_number_till, 295 created_after=created_after, 296 created_before=created_before, 297 added_after=added_after, 298 added_from=added_from, 299 added_before=added_before, 300 added_until=added_until, 301 modified_after=modified_after, 302 modified_from=modified_from, 303 modified_before=modified_before, 304 modified_until=modified_until, 305 checksum=checksum, 306 page_size=page_size, 307 page=page, 308 ordering=ordering, 309 descending=descending, 310 max_results=max_results, 311 on_page=on_page, 312 ) 313 ), 314 ) 315 316 def update( 317 self, 318 id: int, 319 *, 320 title: str | Unset = UNSET, 321 content: str | Unset = UNSET, 322 created: date | str | None | Unset = UNSET, 323 correspondent: int | str | None | Unset = UNSET, 324 document_type: int | str | None | Unset = UNSET, 325 storage_path: int | str | None | Unset = UNSET, 326 tags: List[int | str] | None | Unset = UNSET, 327 archive_serial_number: int | None | Unset = UNSET, 328 custom_fields: List[dict[str, Any]] | None | Unset = UNSET, 329 owner: int | None | Unset = UNSET, 330 set_permissions: SetPermissions | None | Unset = UNSET, 331 remove_inbox_tags: bool | None | Unset = UNSET, 332 ) -> Document: 333 """Partially update a document (PATCH semantics). 334 335 Args: 336 id: Numeric ID of the document to update. 337 title: New document title. 338 content: OCR text content of the document. 339 created: Creation date as an ISO-8601 string (``"YYYY-MM-DD"``) or a 340 :class:`~datetime.date` object. 341 correspondent: Correspondent to assign, as an ID or name. 342 Pass ``None`` to clear the correspondent. 343 document_type: Document type to assign, as an ID or name. 344 Pass ``None`` to clear the document type. 345 storage_path: Storage path to assign, as an ID or name. 346 Pass ``None`` to clear the storage path. 347 tags: Full replacement list of tags (IDs or names). 348 archive_serial_number: Archive serial number to assign. 349 Pass ``None`` to clear the archive serial number. 350 custom_fields: List of ``{"field": <field_id>, "value": ...}`` dicts. 351 owner: Numeric user ID to assign as document owner. 352 Pass ``None`` to clear the owner. 353 set_permissions: Explicit view/change permission sets. 354 Pass ``None`` to clear all permissions (overwrite with empty). 355 Omit (or pass :data:`~easypaperless.UNSET`) to leave unchanged. 356 remove_inbox_tags: When ``True``, removes all inbox tags from the document. 357 358 Returns: 359 The updated :class:`~easypaperless.models.documents.Document`. 360 """ 361 return cast( 362 Document, 363 self._run( 364 self._async_documents.update( 365 id, 366 title=title, 367 content=content, 368 created=created, 369 correspondent=correspondent, 370 document_type=document_type, 371 storage_path=storage_path, 372 tags=tags, 373 archive_serial_number=archive_serial_number, 374 custom_fields=custom_fields, 375 owner=owner, 376 set_permissions=set_permissions, 377 remove_inbox_tags=remove_inbox_tags, 378 ) 379 ), 380 ) 381 382 def delete(self, id: int) -> None: 383 """Permanently delete a document. 384 385 Args: 386 id: Numeric ID of the document to delete. 387 388 Raises: 389 ~easypaperless.exceptions.NotFoundError: If no document exists 390 with that ID. 391 """ 392 self._run(self._async_documents.delete(id)) 393 394 def download(self, id: int, *, original: bool = False) -> bytes: 395 """Download the binary content of a document. 396 397 Args: 398 id: Numeric ID of the document to download. 399 original: If ``False`` *(default)*, returns the archived PDF. 400 If ``True``, returns the original uploaded file. 401 402 Returns: 403 Raw file bytes. 404 """ 405 return cast(bytes, self._run(self._async_documents.download(id, original=original))) 406 407 def upload( 408 self, 409 file: str | Path, 410 *, 411 title: str | Unset = UNSET, 412 created: date | str | None = None, 413 correspondent: int | str | None | Unset = UNSET, 414 document_type: int | str | None | Unset = UNSET, 415 storage_path: int | str | None | Unset = UNSET, 416 tags: List[int | str] | None = None, 417 archive_serial_number: int | None | Unset = UNSET, 418 custom_fields: List[dict[str, Any]] | None = None, 419 wait: bool = False, 420 poll_interval: float | None = None, 421 poll_timeout: float | None = None, 422 ) -> str | Document: 423 """Upload a document to paperless-ngx. 424 425 Args: 426 file: Path to the file to upload. 427 title: Title to assign to the document. 428 created: Creation date as an ISO-8601 string (``"YYYY-MM-DD"``) or a 429 :class:`~datetime.date` object. 430 correspondent: Correspondent to assign, as an ID or name. 431 document_type: Document type to assign, as an ID or name. 432 storage_path: Storage path to assign, as an ID or name. 433 tags: Tags to assign, as IDs or names. 434 archive_serial_number: Archive serial number to assign. 435 custom_fields: List of ``{"field": <field_id>, "value": ...}`` dicts. 436 wait: If ``False`` *(default)*, returns immediately with the task ID. 437 If ``True``, polls until processing completes. 438 poll_interval: Seconds between task-status checks while waiting for 439 processing to complete (requires ``wait=True``). Overrides the 440 client-level default. When omitted, falls back to the client-level 441 ``poll_interval`` (``2.0`` s unless changed at construction). 442 poll_timeout: Maximum seconds to wait before raising 443 :exc:`~easypaperless.exceptions.TaskTimeoutError` (requires 444 ``wait=True``). Overrides the client-level default. When omitted, 445 falls back to the client-level ``poll_timeout`` (``60.0`` s unless 446 changed at construction). 447 448 Returns: 449 The Celery task ID string when ``wait=False``, or the fully 450 processed :class:`~easypaperless.models.documents.Document` 451 when ``wait=True``. 452 453 Raises: 454 ~easypaperless.exceptions.UploadError: If processing fails. 455 ~easypaperless.exceptions.TaskTimeoutError: If timeout is exceeded. 456 """ 457 return cast( 458 str | Document, 459 self._run( 460 self._async_documents.upload( 461 file, 462 title=title, 463 created=created, 464 correspondent=correspondent, 465 document_type=document_type, 466 storage_path=storage_path, 467 tags=tags, 468 archive_serial_number=archive_serial_number, 469 custom_fields=custom_fields, 470 wait=wait, 471 poll_interval=poll_interval, 472 poll_timeout=poll_timeout, 473 ) 474 ), 475 ) 476 477 def bulk_add_tag(self, document_ids: List[int], tag: int | str) -> None: 478 """Add a tag to multiple documents in a single request. 479 480 Args: 481 document_ids: List of document IDs to tag. 482 tag: Tag to add, as an ID or name. 483 """ 484 self._run(self._async_documents.bulk_add_tag(document_ids, tag)) 485 486 def bulk_remove_tag(self, document_ids: List[int], tag: int | str) -> None: 487 """Remove a tag from multiple documents in a single request. 488 489 Args: 490 document_ids: List of document IDs to un-tag. 491 tag: Tag to remove, as an ID or name. 492 """ 493 self._run(self._async_documents.bulk_remove_tag(document_ids, tag)) 494 495 def bulk_modify_tags( 496 self, 497 document_ids: List[int], 498 *, 499 add_tags: List[int | str] | None = None, 500 remove_tags: List[int | str] | None = None, 501 ) -> None: 502 """Add and/or remove tags on multiple documents atomically. 503 504 Args: 505 document_ids: List of document IDs to modify. 506 add_tags: Tags to add, as IDs or names. 507 remove_tags: Tags to remove, as IDs or names. 508 """ 509 self._run( 510 self._async_documents.bulk_modify_tags( 511 document_ids, add_tags=add_tags, remove_tags=remove_tags 512 ) 513 ) 514 515 def bulk_delete(self, document_ids: List[int]) -> None: 516 """Permanently delete multiple documents in a single request. 517 518 Args: 519 document_ids: List of document IDs to delete. 520 """ 521 self._run(self._async_documents.bulk_delete(document_ids)) 522 523 def bulk_set_correspondent( 524 self, document_ids: List[int], correspondent: int | str | None 525 ) -> None: 526 """Assign a correspondent to multiple documents in a single request. 527 528 Args: 529 document_ids: List of document IDs to modify. 530 correspondent: Correspondent to assign, as an ID or name. 531 Pass ``None`` to clear. 532 """ 533 self._run(self._async_documents.bulk_set_correspondent(document_ids, correspondent)) 534 535 def bulk_set_document_type( 536 self, document_ids: List[int], document_type: int | str | None 537 ) -> None: 538 """Assign a document type to multiple documents in a single request. 539 540 Args: 541 document_ids: List of document IDs to modify. 542 document_type: Document type to assign, as an ID or name. 543 Pass ``None`` to clear. 544 """ 545 self._run(self._async_documents.bulk_set_document_type(document_ids, document_type)) 546 547 def bulk_set_storage_path( 548 self, document_ids: List[int], storage_path: int | str | None 549 ) -> None: 550 """Assign a storage path to multiple documents in a single request. 551 552 Args: 553 document_ids: List of document IDs to modify. 554 storage_path: Storage path to assign, as an ID or name. 555 Pass ``None`` to clear. 556 """ 557 self._run(self._async_documents.bulk_set_storage_path(document_ids, storage_path)) 558 559 def bulk_modify_custom_fields( 560 self, 561 document_ids: List[int], 562 *, 563 add_fields: List[dict[str, Any]] | None = None, 564 remove_fields: List[int] | None = None, 565 ) -> None: 566 """Add and/or remove custom field values on multiple documents. 567 568 Args: 569 document_ids: List of document IDs to modify. 570 add_fields: Custom-field value dicts to add. 571 remove_fields: Custom-field IDs whose values should be removed. 572 """ 573 self._run( 574 self._async_documents.bulk_modify_custom_fields( 575 document_ids, add_fields=add_fields, remove_fields=remove_fields 576 ) 577 ) 578 579 def bulk_set_permissions( 580 self, 581 document_ids: List[int], 582 *, 583 set_permissions: SetPermissions | Unset = UNSET, 584 owner: int | None | Unset = UNSET, 585 merge: bool = False, 586 ) -> None: 587 """Set permissions and/or owner on multiple documents. 588 589 Args: 590 document_ids: List of document IDs to modify. 591 set_permissions: Explicit view/change permission sets. 592 Omit (or pass :data:`~easypaperless.UNSET`) to leave unchanged. 593 owner: Numeric user ID to assign as document owner. 594 Pass ``None`` to clear the owner. 595 Omit (or pass :data:`~easypaperless.UNSET`) to leave unchanged. 596 merge: When ``True``, new permissions are merged with existing ones. 597 """ 598 self._run( 599 self._async_documents.bulk_set_permissions( 600 document_ids, 601 set_permissions=set_permissions, 602 owner=owner, 603 merge=merge, 604 ) 605 )
Sync accessor for documents: client.documents.
99 def get(self, id: int, *, include_metadata: bool = False) -> Document: 100 """Fetch a single document by its ID. 101 102 Args: 103 id: Numeric paperless-ngx document ID. 104 include_metadata: When ``True``, the extended file-level metadata 105 is fetched concurrently and attached to the document. 106 Default: ``False``. 107 108 Returns: 109 The :class:`~easypaperless.models.documents.Document` with the 110 given ID. 111 112 Raises: 113 ~easypaperless.exceptions.NotFoundError: If no document exists 114 with that ID. 115 """ 116 return cast( 117 Document, self._run(self._async_documents.get(id, include_metadata=include_metadata)) 118 )
Fetch a single document by its ID.
Arguments:
- id: Numeric paperless-ngx document ID.
- include_metadata: When
True, the extended file-level metadata is fetched concurrently and attached to the document. Default:False.
Returns:
The
~easypaperless.models.documents.Documentwith the given ID.
Raises:
- ~easypaperless.exceptions.NotFoundError: If no document exists with that ID.
120 def get_metadata(self, id: int) -> DocumentMetadata: 121 """Fetch the extended file-level metadata for a document. 122 123 Args: 124 id: Numeric paperless-ngx document ID. 125 126 Returns: 127 A :class:`~easypaperless.models.documents.DocumentMetadata` instance. 128 129 Raises: 130 ~easypaperless.exceptions.NotFoundError: If no document exists 131 with that ID. 132 """ 133 return cast(DocumentMetadata, self._run(self._async_documents.get_metadata(id)))
Fetch the extended file-level metadata for a document.
Arguments:
- id: Numeric paperless-ngx document ID.
Returns:
A
~easypaperless.models.documents.DocumentMetadatainstance.
Raises:
- ~easypaperless.exceptions.NotFoundError: If no document exists with that ID.
135 def list( 136 self, 137 *, 138 search: str | None = None, 139 search_mode: str = "title_or_content", 140 ids: List[int] | None = None, 141 tags: List[int | str] | None = None, 142 any_tags: List[int | str] | None = None, 143 exclude_tags: List[int | str] | None = None, 144 correspondent: int | str | None | Unset = UNSET, 145 any_correspondent: List[int | str] | None = None, 146 exclude_correspondents: List[int | str] | None = None, 147 document_type: int | str | None | Unset = UNSET, 148 document_type_name_contains: str | None = None, 149 document_type_name_exact: str | None = None, 150 any_document_type: List[int | str] | None = None, 151 exclude_document_types: List[int | str] | None = None, 152 storage_path: int | str | None | Unset = UNSET, 153 any_storage_paths: List[int | str] | None = None, 154 exclude_storage_paths: List[int | str] | None = None, 155 owner: int | None | Unset = UNSET, 156 exclude_owners: List[int] | None = None, 157 custom_fields: List[int | str] | None = None, 158 any_custom_fields: List[int | str] | None = None, 159 exclude_custom_fields: List[int | str] | None = None, 160 custom_field_query: List[Any] | None = None, 161 archive_serial_number: int | None | Unset = UNSET, 162 archive_serial_number_from: int | None = None, 163 archive_serial_number_till: int | None = None, 164 created_after: date | str | None = None, 165 created_before: date | str | None = None, 166 added_after: date | datetime | str | None = None, 167 added_from: date | datetime | str | None = None, 168 added_before: date | datetime | str | None = None, 169 added_until: date | datetime | str | None = None, 170 modified_after: date | datetime | str | None = None, 171 modified_from: date | datetime | str | None = None, 172 modified_before: date | datetime | str | None = None, 173 modified_until: date | datetime | str | None = None, 174 checksum: str | None = None, 175 page_size: int = 25, 176 page: int | None = None, 177 ordering: str | None = None, 178 descending: bool = False, 179 max_results: int | None = None, 180 on_page: Callable[[int, int | None], None] | None = None, 181 ) -> PagedResult[Document]: 182 """Return a filtered list of documents. 183 184 All tag, correspondent, document-type, storage-path, and custom-field 185 parameters accept either integer IDs or string names. 186 187 When ``page`` is ``None`` (the default), all pages are fetched 188 automatically and ``next`` / ``previous`` in the returned 189 :class:`~easypaperless.models.paged_result.PagedResult` are always 190 ``None`` — even if ``max_results`` truncates the final result set. 191 ``count`` always reflects the server total, not the truncated length. 192 When ``page`` is set to a specific integer, only that one page is 193 fetched and ``next`` / ``previous`` contain the raw API values. 194 195 Args: 196 search: Search string. Behaviour depends on ``search_mode``. 197 search_mode: How ``search`` is applied. One of: 198 ``"title_or_content"`` *(default)*, ``"title"``, ``"query"``, 199 ``"original_filename"``. 200 ids: Return only documents whose ID is in this list. 201 tags: Documents must have **all** of these tags (AND semantics). 202 any_tags: Documents must have **at least one** of these tags. 203 exclude_tags: Documents must have **none** of these tags. 204 correspondent: Filter to documents assigned to this correspondent. 205 Pass ``None`` to return only documents with no correspondent set. 206 any_correspondent: Filter to documents assigned to any of these. 207 exclude_correspondents: Exclude documents assigned to any of these. 208 document_type: Filter to documents of exactly this type. 209 Pass ``None`` to return only documents with no document type set. 210 document_type_name_contains: Case-insensitive substring filter on document type name. 211 document_type_name_exact: Case-insensitive exact match on document type name. 212 any_document_type: Filter to documents whose type is any of these. 213 exclude_document_types: Exclude documents whose type is any of these. 214 storage_path: Filter to documents assigned to this storage path. 215 Pass ``None`` to return only documents with no storage path set. 216 any_storage_paths: Filter to documents assigned to any of these paths. 217 exclude_storage_paths: Exclude documents assigned to any of these paths. 218 owner: Filter to documents owned by this user ID. 219 Pass ``None`` to return only documents with no owner set. 220 exclude_owners: Exclude documents owned by any of these user IDs. 221 custom_fields: Documents must have **all** of these custom fields set. 222 any_custom_fields: Documents must have **at least one** of these fields. 223 exclude_custom_fields: Documents must have **none** of these fields. 224 custom_field_query: Filter documents by custom field values using a nested 225 query structure. See the `paperless-ngx API docs 226 <https://docs.paperless-ngx.com/api/#filtering-by-custom-fields>`_ for 227 the query format. 228 archive_serial_number: Filter by exact archive serial number. 229 Pass ``None`` to return only documents with no ASN set. 230 archive_serial_number_from: Filter by ASN >= this value. 231 archive_serial_number_till: Filter by ASN <= this value. 232 created_after: Only documents created after this date. 233 String input must be ISO-8601: ``"YYYY-MM-DD"``. 234 created_before: Only documents created before this date. 235 String input must be ISO-8601: ``"YYYY-MM-DD"``. 236 added_after: Only documents added after this date/time. 237 String input must be ISO-8601: ``"YYYY-MM-DD"`` for date precision or 238 ``"YYYY-MM-DDTHH:MM:SS"`` for datetime precision. 239 added_from: Only documents added on or after this date/time. 240 String input must be ISO-8601: ``"YYYY-MM-DD"`` or ``"YYYY-MM-DDTHH:MM:SS"``. 241 added_before: Only documents added before this date/time. 242 String input must be ISO-8601: ``"YYYY-MM-DD"`` or ``"YYYY-MM-DDTHH:MM:SS"``. 243 added_until: Only documents added on or before this date/time. 244 String input must be ISO-8601: ``"YYYY-MM-DD"`` or ``"YYYY-MM-DDTHH:MM:SS"``. 245 modified_after: Only documents modified after this date/time. 246 String input must be ISO-8601: ``"YYYY-MM-DD"`` or ``"YYYY-MM-DDTHH:MM:SS"``. 247 modified_from: Only documents modified on or after this date/time. 248 String input must be ISO-8601: ``"YYYY-MM-DD"`` or ``"YYYY-MM-DDTHH:MM:SS"``. 249 modified_before: Only documents modified before this date/time. 250 String input must be ISO-8601: ``"YYYY-MM-DD"`` or ``"YYYY-MM-DDTHH:MM:SS"``. 251 modified_until: Only documents modified on or before this date/time. 252 String input must be ISO-8601: ``"YYYY-MM-DD"`` or ``"YYYY-MM-DDTHH:MM:SS"``. 253 checksum: MD5 checksum of the original file (exact match). 254 page_size: Number of results per API page. Default: ``25``. 255 page: Return only this specific page (1-based). 256 ordering: Field name to sort by. 257 descending: When ``True``, reverses the sort direction. 258 max_results: Stop after collecting this many documents. 259 on_page: Callback invoked after each page fetch. 260 261 Returns: 262 :class:`~easypaperless.models.paged_result.PagedResult` of 263 :class:`~easypaperless.models.documents.Document` objects. 264 """ 265 return cast( 266 PagedResult[Document], 267 self._run( 268 self._async_documents.list( 269 search=search, 270 search_mode=search_mode, 271 ids=ids, 272 tags=tags, 273 any_tags=any_tags, 274 exclude_tags=exclude_tags, 275 correspondent=correspondent, 276 any_correspondent=any_correspondent, 277 exclude_correspondents=exclude_correspondents, 278 document_type=document_type, 279 document_type_name_contains=document_type_name_contains, 280 document_type_name_exact=document_type_name_exact, 281 any_document_type=any_document_type, 282 exclude_document_types=exclude_document_types, 283 storage_path=storage_path, 284 any_storage_paths=any_storage_paths, 285 exclude_storage_paths=exclude_storage_paths, 286 owner=owner, 287 exclude_owners=exclude_owners, 288 custom_fields=custom_fields, 289 any_custom_fields=any_custom_fields, 290 exclude_custom_fields=exclude_custom_fields, 291 custom_field_query=custom_field_query, 292 archive_serial_number=archive_serial_number, 293 archive_serial_number_from=archive_serial_number_from, 294 archive_serial_number_till=archive_serial_number_till, 295 created_after=created_after, 296 created_before=created_before, 297 added_after=added_after, 298 added_from=added_from, 299 added_before=added_before, 300 added_until=added_until, 301 modified_after=modified_after, 302 modified_from=modified_from, 303 modified_before=modified_before, 304 modified_until=modified_until, 305 checksum=checksum, 306 page_size=page_size, 307 page=page, 308 ordering=ordering, 309 descending=descending, 310 max_results=max_results, 311 on_page=on_page, 312 ) 313 ), 314 )
Return a filtered list of documents.
All tag, correspondent, document-type, storage-path, and custom-field parameters accept either integer IDs or string names.
When page is None (the default), all pages are fetched
automatically and next / previous in the returned
~easypaperless.models.paged_result.PagedResult are always
None — even if max_results truncates the final result set.
count always reflects the server total, not the truncated length.
When page is set to a specific integer, only that one page is
fetched and next / previous contain the raw API values.
Arguments:
- search: Search string. Behaviour depends on
search_mode. - search_mode: How
searchis applied. One of:"title_or_content"(default),"title","query","original_filename". - ids: Return only documents whose ID is in this list.
- tags: Documents must have all of these tags (AND semantics).
- any_tags: Documents must have at least one of these tags.
- exclude_tags: Documents must have none of these tags.
- correspondent: Filter to documents assigned to this correspondent.
Pass
Noneto return only documents with no correspondent set. - any_correspondent: Filter to documents assigned to any of these.
- exclude_correspondents: Exclude documents assigned to any of these.
- document_type: Filter to documents of exactly this type.
Pass
Noneto return only documents with no document type set. - document_type_name_contains: Case-insensitive substring filter on document type name.
- document_type_name_exact: Case-insensitive exact match on document type name.
- any_document_type: Filter to documents whose type is any of these.
- exclude_document_types: Exclude documents whose type is any of these.
- storage_path: Filter to documents assigned to this storage path.
Pass
Noneto return only documents with no storage path set. - any_storage_paths: Filter to documents assigned to any of these paths.
- exclude_storage_paths: Exclude documents assigned to any of these paths.
- owner: Filter to documents owned by this user ID.
Pass
Noneto return only documents with no owner set. - exclude_owners: Exclude documents owned by any of these user IDs.
- custom_fields: Documents must have all of these custom fields set.
- any_custom_fields: Documents must have at least one of these fields.
- exclude_custom_fields: Documents must have none of these fields.
- custom_field_query: Filter documents by custom field values using a nested query structure. See the paperless-ngx API docs for the query format.
- archive_serial_number: Filter by exact archive serial number.
Pass
Noneto return only documents with no ASN set. - archive_serial_number_from: Filter by ASN >= this value.
- archive_serial_number_till: Filter by ASN <= this value.
- created_after: Only documents created after this date.
String input must be ISO-8601:
"YYYY-MM-DD". - created_before: Only documents created before this date.
String input must be ISO-8601:
"YYYY-MM-DD". - added_after: Only documents added after this date/time.
String input must be ISO-8601:
"YYYY-MM-DD"for date precision or"YYYY-MM-DDTHH:MM:SS"for datetime precision. - added_from: Only documents added on or after this date/time.
String input must be ISO-8601:
"YYYY-MM-DD"or"YYYY-MM-DDTHH:MM:SS". - added_before: Only documents added before this date/time.
String input must be ISO-8601:
"YYYY-MM-DD"or"YYYY-MM-DDTHH:MM:SS". - added_until: Only documents added on or before this date/time.
String input must be ISO-8601:
"YYYY-MM-DD"or"YYYY-MM-DDTHH:MM:SS". - modified_after: Only documents modified after this date/time.
String input must be ISO-8601:
"YYYY-MM-DD"or"YYYY-MM-DDTHH:MM:SS". - modified_from: Only documents modified on or after this date/time.
String input must be ISO-8601:
"YYYY-MM-DD"or"YYYY-MM-DDTHH:MM:SS". - modified_before: Only documents modified before this date/time.
String input must be ISO-8601:
"YYYY-MM-DD"or"YYYY-MM-DDTHH:MM:SS". - modified_until: Only documents modified on or before this date/time.
String input must be ISO-8601:
"YYYY-MM-DD"or"YYYY-MM-DDTHH:MM:SS". - checksum: MD5 checksum of the original file (exact match).
- page_size: Number of results per API page. Default:
25. - page: Return only this specific page (1-based).
- ordering: Field name to sort by.
- descending: When
True, reverses the sort direction. - max_results: Stop after collecting this many documents.
- on_page: Callback invoked after each page fetch.
Returns:
~easypaperless.models.paged_result.PagedResultof~easypaperless.models.documents.Documentobjects.
316 def update( 317 self, 318 id: int, 319 *, 320 title: str | Unset = UNSET, 321 content: str | Unset = UNSET, 322 created: date | str | None | Unset = UNSET, 323 correspondent: int | str | None | Unset = UNSET, 324 document_type: int | str | None | Unset = UNSET, 325 storage_path: int | str | None | Unset = UNSET, 326 tags: List[int | str] | None | Unset = UNSET, 327 archive_serial_number: int | None | Unset = UNSET, 328 custom_fields: List[dict[str, Any]] | None | Unset = UNSET, 329 owner: int | None | Unset = UNSET, 330 set_permissions: SetPermissions | None | Unset = UNSET, 331 remove_inbox_tags: bool | None | Unset = UNSET, 332 ) -> Document: 333 """Partially update a document (PATCH semantics). 334 335 Args: 336 id: Numeric ID of the document to update. 337 title: New document title. 338 content: OCR text content of the document. 339 created: Creation date as an ISO-8601 string (``"YYYY-MM-DD"``) or a 340 :class:`~datetime.date` object. 341 correspondent: Correspondent to assign, as an ID or name. 342 Pass ``None`` to clear the correspondent. 343 document_type: Document type to assign, as an ID or name. 344 Pass ``None`` to clear the document type. 345 storage_path: Storage path to assign, as an ID or name. 346 Pass ``None`` to clear the storage path. 347 tags: Full replacement list of tags (IDs or names). 348 archive_serial_number: Archive serial number to assign. 349 Pass ``None`` to clear the archive serial number. 350 custom_fields: List of ``{"field": <field_id>, "value": ...}`` dicts. 351 owner: Numeric user ID to assign as document owner. 352 Pass ``None`` to clear the owner. 353 set_permissions: Explicit view/change permission sets. 354 Pass ``None`` to clear all permissions (overwrite with empty). 355 Omit (or pass :data:`~easypaperless.UNSET`) to leave unchanged. 356 remove_inbox_tags: When ``True``, removes all inbox tags from the document. 357 358 Returns: 359 The updated :class:`~easypaperless.models.documents.Document`. 360 """ 361 return cast( 362 Document, 363 self._run( 364 self._async_documents.update( 365 id, 366 title=title, 367 content=content, 368 created=created, 369 correspondent=correspondent, 370 document_type=document_type, 371 storage_path=storage_path, 372 tags=tags, 373 archive_serial_number=archive_serial_number, 374 custom_fields=custom_fields, 375 owner=owner, 376 set_permissions=set_permissions, 377 remove_inbox_tags=remove_inbox_tags, 378 ) 379 ), 380 )
Partially update a document (PATCH semantics).
Arguments:
- id: Numeric ID of the document to update.
- title: New document title.
- content: OCR text content of the document.
- created: Creation date as an ISO-8601 string (
"YYYY-MM-DD") or a~datetime.dateobject. - correspondent: Correspondent to assign, as an ID or name.
Pass
Noneto clear the correspondent. - document_type: Document type to assign, as an ID or name.
Pass
Noneto clear the document type. - storage_path: Storage path to assign, as an ID or name.
Pass
Noneto clear the storage path. - tags: Full replacement list of tags (IDs or names).
- archive_serial_number: Archive serial number to assign.
Pass
Noneto clear the archive serial number. - custom_fields: List of
{"field": <field_id>, "value": ...}dicts. - owner: Numeric user ID to assign as document owner.
Pass
Noneto clear the owner. - set_permissions: Explicit view/change permission sets.
Pass
Noneto clear all permissions (overwrite with empty). Omit (or pass~easypaperless.UNSET) to leave unchanged. - remove_inbox_tags: When
True, removes all inbox tags from the document.
Returns:
The updated
~easypaperless.models.documents.Document.
382 def delete(self, id: int) -> None: 383 """Permanently delete a document. 384 385 Args: 386 id: Numeric ID of the document to delete. 387 388 Raises: 389 ~easypaperless.exceptions.NotFoundError: If no document exists 390 with that ID. 391 """ 392 self._run(self._async_documents.delete(id))
Permanently delete a document.
Arguments:
- id: Numeric ID of the document to delete.
Raises:
- ~easypaperless.exceptions.NotFoundError: If no document exists with that ID.
394 def download(self, id: int, *, original: bool = False) -> bytes: 395 """Download the binary content of a document. 396 397 Args: 398 id: Numeric ID of the document to download. 399 original: If ``False`` *(default)*, returns the archived PDF. 400 If ``True``, returns the original uploaded file. 401 402 Returns: 403 Raw file bytes. 404 """ 405 return cast(bytes, self._run(self._async_documents.download(id, original=original)))
Download the binary content of a document.
Arguments:
- id: Numeric ID of the document to download.
- original: If
False(default), returns the archived PDF. IfTrue, returns the original uploaded file.
Returns:
Raw file bytes.
407 def upload( 408 self, 409 file: str | Path, 410 *, 411 title: str | Unset = UNSET, 412 created: date | str | None = None, 413 correspondent: int | str | None | Unset = UNSET, 414 document_type: int | str | None | Unset = UNSET, 415 storage_path: int | str | None | Unset = UNSET, 416 tags: List[int | str] | None = None, 417 archive_serial_number: int | None | Unset = UNSET, 418 custom_fields: List[dict[str, Any]] | None = None, 419 wait: bool = False, 420 poll_interval: float | None = None, 421 poll_timeout: float | None = None, 422 ) -> str | Document: 423 """Upload a document to paperless-ngx. 424 425 Args: 426 file: Path to the file to upload. 427 title: Title to assign to the document. 428 created: Creation date as an ISO-8601 string (``"YYYY-MM-DD"``) or a 429 :class:`~datetime.date` object. 430 correspondent: Correspondent to assign, as an ID or name. 431 document_type: Document type to assign, as an ID or name. 432 storage_path: Storage path to assign, as an ID or name. 433 tags: Tags to assign, as IDs or names. 434 archive_serial_number: Archive serial number to assign. 435 custom_fields: List of ``{"field": <field_id>, "value": ...}`` dicts. 436 wait: If ``False`` *(default)*, returns immediately with the task ID. 437 If ``True``, polls until processing completes. 438 poll_interval: Seconds between task-status checks while waiting for 439 processing to complete (requires ``wait=True``). Overrides the 440 client-level default. When omitted, falls back to the client-level 441 ``poll_interval`` (``2.0`` s unless changed at construction). 442 poll_timeout: Maximum seconds to wait before raising 443 :exc:`~easypaperless.exceptions.TaskTimeoutError` (requires 444 ``wait=True``). Overrides the client-level default. When omitted, 445 falls back to the client-level ``poll_timeout`` (``60.0`` s unless 446 changed at construction). 447 448 Returns: 449 The Celery task ID string when ``wait=False``, or the fully 450 processed :class:`~easypaperless.models.documents.Document` 451 when ``wait=True``. 452 453 Raises: 454 ~easypaperless.exceptions.UploadError: If processing fails. 455 ~easypaperless.exceptions.TaskTimeoutError: If timeout is exceeded. 456 """ 457 return cast( 458 str | Document, 459 self._run( 460 self._async_documents.upload( 461 file, 462 title=title, 463 created=created, 464 correspondent=correspondent, 465 document_type=document_type, 466 storage_path=storage_path, 467 tags=tags, 468 archive_serial_number=archive_serial_number, 469 custom_fields=custom_fields, 470 wait=wait, 471 poll_interval=poll_interval, 472 poll_timeout=poll_timeout, 473 ) 474 ), 475 )
Upload a document to paperless-ngx.
Arguments:
- file: Path to the file to upload.
- title: Title to assign to the document.
- created: Creation date as an ISO-8601 string (
"YYYY-MM-DD") or a~datetime.dateobject. - correspondent: Correspondent to assign, as an ID or name.
- document_type: Document type to assign, as an ID or name.
- storage_path: Storage path to assign, as an ID or name.
- tags: Tags to assign, as IDs or names.
- archive_serial_number: Archive serial number to assign.
- custom_fields: List of
{"field": <field_id>, "value": ...}dicts. - wait: If
False(default), returns immediately with the task ID. IfTrue, polls until processing completes. - poll_interval: Seconds between task-status checks while waiting for
processing to complete (requires
wait=True). Overrides the client-level default. When omitted, falls back to the client-levelpoll_interval(2.0s unless changed at construction). - poll_timeout: Maximum seconds to wait before raising
~easypaperless.exceptions.TaskTimeoutError(requireswait=True). Overrides the client-level default. When omitted, falls back to the client-levelpoll_timeout(60.0s unless changed at construction).
Returns:
The Celery task ID string when
wait=False, or the fully processed~easypaperless.models.documents.Documentwhenwait=True.
Raises:
- ~easypaperless.exceptions.UploadError: If processing fails.
- ~easypaperless.exceptions.TaskTimeoutError: If timeout is exceeded.
477 def bulk_add_tag(self, document_ids: List[int], tag: int | str) -> None: 478 """Add a tag to multiple documents in a single request. 479 480 Args: 481 document_ids: List of document IDs to tag. 482 tag: Tag to add, as an ID or name. 483 """ 484 self._run(self._async_documents.bulk_add_tag(document_ids, tag))
Add a tag to multiple documents in a single request.
Arguments:
- document_ids: List of document IDs to tag.
- tag: Tag to add, as an ID or name.
486 def bulk_remove_tag(self, document_ids: List[int], tag: int | str) -> None: 487 """Remove a tag from multiple documents in a single request. 488 489 Args: 490 document_ids: List of document IDs to un-tag. 491 tag: Tag to remove, as an ID or name. 492 """ 493 self._run(self._async_documents.bulk_remove_tag(document_ids, tag))
Remove a tag from multiple documents in a single request.
Arguments:
- document_ids: List of document IDs to un-tag.
- tag: Tag to remove, as an ID or name.
515 def bulk_delete(self, document_ids: List[int]) -> None: 516 """Permanently delete multiple documents in a single request. 517 518 Args: 519 document_ids: List of document IDs to delete. 520 """ 521 self._run(self._async_documents.bulk_delete(document_ids))
Permanently delete multiple documents in a single request.
Arguments:
- document_ids: List of document IDs to delete.
523 def bulk_set_correspondent( 524 self, document_ids: List[int], correspondent: int | str | None 525 ) -> None: 526 """Assign a correspondent to multiple documents in a single request. 527 528 Args: 529 document_ids: List of document IDs to modify. 530 correspondent: Correspondent to assign, as an ID or name. 531 Pass ``None`` to clear. 532 """ 533 self._run(self._async_documents.bulk_set_correspondent(document_ids, correspondent))
Assign a correspondent to multiple documents in a single request.
Arguments:
- document_ids: List of document IDs to modify.
- correspondent: Correspondent to assign, as an ID or name.
Pass
Noneto clear.
535 def bulk_set_document_type( 536 self, document_ids: List[int], document_type: int | str | None 537 ) -> None: 538 """Assign a document type to multiple documents in a single request. 539 540 Args: 541 document_ids: List of document IDs to modify. 542 document_type: Document type to assign, as an ID or name. 543 Pass ``None`` to clear. 544 """ 545 self._run(self._async_documents.bulk_set_document_type(document_ids, document_type))
Assign a document type to multiple documents in a single request.
Arguments:
- document_ids: List of document IDs to modify.
- document_type: Document type to assign, as an ID or name.
Pass
Noneto clear.
547 def bulk_set_storage_path( 548 self, document_ids: List[int], storage_path: int | str | None 549 ) -> None: 550 """Assign a storage path to multiple documents in a single request. 551 552 Args: 553 document_ids: List of document IDs to modify. 554 storage_path: Storage path to assign, as an ID or name. 555 Pass ``None`` to clear. 556 """ 557 self._run(self._async_documents.bulk_set_storage_path(document_ids, storage_path))
Assign a storage path to multiple documents in a single request.
Arguments:
- document_ids: List of document IDs to modify.
- storage_path: Storage path to assign, as an ID or name.
Pass
Noneto clear.
559 def bulk_modify_custom_fields( 560 self, 561 document_ids: List[int], 562 *, 563 add_fields: List[dict[str, Any]] | None = None, 564 remove_fields: List[int] | None = None, 565 ) -> None: 566 """Add and/or remove custom field values on multiple documents. 567 568 Args: 569 document_ids: List of document IDs to modify. 570 add_fields: Custom-field value dicts to add. 571 remove_fields: Custom-field IDs whose values should be removed. 572 """ 573 self._run( 574 self._async_documents.bulk_modify_custom_fields( 575 document_ids, add_fields=add_fields, remove_fields=remove_fields 576 ) 577 )
Add and/or remove custom field values on multiple documents.
Arguments:
- document_ids: List of document IDs to modify.
- add_fields: Custom-field value dicts to add.
- remove_fields: Custom-field IDs whose values should be removed.
579 def bulk_set_permissions( 580 self, 581 document_ids: List[int], 582 *, 583 set_permissions: SetPermissions | Unset = UNSET, 584 owner: int | None | Unset = UNSET, 585 merge: bool = False, 586 ) -> None: 587 """Set permissions and/or owner on multiple documents. 588 589 Args: 590 document_ids: List of document IDs to modify. 591 set_permissions: Explicit view/change permission sets. 592 Omit (or pass :data:`~easypaperless.UNSET`) to leave unchanged. 593 owner: Numeric user ID to assign as document owner. 594 Pass ``None`` to clear the owner. 595 Omit (or pass :data:`~easypaperless.UNSET`) to leave unchanged. 596 merge: When ``True``, new permissions are merged with existing ones. 597 """ 598 self._run( 599 self._async_documents.bulk_set_permissions( 600 document_ids, 601 set_permissions=set_permissions, 602 owner=owner, 603 merge=merge, 604 ) 605 )
Set permissions and/or owner on multiple documents.
Arguments:
- document_ids: List of document IDs to modify.
- set_permissions: Explicit view/change permission sets.
Omit (or pass
~easypaperless.UNSET) to leave unchanged. - owner: Numeric user ID to assign as document owner.
Pass
Noneto clear the owner. Omit (or pass~easypaperless.UNSET) to leave unchanged. - merge: When
True, new permissions are merged with existing ones.
20class SyncNotesResource: 21 """Sync accessor for document notes: ``client.documents.notes``.""" 22 23 def __init__(self, async_notes: NotesResource, run: Any) -> None: 24 self._async_notes = async_notes 25 self._run = run 26 27 def list( 28 self, 29 document_id: int, 30 *, 31 page: int | None = None, 32 page_size: int | None = None, 33 ) -> PagedResult[DocumentNote]: 34 """Fetch notes attached to a document. 35 36 When ``page`` is ``None`` (the default), all pages are fetched 37 automatically and ``next`` / ``previous`` in the returned 38 :class:`~easypaperless.models.paged_result.PagedResult` are always 39 ``None``. When ``page`` is set to a specific integer, only that one 40 page is fetched and ``next`` / ``previous`` contain the raw API values. 41 42 Args: 43 document_id: Numeric ID of the document whose notes to retrieve. 44 page: Return only this specific page (1-based). 45 page_size: Number of results per page. 46 47 Returns: 48 :class:`~easypaperless.models.paged_result.PagedResult` of 49 :class:`~easypaperless.models.documents.DocumentNote` objects, 50 ordered by creation time. 51 52 Raises: 53 ~easypaperless.exceptions.NotFoundError: If no document exists 54 with that ID. 55 """ 56 return cast( 57 PagedResult[DocumentNote], 58 self._run(self._async_notes.list(document_id, page=page, page_size=page_size)), 59 ) 60 61 def create(self, document_id: int, *, note: str) -> DocumentNote: 62 """Create a new note on a document. 63 64 Args: 65 document_id: Numeric ID of the document to annotate. 66 note: Text content of the note. 67 68 Returns: 69 The newly created :class:`~easypaperless.models.documents.DocumentNote`. 70 71 Raises: 72 ~easypaperless.exceptions.NotFoundError: If no document exists 73 with that ID. 74 """ 75 return cast(DocumentNote, self._run(self._async_notes.create(document_id, note=note))) 76 77 def delete(self, document_id: int, note_id: int) -> None: 78 """Delete a note from a document. 79 80 Args: 81 document_id: Numeric ID of the document that owns the note. 82 note_id: Numeric ID of the note to delete. 83 84 Raises: 85 ~easypaperless.exceptions.NotFoundError: If no document or note 86 exists with the given IDs. 87 """ 88 self._run(self._async_notes.delete(document_id, note_id))
Sync accessor for document notes: client.documents.notes.
27 def list( 28 self, 29 document_id: int, 30 *, 31 page: int | None = None, 32 page_size: int | None = None, 33 ) -> PagedResult[DocumentNote]: 34 """Fetch notes attached to a document. 35 36 When ``page`` is ``None`` (the default), all pages are fetched 37 automatically and ``next`` / ``previous`` in the returned 38 :class:`~easypaperless.models.paged_result.PagedResult` are always 39 ``None``. When ``page`` is set to a specific integer, only that one 40 page is fetched and ``next`` / ``previous`` contain the raw API values. 41 42 Args: 43 document_id: Numeric ID of the document whose notes to retrieve. 44 page: Return only this specific page (1-based). 45 page_size: Number of results per page. 46 47 Returns: 48 :class:`~easypaperless.models.paged_result.PagedResult` of 49 :class:`~easypaperless.models.documents.DocumentNote` objects, 50 ordered by creation time. 51 52 Raises: 53 ~easypaperless.exceptions.NotFoundError: If no document exists 54 with that ID. 55 """ 56 return cast( 57 PagedResult[DocumentNote], 58 self._run(self._async_notes.list(document_id, page=page, page_size=page_size)), 59 )
Fetch notes attached to a document.
When page is None (the default), all pages are fetched
automatically and next / previous in the returned
~easypaperless.models.paged_result.PagedResult are always
None. When page is set to a specific integer, only that one
page is fetched and next / previous contain the raw API values.
Arguments:
- document_id: Numeric ID of the document whose notes to retrieve.
- page: Return only this specific page (1-based).
- page_size: Number of results per page.
Returns:
~easypaperless.models.paged_result.PagedResultof~easypaperless.models.documents.DocumentNoteobjects, ordered by creation time.
Raises:
- ~easypaperless.exceptions.NotFoundError: If no document exists with that ID.
61 def create(self, document_id: int, *, note: str) -> DocumentNote: 62 """Create a new note on a document. 63 64 Args: 65 document_id: Numeric ID of the document to annotate. 66 note: Text content of the note. 67 68 Returns: 69 The newly created :class:`~easypaperless.models.documents.DocumentNote`. 70 71 Raises: 72 ~easypaperless.exceptions.NotFoundError: If no document exists 73 with that ID. 74 """ 75 return cast(DocumentNote, self._run(self._async_notes.create(document_id, note=note)))
Create a new note on a document.
Arguments:
- document_id: Numeric ID of the document to annotate.
- note: Text content of the note.
Returns:
The newly created
~easypaperless.models.documents.DocumentNote.
Raises:
- ~easypaperless.exceptions.NotFoundError: If no document exists with that ID.
77 def delete(self, document_id: int, note_id: int) -> None: 78 """Delete a note from a document. 79 80 Args: 81 document_id: Numeric ID of the document that owns the note. 82 note_id: Numeric ID of the note to delete. 83 84 Raises: 85 ~easypaperless.exceptions.NotFoundError: If no document or note 86 exists with the given IDs. 87 """ 88 self._run(self._async_notes.delete(document_id, note_id))
Delete a note from a document.
Arguments:
- document_id: Numeric ID of the document that owns the note.
- note_id: Numeric ID of the note to delete.
Raises:
- ~easypaperless.exceptions.NotFoundError: If no document or note exists with the given IDs.
18class SyncStoragePathsResource: 19 """Sync accessor for storage paths: ``client.storage_paths``.""" 20 21 def __init__(self, async_storage_paths: StoragePathsResource, run: Any) -> None: 22 self._async_storage_paths = async_storage_paths 23 self._run = run 24 25 def list( 26 self, 27 *, 28 ids: List[int] | None = None, 29 name_contains: str | None = None, 30 name_exact: str | None = None, 31 path_contains: str | None = None, 32 path_exact: str | None = None, 33 page: int | None = None, 34 page_size: int | None = None, 35 ordering: str | None = None, 36 descending: bool = False, 37 ) -> PagedResult[StoragePath]: 38 """Return storage paths defined in paperless-ngx. 39 40 When ``page`` is ``None`` (the default), all pages are fetched 41 automatically and ``next`` / ``previous`` in the result are always 42 ``None``. When ``page`` is set, only that page is fetched and 43 ``next`` / ``previous`` reflect the raw API values. 44 45 Args: 46 ids: Return only storage paths whose ID is in this list. 47 name_contains: Case-insensitive substring filter on name. 48 name_exact: Case-insensitive exact match on name. 49 path_contains: Case-insensitive substring filter on path template. 50 path_exact: Case-insensitive exact match on path template. 51 page: Return only this specific page (1-based). 52 page_size: Number of results per page. 53 ordering: Field to sort by. 54 descending: When ``True``, reverses the sort direction. 55 56 Returns: 57 :class:`~easypaperless.models.paged_result.PagedResult` of 58 :class:`~easypaperless.models.storage_paths.StoragePath` objects. 59 """ 60 return cast( 61 PagedResult[StoragePath], 62 self._run( 63 self._async_storage_paths.list( 64 ids=ids, 65 name_contains=name_contains, 66 name_exact=name_exact, 67 path_contains=path_contains, 68 path_exact=path_exact, 69 page=page, 70 page_size=page_size, 71 ordering=ordering, 72 descending=descending, 73 ) 74 ), 75 ) 76 77 def get(self, id: int) -> StoragePath: 78 """Fetch a single storage path by its ID. 79 80 Args: 81 id: Numeric storage-path ID. 82 83 Returns: 84 The :class:`~easypaperless.models.storage_paths.StoragePath` with the given ID. 85 86 Raises: 87 ~easypaperless.exceptions.NotFoundError: If no storage path exists with that ID. 88 """ 89 return cast(StoragePath, self._run(self._async_storage_paths.get(id))) 90 91 def create( 92 self, 93 *, 94 name: str, 95 path: str | Unset = UNSET, 96 match: str | Unset = UNSET, 97 matching_algorithm: MatchingAlgorithm | Unset = UNSET, 98 is_insensitive: bool = True, 99 owner: int | None | Unset = UNSET, 100 set_permissions: SetPermissions | None | Unset = UNSET, 101 ) -> StoragePath: 102 """Create a new storage path. 103 104 Args: 105 name: Storage-path name. Must be unique. 106 path: Template string for the archive file path. 107 match: Auto-matching pattern. 108 matching_algorithm: Controls how ``match`` is applied. 109 E.g. ``matching_algorithm=MatchingAlgorithm.REGEX`` for 110 regular-expression matching. 111 is_insensitive: When ``True``, ``match`` is case-insensitive. 112 Defaults to ``True``, matching the paperless-ngx API default. 113 owner: Numeric user ID to assign as owner. 114 set_permissions: Explicit view/change permission sets. 115 Pass ``None`` to create with empty permissions. 116 117 Returns: 118 The newly created :class:`~easypaperless.models.storage_paths.StoragePath`. 119 """ 120 return cast( 121 StoragePath, 122 self._run( 123 self._async_storage_paths.create( 124 name=name, 125 path=path, 126 match=match, 127 matching_algorithm=matching_algorithm, 128 is_insensitive=is_insensitive, 129 owner=owner, 130 set_permissions=set_permissions, 131 ) 132 ), 133 ) 134 135 def update( 136 self, 137 id: int, 138 *, 139 name: str | Unset = UNSET, 140 path: str | Unset = UNSET, 141 match: str | Unset = UNSET, 142 matching_algorithm: MatchingAlgorithm | Unset = UNSET, 143 is_insensitive: bool | Unset = UNSET, 144 owner: int | None | Unset = UNSET, 145 set_permissions: SetPermissions | None | Unset = UNSET, 146 ) -> StoragePath: 147 """Partially update a storage path (PATCH semantics). 148 149 Args: 150 id: Numeric ID of the storage path to update. 151 name: Storage-path name. 152 path: Template string for the archive file path. 153 match: Auto-matching pattern. 154 matching_algorithm: Controls how ``match`` is applied. 155 E.g. ``matching_algorithm=MatchingAlgorithm.REGEX`` for 156 regular-expression matching. 157 is_insensitive: When ``True``, ``match`` is case-insensitive. 158 owner: Numeric user ID to assign as owner. 159 Pass ``None`` to clear the owner. 160 Omit (or pass :data:`~easypaperless.UNSET`) to leave unchanged. 161 set_permissions: Explicit view/change permission sets. 162 Pass ``None`` to clear all permissions (overwrite with empty). 163 Omit (or pass :data:`~easypaperless.UNSET`) to leave unchanged. 164 165 Returns: 166 The updated :class:`~easypaperless.models.storage_paths.StoragePath`. 167 """ 168 return cast( 169 StoragePath, 170 self._run( 171 self._async_storage_paths.update( 172 id, 173 name=name, 174 path=path, 175 match=match, 176 matching_algorithm=matching_algorithm, 177 is_insensitive=is_insensitive, 178 owner=owner, 179 set_permissions=set_permissions, 180 ) 181 ), 182 ) 183 184 def delete(self, id: int) -> None: 185 """Delete a storage path. 186 187 Args: 188 id: Numeric ID of the storage path to delete. 189 190 Raises: 191 ~easypaperless.exceptions.NotFoundError: If no storage path exists with that ID. 192 """ 193 self._run(self._async_storage_paths.delete(id)) 194 195 def bulk_delete(self, ids: List[int]) -> None: 196 """Permanently delete multiple storage paths in a single request. 197 198 Args: 199 ids: List of storage path IDs to delete. 200 """ 201 self._run(self._async_storage_paths.bulk_delete(ids)) 202 203 def bulk_set_permissions( 204 self, 205 ids: List[int], 206 *, 207 set_permissions: SetPermissions | Unset = UNSET, 208 owner: int | None | Unset = UNSET, 209 merge: bool = False, 210 ) -> None: 211 """Set permissions and/or owner on multiple storage paths. 212 213 Args: 214 ids: List of storage path IDs to modify. 215 set_permissions: Explicit view/change permission sets. 216 Omit (or pass :data:`~easypaperless.UNSET`) to leave unchanged. 217 owner: Numeric user ID to assign as owner. 218 Pass ``None`` to clear the owner. 219 Omit (or pass :data:`~easypaperless.UNSET`) to leave unchanged. 220 merge: When ``True``, new permissions are merged with existing ones. 221 """ 222 self._run( 223 self._async_storage_paths.bulk_set_permissions( 224 ids, set_permissions=set_permissions, owner=owner, merge=merge 225 ) 226 )
Sync accessor for storage paths: client.storage_paths.
25 def list( 26 self, 27 *, 28 ids: List[int] | None = None, 29 name_contains: str | None = None, 30 name_exact: str | None = None, 31 path_contains: str | None = None, 32 path_exact: str | None = None, 33 page: int | None = None, 34 page_size: int | None = None, 35 ordering: str | None = None, 36 descending: bool = False, 37 ) -> PagedResult[StoragePath]: 38 """Return storage paths defined in paperless-ngx. 39 40 When ``page`` is ``None`` (the default), all pages are fetched 41 automatically and ``next`` / ``previous`` in the result are always 42 ``None``. When ``page`` is set, only that page is fetched and 43 ``next`` / ``previous`` reflect the raw API values. 44 45 Args: 46 ids: Return only storage paths whose ID is in this list. 47 name_contains: Case-insensitive substring filter on name. 48 name_exact: Case-insensitive exact match on name. 49 path_contains: Case-insensitive substring filter on path template. 50 path_exact: Case-insensitive exact match on path template. 51 page: Return only this specific page (1-based). 52 page_size: Number of results per page. 53 ordering: Field to sort by. 54 descending: When ``True``, reverses the sort direction. 55 56 Returns: 57 :class:`~easypaperless.models.paged_result.PagedResult` of 58 :class:`~easypaperless.models.storage_paths.StoragePath` objects. 59 """ 60 return cast( 61 PagedResult[StoragePath], 62 self._run( 63 self._async_storage_paths.list( 64 ids=ids, 65 name_contains=name_contains, 66 name_exact=name_exact, 67 path_contains=path_contains, 68 path_exact=path_exact, 69 page=page, 70 page_size=page_size, 71 ordering=ordering, 72 descending=descending, 73 ) 74 ), 75 )
Return storage paths defined in paperless-ngx.
When page is None (the default), all pages are fetched
automatically and next / previous in the result are always
None. When page is set, only that page is fetched and
next / previous reflect the raw API values.
Arguments:
- ids: Return only storage paths whose ID is in this list.
- name_contains: Case-insensitive substring filter on name.
- name_exact: Case-insensitive exact match on name.
- path_contains: Case-insensitive substring filter on path template.
- path_exact: Case-insensitive exact match on path template.
- page: Return only this specific page (1-based).
- page_size: Number of results per page.
- ordering: Field to sort by.
- descending: When
True, reverses the sort direction.
Returns:
~easypaperless.models.paged_result.PagedResultof~easypaperless.models.storage_paths.StoragePathobjects.
77 def get(self, id: int) -> StoragePath: 78 """Fetch a single storage path by its ID. 79 80 Args: 81 id: Numeric storage-path ID. 82 83 Returns: 84 The :class:`~easypaperless.models.storage_paths.StoragePath` with the given ID. 85 86 Raises: 87 ~easypaperless.exceptions.NotFoundError: If no storage path exists with that ID. 88 """ 89 return cast(StoragePath, self._run(self._async_storage_paths.get(id)))
Fetch a single storage path by its ID.
Arguments:
- id: Numeric storage-path ID.
Returns:
The
~easypaperless.models.storage_paths.StoragePathwith the given ID.
Raises:
- ~easypaperless.exceptions.NotFoundError: If no storage path exists with that ID.
91 def create( 92 self, 93 *, 94 name: str, 95 path: str | Unset = UNSET, 96 match: str | Unset = UNSET, 97 matching_algorithm: MatchingAlgorithm | Unset = UNSET, 98 is_insensitive: bool = True, 99 owner: int | None | Unset = UNSET, 100 set_permissions: SetPermissions | None | Unset = UNSET, 101 ) -> StoragePath: 102 """Create a new storage path. 103 104 Args: 105 name: Storage-path name. Must be unique. 106 path: Template string for the archive file path. 107 match: Auto-matching pattern. 108 matching_algorithm: Controls how ``match`` is applied. 109 E.g. ``matching_algorithm=MatchingAlgorithm.REGEX`` for 110 regular-expression matching. 111 is_insensitive: When ``True``, ``match`` is case-insensitive. 112 Defaults to ``True``, matching the paperless-ngx API default. 113 owner: Numeric user ID to assign as owner. 114 set_permissions: Explicit view/change permission sets. 115 Pass ``None`` to create with empty permissions. 116 117 Returns: 118 The newly created :class:`~easypaperless.models.storage_paths.StoragePath`. 119 """ 120 return cast( 121 StoragePath, 122 self._run( 123 self._async_storage_paths.create( 124 name=name, 125 path=path, 126 match=match, 127 matching_algorithm=matching_algorithm, 128 is_insensitive=is_insensitive, 129 owner=owner, 130 set_permissions=set_permissions, 131 ) 132 ), 133 )
Create a new storage path.
Arguments:
- name: Storage-path name. Must be unique.
- path: Template string for the archive file path.
- match: Auto-matching pattern.
- matching_algorithm: Controls how
matchis applied. E.g.matching_algorithm=MatchingAlgorithm.REGEXfor regular-expression matching. - is_insensitive: When
True,matchis case-insensitive. Defaults toTrue, matching the paperless-ngx API default. - owner: Numeric user ID to assign as owner.
- set_permissions: Explicit view/change permission sets.
Pass
Noneto create with empty permissions.
Returns:
The newly created
~easypaperless.models.storage_paths.StoragePath.
135 def update( 136 self, 137 id: int, 138 *, 139 name: str | Unset = UNSET, 140 path: str | Unset = UNSET, 141 match: str | Unset = UNSET, 142 matching_algorithm: MatchingAlgorithm | Unset = UNSET, 143 is_insensitive: bool | Unset = UNSET, 144 owner: int | None | Unset = UNSET, 145 set_permissions: SetPermissions | None | Unset = UNSET, 146 ) -> StoragePath: 147 """Partially update a storage path (PATCH semantics). 148 149 Args: 150 id: Numeric ID of the storage path to update. 151 name: Storage-path name. 152 path: Template string for the archive file path. 153 match: Auto-matching pattern. 154 matching_algorithm: Controls how ``match`` is applied. 155 E.g. ``matching_algorithm=MatchingAlgorithm.REGEX`` for 156 regular-expression matching. 157 is_insensitive: When ``True``, ``match`` is case-insensitive. 158 owner: Numeric user ID to assign as owner. 159 Pass ``None`` to clear the owner. 160 Omit (or pass :data:`~easypaperless.UNSET`) to leave unchanged. 161 set_permissions: Explicit view/change permission sets. 162 Pass ``None`` to clear all permissions (overwrite with empty). 163 Omit (or pass :data:`~easypaperless.UNSET`) to leave unchanged. 164 165 Returns: 166 The updated :class:`~easypaperless.models.storage_paths.StoragePath`. 167 """ 168 return cast( 169 StoragePath, 170 self._run( 171 self._async_storage_paths.update( 172 id, 173 name=name, 174 path=path, 175 match=match, 176 matching_algorithm=matching_algorithm, 177 is_insensitive=is_insensitive, 178 owner=owner, 179 set_permissions=set_permissions, 180 ) 181 ), 182 )
Partially update a storage path (PATCH semantics).
Arguments:
- id: Numeric ID of the storage path to update.
- name: Storage-path name.
- path: Template string for the archive file path.
- match: Auto-matching pattern.
- matching_algorithm: Controls how
matchis applied. E.g.matching_algorithm=MatchingAlgorithm.REGEXfor regular-expression matching. - is_insensitive: When
True,matchis case-insensitive. - owner: Numeric user ID to assign as owner.
Pass
Noneto clear the owner. Omit (or pass~easypaperless.UNSET) to leave unchanged. - set_permissions: Explicit view/change permission sets.
Pass
Noneto clear all permissions (overwrite with empty). Omit (or pass~easypaperless.UNSET) to leave unchanged.
Returns:
The updated
~easypaperless.models.storage_paths.StoragePath.
184 def delete(self, id: int) -> None: 185 """Delete a storage path. 186 187 Args: 188 id: Numeric ID of the storage path to delete. 189 190 Raises: 191 ~easypaperless.exceptions.NotFoundError: If no storage path exists with that ID. 192 """ 193 self._run(self._async_storage_paths.delete(id))
Delete a storage path.
Arguments:
- id: Numeric ID of the storage path to delete.
Raises:
- ~easypaperless.exceptions.NotFoundError: If no storage path exists with that ID.
195 def bulk_delete(self, ids: List[int]) -> None: 196 """Permanently delete multiple storage paths in a single request. 197 198 Args: 199 ids: List of storage path IDs to delete. 200 """ 201 self._run(self._async_storage_paths.bulk_delete(ids))
Permanently delete multiple storage paths in a single request.
Arguments:
- ids: List of storage path IDs to delete.
203 def bulk_set_permissions( 204 self, 205 ids: List[int], 206 *, 207 set_permissions: SetPermissions | Unset = UNSET, 208 owner: int | None | Unset = UNSET, 209 merge: bool = False, 210 ) -> None: 211 """Set permissions and/or owner on multiple storage paths. 212 213 Args: 214 ids: List of storage path IDs to modify. 215 set_permissions: Explicit view/change permission sets. 216 Omit (or pass :data:`~easypaperless.UNSET`) to leave unchanged. 217 owner: Numeric user ID to assign as owner. 218 Pass ``None`` to clear the owner. 219 Omit (or pass :data:`~easypaperless.UNSET`) to leave unchanged. 220 merge: When ``True``, new permissions are merged with existing ones. 221 """ 222 self._run( 223 self._async_storage_paths.bulk_set_permissions( 224 ids, set_permissions=set_permissions, owner=owner, merge=merge 225 ) 226 )
Set permissions and/or owner on multiple storage paths.
Arguments:
- ids: List of storage path IDs to modify.
- set_permissions: Explicit view/change permission sets.
Omit (or pass
~easypaperless.UNSET) to leave unchanged. - owner: Numeric user ID to assign as owner.
Pass
Noneto clear the owner. Omit (or pass~easypaperless.UNSET) to leave unchanged. - merge: When
True, new permissions are merged with existing ones.
18class SyncTagsResource: 19 """Sync accessor for tags: ``client.tags``.""" 20 21 def __init__(self, async_tags: TagsResource, run: Any) -> None: 22 self._async_tags = async_tags 23 self._run = run 24 25 def list( 26 self, 27 *, 28 ids: List[int] | None = None, 29 name_contains: str | None = None, 30 name_exact: str | None = None, 31 page: int | None = None, 32 page_size: int | None = None, 33 ordering: str | None = None, 34 descending: bool = False, 35 ) -> PagedResult[Tag]: 36 """Return tags defined in paperless-ngx. 37 38 When ``page`` is ``None`` (the default), all pages are fetched 39 automatically and ``next`` / ``previous`` in the result are always 40 ``None``. When ``page`` is set, only that page is fetched and 41 ``next`` / ``previous`` reflect the raw API values. 42 43 Args: 44 ids: Return only tags whose ID is in this list. 45 name_contains: Case-insensitive substring filter on tag name. 46 name_exact: Case-insensitive exact match on tag name. 47 page: Return only this specific page (1-based). 48 page_size: Number of results per page. 49 ordering: Field to sort by. 50 descending: When ``True``, reverses the sort direction. 51 52 Returns: 53 :class:`~easypaperless.models.paged_result.PagedResult` of 54 :class:`~easypaperless.models.tags.Tag` objects. 55 """ 56 return cast( 57 PagedResult[Tag], 58 self._run( 59 self._async_tags.list( 60 ids=ids, 61 name_contains=name_contains, 62 name_exact=name_exact, 63 page=page, 64 page_size=page_size, 65 ordering=ordering, 66 descending=descending, 67 ) 68 ), 69 ) 70 71 def get(self, id: int) -> Tag: 72 """Fetch a single tag by its ID. 73 74 Args: 75 id: Numeric tag ID. 76 77 Returns: 78 The :class:`~easypaperless.models.tags.Tag` with the given ID. 79 80 Raises: 81 ~easypaperless.exceptions.NotFoundError: If no tag exists with 82 that ID. 83 """ 84 return cast(Tag, self._run(self._async_tags.get(id))) 85 86 def create( 87 self, 88 *, 89 name: str, 90 color: str | Unset = UNSET, 91 is_inbox_tag: bool | Unset = UNSET, 92 match: str | Unset = UNSET, 93 matching_algorithm: MatchingAlgorithm | Unset = UNSET, 94 is_insensitive: bool = True, 95 parent: int | None | Unset = UNSET, 96 owner: int | None | Unset = UNSET, 97 set_permissions: SetPermissions | None | Unset = UNSET, 98 ) -> Tag: 99 """Create a new tag. 100 101 Args: 102 name: Tag name. Must be unique. 103 color: Background colour as a CSS hex string. 104 is_inbox_tag: When ``True``, newly ingested documents get this tag. 105 match: Auto-matching pattern. 106 matching_algorithm: Controls how ``match`` is applied. 107 E.g. ``matching_algorithm=MatchingAlgorithm.REGEX`` for 108 regular-expression matching. 109 is_insensitive: When ``True``, ``match`` is case-insensitive. 110 Defaults to ``True``, matching the paperless-ngx API default. 111 parent: ID of parent tag for hierarchical trees. 112 owner: Numeric user ID to assign as owner. 113 set_permissions: Explicit view/change permission sets. 114 Pass ``None`` to create with empty permissions. 115 116 Returns: 117 The newly created :class:`~easypaperless.models.tags.Tag`. 118 """ 119 return cast( 120 Tag, 121 self._run( 122 self._async_tags.create( 123 name=name, 124 color=color, 125 is_inbox_tag=is_inbox_tag, 126 match=match, 127 matching_algorithm=matching_algorithm, 128 is_insensitive=is_insensitive, 129 parent=parent, 130 owner=owner, 131 set_permissions=set_permissions, 132 ) 133 ), 134 ) 135 136 def update( 137 self, 138 id: int, 139 *, 140 name: str | Unset = UNSET, 141 color: str | Unset = UNSET, 142 is_inbox_tag: bool | Unset = UNSET, 143 match: str | Unset = UNSET, 144 matching_algorithm: MatchingAlgorithm | Unset = UNSET, 145 is_insensitive: bool | Unset = UNSET, 146 parent: int | None | Unset = UNSET, 147 owner: int | None | Unset = UNSET, 148 set_permissions: SetPermissions | None | Unset = UNSET, 149 ) -> Tag: 150 """Partially update a tag (PATCH semantics). 151 152 Args: 153 id: Numeric ID of the tag to update. 154 name: Tag name. 155 color: Background colour as a CSS hex string. 156 is_inbox_tag: When ``True``, newly ingested documents get this tag. 157 match: Auto-matching pattern. 158 matching_algorithm: Controls how ``match`` is applied. 159 E.g. ``matching_algorithm=MatchingAlgorithm.REGEX`` for 160 regular-expression matching. 161 is_insensitive: When ``True``, ``match`` is case-insensitive. 162 parent: ID of parent tag. 163 Pass ``None`` to clear (make root tag). 164 Omit (or pass :data:`~easypaperless.UNSET`) to leave unchanged. 165 owner: Numeric user ID to assign as owner. 166 Pass ``None`` to clear the owner. 167 Omit (or pass :data:`~easypaperless.UNSET`) to leave unchanged. 168 set_permissions: Explicit view/change permission sets. 169 Pass ``None`` to clear all permissions (overwrite with empty). 170 Omit (or pass :data:`~easypaperless.UNSET`) to leave unchanged. 171 172 Returns: 173 The updated :class:`~easypaperless.models.tags.Tag`. 174 """ 175 return cast( 176 Tag, 177 self._run( 178 self._async_tags.update( 179 id, 180 name=name, 181 color=color, 182 is_inbox_tag=is_inbox_tag, 183 match=match, 184 matching_algorithm=matching_algorithm, 185 is_insensitive=is_insensitive, 186 parent=parent, 187 owner=owner, 188 set_permissions=set_permissions, 189 ) 190 ), 191 ) 192 193 def delete(self, id: int) -> None: 194 """Delete a tag. 195 196 Args: 197 id: Numeric ID of the tag to delete. 198 199 Raises: 200 ~easypaperless.exceptions.NotFoundError: If no tag exists with 201 that ID. 202 """ 203 self._run(self._async_tags.delete(id)) 204 205 def bulk_delete(self, ids: List[int]) -> None: 206 """Permanently delete multiple tags in a single request. 207 208 Args: 209 ids: List of tag IDs to delete. 210 """ 211 self._run(self._async_tags.bulk_delete(ids)) 212 213 def bulk_set_permissions( 214 self, 215 ids: List[int], 216 *, 217 set_permissions: SetPermissions | Unset = UNSET, 218 owner: int | None | Unset = UNSET, 219 merge: bool = False, 220 ) -> None: 221 """Set permissions and/or owner on multiple tags. 222 223 Args: 224 ids: List of tag IDs to modify. 225 set_permissions: Explicit view/change permission sets. 226 Omit (or pass :data:`~easypaperless.UNSET`) to leave unchanged. 227 owner: Numeric user ID to assign as owner. 228 Pass ``None`` to clear the owner. 229 Omit (or pass :data:`~easypaperless.UNSET`) to leave unchanged. 230 merge: When ``True``, new permissions are merged with existing ones. 231 """ 232 self._run( 233 self._async_tags.bulk_set_permissions( 234 ids, set_permissions=set_permissions, owner=owner, merge=merge 235 ) 236 )
Sync accessor for tags: client.tags.
25 def list( 26 self, 27 *, 28 ids: List[int] | None = None, 29 name_contains: str | None = None, 30 name_exact: str | None = None, 31 page: int | None = None, 32 page_size: int | None = None, 33 ordering: str | None = None, 34 descending: bool = False, 35 ) -> PagedResult[Tag]: 36 """Return tags defined in paperless-ngx. 37 38 When ``page`` is ``None`` (the default), all pages are fetched 39 automatically and ``next`` / ``previous`` in the result are always 40 ``None``. When ``page`` is set, only that page is fetched and 41 ``next`` / ``previous`` reflect the raw API values. 42 43 Args: 44 ids: Return only tags whose ID is in this list. 45 name_contains: Case-insensitive substring filter on tag name. 46 name_exact: Case-insensitive exact match on tag name. 47 page: Return only this specific page (1-based). 48 page_size: Number of results per page. 49 ordering: Field to sort by. 50 descending: When ``True``, reverses the sort direction. 51 52 Returns: 53 :class:`~easypaperless.models.paged_result.PagedResult` of 54 :class:`~easypaperless.models.tags.Tag` objects. 55 """ 56 return cast( 57 PagedResult[Tag], 58 self._run( 59 self._async_tags.list( 60 ids=ids, 61 name_contains=name_contains, 62 name_exact=name_exact, 63 page=page, 64 page_size=page_size, 65 ordering=ordering, 66 descending=descending, 67 ) 68 ), 69 )
Return tags defined in paperless-ngx.
When page is None (the default), all pages are fetched
automatically and next / previous in the result are always
None. When page is set, only that page is fetched and
next / previous reflect the raw API values.
Arguments:
- ids: Return only tags whose ID is in this list.
- name_contains: Case-insensitive substring filter on tag name.
- name_exact: Case-insensitive exact match on tag name.
- page: Return only this specific page (1-based).
- page_size: Number of results per page.
- ordering: Field to sort by.
- descending: When
True, reverses the sort direction.
Returns:
~easypaperless.models.paged_result.PagedResultof~easypaperless.models.tags.Tagobjects.
71 def get(self, id: int) -> Tag: 72 """Fetch a single tag by its ID. 73 74 Args: 75 id: Numeric tag ID. 76 77 Returns: 78 The :class:`~easypaperless.models.tags.Tag` with the given ID. 79 80 Raises: 81 ~easypaperless.exceptions.NotFoundError: If no tag exists with 82 that ID. 83 """ 84 return cast(Tag, self._run(self._async_tags.get(id)))
Fetch a single tag by its ID.
Arguments:
- id: Numeric tag ID.
Returns:
The
~easypaperless.models.tags.Tagwith the given ID.
Raises:
- ~easypaperless.exceptions.NotFoundError: If no tag exists with that ID.
86 def create( 87 self, 88 *, 89 name: str, 90 color: str | Unset = UNSET, 91 is_inbox_tag: bool | Unset = UNSET, 92 match: str | Unset = UNSET, 93 matching_algorithm: MatchingAlgorithm | Unset = UNSET, 94 is_insensitive: bool = True, 95 parent: int | None | Unset = UNSET, 96 owner: int | None | Unset = UNSET, 97 set_permissions: SetPermissions | None | Unset = UNSET, 98 ) -> Tag: 99 """Create a new tag. 100 101 Args: 102 name: Tag name. Must be unique. 103 color: Background colour as a CSS hex string. 104 is_inbox_tag: When ``True``, newly ingested documents get this tag. 105 match: Auto-matching pattern. 106 matching_algorithm: Controls how ``match`` is applied. 107 E.g. ``matching_algorithm=MatchingAlgorithm.REGEX`` for 108 regular-expression matching. 109 is_insensitive: When ``True``, ``match`` is case-insensitive. 110 Defaults to ``True``, matching the paperless-ngx API default. 111 parent: ID of parent tag for hierarchical trees. 112 owner: Numeric user ID to assign as owner. 113 set_permissions: Explicit view/change permission sets. 114 Pass ``None`` to create with empty permissions. 115 116 Returns: 117 The newly created :class:`~easypaperless.models.tags.Tag`. 118 """ 119 return cast( 120 Tag, 121 self._run( 122 self._async_tags.create( 123 name=name, 124 color=color, 125 is_inbox_tag=is_inbox_tag, 126 match=match, 127 matching_algorithm=matching_algorithm, 128 is_insensitive=is_insensitive, 129 parent=parent, 130 owner=owner, 131 set_permissions=set_permissions, 132 ) 133 ), 134 )
Create a new tag.
Arguments:
- name: Tag name. Must be unique.
- color: Background colour as a CSS hex string.
- is_inbox_tag: When
True, newly ingested documents get this tag. - match: Auto-matching pattern.
- matching_algorithm: Controls how
matchis applied. E.g.matching_algorithm=MatchingAlgorithm.REGEXfor regular-expression matching. - is_insensitive: When
True,matchis case-insensitive. Defaults toTrue, matching the paperless-ngx API default. - parent: ID of parent tag for hierarchical trees.
- owner: Numeric user ID to assign as owner.
- set_permissions: Explicit view/change permission sets.
Pass
Noneto create with empty permissions.
Returns:
The newly created
~easypaperless.models.tags.Tag.
136 def update( 137 self, 138 id: int, 139 *, 140 name: str | Unset = UNSET, 141 color: str | Unset = UNSET, 142 is_inbox_tag: bool | Unset = UNSET, 143 match: str | Unset = UNSET, 144 matching_algorithm: MatchingAlgorithm | Unset = UNSET, 145 is_insensitive: bool | Unset = UNSET, 146 parent: int | None | Unset = UNSET, 147 owner: int | None | Unset = UNSET, 148 set_permissions: SetPermissions | None | Unset = UNSET, 149 ) -> Tag: 150 """Partially update a tag (PATCH semantics). 151 152 Args: 153 id: Numeric ID of the tag to update. 154 name: Tag name. 155 color: Background colour as a CSS hex string. 156 is_inbox_tag: When ``True``, newly ingested documents get this tag. 157 match: Auto-matching pattern. 158 matching_algorithm: Controls how ``match`` is applied. 159 E.g. ``matching_algorithm=MatchingAlgorithm.REGEX`` for 160 regular-expression matching. 161 is_insensitive: When ``True``, ``match`` is case-insensitive. 162 parent: ID of parent tag. 163 Pass ``None`` to clear (make root tag). 164 Omit (or pass :data:`~easypaperless.UNSET`) to leave unchanged. 165 owner: Numeric user ID to assign as owner. 166 Pass ``None`` to clear the owner. 167 Omit (or pass :data:`~easypaperless.UNSET`) to leave unchanged. 168 set_permissions: Explicit view/change permission sets. 169 Pass ``None`` to clear all permissions (overwrite with empty). 170 Omit (or pass :data:`~easypaperless.UNSET`) to leave unchanged. 171 172 Returns: 173 The updated :class:`~easypaperless.models.tags.Tag`. 174 """ 175 return cast( 176 Tag, 177 self._run( 178 self._async_tags.update( 179 id, 180 name=name, 181 color=color, 182 is_inbox_tag=is_inbox_tag, 183 match=match, 184 matching_algorithm=matching_algorithm, 185 is_insensitive=is_insensitive, 186 parent=parent, 187 owner=owner, 188 set_permissions=set_permissions, 189 ) 190 ), 191 )
Partially update a tag (PATCH semantics).
Arguments:
- id: Numeric ID of the tag to update.
- name: Tag name.
- color: Background colour as a CSS hex string.
- is_inbox_tag: When
True, newly ingested documents get this tag. - match: Auto-matching pattern.
- matching_algorithm: Controls how
matchis applied. E.g.matching_algorithm=MatchingAlgorithm.REGEXfor regular-expression matching. - is_insensitive: When
True,matchis case-insensitive. - parent: ID of parent tag.
Pass
Noneto clear (make root tag). Omit (or pass~easypaperless.UNSET) to leave unchanged. - owner: Numeric user ID to assign as owner.
Pass
Noneto clear the owner. Omit (or pass~easypaperless.UNSET) to leave unchanged. - set_permissions: Explicit view/change permission sets.
Pass
Noneto clear all permissions (overwrite with empty). Omit (or pass~easypaperless.UNSET) to leave unchanged.
Returns:
The updated
~easypaperless.models.tags.Tag.
193 def delete(self, id: int) -> None: 194 """Delete a tag. 195 196 Args: 197 id: Numeric ID of the tag to delete. 198 199 Raises: 200 ~easypaperless.exceptions.NotFoundError: If no tag exists with 201 that ID. 202 """ 203 self._run(self._async_tags.delete(id))
Delete a tag.
Arguments:
- id: Numeric ID of the tag to delete.
Raises:
- ~easypaperless.exceptions.NotFoundError: If no tag exists with that ID.
205 def bulk_delete(self, ids: List[int]) -> None: 206 """Permanently delete multiple tags in a single request. 207 208 Args: 209 ids: List of tag IDs to delete. 210 """ 211 self._run(self._async_tags.bulk_delete(ids))
Permanently delete multiple tags in a single request.
Arguments:
- ids: List of tag IDs to delete.
213 def bulk_set_permissions( 214 self, 215 ids: List[int], 216 *, 217 set_permissions: SetPermissions | Unset = UNSET, 218 owner: int | None | Unset = UNSET, 219 merge: bool = False, 220 ) -> None: 221 """Set permissions and/or owner on multiple tags. 222 223 Args: 224 ids: List of tag IDs to modify. 225 set_permissions: Explicit view/change permission sets. 226 Omit (or pass :data:`~easypaperless.UNSET`) to leave unchanged. 227 owner: Numeric user ID to assign as owner. 228 Pass ``None`` to clear the owner. 229 Omit (or pass :data:`~easypaperless.UNSET`) to leave unchanged. 230 merge: When ``True``, new permissions are merged with existing ones. 231 """ 232 self._run( 233 self._async_tags.bulk_set_permissions( 234 ids, set_permissions=set_permissions, owner=owner, merge=merge 235 ) 236 )
Set permissions and/or owner on multiple tags.
Arguments:
- ids: List of tag IDs to modify.
- set_permissions: Explicit view/change permission sets.
Omit (or pass
~easypaperless.UNSET) to leave unchanged. - owner: Numeric user ID to assign as owner.
Pass
Noneto clear the owner. Omit (or pass~easypaperless.UNSET) to leave unchanged. - merge: When
True, new permissions are merged with existing ones.