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

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

Accessor for documents: `client.documents`.

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

    109    def __init__(self, core: _ClientCore) -> None:
    110        self._core = core
    111        self.notes = NotesResource(core)

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

    129    async def get(self, id: int, *, include_metadata: bool = False) -> Document:
    130        """Fetch a single document by its ID.
    131
    132        Args:
    133            id: Numeric paperless-ngx document ID.
    134            include_metadata: When ``True``, the extended file-level metadata
    135                is fetched concurrently and attached to the document.
    136                Default: ``False``.
    137
    138        Returns:
    139            The :class:`~easypaperless.models.documents.Document` with the
    140            given ID.
    141
    142        Raises:
    143            ~easypaperless.exceptions.NotFoundError: If no document exists
    144                with that ID.
    145        """
    146        logger.info("Getting document id=%d", id)
    147        if include_metadata:
    148            doc_resp, meta_resp = await asyncio.gather(
    149                self._core._session.get(f"/documents/{id}/"),
    150                self._core._session.get(f"/documents/{id}/metadata/"),
    151            )
    152            data = doc_resp.json()
    153            data["metadata"] = meta_resp.json()
    154        else:
    155            resp = await self._core._session.get(f"/documents/{id}/")
    156            data = resp.json()
    157        return Document.model_validate(data)

Fetch a single document by its ID.

###### Arguments:

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

###### Returns:

> The `~easypaperless.models.documents.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

    159    async def get_metadata(self, id: int) -> DocumentMetadata:
    160        """Fetch the extended file-level metadata for a document.
    161
    162        Args:
    163            id: Numeric paperless-ngx document ID.
    164
    165        Returns:
    166            A :class:`~easypaperless.models.documents.DocumentMetadata` instance.
    167
    168        Raises:
    169            ~easypaperless.exceptions.NotFoundError: If no document exists
    170                with that ID.
    171        """
    172        logger.info("Getting metadata for document id=%d", id)
    173        resp = await self._core._session.get(f"/documents/{id}/metadata/")
    174        return DocumentMetadata.model_validate(resp.json())

Fetch the extended file-level metadata for a document.

###### Arguments:

- id: Numeric paperless-ngx document ID.

###### Returns:

> A `~easypaperless.models.documents.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

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

Return a filtered list of documents.

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

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

###### Arguments:

