easypaperless.resources API documentation

# 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)

View Source

     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]

class CorrespondentsResource: View Source

     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`.

CorrespondentsResource(core: easypaperless.client._ClientCore) View Source

    24    def __init__(self, core: _ClientCore) -> None:
    25        self._core = core

async def list( self, *, ids: Optional[List[int]] = None, name_contains: str | None = None, name_exact: str | None = None, page: int | None = None, page_size: int | None = None, ordering: str | None = None, descending: bool = False) -> easypaperless.PagedResult[Correspondent]: View Source

    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.PagedResult` of `~easypaperless.models.correspondents.Correspondent` objects.

async def get(self, id: int) -> easypaperless.Correspondent: View Source

    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.Correspondent` with the given ID.

###### Raises:

- ~easypaperless.exceptions.NotFoundError: If no correspondent exists with that ID.

async def create( self, *, name: str, match: str | easypaperless.Unset = UNSET, matching_algorithm: easypaperless.MatchingAlgorithm | easypaperless.Unset = UNSET, is_insensitive: bool = True, owner: int | None | easypaperless.Unset = UNSET, set_permissions: easypaperless.SetPermissions | None | easypaperless.Unset = UNSET) -> easypaperless.Correspondent: View Source

     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 `match` is applied. E.g. `matching_algorithm=MatchingAlgorithm.REGEX` for regular-expression matching.
- is_insensitive: When `True`, `match` is case-insensitive. Defaults to `True`, matching the paperless-ngx API default.
- owner: Numeric user ID to assign as owner.
- set_permissions: Explicit view/change permission sets. Pass `None` to create with empty permissions.

###### Returns:

> The newly created `~easypaperless.models.correspondents.Correspondent`.

async def update( self, id: int, *, name: str | easypaperless.Unset = UNSET, match: str | easypaperless.Unset = UNSET, matching_algorithm: easypaperless.MatchingAlgorithm | easypaperless.Unset = UNSET, is_insensitive: bool | easypaperless.Unset = UNSET, owner: int | None | easypaperless.Unset = UNSET, set_permissions: easypaperless.SetPermissions | None | easypaperless.Unset = UNSET) -> easypaperless.Correspondent: View Source

    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 `match` is applied. E.g. `matching_algorithm=MatchingAlgorithm.REGEX` for regular-expression matching.
- is_insensitive: When `True`, `match` is case-insensitive.
- owner: Numeric user ID to assign as owner. Pass `None` to clear the owner. Omit (or pass `~easypaperless.UNSET`) to leave unchanged.
- set_permissions: Explicit view/change permission sets. Pass `None` to clear all permissions (overwrite with empty). Omit (or pass `~easypaperless.UNSET`) to leave unchanged.

###### Returns:

> The updated `~easypaperless.models.correspondents.Correspondent`.

async def delete(self, id: int) -> None: View Source

    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.

async def bulk_delete(self, ids: List[int]) -> None: View Source

    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.

async def bulk_set_permissions( self, ids: List[int], *, set_permissions: easypaperless.SetPermissions | easypaperless.Unset = UNSET, owner: int | None | easypaperless.Unset = UNSET, merge: bool = False) -> None: View Source

    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 `None` to clear the owner. Omit (or pass `~easypaperless.UNSET`) to leave unchanged.
- merge: When `True`, new permissions are merged with existing ones.

class CustomFieldsResource: View Source

     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`.

CustomFieldsResource(core: easypaperless.client._ClientCore) View Source

    23    def __init__(self, core: _ClientCore) -> None:
    24        self._core = core

async def list( self, *, name_contains: str | None = None, name_exact: str | None = None, page: int | None = None, page_size: int | None = None, ordering: str | None = None, descending: bool = False) -> easypaperless.PagedResult[CustomField]: View Source

    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.PagedResult` of `~easypaperless.models.custom_fields.CustomField` objects.

async def get(self, id: int) -> easypaperless.CustomField: View Source

    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.CustomField` with the given ID.

###### Raises:

- ~easypaperless.exceptions.NotFoundError: If no custom field exists with that ID.

async def create( self, *, name: str, data_type: str, extra_data: typing.Any | None = None, owner: int | None | easypaperless.Unset = UNSET, set_permissions: easypaperless.SetPermissions | None | easypaperless.Unset = UNSET) -> easypaperless.CustomField: View Source

     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 `None` to create with empty permissions.

###### Returns:

> The newly created `~easypaperless.models.custom_fields.CustomField`.

async def update( self, id: int, *, name: str | easypaperless.Unset = UNSET, data_type: str | easypaperless.Unset = UNSET, extra_data: typing.Any | None | easypaperless.Unset = UNSET, owner: int | None | easypaperless.Unset = UNSET, set_permissions: easypaperless.SetPermissions | None | easypaperless.Unset = UNSET) -> easypaperless.CustomField: View Source

    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 `None` to clear the owner. Omit (or pass `~easypaperless.UNSET`) to leave unchanged.
- set_permissions: Explicit view/change permission sets. Pass `None` to clear all permissions (overwrite with empty). Omit (or pass `~easypaperless.UNSET`) to leave unchanged.

###### Returns:

> The updated `~easypaperless.models.custom_fields.CustomField`.

async def delete(self, id: int) -> None: View Source

    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.

class DocumentTypesResource: View Source

     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`.

DocumentTypesResource(core: easypaperless.client._ClientCore) View Source

    24    def __init__(self, core: _ClientCore) -> None:
    25        self._core = core

async def list( self, *, ids: Optional[List[int]] = None, name_contains: str | None = None, name_exact: str | None = None, page: int | None = None, page_size: int | None = None, ordering: str | None = None, descending: bool = False) -> easypaperless.PagedResult[DocumentType]: View Source

    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.PagedResult` of `~easypaperless.models.document_types.DocumentType` objects.

