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 24from easypaperless._internal.resources.correspondents import CorrespondentsResource 25from easypaperless._internal.resources.custom_fields import CustomFieldsResource 26from easypaperless._internal.resources.document_types import DocumentTypesResource 27from easypaperless._internal.resources.documents import DocumentsResource, NotesResource 28from easypaperless._internal.resources.storage_paths import StoragePathsResource 29from easypaperless._internal.resources.tags import TagsResource 30from easypaperless._internal.resources.trash import TrashResource 31from easypaperless._internal.resources.users import UsersResource 32from easypaperless._internal.sync_resources.correspondents import SyncCorrespondentsResource 33from easypaperless._internal.sync_resources.custom_fields import SyncCustomFieldsResource 34from easypaperless._internal.sync_resources.document_types import SyncDocumentTypesResource 35from easypaperless._internal.sync_resources.documents import ( 36 SyncDocumentsResource, 37 SyncNotesResource, 38) 39from easypaperless._internal.sync_resources.storage_paths import SyncStoragePathsResource 40from easypaperless._internal.sync_resources.tags import SyncTagsResource 41from easypaperless._internal.sync_resources.trash import SyncTrashResource 42from easypaperless._internal.sync_resources.users import SyncUsersResource 43 44__all__ = [ 45 "CorrespondentsResource", 46 "CustomFieldsResource", 47 "DocumentTypesResource", 48 "DocumentsResource", 49 "NotesResource", 50 "StoragePathsResource", 51 "TagsResource", 52 "SyncCorrespondentsResource", 53 "SyncCustomFieldsResource", 54 "SyncDocumentTypesResource", 55 "SyncDocumentsResource", 56 "SyncNotesResource", 57 "SyncStoragePathsResource", 58 "SyncTagsResource", 59 "UsersResource", 60 "SyncUsersResource", 61 "TrashResource", 62 "SyncTrashResource", 63]
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.
176class DocumentsResource: 177 """Accessor for documents: ``client.documents``.""" 178 179 def __init__(self, core: _ClientCore) -> None: 180 self._core = core 181 self.notes = NotesResource(core) 182 183 async def history( 184 self, 185 document_id: int, 186 *, 187 page: int | None = None, 188 page_size: int | None = None, 189 ) -> PagedResult[AuditLogEntry]: 190 """Fetch the audit log for a document. 191 192 The paperless-ngx ``/api/documents/{id}/history/`` endpoint returns a 193 plain JSON array rather than a paginated envelope. This method wraps 194 the response into a :class:`~easypaperless.models.paged_result.PagedResult` 195 so callers always receive a consistent return type. 196 197 Args: 198 document_id: Numeric ID of the document whose history to retrieve. 199 page: Forwarded to the API as a query parameter when provided. 200 Effect depends on the paperless-ngx version; the server may 201 ignore this parameter. 202 page_size: Forwarded to the API as a query parameter when provided. 203 204 Returns: 205 :class:`~easypaperless.models.paged_result.PagedResult` of 206 :class:`~easypaperless.models.documents.AuditLogEntry` objects, 207 ordered by timestamp descending. 208 209 Raises: 210 ~easypaperless.exceptions.NotFoundError: If no document exists 211 with that ID. 212 """ 213 logger.info("Fetching history for document id=%d", document_id) 214 path = f"/documents/{document_id}/history/" 215 params: dict[str, Any] = {} 216 if page is not None: 217 params["page"] = page 218 if page_size is not None: 219 params["page_size"] = page_size 220 221 resp = await self._core._session.get(path, params=params or None) 222 data = resp.json() 223 224 if isinstance(data, list): 225 entries = [AuditLogEntry.model_validate(item) for item in data] 226 entry_ids: list[int] = [e.id for e in entries] 227 return PagedResult( 228 count=len(entries), 229 next=None, 230 previous=None, 231 all=entry_ids if entry_ids else None, 232 results=entries, 233 ) 234 235 # Forward-compatible: handle a paginated envelope if the API ever adds one. 236 items: list[Any] = list(data.get("results", [])) 237 count: int = data.get("count", 0) 238 all_ids: list[int] | None = data.get("all") 239 return PagedResult( 240 count=count, 241 next=data.get("next"), 242 previous=data.get("previous"), 243 all=all_ids, 244 results=[AuditLogEntry.model_validate(item) for item in items], 245 ) 246 247 @staticmethod 248 def _format_date_value(value: date | datetime | str) -> str: 249 if isinstance(value, datetime): 250 return value.isoformat() 251 if isinstance(value, date): 252 return value.isoformat() 253 return value 254 255 @staticmethod 256 def _is_datetime(value: date | datetime | str) -> bool: 257 if isinstance(value, datetime): 258 return True 259 if isinstance(value, str): 260 return bool(_DATETIME_STR_RE.match(value)) 261 return False 262 263 async def get(self, id: int, *, include_metadata: bool = False) -> Document: 264 """Fetch a single document by its ID. 265 266 Args: 267 id: Numeric paperless-ngx document ID. 268 include_metadata: When ``True``, the extended file-level metadata 269 is fetched concurrently and attached to the document. 270 Default: ``False``. 271 272 Returns: 273 The :class:`~easypaperless.models.documents.Document` with the 274 given ID. 275 276 Raises: 277 ~easypaperless.exceptions.NotFoundError: If no document exists 278 with that ID. 279 """ 280 logger.info("Getting document id=%d", id) 281 if include_metadata: 282 doc_resp, meta_resp = await asyncio.gather( 283 self._core._session.get(f"/documents/{id}/"), 284 self._core._session.get(f"/documents/{id}/metadata/"), 285 ) 286 data = doc_resp.json() 287 data["metadata"] = meta_resp.json() 288 else: 289 resp = await self._core._session.get(f"/documents/{id}/") 290 data = resp.json() 291 return Document.model_validate(data) 292 293 async def get_metadata(self, id: int) -> DocumentMetadata: 294 """Fetch the extended file-level metadata for a document. 295 296 Args: 297 id: Numeric paperless-ngx document ID. 298 299 Returns: 300 A :class:`~easypaperless.models.documents.DocumentMetadata` instance. 301 302 Raises: 303 ~easypaperless.exceptions.NotFoundError: If no document exists 304 with that ID. 305 """ 306 logger.info("Getting metadata for document id=%d", id) 307 resp = await self._core._session.get(f"/documents/{id}/metadata/") 308 return DocumentMetadata.model_validate(resp.json()) 309 310 async def list( 311 self, 312 *, 313 search: str | None = None, 314 search_mode: str = "title_or_content", 315 ids: List[int] | None = None, 316 tags: List[int | str] | None = None, 317 any_tags: List[int | str] | None = None, 318 exclude_tags: List[int | str] | None = None, 319 correspondent: int | str | None | Unset = UNSET, 320 any_correspondent: List[int | str] | None = None, 321 exclude_correspondents: List[int | str] | None = None, 322 document_type: int | str | None | Unset = UNSET, 323 document_type_name_contains: str | None = None, 324 document_type_name_exact: str | None = None, 325 any_document_type: List[int | str] | None = None, 326 exclude_document_types: List[int | str] | None = None, 327 storage_path: int | str | None | Unset = UNSET, 328 any_storage_paths: List[int | str] | None = None, 329 exclude_storage_paths: List[int | str] | None = None, 330 owner: int | None | Unset = UNSET, 331 exclude_owners: List[int] | None = None, 332 custom_fields: List[int | str] | None = None, 333 any_custom_fields: List[int | str] | None = None, 334 exclude_custom_fields: List[int | str] | None = None, 335 custom_field_query: List[Any] | None = None, 336 archive_serial_number: int | None | Unset = UNSET, 337 archive_serial_number_from: int | None = None, 338 archive_serial_number_till: int | None = None, 339 created_after: date | str | None = None, 340 created_before: date | str | None = None, 341 added_after: date | datetime | str | None = None, 342 added_from: date | datetime | str | None = None, 343 added_before: date | datetime | str | None = None, 344 added_until: date | datetime | str | None = None, 345 modified_after: date | datetime | str | None = None, 346 modified_from: date | datetime | str | None = None, 347 modified_before: date | datetime | str | None = None, 348 modified_until: date | datetime | str | None = None, 349 checksum: str | None = None, 350 page_size: int = 25, 351 page: int | None = None, 352 ordering: str | None = None, 353 descending: bool = False, 354 max_results: int | None = None, 355 on_page: Callable[[int, int | None], None] | None = None, 356 ) -> PagedResult[Document]: 357 """Return a filtered list of documents. 358 359 All tag, correspondent, document-type, storage-path, and custom-field 360 parameters accept either integer IDs or string names. 361 362 When ``page`` is ``None`` (the default), all pages are fetched 363 automatically and ``next`` / ``previous`` in the returned 364 :class:`~easypaperless.models.paged_result.PagedResult` are always 365 ``None`` — even if ``max_results`` truncates the final result set. 366 ``count`` always reflects the server total, not the truncated length. 367 When ``page`` is set to a specific integer, only that one page is 368 fetched and ``next`` / ``previous`` contain the raw API values. 369 370 Args: 371 search: Search string. Behaviour depends on ``search_mode``. 372 search_mode: How ``search`` is applied. One of: 373 ``"title_or_content"`` *(default)*, ``"title"``, ``"query"``, 374 ``"original_filename"``. 375 ids: Return only documents whose ID is in this list. 376 tags: Documents must have **all** of these tags (AND semantics). 377 any_tags: Documents must have **at least one** of these tags. 378 exclude_tags: Documents must have **none** of these tags. 379 correspondent: Filter to documents assigned to this correspondent. 380 Pass ``None`` to return only documents with no correspondent set. 381 any_correspondent: Filter to documents assigned to any of these. 382 exclude_correspondents: Exclude documents assigned to any of these. 383 document_type: Filter to documents of exactly this type. 384 Pass ``None`` to return only documents with no document type set. 385 document_type_name_contains: Case-insensitive substring filter on document type name. 386 document_type_name_exact: Case-insensitive exact match on document type name. 387 any_document_type: Filter to documents whose type is any of these. 388 exclude_document_types: Exclude documents whose type is any of these. 389 storage_path: Filter to documents assigned to this storage path. 390 Pass ``None`` to return only documents with no storage path set. 391 any_storage_paths: Filter to documents assigned to any of these paths. 392 exclude_storage_paths: Exclude documents assigned to any of these paths. 393 owner: Filter to documents owned by this user ID. 394 Pass ``None`` to return only documents with no owner set. 395 exclude_owners: Exclude documents owned by any of these user IDs. 396 custom_fields: Documents must have **all** of these custom fields set. 397 any_custom_fields: Documents must have **at least one** of these fields. 398 exclude_custom_fields: Documents must have **none** of these fields. 399 custom_field_query: Filter documents by custom field values using a nested 400 query structure. See the `paperless-ngx API docs 401 <https://docs.paperless-ngx.com/api/#filtering-by-custom-fields>`_ for 402 the query format. 403 archive_serial_number: Filter by exact archive serial number. 404 Pass ``None`` to return only documents with no ASN set. 405 archive_serial_number_from: Filter by ASN >= this value. 406 archive_serial_number_till: Filter by ASN <= this value. 407 created_after: Only documents created after this date. 408 String input must be ISO-8601: ``"YYYY-MM-DD"``. 409 created_before: Only documents created before this date. 410 String input must be ISO-8601: ``"YYYY-MM-DD"``. 411 added_after: Only documents added after this date/time. 412 String input must be ISO-8601: ``"YYYY-MM-DD"`` for date precision or 413 ``"YYYY-MM-DDTHH:MM:SS"`` for datetime precision. 414 added_from: Only documents added on or after this date/time. 415 String input must be ISO-8601: ``"YYYY-MM-DD"`` or ``"YYYY-MM-DDTHH:MM:SS"``. 416 added_before: Only documents added before this date/time. 417 String input must be ISO-8601: ``"YYYY-MM-DD"`` or ``"YYYY-MM-DDTHH:MM:SS"``. 418 added_until: Only documents added on or before this date/time. 419 String input must be ISO-8601: ``"YYYY-MM-DD"`` or ``"YYYY-MM-DDTHH:MM:SS"``. 420 modified_after: Only documents modified after this date/time. 421 String input must be ISO-8601: ``"YYYY-MM-DD"`` or ``"YYYY-MM-DDTHH:MM:SS"``. 422 modified_from: Only documents modified on or after this date/time. 423 String input must be ISO-8601: ``"YYYY-MM-DD"`` or ``"YYYY-MM-DDTHH:MM:SS"``. 424 modified_before: Only documents modified before this date/time. 425 String input must be ISO-8601: ``"YYYY-MM-DD"`` or ``"YYYY-MM-DDTHH:MM:SS"``. 426 modified_until: Only documents modified on or before this date/time. 427 String input must be ISO-8601: ``"YYYY-MM-DD"`` or ``"YYYY-MM-DDTHH:MM:SS"``. 428 checksum: MD5 checksum of the original file (exact match). 429 page_size: Number of results per API page. Default: ``25``. 430 page: Return only this specific page (1-based). 431 ordering: Field name to sort by. 432 descending: When ``True``, reverses the sort direction. 433 max_results: Stop after collecting this many documents. 434 on_page: Callback invoked after each page fetch. 435 436 Returns: 437 :class:`~easypaperless.models.paged_result.PagedResult` of 438 :class:`~easypaperless.models.documents.Document` objects. 439 """ 440 logger.info("Listing documents") 441 resolver = self._core._resolver 442 params: dict[str, Any] = {"page_size": page_size} 443 444 if search is not None: 445 api_param = _SEARCH_MODE_MAP.get(search_mode, "search") 446 params[api_param] = search 447 448 if ids is not None: 449 params["id__in"] = ",".join(str(i) for i in ids) 450 451 if tags is not None: 452 resolved = await resolver.resolve_list("tags", tags) 453 params["tags__id__all"] = ",".join(str(t) for t in resolved) 454 455 if any_tags is not None: 456 resolved = await resolver.resolve_list("tags", any_tags) 457 params["tags__id__in"] = ",".join(str(t) for t in resolved) 458 459 if exclude_tags is not None: 460 resolved = await resolver.resolve_list("tags", exclude_tags) 461 params["tags__id__none"] = ",".join(str(t) for t in resolved) 462 463 if any_correspondent is not None: 464 resolved = await resolver.resolve_list("correspondents", any_correspondent) 465 params["correspondent__id__in"] = ",".join(str(c) for c in resolved) 466 elif not isinstance(correspondent, Unset): 467 if correspondent is None: 468 params["correspondent__isnull"] = "true" 469 else: 470 resolved_id = await resolver.resolve("correspondents", correspondent) 471 params["correspondent__id"] = resolved_id 472 473 if exclude_correspondents is not None: 474 resolved = await resolver.resolve_list("correspondents", exclude_correspondents) 475 params["correspondent__id__none"] = ",".join(str(c) for c in resolved) 476 477 if document_type_name_contains is not None: 478 params["document_type__name__icontains"] = document_type_name_contains 479 if document_type_name_exact is not None: 480 params["document_type__name__iexact"] = document_type_name_exact 481 482 if any_document_type is not None: 483 resolved = await resolver.resolve_list("document_types", any_document_type) 484 params["document_type__id__in"] = ",".join(str(d) for d in resolved) 485 elif not isinstance(document_type, Unset): 486 if document_type is None: 487 params["document_type__isnull"] = "true" 488 else: 489 resolved_id = await resolver.resolve("document_types", document_type) 490 params["document_type__id"] = resolved_id 491 492 if exclude_document_types is not None: 493 resolved = await resolver.resolve_list("document_types", exclude_document_types) 494 params["document_type__id__none"] = ",".join(str(d) for d in resolved) 495 496 if any_storage_paths is not None: 497 resolved = await resolver.resolve_list("storage_paths", any_storage_paths) 498 params["storage_path__id__in"] = ",".join(str(s) for s in resolved) 499 elif not isinstance(storage_path, Unset): 500 if storage_path is None: 501 params["storage_path__isnull"] = "true" 502 else: 503 resolved_id = await resolver.resolve("storage_paths", storage_path) 504 params["storage_path__id"] = resolved_id 505 506 if exclude_storage_paths is not None: 507 resolved = await resolver.resolve_list("storage_paths", exclude_storage_paths) 508 params["storage_path__id__none"] = ",".join(str(s) for s in resolved) 509 510 if not isinstance(owner, Unset): 511 if owner is None: 512 params["owner__isnull"] = "true" 513 else: 514 params["owner__id"] = owner 515 516 if exclude_owners is not None: 517 params["owner__id__none"] = ",".join(str(o) for o in exclude_owners) 518 519 if custom_fields is not None: 520 resolved = await resolver.resolve_list("custom_fields", custom_fields) 521 params["custom_fields__id__all"] = ",".join(str(f) for f in resolved) 522 523 if any_custom_fields is not None: 524 resolved = await resolver.resolve_list("custom_fields", any_custom_fields) 525 params["custom_fields__id__in"] = ",".join(str(f) for f in resolved) 526 527 if exclude_custom_fields is not None: 528 resolved = await resolver.resolve_list("custom_fields", exclude_custom_fields) 529 params["custom_fields__id__none"] = ",".join(str(f) for f in resolved) 530 531 if custom_field_query is not None: 532 params["custom_field_query"] = json.dumps(custom_field_query) 533 534 if not isinstance(archive_serial_number, Unset): 535 if archive_serial_number is None: 536 params["archive_serial_number__isnull"] = "true" 537 else: 538 params["archive_serial_number"] = archive_serial_number 539 540 if archive_serial_number_from is not None: 541 params["archive_serial_number__gte"] = archive_serial_number_from 542 543 if archive_serial_number_till is not None: 544 params["archive_serial_number__lte"] = archive_serial_number_till 545 546 if created_after is not None: 547 params["created__date__gt"] = self._format_date_value(created_after) 548 549 if created_before is not None: 550 params["created__date__lt"] = self._format_date_value(created_before) 551 552 if added_after is not None: 553 key = "added__gt" if self._is_datetime(added_after) else "added__date__gt" 554 params[key] = self._format_date_value(added_after) 555 556 if added_from is not None: 557 key = "added__gte" if self._is_datetime(added_from) else "added__date__gte" 558 params[key] = self._format_date_value(added_from) 559 560 if added_before is not None: 561 key = "added__lt" if self._is_datetime(added_before) else "added__date__lt" 562 params[key] = self._format_date_value(added_before) 563 564 if added_until is not None: 565 key = "added__lte" if self._is_datetime(added_until) else "added__date__lte" 566 params[key] = self._format_date_value(added_until) 567 568 if modified_after is not None: 569 key = "modified__gt" if self._is_datetime(modified_after) else "modified__date__gt" 570 params[key] = self._format_date_value(modified_after) 571 572 if modified_from is not None: 573 key = "modified__gte" if self._is_datetime(modified_from) else "modified__date__gte" 574 params[key] = self._format_date_value(modified_from) 575 576 if modified_before is not None: 577 key = "modified__lt" if self._is_datetime(modified_before) else "modified__date__lt" 578 params[key] = self._format_date_value(modified_before) 579 580 if modified_until is not None: 581 key = "modified__lte" if self._is_datetime(modified_until) else "modified__date__lte" 582 params[key] = self._format_date_value(modified_until) 583 584 if checksum is not None: 585 params["checksum__iexact"] = checksum 586 587 if ordering is not None: 588 params["ordering"] = f"-{ordering}" if descending else ordering 589 590 if page is not None: 591 params["page"] = page 592 raw = await self._core._session.get_page("/documents/", params=params) 593 items = raw.items 594 if max_results is not None: 595 items = items[:max_results] 596 return PagedResult( 597 count=raw.count, 598 next=raw.next, 599 previous=raw.previous, 600 all=raw.all_ids, 601 results=[Document.model_validate(item) for item in items], 602 ) 603 604 raw = await self._core._session.get_all_pages_paged( 605 "/documents/", params, max_results=max_results, on_page=on_page 606 ) 607 return PagedResult( 608 count=raw.count, 609 next=raw.next, 610 previous=raw.previous, 611 all=raw.all_ids, 612 results=[Document.model_validate(item) for item in raw.items], 613 ) 614 615 async def update( 616 self, 617 id: int, 618 *, 619 title: str | Unset = UNSET, 620 content: str | Unset = UNSET, 621 created: date | str | None | Unset = UNSET, 622 correspondent: int | str | None | Unset = UNSET, 623 document_type: int | str | None | Unset = UNSET, 624 storage_path: int | str | None | Unset = UNSET, 625 tags: List[int | str] | None | Unset = UNSET, 626 archive_serial_number: int | None | Unset = UNSET, 627 custom_fields: List[dict[str, Any]] | None | Unset = UNSET, 628 owner: int | None | Unset = UNSET, 629 set_permissions: SetPermissions | None | Unset = UNSET, 630 remove_inbox_tags: bool | None | Unset = UNSET, 631 ) -> Document: 632 """Partially update a document (PATCH semantics). 633 634 Args: 635 id: Numeric ID of the document to update. 636 title: New document title. 637 content: OCR text content of the document. 638 created: Creation date as an ISO-8601 string (``"YYYY-MM-DD"``) or a 639 :class:`~datetime.date` object. 640 correspondent: Correspondent to assign, as an ID or name. 641 Pass ``None`` to clear the correspondent. 642 document_type: Document type to assign, as an ID or name. 643 Pass ``None`` to clear the document type. 644 storage_path: Storage path to assign, as an ID or name. 645 Pass ``None`` to clear the storage path. 646 tags: Full replacement list of tags (IDs or names). 647 archive_serial_number: Archive serial number to assign. 648 Pass ``None`` to clear the archive serial number. 649 custom_fields: List of ``{"field": <field_id>, "value": ...}`` dicts. 650 owner: Numeric user ID to assign as document owner. 651 Pass ``None`` to clear the owner. 652 set_permissions: Explicit view/change permission sets. 653 Pass ``None`` to clear all permissions (overwrite with empty). 654 Omit (or pass :data:`~easypaperless.UNSET`) to leave unchanged. 655 remove_inbox_tags: When ``True``, removes all inbox tags from the document. 656 657 Returns: 658 The updated :class:`~easypaperless.models.documents.Document`. 659 """ 660 logger.info("Updating document id=%d", id) 661 resolver = self._core._resolver 662 payload: dict[str, Any] = {} 663 664 if not isinstance(title, Unset): 665 payload["title"] = title 666 if not isinstance(content, Unset): 667 payload["content"] = content 668 if not isinstance(created, Unset): 669 payload["created"] = self._format_date_value(created) if created is not None else None 670 if not isinstance(correspondent, Unset): 671 payload["correspondent"] = ( 672 None 673 if correspondent is None 674 else await resolver.resolve("correspondents", correspondent) 675 ) 676 if not isinstance(document_type, Unset): 677 payload["document_type"] = ( 678 None 679 if document_type is None 680 else await resolver.resolve("document_types", document_type) 681 ) 682 if not isinstance(storage_path, Unset): 683 payload["storage_path"] = ( 684 None 685 if storage_path is None 686 else await resolver.resolve("storage_paths", storage_path) 687 ) 688 if not isinstance(tags, Unset): 689 payload["tags"] = await resolver.resolve_list("tags", tags or []) 690 if not isinstance(archive_serial_number, Unset): 691 payload["archive_serial_number"] = archive_serial_number 692 if not isinstance(custom_fields, Unset): 693 payload["custom_fields"] = custom_fields 694 if not isinstance(owner, Unset): 695 payload["owner"] = owner 696 if not isinstance(set_permissions, Unset): 697 payload["set_permissions"] = ( 698 SetPermissions().model_dump() 699 if set_permissions is None 700 else set_permissions.model_dump() 701 ) 702 if not isinstance(remove_inbox_tags, Unset): 703 payload["remove_inbox_tags"] = remove_inbox_tags 704 705 resp = await self._core._session.patch(f"/documents/{id}/", json=payload) 706 return Document.model_validate(resp.json()) 707 708 async def delete(self, id: int) -> None: 709 """Permanently delete a document. 710 711 Args: 712 id: Numeric ID of the document to delete. 713 714 Raises: 715 ~easypaperless.exceptions.NotFoundError: If no document exists 716 with that ID. 717 """ 718 logger.info("Deleting document id=%d", id) 719 await self._core._session.delete(f"/documents/{id}/") 720 721 async def download(self, id: int, *, original: bool = False) -> bytes: 722 """Download the binary content of a document. 723 724 Args: 725 id: Numeric ID of the document to download. 726 original: If ``False`` *(default)*, returns the archived PDF 727 (``GET /documents/{id}/download/``). 728 If ``True``, returns the original uploaded file 729 (``GET /documents/{id}/download/?original=true``). 730 731 Returns: 732 Raw file bytes. 733 """ 734 logger.info("Downloading document id=%d (original=%s)", id, original) 735 path = f"/documents/{id}/download/" 736 if original: 737 path += "?original=true" 738 resp = await self._core._session.get_download(path) 739 content_type = resp.headers.get("content-type", "") 740 if "text/html" in content_type or resp.content[:9].lower().startswith(b"<!doctype"): 741 raise ServerError( 742 f"Download returned an HTML page (content-type: {content_type!r}). " 743 "The server redirected to a login page even after re-attaching auth.", 744 status_code=None, 745 ) 746 return resp.content 747 748 async def thumbnail(self, id: int) -> bytes: 749 """Fetch the thumbnail image of a document. 750 751 Args: 752 id: Numeric ID of the document whose thumbnail to retrieve. 753 754 Returns: 755 Raw binary content of the thumbnail image. 756 757 Raises: 758 ~easypaperless.exceptions.NotFoundError: If no document exists 759 with that ID. 760 ~easypaperless.exceptions.ServerError: If the server returns an 761 HTML page (e.g. an auth redirect) instead of the image. 762 """ 763 logger.info("Fetching thumbnail for document id=%d", id) 764 resp = await self._core._session.get_download(f"/documents/{id}/thumb/") 765 content_type = resp.headers.get("content-type", "") 766 if "text/html" in content_type or resp.content[:9].lower().startswith(b"<!doctype"): 767 raise ServerError( 768 f"Thumbnail returned an HTML page (content-type: {content_type!r}). " 769 "The server redirected to a login page even after re-attaching auth.", 770 status_code=None, 771 ) 772 return resp.content 773 774 async def upload( 775 self, 776 file: str | Path, 777 *, 778 title: str | Unset = UNSET, 779 created: date | str | None = None, 780 correspondent: int | str | None | Unset = UNSET, 781 document_type: int | str | None | Unset = UNSET, 782 storage_path: int | str | None | Unset = UNSET, 783 tags: List[int | str] | None = None, 784 archive_serial_number: int | None | Unset = UNSET, 785 custom_fields: List[dict[str, Any]] | None = None, 786 wait: bool = False, 787 poll_interval: float | None = None, 788 poll_timeout: float | None = None, 789 ) -> str | Document: 790 """Upload a document to paperless-ngx. 791 792 Args: 793 file: Path to the file to upload. 794 title: Title to assign to the document. 795 created: Creation date as an ISO-8601 string (``"YYYY-MM-DD"``) or a 796 :class:`~datetime.date` object. 797 correspondent: Correspondent to assign, as an ID or name. 798 document_type: Document type to assign, as an ID or name. 799 storage_path: Storage path to assign, as an ID or name. 800 tags: Tags to assign, as IDs or names. 801 archive_serial_number: Archive serial number to assign. 802 custom_fields: List of ``{"field": <field_id>, "value": ...}`` dicts. 803 wait: If ``False`` *(default)*, returns immediately with the task ID. 804 If ``True``, polls until processing completes. 805 poll_interval: Seconds between task-status checks while waiting for 806 processing to complete (requires ``wait=True``). Overrides the 807 client-level default. When omitted, falls back to the client-level 808 ``poll_interval`` (``2.0`` s unless changed at construction). 809 poll_timeout: Maximum seconds to wait before raising 810 :exc:`~easypaperless.exceptions.TaskTimeoutError` (requires 811 ``wait=True``). Overrides the client-level default. When omitted, 812 falls back to the client-level ``poll_timeout`` (``60.0`` s unless 813 changed at construction). 814 815 Returns: 816 The Celery task ID string when ``wait=False``, or the fully 817 processed :class:`~easypaperless.models.documents.Document` 818 when ``wait=True``. 819 820 Raises: 821 ~easypaperless.exceptions.UploadError: If processing fails. 822 ~easypaperless.exceptions.TaskTimeoutError: If timeout is exceeded. 823 """ 824 resolver = self._core._resolver 825 file_path = Path(file) 826 file_bytes = file_path.read_bytes() 827 logger.info("Uploading %r (%d bytes)", file_path.name, len(file_bytes)) 828 829 data: dict[str, Any] = {} 830 if not isinstance(title, Unset): 831 data["title"] = title 832 if created is not None: 833 data["created"] = self._format_date_value(created) 834 if not isinstance(correspondent, Unset) and correspondent is not None: 835 data["correspondent"] = await resolver.resolve("correspondents", correspondent) 836 if not isinstance(document_type, Unset) and document_type is not None: 837 data["document_type"] = await resolver.resolve("document_types", document_type) 838 if not isinstance(storage_path, Unset) and storage_path is not None: 839 data["storage_path"] = await resolver.resolve("storage_paths", storage_path) 840 if tags is not None: 841 resolved = await resolver.resolve_list("tags", tags) 842 data["tags"] = resolved 843 if not isinstance(archive_serial_number, Unset) and archive_serial_number is not None: 844 data["archive_serial_number"] = archive_serial_number 845 if custom_fields is not None: 846 data["custom_fields"] = json.dumps(custom_fields) 847 848 files = {"document": (file_path.name, file_bytes)} 849 resp = await self._core._session.post("/documents/post_document/", data=data, files=files) 850 task_id: str = resp.text.strip('"') 851 logger.debug("Upload accepted, task_id=%r", task_id) 852 853 if not wait: 854 return task_id 855 856 interval = poll_interval if poll_interval is not None else self._core._poll_interval 857 timeout = poll_timeout if poll_timeout is not None else self._core._poll_timeout 858 return await self._poll_task(task_id, poll_interval=interval, poll_timeout=timeout) 859 860 async def _poll_task( 861 self, task_id: str, *, poll_interval: float, poll_timeout: float 862 ) -> Document: 863 start = time.monotonic() 864 deadline = start + poll_timeout 865 while time.monotonic() < deadline: 866 resp = await self._core._session.get("/tasks/", params={"task_id": task_id}) 867 tasks = resp.json() 868 if not tasks: 869 await asyncio.sleep(poll_interval) 870 continue 871 872 task = Task.model_validate(tasks[0]) 873 elapsed = time.monotonic() - start 874 logger.debug( 875 "Polling task %r (status=%s, elapsed=%.1fs)", 876 task_id, 877 task.status.value if task.status is not None else "unknown", 878 elapsed, 879 ) 880 if task.status == TaskStatus.SUCCESS: 881 if task.related_document is None: 882 raise UploadError(f"Task {task_id!r} succeeded but returned no document ID") 883 doc_id = int(task.related_document) 884 logger.info("Task %r succeeded, document_id=%d", task_id, doc_id) 885 return await self.get(doc_id) 886 elif task.status == TaskStatus.FAILURE: 887 logger.warning("Task %r failed: %s", task_id, task.result) 888 raise UploadError(f"Document processing failed: {task.result}") 889 elif task.status == TaskStatus.REVOKED: 890 logger.warning("Task %r was revoked", task_id) 891 raise UploadError(f"Task {task_id!r} was revoked") 892 await asyncio.sleep(poll_interval) 893 894 elapsed = time.monotonic() - start 895 logger.warning("Task %r timed out after %.1fs", task_id, elapsed) 896 raise TaskTimeoutError(f"Task {task_id!r} did not complete within {poll_timeout}s") 897 898 # ------------------------------------------------------------------------- 899 # Document bulk operations 900 # ------------------------------------------------------------------------- 901 902 async def _bulk_edit(self, document_ids: List[int], method: str, **parameters: Any) -> None: 903 """Execute a bulk-edit operation on a list of documents. 904 905 Args: 906 document_ids: List of document IDs to operate on. 907 method: Bulk-edit method name (e.g. ``"add_tag"``, ``"delete"``). 908 **parameters: Additional keyword arguments forwarded to the API. 909 """ 910 payload = {"documents": document_ids, "method": method, "parameters": parameters} 911 await self._core._session.post("/documents/bulk_edit/", json=payload, timeout=120.0) 912 913 async def bulk_add_tag(self, document_ids: List[int], tag: int | str) -> None: 914 """Add a tag to multiple documents in a single request. 915 916 Args: 917 document_ids: List of document IDs to tag. 918 tag: Tag to add, as an ID or name. 919 """ 920 logger.info("Bulk adding tag %r to %d documents", tag, len(document_ids)) 921 tag_id = await self._core._resolver.resolve("tags", tag) 922 await self._bulk_edit(document_ids, "add_tag", tag=tag_id) 923 924 async def bulk_remove_tag(self, document_ids: List[int], tag: int | str) -> None: 925 """Remove a tag from multiple documents in a single request. 926 927 Args: 928 document_ids: List of document IDs to un-tag. 929 tag: Tag to remove, as an ID or name. 930 """ 931 logger.info("Bulk removing tag %r from %d documents", tag, len(document_ids)) 932 tag_id = await self._core._resolver.resolve("tags", tag) 933 await self._bulk_edit(document_ids, "remove_tag", tag=tag_id) 934 935 async def bulk_modify_tags( 936 self, 937 document_ids: List[int], 938 *, 939 add_tags: List[int | str] | None = None, 940 remove_tags: List[int | str] | None = None, 941 ) -> None: 942 """Add and/or remove tags on multiple documents atomically. 943 944 Args: 945 document_ids: List of document IDs to modify. 946 add_tags: Tags to add, as IDs or names. 947 remove_tags: Tags to remove, as IDs or names. 948 """ 949 logger.info("Bulk modifying tags on %d documents", len(document_ids)) 950 resolver = self._core._resolver 951 add_ids = await resolver.resolve_list("tags", add_tags or []) 952 remove_ids = await resolver.resolve_list("tags", remove_tags or []) 953 await self._bulk_edit(document_ids, "modify_tags", add_tags=add_ids, remove_tags=remove_ids) 954 955 async def bulk_delete(self, document_ids: List[int]) -> None: 956 """Permanently delete multiple documents in a single request. 957 958 Args: 959 document_ids: List of document IDs to delete. 960 """ 961 logger.info("Bulk deleting %d documents", len(document_ids)) 962 await self._bulk_edit(document_ids, "delete") 963 964 async def bulk_set_correspondent( 965 self, document_ids: List[int], correspondent: int | str | None 966 ) -> None: 967 """Assign a correspondent to multiple documents in a single request. 968 969 Args: 970 document_ids: List of document IDs to modify. 971 correspondent: Correspondent to assign, as an ID or name. 972 Pass ``None`` to clear. 973 """ 974 logger.info( 975 "Bulk setting correspondent %r on %d documents", correspondent, len(document_ids) 976 ) 977 cor_id: int | None = None 978 if correspondent is not None: 979 cor_id = await self._core._resolver.resolve("correspondents", correspondent) 980 await self._bulk_edit(document_ids, "set_correspondent", correspondent=cor_id) 981 982 async def bulk_set_document_type( 983 self, document_ids: List[int], document_type: int | str | None 984 ) -> None: 985 """Assign a document type to multiple documents in a single request. 986 987 Args: 988 document_ids: List of document IDs to modify. 989 document_type: Document type to assign, as an ID or name. 990 Pass ``None`` to clear. 991 """ 992 logger.info( 993 "Bulk setting document type %r on %d documents", document_type, len(document_ids) 994 ) 995 dt_id: int | None = None 996 if document_type is not None: 997 dt_id = await self._core._resolver.resolve("document_types", document_type) 998 await self._bulk_edit(document_ids, "set_document_type", document_type=dt_id) 999 1000 async def bulk_set_storage_path( 1001 self, document_ids: List[int], storage_path: int | str | None 1002 ) -> None: 1003 """Assign a storage path to multiple documents in a single request. 1004 1005 Args: 1006 document_ids: List of document IDs to modify. 1007 storage_path: Storage path to assign, as an ID or name. 1008 Pass ``None`` to clear. 1009 """ 1010 logger.info("Bulk setting storage path %r on %d documents", storage_path, len(document_ids)) 1011 sp_id: int | None = None 1012 if storage_path is not None: 1013 sp_id = await self._core._resolver.resolve("storage_paths", storage_path) 1014 await self._bulk_edit(document_ids, "set_storage_path", storage_path=sp_id) 1015 1016 async def bulk_modify_custom_fields( 1017 self, 1018 document_ids: List[int], 1019 *, 1020 add_fields: List[dict[str, Any]] | None = None, 1021 remove_fields: List[int] | None = None, 1022 ) -> None: 1023 """Add and/or remove custom field values on multiple documents. 1024 1025 Args: 1026 document_ids: List of document IDs to modify. 1027 add_fields: Custom-field value dicts to add. 1028 remove_fields: Custom-field IDs whose values should be removed. 1029 """ 1030 logger.info("Bulk modifying custom fields on %d documents", len(document_ids)) 1031 await self._bulk_edit( 1032 document_ids, 1033 "modify_custom_fields", 1034 add_custom_fields=add_fields or [], 1035 remove_custom_fields=remove_fields or [], 1036 ) 1037 1038 async def bulk_set_permissions( 1039 self, 1040 document_ids: List[int], 1041 *, 1042 set_permissions: SetPermissions | Unset = UNSET, 1043 owner: int | None | Unset = UNSET, 1044 merge: bool = False, 1045 ) -> None: 1046 """Set permissions and/or owner on multiple documents. 1047 1048 Args: 1049 document_ids: List of document IDs to modify. 1050 set_permissions: Explicit view/change permission sets. 1051 Omit (or pass :data:`~easypaperless.UNSET`) to leave unchanged. 1052 owner: Numeric user ID to assign as document owner. 1053 Pass ``None`` to clear the owner. 1054 Omit (or pass :data:`~easypaperless.UNSET`) to leave unchanged. 1055 merge: When ``True``, new permissions are merged with existing ones. 1056 """ 1057 logger.info("Bulk setting permissions on %d documents", len(document_ids)) 1058 params: dict[str, Any] = {"merge": merge} 1059 if not isinstance(set_permissions, Unset): 1060 params["set_permissions"] = set_permissions.model_dump() 1061 if not isinstance(owner, Unset): 1062 params["owner"] = owner 1063 await self._bulk_edit(document_ids, "set_permissions", **params) 1064 1065 async def bulk_download( 1066 self, 1067 document_ids: List[int], 1068 *, 1069 content: Literal["archive", "originals", "both"] = "archive", 1070 compression: Literal["none", "deflated", "bzip2", "lzma"] = "none", 1071 follow_formatting: bool = False, 1072 ) -> bytes: 1073 """Download multiple documents as a single ZIP archive. 1074 1075 Args: 1076 document_ids: List of document IDs to include in the ZIP. 1077 content: File variant to include. One of ``"archive"`` *(default)*, 1078 ``"originals"``, or ``"both"``. 1079 compression: ZIP compression algorithm. One of ``"none"`` *(default)*, 1080 ``"deflated"``, ``"bzip2"``, or ``"lzma"``. 1081 follow_formatting: When ``True``, filenames inside the ZIP follow 1082 the storage path formatting configured in paperless-ngx. 1083 Default: ``False``. 1084 1085 Returns: 1086 Raw bytes of the ZIP archive. 1087 """ 1088 logger.info( 1089 "Bulk downloading %d documents (content=%s, compression=%s)", 1090 len(document_ids), 1091 content, 1092 compression, 1093 ) 1094 payload: dict[str, Any] = { 1095 "documents": document_ids, 1096 "content": content, 1097 "compression": compression, 1098 "follow_formatting": follow_formatting, 1099 } 1100 resp = await self._core._session.post("/documents/bulk_download/", json=payload) 1101 return resp.content
Accessor for documents: client.documents.
183 async def history( 184 self, 185 document_id: int, 186 *, 187 page: int | None = None, 188 page_size: int | None = None, 189 ) -> PagedResult[AuditLogEntry]: 190 """Fetch the audit log for a document. 191 192 The paperless-ngx ``/api/documents/{id}/history/`` endpoint returns a 193 plain JSON array rather than a paginated envelope. This method wraps 194 the response into a :class:`~easypaperless.models.paged_result.PagedResult` 195 so callers always receive a consistent return type. 196 197 Args: 198 document_id: Numeric ID of the document whose history to retrieve. 199 page: Forwarded to the API as a query parameter when provided. 200 Effect depends on the paperless-ngx version; the server may 201 ignore this parameter. 202 page_size: Forwarded to the API as a query parameter when provided. 203 204 Returns: 205 :class:`~easypaperless.models.paged_result.PagedResult` of 206 :class:`~easypaperless.models.documents.AuditLogEntry` objects, 207 ordered by timestamp descending. 208 209 Raises: 210 ~easypaperless.exceptions.NotFoundError: If no document exists 211 with that ID. 212 """ 213 logger.info("Fetching history for document id=%d", document_id) 214 path = f"/documents/{document_id}/history/" 215 params: dict[str, Any] = {} 216 if page is not None: 217 params["page"] = page 218 if page_size is not None: 219 params["page_size"] = page_size 220 221 resp = await self._core._session.get(path, params=params or None) 222 data = resp.json() 223 224 if isinstance(data, list): 225 entries = [AuditLogEntry.model_validate(item) for item in data] 226 entry_ids: list[int] = [e.id for e in entries] 227 return PagedResult( 228 count=len(entries), 229 next=None, 230 previous=None, 231 all=entry_ids if entry_ids else None, 232 results=entries, 233 ) 234 235 # Forward-compatible: handle a paginated envelope if the API ever adds one. 236 items: list[Any] = list(data.get("results", [])) 237 count: int = data.get("count", 0) 238 all_ids: list[int] | None = data.get("all") 239 return PagedResult( 240 count=count, 241 next=data.get("next"), 242 previous=data.get("previous"), 243 all=all_ids, 244 results=[AuditLogEntry.model_validate(item) for item in items], 245 )
Fetch the audit log for a document.
The paperless-ngx /api/documents/{id}/history/ endpoint returns a
plain JSON array rather than a paginated envelope. This method wraps
the response into a ~easypaperless.models.paged_result.PagedResult
so callers always receive a consistent return type.
Arguments:
- document_id: Numeric ID of the document whose history to retrieve.
- page: Forwarded to the API as a query parameter when provided. Effect depends on the paperless-ngx version; the server may ignore this parameter.
- page_size: Forwarded to the API as a query parameter when provided.
Returns:
~easypaperless.models.paged_result.PagedResultof~easypaperless.models.documents.AuditLogEntryobjects, ordered by timestamp descending.
Raises:
- ~easypaperless.exceptions.NotFoundError: If no document exists with that ID.
263 async def get(self, id: int, *, include_metadata: bool = False) -> Document: 264 """Fetch a single document by its ID. 265 266 Args: 267 id: Numeric paperless-ngx document ID. 268 include_metadata: When ``True``, the extended file-level metadata 269 is fetched concurrently and attached to the document. 270 Default: ``False``. 271 272 Returns: 273 The :class:`~easypaperless.models.documents.Document` with the 274 given ID. 275 276 Raises: 277 ~easypaperless.exceptions.NotFoundError: If no document exists 278 with that ID. 279 """ 280 logger.info("Getting document id=%d", id) 281 if include_metadata: 282 doc_resp, meta_resp = await asyncio.gather( 283 self._core._session.get(f"/documents/{id}/"), 284 self._core._session.get(f"/documents/{id}/metadata/"), 285 ) 286 data = doc_resp.json() 287 data["metadata"] = meta_resp.json() 288 else: 289 resp = await self._core._session.get(f"/documents/{id}/") 290 data = resp.json() 291 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.
293 async def get_metadata(self, id: int) -> DocumentMetadata: 294 """Fetch the extended file-level metadata for a document. 295 296 Args: 297 id: Numeric paperless-ngx document ID. 298 299 Returns: 300 A :class:`~easypaperless.models.documents.DocumentMetadata` instance. 301 302 Raises: 303 ~easypaperless.exceptions.NotFoundError: If no document exists 304 with that ID. 305 """ 306 logger.info("Getting metadata for document id=%d", id) 307 resp = await self._core._session.get(f"/documents/{id}/metadata/") 308 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.
310 async def list( 311 self, 312 *, 313 search: str | None = None, 314 search_mode: str = "title_or_content", 315 ids: List[int] | None = None, 316 tags: List[int | str] | None = None, 317 any_tags: List[int | str] | None = None, 318 exclude_tags: List[int | str] | None = None, 319 correspondent: int | str | None | Unset = UNSET, 320 any_correspondent: List[int | str] | None = None, 321 exclude_correspondents: List[int | str] | None = None, 322 document_type: int | str | None | Unset = UNSET, 323 document_type_name_contains: str | None = None, 324 document_type_name_exact: str | None = None, 325 any_document_type: List[int | str] | None = None, 326 exclude_document_types: List[int | str] | None = None, 327 storage_path: int | str | None | Unset = UNSET, 328 any_storage_paths: List[int | str] | None = None, 329 exclude_storage_paths: List[int | str] | None = None, 330 owner: int | None | Unset = UNSET, 331 exclude_owners: List[int] | None = None, 332 custom_fields: List[int | str] | None = None, 333 any_custom_fields: List[int | str] | None = None, 334 exclude_custom_fields: List[int | str] | None = None, 335 custom_field_query: List[Any] | None = None, 336 archive_serial_number: int | None | Unset = UNSET, 337 archive_serial_number_from: int | None = None, 338 archive_serial_number_till: int | None = None, 339 created_after: date | str | None = None, 340 created_before: date | str | None = None, 341 added_after: date | datetime | str | None = None, 342 added_from: date | datetime | str | None = None, 343 added_before: date | datetime | str | None = None, 344 added_until: date | datetime | str | None = None, 345 modified_after: date | datetime | str | None = None, 346 modified_from: date | datetime | str | None = None, 347 modified_before: date | datetime | str | None = None, 348 modified_until: date | datetime | str | None = None, 349 checksum: str | None = None, 350 page_size: int = 25, 351 page: int | None = None, 352 ordering: str | None = None, 353 descending: bool = False, 354 max_results: int | None = None, 355 on_page: Callable[[int, int | None], None] | None = None, 356 ) -> PagedResult[Document]: 357 """Return a filtered list of documents. 358 359 All tag, correspondent, document-type, storage-path, and custom-field 360 parameters accept either integer IDs or string names. 361 362 When ``page`` is ``None`` (the default), all pages are fetched 363 automatically and ``next`` / ``previous`` in the returned 364 :class:`~easypaperless.models.paged_result.PagedResult` are always 365 ``None`` — even if ``max_results`` truncates the final result set. 366 ``count`` always reflects the server total, not the truncated length. 367 When ``page`` is set to a specific integer, only that one page is 368 fetched and ``next`` / ``previous`` contain the raw API values. 369 370 Args: 371 search: Search string. Behaviour depends on ``search_mode``. 372 search_mode: How ``search`` is applied. One of: 373 ``"title_or_content"`` *(default)*, ``"title"``, ``"query"``, 374 ``"original_filename"``. 375 ids: Return only documents whose ID is in this list. 376 tags: Documents must have **all** of these tags (AND semantics). 377 any_tags: Documents must have **at least one** of these tags. 378 exclude_tags: Documents must have **none** of these tags. 379 correspondent: Filter to documents assigned to this correspondent. 380 Pass ``None`` to return only documents with no correspondent set. 381 any_correspondent: Filter to documents assigned to any of these. 382 exclude_correspondents: Exclude documents assigned to any of these. 383 document_type: Filter to documents of exactly this type. 384 Pass ``None`` to return only documents with no document type set. 385 document_type_name_contains: Case-insensitive substring filter on document type name. 386 document_type_name_exact: Case-insensitive exact match on document type name. 387 any_document_type: Filter to documents whose type is any of these. 388 exclude_document_types: Exclude documents whose type is any of these. 389 storage_path: Filter to documents assigned to this storage path. 390 Pass ``None`` to return only documents with no storage path set. 391 any_storage_paths: Filter to documents assigned to any of these paths. 392 exclude_storage_paths: Exclude documents assigned to any of these paths. 393 owner: Filter to documents owned by this user ID. 394 Pass ``None`` to return only documents with no owner set. 395 exclude_owners: Exclude documents owned by any of these user IDs. 396 custom_fields: Documents must have **all** of these custom fields set. 397 any_custom_fields: Documents must have **at least one** of these fields. 398 exclude_custom_fields: Documents must have **none** of these fields. 399 custom_field_query: Filter documents by custom field values using a nested 400 query structure. See the `paperless-ngx API docs 401 <https://docs.paperless-ngx.com/api/#filtering-by-custom-fields>`_ for 402 the query format. 403 archive_serial_number: Filter by exact archive serial number. 404 Pass ``None`` to return only documents with no ASN set. 405 archive_serial_number_from: Filter by ASN >= this value. 406 archive_serial_number_till: Filter by ASN <= this value. 407 created_after: Only documents created after this date. 408 String input must be ISO-8601: ``"YYYY-MM-DD"``. 409 created_before: Only documents created before this date. 410 String input must be ISO-8601: ``"YYYY-MM-DD"``. 411 added_after: Only documents added after this date/time. 412 String input must be ISO-8601: ``"YYYY-MM-DD"`` for date precision or 413 ``"YYYY-MM-DDTHH:MM:SS"`` for datetime precision. 414 added_from: Only documents added on or after this date/time. 415 String input must be ISO-8601: ``"YYYY-MM-DD"`` or ``"YYYY-MM-DDTHH:MM:SS"``. 416 added_before: Only documents added before this date/time. 417 String input must be ISO-8601: ``"YYYY-MM-DD"`` or ``"YYYY-MM-DDTHH:MM:SS"``. 418 added_until: Only documents added on or before this date/time. 419 String input must be ISO-8601: ``"YYYY-MM-DD"`` or ``"YYYY-MM-DDTHH:MM:SS"``. 420 modified_after: Only documents modified after this date/time. 421 String input must be ISO-8601: ``"YYYY-MM-DD"`` or ``"YYYY-MM-DDTHH:MM:SS"``. 422 modified_from: Only documents modified on or after this date/time. 423 String input must be ISO-8601: ``"YYYY-MM-DD"`` or ``"YYYY-MM-DDTHH:MM:SS"``. 424 modified_before: Only documents modified before this date/time. 425 String input must be ISO-8601: ``"YYYY-MM-DD"`` or ``"YYYY-MM-DDTHH:MM:SS"``. 426 modified_until: Only documents modified on or before this date/time. 427 String input must be ISO-8601: ``"YYYY-MM-DD"`` or ``"YYYY-MM-DDTHH:MM:SS"``. 428 checksum: MD5 checksum of the original file (exact match). 429 page_size: Number of results per API page. Default: ``25``. 430 page: Return only this specific page (1-based). 431 ordering: Field name to sort by. 432 descending: When ``True``, reverses the sort direction. 433 max_results: Stop after collecting this many documents. 434 on_page: Callback invoked after each page fetch. 435 436 Returns: 437 :class:`~easypaperless.models.paged_result.PagedResult` of 438 :class:`~easypaperless.models.documents.Document` objects. 439 """ 440 logger.info("Listing documents") 441 resolver = self._core._resolver 442 params: dict[str, Any] = {"page_size": page_size} 443 444 if search is not None: 445 api_param = _SEARCH_MODE_MAP.get(search_mode, "search") 446 params[api_param] = search 447 448 if ids is not None: 449 params["id__in"] = ",".join(str(i) for i in ids) 450 451 if tags is not None: 452 resolved = await resolver.resolve_list("tags", tags) 453 params["tags__id__all"] = ",".join(str(t) for t in resolved) 454 455 if any_tags is not None: 456 resolved = await resolver.resolve_list("tags", any_tags) 457 params["tags__id__in"] = ",".join(str(t) for t in resolved) 458 459 if exclude_tags is not None: 460 resolved = await resolver.resolve_list("tags", exclude_tags) 461 params["tags__id__none"] = ",".join(str(t) for t in resolved) 462 463 if any_correspondent is not None: 464 resolved = await resolver.resolve_list("correspondents", any_correspondent) 465 params["correspondent__id__in"] = ",".join(str(c) for c in resolved) 466 elif not isinstance(correspondent, Unset): 467 if correspondent is None: 468 params["correspondent__isnull"] = "true" 469 else: 470 resolved_id = await resolver.resolve("correspondents", correspondent) 471 params["correspondent__id"] = resolved_id 472 473 if exclude_correspondents is not None: 474 resolved = await resolver.resolve_list("correspondents", exclude_correspondents) 475 params["correspondent__id__none"] = ",".join(str(c) for c in resolved) 476 477 if document_type_name_contains is not None: 478 params["document_type__name__icontains"] = document_type_name_contains 479 if document_type_name_exact is not None: 480 params["document_type__name__iexact"] = document_type_name_exact 481 482 if any_document_type is not None: 483 resolved = await resolver.resolve_list("document_types", any_document_type) 484 params["document_type__id__in"] = ",".join(str(d) for d in resolved) 485 elif not isinstance(document_type, Unset): 486 if document_type is None: 487 params["document_type__isnull"] = "true" 488 else: 489 resolved_id = await resolver.resolve("document_types", document_type) 490 params["document_type__id"] = resolved_id 491 492 if exclude_document_types is not None: 493 resolved = await resolver.resolve_list("document_types", exclude_document_types) 494 params["document_type__id__none"] = ",".join(str(d) for d in resolved) 495 496 if any_storage_paths is not None: 497 resolved = await resolver.resolve_list("storage_paths", any_storage_paths) 498 params["storage_path__id__in"] = ",".join(str(s) for s in resolved) 499 elif not isinstance(storage_path, Unset): 500 if storage_path is None: 501 params["storage_path__isnull"] = "true" 502 else: 503 resolved_id = await resolver.resolve("storage_paths", storage_path) 504 params["storage_path__id"] = resolved_id 505 506 if exclude_storage_paths is not None: 507 resolved = await resolver.resolve_list("storage_paths", exclude_storage_paths) 508 params["storage_path__id__none"] = ",".join(str(s) for s in resolved) 509 510 if not isinstance(owner, Unset): 511 if owner is None: 512 params["owner__isnull"] = "true" 513 else: 514 params["owner__id"] = owner 515 516 if exclude_owners is not None: 517 params["owner__id__none"] = ",".join(str(o) for o in exclude_owners) 518 519 if custom_fields is not None: 520 resolved = await resolver.resolve_list("custom_fields", custom_fields) 521 params["custom_fields__id__all"] = ",".join(str(f) for f in resolved) 522 523 if any_custom_fields is not None: 524 resolved = await resolver.resolve_list("custom_fields", any_custom_fields) 525 params["custom_fields__id__in"] = ",".join(str(f) for f in resolved) 526 527 if exclude_custom_fields is not None: 528 resolved = await resolver.resolve_list("custom_fields", exclude_custom_fields) 529 params["custom_fields__id__none"] = ",".join(str(f) for f in resolved) 530 531 if custom_field_query is not None: 532 params["custom_field_query"] = json.dumps(custom_field_query) 533 534 if not isinstance(archive_serial_number, Unset): 535 if archive_serial_number is None: 536 params["archive_serial_number__isnull"] = "true" 537 else: 538 params["archive_serial_number"] = archive_serial_number 539 540 if archive_serial_number_from is not None: 541 params["archive_serial_number__gte"] = archive_serial_number_from 542 543 if archive_serial_number_till is not None: 544 params["archive_serial_number__lte"] = archive_serial_number_till 545 546 if created_after is not None: 547 params["created__date__gt"] = self._format_date_value(created_after) 548 549 if created_before is not None: 550 params["created__date__lt"] = self._format_date_value(created_before) 551 552 if added_after is not None: 553 key = "added__gt" if self._is_datetime(added_after) else "added__date__gt" 554 params[key] = self._format_date_value(added_after) 555 556 if added_from is not None: 557 key = "added__gte" if self._is_datetime(added_from) else "added__date__gte" 558 params[key] = self._format_date_value(added_from) 559 560 if added_before is not None: 561 key = "added__lt" if self._is_datetime(added_before) else "added__date__lt" 562 params[key] = self._format_date_value(added_before) 563 564 if added_until is not None: 565 key = "added__lte" if self._is_datetime(added_until) else "added__date__lte" 566 params[key] = self._format_date_value(added_until) 567 568 if modified_after is not None: 569 key = "modified__gt" if self._is_datetime(modified_after) else "modified__date__gt" 570 params[key] = self._format_date_value(modified_after) 571 572 if modified_from is not None: 573 key = "modified__gte" if self._is_datetime(modified_from) else "modified__date__gte" 574 params[key] = self._format_date_value(modified_from) 575 576 if modified_before is not None: 577 key = "modified__lt" if self._is_datetime(modified_before) else "modified__date__lt" 578 params[key] = self._format_date_value(modified_before) 579 580 if modified_until is not None: 581 key = "modified__lte" if self._is_datetime(modified_until) else "modified__date__lte" 582 params[key] = self._format_date_value(modified_until) 583 584 if checksum is not None: 585 params["checksum__iexact"] = checksum 586 587 if ordering is not None: 588 params["ordering"] = f"-{ordering}" if descending else ordering 589 590 if page is not None: 591 params["page"] = page 592 raw = await self._core._session.get_page("/documents/", params=params) 593 items = raw.items 594 if max_results is not None: 595 items = items[:max_results] 596 return PagedResult( 597 count=raw.count, 598 next=raw.next, 599 previous=raw.previous, 600 all=raw.all_ids, 601 results=[Document.model_validate(item) for item in items], 602 ) 603 604 raw = await self._core._session.get_all_pages_paged( 605 "/documents/", params, max_results=max_results, on_page=on_page 606 ) 607 return PagedResult( 608 count=raw.count, 609 next=raw.next, 610 previous=raw.previous, 611 all=raw.all_ids, 612 results=[Document.model_validate(item) for item in raw.items], 613 )
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.
615 async def update( 616 self, 617 id: int, 618 *, 619 title: str | Unset = UNSET, 620 content: str | Unset = UNSET, 621 created: date | str | None | Unset = UNSET, 622 correspondent: int | str | None | Unset = UNSET, 623 document_type: int | str | None | Unset = UNSET, 624 storage_path: int | str | None | Unset = UNSET, 625 tags: List[int | str] | None | Unset = UNSET, 626 archive_serial_number: int | None | Unset = UNSET, 627 custom_fields: List[dict[str, Any]] | None | Unset = UNSET, 628 owner: int | None | Unset = UNSET, 629 set_permissions: SetPermissions | None | Unset = UNSET, 630 remove_inbox_tags: bool | None | Unset = UNSET, 631 ) -> Document: 632 """Partially update a document (PATCH semantics). 633 634 Args: 635 id: Numeric ID of the document to update. 636 title: New document title. 637 content: OCR text content of the document. 638 created: Creation date as an ISO-8601 string (``"YYYY-MM-DD"``) or a 639 :class:`~datetime.date` object. 640 correspondent: Correspondent to assign, as an ID or name. 641 Pass ``None`` to clear the correspondent. 642 document_type: Document type to assign, as an ID or name. 643 Pass ``None`` to clear the document type. 644 storage_path: Storage path to assign, as an ID or name. 645 Pass ``None`` to clear the storage path. 646 tags: Full replacement list of tags (IDs or names). 647 archive_serial_number: Archive serial number to assign. 648 Pass ``None`` to clear the archive serial number. 649 custom_fields: List of ``{"field": <field_id>, "value": ...}`` dicts. 650 owner: Numeric user ID to assign as document owner. 651 Pass ``None`` to clear the owner. 652 set_permissions: Explicit view/change permission sets. 653 Pass ``None`` to clear all permissions (overwrite with empty). 654 Omit (or pass :data:`~easypaperless.UNSET`) to leave unchanged. 655 remove_inbox_tags: When ``True``, removes all inbox tags from the document. 656 657 Returns: 658 The updated :class:`~easypaperless.models.documents.Document`. 659 """ 660 logger.info("Updating document id=%d", id) 661 resolver = self._core._resolver 662 payload: dict[str, Any] = {} 663 664 if not isinstance(title, Unset): 665 payload["title"] = title 666 if not isinstance(content, Unset): 667 payload["content"] = content 668 if not isinstance(created, Unset): 669 payload["created"] = self._format_date_value(created) if created is not None else None 670 if not isinstance(correspondent, Unset): 671 payload["correspondent"] = ( 672 None 673 if correspondent is None 674 else await resolver.resolve("correspondents", correspondent) 675 ) 676 if not isinstance(document_type, Unset): 677 payload["document_type"] = ( 678 None 679 if document_type is None 680 else await resolver.resolve("document_types", document_type) 681 ) 682 if not isinstance(storage_path, Unset): 683 payload["storage_path"] = ( 684 None 685 if storage_path is None 686 else await resolver.resolve("storage_paths", storage_path) 687 ) 688 if not isinstance(tags, Unset): 689 payload["tags"] = await resolver.resolve_list("tags", tags or []) 690 if not isinstance(archive_serial_number, Unset): 691 payload["archive_serial_number"] = archive_serial_number 692 if not isinstance(custom_fields, Unset): 693 payload["custom_fields"] = custom_fields 694 if not isinstance(owner, Unset): 695 payload["owner"] = owner 696 if not isinstance(set_permissions, Unset): 697 payload["set_permissions"] = ( 698 SetPermissions().model_dump() 699 if set_permissions is None 700 else set_permissions.model_dump() 701 ) 702 if not isinstance(remove_inbox_tags, Unset): 703 payload["remove_inbox_tags"] = remove_inbox_tags 704 705 resp = await self._core._session.patch(f"/documents/{id}/", json=payload) 706 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.
708 async def delete(self, id: int) -> None: 709 """Permanently delete a document. 710 711 Args: 712 id: Numeric ID of the document to delete. 713 714 Raises: 715 ~easypaperless.exceptions.NotFoundError: If no document exists 716 with that ID. 717 """ 718 logger.info("Deleting document id=%d", id) 719 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.
721 async def download(self, id: int, *, original: bool = False) -> bytes: 722 """Download the binary content of a document. 723 724 Args: 725 id: Numeric ID of the document to download. 726 original: If ``False`` *(default)*, returns the archived PDF 727 (``GET /documents/{id}/download/``). 728 If ``True``, returns the original uploaded file 729 (``GET /documents/{id}/download/?original=true``). 730 731 Returns: 732 Raw file bytes. 733 """ 734 logger.info("Downloading document id=%d (original=%s)", id, original) 735 path = f"/documents/{id}/download/" 736 if original: 737 path += "?original=true" 738 resp = await self._core._session.get_download(path) 739 content_type = resp.headers.get("content-type", "") 740 if "text/html" in content_type or resp.content[:9].lower().startswith(b"<!doctype"): 741 raise ServerError( 742 f"Download returned an HTML page (content-type: {content_type!r}). " 743 "The server redirected to a login page even after re-attaching auth.", 744 status_code=None, 745 ) 746 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 (GET /documents/{id}/download/). IfTrue, returns the original uploaded file (GET /documents/{id}/download/?original=true).
Returns:
Raw file bytes.
748 async def thumbnail(self, id: int) -> bytes: 749 """Fetch the thumbnail image of a document. 750 751 Args: 752 id: Numeric ID of the document whose thumbnail to retrieve. 753 754 Returns: 755 Raw binary content of the thumbnail image. 756 757 Raises: 758 ~easypaperless.exceptions.NotFoundError: If no document exists 759 with that ID. 760 ~easypaperless.exceptions.ServerError: If the server returns an 761 HTML page (e.g. an auth redirect) instead of the image. 762 """ 763 logger.info("Fetching thumbnail for document id=%d", id) 764 resp = await self._core._session.get_download(f"/documents/{id}/thumb/") 765 content_type = resp.headers.get("content-type", "") 766 if "text/html" in content_type or resp.content[:9].lower().startswith(b"<!doctype"): 767 raise ServerError( 768 f"Thumbnail returned an HTML page (content-type: {content_type!r}). " 769 "The server redirected to a login page even after re-attaching auth.", 770 status_code=None, 771 ) 772 return resp.content
Fetch the thumbnail image of a document.
Arguments:
- id: Numeric ID of the document whose thumbnail to retrieve.
Returns:
Raw binary content of the thumbnail image.
Raises:
- ~easypaperless.exceptions.NotFoundError: If no document exists with that ID.
- ~easypaperless.exceptions.ServerError: If the server returns an HTML page (e.g. an auth redirect) instead of the image.
774 async def upload( 775 self, 776 file: str | Path, 777 *, 778 title: str | Unset = UNSET, 779 created: date | str | None = None, 780 correspondent: int | str | None | Unset = UNSET, 781 document_type: int | str | None | Unset = UNSET, 782 storage_path: int | str | None | Unset = UNSET, 783 tags: List[int | str] | None = None, 784 archive_serial_number: int | None | Unset = UNSET, 785 custom_fields: List[dict[str, Any]] | None = None, 786 wait: bool = False, 787 poll_interval: float | None = None, 788 poll_timeout: float | None = None, 789 ) -> str | Document: 790 """Upload a document to paperless-ngx. 791 792 Args: 793 file: Path to the file to upload. 794 title: Title to assign to the document. 795 created: Creation date as an ISO-8601 string (``"YYYY-MM-DD"``) or a 796 :class:`~datetime.date` object. 797 correspondent: Correspondent to assign, as an ID or name. 798 document_type: Document type to assign, as an ID or name. 799 storage_path: Storage path to assign, as an ID or name. 800 tags: Tags to assign, as IDs or names. 801 archive_serial_number: Archive serial number to assign. 802 custom_fields: List of ``{"field": <field_id>, "value": ...}`` dicts. 803 wait: If ``False`` *(default)*, returns immediately with the task ID. 804 If ``True``, polls until processing completes. 805 poll_interval: Seconds between task-status checks while waiting for 806 processing to complete (requires ``wait=True``). Overrides the 807 client-level default. When omitted, falls back to the client-level 808 ``poll_interval`` (``2.0`` s unless changed at construction). 809 poll_timeout: Maximum seconds to wait before raising 810 :exc:`~easypaperless.exceptions.TaskTimeoutError` (requires 811 ``wait=True``). Overrides the client-level default. When omitted, 812 falls back to the client-level ``poll_timeout`` (``60.0`` s unless 813 changed at construction). 814 815 Returns: 816 The Celery task ID string when ``wait=False``, or the fully 817 processed :class:`~easypaperless.models.documents.Document` 818 when ``wait=True``. 819 820 Raises: 821 ~easypaperless.exceptions.UploadError: If processing fails. 822 ~easypaperless.exceptions.TaskTimeoutError: If timeout is exceeded. 823 """ 824 resolver = self._core._resolver 825 file_path = Path(file) 826 file_bytes = file_path.read_bytes() 827 logger.info("Uploading %r (%d bytes)", file_path.name, len(file_bytes)) 828 829 data: dict[str, Any] = {} 830 if not isinstance(title, Unset): 831 data["title"] = title 832 if created is not None: 833 data["created"] = self._format_date_value(created) 834 if not isinstance(correspondent, Unset) and correspondent is not None: 835 data["correspondent"] = await resolver.resolve("correspondents", correspondent) 836 if not isinstance(document_type, Unset) and document_type is not None: 837 data["document_type"] = await resolver.resolve("document_types", document_type) 838 if not isinstance(storage_path, Unset) and storage_path is not None: 839 data["storage_path"] = await resolver.resolve("storage_paths", storage_path) 840 if tags is not None: 841 resolved = await resolver.resolve_list("tags", tags) 842 data["tags"] = resolved 843 if not isinstance(archive_serial_number, Unset) and archive_serial_number is not None: 844 data["archive_serial_number"] = archive_serial_number 845 if custom_fields is not None: 846 data["custom_fields"] = json.dumps(custom_fields) 847 848 files = {"document": (file_path.name, file_bytes)} 849 resp = await self._core._session.post("/documents/post_document/", data=data, files=files) 850 task_id: str = resp.text.strip('"') 851 logger.debug("Upload accepted, task_id=%r", task_id) 852 853 if not wait: 854 return task_id 855 856 interval = poll_interval if poll_interval is not None else self._core._poll_interval 857 timeout = poll_timeout if poll_timeout is not None else self._core._poll_timeout 858 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.
913 async def bulk_add_tag(self, document_ids: List[int], tag: int | str) -> None: 914 """Add a tag to multiple documents in a single request. 915 916 Args: 917 document_ids: List of document IDs to tag. 918 tag: Tag to add, as an ID or name. 919 """ 920 logger.info("Bulk adding tag %r to %d documents", tag, len(document_ids)) 921 tag_id = await self._core._resolver.resolve("tags", tag) 922 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.
924 async def bulk_remove_tag(self, document_ids: List[int], tag: int | str) -> None: 925 """Remove a tag from multiple documents in a single request. 926 927 Args: 928 document_ids: List of document IDs to un-tag. 929 tag: Tag to remove, as an ID or name. 930 """ 931 logger.info("Bulk removing tag %r from %d documents", tag, len(document_ids)) 932 tag_id = await self._core._resolver.resolve("tags", tag) 933 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.
955 async def bulk_delete(self, document_ids: List[int]) -> None: 956 """Permanently delete multiple documents in a single request. 957 958 Args: 959 document_ids: List of document IDs to delete. 960 """ 961 logger.info("Bulk deleting %d documents", len(document_ids)) 962 await self._bulk_edit(document_ids, "delete")
Permanently delete multiple documents in a single request.
Arguments:
- document_ids: List of document IDs to delete.
964 async def bulk_set_correspondent( 965 self, document_ids: List[int], correspondent: int | str | None 966 ) -> None: 967 """Assign a correspondent to multiple documents in a single request. 968 969 Args: 970 document_ids: List of document IDs to modify. 971 correspondent: Correspondent to assign, as an ID or name. 972 Pass ``None`` to clear. 973 """ 974 logger.info( 975 "Bulk setting correspondent %r on %d documents", correspondent, len(document_ids) 976 ) 977 cor_id: int | None = None 978 if correspondent is not None: 979 cor_id = await self._core._resolver.resolve("correspondents", correspondent) 980 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.
982 async def bulk_set_document_type( 983 self, document_ids: List[int], document_type: int | str | None 984 ) -> None: 985 """Assign a document type to multiple documents in a single request. 986 987 Args: 988 document_ids: List of document IDs to modify. 989 document_type: Document type to assign, as an ID or name. 990 Pass ``None`` to clear. 991 """ 992 logger.info( 993 "Bulk setting document type %r on %d documents", document_type, len(document_ids) 994 ) 995 dt_id: int | None = None 996 if document_type is not None: 997 dt_id = await self._core._resolver.resolve("document_types", document_type) 998 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.
1000 async def bulk_set_storage_path( 1001 self, document_ids: List[int], storage_path: int | str | None 1002 ) -> None: 1003 """Assign a storage path to multiple documents in a single request. 1004 1005 Args: 1006 document_ids: List of document IDs to modify. 1007 storage_path: Storage path to assign, as an ID or name. 1008 Pass ``None`` to clear. 1009 """ 1010 logger.info("Bulk setting storage path %r on %d documents", storage_path, len(document_ids)) 1011 sp_id: int | None = None 1012 if storage_path is not None: 1013 sp_id = await self._core._resolver.resolve("storage_paths", storage_path) 1014 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.
1016 async def bulk_modify_custom_fields( 1017 self, 1018 document_ids: List[int], 1019 *, 1020 add_fields: List[dict[str, Any]] | None = None, 1021 remove_fields: List[int] | None = None, 1022 ) -> None: 1023 """Add and/or remove custom field values on multiple documents. 1024 1025 Args: 1026 document_ids: List of document IDs to modify. 1027 add_fields: Custom-field value dicts to add. 1028 remove_fields: Custom-field IDs whose values should be removed. 1029 """ 1030 logger.info("Bulk modifying custom fields on %d documents", len(document_ids)) 1031 await self._bulk_edit( 1032 document_ids, 1033 "modify_custom_fields", 1034 add_custom_fields=add_fields or [], 1035 remove_custom_fields=remove_fields or [], 1036 )
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.
1038 async def bulk_set_permissions( 1039 self, 1040 document_ids: List[int], 1041 *, 1042 set_permissions: SetPermissions | Unset = UNSET, 1043 owner: int | None | Unset = UNSET, 1044 merge: bool = False, 1045 ) -> None: 1046 """Set permissions and/or owner on multiple documents. 1047 1048 Args: 1049 document_ids: List of document IDs to modify. 1050 set_permissions: Explicit view/change permission sets. 1051 Omit (or pass :data:`~easypaperless.UNSET`) to leave unchanged. 1052 owner: Numeric user ID to assign as document owner. 1053 Pass ``None`` to clear the owner. 1054 Omit (or pass :data:`~easypaperless.UNSET`) to leave unchanged. 1055 merge: When ``True``, new permissions are merged with existing ones. 1056 """ 1057 logger.info("Bulk setting permissions on %d documents", len(document_ids)) 1058 params: dict[str, Any] = {"merge": merge} 1059 if not isinstance(set_permissions, Unset): 1060 params["set_permissions"] = set_permissions.model_dump() 1061 if not isinstance(owner, Unset): 1062 params["owner"] = owner 1063 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.
1065 async def bulk_download( 1066 self, 1067 document_ids: List[int], 1068 *, 1069 content: Literal["archive", "originals", "both"] = "archive", 1070 compression: Literal["none", "deflated", "bzip2", "lzma"] = "none", 1071 follow_formatting: bool = False, 1072 ) -> bytes: 1073 """Download multiple documents as a single ZIP archive. 1074 1075 Args: 1076 document_ids: List of document IDs to include in the ZIP. 1077 content: File variant to include. One of ``"archive"`` *(default)*, 1078 ``"originals"``, or ``"both"``. 1079 compression: ZIP compression algorithm. One of ``"none"`` *(default)*, 1080 ``"deflated"``, ``"bzip2"``, or ``"lzma"``. 1081 follow_formatting: When ``True``, filenames inside the ZIP follow 1082 the storage path formatting configured in paperless-ngx. 1083 Default: ``False``. 1084 1085 Returns: 1086 Raw bytes of the ZIP archive. 1087 """ 1088 logger.info( 1089 "Bulk downloading %d documents (content=%s, compression=%s)", 1090 len(document_ids), 1091 content, 1092 compression, 1093 ) 1094 payload: dict[str, Any] = { 1095 "documents": document_ids, 1096 "content": content, 1097 "compression": compression, 1098 "follow_formatting": follow_formatting, 1099 } 1100 resp = await self._core._session.post("/documents/bulk_download/", json=payload) 1101 return resp.content
Download multiple documents as a single ZIP archive.
Arguments:
- document_ids: List of document IDs to include in the ZIP.
- content: File variant to include. One of
"archive"(default),"originals", or"both". - compression: ZIP compression algorithm. One of
"none"(default),"deflated","bzip2", or"lzma". - follow_formatting: When
True, filenames inside the ZIP follow the storage path formatting configured in paperless-ngx. Default:False.
Returns:
Raw bytes of the ZIP archive.
44class NotesResource: 45 """Accessor for document notes: ``client.documents.notes``.""" 46 47 def __init__(self, core: _ClientCore) -> None: 48 self._core = core 49 50 async def list( 51 self, 52 document_id: int, 53 *, 54 page: int | None = None, 55 page_size: int | None = None, 56 ) -> PagedResult[DocumentNote]: 57 """Fetch notes attached to a document. 58 59 When ``page`` is ``None`` (the default), all pages are fetched 60 automatically and ``next`` / ``previous`` in the returned 61 :class:`~easypaperless.models.paged_result.PagedResult` are always 62 ``None``. When ``page`` is set to a specific integer, only that one 63 page is fetched and ``next`` / ``previous`` contain the raw API values. 64 65 Args: 66 document_id: Numeric ID of the document whose notes to retrieve. 67 page: Return only this specific page (1-based). 68 page_size: Number of results per page. 69 70 Returns: 71 :class:`~easypaperless.models.paged_result.PagedResult` of 72 :class:`~easypaperless.models.documents.DocumentNote` objects, 73 ordered by creation time. 74 75 Raises: 76 ~easypaperless.exceptions.NotFoundError: If no document exists 77 with that ID. 78 """ 79 logger.info("Listing notes for document id=%d", document_id) 80 path = f"/documents/{document_id}/notes/" 81 params: dict[str, Any] = {} 82 if page_size is not None: 83 params["page_size"] = page_size 84 if page is not None: 85 params["page"] = page 86 87 resp = await self._core._session.get(path, params=params or None) 88 data = resp.json() 89 90 if isinstance(data, list): 91 # The paperless-ngx notes endpoint returns a plain JSON array rather 92 # than a paginated envelope. Build a synthetic PagedResult so callers 93 # always receive a consistent return type regardless of API version. 94 notes = [DocumentNote.model_validate(item) for item in data] 95 note_ids = [n.id for n in notes if n.id is not None] 96 all_ids: list[int] | None = note_ids if note_ids else None 97 return PagedResult( 98 count=len(notes), 99 next=None, 100 previous=None, 101 all=all_ids, 102 results=notes, 103 ) 104 105 # Paginated dict envelope — forward-compatible with potential future API changes. 106 items: list[Any] = list(data.get("results", [])) 107 count: int = data.get("count", 0) 108 page_all_ids: list[int] | None = data.get("all") 109 110 if page is None: 111 next_url: str | None = data.get("next") 112 while next_url: 113 next_url = self._core._session._normalise_next_url(next_url) 114 page_resp = await self._core._session.get(next_url) 115 page_data = page_resp.json() 116 items.extend(page_data.get("results", [])) 117 next_url = page_data.get("next") 118 return PagedResult( 119 count=count, 120 next=None, 121 previous=None, 122 all=page_all_ids, 123 results=[DocumentNote.model_validate(item) for item in items], 124 ) 125 126 return cast( 127 PagedResult[DocumentNote], 128 PagedResult( 129 count=count, 130 next=data.get("next"), 131 previous=data.get("previous"), 132 all=page_all_ids, 133 results=[DocumentNote.model_validate(item) for item in items], 134 ), 135 ) 136 137 async def create(self, document_id: int, *, note: str) -> DocumentNote: 138 """Create a new note on a document. 139 140 Args: 141 document_id: Numeric ID of the document to annotate. 142 note: Text content of the note. 143 144 Returns: 145 The newly created :class:`~easypaperless.models.documents.DocumentNote`. 146 147 Raises: 148 ~easypaperless.exceptions.NotFoundError: If no document exists 149 with that ID. 150 """ 151 logger.info("Creating note for document id=%d", document_id) 152 resp = await self._core._session.post( 153 f"/documents/{document_id}/notes/", 154 json={"note": note}, 155 ) 156 data = resp.json() 157 if isinstance(data, list): 158 return DocumentNote.model_validate(data[-1]) 159 return DocumentNote.model_validate(data) 160 161 async def delete(self, document_id: int, note_id: int) -> None: 162 """Delete a note from a document. 163 164 Args: 165 document_id: Numeric ID of the document that owns the note. 166 note_id: Numeric ID of the note to delete. 167 168 Raises: 169 ~easypaperless.exceptions.NotFoundError: If no document or note 170 exists with the given IDs. 171 """ 172 logger.info("Deleting note id=%d from document id=%d", note_id, document_id) 173 await self._core._session.delete(f"/documents/{document_id}/notes/", params={"id": note_id})
Accessor for document notes: client.documents.notes.
50 async def list( 51 self, 52 document_id: int, 53 *, 54 page: int | None = None, 55 page_size: int | None = None, 56 ) -> PagedResult[DocumentNote]: 57 """Fetch notes attached to a document. 58 59 When ``page`` is ``None`` (the default), all pages are fetched 60 automatically and ``next`` / ``previous`` in the returned 61 :class:`~easypaperless.models.paged_result.PagedResult` are always 62 ``None``. When ``page`` is set to a specific integer, only that one 63 page is fetched and ``next`` / ``previous`` contain the raw API values. 64 65 Args: 66 document_id: Numeric ID of the document whose notes to retrieve. 67 page: Return only this specific page (1-based). 68 page_size: Number of results per page. 69 70 Returns: 71 :class:`~easypaperless.models.paged_result.PagedResult` of 72 :class:`~easypaperless.models.documents.DocumentNote` objects, 73 ordered by creation time. 74 75 Raises: 76 ~easypaperless.exceptions.NotFoundError: If no document exists 77 with that ID. 78 """ 79 logger.info("Listing notes for document id=%d", document_id) 80 path = f"/documents/{document_id}/notes/" 81 params: dict[str, Any] = {} 82 if page_size is not None: 83 params["page_size"] = page_size 84 if page is not None: 85 params["page"] = page 86 87 resp = await self._core._session.get(path, params=params or None) 88 data = resp.json() 89 90 if isinstance(data, list): 91 # The paperless-ngx notes endpoint returns a plain JSON array rather 92 # than a paginated envelope. Build a synthetic PagedResult so callers 93 # always receive a consistent return type regardless of API version. 94 notes = [DocumentNote.model_validate(item) for item in data] 95 note_ids = [n.id for n in notes if n.id is not None] 96 all_ids: list[int] | None = note_ids if note_ids else None 97 return PagedResult( 98 count=len(notes), 99 next=None, 100 previous=None, 101 all=all_ids, 102 results=notes, 103 ) 104 105 # Paginated dict envelope — forward-compatible with potential future API changes. 106 items: list[Any] = list(data.get("results", [])) 107 count: int = data.get("count", 0) 108 page_all_ids: list[int] | None = data.get("all") 109 110 if page is None: 111 next_url: str | None = data.get("next") 112 while next_url: 113 next_url = self._core._session._normalise_next_url(next_url) 114 page_resp = await self._core._session.get(next_url) 115 page_data = page_resp.json() 116 items.extend(page_data.get("results", [])) 117 next_url = page_data.get("next") 118 return PagedResult( 119 count=count, 120 next=None, 121 previous=None, 122 all=page_all_ids, 123 results=[DocumentNote.model_validate(item) for item in items], 124 ) 125 126 return cast( 127 PagedResult[DocumentNote], 128 PagedResult( 129 count=count, 130 next=data.get("next"), 131 previous=data.get("previous"), 132 all=page_all_ids, 133 results=[DocumentNote.model_validate(item) for item in items], 134 ), 135 )
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.
137 async def create(self, document_id: int, *, note: str) -> DocumentNote: 138 """Create a new note on a document. 139 140 Args: 141 document_id: Numeric ID of the document to annotate. 142 note: Text content of the note. 143 144 Returns: 145 The newly created :class:`~easypaperless.models.documents.DocumentNote`. 146 147 Raises: 148 ~easypaperless.exceptions.NotFoundError: If no document exists 149 with that ID. 150 """ 151 logger.info("Creating note for document id=%d", document_id) 152 resp = await self._core._session.post( 153 f"/documents/{document_id}/notes/", 154 json={"note": note}, 155 ) 156 data = resp.json() 157 if isinstance(data, list): 158 return DocumentNote.model_validate(data[-1]) 159 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.
161 async def delete(self, document_id: int, note_id: int) -> None: 162 """Delete a note from a document. 163 164 Args: 165 document_id: Numeric ID of the document that owns the note. 166 note_id: Numeric ID of the note to delete. 167 168 Raises: 169 ~easypaperless.exceptions.NotFoundError: If no document or note 170 exists with the given IDs. 171 """ 172 logger.info("Deleting note id=%d from document id=%d", note_id, document_id) 173 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 history( 100 self, 101 document_id: int, 102 *, 103 page: int | None = None, 104 page_size: int | None = None, 105 ) -> PagedResult[AuditLogEntry]: 106 """Fetch the audit log for a document. 107 108 The paperless-ngx ``/api/documents/{id}/history/`` endpoint returns a 109 plain JSON array rather than a paginated envelope. This method wraps 110 the response into a :class:`~easypaperless.models.paged_result.PagedResult` 111 so callers always receive a consistent return type. 112 113 Args: 114 document_id: Numeric ID of the document whose history to retrieve. 115 page: Forwarded to the API as a query parameter when provided. 116 Effect depends on the paperless-ngx version; the server may 117 ignore this parameter. 118 page_size: Forwarded to the API as a query parameter when provided. 119 120 Returns: 121 :class:`~easypaperless.models.paged_result.PagedResult` of 122 :class:`~easypaperless.models.documents.AuditLogEntry` objects, 123 ordered by timestamp descending. 124 125 Raises: 126 ~easypaperless.exceptions.NotFoundError: If no document exists 127 with that ID. 128 """ 129 return cast( 130 PagedResult[AuditLogEntry], 131 self._run(self._async_documents.history(document_id, page=page, page_size=page_size)), 132 ) 133 134 def get(self, id: int, *, include_metadata: bool = False) -> Document: 135 """Fetch a single document by its ID. 136 137 Args: 138 id: Numeric paperless-ngx document ID. 139 include_metadata: When ``True``, the extended file-level metadata 140 is fetched concurrently and attached to the document. 141 Default: ``False``. 142 143 Returns: 144 The :class:`~easypaperless.models.documents.Document` with the 145 given ID. 146 147 Raises: 148 ~easypaperless.exceptions.NotFoundError: If no document exists 149 with that ID. 150 """ 151 return cast( 152 Document, self._run(self._async_documents.get(id, include_metadata=include_metadata)) 153 ) 154 155 def get_metadata(self, id: int) -> DocumentMetadata: 156 """Fetch the extended file-level metadata for a document. 157 158 Args: 159 id: Numeric paperless-ngx document ID. 160 161 Returns: 162 A :class:`~easypaperless.models.documents.DocumentMetadata` instance. 163 164 Raises: 165 ~easypaperless.exceptions.NotFoundError: If no document exists 166 with that ID. 167 """ 168 return cast(DocumentMetadata, self._run(self._async_documents.get_metadata(id))) 169 170 def list( 171 self, 172 *, 173 search: str | None = None, 174 search_mode: str = "title_or_content", 175 ids: List[int] | None = None, 176 tags: List[int | str] | None = None, 177 any_tags: List[int | str] | None = None, 178 exclude_tags: List[int | str] | None = None, 179 correspondent: int | str | None | Unset = UNSET, 180 any_correspondent: List[int | str] | None = None, 181 exclude_correspondents: List[int | str] | None = None, 182 document_type: int | str | None | Unset = UNSET, 183 document_type_name_contains: str | None = None, 184 document_type_name_exact: str | None = None, 185 any_document_type: List[int | str] | None = None, 186 exclude_document_types: List[int | str] | None = None, 187 storage_path: int | str | None | Unset = UNSET, 188 any_storage_paths: List[int | str] | None = None, 189 exclude_storage_paths: List[int | str] | None = None, 190 owner: int | None | Unset = UNSET, 191 exclude_owners: List[int] | None = None, 192 custom_fields: List[int | str] | None = None, 193 any_custom_fields: List[int | str] | None = None, 194 exclude_custom_fields: List[int | str] | None = None, 195 custom_field_query: List[Any] | None = None, 196 archive_serial_number: int | None | Unset = UNSET, 197 archive_serial_number_from: int | None = None, 198 archive_serial_number_till: int | None = None, 199 created_after: date | str | None = None, 200 created_before: date | str | None = None, 201 added_after: date | datetime | str | None = None, 202 added_from: date | datetime | str | None = None, 203 added_before: date | datetime | str | None = None, 204 added_until: date | datetime | str | None = None, 205 modified_after: date | datetime | str | None = None, 206 modified_from: date | datetime | str | None = None, 207 modified_before: date | datetime | str | None = None, 208 modified_until: date | datetime | str | None = None, 209 checksum: str | None = None, 210 page_size: int = 25, 211 page: int | None = None, 212 ordering: str | None = None, 213 descending: bool = False, 214 max_results: int | None = None, 215 on_page: Callable[[int, int | None], None] | None = None, 216 ) -> PagedResult[Document]: 217 """Return a filtered list of documents. 218 219 All tag, correspondent, document-type, storage-path, and custom-field 220 parameters accept either integer IDs or string names. 221 222 When ``page`` is ``None`` (the default), all pages are fetched 223 automatically and ``next`` / ``previous`` in the returned 224 :class:`~easypaperless.models.paged_result.PagedResult` are always 225 ``None`` — even if ``max_results`` truncates the final result set. 226 ``count`` always reflects the server total, not the truncated length. 227 When ``page`` is set to a specific integer, only that one page is 228 fetched and ``next`` / ``previous`` contain the raw API values. 229 230 Args: 231 search: Search string. Behaviour depends on ``search_mode``. 232 search_mode: How ``search`` is applied. One of: 233 ``"title_or_content"`` *(default)*, ``"title"``, ``"query"``, 234 ``"original_filename"``. 235 ids: Return only documents whose ID is in this list. 236 tags: Documents must have **all** of these tags (AND semantics). 237 any_tags: Documents must have **at least one** of these tags. 238 exclude_tags: Documents must have **none** of these tags. 239 correspondent: Filter to documents assigned to this correspondent. 240 Pass ``None`` to return only documents with no correspondent set. 241 any_correspondent: Filter to documents assigned to any of these. 242 exclude_correspondents: Exclude documents assigned to any of these. 243 document_type: Filter to documents of exactly this type. 244 Pass ``None`` to return only documents with no document type set. 245 document_type_name_contains: Case-insensitive substring filter on document type name. 246 document_type_name_exact: Case-insensitive exact match on document type name. 247 any_document_type: Filter to documents whose type is any of these. 248 exclude_document_types: Exclude documents whose type is any of these. 249 storage_path: Filter to documents assigned to this storage path. 250 Pass ``None`` to return only documents with no storage path set. 251 any_storage_paths: Filter to documents assigned to any of these paths. 252 exclude_storage_paths: Exclude documents assigned to any of these paths. 253 owner: Filter to documents owned by this user ID. 254 Pass ``None`` to return only documents with no owner set. 255 exclude_owners: Exclude documents owned by any of these user IDs. 256 custom_fields: Documents must have **all** of these custom fields set. 257 any_custom_fields: Documents must have **at least one** of these fields. 258 exclude_custom_fields: Documents must have **none** of these fields. 259 custom_field_query: Filter documents by custom field values using a nested 260 query structure. See the `paperless-ngx API docs 261 <https://docs.paperless-ngx.com/api/#filtering-by-custom-fields>`_ for 262 the query format. 263 archive_serial_number: Filter by exact archive serial number. 264 Pass ``None`` to return only documents with no ASN set. 265 archive_serial_number_from: Filter by ASN >= this value. 266 archive_serial_number_till: Filter by ASN <= this value. 267 created_after: Only documents created after this date. 268 String input must be ISO-8601: ``"YYYY-MM-DD"``. 269 created_before: Only documents created before this date. 270 String input must be ISO-8601: ``"YYYY-MM-DD"``. 271 added_after: Only documents added after this date/time. 272 String input must be ISO-8601: ``"YYYY-MM-DD"`` for date precision or 273 ``"YYYY-MM-DDTHH:MM:SS"`` for datetime precision. 274 added_from: Only documents added on or after this date/time. 275 String input must be ISO-8601: ``"YYYY-MM-DD"`` or ``"YYYY-MM-DDTHH:MM:SS"``. 276 added_before: Only documents added before this date/time. 277 String input must be ISO-8601: ``"YYYY-MM-DD"`` or ``"YYYY-MM-DDTHH:MM:SS"``. 278 added_until: Only documents added on or before this date/time. 279 String input must be ISO-8601: ``"YYYY-MM-DD"`` or ``"YYYY-MM-DDTHH:MM:SS"``. 280 modified_after: Only documents modified after this date/time. 281 String input must be ISO-8601: ``"YYYY-MM-DD"`` or ``"YYYY-MM-DDTHH:MM:SS"``. 282 modified_from: Only documents modified on or after this date/time. 283 String input must be ISO-8601: ``"YYYY-MM-DD"`` or ``"YYYY-MM-DDTHH:MM:SS"``. 284 modified_before: Only documents modified before this date/time. 285 String input must be ISO-8601: ``"YYYY-MM-DD"`` or ``"YYYY-MM-DDTHH:MM:SS"``. 286 modified_until: Only documents modified on or before this date/time. 287 String input must be ISO-8601: ``"YYYY-MM-DD"`` or ``"YYYY-MM-DDTHH:MM:SS"``. 288 checksum: MD5 checksum of the original file (exact match). 289 page_size: Number of results per API page. Default: ``25``. 290 page: Return only this specific page (1-based). 291 ordering: Field name to sort by. 292 descending: When ``True``, reverses the sort direction. 293 max_results: Stop after collecting this many documents. 294 on_page: Callback invoked after each page fetch. 295 296 Returns: 297 :class:`~easypaperless.models.paged_result.PagedResult` of 298 :class:`~easypaperless.models.documents.Document` objects. 299 """ 300 return cast( 301 PagedResult[Document], 302 self._run( 303 self._async_documents.list( 304 search=search, 305 search_mode=search_mode, 306 ids=ids, 307 tags=tags, 308 any_tags=any_tags, 309 exclude_tags=exclude_tags, 310 correspondent=correspondent, 311 any_correspondent=any_correspondent, 312 exclude_correspondents=exclude_correspondents, 313 document_type=document_type, 314 document_type_name_contains=document_type_name_contains, 315 document_type_name_exact=document_type_name_exact, 316 any_document_type=any_document_type, 317 exclude_document_types=exclude_document_types, 318 storage_path=storage_path, 319 any_storage_paths=any_storage_paths, 320 exclude_storage_paths=exclude_storage_paths, 321 owner=owner, 322 exclude_owners=exclude_owners, 323 custom_fields=custom_fields, 324 any_custom_fields=any_custom_fields, 325 exclude_custom_fields=exclude_custom_fields, 326 custom_field_query=custom_field_query, 327 archive_serial_number=archive_serial_number, 328 archive_serial_number_from=archive_serial_number_from, 329 archive_serial_number_till=archive_serial_number_till, 330 created_after=created_after, 331 created_before=created_before, 332 added_after=added_after, 333 added_from=added_from, 334 added_before=added_before, 335 added_until=added_until, 336 modified_after=modified_after, 337 modified_from=modified_from, 338 modified_before=modified_before, 339 modified_until=modified_until, 340 checksum=checksum, 341 page_size=page_size, 342 page=page, 343 ordering=ordering, 344 descending=descending, 345 max_results=max_results, 346 on_page=on_page, 347 ) 348 ), 349 ) 350 351 def update( 352 self, 353 id: int, 354 *, 355 title: str | Unset = UNSET, 356 content: str | Unset = UNSET, 357 created: date | str | None | Unset = UNSET, 358 correspondent: int | str | None | Unset = UNSET, 359 document_type: int | str | None | Unset = UNSET, 360 storage_path: int | str | None | Unset = UNSET, 361 tags: List[int | str] | None | Unset = UNSET, 362 archive_serial_number: int | None | Unset = UNSET, 363 custom_fields: List[dict[str, Any]] | None | Unset = UNSET, 364 owner: int | None | Unset = UNSET, 365 set_permissions: SetPermissions | None | Unset = UNSET, 366 remove_inbox_tags: bool | None | Unset = UNSET, 367 ) -> Document: 368 """Partially update a document (PATCH semantics). 369 370 Args: 371 id: Numeric ID of the document to update. 372 title: New document title. 373 content: OCR text content of the document. 374 created: Creation date as an ISO-8601 string (``"YYYY-MM-DD"``) or a 375 :class:`~datetime.date` object. 376 correspondent: Correspondent to assign, as an ID or name. 377 Pass ``None`` to clear the correspondent. 378 document_type: Document type to assign, as an ID or name. 379 Pass ``None`` to clear the document type. 380 storage_path: Storage path to assign, as an ID or name. 381 Pass ``None`` to clear the storage path. 382 tags: Full replacement list of tags (IDs or names). 383 archive_serial_number: Archive serial number to assign. 384 Pass ``None`` to clear the archive serial number. 385 custom_fields: List of ``{"field": <field_id>, "value": ...}`` dicts. 386 owner: Numeric user ID to assign as document owner. 387 Pass ``None`` to clear the owner. 388 set_permissions: Explicit view/change permission sets. 389 Pass ``None`` to clear all permissions (overwrite with empty). 390 Omit (or pass :data:`~easypaperless.UNSET`) to leave unchanged. 391 remove_inbox_tags: When ``True``, removes all inbox tags from the document. 392 393 Returns: 394 The updated :class:`~easypaperless.models.documents.Document`. 395 """ 396 return cast( 397 Document, 398 self._run( 399 self._async_documents.update( 400 id, 401 title=title, 402 content=content, 403 created=created, 404 correspondent=correspondent, 405 document_type=document_type, 406 storage_path=storage_path, 407 tags=tags, 408 archive_serial_number=archive_serial_number, 409 custom_fields=custom_fields, 410 owner=owner, 411 set_permissions=set_permissions, 412 remove_inbox_tags=remove_inbox_tags, 413 ) 414 ), 415 ) 416 417 def delete(self, id: int) -> None: 418 """Permanently delete a document. 419 420 Args: 421 id: Numeric ID of the document to delete. 422 423 Raises: 424 ~easypaperless.exceptions.NotFoundError: If no document exists 425 with that ID. 426 """ 427 self._run(self._async_documents.delete(id)) 428 429 def download(self, id: int, *, original: bool = False) -> bytes: 430 """Download the binary content of a document. 431 432 Args: 433 id: Numeric ID of the document to download. 434 original: If ``False`` *(default)*, returns the archived PDF 435 (``GET /documents/{id}/download/``). 436 If ``True``, returns the original uploaded file 437 (``GET /documents/{id}/download/?original=true``). 438 439 Returns: 440 Raw file bytes. 441 """ 442 return cast(bytes, self._run(self._async_documents.download(id, original=original))) 443 444 def thumbnail(self, id: int) -> bytes: 445 """Fetch the thumbnail image of a document. 446 447 Args: 448 id: Numeric ID of the document whose thumbnail to retrieve. 449 450 Returns: 451 Raw binary content of the thumbnail image. 452 453 Raises: 454 ~easypaperless.exceptions.NotFoundError: If no document exists 455 with that ID. 456 ~easypaperless.exceptions.ServerError: If the server returns an 457 HTML page (e.g. an auth redirect) instead of the image. 458 """ 459 return cast(bytes, self._run(self._async_documents.thumbnail(id))) 460 461 def upload( 462 self, 463 file: str | Path, 464 *, 465 title: str | Unset = UNSET, 466 created: date | str | None = None, 467 correspondent: int | str | None | Unset = UNSET, 468 document_type: int | str | None | Unset = UNSET, 469 storage_path: int | str | None | Unset = UNSET, 470 tags: List[int | str] | None = None, 471 archive_serial_number: int | None | Unset = UNSET, 472 custom_fields: List[dict[str, Any]] | None = None, 473 wait: bool = False, 474 poll_interval: float | None = None, 475 poll_timeout: float | None = None, 476 ) -> str | Document: 477 """Upload a document to paperless-ngx. 478 479 Args: 480 file: Path to the file to upload. 481 title: Title to assign to the document. 482 created: Creation date as an ISO-8601 string (``"YYYY-MM-DD"``) or a 483 :class:`~datetime.date` object. 484 correspondent: Correspondent to assign, as an ID or name. 485 document_type: Document type to assign, as an ID or name. 486 storage_path: Storage path to assign, as an ID or name. 487 tags: Tags to assign, as IDs or names. 488 archive_serial_number: Archive serial number to assign. 489 custom_fields: List of ``{"field": <field_id>, "value": ...}`` dicts. 490 wait: If ``False`` *(default)*, returns immediately with the task ID. 491 If ``True``, polls until processing completes. 492 poll_interval: Seconds between task-status checks while waiting for 493 processing to complete (requires ``wait=True``). Overrides the 494 client-level default. When omitted, falls back to the client-level 495 ``poll_interval`` (``2.0`` s unless changed at construction). 496 poll_timeout: Maximum seconds to wait before raising 497 :exc:`~easypaperless.exceptions.TaskTimeoutError` (requires 498 ``wait=True``). Overrides the client-level default. When omitted, 499 falls back to the client-level ``poll_timeout`` (``60.0`` s unless 500 changed at construction). 501 502 Returns: 503 The Celery task ID string when ``wait=False``, or the fully 504 processed :class:`~easypaperless.models.documents.Document` 505 when ``wait=True``. 506 507 Raises: 508 ~easypaperless.exceptions.UploadError: If processing fails. 509 ~easypaperless.exceptions.TaskTimeoutError: If timeout is exceeded. 510 """ 511 return cast( 512 str | Document, 513 self._run( 514 self._async_documents.upload( 515 file, 516 title=title, 517 created=created, 518 correspondent=correspondent, 519 document_type=document_type, 520 storage_path=storage_path, 521 tags=tags, 522 archive_serial_number=archive_serial_number, 523 custom_fields=custom_fields, 524 wait=wait, 525 poll_interval=poll_interval, 526 poll_timeout=poll_timeout, 527 ) 528 ), 529 ) 530 531 def bulk_add_tag(self, document_ids: List[int], tag: int | str) -> None: 532 """Add a tag to multiple documents in a single request. 533 534 Args: 535 document_ids: List of document IDs to tag. 536 tag: Tag to add, as an ID or name. 537 """ 538 self._run(self._async_documents.bulk_add_tag(document_ids, tag)) 539 540 def bulk_remove_tag(self, document_ids: List[int], tag: int | str) -> None: 541 """Remove a tag from multiple documents in a single request. 542 543 Args: 544 document_ids: List of document IDs to un-tag. 545 tag: Tag to remove, as an ID or name. 546 """ 547 self._run(self._async_documents.bulk_remove_tag(document_ids, tag)) 548 549 def bulk_modify_tags( 550 self, 551 document_ids: List[int], 552 *, 553 add_tags: List[int | str] | None = None, 554 remove_tags: List[int | str] | None = None, 555 ) -> None: 556 """Add and/or remove tags on multiple documents atomically. 557 558 Args: 559 document_ids: List of document IDs to modify. 560 add_tags: Tags to add, as IDs or names. 561 remove_tags: Tags to remove, as IDs or names. 562 """ 563 self._run( 564 self._async_documents.bulk_modify_tags( 565 document_ids, add_tags=add_tags, remove_tags=remove_tags 566 ) 567 ) 568 569 def bulk_delete(self, document_ids: List[int]) -> None: 570 """Permanently delete multiple documents in a single request. 571 572 Args: 573 document_ids: List of document IDs to delete. 574 """ 575 self._run(self._async_documents.bulk_delete(document_ids)) 576 577 def bulk_set_correspondent( 578 self, document_ids: List[int], correspondent: int | str | None 579 ) -> None: 580 """Assign a correspondent to multiple documents in a single request. 581 582 Args: 583 document_ids: List of document IDs to modify. 584 correspondent: Correspondent to assign, as an ID or name. 585 Pass ``None`` to clear. 586 """ 587 self._run(self._async_documents.bulk_set_correspondent(document_ids, correspondent)) 588 589 def bulk_set_document_type( 590 self, document_ids: List[int], document_type: int | str | None 591 ) -> None: 592 """Assign a document type to multiple documents in a single request. 593 594 Args: 595 document_ids: List of document IDs to modify. 596 document_type: Document type to assign, as an ID or name. 597 Pass ``None`` to clear. 598 """ 599 self._run(self._async_documents.bulk_set_document_type(document_ids, document_type)) 600 601 def bulk_set_storage_path( 602 self, document_ids: List[int], storage_path: int | str | None 603 ) -> None: 604 """Assign a storage path to multiple documents in a single request. 605 606 Args: 607 document_ids: List of document IDs to modify. 608 storage_path: Storage path to assign, as an ID or name. 609 Pass ``None`` to clear. 610 """ 611 self._run(self._async_documents.bulk_set_storage_path(document_ids, storage_path)) 612 613 def bulk_modify_custom_fields( 614 self, 615 document_ids: List[int], 616 *, 617 add_fields: List[dict[str, Any]] | None = None, 618 remove_fields: List[int] | None = None, 619 ) -> None: 620 """Add and/or remove custom field values on multiple documents. 621 622 Args: 623 document_ids: List of document IDs to modify. 624 add_fields: Custom-field value dicts to add. 625 remove_fields: Custom-field IDs whose values should be removed. 626 """ 627 self._run( 628 self._async_documents.bulk_modify_custom_fields( 629 document_ids, add_fields=add_fields, remove_fields=remove_fields 630 ) 631 ) 632 633 def bulk_set_permissions( 634 self, 635 document_ids: List[int], 636 *, 637 set_permissions: SetPermissions | Unset = UNSET, 638 owner: int | None | Unset = UNSET, 639 merge: bool = False, 640 ) -> None: 641 """Set permissions and/or owner on multiple documents. 642 643 Args: 644 document_ids: List of document IDs to modify. 645 set_permissions: Explicit view/change permission sets. 646 Omit (or pass :data:`~easypaperless.UNSET`) to leave unchanged. 647 owner: Numeric user ID to assign as document owner. 648 Pass ``None`` to clear the owner. 649 Omit (or pass :data:`~easypaperless.UNSET`) to leave unchanged. 650 merge: When ``True``, new permissions are merged with existing ones. 651 """ 652 self._run( 653 self._async_documents.bulk_set_permissions( 654 document_ids, 655 set_permissions=set_permissions, 656 owner=owner, 657 merge=merge, 658 ) 659 ) 660 661 def bulk_download( 662 self, 663 document_ids: List[int], 664 *, 665 content: Literal["archive", "originals", "both"] = "archive", 666 compression: Literal["none", "deflated", "bzip2", "lzma"] = "none", 667 follow_formatting: bool = False, 668 ) -> bytes: 669 """Download multiple documents as a single ZIP archive. 670 671 Args: 672 document_ids: List of document IDs to include in the ZIP. 673 content: File variant to include. One of ``"archive"`` *(default)*, 674 ``"originals"``, or ``"both"``. 675 compression: ZIP compression algorithm. One of ``"none"`` *(default)*, 676 ``"deflated"``, ``"bzip2"``, or ``"lzma"``. 677 follow_formatting: When ``True``, filenames inside the ZIP follow 678 the storage path formatting configured in paperless-ngx. 679 Default: ``False``. 680 681 Returns: 682 Raw bytes of the ZIP archive. 683 """ 684 return cast( 685 bytes, 686 self._run( 687 self._async_documents.bulk_download( 688 document_ids, 689 content=content, 690 compression=compression, 691 follow_formatting=follow_formatting, 692 ) 693 ), 694 )
Sync accessor for documents: client.documents.
99 def history( 100 self, 101 document_id: int, 102 *, 103 page: int | None = None, 104 page_size: int | None = None, 105 ) -> PagedResult[AuditLogEntry]: 106 """Fetch the audit log for a document. 107 108 The paperless-ngx ``/api/documents/{id}/history/`` endpoint returns a 109 plain JSON array rather than a paginated envelope. This method wraps 110 the response into a :class:`~easypaperless.models.paged_result.PagedResult` 111 so callers always receive a consistent return type. 112 113 Args: 114 document_id: Numeric ID of the document whose history to retrieve. 115 page: Forwarded to the API as a query parameter when provided. 116 Effect depends on the paperless-ngx version; the server may 117 ignore this parameter. 118 page_size: Forwarded to the API as a query parameter when provided. 119 120 Returns: 121 :class:`~easypaperless.models.paged_result.PagedResult` of 122 :class:`~easypaperless.models.documents.AuditLogEntry` objects, 123 ordered by timestamp descending. 124 125 Raises: 126 ~easypaperless.exceptions.NotFoundError: If no document exists 127 with that ID. 128 """ 129 return cast( 130 PagedResult[AuditLogEntry], 131 self._run(self._async_documents.history(document_id, page=page, page_size=page_size)), 132 )
Fetch the audit log for a document.
The paperless-ngx /api/documents/{id}/history/ endpoint returns a
plain JSON array rather than a paginated envelope. This method wraps
the response into a ~easypaperless.models.paged_result.PagedResult
so callers always receive a consistent return type.
Arguments:
- document_id: Numeric ID of the document whose history to retrieve.
- page: Forwarded to the API as a query parameter when provided. Effect depends on the paperless-ngx version; the server may ignore this parameter.
- page_size: Forwarded to the API as a query parameter when provided.
Returns:
~easypaperless.models.paged_result.PagedResultof~easypaperless.models.documents.AuditLogEntryobjects, ordered by timestamp descending.
Raises:
- ~easypaperless.exceptions.NotFoundError: If no document exists with that ID.
134 def get(self, id: int, *, include_metadata: bool = False) -> Document: 135 """Fetch a single document by its ID. 136 137 Args: 138 id: Numeric paperless-ngx document ID. 139 include_metadata: When ``True``, the extended file-level metadata 140 is fetched concurrently and attached to the document. 141 Default: ``False``. 142 143 Returns: 144 The :class:`~easypaperless.models.documents.Document` with the 145 given ID. 146 147 Raises: 148 ~easypaperless.exceptions.NotFoundError: If no document exists 149 with that ID. 150 """ 151 return cast( 152 Document, self._run(self._async_documents.get(id, include_metadata=include_metadata)) 153 )
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.
155 def get_metadata(self, id: int) -> DocumentMetadata: 156 """Fetch the extended file-level metadata for a document. 157 158 Args: 159 id: Numeric paperless-ngx document ID. 160 161 Returns: 162 A :class:`~easypaperless.models.documents.DocumentMetadata` instance. 163 164 Raises: 165 ~easypaperless.exceptions.NotFoundError: If no document exists 166 with that ID. 167 """ 168 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.
170 def list( 171 self, 172 *, 173 search: str | None = None, 174 search_mode: str = "title_or_content", 175 ids: List[int] | None = None, 176 tags: List[int | str] | None = None, 177 any_tags: List[int | str] | None = None, 178 exclude_tags: List[int | str] | None = None, 179 correspondent: int | str | None | Unset = UNSET, 180 any_correspondent: List[int | str] | None = None, 181 exclude_correspondents: List[int | str] | None = None, 182 document_type: int | str | None | Unset = UNSET, 183 document_type_name_contains: str | None = None, 184 document_type_name_exact: str | None = None, 185 any_document_type: List[int | str] | None = None, 186 exclude_document_types: List[int | str] | None = None, 187 storage_path: int | str | None | Unset = UNSET, 188 any_storage_paths: List[int | str] | None = None, 189 exclude_storage_paths: List[int | str] | None = None, 190 owner: int | None | Unset = UNSET, 191 exclude_owners: List[int] | None = None, 192 custom_fields: List[int | str] | None = None, 193 any_custom_fields: List[int | str] | None = None, 194 exclude_custom_fields: List[int | str] | None = None, 195 custom_field_query: List[Any] | None = None, 196 archive_serial_number: int | None | Unset = UNSET, 197 archive_serial_number_from: int | None = None, 198 archive_serial_number_till: int | None = None, 199 created_after: date | str | None = None, 200 created_before: date | str | None = None, 201 added_after: date | datetime | str | None = None, 202 added_from: date | datetime | str | None = None, 203 added_before: date | datetime | str | None = None, 204 added_until: date | datetime | str | None = None, 205 modified_after: date | datetime | str | None = None, 206 modified_from: date | datetime | str | None = None, 207 modified_before: date | datetime | str | None = None, 208 modified_until: date | datetime | str | None = None, 209 checksum: str | None = None, 210 page_size: int = 25, 211 page: int | None = None, 212 ordering: str | None = None, 213 descending: bool = False, 214 max_results: int | None = None, 215 on_page: Callable[[int, int | None], None] | None = None, 216 ) -> PagedResult[Document]: 217 """Return a filtered list of documents. 218 219 All tag, correspondent, document-type, storage-path, and custom-field 220 parameters accept either integer IDs or string names. 221 222 When ``page`` is ``None`` (the default), all pages are fetched 223 automatically and ``next`` / ``previous`` in the returned 224 :class:`~easypaperless.models.paged_result.PagedResult` are always 225 ``None`` — even if ``max_results`` truncates the final result set. 226 ``count`` always reflects the server total, not the truncated length. 227 When ``page`` is set to a specific integer, only that one page is 228 fetched and ``next`` / ``previous`` contain the raw API values. 229 230 Args: 231 search: Search string. Behaviour depends on ``search_mode``. 232 search_mode: How ``search`` is applied. One of: 233 ``"title_or_content"`` *(default)*, ``"title"``, ``"query"``, 234 ``"original_filename"``. 235 ids: Return only documents whose ID is in this list. 236 tags: Documents must have **all** of these tags (AND semantics). 237 any_tags: Documents must have **at least one** of these tags. 238 exclude_tags: Documents must have **none** of these tags. 239 correspondent: Filter to documents assigned to this correspondent. 240 Pass ``None`` to return only documents with no correspondent set. 241 any_correspondent: Filter to documents assigned to any of these. 242 exclude_correspondents: Exclude documents assigned to any of these. 243 document_type: Filter to documents of exactly this type. 244 Pass ``None`` to return only documents with no document type set. 245 document_type_name_contains: Case-insensitive substring filter on document type name. 246 document_type_name_exact: Case-insensitive exact match on document type name. 247 any_document_type: Filter to documents whose type is any of these. 248 exclude_document_types: Exclude documents whose type is any of these. 249 storage_path: Filter to documents assigned to this storage path. 250 Pass ``None`` to return only documents with no storage path set. 251 any_storage_paths: Filter to documents assigned to any of these paths. 252 exclude_storage_paths: Exclude documents assigned to any of these paths. 253 owner: Filter to documents owned by this user ID. 254 Pass ``None`` to return only documents with no owner set. 255 exclude_owners: Exclude documents owned by any of these user IDs. 256 custom_fields: Documents must have **all** of these custom fields set. 257 any_custom_fields: Documents must have **at least one** of these fields. 258 exclude_custom_fields: Documents must have **none** of these fields. 259 custom_field_query: Filter documents by custom field values using a nested 260 query structure. See the `paperless-ngx API docs 261 <https://docs.paperless-ngx.com/api/#filtering-by-custom-fields>`_ for 262 the query format. 263 archive_serial_number: Filter by exact archive serial number. 264 Pass ``None`` to return only documents with no ASN set. 265 archive_serial_number_from: Filter by ASN >= this value. 266 archive_serial_number_till: Filter by ASN <= this value. 267 created_after: Only documents created after this date. 268 String input must be ISO-8601: ``"YYYY-MM-DD"``. 269 created_before: Only documents created before this date. 270 String input must be ISO-8601: ``"YYYY-MM-DD"``. 271 added_after: Only documents added after this date/time. 272 String input must be ISO-8601: ``"YYYY-MM-DD"`` for date precision or 273 ``"YYYY-MM-DDTHH:MM:SS"`` for datetime precision. 274 added_from: Only documents added on or after this date/time. 275 String input must be ISO-8601: ``"YYYY-MM-DD"`` or ``"YYYY-MM-DDTHH:MM:SS"``. 276 added_before: Only documents added before this date/time. 277 String input must be ISO-8601: ``"YYYY-MM-DD"`` or ``"YYYY-MM-DDTHH:MM:SS"``. 278 added_until: Only documents added on or before this date/time. 279 String input must be ISO-8601: ``"YYYY-MM-DD"`` or ``"YYYY-MM-DDTHH:MM:SS"``. 280 modified_after: Only documents modified after this date/time. 281 String input must be ISO-8601: ``"YYYY-MM-DD"`` or ``"YYYY-MM-DDTHH:MM:SS"``. 282 modified_from: Only documents modified on or after this date/time. 283 String input must be ISO-8601: ``"YYYY-MM-DD"`` or ``"YYYY-MM-DDTHH:MM:SS"``. 284 modified_before: Only documents modified before this date/time. 285 String input must be ISO-8601: ``"YYYY-MM-DD"`` or ``"YYYY-MM-DDTHH:MM:SS"``. 286 modified_until: Only documents modified on or before this date/time. 287 String input must be ISO-8601: ``"YYYY-MM-DD"`` or ``"YYYY-MM-DDTHH:MM:SS"``. 288 checksum: MD5 checksum of the original file (exact match). 289 page_size: Number of results per API page. Default: ``25``. 290 page: Return only this specific page (1-based). 291 ordering: Field name to sort by. 292 descending: When ``True``, reverses the sort direction. 293 max_results: Stop after collecting this many documents. 294 on_page: Callback invoked after each page fetch. 295 296 Returns: 297 :class:`~easypaperless.models.paged_result.PagedResult` of 298 :class:`~easypaperless.models.documents.Document` objects. 299 """ 300 return cast( 301 PagedResult[Document], 302 self._run( 303 self._async_documents.list( 304 search=search, 305 search_mode=search_mode, 306 ids=ids, 307 tags=tags, 308 any_tags=any_tags, 309 exclude_tags=exclude_tags, 310 correspondent=correspondent, 311 any_correspondent=any_correspondent, 312 exclude_correspondents=exclude_correspondents, 313 document_type=document_type, 314 document_type_name_contains=document_type_name_contains, 315 document_type_name_exact=document_type_name_exact, 316 any_document_type=any_document_type, 317 exclude_document_types=exclude_document_types, 318 storage_path=storage_path, 319 any_storage_paths=any_storage_paths, 320 exclude_storage_paths=exclude_storage_paths, 321 owner=owner, 322 exclude_owners=exclude_owners, 323 custom_fields=custom_fields, 324 any_custom_fields=any_custom_fields, 325 exclude_custom_fields=exclude_custom_fields, 326 custom_field_query=custom_field_query, 327 archive_serial_number=archive_serial_number, 328 archive_serial_number_from=archive_serial_number_from, 329 archive_serial_number_till=archive_serial_number_till, 330 created_after=created_after, 331 created_before=created_before, 332 added_after=added_after, 333 added_from=added_from, 334 added_before=added_before, 335 added_until=added_until, 336 modified_after=modified_after, 337 modified_from=modified_from, 338 modified_before=modified_before, 339 modified_until=modified_until, 340 checksum=checksum, 341 page_size=page_size, 342 page=page, 343 ordering=ordering, 344 descending=descending, 345 max_results=max_results, 346 on_page=on_page, 347 ) 348 ), 349 )
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.
351 def update( 352 self, 353 id: int, 354 *, 355 title: str | Unset = UNSET, 356 content: str | Unset = UNSET, 357 created: date | str | None | Unset = UNSET, 358 correspondent: int | str | None | Unset = UNSET, 359 document_type: int | str | None | Unset = UNSET, 360 storage_path: int | str | None | Unset = UNSET, 361 tags: List[int | str] | None | Unset = UNSET, 362 archive_serial_number: int | None | Unset = UNSET, 363 custom_fields: List[dict[str, Any]] | None | Unset = UNSET, 364 owner: int | None | Unset = UNSET, 365 set_permissions: SetPermissions | None | Unset = UNSET, 366 remove_inbox_tags: bool | None | Unset = UNSET, 367 ) -> Document: 368 """Partially update a document (PATCH semantics). 369 370 Args: 371 id: Numeric ID of the document to update. 372 title: New document title. 373 content: OCR text content of the document. 374 created: Creation date as an ISO-8601 string (``"YYYY-MM-DD"``) or a 375 :class:`~datetime.date` object. 376 correspondent: Correspondent to assign, as an ID or name. 377 Pass ``None`` to clear the correspondent. 378 document_type: Document type to assign, as an ID or name. 379 Pass ``None`` to clear the document type. 380 storage_path: Storage path to assign, as an ID or name. 381 Pass ``None`` to clear the storage path. 382 tags: Full replacement list of tags (IDs or names). 383 archive_serial_number: Archive serial number to assign. 384 Pass ``None`` to clear the archive serial number. 385 custom_fields: List of ``{"field": <field_id>, "value": ...}`` dicts. 386 owner: Numeric user ID to assign as document owner. 387 Pass ``None`` to clear the owner. 388 set_permissions: Explicit view/change permission sets. 389 Pass ``None`` to clear all permissions (overwrite with empty). 390 Omit (or pass :data:`~easypaperless.UNSET`) to leave unchanged. 391 remove_inbox_tags: When ``True``, removes all inbox tags from the document. 392 393 Returns: 394 The updated :class:`~easypaperless.models.documents.Document`. 395 """ 396 return cast( 397 Document, 398 self._run( 399 self._async_documents.update( 400 id, 401 title=title, 402 content=content, 403 created=created, 404 correspondent=correspondent, 405 document_type=document_type, 406 storage_path=storage_path, 407 tags=tags, 408 archive_serial_number=archive_serial_number, 409 custom_fields=custom_fields, 410 owner=owner, 411 set_permissions=set_permissions, 412 remove_inbox_tags=remove_inbox_tags, 413 ) 414 ), 415 )
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.
417 def delete(self, id: int) -> None: 418 """Permanently delete a document. 419 420 Args: 421 id: Numeric ID of the document to delete. 422 423 Raises: 424 ~easypaperless.exceptions.NotFoundError: If no document exists 425 with that ID. 426 """ 427 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.
429 def download(self, id: int, *, original: bool = False) -> bytes: 430 """Download the binary content of a document. 431 432 Args: 433 id: Numeric ID of the document to download. 434 original: If ``False`` *(default)*, returns the archived PDF 435 (``GET /documents/{id}/download/``). 436 If ``True``, returns the original uploaded file 437 (``GET /documents/{id}/download/?original=true``). 438 439 Returns: 440 Raw file bytes. 441 """ 442 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 (GET /documents/{id}/download/). IfTrue, returns the original uploaded file (GET /documents/{id}/download/?original=true).
Returns:
Raw file bytes.
444 def thumbnail(self, id: int) -> bytes: 445 """Fetch the thumbnail image of a document. 446 447 Args: 448 id: Numeric ID of the document whose thumbnail to retrieve. 449 450 Returns: 451 Raw binary content of the thumbnail image. 452 453 Raises: 454 ~easypaperless.exceptions.NotFoundError: If no document exists 455 with that ID. 456 ~easypaperless.exceptions.ServerError: If the server returns an 457 HTML page (e.g. an auth redirect) instead of the image. 458 """ 459 return cast(bytes, self._run(self._async_documents.thumbnail(id)))
Fetch the thumbnail image of a document.
Arguments:
- id: Numeric ID of the document whose thumbnail to retrieve.
Returns:
Raw binary content of the thumbnail image.
Raises:
- ~easypaperless.exceptions.NotFoundError: If no document exists with that ID.
- ~easypaperless.exceptions.ServerError: If the server returns an HTML page (e.g. an auth redirect) instead of the image.
461 def upload( 462 self, 463 file: str | Path, 464 *, 465 title: str | Unset = UNSET, 466 created: date | str | None = None, 467 correspondent: int | str | None | Unset = UNSET, 468 document_type: int | str | None | Unset = UNSET, 469 storage_path: int | str | None | Unset = UNSET, 470 tags: List[int | str] | None = None, 471 archive_serial_number: int | None | Unset = UNSET, 472 custom_fields: List[dict[str, Any]] | None = None, 473 wait: bool = False, 474 poll_interval: float | None = None, 475 poll_timeout: float | None = None, 476 ) -> str | Document: 477 """Upload a document to paperless-ngx. 478 479 Args: 480 file: Path to the file to upload. 481 title: Title to assign to the document. 482 created: Creation date as an ISO-8601 string (``"YYYY-MM-DD"``) or a 483 :class:`~datetime.date` object. 484 correspondent: Correspondent to assign, as an ID or name. 485 document_type: Document type to assign, as an ID or name. 486 storage_path: Storage path to assign, as an ID or name. 487 tags: Tags to assign, as IDs or names. 488 archive_serial_number: Archive serial number to assign. 489 custom_fields: List of ``{"field": <field_id>, "value": ...}`` dicts. 490 wait: If ``False`` *(default)*, returns immediately with the task ID. 491 If ``True``, polls until processing completes. 492 poll_interval: Seconds between task-status checks while waiting for 493 processing to complete (requires ``wait=True``). Overrides the 494 client-level default. When omitted, falls back to the client-level 495 ``poll_interval`` (``2.0`` s unless changed at construction). 496 poll_timeout: Maximum seconds to wait before raising 497 :exc:`~easypaperless.exceptions.TaskTimeoutError` (requires 498 ``wait=True``). Overrides the client-level default. When omitted, 499 falls back to the client-level ``poll_timeout`` (``60.0`` s unless 500 changed at construction). 501 502 Returns: 503 The Celery task ID string when ``wait=False``, or the fully 504 processed :class:`~easypaperless.models.documents.Document` 505 when ``wait=True``. 506 507 Raises: 508 ~easypaperless.exceptions.UploadError: If processing fails. 509 ~easypaperless.exceptions.TaskTimeoutError: If timeout is exceeded. 510 """ 511 return cast( 512 str | Document, 513 self._run( 514 self._async_documents.upload( 515 file, 516 title=title, 517 created=created, 518 correspondent=correspondent, 519 document_type=document_type, 520 storage_path=storage_path, 521 tags=tags, 522 archive_serial_number=archive_serial_number, 523 custom_fields=custom_fields, 524 wait=wait, 525 poll_interval=poll_interval, 526 poll_timeout=poll_timeout, 527 ) 528 ), 529 )
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.
531 def bulk_add_tag(self, document_ids: List[int], tag: int | str) -> None: 532 """Add a tag to multiple documents in a single request. 533 534 Args: 535 document_ids: List of document IDs to tag. 536 tag: Tag to add, as an ID or name. 537 """ 538 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.
540 def bulk_remove_tag(self, document_ids: List[int], tag: int | str) -> None: 541 """Remove a tag from multiple documents in a single request. 542 543 Args: 544 document_ids: List of document IDs to un-tag. 545 tag: Tag to remove, as an ID or name. 546 """ 547 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.
569 def bulk_delete(self, document_ids: List[int]) -> None: 570 """Permanently delete multiple documents in a single request. 571 572 Args: 573 document_ids: List of document IDs to delete. 574 """ 575 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.
577 def bulk_set_correspondent( 578 self, document_ids: List[int], correspondent: int | str | None 579 ) -> None: 580 """Assign a correspondent to multiple documents in a single request. 581 582 Args: 583 document_ids: List of document IDs to modify. 584 correspondent: Correspondent to assign, as an ID or name. 585 Pass ``None`` to clear. 586 """ 587 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.
589 def bulk_set_document_type( 590 self, document_ids: List[int], document_type: int | str | None 591 ) -> None: 592 """Assign a document type to multiple documents in a single request. 593 594 Args: 595 document_ids: List of document IDs to modify. 596 document_type: Document type to assign, as an ID or name. 597 Pass ``None`` to clear. 598 """ 599 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.
601 def bulk_set_storage_path( 602 self, document_ids: List[int], storage_path: int | str | None 603 ) -> None: 604 """Assign a storage path to multiple documents in a single request. 605 606 Args: 607 document_ids: List of document IDs to modify. 608 storage_path: Storage path to assign, as an ID or name. 609 Pass ``None`` to clear. 610 """ 611 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.
613 def bulk_modify_custom_fields( 614 self, 615 document_ids: List[int], 616 *, 617 add_fields: List[dict[str, Any]] | None = None, 618 remove_fields: List[int] | None = None, 619 ) -> None: 620 """Add and/or remove custom field values on multiple documents. 621 622 Args: 623 document_ids: List of document IDs to modify. 624 add_fields: Custom-field value dicts to add. 625 remove_fields: Custom-field IDs whose values should be removed. 626 """ 627 self._run( 628 self._async_documents.bulk_modify_custom_fields( 629 document_ids, add_fields=add_fields, remove_fields=remove_fields 630 ) 631 )
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.
633 def bulk_set_permissions( 634 self, 635 document_ids: List[int], 636 *, 637 set_permissions: SetPermissions | Unset = UNSET, 638 owner: int | None | Unset = UNSET, 639 merge: bool = False, 640 ) -> None: 641 """Set permissions and/or owner on multiple documents. 642 643 Args: 644 document_ids: List of document IDs to modify. 645 set_permissions: Explicit view/change permission sets. 646 Omit (or pass :data:`~easypaperless.UNSET`) to leave unchanged. 647 owner: Numeric user ID to assign as document owner. 648 Pass ``None`` to clear the owner. 649 Omit (or pass :data:`~easypaperless.UNSET`) to leave unchanged. 650 merge: When ``True``, new permissions are merged with existing ones. 651 """ 652 self._run( 653 self._async_documents.bulk_set_permissions( 654 document_ids, 655 set_permissions=set_permissions, 656 owner=owner, 657 merge=merge, 658 ) 659 )
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.
661 def bulk_download( 662 self, 663 document_ids: List[int], 664 *, 665 content: Literal["archive", "originals", "both"] = "archive", 666 compression: Literal["none", "deflated", "bzip2", "lzma"] = "none", 667 follow_formatting: bool = False, 668 ) -> bytes: 669 """Download multiple documents as a single ZIP archive. 670 671 Args: 672 document_ids: List of document IDs to include in the ZIP. 673 content: File variant to include. One of ``"archive"`` *(default)*, 674 ``"originals"``, or ``"both"``. 675 compression: ZIP compression algorithm. One of ``"none"`` *(default)*, 676 ``"deflated"``, ``"bzip2"``, or ``"lzma"``. 677 follow_formatting: When ``True``, filenames inside the ZIP follow 678 the storage path formatting configured in paperless-ngx. 679 Default: ``False``. 680 681 Returns: 682 Raw bytes of the ZIP archive. 683 """ 684 return cast( 685 bytes, 686 self._run( 687 self._async_documents.bulk_download( 688 document_ids, 689 content=content, 690 compression=compression, 691 follow_formatting=follow_formatting, 692 ) 693 ), 694 )
Download multiple documents as a single ZIP archive.
Arguments:
- document_ids: List of document IDs to include in the ZIP.
- content: File variant to include. One of
"archive"(default),"originals", or"both". - compression: ZIP compression algorithm. One of
"none"(default),"deflated","bzip2", or"lzma". - follow_formatting: When
True, filenames inside the ZIP follow the storage path formatting configured in paperless-ngx. Default:False.
Returns:
Raw bytes of the ZIP archive.
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.
20class UsersResource: 21 """Accessor for users: ``client.users``.""" 22 23 def __init__(self, core: _ClientCore) -> None: 24 self._core = core 25 26 async def list( 27 self, 28 *, 29 username_contains: str | Unset = UNSET, 30 username_exact: str | Unset = UNSET, 31 ordering: str | Unset = UNSET, 32 page: int | Unset = UNSET, 33 page_size: int | Unset = UNSET, 34 ) -> PagedResult[User]: 35 """Return users defined in paperless-ngx. 36 37 When ``page`` is ``UNSET`` (the default), all pages are fetched 38 automatically and ``next`` / ``previous`` in the result are always 39 ``None``. When ``page`` is set, only that page is fetched and 40 ``next`` / ``previous`` reflect the raw API values. 41 42 Args: 43 username_contains: Case-insensitive substring filter on username. 44 username_exact: Case-insensitive exact match on username. 45 ordering: Field to sort by. 46 page: Return only this specific page (1-based). 47 page_size: Number of results per page. 48 49 Returns: 50 :class:`~easypaperless.models.paged_result.PagedResult` of 51 :class:`~easypaperless.models.users.User` objects. 52 """ 53 logger.info("Listing users") 54 params: dict[str, Any] = {} 55 if not isinstance(username_contains, Unset): 56 params["username__icontains"] = username_contains 57 if not isinstance(username_exact, Unset): 58 params["username__iexact"] = username_exact 59 if not isinstance(ordering, Unset): 60 params["ordering"] = ordering 61 if not isinstance(page, Unset): 62 params["page"] = page 63 if not isinstance(page_size, Unset): 64 params["page_size"] = page_size 65 return cast( 66 PagedResult[User], 67 await self._core._list_resource("users", User, params or None), 68 ) 69 70 async def get(self, id: int) -> User: 71 """Fetch a single user by their ID. 72 73 Args: 74 id: Numeric user ID. 75 76 Returns: 77 The :class:`~easypaperless.models.users.User` with the given ID. 78 79 Raises: 80 ~easypaperless.exceptions.NotFoundError: If no user exists with 81 that ID. 82 """ 83 logger.info("Getting user id=%d", id) 84 return cast(User, await self._core._get_resource("users", id, User)) 85 86 async def create( 87 self, 88 *, 89 username: str, 90 email: str | Unset = UNSET, 91 password: str | Unset = UNSET, 92 first_name: str | Unset = UNSET, 93 last_name: str | Unset = UNSET, 94 date_joined: datetime | Unset = UNSET, 95 is_staff: bool | Unset = UNSET, 96 is_active: bool | Unset = UNSET, 97 is_superuser: bool | Unset = UNSET, 98 groups: List[int] | Unset = UNSET, 99 user_permissions: List[str] | Unset = UNSET, 100 ) -> User: 101 """Create a new user. 102 103 Args: 104 username: Login username. Must be unique. 105 email: Email address. 106 password: Password for the new account. 107 first_name: Given name. 108 last_name: Family name. 109 date_joined: Account creation timestamp. 110 is_staff: Grant staff (admin UI) access. 111 is_active: Whether the account is active. 112 is_superuser: Grant unrestricted superuser access. 113 groups: IDs of groups to assign the user to. 114 user_permissions: Directly assigned permission strings. 115 116 Returns: 117 The newly created :class:`~easypaperless.models.users.User`. 118 """ 119 logger.info("Creating user username=%r", username) 120 return cast( 121 User, 122 await self._core._create_resource( 123 "users", 124 User, 125 username=username, 126 email=email, 127 password=password, 128 first_name=first_name, 129 last_name=last_name, 130 date_joined=date_joined, 131 is_staff=is_staff, 132 is_active=is_active, 133 is_superuser=is_superuser, 134 groups=groups, 135 user_permissions=user_permissions, 136 ), 137 ) 138 139 async def update( 140 self, 141 id: int, 142 *, 143 username: str | Unset = UNSET, 144 email: str | Unset = UNSET, 145 password: str | Unset = UNSET, 146 first_name: str | Unset = UNSET, 147 last_name: str | Unset = UNSET, 148 date_joined: datetime | Unset = UNSET, 149 is_staff: bool | Unset = UNSET, 150 is_active: bool | Unset = UNSET, 151 is_superuser: bool | Unset = UNSET, 152 groups: List[int] | Unset = UNSET, 153 user_permissions: List[str] | Unset = UNSET, 154 ) -> User: 155 """Partially update a user (PATCH semantics). 156 157 Only fields with a non-:data:`~easypaperless.UNSET` value are included 158 in the request body. Omit a parameter (or pass 159 :data:`~easypaperless.UNSET`) to leave it unchanged. 160 161 Args: 162 id: Numeric ID of the user to update. 163 username: Login username. 164 email: Email address. 165 password: New password. 166 first_name: Given name. 167 last_name: Family name. 168 date_joined: Account creation timestamp. 169 is_staff: Grant or revoke staff access. 170 is_active: Activate or deactivate the account. 171 is_superuser: Grant or revoke superuser access. 172 groups: IDs of groups to assign the user to. 173 user_permissions: Directly assigned permission strings. 174 175 Returns: 176 The updated :class:`~easypaperless.models.users.User`. 177 """ 178 logger.info("Updating user id=%d", id) 179 return cast( 180 User, 181 await self._core._update_resource( 182 "users", 183 id, 184 User, 185 username=username, 186 email=email, 187 password=password, 188 first_name=first_name, 189 last_name=last_name, 190 date_joined=date_joined, 191 is_staff=is_staff, 192 is_active=is_active, 193 is_superuser=is_superuser, 194 groups=groups, 195 user_permissions=user_permissions, 196 ), 197 ) 198 199 async def delete(self, id: int) -> None: 200 """Delete a user. 201 202 Args: 203 id: Numeric ID of the user to delete. 204 205 Raises: 206 ~easypaperless.exceptions.NotFoundError: If no user exists with 207 that ID. 208 """ 209 logger.info("Deleting user id=%d", id) 210 await self._core._delete_resource("users", id)
Accessor for users: client.users.
26 async def list( 27 self, 28 *, 29 username_contains: str | Unset = UNSET, 30 username_exact: str | Unset = UNSET, 31 ordering: str | Unset = UNSET, 32 page: int | Unset = UNSET, 33 page_size: int | Unset = UNSET, 34 ) -> PagedResult[User]: 35 """Return users defined in paperless-ngx. 36 37 When ``page`` is ``UNSET`` (the default), all pages are fetched 38 automatically and ``next`` / ``previous`` in the result are always 39 ``None``. When ``page`` is set, only that page is fetched and 40 ``next`` / ``previous`` reflect the raw API values. 41 42 Args: 43 username_contains: Case-insensitive substring filter on username. 44 username_exact: Case-insensitive exact match on username. 45 ordering: Field to sort by. 46 page: Return only this specific page (1-based). 47 page_size: Number of results per page. 48 49 Returns: 50 :class:`~easypaperless.models.paged_result.PagedResult` of 51 :class:`~easypaperless.models.users.User` objects. 52 """ 53 logger.info("Listing users") 54 params: dict[str, Any] = {} 55 if not isinstance(username_contains, Unset): 56 params["username__icontains"] = username_contains 57 if not isinstance(username_exact, Unset): 58 params["username__iexact"] = username_exact 59 if not isinstance(ordering, Unset): 60 params["ordering"] = ordering 61 if not isinstance(page, Unset): 62 params["page"] = page 63 if not isinstance(page_size, Unset): 64 params["page_size"] = page_size 65 return cast( 66 PagedResult[User], 67 await self._core._list_resource("users", User, params or None), 68 )
Return users defined in paperless-ngx.
When page is UNSET (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:
- username_contains: Case-insensitive substring filter on username.
- username_exact: Case-insensitive exact match on username.
- ordering: Field to sort by.
- page: Return only this specific page (1-based).
- page_size: Number of results per page.
Returns:
~easypaperless.models.paged_result.PagedResultof~easypaperless.models.users.Userobjects.
70 async def get(self, id: int) -> User: 71 """Fetch a single user by their ID. 72 73 Args: 74 id: Numeric user ID. 75 76 Returns: 77 The :class:`~easypaperless.models.users.User` with the given ID. 78 79 Raises: 80 ~easypaperless.exceptions.NotFoundError: If no user exists with 81 that ID. 82 """ 83 logger.info("Getting user id=%d", id) 84 return cast(User, await self._core._get_resource("users", id, User))
Fetch a single user by their ID.
Arguments:
- id: Numeric user ID.
Returns:
The
~easypaperless.models.users.Userwith the given ID.
Raises:
- ~easypaperless.exceptions.NotFoundError: If no user exists with that ID.
86 async def create( 87 self, 88 *, 89 username: str, 90 email: str | Unset = UNSET, 91 password: str | Unset = UNSET, 92 first_name: str | Unset = UNSET, 93 last_name: str | Unset = UNSET, 94 date_joined: datetime | Unset = UNSET, 95 is_staff: bool | Unset = UNSET, 96 is_active: bool | Unset = UNSET, 97 is_superuser: bool | Unset = UNSET, 98 groups: List[int] | Unset = UNSET, 99 user_permissions: List[str] | Unset = UNSET, 100 ) -> User: 101 """Create a new user. 102 103 Args: 104 username: Login username. Must be unique. 105 email: Email address. 106 password: Password for the new account. 107 first_name: Given name. 108 last_name: Family name. 109 date_joined: Account creation timestamp. 110 is_staff: Grant staff (admin UI) access. 111 is_active: Whether the account is active. 112 is_superuser: Grant unrestricted superuser access. 113 groups: IDs of groups to assign the user to. 114 user_permissions: Directly assigned permission strings. 115 116 Returns: 117 The newly created :class:`~easypaperless.models.users.User`. 118 """ 119 logger.info("Creating user username=%r", username) 120 return cast( 121 User, 122 await self._core._create_resource( 123 "users", 124 User, 125 username=username, 126 email=email, 127 password=password, 128 first_name=first_name, 129 last_name=last_name, 130 date_joined=date_joined, 131 is_staff=is_staff, 132 is_active=is_active, 133 is_superuser=is_superuser, 134 groups=groups, 135 user_permissions=user_permissions, 136 ), 137 )
Create a new user.
Arguments:
- username: Login username. Must be unique.
- email: Email address.
- password: Password for the new account.
- first_name: Given name.
- last_name: Family name.
- date_joined: Account creation timestamp.
- is_staff: Grant staff (admin UI) access.
- is_active: Whether the account is active.
- is_superuser: Grant unrestricted superuser access.
- groups: IDs of groups to assign the user to.
- user_permissions: Directly assigned permission strings.
Returns:
The newly created
~easypaperless.models.users.User.
139 async def update( 140 self, 141 id: int, 142 *, 143 username: str | Unset = UNSET, 144 email: str | Unset = UNSET, 145 password: str | Unset = UNSET, 146 first_name: str | Unset = UNSET, 147 last_name: str | Unset = UNSET, 148 date_joined: datetime | Unset = UNSET, 149 is_staff: bool | Unset = UNSET, 150 is_active: bool | Unset = UNSET, 151 is_superuser: bool | Unset = UNSET, 152 groups: List[int] | Unset = UNSET, 153 user_permissions: List[str] | Unset = UNSET, 154 ) -> User: 155 """Partially update a user (PATCH semantics). 156 157 Only fields with a non-:data:`~easypaperless.UNSET` value are included 158 in the request body. Omit a parameter (or pass 159 :data:`~easypaperless.UNSET`) to leave it unchanged. 160 161 Args: 162 id: Numeric ID of the user to update. 163 username: Login username. 164 email: Email address. 165 password: New password. 166 first_name: Given name. 167 last_name: Family name. 168 date_joined: Account creation timestamp. 169 is_staff: Grant or revoke staff access. 170 is_active: Activate or deactivate the account. 171 is_superuser: Grant or revoke superuser access. 172 groups: IDs of groups to assign the user to. 173 user_permissions: Directly assigned permission strings. 174 175 Returns: 176 The updated :class:`~easypaperless.models.users.User`. 177 """ 178 logger.info("Updating user id=%d", id) 179 return cast( 180 User, 181 await self._core._update_resource( 182 "users", 183 id, 184 User, 185 username=username, 186 email=email, 187 password=password, 188 first_name=first_name, 189 last_name=last_name, 190 date_joined=date_joined, 191 is_staff=is_staff, 192 is_active=is_active, 193 is_superuser=is_superuser, 194 groups=groups, 195 user_permissions=user_permissions, 196 ), 197 )
Partially update a user (PATCH semantics).
Only fields with a non-~easypaperless.UNSET value are included
in the request body. Omit a parameter (or pass
~easypaperless.UNSET) to leave it unchanged.
Arguments:
- id: Numeric ID of the user to update.
- username: Login username.
- email: Email address.
- password: New password.
- first_name: Given name.
- last_name: Family name.
- date_joined: Account creation timestamp.
- is_staff: Grant or revoke staff access.
- is_active: Activate or deactivate the account.
- is_superuser: Grant or revoke superuser access.
- groups: IDs of groups to assign the user to.
- user_permissions: Directly assigned permission strings.
Returns:
The updated
~easypaperless.models.users.User.
199 async def delete(self, id: int) -> None: 200 """Delete a user. 201 202 Args: 203 id: Numeric ID of the user to delete. 204 205 Raises: 206 ~easypaperless.exceptions.NotFoundError: If no user exists with 207 that ID. 208 """ 209 logger.info("Deleting user id=%d", id) 210 await self._core._delete_resource("users", id)
Delete a user.
Arguments:
- id: Numeric ID of the user to delete.
Raises:
- ~easypaperless.exceptions.NotFoundError: If no user exists with that ID.
17class SyncUsersResource: 18 """Sync accessor for users: ``client.users``.""" 19 20 def __init__(self, async_users: UsersResource, run: Any) -> None: 21 self._async_users = async_users 22 self._run = run 23 24 def list( 25 self, 26 *, 27 username_contains: str | Unset = UNSET, 28 username_exact: str | Unset = UNSET, 29 ordering: str | Unset = UNSET, 30 page: int | Unset = UNSET, 31 page_size: int | Unset = UNSET, 32 ) -> PagedResult[User]: 33 """Return users defined in paperless-ngx. 34 35 When ``page`` is ``UNSET`` (the default), all pages are fetched 36 automatically and ``next`` / ``previous`` in the result are always 37 ``None``. When ``page`` is set, only that page is fetched and 38 ``next`` / ``previous`` reflect the raw API values. 39 40 Args: 41 username_contains: Case-insensitive substring filter on username. 42 username_exact: Case-insensitive exact match on username. 43 ordering: Field to sort by. 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.users.User` objects. 50 """ 51 return cast( 52 PagedResult[User], 53 self._run( 54 self._async_users.list( 55 username_contains=username_contains, 56 username_exact=username_exact, 57 ordering=ordering, 58 page=page, 59 page_size=page_size, 60 ) 61 ), 62 ) 63 64 def get(self, id: int) -> User: 65 """Fetch a single user by their ID. 66 67 Args: 68 id: Numeric user ID. 69 70 Returns: 71 The :class:`~easypaperless.models.users.User` with the given ID. 72 73 Raises: 74 ~easypaperless.exceptions.NotFoundError: If no user exists with 75 that ID. 76 """ 77 return cast(User, self._run(self._async_users.get(id))) 78 79 def create( 80 self, 81 *, 82 username: str, 83 email: str | Unset = UNSET, 84 password: str | Unset = UNSET, 85 first_name: str | Unset = UNSET, 86 last_name: str | Unset = UNSET, 87 date_joined: datetime | Unset = UNSET, 88 is_staff: bool | Unset = UNSET, 89 is_active: bool | Unset = UNSET, 90 is_superuser: bool | Unset = UNSET, 91 groups: List[int] | Unset = UNSET, 92 user_permissions: List[str] | Unset = UNSET, 93 ) -> User: 94 """Create a new user. 95 96 Args: 97 username: Login username. Must be unique. 98 email: Email address. 99 password: Password for the new account. 100 first_name: Given name. 101 last_name: Family name. 102 date_joined: Account creation timestamp. 103 is_staff: Grant staff (admin UI) access. 104 is_active: Whether the account is active. 105 is_superuser: Grant unrestricted superuser access. 106 groups: IDs of groups to assign the user to. 107 user_permissions: Directly assigned permission strings. 108 109 Returns: 110 The newly created :class:`~easypaperless.models.users.User`. 111 """ 112 return cast( 113 User, 114 self._run( 115 self._async_users.create( 116 username=username, 117 email=email, 118 password=password, 119 first_name=first_name, 120 last_name=last_name, 121 date_joined=date_joined, 122 is_staff=is_staff, 123 is_active=is_active, 124 is_superuser=is_superuser, 125 groups=groups, 126 user_permissions=user_permissions, 127 ) 128 ), 129 ) 130 131 def update( 132 self, 133 id: int, 134 *, 135 username: str | Unset = UNSET, 136 email: str | Unset = UNSET, 137 password: str | Unset = UNSET, 138 first_name: str | Unset = UNSET, 139 last_name: str | Unset = UNSET, 140 date_joined: datetime | Unset = UNSET, 141 is_staff: bool | Unset = UNSET, 142 is_active: bool | Unset = UNSET, 143 is_superuser: bool | Unset = UNSET, 144 groups: List[int] | Unset = UNSET, 145 user_permissions: List[str] | Unset = UNSET, 146 ) -> User: 147 """Partially update a user (PATCH semantics). 148 149 Only fields with a non-:data:`~easypaperless.UNSET` value are included 150 in the request body. Omit a parameter (or pass 151 :data:`~easypaperless.UNSET`) to leave it unchanged. 152 153 Args: 154 id: Numeric ID of the user to update. 155 username: Login username. 156 email: Email address. 157 password: New password. 158 first_name: Given name. 159 last_name: Family name. 160 date_joined: Account creation timestamp. 161 is_staff: Grant or revoke staff access. 162 is_active: Activate or deactivate the account. 163 is_superuser: Grant or revoke superuser access. 164 groups: IDs of groups to assign the user to. 165 user_permissions: Directly assigned permission strings. 166 167 Returns: 168 The updated :class:`~easypaperless.models.users.User`. 169 """ 170 return cast( 171 User, 172 self._run( 173 self._async_users.update( 174 id, 175 username=username, 176 email=email, 177 password=password, 178 first_name=first_name, 179 last_name=last_name, 180 date_joined=date_joined, 181 is_staff=is_staff, 182 is_active=is_active, 183 is_superuser=is_superuser, 184 groups=groups, 185 user_permissions=user_permissions, 186 ) 187 ), 188 ) 189 190 def delete(self, id: int) -> None: 191 """Delete a user. 192 193 Args: 194 id: Numeric ID of the user to delete. 195 196 Raises: 197 ~easypaperless.exceptions.NotFoundError: If no user exists with 198 that ID. 199 """ 200 self._run(self._async_users.delete(id))
Sync accessor for users: client.users.
24 def list( 25 self, 26 *, 27 username_contains: str | Unset = UNSET, 28 username_exact: str | Unset = UNSET, 29 ordering: str | Unset = UNSET, 30 page: int | Unset = UNSET, 31 page_size: int | Unset = UNSET, 32 ) -> PagedResult[User]: 33 """Return users defined in paperless-ngx. 34 35 When ``page`` is ``UNSET`` (the default), all pages are fetched 36 automatically and ``next`` / ``previous`` in the result are always 37 ``None``. When ``page`` is set, only that page is fetched and 38 ``next`` / ``previous`` reflect the raw API values. 39 40 Args: 41 username_contains: Case-insensitive substring filter on username. 42 username_exact: Case-insensitive exact match on username. 43 ordering: Field to sort by. 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.users.User` objects. 50 """ 51 return cast( 52 PagedResult[User], 53 self._run( 54 self._async_users.list( 55 username_contains=username_contains, 56 username_exact=username_exact, 57 ordering=ordering, 58 page=page, 59 page_size=page_size, 60 ) 61 ), 62 )
Return users defined in paperless-ngx.
When page is UNSET (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:
- username_contains: Case-insensitive substring filter on username.
- username_exact: Case-insensitive exact match on username.
- ordering: Field to sort by.
- page: Return only this specific page (1-based).
- page_size: Number of results per page.
Returns:
~easypaperless.models.paged_result.PagedResultof~easypaperless.models.users.Userobjects.
64 def get(self, id: int) -> User: 65 """Fetch a single user by their ID. 66 67 Args: 68 id: Numeric user ID. 69 70 Returns: 71 The :class:`~easypaperless.models.users.User` with the given ID. 72 73 Raises: 74 ~easypaperless.exceptions.NotFoundError: If no user exists with 75 that ID. 76 """ 77 return cast(User, self._run(self._async_users.get(id)))
Fetch a single user by their ID.
Arguments:
- id: Numeric user ID.
Returns:
The
~easypaperless.models.users.Userwith the given ID.
Raises:
- ~easypaperless.exceptions.NotFoundError: If no user exists with that ID.
79 def create( 80 self, 81 *, 82 username: str, 83 email: str | Unset = UNSET, 84 password: str | Unset = UNSET, 85 first_name: str | Unset = UNSET, 86 last_name: str | Unset = UNSET, 87 date_joined: datetime | Unset = UNSET, 88 is_staff: bool | Unset = UNSET, 89 is_active: bool | Unset = UNSET, 90 is_superuser: bool | Unset = UNSET, 91 groups: List[int] | Unset = UNSET, 92 user_permissions: List[str] | Unset = UNSET, 93 ) -> User: 94 """Create a new user. 95 96 Args: 97 username: Login username. Must be unique. 98 email: Email address. 99 password: Password for the new account. 100 first_name: Given name. 101 last_name: Family name. 102 date_joined: Account creation timestamp. 103 is_staff: Grant staff (admin UI) access. 104 is_active: Whether the account is active. 105 is_superuser: Grant unrestricted superuser access. 106 groups: IDs of groups to assign the user to. 107 user_permissions: Directly assigned permission strings. 108 109 Returns: 110 The newly created :class:`~easypaperless.models.users.User`. 111 """ 112 return cast( 113 User, 114 self._run( 115 self._async_users.create( 116 username=username, 117 email=email, 118 password=password, 119 first_name=first_name, 120 last_name=last_name, 121 date_joined=date_joined, 122 is_staff=is_staff, 123 is_active=is_active, 124 is_superuser=is_superuser, 125 groups=groups, 126 user_permissions=user_permissions, 127 ) 128 ), 129 )
Create a new user.
Arguments:
- username: Login username. Must be unique.
- email: Email address.
- password: Password for the new account.
- first_name: Given name.
- last_name: Family name.
- date_joined: Account creation timestamp.
- is_staff: Grant staff (admin UI) access.
- is_active: Whether the account is active.
- is_superuser: Grant unrestricted superuser access.
- groups: IDs of groups to assign the user to.
- user_permissions: Directly assigned permission strings.
Returns:
The newly created
~easypaperless.models.users.User.
131 def update( 132 self, 133 id: int, 134 *, 135 username: str | Unset = UNSET, 136 email: str | Unset = UNSET, 137 password: str | Unset = UNSET, 138 first_name: str | Unset = UNSET, 139 last_name: str | Unset = UNSET, 140 date_joined: datetime | Unset = UNSET, 141 is_staff: bool | Unset = UNSET, 142 is_active: bool | Unset = UNSET, 143 is_superuser: bool | Unset = UNSET, 144 groups: List[int] | Unset = UNSET, 145 user_permissions: List[str] | Unset = UNSET, 146 ) -> User: 147 """Partially update a user (PATCH semantics). 148 149 Only fields with a non-:data:`~easypaperless.UNSET` value are included 150 in the request body. Omit a parameter (or pass 151 :data:`~easypaperless.UNSET`) to leave it unchanged. 152 153 Args: 154 id: Numeric ID of the user to update. 155 username: Login username. 156 email: Email address. 157 password: New password. 158 first_name: Given name. 159 last_name: Family name. 160 date_joined: Account creation timestamp. 161 is_staff: Grant or revoke staff access. 162 is_active: Activate or deactivate the account. 163 is_superuser: Grant or revoke superuser access. 164 groups: IDs of groups to assign the user to. 165 user_permissions: Directly assigned permission strings. 166 167 Returns: 168 The updated :class:`~easypaperless.models.users.User`. 169 """ 170 return cast( 171 User, 172 self._run( 173 self._async_users.update( 174 id, 175 username=username, 176 email=email, 177 password=password, 178 first_name=first_name, 179 last_name=last_name, 180 date_joined=date_joined, 181 is_staff=is_staff, 182 is_active=is_active, 183 is_superuser=is_superuser, 184 groups=groups, 185 user_permissions=user_permissions, 186 ) 187 ), 188 )
Partially update a user (PATCH semantics).
Only fields with a non-~easypaperless.UNSET value are included
in the request body. Omit a parameter (or pass
~easypaperless.UNSET) to leave it unchanged.
Arguments:
- id: Numeric ID of the user to update.
- username: Login username.
- email: Email address.
- password: New password.
- first_name: Given name.
- last_name: Family name.
- date_joined: Account creation timestamp.
- is_staff: Grant or revoke staff access.
- is_active: Activate or deactivate the account.
- is_superuser: Grant or revoke superuser access.
- groups: IDs of groups to assign the user to.
- user_permissions: Directly assigned permission strings.
Returns:
The updated
~easypaperless.models.users.User.
190 def delete(self, id: int) -> None: 191 """Delete a user. 192 193 Args: 194 id: Numeric ID of the user to delete. 195 196 Raises: 197 ~easypaperless.exceptions.NotFoundError: If no user exists with 198 that ID. 199 """ 200 self._run(self._async_users.delete(id))
Delete a user.
Arguments:
- id: Numeric ID of the user to delete.
Raises:
- ~easypaperless.exceptions.NotFoundError: If no user exists with that ID.
19class TrashResource: 20 """Accessor for the trash bin: ``client.trash``.""" 21 22 def __init__(self, core: _ClientCore) -> None: 23 self._core = core 24 25 async def list( 26 self, 27 *, 28 page: int | Unset = UNSET, 29 page_size: int | Unset = UNSET, 30 ) -> PagedResult[Document]: 31 """Return all documents currently in the trash. 32 33 When ``page`` is ``UNSET`` (the default), all pages are fetched 34 automatically and ``next`` / ``previous`` in the result are always 35 ``None``. When ``page`` is set, only that page is fetched and 36 ``next`` / ``previous`` reflect the raw API values. 37 38 Args: 39 page: Return only this specific page (1-based). 40 page_size: Number of results per page. 41 42 Returns: 43 :class:`~easypaperless.models.paged_result.PagedResult` of 44 :class:`~easypaperless.models.documents.Document` objects currently 45 in the trash. 46 """ 47 logger.info("Listing trashed documents") 48 params: dict[str, Any] = {} 49 if not isinstance(page, Unset): 50 params["page"] = page 51 if not isinstance(page_size, Unset): 52 params["page_size"] = page_size 53 return cast( 54 PagedResult[Document], 55 await self._core._list_resource("trash", Document, params or None), 56 ) 57 58 async def restore(self, document_ids: List[int]) -> None: 59 """Restore trashed documents back to active status. 60 61 Args: 62 document_ids: List of numeric document IDs to restore. 63 """ 64 logger.info("Restoring %d trashed document(s)", len(document_ids)) 65 await self._core._session.post( 66 "/trash/", 67 json={"documents": document_ids, "action": "restore"}, 68 ) 69 70 async def empty(self, document_ids: List[int]) -> None: 71 """Permanently delete trashed documents. 72 73 .. warning:: 74 **This operation is irreversible and cannot be undone.** 75 The documents will be permanently removed and cannot be recovered. 76 77 Args: 78 document_ids: List of numeric document IDs to permanently delete. 79 """ 80 logger.info("Permanently deleting %d trashed document(s)", len(document_ids)) 81 await self._core._session.post( 82 "/trash/", 83 json={"documents": document_ids, "action": "empty"}, 84 )
Accessor for the trash bin: client.trash.
25 async def list( 26 self, 27 *, 28 page: int | Unset = UNSET, 29 page_size: int | Unset = UNSET, 30 ) -> PagedResult[Document]: 31 """Return all documents currently in the trash. 32 33 When ``page`` is ``UNSET`` (the default), all pages are fetched 34 automatically and ``next`` / ``previous`` in the result are always 35 ``None``. When ``page`` is set, only that page is fetched and 36 ``next`` / ``previous`` reflect the raw API values. 37 38 Args: 39 page: Return only this specific page (1-based). 40 page_size: Number of results per page. 41 42 Returns: 43 :class:`~easypaperless.models.paged_result.PagedResult` of 44 :class:`~easypaperless.models.documents.Document` objects currently 45 in the trash. 46 """ 47 logger.info("Listing trashed documents") 48 params: dict[str, Any] = {} 49 if not isinstance(page, Unset): 50 params["page"] = page 51 if not isinstance(page_size, Unset): 52 params["page_size"] = page_size 53 return cast( 54 PagedResult[Document], 55 await self._core._list_resource("trash", Document, params or None), 56 )
Return all documents currently in the trash.
When page is UNSET (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:
- page: Return only this specific page (1-based).
- page_size: Number of results per page.
Returns:
~easypaperless.models.paged_result.PagedResultof~easypaperless.models.documents.Documentobjects currently in the trash.
58 async def restore(self, document_ids: List[int]) -> None: 59 """Restore trashed documents back to active status. 60 61 Args: 62 document_ids: List of numeric document IDs to restore. 63 """ 64 logger.info("Restoring %d trashed document(s)", len(document_ids)) 65 await self._core._session.post( 66 "/trash/", 67 json={"documents": document_ids, "action": "restore"}, 68 )
Restore trashed documents back to active status.
Arguments:
- document_ids: List of numeric document IDs to restore.
70 async def empty(self, document_ids: List[int]) -> None: 71 """Permanently delete trashed documents. 72 73 .. warning:: 74 **This operation is irreversible and cannot be undone.** 75 The documents will be permanently removed and cannot be recovered. 76 77 Args: 78 document_ids: List of numeric document IDs to permanently delete. 79 """ 80 logger.info("Permanently deleting %d trashed document(s)", len(document_ids)) 81 await self._core._session.post( 82 "/trash/", 83 json={"documents": document_ids, "action": "empty"}, 84 )
Permanently delete trashed documents.
This operation is irreversible and cannot be undone. The documents will be permanently removed and cannot be recovered.
Arguments:
- document_ids: List of numeric document IDs to permanently delete.
16class SyncTrashResource: 17 """Sync accessor for the trash bin: ``client.trash``.""" 18 19 def __init__(self, async_trash: TrashResource, run: Any) -> None: 20 self._async_trash = async_trash 21 self._run = run 22 23 def list( 24 self, 25 *, 26 page: int | Unset = UNSET, 27 page_size: int | Unset = UNSET, 28 ) -> PagedResult[Document]: 29 """Return all documents currently in the trash. 30 31 When ``page`` is ``UNSET`` (the default), all pages are fetched 32 automatically and ``next`` / ``previous`` in the result are always 33 ``None``. When ``page`` is set, only that page is fetched and 34 ``next`` / ``previous`` reflect the raw API values. 35 36 Args: 37 page: Return only this specific page (1-based). 38 page_size: Number of results per page. 39 40 Returns: 41 :class:`~easypaperless.models.paged_result.PagedResult` of 42 :class:`~easypaperless.models.documents.Document` objects currently 43 in the trash. 44 """ 45 return cast( 46 PagedResult[Document], 47 self._run(self._async_trash.list(page=page, page_size=page_size)), 48 ) 49 50 def restore(self, document_ids: List[int]) -> None: 51 """Restore trashed documents back to active status. 52 53 Args: 54 document_ids: List of numeric document IDs to restore. 55 """ 56 self._run(self._async_trash.restore(document_ids)) 57 58 def empty(self, document_ids: List[int]) -> None: 59 """Permanently delete trashed documents. 60 61 .. warning:: 62 **This operation is irreversible and cannot be undone.** 63 The documents will be permanently removed and cannot be recovered. 64 65 Args: 66 document_ids: List of numeric document IDs to permanently delete. 67 """ 68 self._run(self._async_trash.empty(document_ids))
Sync accessor for the trash bin: client.trash.
23 def list( 24 self, 25 *, 26 page: int | Unset = UNSET, 27 page_size: int | Unset = UNSET, 28 ) -> PagedResult[Document]: 29 """Return all documents currently in the trash. 30 31 When ``page`` is ``UNSET`` (the default), all pages are fetched 32 automatically and ``next`` / ``previous`` in the result are always 33 ``None``. When ``page`` is set, only that page is fetched and 34 ``next`` / ``previous`` reflect the raw API values. 35 36 Args: 37 page: Return only this specific page (1-based). 38 page_size: Number of results per page. 39 40 Returns: 41 :class:`~easypaperless.models.paged_result.PagedResult` of 42 :class:`~easypaperless.models.documents.Document` objects currently 43 in the trash. 44 """ 45 return cast( 46 PagedResult[Document], 47 self._run(self._async_trash.list(page=page, page_size=page_size)), 48 )
Return all documents currently in the trash.
When page is UNSET (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:
- page: Return only this specific page (1-based).
- page_size: Number of results per page.
Returns:
~easypaperless.models.paged_result.PagedResultof~easypaperless.models.documents.Documentobjects currently in the trash.
50 def restore(self, document_ids: List[int]) -> None: 51 """Restore trashed documents back to active status. 52 53 Args: 54 document_ids: List of numeric document IDs to restore. 55 """ 56 self._run(self._async_trash.restore(document_ids))
Restore trashed documents back to active status.
Arguments:
- document_ids: List of numeric document IDs to restore.
58 def empty(self, document_ids: List[int]) -> None: 59 """Permanently delete trashed documents. 60 61 .. warning:: 62 **This operation is irreversible and cannot be undone.** 63 The documents will be permanently removed and cannot be recovered. 64 65 Args: 66 document_ids: List of numeric document IDs to permanently delete. 67 """ 68 self._run(self._async_trash.empty(document_ids))
Permanently delete trashed documents.
This operation is irreversible and cannot be undone. The documents will be permanently removed and cannot be recovered.
Arguments:
- document_ids: List of numeric document IDs to permanently delete.