- search: Search string. Behaviour depends on `search_mode`.
- search_mode: How `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

    481    async def update(
    482        self,
    483        id: int,
    484        *,
    485        title: str | Unset = UNSET,
    486        content: str | Unset = UNSET,
    487        created: date | str | None | Unset = UNSET,
    488        correspondent: int | str | None | Unset = UNSET,
    489        document_type: int | str | None | Unset = UNSET,
    490        storage_path: int | str | None | Unset = UNSET,
    491        tags: List[int | str] | None | Unset = UNSET,
    492        archive_serial_number: int | None | Unset = UNSET,
    493        custom_fields: List[dict[str, Any]] | None | Unset = UNSET,
    494        owner: int | None | Unset = UNSET,
    495        set_permissions: SetPermissions | None | Unset = UNSET,
    496        remove_inbox_tags: bool | None | Unset = UNSET,
    497    ) -> Document:
    498        """Partially update a document (PATCH semantics).
    499
    500        Args:
    501            id: Numeric ID of the document to update.
    502            title: New document title.
    503            content: OCR text content of the document.
    504            created: Creation date as an ISO-8601 string (``"YYYY-MM-DD"``) or a
    505                :class:`~datetime.date` object.
    506            correspondent: Correspondent to assign, as an ID or name.
    507                Pass ``None`` to clear the correspondent.
    508            document_type: Document type to assign, as an ID or name.
    509                Pass ``None`` to clear the document type.
    510            storage_path: Storage path to assign, as an ID or name.
    511                Pass ``None`` to clear the storage path.
    512            tags: Full replacement list of tags (IDs or names).
    513            archive_serial_number: Archive serial number to assign.
    514                Pass ``None`` to clear the archive serial number.
    515            custom_fields: List of ``{"field": <field_id>, "value": ...}`` dicts.
    516            owner: Numeric user ID to assign as document owner.
    517                Pass ``None`` to clear the owner.
    518            set_permissions: Explicit view/change permission sets.
    519                Pass ``None`` to clear all permissions (overwrite with empty).
    520                Omit (or pass :data:`~easypaperless.UNSET`) to leave unchanged.
    521            remove_inbox_tags: When ``True``, removes all inbox tags from the document.
    522
    523        Returns:
    524            The updated :class:`~easypaperless.models.documents.Document`.
    525        """
    526        logger.info("Updating document id=%d", id)
    527        resolver = self._core._resolver
    528        payload: dict[str, Any] = {}
    529
    530        if not isinstance(title, Unset):
    531            payload["title"] = title
    532        if not isinstance(content, Unset):
    533            payload["content"] = content
    534        if not isinstance(created, Unset):
    535            payload["created"] = self._format_date_value(created) if created is not None else None
    536        if not isinstance(correspondent, Unset):
    537            payload["correspondent"] = (
    538                None
    539                if correspondent is None
    540                else await resolver.resolve("correspondents", correspondent)
    541            )
    542        if not isinstance(document_type, Unset):
    543            payload["document_type"] = (
    544                None
    545                if document_type is None
    546                else await resolver.resolve("document_types", document_type)
    547            )
    548        if not isinstance(storage_path, Unset):
    549            payload["storage_path"] = (
    550                None
    551                if storage_path is None
    552                else await resolver.resolve("storage_paths", storage_path)
    553            )
    554        if not isinstance(tags, Unset):
    555            payload["tags"] = await resolver.resolve_list("tags", tags or [])
    556        if not isinstance(archive_serial_number, Unset):
    557            payload["archive_serial_number"] = archive_serial_number
    558        if not isinstance(custom_fields, Unset):
    559            payload["custom_fields"] = custom_fields
    560        if not isinstance(owner, Unset):
    561            payload["owner"] = owner
    562        if not isinstance(set_permissions, Unset):
    563            payload["set_permissions"] = (
    564                SetPermissions().model_dump()
    565                if set_permissions is None
    566                else set_permissions.model_dump()
    567            )
    568        if not isinstance(remove_inbox_tags, Unset):
    569            payload["remove_inbox_tags"] = remove_inbox_tags
    570
    571        resp = await self._core._session.patch(f"/documents/{id}/", json=payload)
    572        return Document.model_validate(resp.json())

Partially update a document (PATCH semantics).

###### Arguments:

- id: Numeric ID of the document to update.
- title: New document title.
- content: OCR text content of the document.
- created: Creation date as an ISO-8601 string (`"YYYY-MM-DD"`) or a `~datetime.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

    574    async def delete(self, id: int) -> None:
    575        """Permanently delete a document.
    576
    577        Args:
    578            id: Numeric ID of the document to delete.
    579
    580        Raises:
    581            ~easypaperless.exceptions.NotFoundError: If no document exists
    582                with that ID.
    583        """
    584        logger.info("Deleting document id=%d", id)
    585        await self._core._session.delete(f"/documents/{id}/")

Permanently delete a document.

###### Arguments:

- id: Numeric ID of the document to delete.

###### Raises:

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

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

    587    async def download(self, id: int, *, original: bool = False) -> bytes:
    588        """Download the binary content of a document.
    589
    590        Args:
    591            id: Numeric ID of the document to download.
    592            original: If ``False`` *(default)*, returns the archived PDF.
    593                If ``True``, returns the original uploaded file.
    594
    595        Returns:
    596            Raw file bytes.
    597        """
    598        logger.info("Downloading document id=%d (original=%s)", id, original)
    599        endpoint = "download" if original else "archive"
    600        resp = await self._core._session.get_download(f"/documents/{id}/{endpoint}/")
    601        content_type = resp.headers.get("content-type", "")
    602        if "text/html" in content_type or resp.content[:9].lower().startswith(b"<!doctype"):
    603            raise ServerError(
    604                f"Download returned an HTML page (content-type: {content_type!r}). "
    605                "The server redirected to a login page even after re-attaching auth.",
    606                status_code=None,
    607            )
    608        return resp.content

Download the binary content of a document.

###### Arguments:

- id: Numeric ID of the document to download.
- original: If `False` (default), returns the archived PDF. 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

    610    async def upload(
    611        self,
    612        file: str | Path,
    613        *,
    614        title: str | Unset = UNSET,
    615        created: date | str | None = None,
    616        correspondent: int | str | None | Unset = UNSET,
    617        document_type: int | str | None | Unset = UNSET,
    618        storage_path: int | str | None | Unset = UNSET,
    619        tags: List[int | str] | None = None,
    620        archive_serial_number: int | None | Unset = UNSET,
    621        custom_fields: List[dict[str, Any]] | None = None,
    622        wait: bool = False,
    623        poll_interval: float | None = None,
    624        poll_timeout: float | None = None,
    625    ) -> str | Document:
    626        """Upload a document to paperless-ngx.
    627
    628        Args:
    629            file: Path to the file to upload.
    630            title: Title to assign to the document.
    631            created: Creation date as an ISO-8601 string (``"YYYY-MM-DD"``) or a
    632                :class:`~datetime.date` object.
    633            correspondent: Correspondent to assign, as an ID or name.
    634            document_type: Document type to assign, as an ID or name.
    635            storage_path: Storage path to assign, as an ID or name.
    636            tags: Tags to assign, as IDs or names.
    637            archive_serial_number: Archive serial number to assign.
    638            custom_fields: List of ``{"field": <field_id>, "value": ...}`` dicts.
    639            wait: If ``False`` *(default)*, returns immediately with the task ID.
    640                If ``True``, polls until processing completes.
    641            poll_interval: Seconds between task-status checks while waiting for
    642                processing to complete (requires ``wait=True``). Overrides the
    643                client-level default. When omitted, falls back to the client-level
    644                ``poll_interval`` (``2.0`` s unless changed at construction).
    645            poll_timeout: Maximum seconds to wait before raising
    646                :exc:`~easypaperless.exceptions.TaskTimeoutError` (requires
    647                ``wait=True``). Overrides the client-level default. When omitted,
    648                falls back to the client-level ``poll_timeout`` (``60.0`` s unless
    649                changed at construction).
    650
    651        Returns:
    652            The Celery task ID string when ``wait=False``, or the fully
    653            processed :class:`~easypaperless.models.documents.Document`
    654            when ``wait=True``.
    655
    656        Raises:
    657            ~easypaperless.exceptions.UploadError: If processing fails.
    658            ~easypaperless.exceptions.TaskTimeoutError: If timeout is exceeded.
    659        """
    660        resolver = self._core._resolver
    661        file_path = Path(file)
    662        file_bytes = file_path.read_bytes()
    663        logger.info("Uploading %r (%d bytes)", file_path.name, len(file_bytes))
    664
    665        data: dict[str, Any] = {}
    666        if not isinstance(title, Unset):
    667            data["title"] = title
    668        if created is not None:
    669            data["created"] = self._format_date_value(created)
    670        if not isinstance(correspondent, Unset) and correspondent is not None:
    671            data["correspondent"] = await resolver.resolve("correspondents", correspondent)
    672        if not isinstance(document_type, Unset) and document_type is not None:
    673            data["document_type"] = await resolver.resolve("document_types", document_type)
    674        if not isinstance(storage_path, Unset) and storage_path is not None:
    675            data["storage_path"] = await resolver.resolve("storage_paths", storage_path)
    676        if tags is not None:
    677            resolved = await resolver.resolve_list("tags", tags)
    678            data["tags"] = resolved
    679        if not isinstance(archive_serial_number, Unset) and archive_serial_number is not None:
    680            data["archive_serial_number"] = archive_serial_number
    681        if custom_fields is not None:
    682            data["custom_fields"] = json.dumps(custom_fields)
    683
    684        files = {"document": (file_path.name, file_bytes)}
    685        resp = await self._core._session.post("/documents/post_document/", data=data, files=files)
    686        task_id: str = resp.text.strip('"')
    687        logger.debug("Upload accepted, task_id=%r", task_id)
    688
    689        if not wait:
    690            return task_id
    691
    692        interval = poll_interval if poll_interval is not None else self._core._poll_interval
    693        timeout = poll_timeout if poll_timeout is not None else self._core._poll_timeout
    694        return await self._poll_task(task_id, poll_interval=interval, poll_timeout=timeout)

Upload a document to paperless-ngx.

###### Arguments:

- file: Path to the file to upload.
- title: Title to assign to the document.
- created: Creation date as an ISO-8601 string (`"YYYY-MM-DD"`) or a `~datetime.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

    749    async def bulk_add_tag(self, document_ids: List[int], tag: int | str) -> None:
    750        """Add a tag to multiple documents in a single request.
    751
    752        Args:
    753            document_ids: List of document IDs to tag.
    754            tag: Tag to add, as an ID or name.
    755        """
    756        logger.info("Bulk adding tag %r to %d documents", tag, len(document_ids))
    757        tag_id = await self._core._resolver.resolve("tags", tag)
    758        await self._bulk_edit(document_ids, "add_tag", tag=tag_id)

Add a tag to multiple documents in a single request.

###### Arguments:

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

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

    760    async def bulk_remove_tag(self, document_ids: List[int], tag: int | str) -> None:
    761        """Remove a tag from multiple documents in a single request.
    762
    763        Args:
    764            document_ids: List of document IDs to un-tag.
    765            tag: Tag to remove, as an ID or name.
    766        """
    767        logger.info("Bulk removing tag %r from %d documents", tag, len(document_ids))
    768        tag_id = await self._core._resolver.resolve("tags", tag)
    769        await self._bulk_edit(document_ids, "remove_tag", tag=tag_id)

Remove a tag from multiple documents in a single request.

###### Arguments:

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

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

    771    async def bulk_modify_tags(
    772        self,
    773        document_ids: List[int],
    774        *,
    775        add_tags: List[int | str] | None = None,
    776        remove_tags: List[int | str] | None = None,
    777    ) -> None:
    778        """Add and/or remove tags on multiple documents atomically.
    779
    780        Args:
    781            document_ids: List of document IDs to modify.
    782            add_tags: Tags to add, as IDs or names.
    783            remove_tags: Tags to remove, as IDs or names.
    784        """
    785        logger.info("Bulk modifying tags on %d documents", len(document_ids))
    786        resolver = self._core._resolver
    787        add_ids = await resolver.resolve_list("tags", add_tags or [])
    788        remove_ids = await resolver.resolve_list("tags", remove_tags or [])
    789        await self._bulk_edit(document_ids, "modify_tags", add_tags=add_ids, remove_tags=remove_ids)

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

    791    async def bulk_delete(self, document_ids: List[int]) -> None:
    792        """Permanently delete multiple documents in a single request.
    793
    794        Args:
    795            document_ids: List of document IDs to delete.
    796        """
    797        logger.info("Bulk deleting %d documents", len(document_ids))
    798        await self._bulk_edit(document_ids, "delete")

Permanently delete multiple documents in a single request.

###### Arguments:

- document_ids: List of document IDs to delete.

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

    800    async def bulk_set_correspondent(
    801        self, document_ids: List[int], correspondent: int | str | None
    802    ) -> None:
    803        """Assign a correspondent to multiple documents in a single request.
    804
    805        Args:
    806            document_ids: List of document IDs to modify.
    807            correspondent: Correspondent to assign, as an ID or name.
    808                Pass ``None`` to clear.
    809        """
    810        logger.info(
    811            "Bulk setting correspondent %r on %d documents", correspondent, len(document_ids)
    812        )
    813        cor_id: int | None = None
    814        if correspondent is not None:
    815            cor_id = await self._core._resolver.resolve("correspondents", correspondent)
    816        await self._bulk_edit(document_ids, "set_correspondent", correspondent=cor_id)

Assign a correspondent to multiple documents in a single request.

###### Arguments:

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

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

    818    async def bulk_set_document_type(
    819        self, document_ids: List[int], document_type: int | str | None
    820    ) -> None:
    821        """Assign a document type to multiple documents in a single request.
    822
    823        Args:
    824            document_ids: List of document IDs to modify.
    825            document_type: Document type to assign, as an ID or name.
    826                Pass ``None`` to clear.
    827        """
    828        logger.info(
    829            "Bulk setting document type %r on %d documents", document_type, len(document_ids)
    830        )
    831        dt_id: int | None = None
    832        if document_type is not None:
    833            dt_id = await self._core._resolver.resolve("document_types", document_type)
    834        await self._bulk_edit(document_ids, "set_document_type", document_type=dt_id)

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

###### Arguments:

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

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

    836    async def bulk_set_storage_path(
    837        self, document_ids: List[int], storage_path: int | str | None
    838    ) -> None:
    839        """Assign a storage path to multiple documents in a single request.
    840
    841        Args:
    842            document_ids: List of document IDs to modify.
    843            storage_path: Storage path to assign, as an ID or name.
    844                Pass ``None`` to clear.
    845        """
    846        logger.info("Bulk setting storage path %r on %d documents", storage_path, len(document_ids))
    847        sp_id: int | None = None
    848        if storage_path is not None:
    849            sp_id = await self._core._resolver.resolve("storage_paths", storage_path)
    850        await self._bulk_edit(document_ids, "set_storage_path", storage_path=sp_id)

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

###### Arguments:

- document_ids: List of document IDs to modify.
- storage_path: Storage path to assign, as an ID or name. Pass `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

    852    async def bulk_modify_custom_fields(
    853        self,
    854        document_ids: List[int],
    855        *,
    856        add_fields: List[dict[str, Any]] | None = None,
    857        remove_fields: List[int] | None = None,
    858    ) -> None:
    859        """Add and/or remove custom field values on multiple documents.
    860
    861        Args:
    862            document_ids: List of document IDs to modify.
    863            add_fields: Custom-field value dicts to add.
    864            remove_fields: Custom-field IDs whose values should be removed.
    865        """
    866        logger.info("Bulk modifying custom fields on %d documents", len(document_ids))
    867        await self._bulk_edit(
    868            document_ids,
    869            "modify_custom_fields",
    870            add_custom_fields=add_fields or [],
    871            remove_custom_fields=remove_fields or [],
    872        )

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