async def get(self, id: int) -> easypaperless.DocumentType: View Source

    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.DocumentType` with the given ID.

###### Raises:

- ~easypaperless.exceptions.NotFoundError: If no document type exists with that ID.

async def create( self, *, name: str, match: str | easypaperless.Unset = UNSET, matching_algorithm: easypaperless.MatchingAlgorithm | easypaperless.Unset = UNSET, is_insensitive: bool = True, owner: int | None | easypaperless.Unset = UNSET, set_permissions: easypaperless.SetPermissions | None | easypaperless.Unset = UNSET) -> easypaperless.DocumentType: View Source

     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 `match` is applied. E.g. `matching_algorithm=MatchingAlgorithm.REGEX` for regular-expression matching.
- is_insensitive: When `True`, `match` is case-insensitive. Defaults to `True`, matching the paperless-ngx API default.
- owner: Numeric user ID to assign as owner.
- set_permissions: Explicit view/change permission sets. Pass `None` to create with empty permissions.

###### Returns:

> The newly created `~easypaperless.models.document_types.DocumentType`.

async def update( self, id: int, *, name: str | easypaperless.Unset = UNSET, match: str | easypaperless.Unset = UNSET, matching_algorithm: easypaperless.MatchingAlgorithm | easypaperless.Unset = UNSET, is_insensitive: bool | easypaperless.Unset = UNSET, owner: int | None | easypaperless.Unset = UNSET, set_permissions: easypaperless.SetPermissions | None | easypaperless.Unset = UNSET) -> easypaperless.DocumentType: View Source

    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 `match` is applied. E.g. `matching_algorithm=MatchingAlgorithm.REGEX` for regular-expression matching.
- is_insensitive: When `True`, `match` is case-insensitive.
- owner: Numeric user ID to assign as owner. Pass `None` to clear the owner. Omit (or pass `~easypaperless.UNSET`) to leave unchanged.
- set_permissions: Explicit view/change permission sets. Pass `None` to clear all permissions (overwrite with empty). Omit (or pass `~easypaperless.UNSET`) to leave unchanged.

###### Returns:

> The updated `~easypaperless.models.document_types.DocumentType`.

async def delete(self, id: int) -> None: View Source

    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.

async def bulk_delete(self, ids: List[int]) -> None: View Source

    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.

async def bulk_set_permissions( self, ids: List[int], *, set_permissions: easypaperless.SetPermissions | easypaperless.Unset = UNSET, owner: int | None | easypaperless.Unset = UNSET, merge: bool = False) -> None: View Source

    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 `None` to clear the owner. Omit (or pass `~easypaperless.UNSET`) to leave unchanged.
- merge: When `True`, new permissions are merged with existing ones.

class DocumentsResource: View Source

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

Accessor for documents: `client.documents`.

DocumentsResource(core: easypaperless.client._ClientCore) View Source

    141    def __init__(self, core: _ClientCore) -> None:
    142        self._core = core
    143        self.notes = NotesResource(core)

notes
async def get( self, id: int, *, include_metadata: bool = False) -> easypaperless.Document: View Source

    161    async def get(self, id: int, *, include_metadata: bool = False) -> Document:
    162        """Fetch a single document by its ID.
    163
    164        Args:
    165            id: Numeric paperless-ngx document ID.
    166            include_metadata: When ``True``, the extended file-level metadata
    167                is fetched concurrently and attached to the document.
    168                Default: ``False``.
    169
    170        Returns:
    171            The :class:`~easypaperless.models.documents.Document` with the
    172            given ID.
    173
    174        Raises:
    175            ~easypaperless.exceptions.NotFoundError: If no document exists
    176                with that ID.
    177        """
    178        logger.info("Getting document id=%d", id)
    179        if include_metadata:
    180            doc_resp, meta_resp = await asyncio.gather(
    181                self._core._session.get(f"/documents/{id}/"),
    182                self._core._session.get(f"/documents/{id}/metadata/"),
    183            )
    184            data = doc_resp.json()
    185            data["metadata"] = meta_resp.json()
    186        else:
    187            resp = await self._core._session.get(f"/documents/{id}/")
    188            data = resp.json()
    189        return Document.model_validate(data)

Fetch a single document by its ID.

###### Arguments:

- id: Numeric paperless-ngx document ID.
- include_metadata: When `True`, the extended file-level metadata is fetched concurrently and attached to the document. Default: `False`.

###### Returns:

> The `~easypaperless.models.documents.Document` with the given ID.

###### Raises:

- ~easypaperless.exceptions.NotFoundError: If no document exists with that ID.

async def get_metadata(self, id: int) -> easypaperless.DocumentMetadata: View Source

    191    async def get_metadata(self, id: int) -> DocumentMetadata:
    192        """Fetch the extended file-level metadata for a document.
    193
    194        Args:
    195            id: Numeric paperless-ngx document ID.
    196
    197        Returns:
    198            A :class:`~easypaperless.models.documents.DocumentMetadata` instance.
    199
    200        Raises:
    201            ~easypaperless.exceptions.NotFoundError: If no document exists
    202                with that ID.
    203        """
    204        logger.info("Getting metadata for document id=%d", id)
    205        resp = await self._core._session.get(f"/documents/{id}/metadata/")
    206        return DocumentMetadata.model_validate(resp.json())

Fetch the extended file-level metadata for a document.

###### Arguments:

- id: Numeric paperless-ngx document ID.

###### Returns:

> A `~easypaperless.models.documents.DocumentMetadata` instance.

###### Raises:

- ~easypaperless.exceptions.NotFoundError: If no document exists with that ID.

async def list( self, *, search: str | None = None, search_mode: str = 'title_or_content', ids: Optional[List[int]] = None, tags: Optional[List[Union[str, int]]] = None, any_tags: Optional[List[Union[str, int]]] = None, exclude_tags: Optional[List[Union[str, int]]] = None, correspondent: int | str | None | easypaperless.Unset = UNSET, any_correspondent: Optional[List[Union[str, int]]] = None, exclude_correspondents: Optional[List[Union[str, int]]] = None, document_type: int | str | None | easypaperless.Unset = UNSET, document_type_name_contains: str | None = None, document_type_name_exact: str | None = None, any_document_type: Optional[List[Union[str, int]]] = None, exclude_document_types: Optional[List[Union[str, int]]] = None, storage_path: int | str | None | easypaperless.Unset = UNSET, any_storage_paths: Optional[List[Union[str, int]]] = None, exclude_storage_paths: Optional[List[Union[str, int]]] = None, owner: int | None | easypaperless.Unset = UNSET, exclude_owners: Optional[List[int]] = None, custom_fields: Optional[List[Union[str, int]]] = None, any_custom_fields: Optional[List[Union[str, int]]] = None, exclude_custom_fields: Optional[List[Union[str, int]]] = None, custom_field_query: Optional[List[Any]] = None, archive_serial_number: int | None | easypaperless.Unset = UNSET, archive_serial_number_from: int | None = None, archive_serial_number_till: int | None = None, created_after: datetime.date | str | None = None, created_before: datetime.date | str | None = None, added_after: datetime.date | datetime.datetime | str | None = None, added_from: datetime.date | datetime.datetime | str | None = None, added_before: datetime.date | datetime.datetime | str | None = None, added_until: datetime.date | datetime.datetime | str | None = None, modified_after: datetime.date | datetime.datetime | str | None = None, modified_from: datetime.date | datetime.datetime | str | None = None, modified_before: datetime.date | datetime.datetime | str | None = None, modified_until: datetime.date | datetime.datetime | str | None = None, checksum: str | None = None, page_size: int = 25, page: int | None = None, ordering: str | None = None, descending: bool = False, max_results: int | None = None, on_page: Callable[[int, int | None], None] | None = None) -> easypaperless.PagedResult[Document]: View Source

    208    async def list(
    209        self,
    210        *,
    211        search: str | None = None,
    212        search_mode: str = "title_or_content",
    213        ids: List[int] | None = None,
    214        tags: List[int | str] | None = None,
    215        any_tags: List[int | str] | None = None,
    216        exclude_tags: List[int | str] | None = None,
    217        correspondent: int | str | None | Unset = UNSET,
    218        any_correspondent: List[int | str] | None = None,
    219        exclude_correspondents: List[int | str] | None = None,
    220        document_type: int | str | None | Unset = UNSET,
    221        document_type_name_contains: str | None = None,
    222        document_type_name_exact: str | None = None,
    223        any_document_type: List[int | str] | None = None,
    224        exclude_document_types: List[int | str] | None = None,
    225        storage_path: int | str | None | Unset = UNSET,
    226        any_storage_paths: List[int | str] | None = None,
    227        exclude_storage_paths: List[int | str] | None = None,
    228        owner: int | None | Unset = UNSET,
    229        exclude_owners: List[int] | None = None,
    230        custom_fields: List[int | str] | None = None,
    231        any_custom_fields: List[int | str] | None = None,
    232        exclude_custom_fields: List[int | str] | None = None,
    233        custom_field_query: List[Any] | None = None,
    234        archive_serial_number: int | None | Unset = UNSET,
    235        archive_serial_number_from: int | None = None,
    236        archive_serial_number_till: int | None = None,
    237        created_after: date | str | None = None,
    238        created_before: date | str | None = None,
    239        added_after: date | datetime | str | None = None,
    240        added_from: date | datetime | str | None = None,
    241        added_before: date | datetime | str | None = None,
    242        added_until: date | datetime | str | None = None,
    243        modified_after: date | datetime | str | None = None,
    244        modified_from: date | datetime | str | None = None,
    245        modified_before: date | datetime | str | None = None,
    246        modified_until: date | datetime | str | None = None,
    247        checksum: str | None = None,
    248        page_size: int = 25,
    249        page: int | None = None,
    250        ordering: str | None = None,
    251        descending: bool = False,
    252        max_results: int | None = None,
    253        on_page: Callable[[int, int | None], None] | None = None,
    254    ) -> PagedResult[Document]:
    255        """Return a filtered list of documents.
    256
    257        All tag, correspondent, document-type, storage-path, and custom-field
    258        parameters accept either integer IDs or string names.
    259
    260        When ``page`` is ``None`` (the default), all pages are fetched
    261        automatically and ``next`` / ``previous`` in the returned
    262        :class:`~easypaperless.models.paged_result.PagedResult` are always
    263        ``None`` — even if ``max_results`` truncates the final result set.
    264        ``count`` always reflects the server total, not the truncated length.
    265        When ``page`` is set to a specific integer, only that one page is
    266        fetched and ``next`` / ``previous`` contain the raw API values.
    267
    268        Args:
    269            search: Search string.  Behaviour depends on ``search_mode``.
    270            search_mode: How ``search`` is applied.  One of:
    271                ``"title_or_content"`` *(default)*, ``"title"``, ``"query"``,
    272                ``"original_filename"``.
    273            ids: Return only documents whose ID is in this list.
    274            tags: Documents must have **all** of these tags (AND semantics).
    275            any_tags: Documents must have **at least one** of these tags.
    276            exclude_tags: Documents must have **none** of these tags.
    277            correspondent: Filter to documents assigned to this correspondent.
    278                Pass ``None`` to return only documents with no correspondent set.
    279            any_correspondent: Filter to documents assigned to any of these.
    280            exclude_correspondents: Exclude documents assigned to any of these.
    281            document_type: Filter to documents of exactly this type.
    282                Pass ``None`` to return only documents with no document type set.
    283            document_type_name_contains: Case-insensitive substring filter on document type name.
    284            document_type_name_exact: Case-insensitive exact match on document type name.
    285            any_document_type: Filter to documents whose type is any of these.
    286            exclude_document_types: Exclude documents whose type is any of these.
    287            storage_path: Filter to documents assigned to this storage path.
    288                Pass ``None`` to return only documents with no storage path set.
    289            any_storage_paths: Filter to documents assigned to any of these paths.
    290            exclude_storage_paths: Exclude documents assigned to any of these paths.
    291            owner: Filter to documents owned by this user ID.
    292                Pass ``None`` to return only documents with no owner set.
    293            exclude_owners: Exclude documents owned by any of these user IDs.
    294            custom_fields: Documents must have **all** of these custom fields set.
    295            any_custom_fields: Documents must have **at least one** of these fields.
    296            exclude_custom_fields: Documents must have **none** of these fields.
    297            custom_field_query: Filter documents by custom field values using a nested
    298                query structure. See the `paperless-ngx API docs
    299                <https://docs.paperless-ngx.com/api/#filtering-by-custom-fields>`_ for
    300                the query format.
    301            archive_serial_number: Filter by exact archive serial number.
    302                Pass ``None`` to return only documents with no ASN set.
    303            archive_serial_number_from: Filter by ASN >= this value.
    304            archive_serial_number_till: Filter by ASN <= this value.
    305            created_after: Only documents created after this date.
    306                String input must be ISO-8601: ``"YYYY-MM-DD"``.
    307            created_before: Only documents created before this date.
    308                String input must be ISO-8601: ``"YYYY-MM-DD"``.
    309            added_after: Only documents added after this date/time.
    310                String input must be ISO-8601: ``"YYYY-MM-DD"`` for date precision or
    311                ``"YYYY-MM-DDTHH:MM:SS"`` for datetime precision.
    312            added_from: Only documents added on or after this date/time.
    313                String input must be ISO-8601: ``"YYYY-MM-DD"`` or ``"YYYY-MM-DDTHH:MM:SS"``.
    314            added_before: Only documents added before this date/time.
    315                String input must be ISO-8601: ``"YYYY-MM-DD"`` or ``"YYYY-MM-DDTHH:MM:SS"``.
    316            added_until: Only documents added on or before this date/time.
    317                String input must be ISO-8601: ``"YYYY-MM-DD"`` or ``"YYYY-MM-DDTHH:MM:SS"``.
    318            modified_after: Only documents modified after this date/time.
    319                String input must be ISO-8601: ``"YYYY-MM-DD"`` or ``"YYYY-MM-DDTHH:MM:SS"``.
    320            modified_from: Only documents modified on or after this date/time.
    321                String input must be ISO-8601: ``"YYYY-MM-DD"`` or ``"YYYY-MM-DDTHH:MM:SS"``.
    322            modified_before: Only documents modified before this date/time.
    323                String input must be ISO-8601: ``"YYYY-MM-DD"`` or ``"YYYY-MM-DDTHH:MM:SS"``.
    324            modified_until: Only documents modified on or before this date/time.
    325                String input must be ISO-8601: ``"YYYY-MM-DD"`` or ``"YYYY-MM-DDTHH:MM:SS"``.
    326            checksum: MD5 checksum of the original file (exact match).
    327            page_size: Number of results per API page.  Default: ``25``.
    328            page: Return only this specific page (1-based).
    329            ordering: Field name to sort by.
    330            descending: When ``True``, reverses the sort direction.
    331            max_results: Stop after collecting this many documents.
    332            on_page: Callback invoked after each page fetch.
    333
    334        Returns:
    335            :class:`~easypaperless.models.paged_result.PagedResult` of
    336            :class:`~easypaperless.models.documents.Document` objects.
    337        """
    338        logger.info("Listing documents")
    339        resolver = self._core._resolver
    340        params: dict[str, Any] = {"page_size": page_size}
    341
    342        if search is not None:
    343            api_param = _SEARCH_MODE_MAP.get(search_mode, "search")
    344            params[api_param] = search
    345
    346        if ids is not None:
    347            params["id__in"] = ",".join(str(i) for i in ids)
    348
    349        if tags is not None:
    350            resolved = await resolver.resolve_list("tags", tags)
    351            params["tags__id__all"] = ",".join(str(t) for t in resolved)
    352
    353        if any_tags is not None:
    354            resolved = await resolver.resolve_list("tags", any_tags)
    355            params["tags__id__in"] = ",".join(str(t) for t in resolved)
    356
    357        if exclude_tags is not None:
    358            resolved = await resolver.resolve_list("tags", exclude_tags)
    359            params["tags__id__none"] = ",".join(str(t) for t in resolved)
    360
    361        if any_correspondent is not None:
    362            resolved = await resolver.resolve_list("correspondents", any_correspondent)
    363            params["correspondent__id__in"] = ",".join(str(c) for c in resolved)
    364        elif not isinstance(correspondent, Unset):
    365            if correspondent is None:
    366                params["correspondent__isnull"] = "true"
    367            else:
    368                resolved_id = await resolver.resolve("correspondents", correspondent)
    369                params["correspondent__id__in"] = resolved_id
    370
    371        if exclude_correspondents is not None:
    372            resolved = await resolver.resolve_list("correspondents", exclude_correspondents)
    373            params["correspondent__id__none"] = ",".join(str(c) for c in resolved)
    374
    375        if document_type_name_contains is not None:
    376            params["document_type__name__icontains"] = document_type_name_contains
    377        if document_type_name_exact is not None:
    378            params["document_type__name__iexact"] = document_type_name_exact
    379
    380        if any_document_type is not None:
    381            resolved = await resolver.resolve_list("document_types", any_document_type)
    382            params["document_type__id__in"] = ",".join(str(d) for d in resolved)
    383        elif not isinstance(document_type, Unset):
    384            if document_type is None:
    385                params["document_type__isnull"] = "true"
    386            else:
    387                resolved_id = await resolver.resolve("document_types", document_type)
    388                params["document_type"] = resolved_id
    389
    390        if exclude_document_types is not None:
    391            resolved = await resolver.resolve_list("document_types", exclude_document_types)
    392            params["document_type__id__none"] = ",".join(str(d) for d in resolved)
    393
    394        if any_storage_paths is not None:
    395            resolved = await resolver.resolve_list("storage_paths", any_storage_paths)
    396            params["storage_path__id__in"] = ",".join(str(s) for s in resolved)
    397        elif not isinstance(storage_path, Unset):
    398            if storage_path is None:
    399                params["storage_path__isnull"] = "true"
    400            else:
    401                resolved_id = await resolver.resolve("storage_paths", storage_path)
    402                params["storage_path__id__in"] = resolved_id
    403
    404        if exclude_storage_paths is not None:
    405            resolved = await resolver.resolve_list("storage_paths", exclude_storage_paths)
    406            params["storage_path__id__none"] = ",".join(str(s) for s in resolved)
    407
    408        if not isinstance(owner, Unset):
    409            if owner is None:
    410                params["owner__isnull"] = "true"
    411            else:
    412                params["owner__id__in"] = owner
    413
    414        if exclude_owners is not None:
    415            params["owner__id__none"] = ",".join(str(o) for o in exclude_owners)
    416
    417        if custom_fields is not None:
    418            resolved = await resolver.resolve_list("custom_fields", custom_fields)
    419            params["custom_fields__id__all"] = ",".join(str(f) for f in resolved)
    420
    421        if any_custom_fields is not None:
    422            resolved = await resolver.resolve_list("custom_fields", any_custom_fields)
    423            params["custom_fields__id__in"] = ",".join(str(f) for f in resolved)
    424
    425        if exclude_custom_fields is not None:
    426            resolved = await resolver.resolve_list("custom_fields", exclude_custom_fields)
    427            params["custom_fields__id__none"] = ",".join(str(f) for f in resolved)
    428
    429        if custom_field_query is not None:
    430            params["custom_field_query"] = json.dumps(custom_field_query)
    431
    432        if not isinstance(archive_serial_number, Unset):
    433            if archive_serial_number is None:
    434                params["archive_serial_number__isnull"] = "true"
    435            else:
    436                params["archive_serial_number"] = archive_serial_number
    437
    438        if archive_serial_number_from is not None:
    439            params["archive_serial_number__gte"] = archive_serial_number_from
    440
    441        if archive_serial_number_till is not None:
    442            params["archive_serial_number__lte"] = archive_serial_number_till
    443
    444        if created_after is not None:
    445            params["created__date__gt"] = self._format_date_value(created_after)
    446
    447        if created_before is not None:
    448            params["created__date__lt"] = self._format_date_value(created_before)
    449
    450        if added_after is not None:
    451            key = "added__gt" if self._is_datetime(added_after) else "added__date__gt"
    452            params[key] = self._format_date_value(added_after)
    453
    454        if added_from is not None:
    455            key = "added__gte" if self._is_datetime(added_from) else "added__date__gte"
    456            params[key] = self._format_date_value(added_from)
    457
    458        if added_before is not None:
    459            key = "added__lt" if self._is_datetime(added_before) else "added__date__lt"
    460            params[key] = self._format_date_value(added_before)
    461
    462        if added_until is not None:
    463            key = "added__lte" if self._is_datetime(added_until) else "added__date__lte"
    464            params[key] = self._format_date_value(added_until)
    465
    466        if modified_after is not None:
    467            key = "modified__gt" if self._is_datetime(modified_after) else "modified__date__gt"
    468            params[key] = self._format_date_value(modified_after)
    469
    470        if modified_from is not None:
    471            key = "modified__gte" if self._is_datetime(modified_from) else "modified__date__gte"
    472            params[key] = self._format_date_value(modified_from)
    473
    474        if modified_before is not None:
    475            key = "modified__lt" if self._is_datetime(modified_before) else "modified__date__lt"
    476            params[key] = self._format_date_value(modified_before)
    477
    478        if modified_until is not None:
    479            key = "modified__lte" if self._is_datetime(modified_until) else "modified__date__lte"
    480            params[key] = self._format_date_value(modified_until)
    481
    482        if checksum is not None:
    483            params["checksum__iexact"] = checksum
    484
    485        if ordering is not None:
    486            params["ordering"] = f"-{ordering}" if descending else ordering
    487
    488        if page is not None:
    489            params["page"] = page
    490            raw = await self._core._session.get_page("/documents/", params=params)
    491            items = raw.items
    492            if max_results is not None:
    493                items = items[:max_results]
    494            return PagedResult(
    495                count=raw.count,
    496                next=raw.next,
    497                previous=raw.previous,
    498                all=raw.all_ids,
    499                results=[Document.model_validate(item) for item in items],
    500            )
    501
    502        raw = await self._core._session.get_all_pages_paged(
    503            "/documents/", params, max_results=max_results, on_page=on_page
    504        )
    505        return PagedResult(
    506            count=raw.count,
    507            next=raw.next,
    508            previous=raw.previous,
    509            all=raw.all_ids,
    510            results=[Document.model_validate(item) for item in raw.items],
    511        )

Return a filtered list of documents.

All tag, correspondent, document-type, storage-path, and custom-field parameters accept either integer IDs or string names.

When `page` is `None` (the default), all pages are fetched automatically and `next` / `previous` in the returned `~easypaperless.models.paged_result.PagedResult` are always `None` — even if `max_results` truncates the final result set. `count` always reflects the server total, not the truncated length. When `page` is set to a specific integer, only that one page is fetched and `next` / `previous` contain the raw API values.

###### Arguments:

- search: Search string. Behaviour depends on `search_mode`.
- search_mode: How `search` is 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 `None` to 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 `None` to 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 `None` to 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 `None` to 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 `None` to 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.PagedResult` of `~easypaperless.models.documents.Document` objects.

async def update( self, id: int, *, title: str | easypaperless.Unset = UNSET, content: str | easypaperless.Unset = UNSET, created: datetime.date | str | None | easypaperless.Unset = UNSET, correspondent: int | str | None | easypaperless.Unset = UNSET, document_type: int | str | None | easypaperless.Unset = UNSET, storage_path: int | str | None | easypaperless.Unset = UNSET, tags: Union[List[Union[str, int]], NoneType, easypaperless.Unset] = UNSET, archive_serial_number: int | None | easypaperless.Unset = UNSET, custom_fields: Union[List[dict[str, Any]], NoneType, easypaperless.Unset] = UNSET, owner: int | None | easypaperless.Unset = UNSET, set_permissions: easypaperless.SetPermissions | None | easypaperless.Unset = UNSET, remove_inbox_tags: bool | None | easypaperless.Unset = UNSET) -> easypaperless.Document: View Source

    513    async def update(
    514        self,
    515        id: int,
    516        *,
    517        title: str | Unset = UNSET,
    518        content: str | Unset = UNSET,
    519        created: date | str | None | Unset = UNSET,
    520        correspondent: int | str | None | Unset = UNSET,
    521        document_type: int | str | None | Unset = UNSET,
    522        storage_path: int | str | None | Unset = UNSET,
    523        tags: List[int | str] | None | Unset = UNSET,
    524        archive_serial_number: int | None | Unset = UNSET,
    525        custom_fields: List[dict[str, Any]] | None | Unset = UNSET,
    526        owner: int | None | Unset = UNSET,
    527        set_permissions: SetPermissions | None | Unset = UNSET,
    528        remove_inbox_tags: bool | None | Unset = UNSET,
    529    ) -> Document:
    530        """Partially update a document (PATCH semantics).
    531
    532        Args:
    533            id: Numeric ID of the document to update.
    534            title: New document title.
    535            content: OCR text content of the document.
    536            created: Creation date as an ISO-8601 string (``"YYYY-MM-DD"``) or a
    537                :class:`~datetime.date` object.
    538            correspondent: Correspondent to assign, as an ID or name.
    539                Pass ``None`` to clear the correspondent.
    540            document_type: Document type to assign, as an ID or name.
    541                Pass ``None`` to clear the document type.
    542            storage_path: Storage path to assign, as an ID or name.
    543                Pass ``None`` to clear the storage path.
    544            tags: Full replacement list of tags (IDs or names).
    545            archive_serial_number: Archive serial number to assign.
    546                Pass ``None`` to clear the archive serial number.
    547            custom_fields: List of ``{"field": <field_id>, "value": ...}`` dicts.
    548            owner: Numeric user ID to assign as document owner.
    549                Pass ``None`` to clear the owner.
    550            set_permissions: Explicit view/change permission sets.
    551                Pass ``None`` to clear all permissions (overwrite with empty).
    552                Omit (or pass :data:`~easypaperless.UNSET`) to leave unchanged.
    553            remove_inbox_tags: When ``True``, removes all inbox tags from the document.
    554
    555        Returns:
    556            The updated :class:`~easypaperless.models.documents.Document`.
    557        """
    558        logger.info("Updating document id=%d", id)
    559        resolver = self._core._resolver
    560        payload: dict[str, Any] = {}
    561
    562        if not isinstance(title, Unset):
    563            payload["title"] = title
    564        if not isinstance(content, Unset):
    565            payload["content"] = content
    566        if not isinstance(created, Unset):
    567            payload["created"] = self._format_date_value(created) if created is not None else None
    568        if not isinstance(correspondent, Unset):
    569            payload["correspondent"] = (
    570                None
    571                if correspondent is None
    572                else await resolver.resolve("correspondents", correspondent)
    573            )
    574        if not isinstance(document_type, Unset):
    575            payload["document_type"] = (
    576                None
    577                if document_type is None
    578                else await resolver.resolve("document_types", document_type)
    579            )
    580        if not isinstance(storage_path, Unset):
    581            payload["storage_path"] = (
    582                None
    583                if storage_path is None
    584                else await resolver.resolve("storage_paths", storage_path)
    585            )
    586        if not isinstance(tags, Unset):
    587            payload["tags"] = await resolver.resolve_list("tags", tags or [])
    588        if not isinstance(archive_serial_number, Unset):
    589            payload["archive_serial_number"] = archive_serial_number
    590        if not isinstance(custom_fields, Unset):
    591            payload["custom_fields"] = custom_fields
    592        if not isinstance(owner, Unset):
    593            payload["owner"] = owner
    594        if not isinstance(set_permissions, Unset):
    595            payload["set_permissions"] = (
    596                SetPermissions().model_dump()
    597                if set_permissions is None
    598                else set_permissions.model_dump()
    599            )
    600        if not isinstance(remove_inbox_tags, Unset):
    601            payload["remove_inbox_tags"] = remove_inbox_tags
    602
    603        resp = await self._core._session.patch(f"/documents/{id}/", json=payload)
    604        return Document.model_validate(resp.json())

Partially update a document (PATCH semantics).

###### Arguments:

- id: Numeric ID of the document to update.
- title: New document title.
- content: OCR text content of the document.
- created: Creation date as an ISO-8601 string (`"YYYY-MM-DD"`) or a `~datetime.date` object.
- correspondent: Correspondent to assign, as an ID or name. Pass `None` to clear the correspondent.
- document_type: Document type to assign, as an ID or name. Pass `None` to clear the document type.
- storage_path: Storage path to assign, as an ID or name. Pass `None` to clear the storage path.
- tags: Full replacement list of tags (IDs or names).
- archive_serial_number: Archive serial number to assign. Pass `None` to clear the archive serial number.
- custom_fields: List of `{"field": <field_id>, "value": ...}` dicts.
- owner: Numeric user ID to assign as document owner. Pass `None` to clear the owner.
- set_permissions: Explicit view/change permission sets. Pass `None` to 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`.

async def delete(self, id: int) -> None: View Source

    606    async def delete(self, id: int) -> None:
    607        """Permanently delete a document.
    608
    609        Args:
    610            id: Numeric ID of the document to delete.
    611
    612        Raises:
    613            ~easypaperless.exceptions.NotFoundError: If no document exists
    614                with that ID.
    615        """
    616        logger.info("Deleting document id=%d", id)
    617        await self._core._session.delete(f"/documents/{id}/")

Permanently delete a document.

###### Arguments:

- id: Numeric ID of the document to delete.

###### Raises:

- ~easypaperless.exceptions.NotFoundError: If no document exists with that ID.

async def download(self, id: int, *, original: bool = False) -> bytes: View Source

    619    async def download(self, id: int, *, original: bool = False) -> bytes:
    620        """Download the binary content of a document.
    621
    622        Args:
    623            id: Numeric ID of the document to download.
    624            original: If ``False`` *(default)*, returns the archived PDF.
    625                If ``True``, returns the original uploaded file.
    626
    627        Returns:
    628            Raw file bytes.
    629        """
    630        logger.info("Downloading document id=%d (original=%s)", id, original)
    631        endpoint = "download" if original else "archive"
    632        resp = await self._core._session.get_download(f"/documents/{id}/{endpoint}/")
    633        content_type = resp.headers.get("content-type", "")
    634        if "text/html" in content_type or resp.content[:9].lower().startswith(b"<!doctype"):
    635            raise ServerError(
    636                f"Download returned an HTML page (content-type: {content_type!r}). "
    637                "The server redirected to a login page even after re-attaching auth.",
    638                status_code=None,
    639            )
    640        return resp.content

Download the binary content of a document.

###### Arguments:

- id: Numeric ID of the document to download.
- original: If `False` (default), returns the archived PDF. If `True`, returns the original uploaded file.

###### Returns:

> Raw file bytes.

async def upload( self, file: str | pathlib._local.Path, *, title: str | easypaperless.Unset = UNSET, created: datetime.date | str | None = None, correspondent: int | str | None | easypaperless.Unset = UNSET, document_type: int | str | None | easypaperless.Unset = UNSET, storage_path: int | str | None | easypaperless.Unset = UNSET, tags: Optional[List[Union[str, int]]] = None, archive_serial_number: int | None | easypaperless.Unset = UNSET, custom_fields: Optional[List[dict[str, Any]]] = None, wait: bool = False, poll_interval: float | None = None, poll_timeout: float | None = None) -> str | easypaperless.Document: View Source

    642    async def upload(
    643        self,
    644        file: str | Path,
    645        *,
    646        title: str | Unset = UNSET,
    647        created: date | str | None = None,
    648        correspondent: int | str | None | Unset = UNSET,
    649        document_type: int | str | None | Unset = UNSET,
    650        storage_path: int | str | None | Unset = UNSET,
    651        tags: List[int | str] | None = None,
    652        archive_serial_number: int | None | Unset = UNSET,
    653        custom_fields: List[dict[str, Any]] | None = None,
    654        wait: bool = False,
    655        poll_interval: float | None = None,
    656        poll_timeout: float | None = None,
    657    ) -> str | Document:
    658        """Upload a document to paperless-ngx.
    659
    660        Args:
    661            file: Path to the file to upload.
    662            title: Title to assign to the document.
    663            created: Creation date as an ISO-8601 string (``"YYYY-MM-DD"``) or a
    664                :class:`~datetime.date` object.
    665            correspondent: Correspondent to assign, as an ID or name.
    666            document_type: Document type to assign, as an ID or name.
    667            storage_path: Storage path to assign, as an ID or name.
    668            tags: Tags to assign, as IDs or names.
    669            archive_serial_number: Archive serial number to assign.
    670            custom_fields: List of ``{"field": <field_id>, "value": ...}`` dicts.
    671            wait: If ``False`` *(default)*, returns immediately with the task ID.
    672                If ``True``, polls until processing completes.
    673            poll_interval: Seconds between task-status checks while waiting for
    674                processing to complete (requires ``wait=True``). Overrides the
    675                client-level default. When omitted, falls back to the client-level
    676                ``poll_interval`` (``2.0`` s unless changed at construction).
    677            poll_timeout: Maximum seconds to wait before raising
    678                :exc:`~easypaperless.exceptions.TaskTimeoutError` (requires
    679                ``wait=True``). Overrides the client-level default. When omitted,
    680                falls back to the client-level ``poll_timeout`` (``60.0`` s unless
    681                changed at construction).
    682
    683        Returns:
    684            The Celery task ID string when ``wait=False``, or the fully
    685            processed :class:`~easypaperless.models.documents.Document`
    686            when ``wait=True``.
    687
    688        Raises:
    689            ~easypaperless.exceptions.UploadError: If processing fails.
    690            ~easypaperless.exceptions.TaskTimeoutError: If timeout is exceeded.
    691        """
    692        resolver = self._core._resolver
    693        file_path = Path(file)
    694        file_bytes = file_path.read_bytes()
    695        logger.info("Uploading %r (%d bytes)", file_path.name, len(file_bytes))
    696
    697        data: dict[str, Any] = {}
    698        if not isinstance(title, Unset):
    699            data["title"] = title
    700        if created is not None:
    701            data["created"] = self._format_date_value(created)
    702        if not isinstance(correspondent, Unset) and correspondent is not None:
    703            data["correspondent"] = await resolver.resolve("correspondents", correspondent)
    704        if not isinstance(document_type, Unset) and document_type is not None:
    705            data["document_type"] = await resolver.resolve("document_types", document_type)
    706        if not isinstance(storage_path, Unset) and storage_path is not None:
    707            data["storage_path"] = await resolver.resolve("storage_paths", storage_path)
    708        if tags is not None:
    709            resolved = await resolver.resolve_list("tags", tags)
    710            data["tags"] = resolved
    711        if not isinstance(archive_serial_number, Unset) and archive_serial_number is not None:
    712            data["archive_serial_number"] = archive_serial_number
    713        if custom_fields is not None:
    714            data["custom_fields"] = json.dumps(custom_fields)
    715
    716        files = {"document": (file_path.name, file_bytes)}
    717        resp = await self._core._session.post("/documents/post_document/", data=data, files=files)
    718        task_id: str = resp.text.strip('"')
    719        logger.debug("Upload accepted, task_id=%r", task_id)
    720
    721        if not wait:
    722            return task_id
    723
    724        interval = poll_interval if poll_interval is not None else self._core._poll_interval
    725        timeout = poll_timeout if poll_timeout is not None else self._core._poll_timeout
    726        return await self._poll_task(task_id, poll_interval=interval, poll_timeout=timeout)

Upload a document to paperless-ngx.

###### Arguments:

- file: Path to the file to upload.
- title: Title to assign to the document.
- created: Creation date as an ISO-8601 string (`"YYYY-MM-DD"`) or a `~datetime.date` object.
- 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. If `True`, 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-level `poll_interval` (`2.0` s unless changed at construction).
- poll_timeout: Maximum seconds to wait before raising `~easypaperless.exceptions.TaskTimeoutError` (requires `wait=True`). Overrides the client-level default. When omitted, falls back to the client-level `poll_timeout` (`60.0` s unless changed at construction).

###### Returns:

> The Celery task ID string when `wait=False`, or the fully processed `~easypaperless.models.documents.Document` when `wait=True`.

###### Raises:

- ~easypaperless.exceptions.UploadError: If processing fails.
- ~easypaperless.exceptions.TaskTimeoutError: If timeout is exceeded.

async def bulk_add_tag(self, document_ids: List[int], tag: int | str) -> None: View Source

    781    async def bulk_add_tag(self, document_ids: List[int], tag: int | str) -> None:
    782        """Add a tag to multiple documents in a single request.
    783
    784        Args:
    785            document_ids: List of document IDs to tag.
    786            tag: Tag to add, as an ID or name.
    787        """
    788        logger.info("Bulk adding tag %r to %d documents", tag, len(document_ids))
    789        tag_id = await self._core._resolver.resolve("tags", tag)
    790        await self._bulk_edit(document_ids, "add_tag", tag=tag_id)

Add a tag to multiple documents in a single request.

###### Arguments:

- document_ids: List of document IDs to tag.
- tag: Tag to add, as an ID or name.

async def bulk_remove_tag(self, document_ids: List[int], tag: int | str) -> None: View Source

    792    async def bulk_remove_tag(self, document_ids: List[int], tag: int | str) -> None:
    793        """Remove a tag from multiple documents in a single request.
    794
    795        Args:
    796            document_ids: List of document IDs to un-tag.
    797            tag: Tag to remove, as an ID or name.
    798        """
    799        logger.info("Bulk removing tag %r from %d documents", tag, len(document_ids))
    800        tag_id = await self._core._resolver.resolve("tags", tag)
    801        await self._bulk_edit(document_ids, "remove_tag", tag=tag_id)

Remove a tag from multiple documents in a single request.

###### Arguments:

- document_ids: List of document IDs to un-tag.
- tag: Tag to remove, as an ID or name.

async def bulk_modify_tags( self, document_ids: List[int], *, add_tags: Optional[List[Union[str, int]]] = None, remove_tags: Optional[List[Union[str, int]]] = None) -> None: View Source

    803    async def bulk_modify_tags(
    804        self,
    805        document_ids: List[int],
    806        *,
    807        add_tags: List[int | str] | None = None,
    808        remove_tags: List[int | str] | None = None,
    809    ) -> None:
    810        """Add and/or remove tags on multiple documents atomically.
    811
    812        Args:
    813            document_ids: List of document IDs to modify.
    814            add_tags: Tags to add, as IDs or names.
    815            remove_tags: Tags to remove, as IDs or names.
    816        """
    817        logger.info("Bulk modifying tags on %d documents", len(document_ids))
    818        resolver = self._core._resolver
    819        add_ids = await resolver.resolve_list("tags", add_tags or [])
    820        remove_ids = await resolver.resolve_list("tags", remove_tags or [])
    821        await self._bulk_edit(document_ids, "modify_tags", add_tags=add_ids, remove_tags=remove_ids)

Add and/or remove tags on multiple documents atomically.

###### Arguments:

- document_ids: List of document IDs to modify.
- add_tags: Tags to add, as IDs or names.
- remove_tags: Tags to remove, as IDs or names.

async def bulk_delete(self, document_ids: List[int]) -> None: View Source

    823    async def bulk_delete(self, document_ids: List[int]) -> None:
    824        """Permanently delete multiple documents in a single request.
    825
    826        Args:
    827            document_ids: List of document IDs to delete.
    828        """
    829        logger.info("Bulk deleting %d documents", len(document_ids))
    830        await self._bulk_edit(document_ids, "delete")

Permanently delete multiple documents in a single request.

###### Arguments:

- document_ids: List of document IDs to delete.

async def bulk_set_correspondent(self, document_ids: List[int], correspondent: int | str | None) -> None: View Source

    832    async def bulk_set_correspondent(
    833        self, document_ids: List[int], correspondent: int | str | None
    834    ) -> None:
    835        """Assign a correspondent to multiple documents in a single request.
    836
    837        Args:
    838            document_ids: List of document IDs to modify.
    839            correspondent: Correspondent to assign, as an ID or name.
    840                Pass ``None`` to clear.
    841        """
    842        logger.info(
    843            "Bulk setting correspondent %r on %d documents", correspondent, len(document_ids)
    844        )
    845        cor_id: int | None = None
    846        if correspondent is not None:
    847            cor_id = await self._core._resolver.resolve("correspondents", correspondent)
    848        await self._bulk_edit(document_ids, "set_correspondent", correspondent=cor_id)

Assign a correspondent to multiple documents in a single request.

###### Arguments:

- document_ids: List of document IDs to modify.
- correspondent: Correspondent to assign, as an ID or name. Pass `None` to clear.

async def bulk_set_document_type(self, document_ids: List[int], document_type: int | str | None) -> None: View Source

    850    async def bulk_set_document_type(
    851        self, document_ids: List[int], document_type: int | str | None
    852    ) -> None:
    853        """Assign a document type to multiple documents in a single request.
    854
    855        Args:
    856            document_ids: List of document IDs to modify.
    857            document_type: Document type to assign, as an ID or name.
    858                Pass ``None`` to clear.
    859        """
    860        logger.info(
    861            "Bulk setting document type %r on %d documents", document_type, len(document_ids)
    862        )
    863        dt_id: int | None = None
    864        if document_type is not None:
    865            dt_id = await self._core._resolver.resolve("document_types", document_type)
    866        await self._bulk_edit(document_ids, "set_document_type", document_type=dt_id)

Assign a document type to multiple documents in a single request.

###### Arguments:

- document_ids: List of document IDs to modify.
- document_type: Document type to assign, as an ID or name. Pass `None` to clear.

async def bulk_set_storage_path(self, document_ids: List[int], storage_path: int | str | None) -> None: View Source

    868    async def bulk_set_storage_path(
    869        self, document_ids: List[int], storage_path: int | str | None
    870    ) -> None:
    871        """Assign a storage path to multiple documents in a single request.
    872
    873        Args:
    874            document_ids: List of document IDs to modify.
    875            storage_path: Storage path to assign, as an ID or name.
    876                Pass ``None`` to clear.
    877        """
    878        logger.info("Bulk setting storage path %r on %d documents", storage_path, len(document_ids))
    879        sp_id: int | None = None
    880        if storage_path is not None:
    881            sp_id = await self._core._resolver.resolve("storage_paths", storage_path)
    882        await self._bulk_edit(document_ids, "set_storage_path", storage_path=sp_id)

Assign a storage path to multiple documents in a single request.

###### Arguments:

- document_ids: List of document IDs to modify.
- storage_path: Storage path to assign, as an ID or name. Pass `None` to clear.

async def bulk_modify_custom_fields( self, document_ids: List[int], *, add_fields: Optional[List[dict[str, Any]]] = None, remove_fields: Optional[List[int]] = None) -> None: View Source

    884    async def bulk_modify_custom_fields(
    885        self,
    886        document_ids: List[int],
    887        *,
    888        add_fields: List[dict[str, Any]] | None = None,
    889        remove_fields: List[int] | None = None,
    890    ) -> None:
    891        """Add and/or remove custom field values on multiple documents.
    892
    893        Args:
    894            document_ids: List of document IDs to modify.
    895            add_fields: Custom-field value dicts to add.
    896            remove_fields: Custom-field IDs whose values should be removed.
    897        """
    898        logger.info("Bulk modifying custom fields on %d documents", len(document_ids))
    899        await self._bulk_edit(
    900            document_ids,
    901            "modify_custom_fields",
    902            add_custom_fields=add_fields or [],
    903            remove_custom_fields=remove_fields or [],
    904        )

Add and/or remove custom field values on multiple documents.

###### Arguments:

- document_ids: List of document IDs to modify.
- add_fields: Custom-field value dicts to add.
- remove_fields: Custom-field IDs whose values should be removed.

async def bulk_set_permissions( self, document_ids: List[int], *, set_permissions: easypaperless.SetPermissions | easypaperless.Unset = UNSET, owner: int | None | easypaperless.Unset = UNSET, merge: bool = False) -> None: View Source

    906    async def bulk_set_permissions(
    907        self,
    908        document_ids: List[int],
    909        *,
    910        set_permissions: SetPermissions | Unset = UNSET,
    911        owner: int | None | Unset = UNSET,
    912        merge: bool = False,
    913    ) -> None:
    914        """Set permissions and/or owner on multiple documents.
    915
    916        Args:
    917            document_ids: List of document IDs to modify.
    918            set_permissions: Explicit view/change permission sets.
    919                Omit (or pass :data:`~easypaperless.UNSET`) to leave unchanged.
    920            owner: Numeric user ID to assign as document owner.
    921                Pass ``None`` to clear the owner.
    922                Omit (or pass :data:`~easypaperless.UNSET`) to leave unchanged.
    923            merge: When ``True``, new permissions are merged with existing ones.
    924        """
    925        logger.info("Bulk setting permissions on %d documents", len(document_ids))
    926        params: dict[str, Any] = {"merge": merge}
    927        if not isinstance(set_permissions, Unset):
    928            params["set_permissions"] = set_permissions.model_dump()
    929        if not isinstance(owner, Unset):
    930            params["owner"] = owner
    931        await self._bulk_edit(document_ids, "set_permissions", **params)

Set permissions and/or owner on multiple documents.

###### Arguments:

- document_ids: List of document IDs to modify.
- set_permissions: Explicit view/change permission sets. Omit (or pass `~easypaperless.UNSET`) to leave unchanged.
- owner: Numeric user ID to assign as document owner. Pass `None` to clear the owner. Omit (or pass `~easypaperless.UNSET`) to leave unchanged.
- merge: When `True`, new permissions are merged with existing ones.

class NotesResource: View Source

     43class NotesResource:
     44    """Accessor for document notes: ``client.documents.notes``."""
     45
     46    def __init__(self, core: _ClientCore) -> None:
     47        self._core = core
     48
     49    async def list(
     50        self,
     51        document_id: int,
     52        *,
     53        page: int | None = None,
     54        page_size: int | None = None,
     55    ) -> PagedResult[DocumentNote]:
     56        """Fetch notes attached to a document.
     57
     58        When ``page`` is ``None`` (the default), all pages are fetched
     59        automatically and ``next`` / ``previous`` in the returned
     60        :class:`~easypaperless.models.paged_result.PagedResult` are always
     61        ``None``.  When ``page`` is set to a specific integer, only that one
     62        page is fetched and ``next`` / ``previous`` contain the raw API values.
     63
     64        Args:
     65            document_id: Numeric ID of the document whose notes to retrieve.
     66            page: Return only this specific page (1-based).
     67            page_size: Number of results per page.
     68
     69        Returns:
     70            :class:`~easypaperless.models.paged_result.PagedResult` of
     71            :class:`~easypaperless.models.documents.DocumentNote` objects,
     72            ordered by creation time.
     73
     74        Raises:
     75            ~easypaperless.exceptions.NotFoundError: If no document exists
     76                with that ID.
     77        """
     78        logger.info("Listing notes for document id=%d", document_id)
     79        path = f"/documents/{document_id}/notes/"
     80        params: dict[str, Any] = {}
     81        if page_size is not None:
     82            params["page_size"] = page_size
     83        if page is not None:
     84            params["page"] = page
     85            raw = await self._core._session.get_page(path, params=params)
     86        else:
     87            raw = await self._core._session.get_all_pages_paged(path, params or None)
     88        return cast(
     89            PagedResult[DocumentNote],
     90            PagedResult(
     91                count=raw.count,
     92                next=raw.next,
     93                previous=raw.previous,
     94                all=raw.all_ids,
     95                results=[DocumentNote.model_validate(item) for item in raw.items],
     96            ),
     97        )
     98
     99    async def create(self, document_id: int, *, note: str) -> DocumentNote:
    100        """Create a new note on a document.
    101
    102        Args:
    103            document_id: Numeric ID of the document to annotate.
    104            note: Text content of the note.
    105
    106        Returns:
    107            The newly created :class:`~easypaperless.models.documents.DocumentNote`.
    108
    109        Raises:
    110            ~easypaperless.exceptions.NotFoundError: If no document exists
    111                with that ID.
    112        """
    113        logger.info("Creating note for document id=%d", document_id)
    114        resp = await self._core._session.post(
    115            f"/documents/{document_id}/notes/",
    116            json={"note": note},
    117        )
    118        data = resp.json()
    119        if isinstance(data, list):
    120            return DocumentNote.model_validate(data[-1])
    121        return DocumentNote.model_validate(data)
    122
    123    async def delete(self, document_id: int, note_id: int) -> None:
    124        """Delete a note from a document.
    125
    126        Args:
    127            document_id: Numeric ID of the document that owns the note.
    128            note_id: Numeric ID of the note to delete.
    129
    130        Raises:
    131            ~easypaperless.exceptions.NotFoundError: If no document or note
    132                exists with the given IDs.
    133        """
    134        logger.info("Deleting note id=%d from document id=%d", note_id, document_id)
    135        await self._core._session.delete(f"/documents/{document_id}/notes/", params={"id": note_id})

Accessor for document notes: `client.documents.notes`.

NotesResource(core: easypaperless.client._ClientCore) View Source

    46    def __init__(self, core: _ClientCore) -> None:
    47        self._core = core

async def list( self, document_id: int, *, page: int | None = None, page_size: int | None = None) -> easypaperless.PagedResult[DocumentNote]: View Source

    49    async def list(
    50        self,
    51        document_id: int,
    52        *,
    53        page: int | None = None,
    54        page_size: int | None = None,
    55    ) -> PagedResult[DocumentNote]:
    56        """Fetch notes attached to a document.
    57
    58        When ``page`` is ``None`` (the default), all pages are fetched
    59        automatically and ``next`` / ``previous`` in the returned
    60        :class:`~easypaperless.models.paged_result.PagedResult` are always
    61        ``None``.  When ``page`` is set to a specific integer, only that one
    62        page is fetched and ``next`` / ``previous`` contain the raw API values.
    63
    64        Args:
    65            document_id: Numeric ID of the document whose notes to retrieve.
    66            page: Return only this specific page (1-based).
    67            page_size: Number of results per page.
    68
    69        Returns:
    70            :class:`~easypaperless.models.paged_result.PagedResult` of
    71            :class:`~easypaperless.models.documents.DocumentNote` objects,
    72            ordered by creation time.
    73
    74        Raises:
    75            ~easypaperless.exceptions.NotFoundError: If no document exists
    76                with that ID.
    77        """
    78        logger.info("Listing notes for document id=%d", document_id)
    79        path = f"/documents/{document_id}/notes/"
    80        params: dict[str, Any] = {}
    81        if page_size is not None:
    82            params["page_size"] = page_size
    83        if page is not None:
    84            params["page"] = page
    85            raw = await self._core._session.get_page(path, params=params)
    86        else:
    87            raw = await self._core._session.get_all_pages_paged(path, params or None)
    88        return cast(
    89            PagedResult[DocumentNote],
    90            PagedResult(
    91                count=raw.count,
    92                next=raw.next,
    93                previous=raw.previous,
    94                all=raw.all_ids,
    95                results=[DocumentNote.model_validate(item) for item in raw.items],
    96            ),
    97        )

Fetch notes attached to a document.

When `page` is `None` (the default), all pages are fetched automatically and `next` / `previous` in the returned `~easypaperless.models.paged_result.PagedResult` are always `None`. When `page` is set to a specific integer, only that one page is fetched and `next` / `previous` contain the raw API values.

###### Arguments:

- document_id: Numeric ID of the document whose notes to retrieve.
- page: Return only this specific page (1-based).
- page_size: Number of results per page.

###### Returns:

> `~easypaperless.models.paged_result.PagedResult` of `~easypaperless.models.documents.DocumentNote` objects, ordered by creation time.

###### Raises:

- ~easypaperless.exceptions.NotFoundError: If no document exists with that ID.

async def create( self, document_id: int, *, note: str) -> easypaperless.DocumentNote: View Source

     99    async def create(self, document_id: int, *, note: str) -> DocumentNote:
    100        """Create a new note on a document.
    101
    102        Args:
    103            document_id: Numeric ID of the document to annotate.
    104            note: Text content of the note.
    105
    106        Returns:
    107            The newly created :class:`~easypaperless.models.documents.DocumentNote`.
    108
    109        Raises:
    110            ~easypaperless.exceptions.NotFoundError: If no document exists
    111                with that ID.
    112        """
    113        logger.info("Creating note for document id=%d", document_id)
    114        resp = await self._core._session.post(
    115            f"/documents/{document_id}/notes/",
    116            json={"note": note},
    117        )
    118        data = resp.json()
    119        if isinstance(data, list):
    120            return DocumentNote.model_validate(data[-1])
    121        return DocumentNote.model_validate(data)

Create a new note on a document.

###### Arguments:

- document_id: Numeric ID of the document to annotate.
- note: Text content of the note.

###### Returns:

> The newly created `~easypaperless.models.documents.DocumentNote`.

###### Raises:

- ~easypaperless.exceptions.NotFoundError: If no document exists with that ID.

async def delete(self, document_id: int, note_id: int) -> None: View Source

    123    async def delete(self, document_id: int, note_id: int) -> None:
    124        """Delete a note from a document.
    125
    126        Args:
    127            document_id: Numeric ID of the document that owns the note.
    128            note_id: Numeric ID of the note to delete.
    129
    130        Raises:
    131            ~easypaperless.exceptions.NotFoundError: If no document or note
    132                exists with the given IDs.
    133        """
    134        logger.info("Deleting note id=%d from document id=%d", note_id, document_id)
    135        await self._core._session.delete(f"/documents/{document_id}/notes/", params={"id": note_id})

Delete a note from a document.

###### Arguments:

- document_id: Numeric ID of the document that owns the note.
- note_id: Numeric ID of the note to delete.

###### Raises:

- ~easypaperless.exceptions.NotFoundError: If no document or note exists with the given IDs.

class StoragePathsResource: View Source

     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`.

StoragePathsResource(core: easypaperless.client._ClientCore) View Source

    24    def __init__(self, core: _ClientCore) -> None:
    25        self._core = core

async def list( self, *, ids: Optional[List[int]] = None, name_contains: str | None = None, name_exact: str | None = None, path_contains: str | None = None, path_exact: str | None = None, page: int | None = None, page_size: int | None = None, ordering: str | None = None, descending: bool = False) -> easypaperless.PagedResult[StoragePath]: View Source

    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.PagedResult` of `~easypaperless.models.storage_paths.StoragePath` objects.

async def get(self, id: int) -> easypaperless.StoragePath: View Source

    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.StoragePath` with the given ID.

###### Raises:

- ~easypaperless.exceptions.NotFoundError: If no storage path exists with that ID.

async def create( self, *, name: str, path: str | easypaperless.Unset = UNSET, match: str | easypaperless.Unset = UNSET, matching_algorithm: easypaperless.MatchingAlgorithm | easypaperless.Unset = UNSET, is_insensitive: bool = True, owner: int | None | easypaperless.Unset = UNSET, set_permissions: easypaperless.SetPermissions | None | easypaperless.Unset = UNSET) -> easypaperless.StoragePath: View Source

    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 `match` is applied. E.g. `matching_algorithm=MatchingAlgorithm.REGEX` for regular-expression matching.
- is_insensitive: When `True`, `match` is case-insensitive. Defaults to `True`, matching the paperless-ngx API default.
- owner: Numeric user ID to assign as owner.
- set_permissions: Explicit view/change permission sets. Pass `None` to create with empty permissions.

###### Returns:

> The newly created `~easypaperless.models.storage_paths.StoragePath`.

async def update( self, id: int, *, name: str | easypaperless.Unset = UNSET, path: str | easypaperless.Unset = UNSET, match: str | easypaperless.Unset = UNSET, matching_algorithm: easypaperless.MatchingAlgorithm | easypaperless.Unset = UNSET, is_insensitive: bool | easypaperless.Unset = UNSET, owner: int | None | easypaperless.Unset = UNSET, set_permissions: easypaperless.SetPermissions | None | easypaperless.Unset = UNSET) -> easypaperless.StoragePath: View Source

    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 `match` is applied. E.g. `matching_algorithm=MatchingAlgorithm.REGEX` for regular-expression matching.
- is_insensitive: When `True`, `match` is case-insensitive.
- owner: Numeric user ID to assign as owner. Pass `None` to clear the owner. Omit (or pass `~easypaperless.UNSET`) to leave unchanged.
- set_permissions: Explicit view/change permission sets. Pass `None` to clear all permissions (overwrite with empty). Omit (or pass `~easypaperless.UNSET`) to leave unchanged.

###### Returns:

> The updated `~easypaperless.models.storage_paths.StoragePath`.

async def delete(self, id: int) -> None: View Source

    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.

async def bulk_delete(self, ids: List[int]) -> None: View Source

    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.

async def bulk_set_permissions( self, ids: List[int], *, set_permissions: easypaperless.SetPermissions | easypaperless.Unset = UNSET, owner: int | None | easypaperless.Unset = UNSET, merge: bool = False) -> None: View Source

    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 `None` to clear the owner. Omit (or pass `~easypaperless.UNSET`) to leave unchanged.
- merge: When `True`, new permissions are merged with existing ones.

class TagsResource: View Source

     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`.

TagsResource(core: easypaperless.client._ClientCore) View Source

    24    def __init__(self, core: _ClientCore) -> None:
    25        self._core = core

async def list( self, *, ids: Optional[List[int]] = None, name_contains: str | None = None, name_exact: str | None = None, page: int | None = None, page_size: int | None = None, ordering: str | None = None, descending: bool = False) -> easypaperless.PagedResult[Tag]: View Source

    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.PagedResult` of `~easypaperless.models.tags.Tag` objects.

async def get(self, id: int) -> easypaperless.Tag: View Source

    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.Tag` with the given ID.

###### Raises:

- ~easypaperless.exceptions.NotFoundError: If no tag exists with that ID.

async def create( self, *, name: str, color: str | easypaperless.Unset = UNSET, is_inbox_tag: bool | easypaperless.Unset = UNSET, match: str | easypaperless.Unset = UNSET, matching_algorithm: easypaperless.MatchingAlgorithm | easypaperless.Unset = UNSET, is_insensitive: bool = True, parent: int | None | easypaperless.Unset = UNSET, owner: int | None | easypaperless.Unset = UNSET, set_permissions: easypaperless.SetPermissions | None | easypaperless.Unset = UNSET) -> easypaperless.Tag: View Source

     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 `match` is applied. E.g. `matching_algorithm=MatchingAlgorithm.REGEX` for regular-expression matching.
- is_insensitive: When `True`, `match` is case-insensitive. Defaults to `True`, 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 `None` to create with empty permissions.

###### Returns:

> The newly created `~easypaperless.models.tags.Tag`.

async def update( self, id: int, *, name: str | easypaperless.Unset = UNSET, color: str | easypaperless.Unset = UNSET, is_inbox_tag: bool | easypaperless.Unset = UNSET, match: str | easypaperless.Unset = UNSET, matching_algorithm: easypaperless.MatchingAlgorithm | easypaperless.Unset = UNSET, is_insensitive: bool | easypaperless.Unset = UNSET, parent: int | None | easypaperless.Unset = UNSET, owner: int | None | easypaperless.Unset = UNSET, set_permissions: easypaperless.SetPermissions | None | easypaperless.Unset = UNSET) -> easypaperless.Tag: View Source

    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 `match` is applied. E.g. `matching_algorithm=MatchingAlgorithm.REGEX` for regular-expression matching.
- is_insensitive: When `True`, `match` is case-insensitive.
- parent: ID of parent tag. Pass `None` to clear (make root tag). Omit (or pass `~easypaperless.UNSET`) to leave unchanged.
- owner: Numeric user ID to assign as owner. Pass `None` to clear the owner. Omit (or pass `~easypaperless.UNSET`) to leave unchanged.
- set_permissions: Explicit view/change permission sets. Pass `None` to clear all permissions (overwrite with empty). Omit (or pass `~easypaperless.UNSET`) to leave unchanged.

###### Returns:

> The updated `~easypaperless.models.tags.Tag`.

async def delete(self, id: int) -> None: View Source

    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.

async def bulk_delete(self, ids: List[int]) -> None: View Source

    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.

async def bulk_set_permissions( self, ids: List[int], *, set_permissions: easypaperless.SetPermissions | easypaperless.Unset = UNSET, owner: int | None | easypaperless.Unset = UNSET, merge: bool = False) -> None: View Source

    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 `None` to clear the owner. Omit (or pass `~easypaperless.UNSET`) to leave unchanged.
- merge: When `True`, new permissions are merged with existing ones.

class SyncCorrespondentsResource: View Source

     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`.

SyncCorrespondentsResource( async_correspondents: CorrespondentsResource, run: Any) View Source

    21    def __init__(self, async_correspondents: CorrespondentsResource, run: Any) -> None:
    22        self._async_correspondents = async_correspondents
    23        self._run = run

def list( self, *, ids: Optional[List[int]] = None, name_contains: str | None = None, name_exact: str | None = None, page: int | None = None, page_size: int | None = None, ordering: str | None = None, descending: bool = False) -> easypaperless.PagedResult[Correspondent]: View Source

    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.PagedResult` of `~easypaperless.models.correspondents.Correspondent` objects.

def get(self, id: int) -> easypaperless.Correspondent: View Source

    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.Correspondent` with the given ID.

###### Raises:

- ~easypaperless.exceptions.NotFoundError: If no correspondent exists with that ID.

def create( self, *, name: str, match: str | easypaperless.Unset = UNSET, matching_algorithm: easypaperless.MatchingAlgorithm | easypaperless.Unset = UNSET, is_insensitive: bool = True, owner: int | None | easypaperless.Unset = UNSET, set_permissions: easypaperless.SetPermissions | None | easypaperless.Unset = UNSET) -> easypaperless.Correspondent: View Source

     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 `match` is applied. E.g. `matching_algorithm=MatchingAlgorithm.REGEX` for regular-expression matching.
- is_insensitive: When `True`, `match` is case-insensitive. Defaults to `True`, matching the paperless-ngx API default.
- owner: Numeric user ID to assign as owner.
- set_permissions: Explicit view/change permission sets. Pass `None` to create with empty permissions.

###### Returns:

> The newly created `~easypaperless.models.correspondents.Correspondent`.

def update( self, id: int, *, name: str | easypaperless.Unset = UNSET, match: str | easypaperless.Unset = UNSET, matching_algorithm: easypaperless.MatchingAlgorithm | easypaperless.Unset = UNSET, is_insensitive: bool | easypaperless.Unset = UNSET, owner: int | None | easypaperless.Unset = UNSET, set_permissions: easypaperless.SetPermissions | None | easypaperless.Unset = UNSET) -> easypaperless.Correspondent: View Source

    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 `match` is applied. E.g. `matching_algorithm=MatchingAlgorithm.REGEX` for regular-expression matching.
- is_insensitive: When `True`, `match` is case-insensitive.
- owner: Numeric user ID to assign as owner. Pass `None` to clear the owner. Omit (or pass `~easypaperless.UNSET`) to leave unchanged.
- set_permissions: Explicit view/change permission sets. Pass `None` to clear all permissions (overwrite with empty). Omit (or pass `~easypaperless.UNSET`) to leave unchanged.

###### Returns:

> The updated `~easypaperless.models.correspondents.Correspondent`.

def delete(self, id: int) -> None: View Source

    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.

def bulk_delete(self, ids: List[int]) -> None: View Source

    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.

def bulk_set_permissions( self, ids: List[int], *, set_permissions: easypaperless.SetPermissions | easypaperless.Unset = UNSET, owner: int | None | easypaperless.Unset = UNSET, merge: bool = False) -> None: View Source

    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 `None` to clear the owner. Omit (or pass `~easypaperless.UNSET`) to leave unchanged.
- merge: When `True`, new permissions are merged with existing ones.

class SyncCustomFieldsResource: View Source

     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`.

SyncCustomFieldsResource( async_custom_fields: CustomFieldsResource, run: Any) View Source

    20    def __init__(self, async_custom_fields: CustomFieldsResource, run: Any) -> None:
    21        self._async_custom_fields = async_custom_fields
    22        self._run = run

def list( self, *, name_contains: str | None = None, name_exact: str | None = None, page: int | None = None, page_size: int | None = None, ordering: str | None = None, descending: bool = False) -> easypaperless.PagedResult[CustomField]: View Source

    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.PagedResult` of `~easypaperless.models.custom_fields.CustomField` objects.

def get(self, id: int) -> easypaperless.CustomField: View Source

    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.CustomField` with the given ID.

###### Raises:

- ~easypaperless.exceptions.NotFoundError: If no custom field exists with that ID.

def create( self, *, name: str, data_type: str, extra_data: typing.Any | None = None, owner: int | None | easypaperless.Unset = UNSET, set_permissions: easypaperless.SetPermissions | None | easypaperless.Unset = UNSET) -> easypaperless.CustomField: View Source

     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 `None` to create with empty permissions.

###### Returns:

> The newly created `~easypaperless.models.custom_fields.CustomField`.

def update( self, id: int, *, name: str | easypaperless.Unset = UNSET, data_type: str | easypaperless.Unset = UNSET, extra_data: typing.Any | None | easypaperless.Unset = UNSET, owner: int | None | easypaperless.Unset = UNSET, set_permissions: easypaperless.SetPermissions | None | easypaperless.Unset = UNSET) -> easypaperless.CustomField: View Source

    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 `None` to clear the owner. Omit (or pass `~easypaperless.UNSET`) to leave unchanged.
- set_permissions: Explicit view/change permission sets. Pass `None` to clear all permissions (overwrite with empty). Omit (or pass `~easypaperless.UNSET`) to leave unchanged.

###### Returns:

> The updated `~easypaperless.models.custom_fields.CustomField`.

def delete(self, id: int) -> None: View Source

    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.

class SyncDocumentTypesResource: View Source

     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`.

SyncDocumentTypesResource( async_document_types: DocumentTypesResource, run: Any) View Source

    21    def __init__(self, async_document_types: DocumentTypesResource, run: Any) -> None:
    22        self._async_document_types = async_document_types
    23        self._run = run

def list( self, *, ids: Optional[List[int]] = None, name_contains: str | None = None, name_exact: str | None = None, page: int | None = None, page_size: int | None = None, ordering: str | None = None, descending: bool = False) -> easypaperless.PagedResult[DocumentType]: View Source

    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.PagedResult` of `~easypaperless.models.document_types.DocumentType` objects.

def get(self, id: int) -> easypaperless.DocumentType: View Source

    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.DocumentType` with the given ID.

###### Raises:

- ~easypaperless.exceptions.NotFoundError: If no document type exists with that ID.

def create( self, *, name: str, match: str | easypaperless.Unset = UNSET, matching_algorithm: easypaperless.MatchingAlgorithm | easypaperless.Unset = UNSET, is_insensitive: bool = True, owner: int | None | easypaperless.Unset = UNSET, set_permissions: easypaperless.SetPermissions | None | easypaperless.Unset = UNSET) -> easypaperless.DocumentType: View Source

     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 `match` is applied. E.g. `matching_algorithm=MatchingAlgorithm.REGEX` for regular-expression matching.
- is_insensitive: When `True`, `match` is case-insensitive. Defaults to `True`, matching the paperless-ngx API default.
- owner: Numeric user ID to assign as owner.
- set_permissions: Explicit view/change permission sets. Pass `None` to create with empty permissions.

###### Returns:

> The newly created `~easypaperless.models.document_types.DocumentType`.

def update( self, id: int, *, name: str | easypaperless.Unset = UNSET, match: str | easypaperless.Unset = UNSET, matching_algorithm: easypaperless.MatchingAlgorithm | easypaperless.Unset = UNSET, is_insensitive: bool | easypaperless.Unset = UNSET, owner: int | None | easypaperless.Unset = UNSET, set_permissions: easypaperless.SetPermissions | None | easypaperless.Unset = UNSET) -> easypaperless.DocumentType: View Source

    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 `match` is applied. E.g. `matching_algorithm=MatchingAlgorithm.REGEX` for regular-expression matching.
- is_insensitive: When `True`, `match` is case-insensitive.
- owner: Numeric user ID to assign as owner. Pass `None` to clear the owner. Omit (or pass `~easypaperless.UNSET`) to leave unchanged.
- set_permissions: Explicit view/change permission sets. Pass `None` to clear all permissions (overwrite with empty). Omit (or pass `~easypaperless.UNSET`) to leave unchanged.

###### Returns:

> The updated `~easypaperless.models.document_types.DocumentType`.

def delete(self, id: int) -> None: View Source

    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.

def bulk_delete(self, ids: List[int]) -> None: View Source

    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.

def bulk_set_permissions( self, ids: List[int], *, set_permissions: easypaperless.SetPermissions | easypaperless.Unset = UNSET, owner: int | None | easypaperless.Unset = UNSET, merge: bool = False) -> None: View Source

    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 `None` to clear the owner. Omit (or pass `~easypaperless.UNSET`) to leave unchanged.
- merge: When `True`, new permissions are merged with existing ones.

class SyncDocumentsResource: View Source

     91class SyncDocumentsResource:
     92    """Sync accessor for documents: ``client.documents``."""
     93
     94    def __init__(self, async_documents: DocumentsResource, run: Any) -> None:
     95        self._async_documents = async_documents
     96        self._run = run
     97        self.notes = SyncNotesResource(async_documents.notes, run)
     98
     99    def get(self, id: int, *, include_metadata: bool = False) -> Document:
    100        """Fetch a single document by its ID.
    101
    102        Args:
    103            id: Numeric paperless-ngx document ID.
    104            include_metadata: When ``True``, the extended file-level metadata
    105                is fetched concurrently and attached to the document.
    106                Default: ``False``.
    107
    108        Returns:
    109            The :class:`~easypaperless.models.documents.Document` with the
    110            given ID.
    111
    112        Raises:
    113            ~easypaperless.exceptions.NotFoundError: If no document exists
    114                with that ID.
    115        """
    116        return cast(
    117            Document, self._run(self._async_documents.get(id, include_metadata=include_metadata))
    118        )
    119
    120    def get_metadata(self, id: int) -> DocumentMetadata:
    121        """Fetch the extended file-level metadata for a document.
    122
    123        Args:
    124            id: Numeric paperless-ngx document ID.
    125
    126        Returns:
    127            A :class:`~easypaperless.models.documents.DocumentMetadata` instance.
    128
    129        Raises:
    130            ~easypaperless.exceptions.NotFoundError: If no document exists
    131                with that ID.
    132        """
    133        return cast(DocumentMetadata, self._run(self._async_documents.get_metadata(id)))
    134
    135    def list(
    136        self,
    137        *,
    138        search: str | None = None,
    139        search_mode: str = "title_or_content",
    140        ids: List[int] | None = None,
    141        tags: List[int | str] | None = None,
    142        any_tags: List[int | str] | None = None,
    143        exclude_tags: List[int | str] | None = None,
    144        correspondent: int | str | None | Unset = UNSET,
    145        any_correspondent: List[int | str] | None = None,
    146        exclude_correspondents: List[int | str] | None = None,
    147        document_type: int | str | None | Unset = UNSET,
    148        document_type_name_contains: str | None = None,
    149        document_type_name_exact: str | None = None,
    150        any_document_type: List[int | str] | None = None,
    151        exclude_document_types: List[int | str] | None = None,
    152        storage_path: int | str | None | Unset = UNSET,
    153        any_storage_paths: List[int | str] | None = None,
    154        exclude_storage_paths: List[int | str] | None = None,
    155        owner: int | None | Unset = UNSET,
    156        exclude_owners: List[int] | None = None,
    157        custom_fields: List[int | str] | None = None,
    158        any_custom_fields: List[int | str] | None = None,
    159        exclude_custom_fields: List[int | str] | None = None,
    160        custom_field_query: List[Any] | None = None,
    161        archive_serial_number: int | None | Unset = UNSET,
    162        archive_serial_number_from: int | None = None,
    163        archive_serial_number_till: int | None = None,
    164        created_after: date | str | None = None,
    165        created_before: date | str | None = None,
    166        added_after: date | datetime | str | None = None,
    167        added_from: date | datetime | str | None = None,
    168        added_before: date | datetime | str | None = None,
    169        added_until: date | datetime | str | None = None,
    170        modified_after: date | datetime | str | None = None,
    171        modified_from: date | datetime | str | None = None,
    172        modified_before: date | datetime | str | None = None,
    173        modified_until: date | datetime | str | None = None,
    174        checksum: str | None = None,
    175        page_size: int = 25,
    176        page: int | None = None,
    177        ordering: str | None = None,
    178        descending: bool = False,
    179        max_results: int | None = None,
    180        on_page: Callable[[int, int | None], None] | None = None,
    181    ) -> PagedResult[Document]:
    182        """Return a filtered list of documents.
    183
    184        All tag, correspondent, document-type, storage-path, and custom-field
    185        parameters accept either integer IDs or string names.
    186
    187        When ``page`` is ``None`` (the default), all pages are fetched
    188        automatically and ``next`` / ``previous`` in the returned
    189        :class:`~easypaperless.models.paged_result.PagedResult` are always
    190        ``None`` — even if ``max_results`` truncates the final result set.
    191        ``count`` always reflects the server total, not the truncated length.
    192        When ``page`` is set to a specific integer, only that one page is
    193        fetched and ``next`` / ``previous`` contain the raw API values.
    194
    195        Args:
    196            search: Search string.  Behaviour depends on ``search_mode``.
    197            search_mode: How ``search`` is applied.  One of:
    198                ``"title_or_content"`` *(default)*, ``"title"``, ``"query"``,
    199                ``"original_filename"``.
    200            ids: Return only documents whose ID is in this list.
    201            tags: Documents must have **all** of these tags (AND semantics).
    202            any_tags: Documents must have **at least one** of these tags.
    203            exclude_tags: Documents must have **none** of these tags.
    204            correspondent: Filter to documents assigned to this correspondent.
    205                Pass ``None`` to return only documents with no correspondent set.
    206            any_correspondent: Filter to documents assigned to any of these.
    207            exclude_correspondents: Exclude documents assigned to any of these.
    208            document_type: Filter to documents of exactly this type.
    209                Pass ``None`` to return only documents with no document type set.
    210            document_type_name_contains: Case-insensitive substring filter on document type name.
    211            document_type_name_exact: Case-insensitive exact match on document type name.
    212            any_document_type: Filter to documents whose type is any of these.
    213            exclude_document_types: Exclude documents whose type is any of these.
    214            storage_path: Filter to documents assigned to this storage path.
    215                Pass ``None`` to return only documents with no storage path set.
    216            any_storage_paths: Filter to documents assigned to any of these paths.
    217            exclude_storage_paths: Exclude documents assigned to any of these paths.
    218            owner: Filter to documents owned by this user ID.
    219                Pass ``None`` to return only documents with no owner set.
    220            exclude_owners: Exclude documents owned by any of these user IDs.
    221            custom_fields: Documents must have **all** of these custom fields set.
    222            any_custom_fields: Documents must have **at least one** of these fields.
    223            exclude_custom_fields: Documents must have **none** of these fields.
    224            custom_field_query: Filter documents by custom field values using a nested
    225                query structure. See the `paperless-ngx API docs
    226                <https://docs.paperless-ngx.com/api/#filtering-by-custom-fields>`_ for
    227                the query format.
    228            archive_serial_number: Filter by exact archive serial number.
    229                Pass ``None`` to return only documents with no ASN set.
    230            archive_serial_number_from: Filter by ASN >= this value.
    231            archive_serial_number_till: Filter by ASN <= this value.
    232            created_after: Only documents created after this date.
    233                String input must be ISO-8601: ``"YYYY-MM-DD"``.
    234            created_before: Only documents created before this date.
    235                String input must be ISO-8601: ``"YYYY-MM-DD"``.
    236            added_after: Only documents added after this date/time.
    237                String input must be ISO-8601: ``"YYYY-MM-DD"`` for date precision or
    238                ``"YYYY-MM-DDTHH:MM:SS"`` for datetime precision.
    239            added_from: Only documents added on or after this date/time.
    240                String input must be ISO-8601: ``"YYYY-MM-DD"`` or ``"YYYY-MM-DDTHH:MM:SS"``.
    241            added_before: Only documents added before this date/time.
    242                String input must be ISO-8601: ``"YYYY-MM-DD"`` or ``"YYYY-MM-DDTHH:MM:SS"``.
    243            added_until: Only documents added on or before this date/time.
    244                String input must be ISO-8601: ``"YYYY-MM-DD"`` or ``"YYYY-MM-DDTHH:MM:SS"``.
    245            modified_after: Only documents modified after this date/time.
    246                String input must be ISO-8601: ``"YYYY-MM-DD"`` or ``"YYYY-MM-DDTHH:MM:SS"``.
    247            modified_from: Only documents modified on or after this date/time.
    248                String input must be ISO-8601: ``"YYYY-MM-DD"`` or ``"YYYY-MM-DDTHH:MM:SS"``.
    249            modified_before: Only documents modified before this date/time.
    250                String input must be ISO-8601: ``"YYYY-MM-DD"`` or ``"YYYY-MM-DDTHH:MM:SS"``.
    251            modified_until: Only documents modified on or before this date/time.
    252                String input must be ISO-8601: ``"YYYY-MM-DD"`` or ``"YYYY-MM-DDTHH:MM:SS"``.
    253            checksum: MD5 checksum of the original file (exact match).
    254            page_size: Number of results per API page.  Default: ``25``.
    255            page: Return only this specific page (1-based).
    256            ordering: Field name to sort by.
    257            descending: When ``True``, reverses the sort direction.
    258            max_results: Stop after collecting this many documents.
    259            on_page: Callback invoked after each page fetch.
    260
    261        Returns:
    262            :class:`~easypaperless.models.paged_result.PagedResult` of
    263            :class:`~easypaperless.models.documents.Document` objects.
    264        """
    265        return cast(
    266            PagedResult[Document],
    267            self._run(
    268                self._async_documents.list(
    269                    search=search,
    270                    search_mode=search_mode,
    271                    ids=ids,
    272                    tags=tags,
    273                    any_tags=any_tags,
    274                    exclude_tags=exclude_tags,
    275                    correspondent=correspondent,
    276                    any_correspondent=any_correspondent,
    277                    exclude_correspondents=exclude_correspondents,
    278                    document_type=document_type,
    279                    document_type_name_contains=document_type_name_contains,
    280                    document_type_name_exact=document_type_name_exact,
    281                    any_document_type=any_document_type,
    282                    exclude_document_types=exclude_document_types,
    283                    storage_path=storage_path,
    284                    any_storage_paths=any_storage_paths,
    285                    exclude_storage_paths=exclude_storage_paths,
    286                    owner=owner,
    287                    exclude_owners=exclude_owners,
    288                    custom_fields=custom_fields,
    289                    any_custom_fields=any_custom_fields,
    290                    exclude_custom_fields=exclude_custom_fields,
    291                    custom_field_query=custom_field_query,
    292                    archive_serial_number=archive_serial_number,
    293                    archive_serial_number_from=archive_serial_number_from,
    294                    archive_serial_number_till=archive_serial_number_till,
    295                    created_after=created_after,
    296                    created_before=created_before,
    297                    added_after=added_after,
    298                    added_from=added_from,
    299                    added_before=added_before,
    300                    added_until=added_until,
    301                    modified_after=modified_after,
    302                    modified_from=modified_from,
    303                    modified_before=modified_before,
    304                    modified_until=modified_until,
    305                    checksum=checksum,
    306                    page_size=page_size,
    307                    page=page,
    308                    ordering=ordering,
    309                    descending=descending,
    310                    max_results=max_results,
    311                    on_page=on_page,
    312                )
    313            ),
    314        )
    315
    316    def update(
    317        self,
    318        id: int,
    319        *,
    320        title: str | Unset = UNSET,
    321        content: str | Unset = UNSET,
    322        created: date | str | None | Unset = UNSET,
    323        correspondent: int | str | None | Unset = UNSET,
    324        document_type: int | str | None | Unset = UNSET,
    325        storage_path: int | str | None | Unset = UNSET,
    326        tags: List[int | str] | None | Unset = UNSET,
    327        archive_serial_number: int | None | Unset = UNSET,
    328        custom_fields: List[dict[str, Any]] | None | Unset = UNSET,
    329        owner: int | None | Unset = UNSET,
    330        set_permissions: SetPermissions | None | Unset = UNSET,
    331        remove_inbox_tags: bool | None | Unset = UNSET,
    332    ) -> Document:
    333        """Partially update a document (PATCH semantics).
    334
    335        Args:
    336            id: Numeric ID of the document to update.
    337            title: New document title.
    338            content: OCR text content of the document.
    339            created: Creation date as an ISO-8601 string (``"YYYY-MM-DD"``) or a
    340                :class:`~datetime.date` object.
    341            correspondent: Correspondent to assign, as an ID or name.
    342                Pass ``None`` to clear the correspondent.
    343            document_type: Document type to assign, as an ID or name.
    344                Pass ``None`` to clear the document type.
    345            storage_path: Storage path to assign, as an ID or name.
    346                Pass ``None`` to clear the storage path.
    347            tags: Full replacement list of tags (IDs or names).
    348            archive_serial_number: Archive serial number to assign.
    349                Pass ``None`` to clear the archive serial number.
    350            custom_fields: List of ``{"field": <field_id>, "value": ...}`` dicts.
    351            owner: Numeric user ID to assign as document owner.
    352                Pass ``None`` to clear the owner.
    353            set_permissions: Explicit view/change permission sets.
    354                Pass ``None`` to clear all permissions (overwrite with empty).
    355                Omit (or pass :data:`~easypaperless.UNSET`) to leave unchanged.
    356            remove_inbox_tags: When ``True``, removes all inbox tags from the document.
    357
    358        Returns:
    359            The updated :class:`~easypaperless.models.documents.Document`.
    360        """
    361        return cast(
    362            Document,
    363            self._run(
    364                self._async_documents.update(
    365                    id,
    366                    title=title,
    367                    content=content,
    368                    created=created,
    369                    correspondent=correspondent,
    370                    document_type=document_type,
    371                    storage_path=storage_path,
    372                    tags=tags,
    373                    archive_serial_number=archive_serial_number,
    374                    custom_fields=custom_fields,
    375                    owner=owner,
    376                    set_permissions=set_permissions,
    377                    remove_inbox_tags=remove_inbox_tags,
    378                )
    379            ),
    380        )
    381
    382    def delete(self, id: int) -> None:
    383        """Permanently delete a document.
    384
    385        Args:
    386            id: Numeric ID of the document to delete.
    387
    388        Raises:
    389            ~easypaperless.exceptions.NotFoundError: If no document exists
    390                with that ID.
    391        """
    392        self._run(self._async_documents.delete(id))
    393
    394    def download(self, id: int, *, original: bool = False) -> bytes:
    395        """Download the binary content of a document.
    396
    397        Args:
    398            id: Numeric ID of the document to download.
    399            original: If ``False`` *(default)*, returns the archived PDF.
    400                If ``True``, returns the original uploaded file.
    401
    402        Returns:
    403            Raw file bytes.
    404        """
    405        return cast(bytes, self._run(self._async_documents.download(id, original=original)))
    406
    407    def upload(
    408        self,
    409        file: str | Path,
    410        *,
    411        title: str | Unset = UNSET,
    412        created: date | str | None = None,
    413        correspondent: int | str | None | Unset = UNSET,
    414        document_type: int | str | None | Unset = UNSET,
    415        storage_path: int | str | None | Unset = UNSET,
    416        tags: List[int | str] | None = None,
    417        archive_serial_number: int | None | Unset = UNSET,
    418        custom_fields: List[dict[str, Any]] | None = None,
    419        wait: bool = False,
    420        poll_interval: float | None = None,
    421        poll_timeout: float | None = None,
    422    ) -> str | Document:
    423        """Upload a document to paperless-ngx.
    424
    425        Args:
    426            file: Path to the file to upload.
    427            title: Title to assign to the document.
    428            created: Creation date as an ISO-8601 string (``"YYYY-MM-DD"``) or a
    429                :class:`~datetime.date` object.
    430            correspondent: Correspondent to assign, as an ID or name.
    431            document_type: Document type to assign, as an ID or name.
    432            storage_path: Storage path to assign, as an ID or name.
    433            tags: Tags to assign, as IDs or names.
    434            archive_serial_number: Archive serial number to assign.
    435            custom_fields: List of ``{"field": <field_id>, "value": ...}`` dicts.
    436            wait: If ``False`` *(default)*, returns immediately with the task ID.
    437                If ``True``, polls until processing completes.
    438            poll_interval: Seconds between task-status checks while waiting for
    439                processing to complete (requires ``wait=True``). Overrides the
    440                client-level default. When omitted, falls back to the client-level
    441                ``poll_interval`` (``2.0`` s unless changed at construction).
    442            poll_timeout: Maximum seconds to wait before raising
    443                :exc:`~easypaperless.exceptions.TaskTimeoutError` (requires
    444                ``wait=True``). Overrides the client-level default. When omitted,
    445                falls back to the client-level ``poll_timeout`` (``60.0`` s unless
    446                changed at construction).
    447
    448        Returns:
    449            The Celery task ID string when ``wait=False``, or the fully
    450            processed :class:`~easypaperless.models.documents.Document`
    451            when ``wait=True``.
    452
    453        Raises:
    454            ~easypaperless.exceptions.UploadError: If processing fails.
    455            ~easypaperless.exceptions.TaskTimeoutError: If timeout is exceeded.
    456        """
    457        return cast(
    458            str | Document,
    459            self._run(
    460                self._async_documents.upload(
    461                    file,
    462                    title=title,
    463                    created=created,
    464                    correspondent=correspondent,
    465                    document_type=document_type,
    466                    storage_path=storage_path,
    467                    tags=tags,
    468                    archive_serial_number=archive_serial_number,
    469                    custom_fields=custom_fields,
    470                    wait=wait,
    471                    poll_interval=poll_interval,
    472                    poll_timeout=poll_timeout,
    473                )
    474            ),
    475        )
    476
    477    def bulk_add_tag(self, document_ids: List[int], tag: int | str) -> None:
    478        """Add a tag to multiple documents in a single request.
    479
    480        Args:
    481            document_ids: List of document IDs to tag.
    482            tag: Tag to add, as an ID or name.
    483        """
    484        self._run(self._async_documents.bulk_add_tag(document_ids, tag))
    485
    486    def bulk_remove_tag(self, document_ids: List[int], tag: int | str) -> None:
    487        """Remove a tag from multiple documents in a single request.
    488
    489        Args:
    490            document_ids: List of document IDs to un-tag.
    491            tag: Tag to remove, as an ID or name.
    492        """
    493        self._run(self._async_documents.bulk_remove_tag(document_ids, tag))
    494
    495    def bulk_modify_tags(
    496        self,
    497        document_ids: List[int],
    498        *,
    499        add_tags: List[int | str] | None = None,
    500        remove_tags: List[int | str] | None = None,
    501    ) -> None:
    502        """Add and/or remove tags on multiple documents atomically.
    503
    504        Args:
    505            document_ids: List of document IDs to modify.
    506            add_tags: Tags to add, as IDs or names.
    507            remove_tags: Tags to remove, as IDs or names.
    508        """
    509        self._run(
    510            self._async_documents.bulk_modify_tags(
    511                document_ids, add_tags=add_tags, remove_tags=remove_tags
    512            )
    513        )
    514
    515    def bulk_delete(self, document_ids: List[int]) -> None:
    516        """Permanently delete multiple documents in a single request.
    517
    518        Args:
    519            document_ids: List of document IDs to delete.
    520        """
    521        self._run(self._async_documents.bulk_delete(document_ids))
    522
    523    def bulk_set_correspondent(
    524        self, document_ids: List[int], correspondent: int | str | None
    525    ) -> None:
    526        """Assign a correspondent to multiple documents in a single request.
    527
    528        Args:
    529            document_ids: List of document IDs to modify.
    530            correspondent: Correspondent to assign, as an ID or name.
    531                Pass ``None`` to clear.
    532        """
    533        self._run(self._async_documents.bulk_set_correspondent(document_ids, correspondent))
    534
    535    def bulk_set_document_type(
    536        self, document_ids: List[int], document_type: int | str | None
    537    ) -> None:
    538        """Assign a document type to multiple documents in a single request.
    539
    540        Args:
    541            document_ids: List of document IDs to modify.
    542            document_type: Document type to assign, as an ID or name.
    543                Pass ``None`` to clear.
    544        """
    545        self._run(self._async_documents.bulk_set_document_type(document_ids, document_type))
    546
    547    def bulk_set_storage_path(
    548        self, document_ids: List[int], storage_path: int | str | None
    549    ) -> None:
    550        """Assign a storage path to multiple documents in a single request.
    551
    552        Args:
    553            document_ids: List of document IDs to modify.
    554            storage_path: Storage path to assign, as an ID or name.
    555                Pass ``None`` to clear.
    556        """
    557        self._run(self._async_documents.bulk_set_storage_path(document_ids, storage_path))
    558
    559    def bulk_modify_custom_fields(
    560        self,
    561        document_ids: List[int],
    562        *,
    563        add_fields: List[dict[str, Any]] | None = None,
    564        remove_fields: List[int] | None = None,
    565    ) -> None:
    566        """Add and/or remove custom field values on multiple documents.
    567
    568        Args:
    569            document_ids: List of document IDs to modify.
    570            add_fields: Custom-field value dicts to add.
    571            remove_fields: Custom-field IDs whose values should be removed.
    572        """
    573        self._run(
    574            self._async_documents.bulk_modify_custom_fields(
    575                document_ids, add_fields=add_fields, remove_fields=remove_fields
    576            )
    577        )
    578
    579    def bulk_set_permissions(
    580        self,
    581        document_ids: List[int],
    582        *,
    583        set_permissions: SetPermissions | Unset = UNSET,
    584        owner: int | None | Unset = UNSET,
    585        merge: bool = False,
    586    ) -> None:
    587        """Set permissions and/or owner on multiple documents.
    588
    589        Args:
    590            document_ids: List of document IDs to modify.
    591            set_permissions: Explicit view/change permission sets.
    592                Omit (or pass :data:`~easypaperless.UNSET`) to leave unchanged.
    593            owner: Numeric user ID to assign as document owner.
    594                Pass ``None`` to clear the owner.
    595                Omit (or pass :data:`~easypaperless.UNSET`) to leave unchanged.
    596            merge: When ``True``, new permissions are merged with existing ones.
    597        """
    598        self._run(
    599            self._async_documents.bulk_set_permissions(
    600                document_ids,
    601                set_permissions=set_permissions,
    602                owner=owner,
    603                merge=merge,
    604            )
    605        )

Sync accessor for documents: `client.documents`.

SyncDocumentsResource( async_documents: DocumentsResource, run: Any) View Source

    94    def __init__(self, async_documents: DocumentsResource, run: Any) -> None:
    95        self._async_documents = async_documents
    96        self._run = run
    97        self.notes = SyncNotesResource(async_documents.notes, run)

notes
def get( self, id: int, *, include_metadata: bool = False) -> easypaperless.Document: View Source

     99    def get(self, id: int, *, include_metadata: bool = False) -> Document:
    100        """Fetch a single document by its ID.
    101
    102        Args:
    103            id: Numeric paperless-ngx document ID.
    104            include_metadata: When ``True``, the extended file-level metadata
    105                is fetched concurrently and attached to the document.
    106                Default: ``False``.
    107
    108        Returns:
    109            The :class:`~easypaperless.models.documents.Document` with the
    110            given ID.
    111
    112        Raises:
    113            ~easypaperless.exceptions.NotFoundError: If no document exists
    114                with that ID.
    115        """
    116        return cast(
    117            Document, self._run(self._async_documents.get(id, include_metadata=include_metadata))
    118        )

Fetch a single document by its ID.

###### Arguments:

- id: Numeric paperless-ngx document ID.
- include_metadata: When `True`, the extended file-level metadata is fetched concurrently and attached to the document. Default: `False`.

###### Returns:

> The `~easypaperless.models.documents.Document` with the given ID.

###### Raises:

- ~easypaperless.exceptions.NotFoundError: If no document exists with that ID.

def get_metadata(self, id: int) -> easypaperless.DocumentMetadata: View Source

    120    def get_metadata(self, id: int) -> DocumentMetadata:
    121        """Fetch the extended file-level metadata for a document.
    122
    123        Args:
    124            id: Numeric paperless-ngx document ID.
    125
    126        Returns:
    127            A :class:`~easypaperless.models.documents.DocumentMetadata` instance.
    128
    129        Raises:
    130            ~easypaperless.exceptions.NotFoundError: If no document exists
    131                with that ID.
    132        """
    133        return cast(DocumentMetadata, self._run(self._async_documents.get_metadata(id)))

Fetch the extended file-level metadata for a document.

###### Arguments:

- id: Numeric paperless-ngx document ID.

###### Returns:

> A `~easypaperless.models.documents.DocumentMetadata` instance.

###### Raises:

- ~easypaperless.exceptions.NotFoundError: If no document exists with that ID.

def list( self, *, search: str | None = None, search_mode: str = 'title_or_content', ids: Optional[List[int]] = None, tags: Optional[List[Union[str, int]]] = None, any_tags: Optional[List[Union[str, int]]] = None, exclude_tags: Optional[List[Union[str, int]]] = None, correspondent: int | str | None | easypaperless.Unset = UNSET, any_correspondent: Optional[List[Union[str, int]]] = None, exclude_correspondents: Optional[List[Union[str, int]]] = None, document_type: int | str | None | easypaperless.Unset = UNSET, document_type_name_contains: str | None = None, document_type_name_exact: str | None = None, any_document_type: Optional[List[Union[str, int]]] = None, exclude_document_types: Optional[List[Union[str, int]]] = None, storage_path: int | str | None | easypaperless.Unset = UNSET, any_storage_paths: Optional[List[Union[str, int]]] = None, exclude_storage_paths: Optional[List[Union[str, int]]] = None, owner: int | None | easypaperless.Unset = UNSET, exclude_owners: Optional[List[int]] = None, custom_fields: Optional[List[Union[str, int]]] = None, any_custom_fields: Optional[List[Union[str, int]]] = None, exclude_custom_fields: Optional[List[Union[str, int]]] = None, custom_field_query: Optional[List[Any]] = None, archive_serial_number: int | None | easypaperless.Unset = UNSET, archive_serial_number_from: int | None = None, archive_serial_number_till: int | None = None, created_after: datetime.date | str | None = None, created_before: datetime.date | str | None = None, added_after: datetime.date | datetime.datetime | str | None = None, added_from: datetime.date | datetime.datetime | str | None = None, added_before: datetime.date | datetime.datetime | str | None = None, added_until: datetime.date | datetime.datetime | str | None = None, modified_after: datetime.date | datetime.datetime | str | None = None, modified_from: datetime.date | datetime.datetime | str | None = None, modified_before: datetime.date | datetime.datetime | str | None = None, modified_until: datetime.date | datetime.datetime | str | None = None, checksum: str | None = None, page_size: int = 25, page: int | None = None, ordering: str | None = None, descending: bool = False, max_results: int | None = None, on_page: Callable[[int, int | None], None] | None = None) -> easypaperless.PagedResult[Document]: View Source

    135    def list(
    136        self,
    137        *,
    138        search: str | None = None,
    139        search_mode: str = "title_or_content",
    140        ids: List[int] | None = None,
    141        tags: List[int | str] | None = None,
    142        any_tags: List[int | str] | None = None,
    143        exclude_tags: List[int | str] | None = None,
    144        correspondent: int | str | None | Unset = UNSET,
    145        any_correspondent: List[int | str] | None = None,
    146        exclude_correspondents: List[int | str] | None = None,
    147        document_type: int | str | None | Unset = UNSET,
    148        document_type_name_contains: str | None = None,
    149        document_type_name_exact: str | None = None,
    150        any_document_type: List[int | str] | None = None,
    151        exclude_document_types: List[int | str] | None = None,
    152        storage_path: int | str | None | Unset = UNSET,
    153        any_storage_paths: List[int | str] | None = None,
    154        exclude_storage_paths: List[int | str] | None = None,
    155        owner: int | None | Unset = UNSET,
    156        exclude_owners: List[int] | None = None,
    157        custom_fields: List[int | str] | None = None,
    158        any_custom_fields: List[int | str] | None = None,
    159        exclude_custom_fields: List[int | str] | None = None,
    160        custom_field_query: List[Any] | None = None,
    161        archive_serial_number: int | None | Unset = UNSET,
    162        archive_serial_number_from: int | None = None,
    163        archive_serial_number_till: int | None = None,
    164        created_after: date | str | None = None,
    165        created_before: date | str | None = None,
    166        added_after: date | datetime | str | None = None,
    167        added_from: date | datetime | str | None = None,
    168        added_before: date | datetime | str | None = None,
    169        added_until: date | datetime | str | None = None,
    170        modified_after: date | datetime | str | None = None,
    171        modified_from: date | datetime | str | None = None,
    172        modified_before: date | datetime | str | None = None,
    173        modified_until: date | datetime | str | None = None,
    174        checksum: str | None = None,
    175        page_size: int = 25,
    176        page: int | None = None,
    177        ordering: str | None = None,
    178        descending: bool = False,
    179        max_results: int | None = None,
    180        on_page: Callable[[int, int | None], None] | None = None,
    181    ) -> PagedResult[Document]:
    182        """Return a filtered list of documents.
    183
    184        All tag, correspondent, document-type, storage-path, and custom-field
    185        parameters accept either integer IDs or string names.
    186
    187        When ``page`` is ``None`` (the default), all pages are fetched
    188        automatically and ``next`` / ``previous`` in the returned
    189        :class:`~easypaperless.models.paged_result.PagedResult` are always
    190        ``None`` — even if ``max_results`` truncates the final result set.
    191        ``count`` always reflects the server total, not the truncated length.
    192        When ``page`` is set to a specific integer, only that one page is
    193        fetched and ``next`` / ``previous`` contain the raw API values.
    194
    195        Args:
    196            search: Search string.  Behaviour depends on ``search_mode``.
    197            search_mode: How ``search`` is applied.  One of:
    198                ``"title_or_content"`` *(default)*, ``"title"``, ``"query"``,
    199                ``"original_filename"``.
    200            ids: Return only documents whose ID is in this list.
    201            tags: Documents must have **all** of these tags (AND semantics).
    202            any_tags: Documents must have **at least one** of these tags.
    203            exclude_tags: Documents must have **none** of these tags.
    204            correspondent: Filter to documents assigned to this correspondent.
    205                Pass ``None`` to return only documents with no correspondent set.
    206            any_correspondent: Filter to documents assigned to any of these.
    207            exclude_correspondents: Exclude documents assigned to any of these.
    208            document_type: Filter to documents of exactly this type.
    209                Pass ``None`` to return only documents with no document type set.
    210            document_type_name_contains: Case-insensitive substring filter on document type name.
    211            document_type_name_exact: Case-insensitive exact match on document type name.
    212            any_document_type: Filter to documents whose type is any of these.
    213            exclude_document_types: Exclude documents whose type is any of these.
    214            storage_path: Filter to documents assigned to this storage path.
    215                Pass ``None`` to return only documents with no storage path set.
    216            any_storage_paths: Filter to documents assigned to any of these paths.
    217            exclude_storage_paths: Exclude documents assigned to any of these paths.
    218            owner: Filter to documents owned by this user ID.
    219                Pass ``None`` to return only documents with no owner set.
    220            exclude_owners: Exclude documents owned by any of these user IDs.
    221            custom_fields: Documents must have **all** of these custom fields set.
    222            any_custom_fields: Documents must have **at least one** of these fields.
    223            exclude_custom_fields: Documents must have **none** of these fields.
    224            custom_field_query: Filter documents by custom field values using a nested
    225                query structure. See the `paperless-ngx API docs
    226                <https://docs.paperless-ngx.com/api/#filtering-by-custom-fields>`_ for
    227                the query format.
    228            archive_serial_number: Filter by exact archive serial number.
    229                Pass ``None`` to return only documents with no ASN set.
    230            archive_serial_number_from: Filter by ASN >= this value.
    231            archive_serial_number_till: Filter by ASN <= this value.
    232            created_after: Only documents created after this date.
    233                String input must be ISO-8601: ``"YYYY-MM-DD"``.
    234            created_before: Only documents created before this date.
    235                String input must be ISO-8601: ``"YYYY-MM-DD"``.
    236            added_after: Only documents added after this date/time.
    237                String input must be ISO-8601: ``"YYYY-MM-DD"`` for date precision or
    238                ``"YYYY-MM-DDTHH:MM:SS"`` for datetime precision.
    239            added_from: Only documents added on or after this date/time.
    240                String input must be ISO-8601: ``"YYYY-MM-DD"`` or ``"YYYY-MM-DDTHH:MM:SS"``.
    241            added_before: Only documents added before this date/time.
    242                String input must be ISO-8601: ``"YYYY-MM-DD"`` or ``"YYYY-MM-DDTHH:MM:SS"``.
    243            added_until: Only documents added on or before this date/time.
    244                String input must be ISO-8601: ``"YYYY-MM-DD"`` or ``"YYYY-MM-DDTHH:MM:SS"``.
    245            modified_after: Only documents modified after this date/time.
    246                String input must be ISO-8601: ``"YYYY-MM-DD"`` or ``"YYYY-MM-DDTHH:MM:SS"``.
    247            modified_from: Only documents modified on or after this date/time.
    248                String input must be ISO-8601: ``"YYYY-MM-DD"`` or ``"YYYY-MM-DDTHH:MM:SS"``.
    249            modified_before: Only documents modified before this date/time.
    250                String input must be ISO-8601: ``"YYYY-MM-DD"`` or ``"YYYY-MM-DDTHH:MM:SS"``.
    251            modified_until: Only documents modified on or before this date/time.
    252                String input must be ISO-8601: ``"YYYY-MM-DD"`` or ``"YYYY-MM-DDTHH:MM:SS"``.
    253            checksum: MD5 checksum of the original file (exact match).
    254            page_size: Number of results per API page.  Default: ``25``.
    255            page: Return only this specific page (1-based).
    256            ordering: Field name to sort by.
    257            descending: When ``True``, reverses the sort direction.
    258            max_results: Stop after collecting this many documents.
    259            on_page: Callback invoked after each page fetch.
    260
    261        Returns:
    262            :class:`~easypaperless.models.paged_result.PagedResult` of
    263            :class:`~easypaperless.models.documents.Document` objects.
    264        """
    265        return cast(
    266            PagedResult[Document],
    267            self._run(
    268                self._async_documents.list(
    269                    search=search,
    270                    search_mode=search_mode,
    271                    ids=ids,
    272                    tags=tags,
    273                    any_tags=any_tags,
    274                    exclude_tags=exclude_tags,
    275                    correspondent=correspondent,
    276                    any_correspondent=any_correspondent,
    277                    exclude_correspondents=exclude_correspondents,
    278                    document_type=document_type,
    279                    document_type_name_contains=document_type_name_contains,
    280                    document_type_name_exact=document_type_name_exact,
    281                    any_document_type=any_document_type,
    282                    exclude_document_types=exclude_document_types,
    283                    storage_path=storage_path,
    284                    any_storage_paths=any_storage_paths,
    285                    exclude_storage_paths=exclude_storage_paths,
    286                    owner=owner,
    287                    exclude_owners=exclude_owners,
    288                    custom_fields=custom_fields,
    289                    any_custom_fields=any_custom_fields,
    290                    exclude_custom_fields=exclude_custom_fields,
    291                    custom_field_query=custom_field_query,
    292                    archive_serial_number=archive_serial_number,
    293                    archive_serial_number_from=archive_serial_number_from,
    294                    archive_serial_number_till=archive_serial_number_till,
    295                    created_after=created_after,
    296                    created_before=created_before,
    297                    added_after=added_after,
    298                    added_from=added_from,
    299                    added_before=added_before,
    300                    added_until=added_until,
    301                    modified_after=modified_after,
    302                    modified_from=modified_from,
    303                    modified_before=modified_before,
    304                    modified_until=modified_until,
    305                    checksum=checksum,
    306                    page_size=page_size,
    307                    page=page,
    308                    ordering=ordering,
    309                    descending=descending,
    310                    max_results=max_results,
    311                    on_page=on_page,
    312                )
    313            ),
    314        )

Return a filtered list of documents.

All tag, correspondent, document-type, storage-path, and custom-field parameters accept either integer IDs or string names.

When `page` is `None` (the default), all pages are fetched automatically and `next` / `previous` in the returned `~easypaperless.models.paged_result.PagedResult` are always `None` — even if `max_results` truncates the final result set. `count` always reflects the server total, not the truncated length. When `page` is set to a specific integer, only that one page is fetched and `next` / `previous` contain the raw API values.

###### Arguments:

- search: Search string. Behaviour depends on `search_mode`.
- search_mode: How `search` is 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 `None` to 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 `None` to 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 `None` to 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 `None` to 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 `None` to 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.PagedResult` of `~easypaperless.models.documents.Document` objects.

def update( self, id: int, *, title: str | easypaperless.Unset = UNSET, content: str | easypaperless.Unset = UNSET, created: datetime.date | str | None | easypaperless.Unset = UNSET, correspondent: int | str | None | easypaperless.Unset = UNSET, document_type: int | str | None | easypaperless.Unset = UNSET, storage_path: int | str | None | easypaperless.Unset = UNSET, tags: Union[List[Union[str, int]], NoneType, easypaperless.Unset] = UNSET, archive_serial_number: int | None | easypaperless.Unset = UNSET, custom_fields: Union[List[dict[str, Any]], NoneType, easypaperless.Unset] = UNSET, owner: int | None | easypaperless.Unset = UNSET, set_permissions: easypaperless.SetPermissions | None | easypaperless.Unset = UNSET, remove_inbox_tags: bool | None | easypaperless.Unset = UNSET) -> easypaperless.Document: View Source

    316    def update(
    317        self,
    318        id: int,
    319        *,
    320        title: str | Unset = UNSET,
    321        content: str | Unset = UNSET,
    322        created: date | str | None | Unset = UNSET,
    323        correspondent: int | str | None | Unset = UNSET,
    324        document_type: int | str | None | Unset = UNSET,
    325        storage_path: int | str | None | Unset = UNSET,
    326        tags: List[int | str] | None | Unset = UNSET,
    327        archive_serial_number: int | None | Unset = UNSET,
    328        custom_fields: List[dict[str, Any]] | None | Unset = UNSET,
    329        owner: int | None | Unset = UNSET,
    330        set_permissions: SetPermissions | None | Unset = UNSET,
    331        remove_inbox_tags: bool | None | Unset = UNSET,
    332    ) -> Document:
    333        """Partially update a document (PATCH semantics).
    334
    335        Args:
    336            id: Numeric ID of the document to update.
    337            title: New document title.
    338            content: OCR text content of the document.
    339            created: Creation date as an ISO-8601 string (``"YYYY-MM-DD"``) or a
    340                :class:`~datetime.date` object.
    341            correspondent: Correspondent to assign, as an ID or name.
    342                Pass ``None`` to clear the correspondent.
    343            document_type: Document type to assign, as an ID or name.
    344                Pass ``None`` to clear the document type.
    345            storage_path: Storage path to assign, as an ID or name.
    346                Pass ``None`` to clear the storage path.
    347            tags: Full replacement list of tags (IDs or names).
    348            archive_serial_number: Archive serial number to assign.
    349                Pass ``None`` to clear the archive serial number.
    350            custom_fields: List of ``{"field": <field_id>, "value": ...}`` dicts.
    351            owner: Numeric user ID to assign as document owner.
    352                Pass ``None`` to clear the owner.
    353            set_permissions: Explicit view/change permission sets.
    354                Pass ``None`` to clear all permissions (overwrite with empty).
    355                Omit (or pass :data:`~easypaperless.UNSET`) to leave unchanged.
    356            remove_inbox_tags: When ``True``, removes all inbox tags from the document.
    357
    358        Returns:
    359            The updated :class:`~easypaperless.models.documents.Document`.
    360        """
    361        return cast(
    362            Document,
    363            self._run(
    364                self._async_documents.update(
    365                    id,
    366                    title=title,
    367                    content=content,
    368                    created=created,
    369                    correspondent=correspondent,
    370                    document_type=document_type,
    371                    storage_path=storage_path,
    372                    tags=tags,
    373                    archive_serial_number=archive_serial_number,
    374                    custom_fields=custom_fields,
    375                    owner=owner,
    376                    set_permissions=set_permissions,
    377                    remove_inbox_tags=remove_inbox_tags,
    378                )
    379            ),
    380        )

Partially update a document (PATCH semantics).

###### Arguments:

- id: Numeric ID of the document to update.
- title: New document title.
- content: OCR text content of the document.
- created: Creation date as an ISO-8601 string (`"YYYY-MM-DD"`) or a `~datetime.date` object.
- correspondent: Correspondent to assign, as an ID or name. Pass `None` to clear the correspondent.
- document_type: Document type to assign, as an ID or name. Pass `None` to clear the document type.
- storage_path: Storage path to assign, as an ID or name. Pass `None` to clear the storage path.
- tags: Full replacement list of tags (IDs or names).
- archive_serial_number: Archive serial number to assign. Pass `None` to clear the archive serial number.
- custom_fields: List of `{"field": <field_id>, "value": ...}` dicts.
- owner: Numeric user ID to assign as document owner. Pass `None` to clear the owner.
- set_permissions: Explicit view/change permission sets. Pass `None` to 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`.

def delete(self, id: int) -> None: View Source

    382    def delete(self, id: int) -> None:
    383        """Permanently delete a document.
    384
    385        Args:
    386            id: Numeric ID of the document to delete.
    387
    388        Raises:
    389            ~easypaperless.exceptions.NotFoundError: If no document exists
    390                with that ID.
    391        """
    392        self._run(self._async_documents.delete(id))

Permanently delete a document.

###### Arguments:

- id: Numeric ID of the document to delete.

###### Raises:

- ~easypaperless.exceptions.NotFoundError: If no document exists with that ID.

def download(self, id: int, *, original: bool = False) -> bytes: View Source

    394    def download(self, id: int, *, original: bool = False) -> bytes:
    395        """Download the binary content of a document.
    396
    397        Args:
    398            id: Numeric ID of the document to download.
    399            original: If ``False`` *(default)*, returns the archived PDF.
    400                If ``True``, returns the original uploaded file.
    401
    402        Returns:
    403            Raw file bytes.
    404        """
    405        return cast(bytes, self._run(self._async_documents.download(id, original=original)))

Download the binary content of a document.

###### Arguments:

- id: Numeric ID of the document to download.
- original: If `False` (default), returns the archived PDF. If `True`, returns the original uploaded file.

###### Returns:

> Raw file bytes.

def upload( self, file: str | pathlib._local.Path, *, title: str | easypaperless.Unset = UNSET, created: datetime.date | str | None = None, correspondent: int | str | None | easypaperless.Unset = UNSET, document_type: int | str | None | easypaperless.Unset = UNSET, storage_path: int | str | None | easypaperless.Unset = UNSET, tags: Optional[List[Union[str, int]]] = None, archive_serial_number: int | None | easypaperless.Unset = UNSET, custom_fields: Optional[List[dict[str, Any]]] = None, wait: bool = False, poll_interval: float | None = None, poll_timeout: float | None = None) -> str | easypaperless.Document: View Source

    407    def upload(
    408        self,
    409        file: str | Path,
    410        *,
    411        title: str | Unset = UNSET,
    412        created: date | str | None = None,
    413        correspondent: int | str | None | Unset = UNSET,
    414        document_type: int | str | None | Unset = UNSET,
    415        storage_path: int | str | None | Unset = UNSET,
    416        tags: List[int | str] | None = None,
    417        archive_serial_number: int | None | Unset = UNSET,
    418        custom_fields: List[dict[str, Any]] | None = None,
    419        wait: bool = False,
    420        poll_interval: float | None = None,
    421        poll_timeout: float | None = None,
    422    ) -> str | Document:
    423        """Upload a document to paperless-ngx.
    424
    425        Args:
    426            file: Path to the file to upload.
    427            title: Title to assign to the document.
    428            created: Creation date as an ISO-8601 string (``"YYYY-MM-DD"``) or a
    429                :class:`~datetime.date` object.
    430            correspondent: Correspondent to assign, as an ID or name.
    431            document_type: Document type to assign, as an ID or name.
    432            storage_path: Storage path to assign, as an ID or name.
    433            tags: Tags to assign, as IDs or names.
    434            archive_serial_number: Archive serial number to assign.
    435            custom_fields: List of ``{"field": <field_id>, "value": ...}`` dicts.
    436            wait: If ``False`` *(default)*, returns immediately with the task ID.
    437                If ``True``, polls until processing completes.
    438            poll_interval: Seconds between task-status checks while waiting for
    439                processing to complete (requires ``wait=True``). Overrides the
    440                client-level default. When omitted, falls back to the client-level
    441                ``poll_interval`` (``2.0`` s unless changed at construction).
    442            poll_timeout: Maximum seconds to wait before raising
    443                :exc:`~easypaperless.exceptions.TaskTimeoutError` (requires
    444                ``wait=True``). Overrides the client-level default. When omitted,
    445                falls back to the client-level ``poll_timeout`` (``60.0`` s unless
    446                changed at construction).
    447
    448        Returns:
    449            The Celery task ID string when ``wait=False``, or the fully
    450            processed :class:`~easypaperless.models.documents.Document`
    451            when ``wait=True``.
    452
    453        Raises:
    454            ~easypaperless.exceptions.UploadError: If processing fails.
    455            ~easypaperless.exceptions.TaskTimeoutError: If timeout is exceeded.
    456        """
    457        return cast(
    458            str | Document,
    459            self._run(
    460                self._async_documents.upload(
    461                    file,
    462                    title=title,
    463                    created=created,
    464                    correspondent=correspondent,
    465                    document_type=document_type,
    466                    storage_path=storage_path,
    467                    tags=tags,
    468                    archive_serial_number=archive_serial_number,
    469                    custom_fields=custom_fields,
    470                    wait=wait,
    471                    poll_interval=poll_interval,
    472                    poll_timeout=poll_timeout,
    473                )
    474            ),
    475        )

Upload a document to paperless-ngx.

###### Arguments:

- file: Path to the file to upload.
- title: Title to assign to the document.
- created: Creation date as an ISO-8601 string (`"YYYY-MM-DD"`) or a `~datetime.date` object.
- 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. If `True`, 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-level `poll_interval` (`2.0` s unless changed at construction).
- poll_timeout: Maximum seconds to wait before raising `~easypaperless.exceptions.TaskTimeoutError` (requires `wait=True`). Overrides the client-level default. When omitted, falls back to the client-level `poll_timeout` (`60.0` s unless changed at construction).

###### Returns:

> The Celery task ID string when `wait=False`, or the fully processed `~easypaperless.models.documents.Document` when `wait=True`.

###### Raises:

- ~easypaperless.exceptions.UploadError: If processing fails.
- ~easypaperless.exceptions.TaskTimeoutError: If timeout is exceeded.

def bulk_add_tag(self, document_ids: List[int], tag: int | str) -> None: View Source

    477    def bulk_add_tag(self, document_ids: List[int], tag: int | str) -> None:
    478        """Add a tag to multiple documents in a single request.
    479
    480        Args:
    481            document_ids: List of document IDs to tag.
    482            tag: Tag to add, as an ID or name.
    483        """
    484        self._run(self._async_documents.bulk_add_tag(document_ids, tag))

Add a tag to multiple documents in a single request.

###### Arguments:

- document_ids: List of document IDs to tag.
- tag: Tag to add, as an ID or name.

def bulk_remove_tag(self, document_ids: List[int], tag: int | str) -> None: View Source

    486    def bulk_remove_tag(self, document_ids: List[int], tag: int | str) -> None:
    487        """Remove a tag from multiple documents in a single request.
    488
    489        Args:
    490            document_ids: List of document IDs to un-tag.
    491            tag: Tag to remove, as an ID or name.
    492        """
    493        self._run(self._async_documents.bulk_remove_tag(document_ids, tag))

Remove a tag from multiple documents in a single request.

###### Arguments:

- document_ids: List of document IDs to un-tag.
- tag: Tag to remove, as an ID or name.

def bulk_modify_tags( self, document_ids: List[int], *, add_tags: Optional[List[Union[str, int]]] = None, remove_tags: Optional[List[Union[str, int]]] = None) -> None: View Source

    495    def bulk_modify_tags(
    496        self,
    497        document_ids: List[int],
    498        *,
    499        add_tags: List[int | str] | None = None,
    500        remove_tags: List[int | str] | None = None,
    501    ) -> None:
    502        """Add and/or remove tags on multiple documents atomically.
    503
    504        Args:
    505            document_ids: List of document IDs to modify.
    506            add_tags: Tags to add, as IDs or names.
    507            remove_tags: Tags to remove, as IDs or names.
    508        """
    509        self._run(
    510            self._async_documents.bulk_modify_tags(
    511                document_ids, add_tags=add_tags, remove_tags=remove_tags
    512            )
    513        )

Add and/or remove tags on multiple documents atomically.

###### Arguments:

- document_ids: List of document IDs to modify.
- add_tags: Tags to add, as IDs or names.
- remove_tags: Tags to remove, as IDs or names.

def bulk_delete(self, document_ids: List[int]) -> None: View Source

    515    def bulk_delete(self, document_ids: List[int]) -> None:
    516        """Permanently delete multiple documents in a single request.
    517
    518        Args:
    519            document_ids: List of document IDs to delete.
    520        """
    521        self._run(self._async_documents.bulk_delete(document_ids))

Permanently delete multiple documents in a single request.

###### Arguments:

- document_ids: List of document IDs to delete.

def bulk_set_correspondent(self, document_ids: List[int], correspondent: int | str | None) -> None: View Source

    523    def bulk_set_correspondent(
    524        self, document_ids: List[int], correspondent: int | str | None
    525    ) -> None:
    526        """Assign a correspondent to multiple documents in a single request.
    527
    528        Args:
    529            document_ids: List of document IDs to modify.
    530            correspondent: Correspondent to assign, as an ID or name.
    531                Pass ``None`` to clear.
    532        """
    533        self._run(self._async_documents.bulk_set_correspondent(document_ids, correspondent))

Assign a correspondent to multiple documents in a single request.

###### Arguments:

- document_ids: List of document IDs to modify.
- correspondent: Correspondent to assign, as an ID or name. Pass `None` to clear.

def bulk_set_document_type(self, document_ids: List[int], document_type: int | str | None) -> None: View Source

    535    def bulk_set_document_type(
    536        self, document_ids: List[int], document_type: int | str | None
    537    ) -> None:
    538        """Assign a document type to multiple documents in a single request.
    539
    540        Args:
    541            document_ids: List of document IDs to modify.
    542            document_type: Document type to assign, as an ID or name.
    543                Pass ``None`` to clear.
    544        """
    545        self._run(self._async_documents.bulk_set_document_type(document_ids, document_type))

Assign a document type to multiple documents in a single request.

###### Arguments:

- document_ids: List of document IDs to modify.
- document_type: Document type to assign, as an ID or name. Pass `None` to clear.

def bulk_set_storage_path(self, document_ids: List[int], storage_path: int | str | None) -> None: View Source

    547    def bulk_set_storage_path(
    548        self, document_ids: List[int], storage_path: int | str | None
    549    ) -> None:
    550        """Assign a storage path to multiple documents in a single request.
    551
    552        Args:
    553            document_ids: List of document IDs to modify.
    554            storage_path: Storage path to assign, as an ID or name.
    555                Pass ``None`` to clear.
    556        """
    557        self._run(self._async_documents.bulk_set_storage_path(document_ids, storage_path))

Assign a storage path to multiple documents in a single request.

###### Arguments:

- document_ids: List of document IDs to modify.
- storage_path: Storage path to assign, as an ID or name. Pass `None` to clear.

def bulk_modify_custom_fields( self, document_ids: List[int], *, add_fields: Optional[List[dict[str, Any]]] = None, remove_fields: Optional[List[int]] = None) -> None: View Source

    559    def bulk_modify_custom_fields(
    560        self,
    561        document_ids: List[int],
    562        *,
    563        add_fields: List[dict[str, Any]] | None = None,
    564        remove_fields: List[int] | None = None,
    565    ) -> None:
    566        """Add and/or remove custom field values on multiple documents.
    567
    568        Args:
    569            document_ids: List of document IDs to modify.
    570            add_fields: Custom-field value dicts to add.
    571            remove_fields: Custom-field IDs whose values should be removed.
    572        """
    573        self._run(
    574            self._async_documents.bulk_modify_custom_fields(
    575                document_ids, add_fields=add_fields, remove_fields=remove_fields
    576            )
    577        )

Add and/or remove custom field values on multiple documents.

###### Arguments:

- document_ids: List of document IDs to modify.
- add_fields: Custom-field value dicts to add.
- remove_fields: Custom-field IDs whose values should be removed.

def bulk_set_permissions( self, document_ids: List[int], *, set_permissions: easypaperless.SetPermissions | easypaperless.Unset = UNSET, owner: int | None | easypaperless.Unset = UNSET, merge: bool = False) -> None: View Source

    579    def bulk_set_permissions(
    580        self,
    581        document_ids: List[int],
    582        *,
    583        set_permissions: SetPermissions | Unset = UNSET,
    584        owner: int | None | Unset = UNSET,
    585        merge: bool = False,
    586    ) -> None:
    587        """Set permissions and/or owner on multiple documents.
    588
    589        Args:
    590            document_ids: List of document IDs to modify.
    591            set_permissions: Explicit view/change permission sets.
    592                Omit (or pass :data:`~easypaperless.UNSET`) to leave unchanged.
    593            owner: Numeric user ID to assign as document owner.
    594                Pass ``None`` to clear the owner.
    595                Omit (or pass :data:`~easypaperless.UNSET`) to leave unchanged.
    596            merge: When ``True``, new permissions are merged with existing ones.
    597        """
    598        self._run(
    599            self._async_documents.bulk_set_permissions(
    600                document_ids,
    601                set_permissions=set_permissions,
    602                owner=owner,
    603                merge=merge,
    604            )
    605        )

Set permissions and/or owner on multiple documents.

###### Arguments:

- document_ids: List of document IDs to modify.
- set_permissions: Explicit view/change permission sets. Omit (or pass `~easypaperless.UNSET`) to leave unchanged.
- owner: Numeric user ID to assign as document owner. Pass `None` to clear the owner. Omit (or pass `~easypaperless.UNSET`) to leave unchanged.
- merge: When `True`, new permissions are merged with existing ones.

class SyncNotesResource: View Source

    20class SyncNotesResource:
    21    """Sync accessor for document notes: ``client.documents.notes``."""
    22
    23    def __init__(self, async_notes: NotesResource, run: Any) -> None:
    24        self._async_notes = async_notes
    25        self._run = run
    26
    27    def list(
    28        self,
    29        document_id: int,
    30        *,
    31        page: int | None = None,
    32        page_size: int | None = None,
    33    ) -> PagedResult[DocumentNote]:
    34        """Fetch notes attached to a document.
    35
    36        When ``page`` is ``None`` (the default), all pages are fetched
    37        automatically and ``next`` / ``previous`` in the returned
    38        :class:`~easypaperless.models.paged_result.PagedResult` are always
    39        ``None``.  When ``page`` is set to a specific integer, only that one
    40        page is fetched and ``next`` / ``previous`` contain the raw API values.
    41
    42        Args:
    43            document_id: Numeric ID of the document whose notes to retrieve.
    44            page: Return only this specific page (1-based).
    45            page_size: Number of results per page.
    46
    47        Returns:
    48            :class:`~easypaperless.models.paged_result.PagedResult` of
    49            :class:`~easypaperless.models.documents.DocumentNote` objects,
    50            ordered by creation time.
    51
    52        Raises:
    53            ~easypaperless.exceptions.NotFoundError: If no document exists
    54                with that ID.
    55        """
    56        return cast(
    57            PagedResult[DocumentNote],
    58            self._run(self._async_notes.list(document_id, page=page, page_size=page_size)),
    59        )
    60
    61    def create(self, document_id: int, *, note: str) -> DocumentNote:
    62        """Create a new note on a document.
    63
    64        Args:
    65            document_id: Numeric ID of the document to annotate.
    66            note: Text content of the note.
    67
    68        Returns:
    69            The newly created :class:`~easypaperless.models.documents.DocumentNote`.
    70
    71        Raises:
    72            ~easypaperless.exceptions.NotFoundError: If no document exists
    73                with that ID.
    74        """
    75        return cast(DocumentNote, self._run(self._async_notes.create(document_id, note=note)))
    76
    77    def delete(self, document_id: int, note_id: int) -> None:
    78        """Delete a note from a document.
    79
    80        Args:
    81            document_id: Numeric ID of the document that owns the note.
    82            note_id: Numeric ID of the note to delete.
    83
    84        Raises:
    85            ~easypaperless.exceptions.NotFoundError: If no document or note
    86                exists with the given IDs.
    87        """
    88        self._run(self._async_notes.delete(document_id, note_id))

Sync accessor for document notes: `client.documents.notes`.

SyncNotesResource( async_notes: NotesResource, run: Any) View Source

    23    def __init__(self, async_notes: NotesResource, run: Any) -> None:
    24        self._async_notes = async_notes
    25        self._run = run

def list( self, document_id: int, *, page: int | None = None, page_size: int | None = None) -> easypaperless.PagedResult[DocumentNote]: View Source

    27    def list(
    28        self,
    29        document_id: int,
    30        *,
    31        page: int | None = None,
    32        page_size: int | None = None,
    33    ) -> PagedResult[DocumentNote]:
    34        """Fetch notes attached to a document.
    35
    36        When ``page`` is ``None`` (the default), all pages are fetched
    37        automatically and ``next`` / ``previous`` in the returned
    38        :class:`~easypaperless.models.paged_result.PagedResult` are always
    39        ``None``.  When ``page`` is set to a specific integer, only that one
    40        page is fetched and ``next`` / ``previous`` contain the raw API values.
    41
    42        Args:
    43            document_id: Numeric ID of the document whose notes to retrieve.
    44            page: Return only this specific page (1-based).
    45            page_size: Number of results per page.
    46
    47        Returns:
    48            :class:`~easypaperless.models.paged_result.PagedResult` of
    49            :class:`~easypaperless.models.documents.DocumentNote` objects,
    50            ordered by creation time.
    51
    52        Raises:
    53            ~easypaperless.exceptions.NotFoundError: If no document exists
    54                with that ID.
    55        """
    56        return cast(
    57            PagedResult[DocumentNote],
    58            self._run(self._async_notes.list(document_id, page=page, page_size=page_size)),
    59        )

Fetch notes attached to a document.

When `page` is `None` (the default), all pages are fetched automatically and `next` / `previous` in the returned `~easypaperless.models.paged_result.PagedResult` are always `None`. When `page` is set to a specific integer, only that one page is fetched and `next` / `previous` contain the raw API values.

###### Arguments:

- document_id: Numeric ID of the document whose notes to retrieve.
- page: Return only this specific page (1-based).
- page_size: Number of results per page.

###### Returns:

> `~easypaperless.models.paged_result.PagedResult` of `~easypaperless.models.documents.DocumentNote` objects, ordered by creation time.

###### Raises:

- ~easypaperless.exceptions.NotFoundError: If no document exists with that ID.

def create( self, document_id: int, *, note: str) -> easypaperless.DocumentNote: View Source

    61    def create(self, document_id: int, *, note: str) -> DocumentNote:
    62        """Create a new note on a document.
    63
    64        Args:
    65            document_id: Numeric ID of the document to annotate.
    66            note: Text content of the note.
    67
    68        Returns:
    69            The newly created :class:`~easypaperless.models.documents.DocumentNote`.
    70
    71        Raises:
    72            ~easypaperless.exceptions.NotFoundError: If no document exists
    73                with that ID.
    74        """
    75        return cast(DocumentNote, self._run(self._async_notes.create(document_id, note=note)))

Create a new note on a document.

###### Arguments:

- document_id: Numeric ID of the document to annotate.
- note: Text content of the note.

###### Returns:

> The newly created `~easypaperless.models.documents.DocumentNote`.

###### Raises:

- ~easypaperless.exceptions.NotFoundError: If no document exists with that ID.

def delete(self, document_id: int, note_id: int) -> None: View Source

    77    def delete(self, document_id: int, note_id: int) -> None:
    78        """Delete a note from a document.
    79
    80        Args:
    81            document_id: Numeric ID of the document that owns the note.
    82            note_id: Numeric ID of the note to delete.
    83
    84        Raises:
    85            ~easypaperless.exceptions.NotFoundError: If no document or note
    86                exists with the given IDs.
    87        """
    88        self._run(self._async_notes.delete(document_id, note_id))

Delete a note from a document.

###### Arguments:

- document_id: Numeric ID of the document that owns the note.
- note_id: Numeric ID of the note to delete.

###### Raises:

- ~easypaperless.exceptions.NotFoundError: If no document or note exists with the given IDs.

class SyncStoragePathsResource: View Source

     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`.

SyncStoragePathsResource( async_storage_paths: StoragePathsResource, run: Any) View Source

    21    def __init__(self, async_storage_paths: StoragePathsResource, run: Any) -> None:
    22        self._async_storage_paths = async_storage_paths
    23        self._run = run

def list( self, *, ids: Optional[List[int]] = None, name_contains: str | None = None, name_exact: str | None = None, path_contains: str | None = None, path_exact: str | None = None, page: int | None = None, page_size: int | None = None, ordering: str | None = None, descending: bool = False) -> easypaperless.PagedResult[StoragePath]: View Source

    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.PagedResult` of `~easypaperless.models.storage_paths.StoragePath` objects.

def get(self, id: int) -> easypaperless.StoragePath: View Source

    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.StoragePath` with the given ID.

###### Raises:

- ~easypaperless.exceptions.NotFoundError: If no storage path exists with that ID.

def create( self, *, name: str, path: str | easypaperless.Unset = UNSET, match: str | easypaperless.Unset = UNSET, matching_algorithm: easypaperless.MatchingAlgorithm | easypaperless.Unset = UNSET, is_insensitive: bool = True, owner: int | None | easypaperless.Unset = UNSET, set_permissions: easypaperless.SetPermissions | None | easypaperless.Unset = UNSET) -> easypaperless.StoragePath: View Source

     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 `match` is applied. E.g. `matching_algorithm=MatchingAlgorithm.REGEX` for regular-expression matching.
- is_insensitive: When `True`, `match` is case-insensitive. Defaults to `True`, matching the paperless-ngx API default.
- owner: Numeric user ID to assign as owner.
- set_permissions: Explicit view/change permission sets. Pass `None` to create with empty permissions.

###### Returns:

> The newly created `~easypaperless.models.storage_paths.StoragePath`.

def update( self, id: int, *, name: str | easypaperless.Unset = UNSET, path: str | easypaperless.Unset = UNSET, match: str | easypaperless.Unset = UNSET, matching_algorithm: easypaperless.MatchingAlgorithm | easypaperless.Unset = UNSET, is_insensitive: bool | easypaperless.Unset = UNSET, owner: int | None | easypaperless.Unset = UNSET, set_permissions: easypaperless.SetPermissions | None | easypaperless.Unset = UNSET) -> easypaperless.StoragePath: View Source

    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 `match` is applied. E.g. `matching_algorithm=MatchingAlgorithm.REGEX` for regular-expression matching.
- is_insensitive: When `True`, `match` is case-insensitive.
- owner: Numeric user ID to assign as owner. Pass `None` to clear the owner. Omit (or pass `~easypaperless.UNSET`) to leave unchanged.
- set_permissions: Explicit view/change permission sets. Pass `None` to clear all permissions (overwrite with empty). Omit (or pass `~easypaperless.UNSET`) to leave unchanged.

###### Returns:

> The updated `~easypaperless.models.storage_paths.StoragePath`.

def delete(self, id: int) -> None: View Source

    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.

def bulk_delete(self, ids: List[int]) -> None: View Source

    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.

def bulk_set_permissions( self, ids: List[int], *, set_permissions: easypaperless.SetPermissions | easypaperless.Unset = UNSET, owner: int | None | easypaperless.Unset = UNSET, merge: bool = False) -> None: View Source

    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 `None` to clear the owner. Omit (or pass `~easypaperless.UNSET`) to leave unchanged.
- merge: When `True`, new permissions are merged with existing ones.

class SyncTagsResource: View Source

     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`.

SyncTagsResource( async_tags: TagsResource, run: Any) View Source

    21    def __init__(self, async_tags: TagsResource, run: Any) -> None:
    22        self._async_tags = async_tags
    23        self._run = run

def list( self, *, ids: Optional[List[int]] = None, name_contains: str | None = None, name_exact: str | None = None, page: int | None = None, page_size: int | None = None, ordering: str | None = None, descending: bool = False) -> easypaperless.PagedResult[Tag]: View Source

    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.PagedResult` of `~easypaperless.models.tags.Tag` objects.

def get(self, id: int) -> easypaperless.Tag: View Source

    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.Tag` with the given ID.

###### Raises:

- ~easypaperless.exceptions.NotFoundError: If no tag exists with that ID.

def create( self, *, name: str, color: str | easypaperless.Unset = UNSET, is_inbox_tag: bool | easypaperless.Unset = UNSET, match: str | easypaperless.Unset = UNSET, matching_algorithm: easypaperless.MatchingAlgorithm | easypaperless.Unset = UNSET, is_insensitive: bool = True, parent: int | None | easypaperless.Unset = UNSET, owner: int | None | easypaperless.Unset = UNSET, set_permissions: easypaperless.SetPermissions | None | easypaperless.Unset = UNSET) -> easypaperless.Tag: View Source

     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 `match` is applied. E.g. `matching_algorithm=MatchingAlgorithm.REGEX` for regular-expression matching.
- is_insensitive: When `True`, `match` is case-insensitive. Defaults to `True`, 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 `None` to create with empty permissions.

###### Returns:

> The newly created `~easypaperless.models.tags.Tag`.

def update( self, id: int, *, name: str | easypaperless.Unset = UNSET, color: str | easypaperless.Unset = UNSET, is_inbox_tag: bool | easypaperless.Unset = UNSET, match: str | easypaperless.Unset = UNSET, matching_algorithm: easypaperless.MatchingAlgorithm | easypaperless.Unset = UNSET, is_insensitive: bool | easypaperless.Unset = UNSET, parent: int | None | easypaperless.Unset = UNSET, owner: int | None | easypaperless.Unset = UNSET, set_permissions: easypaperless.SetPermissions | None | easypaperless.Unset = UNSET) -> easypaperless.Tag: View Source

    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 `match` is applied. E.g. `matching_algorithm=MatchingAlgorithm.REGEX` for regular-expression matching.
- is_insensitive: When `True`, `match` is case-insensitive.
- parent: ID of parent tag. Pass `None` to clear (make root tag). Omit (or pass `~easypaperless.UNSET`) to leave unchanged.
- owner: Numeric user ID to assign as owner. Pass `None` to clear the owner. Omit (or pass `~easypaperless.UNSET`) to leave unchanged.
- set_permissions: Explicit view/change permission sets. Pass `None` to clear all permissions (overwrite with empty). Omit (or pass `~easypaperless.UNSET`) to leave unchanged.

###### Returns:

> The updated `~easypaperless.models.tags.Tag`.

def delete(self, id: int) -> None: View Source

    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.

def bulk_delete(self, ids: List[int]) -> None: View Source

    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.

def bulk_set_permissions( self, ids: List[int], *, set_permissions: easypaperless.SetPermissions | easypaperless.Unset = UNSET, owner: int | None | easypaperless.Unset = UNSET, merge: bool = False) -> None: View Source

    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 `None` to clear the owner. Omit (or pass `~easypaperless.UNSET`) to leave unchanged.
- merge: When `True`, new permissions are merged with existing ones.