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