###### Arguments:

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

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

    874    async def bulk_set_permissions(
    875        self,
    876        document_ids: List[int],
    877        *,
    878        set_permissions: SetPermissions | Unset = UNSET,
    879        owner: int | None | Unset = UNSET,
    880        merge: bool = False,
    881    ) -> None:
    882        """Set permissions and/or owner on multiple documents.
    883
    884        Args:
    885            document_ids: List of document IDs to modify.
    886            set_permissions: Explicit view/change permission sets.
    887                Omit (or pass :data:`~easypaperless.UNSET`) to leave unchanged.
    888            owner: Numeric user ID to assign as document owner.
    889                Pass ``None`` to clear the owner.
    890                Omit (or pass :data:`~easypaperless.UNSET`) to leave unchanged.
    891            merge: When ``True``, new permissions are merged with existing ones.
    892        """
    893        logger.info("Bulk setting permissions on %d documents", len(document_ids))
    894        params: dict[str, Any] = {"merge": merge}
    895        if not isinstance(set_permissions, Unset):
    896            params["set_permissions"] = set_permissions.model_dump()
    897        if not isinstance(owner, Unset):
    898            params["owner"] = owner
    899        await self._bulk_edit(document_ids, "set_permissions", **params)

Set permissions and/or owner on multiple documents.

###### Arguments:

- document_ids: List of document IDs to modify.
- set_permissions: Explicit view/change permission sets. Omit (or pass `~easypaperless.UNSET`) to leave unchanged.
- owner: Numeric user ID to assign as document owner. Pass `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(self, document_id: int) -> List[DocumentNote]:
     50        """Fetch all notes attached to a document.
     51
     52        Args:
     53            document_id: Numeric ID of the document whose notes to retrieve.
     54
     55        Returns:
     56            List of :class:`~easypaperless.models.documents.DocumentNote` objects,
     57            ordered by creation time.
     58
     59        Raises:
     60            ~easypaperless.exceptions.NotFoundError: If no document exists
     61                with that ID.
     62        """
     63        logger.info("Listing notes for document id=%d", document_id)
     64        resp = await self._core._session.get(f"/documents/{document_id}/notes/")
     65        return [DocumentNote.model_validate(item) for item in resp.json()]
     66
     67    async def create(self, document_id: int, *, note: str) -> DocumentNote:
     68        """Create a new note on a document.
     69
     70        Args:
     71            document_id: Numeric ID of the document to annotate.
     72            note: Text content of the note.
     73
     74        Returns:
     75            The newly created :class:`~easypaperless.models.documents.DocumentNote`.
     76
     77        Raises:
     78            ~easypaperless.exceptions.NotFoundError: If no document exists
     79                with that ID.
     80        """
     81        logger.info("Creating note for document id=%d", document_id)
     82        resp = await self._core._session.post(
     83            f"/documents/{document_id}/notes/",
     84            json={"note": note},
     85        )
     86        data = resp.json()
     87        if isinstance(data, list):
     88            return DocumentNote.model_validate(data[-1])
     89        return DocumentNote.model_validate(data)
     90
     91    async def delete(self, document_id: int, note_id: int) -> None:
     92        """Delete a note from a document.
     93
     94        Args:
     95            document_id: Numeric ID of the document that owns the note.
     96            note_id: Numeric ID of the note to delete.
     97
     98        Raises:
     99            ~easypaperless.exceptions.NotFoundError: If no document or note
    100                exists with the given IDs.
    101        """
    102        logger.info("Deleting note id=%d from document id=%d", note_id, document_id)
    103        await self._core._session.delete(f"/documents/{document_id}/notes/", params={"id": note_id})

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

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) -> List[easypaperless.DocumentNote]: View Source

    49    async def list(self, document_id: int) -> List[DocumentNote]:
    50        """Fetch all notes attached to a document.
    51
    52        Args:
    53            document_id: Numeric ID of the document whose notes to retrieve.
    54
    55        Returns:
    56            List of :class:`~easypaperless.models.documents.DocumentNote` objects,
    57            ordered by creation time.
    58
    59        Raises:
    60            ~easypaperless.exceptions.NotFoundError: If no document exists
    61                with that ID.
    62        """
    63        logger.info("Listing notes for document id=%d", document_id)
    64        resp = await self._core._session.get(f"/documents/{document_id}/notes/")
    65        return [DocumentNote.model_validate(item) for item in resp.json()]

Fetch all notes attached to a document.

###### Arguments:

- document_id: Numeric ID of the document whose notes to retrieve.

###### Returns:

> List of `~easypaperless.models.documents.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

    67    async def create(self, document_id: int, *, note: str) -> DocumentNote:
    68        """Create a new note on a document.
    69
    70        Args:
    71            document_id: Numeric ID of the document to annotate.
    72            note: Text content of the note.
    73
    74        Returns:
    75            The newly created :class:`~easypaperless.models.documents.DocumentNote`.
    76
    77        Raises:
    78            ~easypaperless.exceptions.NotFoundError: If no document exists
    79                with that ID.
    80        """
    81        logger.info("Creating note for document id=%d", document_id)
    82        resp = await self._core._session.post(
    83            f"/documents/{document_id}/notes/",
    84            json={"note": note},
    85        )
    86        data = resp.json()
    87        if isinstance(data, list):
    88            return DocumentNote.model_validate(data[-1])
    89        return DocumentNote.model_validate(data)

Create a new note on a document.

###### Arguments:

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

###### Returns:

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

###### Raises:

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

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

     91    async def delete(self, document_id: int, note_id: int) -> None:
     92        """Delete a note from a document.
     93
     94        Args:
     95            document_id: Numeric ID of the document that owns the note.
     96            note_id: Numeric ID of the note to delete.
     97
     98        Raises:
     99            ~easypaperless.exceptions.NotFoundError: If no document or note
    100                exists with the given IDs.
    101        """
    102        logger.info("Deleting note id=%d from document id=%d", note_id, document_id)
    103        await self._core._session.delete(f"/documents/{document_id}/notes/", params={"id": note_id})

Delete a note from a document.

###### Arguments:

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

###### Raises:

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

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

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

Sync accessor for documents: `client.documents`.

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

    76    def __init__(self, async_documents: DocumentsResource, run: Any) -> None:
    77        self._async_documents = async_documents
    78        self._run = run
    79        self.notes = SyncNotesResource(async_documents.notes, run)

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

     81    def get(self, id: int, *, include_metadata: bool = False) -> Document:
     82        """Fetch a single document by its ID.
     83
     84        Args:
     85            id: Numeric paperless-ngx document ID.
     86            include_metadata: When ``True``, the extended file-level metadata
     87                is fetched concurrently and attached to the document.
     88                Default: ``False``.
     89
     90        Returns:
     91            The :class:`~easypaperless.models.documents.Document` with the
     92            given ID.
     93
     94        Raises:
     95            ~easypaperless.exceptions.NotFoundError: If no document exists
     96                with that ID.
     97        """
     98        return cast(
     99            Document, self._run(self._async_documents.get(id, include_metadata=include_metadata))
    100        )

Fetch a single document by its ID.

###### Arguments:

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

###### Returns:

> The `~easypaperless.models.documents.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

    102    def get_metadata(self, id: int) -> DocumentMetadata:
    103        """Fetch the extended file-level metadata for a document.
    104
    105        Args:
    106            id: Numeric paperless-ngx document ID.
    107
    108        Returns:
    109            A :class:`~easypaperless.models.documents.DocumentMetadata` instance.
    110
    111        Raises:
    112            ~easypaperless.exceptions.NotFoundError: If no document exists
    113                with that ID.
    114        """
    115        return cast(DocumentMetadata, self._run(self._async_documents.get_metadata(id)))

Fetch the extended file-level metadata for a document.

###### Arguments:

- id: Numeric paperless-ngx document ID.

###### Returns:

> A `~easypaperless.models.documents.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

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

Return a filtered list of documents.

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

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

###### Arguments:

- search: Search string. Behaviour depends on `search_mode`.
- search_mode: How `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

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

Partially update a document (PATCH semantics).

###### Arguments:

- id: Numeric ID of the document to update.
- title: New document title.
- content: OCR text content of the document.
- created: Creation date as an ISO-8601 string (`"YYYY-MM-DD"`) or a `~datetime.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

    364    def delete(self, id: int) -> None:
    365        """Permanently delete a document.
    366
    367        Args:
    368            id: Numeric ID of the document to delete.
    369
    370        Raises:
    371            ~easypaperless.exceptions.NotFoundError: If no document exists
    372                with that ID.
    373        """
    374        self._run(self._async_documents.delete(id))

Permanently delete a document.

###### Arguments:

- id: Numeric ID of the document to delete.

###### Raises:

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

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

    376    def download(self, id: int, *, original: bool = False) -> bytes:
    377        """Download the binary content of a document.
    378
    379        Args:
    380            id: Numeric ID of the document to download.
    381            original: If ``False`` *(default)*, returns the archived PDF.
    382                If ``True``, returns the original uploaded file.
    383
    384        Returns:
    385            Raw file bytes.
    386        """
    387        return cast(bytes, self._run(self._async_documents.download(id, original=original)))

Download the binary content of a document.

###### Arguments:

- id: Numeric ID of the document to download.
- original: If `False` (default), returns the archived PDF. 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

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

Upload a document to paperless-ngx.

###### Arguments:

- file: Path to the file to upload.
- title: Title to assign to the document.
- created: Creation date as an ISO-8601 string (`"YYYY-MM-DD"`) or a `~datetime.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

    459    def bulk_add_tag(self, document_ids: List[int], tag: int | str) -> None:
    460        """Add a tag to multiple documents in a single request.
    461
    462        Args:
    463            document_ids: List of document IDs to tag.
    464            tag: Tag to add, as an ID or name.
    465        """
    466        self._run(self._async_documents.bulk_add_tag(document_ids, tag))

Add a tag to multiple documents in a single request.

###### Arguments:

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

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

    468    def bulk_remove_tag(self, document_ids: List[int], tag: int | str) -> None:
    469        """Remove a tag from multiple documents in a single request.
    470
    471        Args:
    472            document_ids: List of document IDs to un-tag.
    473            tag: Tag to remove, as an ID or name.
    474        """
    475        self._run(self._async_documents.bulk_remove_tag(document_ids, tag))

Remove a tag from multiple documents in a single request.

###### Arguments:

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

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

    477    def bulk_modify_tags(
    478        self,
    479        document_ids: List[int],
    480        *,
    481        add_tags: List[int | str] | None = None,
    482        remove_tags: List[int | str] | None = None,
    483    ) -> None:
    484        """Add and/or remove tags on multiple documents atomically.
    485
    486        Args:
    487            document_ids: List of document IDs to modify.
    488            add_tags: Tags to add, as IDs or names.
    489            remove_tags: Tags to remove, as IDs or names.
    490        """
    491        self._run(
    492            self._async_documents.bulk_modify_tags(
    493                document_ids, add_tags=add_tags, remove_tags=remove_tags
    494            )
    495        )

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

    497    def bulk_delete(self, document_ids: List[int]) -> None:
    498        """Permanently delete multiple documents in a single request.
    499
    500        Args:
    501            document_ids: List of document IDs to delete.
    502        """
    503        self._run(self._async_documents.bulk_delete(document_ids))

Permanently delete multiple documents in a single request.

###### Arguments:

- document_ids: List of document IDs to delete.

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

    505    def bulk_set_correspondent(
    506        self, document_ids: List[int], correspondent: int | str | None
    507    ) -> None:
    508        """Assign a correspondent to multiple documents in a single request.
    509
    510        Args:
    511            document_ids: List of document IDs to modify.
    512            correspondent: Correspondent to assign, as an ID or name.
    513                Pass ``None`` to clear.
    514        """
    515        self._run(self._async_documents.bulk_set_correspondent(document_ids, correspondent))

Assign a correspondent to multiple documents in a single request.

###### Arguments:

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

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

    517    def bulk_set_document_type(
    518        self, document_ids: List[int], document_type: int | str | None
    519    ) -> None:
    520        """Assign a document type to multiple documents in a single request.
    521
    522        Args:
    523            document_ids: List of document IDs to modify.
    524            document_type: Document type to assign, as an ID or name.
    525                Pass ``None`` to clear.
    526        """
    527        self._run(self._async_documents.bulk_set_document_type(document_ids, document_type))

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

###### Arguments:

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

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

    529    def bulk_set_storage_path(
    530        self, document_ids: List[int], storage_path: int | str | None
    531    ) -> None:
    532        """Assign a storage path to multiple documents in a single request.
    533
    534        Args:
    535            document_ids: List of document IDs to modify.
    536            storage_path: Storage path to assign, as an ID or name.
    537                Pass ``None`` to clear.
    538        """
    539        self._run(self._async_documents.bulk_set_storage_path(document_ids, storage_path))

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

###### Arguments:

- document_ids: List of document IDs to modify.
- storage_path: Storage path to assign, as an ID or name. Pass `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

    541    def bulk_modify_custom_fields(
    542        self,
    543        document_ids: List[int],
    544        *,
    545        add_fields: List[dict[str, Any]] | None = None,
    546        remove_fields: List[int] | None = None,
    547    ) -> None:
    548        """Add and/or remove custom field values on multiple documents.
    549
    550        Args:
    551            document_ids: List of document IDs to modify.
    552            add_fields: Custom-field value dicts to add.
    553            remove_fields: Custom-field IDs whose values should be removed.
    554        """
    555        self._run(
    556            self._async_documents.bulk_modify_custom_fields(
    557                document_ids, add_fields=add_fields, remove_fields=remove_fields
    558            )
    559        )

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

###### Arguments:

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

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

    561    def bulk_set_permissions(
    562        self,
    563        document_ids: List[int],
    564        *,
    565        set_permissions: SetPermissions | Unset = UNSET,
    566        owner: int | None | Unset = UNSET,
    567        merge: bool = False,
    568    ) -> None:
    569        """Set permissions and/or owner on multiple documents.
    570
    571        Args:
    572            document_ids: List of document IDs to modify.
    573            set_permissions: Explicit view/change permission sets.
    574                Omit (or pass :data:`~easypaperless.UNSET`) to leave unchanged.
    575            owner: Numeric user ID to assign as document owner.
    576                Pass ``None`` to clear the owner.
    577                Omit (or pass :data:`~easypaperless.UNSET`) to leave unchanged.
    578            merge: When ``True``, new permissions are merged with existing ones.
    579        """
    580        self._run(
    581            self._async_documents.bulk_set_permissions(
    582                document_ids,
    583                set_permissions=set_permissions,
    584                owner=owner,
    585                merge=merge,
    586            )
    587        )

Set permissions and/or owner on multiple documents.

###### Arguments:

- document_ids: List of document IDs to modify.
- set_permissions: Explicit view/change permission sets. Omit (or pass `~easypaperless.UNSET`) to leave unchanged.
- owner: Numeric user ID to assign as document owner. Pass `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(self, document_id: int) -> List[DocumentNote]:
    28        """Fetch all notes attached to a document.
    29
    30        Args:
    31            document_id: Numeric ID of the document whose notes to retrieve.
    32
    33        Returns:
    34            List of :class:`~easypaperless.models.documents.DocumentNote` objects,
    35            ordered by creation time.
    36
    37        Raises:
    38            ~easypaperless.exceptions.NotFoundError: If no document exists
    39                with that ID.
    40        """
    41        return cast(List[DocumentNote], self._run(self._async_notes.list(document_id)))
    42
    43    def create(self, document_id: int, *, note: str) -> DocumentNote:
    44        """Create a new note on a document.
    45
    46        Args:
    47            document_id: Numeric ID of the document to annotate.
    48            note: Text content of the note.
    49
    50        Returns:
    51            The newly created :class:`~easypaperless.models.documents.DocumentNote`.
    52
    53        Raises:
    54            ~easypaperless.exceptions.NotFoundError: If no document exists
    55                with that ID.
    56        """
    57        return cast(DocumentNote, self._run(self._async_notes.create(document_id, note=note)))
    58
    59    def delete(self, document_id: int, note_id: int) -> None:
    60        """Delete a note from a document.
    61
    62        Args:
    63            document_id: Numeric ID of the document that owns the note.
    64            note_id: Numeric ID of the note to delete.
    65
    66        Raises:
    67            ~easypaperless.exceptions.NotFoundError: If no document or note
    68                exists with the given IDs.
    69        """
    70        self._run(self._async_notes.delete(document_id, note_id))

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

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) -> List[easypaperless.DocumentNote]: View Source

    27    def list(self, document_id: int) -> List[DocumentNote]:
    28        """Fetch all notes attached to a document.
    29
    30        Args:
    31            document_id: Numeric ID of the document whose notes to retrieve.
    32
    33        Returns:
    34            List of :class:`~easypaperless.models.documents.DocumentNote` objects,
    35            ordered by creation time.
    36
    37        Raises:
    38            ~easypaperless.exceptions.NotFoundError: If no document exists
    39                with that ID.
    40        """
    41        return cast(List[DocumentNote], self._run(self._async_notes.list(document_id)))

Fetch all notes attached to a document.

###### Arguments:

- document_id: Numeric ID of the document whose notes to retrieve.

###### Returns:

> List of `~easypaperless.models.documents.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

    43    def create(self, document_id: int, *, note: str) -> DocumentNote:
    44        """Create a new note on a document.
    45
    46        Args:
    47            document_id: Numeric ID of the document to annotate.
    48            note: Text content of the note.
    49
    50        Returns:
    51            The newly created :class:`~easypaperless.models.documents.DocumentNote`.
    52
    53        Raises:
    54            ~easypaperless.exceptions.NotFoundError: If no document exists
    55                with that ID.
    56        """
    57        return cast(DocumentNote, self._run(self._async_notes.create(document_id, note=note)))

Create a new note on a document.

###### Arguments:

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

###### Returns:

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

###### Raises:

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

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

    59    def delete(self, document_id: int, note_id: int) -> None:
    60        """Delete a note from a document.
    61
    62        Args:
    63            document_id: Numeric ID of the document that owns the note.
    64            note_id: Numeric ID of the note to delete.
    65
    66        Raises:
    67            ~easypaperless.exceptions.NotFoundError: If no document or note
    68                exists with the given IDs.
    69        """
    70        self._run(self._async_notes.delete(document_id, note_id))

Delete a note from a document.

###### Arguments:

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

###### Raises:

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

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.