easypaperless API documentation

# easypaperless

easypaperless — Python API wrapper for paperless-ngx.

View Source

     1"""easypaperless — Python API wrapper for paperless-ngx."""
     2
     3import importlib.metadata
     4import logging
     5
     6__version__: str = importlib.metadata.version("easypaperless")
     7
     8from easypaperless import resources as resources  # noqa: F401
     9from easypaperless._internal.sentinel import UNSET, Unset
    10from easypaperless.client import PaperlessClient
    11from easypaperless.exceptions import (
    12    AuthError,
    13    NotFoundError,
    14    PaperlessError,
    15    ServerError,
    16    TaskTimeoutError,
    17    UploadError,
    18    ValidationError,
    19)
    20from easypaperless.models import (
    21    Correspondent,
    22    CustomField,
    23    CustomFieldValue,
    24    Document,
    25    DocumentMetadata,
    26    DocumentNote,
    27    DocumentType,
    28    FieldDataType,
    29    FileMetadataEntry,
    30    MatchingAlgorithm,
    31    PagedResult,
    32    PermissionSet,
    33    SearchHit,
    34    SetPermissions,
    35    StoragePath,
    36    Tag,
    37    Task,
    38    TaskStatus,
    39)
    40from easypaperless.sync import SyncPaperlessClient
    41
    42logging.getLogger("easypaperless").addHandler(logging.NullHandler())
    43
    44__all__ = [
    45    "__version__",
    46    # Clients
    47    "PaperlessClient",
    48    "SyncPaperlessClient",
    49    # Sentinel
    50    "UNSET",
    51    "Unset",
    52    # Models
    53    "MatchingAlgorithm",
    54    "PagedResult",
    55    "Correspondent",
    56    "CustomField",
    57    "CustomFieldValue",
    58    "Document",
    59    "DocumentMetadata",
    60    "DocumentNote",
    61    "DocumentType",
    62    "FieldDataType",
    63    "FileMetadataEntry",
    64    "PermissionSet",
    65    "SearchHit",
    66    "SetPermissions",
    67    "StoragePath",
    68    "Tag",
    69    "Task",
    70    "TaskStatus",
    71    # Exceptions
    72    "PaperlessError",
    73    "AuthError",
    74    "NotFoundError",
    75    "ValidationError",
    76    "ServerError",
    77    "UploadError",
    78    "TaskTimeoutError",
    79]

__version__: str = '0.2.1'
class PaperlessClient(easypaperless.client._ClientCore): View Source

    152class PaperlessClient(_ClientCore):
    153    """Async client for the paperless-ngx API.
    154
    155    Resources are accessible as attributes:
    156
    157    * ``client.correspondents`` — correspondent CRUD + bulk ops -
    158      see `easypaperless.resources.CorrespondentsResource`
    159    * ``client.custom_fields`` — custom field CRUD -
    160      see `easypaperless.resources.CustomFieldsResource`
    161    * ``client.document_types`` — document type CRUD + bulk ops -
    162      see `easypaperless.resources.DocumentTypesResource`
    163    * ``client.documents`` — document CRUD, bulk ops, upload, download -
    164      see `easypaperless.resources.DocumentsResource`
    165    * ``client.documents.notes`` — document notes -
    166      see `easypaperless.resources.NotesResource`
    167    * ``client.storage_paths`` — storage path CRUD + bulk ops -
    168      see `easypaperless.resources.StoragePathsResource`
    169    * ``client.tags`` — tag CRUD + bulk ops -
    170      see `easypaperless.resources.TagsResource`
    171
    172    Use as an async context manager to ensure the underlying HTTP connection
    173    pool is closed when you are done:
    174
    175    Example:
    176        async with PaperlessClient(url="http://localhost:8000", api_token="abc") as client:
    177            docs = await client.documents.list(max_results=10)
    178    """
    179
    180    def __init__(
    181        self,
    182        url: str,
    183        api_token: str,
    184        *,
    185        timeout: float = 30.0,
    186        poll_interval: float = 2.0,
    187        poll_timeout: float = 60.0,
    188    ) -> None:
    189        """Create an async paperless-ngx client.
    190
    191        Args:
    192            url: Base URL of the paperless-ngx instance
    193                (e.g. ``"http://localhost:8000"``).
    194            api_token: API token.  Generate one in paperless-ngx under
    195                *Settings → API → Generate Token*.
    196            timeout: Default request timeout in seconds.  Default: ``30.0``.
    197            poll_interval: Seconds between status checks when ``wait=True``
    198                is passed to :meth:`documents.upload`.  Default: ``2.0``.
    199            poll_timeout: Maximum seconds to wait for a document to finish
    200                processing before raising
    201                :exc:`~easypaperless.exceptions.TaskTimeoutError`.
    202                Default: ``60.0``.
    203        """
    204        super().__init__(
    205            url, api_token, timeout=timeout, poll_interval=poll_interval, poll_timeout=poll_timeout
    206        )
    207
    208    async def __aenter__(self) -> PaperlessClient:
    209        return self
    210
    211    async def __aexit__(self, *args: Any) -> None:
    212        await self.close()

Async client for the paperless-ngx API.

Resources are accessible as attributes:

- `client.correspondents` — correspondent CRUD + bulk ops - see `easypaperless.resources.CorrespondentsResource`
- `client.custom_fields` — custom field CRUD - see `easypaperless.resources.CustomFieldsResource`
- `client.document_types` — document type CRUD + bulk ops - see `easypaperless.resources.DocumentTypesResource`
- `client.documents` — document CRUD, bulk ops, upload, download - see `easypaperless.resources.DocumentsResource`
- `client.documents.notes` — document notes - see `easypaperless.resources.NotesResource`
- `client.storage_paths` — storage path CRUD + bulk ops - see `easypaperless.resources.StoragePathsResource`
- `client.tags` — tag CRUD + bulk ops - see `easypaperless.resources.TagsResource`

Use as an async context manager to ensure the underlying HTTP connection pool is closed when you are done:

###### Example:

> async with PaperlessClient(url="http://localhost:8000", api_token="abc") as client: docs = await client.documents.list(max_results=10)

PaperlessClient( url: str, api_token: str, *, timeout: float = 30.0, poll_interval: float = 2.0, poll_timeout: float = 60.0) View Source

    180    def __init__(
    181        self,
    182        url: str,
    183        api_token: str,
    184        *,
    185        timeout: float = 30.0,
    186        poll_interval: float = 2.0,
    187        poll_timeout: float = 60.0,
    188    ) -> None:
    189        """Create an async paperless-ngx client.
    190
    191        Args:
    192            url: Base URL of the paperless-ngx instance
    193                (e.g. ``"http://localhost:8000"``).
    194            api_token: API token.  Generate one in paperless-ngx under
    195                *Settings → API → Generate Token*.
    196            timeout: Default request timeout in seconds.  Default: ``30.0``.
    197            poll_interval: Seconds between status checks when ``wait=True``
    198                is passed to :meth:`documents.upload`.  Default: ``2.0``.
    199            poll_timeout: Maximum seconds to wait for a document to finish
    200                processing before raising
    201                :exc:`~easypaperless.exceptions.TaskTimeoutError`.
    202                Default: ``60.0``.
    203        """
    204        super().__init__(
    205            url, api_token, timeout=timeout, poll_interval=poll_interval, poll_timeout=poll_timeout
    206        )

Create an async paperless-ngx client.

###### Arguments:

- url: Base URL of the paperless-ngx instance (e.g. `"http://localhost:8000"`).
- api_token: API token. Generate one in paperless-ngx under Settings → API → Generate Token.
- timeout: Default request timeout in seconds. Default: `30.0`.
- poll_interval: Seconds between status checks when `wait=True` is passed to `documents.upload()`. Default: `2.0`.
- poll_timeout: Maximum seconds to wait for a document to finish processing before raising `~easypaperless.exceptions.TaskTimeoutError`. Default: `60.0`.

class SyncPaperlessClient(easypaperless.sync._SyncCore): View Source

     77class SyncPaperlessClient(_SyncCore):
     78    """Synchronous interface to paperless-ngx.
     79
     80    Resources are accessible as attributes:
     81
     82    * ``client.correspondents`` — correspondent CRUD + bulk ops -
     83      see `easypaperless.resources.SyncCorrespondentsResource`
     84    * ``client.custom_fields`` — custom field CRUD -
     85      see `easypaperless.resources.SyncCustomFieldsResource`
     86    * ``client.document_types`` — document type CRUD + bulk ops -
     87      see `easypaperless.resources.SyncDocumentTypesResource`
     88    * ``client.documents`` — document CRUD, bulk ops, upload, download -
     89      see `easypaperless.resources.SyncDocumentsResource`
     90    * ``client.documents.notes`` — document notes -
     91      see `easypaperless.resources.SyncNotesResource`
     92    * ``client.storage_paths`` — storage path CRUD + bulk ops -
     93      see `easypaperless.resources.SyncStoragePathsResource`
     94    * ``client.tags`` — tag CRUD + bulk ops -
     95      see `easypaperless.resources.SyncTagsResource`
     96
     97    All methods are synchronous wrappers around the async
     98    :class:`~easypaperless.client.PaperlessClient`.  Operations run on a
     99    dedicated background event loop thread so that the httpx connection pool
    100    is reused across calls and cleanup works correctly.
    101
    102    Use as a context manager to ensure proper cleanup:
    103
    104    Example:
    105        with SyncPaperlessClient(url="http://localhost:8000", api_token="abc") as client:
    106            tags = client.tags.list()
    107            docs = client.documents.list(search="invoice")
    108
    109    Note:
    110        Cannot be used inside an already-running event loop (e.g. Jupyter
    111        notebooks).  Use :class:`~easypaperless.client.PaperlessClient`
    112        directly in those environments.
    113    """
    114
    115    def __init__(self, url: str, api_token: str, **kwargs: Any) -> None:
    116        """Create a synchronous paperless-ngx client.
    117
    118        Args:
    119            url: Base URL of the paperless-ngx instance
    120                (e.g. ``"http://localhost:8000"``).
    121            api_token: API token.  Generate one in paperless-ngx under
    122                *Settings → API → Generate Token*.
    123            **kwargs: Additional keyword arguments forwarded to
    124                :class:`~easypaperless.client.PaperlessClient` (e.g.
    125                ``poll_interval``, ``poll_timeout``).
    126        """
    127        super().__init__(url, api_token, **kwargs)
    128
    129    def __enter__(self) -> SyncPaperlessClient:
    130        return self
    131
    132    def __exit__(self, *args: Any) -> None:
    133        self.close()

Synchronous interface to paperless-ngx.

Resources are accessible as attributes:

- `client.correspondents` — correspondent CRUD + bulk ops - see `easypaperless.resources.SyncCorrespondentsResource`
- `client.custom_fields` — custom field CRUD - see `easypaperless.resources.SyncCustomFieldsResource`
- `client.document_types` — document type CRUD + bulk ops - see `easypaperless.resources.SyncDocumentTypesResource`
- `client.documents` — document CRUD, bulk ops, upload, download - see `easypaperless.resources.SyncDocumentsResource`
- `client.documents.notes` — document notes - see `easypaperless.resources.SyncNotesResource`
- `client.storage_paths` — storage path CRUD + bulk ops - see `easypaperless.resources.SyncStoragePathsResource`
- `client.tags` — tag CRUD + bulk ops - see `easypaperless.resources.SyncTagsResource`

All methods are synchronous wrappers around the async `~easypaperless.client.PaperlessClient`. Operations run on a dedicated background event loop thread so that the httpx connection pool is reused across calls and cleanup works correctly.

Use as a context manager to ensure proper cleanup:

###### Example:

> with SyncPaperlessClient(url="http://localhost:8000", api_token="abc") as client: tags = client.tags.list() docs = client.documents.list(search="invoice")

###### Note:

> Cannot be used inside an already-running event loop (e.g. Jupyter notebooks). Use `~easypaperless.client.PaperlessClient` directly in those environments.

SyncPaperlessClient(url: str, api_token: str, **kwargs: Any) View Source

    115    def __init__(self, url: str, api_token: str, **kwargs: Any) -> None:
    116        """Create a synchronous paperless-ngx client.
    117
    118        Args:
    119            url: Base URL of the paperless-ngx instance
    120                (e.g. ``"http://localhost:8000"``).
    121            api_token: API token.  Generate one in paperless-ngx under
    122                *Settings → API → Generate Token*.
    123            **kwargs: Additional keyword arguments forwarded to
    124                :class:`~easypaperless.client.PaperlessClient` (e.g.
    125                ``poll_interval``, ``poll_timeout``).
    126        """
    127        super().__init__(url, api_token, **kwargs)

Create a synchronous paperless-ngx client.

###### Arguments:

- url: Base URL of the paperless-ngx instance (e.g. `"http://localhost:8000"`).
- api_token: API token. Generate one in paperless-ngx under Settings → API → Generate Token.
- **kwargs: Additional keyword arguments forwarded to `~easypaperless.client.PaperlessClient` (e.g. `poll_interval`, `poll_timeout`).

UNSET = UNSET
class Unset: View Source

     9class Unset:
    10    """Sentinel type signalling that a parameter was not provided.
    11
    12    Use the singleton :data:`UNSET` constant — do not instantiate directly.
    13    """
    14
    15    __slots__ = ()
    16
    17    def __repr__(self) -> str:
    18        return "UNSET"

Sentinel type signalling that a parameter was not provided.

Use the singleton `UNSET` constant — do not instantiate directly.

class MatchingAlgorithm(enum.IntEnum): View Source

     9class MatchingAlgorithm(IntEnum):
    10    """Auto-matching algorithm used by tags, correspondents, document types, and storage paths."""
    11
    12    NONE = 0
    13    ANY_WORD = 1
    14    ALL_WORDS = 2
    15    EXACT = 3
    16    REGEX = 4
    17    FUZZY = 5
    18    AUTO = 6

Auto-matching algorithm used by tags, correspondents, document types, and storage paths.

NONE = <MatchingAlgorithm.NONE: 0>
ANY_WORD = <MatchingAlgorithm.ANY_WORD: 1>
ALL_WORDS = <MatchingAlgorithm.ALL_WORDS: 2>
EXACT = <MatchingAlgorithm.EXACT: 3>
REGEX = <MatchingAlgorithm.REGEX: 4>
FUZZY = <MatchingAlgorithm.FUZZY: 5>
AUTO = <MatchingAlgorithm.AUTO: 6>
class PagedResult(pydantic.main.BaseModel, typing.Generic[~T]): View Source

    13class PagedResult(BaseModel, Generic[T]):
    14    """Wrapper returned by all ``list()`` methods.
    15
    16    Holds the pagination metadata returned by paperless-ngx alongside the
    17    deserialized resource items.
    18
    19    Attributes:
    20        count: Total number of matching items as reported by the server on
    21            the first fetched page.
    22        next: URL of the next page as returned by the API, or ``None``.
    23            Always ``None`` when auto-pagination is active (the default
    24            ``page=None``), because the navigation URL is meaningless once
    25            all pages have been consumed by the library.
    26        previous: URL of the previous page as returned by the API, or
    27            ``None``.  Always ``None`` when auto-pagination is active.
    28        all: All matching item IDs when the API includes them; ``None``
    29            otherwise.
    30        results: The deserialized resource items for this page / all fetched
    31            pages.
    32    """
    33
    34    count: int
    35    next: str | None = None
    36    previous: str | None = None
    37    all: List[int] | None = None
    38    results: List[T] = Field(default_factory=list)

Wrapper returned by all `list()` methods.

Holds the pagination metadata returned by paperless-ngx alongside the deserialized resource items.

###### Attributes:

- count: Total number of matching items as reported by the server on the first fetched page.
- next: URL of the next page as returned by the API, or `None`. Always `None` when auto-pagination is active (the default `page=None`), because the navigation URL is meaningless once all pages have been consumed by the library.
- previous: URL of the previous page as returned by the API, or `None`. Always `None` when auto-pagination is active.
- all: All matching item IDs when the API includes them; `None` otherwise.
- results: The deserialized resource items for this page / all fetched pages.

count: int = PydanticUndefined
next: str | None = None
previous: str | None = None
all: Optional[List[int]] = None
results: List[~T] = PydanticUndefined
class Correspondent(pydantic.main.BaseModel): View Source

    13class Correspondent(BaseModel):
    14    """A paperless-ngx correspondent (sender or recipient of a document).
    15
    16    Attributes:
    17        id: Unique correspondent ID.
    18        name: Correspondent name.
    19        document_count: Number of documents assigned to this correspondent.
    20        last_correspondence: Date of the most recent document assigned here,
    21            or ``None``.
    22    """
    23
    24    model_config = ConfigDict(extra="ignore")
    25
    26    id: int
    27    name: str
    28    slug: str | None = None
    29    match: str | None = None
    30    matching_algorithm: MatchingAlgorithm | None = None
    31    is_insensitive: bool | None = None
    32    document_count: int | None = None
    33    last_correspondence: date | None = None
    34    owner: int | None = None
    35    user_can_change: bool | None = None

A paperless-ngx correspondent (sender or recipient of a document).

###### Attributes:

- id: Unique correspondent ID.
- name: Correspondent name.
- document_count: Number of documents assigned to this correspondent.
- last_correspondence: Date of the most recent document assigned here, or `None`.

id: int = PydanticUndefined
name: str = PydanticUndefined
slug: str | None = None
match: str | None = None
matching_algorithm: MatchingAlgorithm | None = None
is_insensitive: bool | None = None
document_count: int | None = None
last_correspondence: datetime.date | None = None
owner: int | None = None
user_can_change: bool | None = None
class CustomField(pydantic.main.BaseModel): View Source

    26class CustomField(BaseModel):
    27    """A custom field definition in paperless-ngx.
    28
    29    Attributes:
    30        id: Unique custom-field ID.
    31        name: Field name shown in the UI.
    32        data_type: The value type for this field (see
    33            :class:`FieldDataType`).
    34        extra_data: Additional configuration (e.g. select options), or
    35            ``None``.
    36        document_count: Number of documents that have a value for this field.
    37    """
    38
    39    model_config = ConfigDict(extra="ignore")
    40
    41    id: int
    42    name: str
    43    data_type: FieldDataType
    44    extra_data: Any = None
    45    document_count: int | None = None

A custom field definition in paperless-ngx.

###### Attributes:

- id: Unique custom-field ID.
- name: Field name shown in the UI.
- data_type: The value type for this field (see `FieldDataType`).
- extra_data: Additional configuration (e.g. select options), or `None`.
- document_count: Number of documents that have a value for this field.

id: int = PydanticUndefined
name: str = PydanticUndefined
data_type: FieldDataType = PydanticUndefined
extra_data: Any = None
document_count: int | None = None
class CustomFieldValue(pydantic.main.BaseModel): View Source

    66class CustomFieldValue(BaseModel):
    67    """A custom field value attached to a document.
    68
    69    Attributes:
    70        field: ID of the :class:`~easypaperless.models.custom_fields.CustomField`
    71            definition.
    72        value: The stored value; its Python type depends on the field's
    73            ``data_type``.
    74    """
    75
    76    model_config = ConfigDict(extra="ignore")
    77
    78    field: int
    79    value: Any = None

A custom field value attached to a document.

###### Attributes:

- field: ID of the `~easypaperless.models.custom_fields.CustomField` definition.
- value: The stored value; its Python type depends on the field's `data_type`.

field: int = PydanticUndefined
value: Any = None
class Document(pydantic.main.BaseModel): View Source

    173class Document(BaseModel):
    174    """A paperless-ngx document.
    175
    176    Attributes:
    177        id: Unique document ID.
    178        title: Document title.
    179        content: Full OCR text content, if available.
    180        tags: List of tag IDs assigned to this document.
    181        document_type: ID of the assigned document type, or ``None``.
    182        correspondent: ID of the assigned correspondent, or ``None``.
    183        storage_path: ID of the assigned storage path, or ``None``.
    184        created: Document creation date (``date`` object). Changed from
    185            ``datetime`` to ``date`` in paperless-ngx API v9.
    186        created_date: Date portion of creation. **Deprecated** by
    187            paperless-ngx as of v9 — use ``created`` instead. Will be
    188            removed in a future API version.
    189        archive_serial_number: Archive serial number (ASN), or ``None``.
    190        custom_fields: List of :class:`CustomFieldValue` instances.
    191        notes: User notes attached to this document.
    192        search_hit: Full-text search relevance metadata, populated only when
    193            the document was returned by a full-text search.
    194        metadata: Extended file-level metadata (checksums, sizes, MIME type).
    195            ``None`` unless the document was fetched with
    196            ``include_metadata=True`` or retrieved via
    197            :meth:`~easypaperless._internal.resources.documents.DocumentsResource.get_metadata`.
    198    """
    199
    200    model_config = ConfigDict(extra="ignore", populate_by_name=True)
    201
    202    id: int
    203    title: str
    204    content: str | None = None
    205    tags: list[int] = Field(default_factory=list)
    206    document_type: int | None = None
    207    correspondent: int | None = None
    208    storage_path: int | None = None
    209    created: date | None = None
    210    created_date: date | None = None
    211    modified: datetime | None = None
    212    added: datetime | None = None
    213    archive_serial_number: int | None = None
    214    original_file_name: str | None = None
    215    archived_file_name: str | None = None
    216    owner: int | None = None
    217    user_can_change: bool | None = None
    218    is_shared_by_requester: bool | None = None
    219    notes: list[DocumentNote] = Field(default_factory=list)
    220    custom_fields: list[CustomFieldValue] = Field(default_factory=list)
    221    search_hit: SearchHit | None = Field(default=None, alias="__search_hit__")
    222    metadata: DocumentMetadata | None = None

A paperless-ngx document.

###### Attributes:

- id: Unique document ID.
- title: Document title.
- content: Full OCR text content, if available.
- tags: List of tag IDs assigned to this document.
- document_type: ID of the assigned document type, or `None`.
- correspondent: ID of the assigned correspondent, or `None`.
- storage_path: ID of the assigned storage path, or `None`.
- created: Document creation date (`date` object). Changed from `datetime` to `date` in paperless-ngx API v9.
- created_date: Date portion of creation. Deprecated by paperless-ngx as of v9 — use `created` instead. Will be removed in a future API version.
- archive_serial_number: Archive serial number (ASN), or `None`.
- custom_fields: List of `CustomFieldValue` instances.
- notes: User notes attached to this document.
- search_hit: Full-text search relevance metadata, populated only when the document was returned by a full-text search.
- metadata: Extended file-level metadata (checksums, sizes, MIME type). `None` unless the document was fetched with `include_metadata=True` or retrieved via `~easypaperless._internal.resources.documents.DocumentsResource.get_metadata()`.

id: int = PydanticUndefined
title: str = PydanticUndefined
content: str | None = None
tags: list[int] = PydanticUndefined
document_type: int | None = None
correspondent: int | None = None
storage_path: int | None = None
created: datetime.date | None = None
created_date: datetime.date | None = None
modified: datetime.datetime | None = None
added: datetime.datetime | None = None
archive_serial_number: int | None = None
original_file_name: str | None = None
archived_file_name: str | None = None
owner: int | None = None
user_can_change: bool | None = None
is_shared_by_requester: bool | None = None
notes: list[DocumentNote] = PydanticUndefined
custom_fields: list[CustomFieldValue] = PydanticUndefined
search_hit: SearchHit | None = None
metadata: DocumentMetadata | None = None
class DocumentMetadata(pydantic.main.BaseModel): View Source

    131class DocumentMetadata(BaseModel):
    132    """Extended file-level metadata for a document.
    133
    134    Returned by ``GET /api/documents/{id}/metadata/`` and optionally attached
    135    to a :class:`Document` when
    136    :meth:`~easypaperless._internal.resources.documents.DocumentsResource.get`
    137    is called with ``include_metadata=True``.
    138
    139    Because reading metadata requires disk I/O it is **not** included in
    140    document list responses; it must be requested explicitly.
    141
    142    Attributes:
    143        original_checksum: MD5 checksum of the original uploaded file.
    144        original_size: Size of the original file in bytes.
    145        original_mime_type: MIME type of the original file
    146            (e.g. ``"application/pdf"``).
    147        media_filename: Path of the archived file relative to the
    148            paperless-ngx media root.
    149        has_archive_version: ``True`` when paperless-ngx has produced an
    150            archived (post-processed) PDF in addition to the original.
    151        original_metadata: File-level metadata entries extracted from the
    152            original document (PDF XMP/info tags, etc.).
    153        archive_checksum: MD5 checksum of the archived file, or ``None`` if
    154            no archive version exists.
    155        archive_size: Size of the archived file in bytes, or ``None``.
    156        archive_metadata: File-level metadata entries from the archived
    157            document, or ``None``.
    158    """
    159
    160    model_config = ConfigDict(extra="ignore")
    161
    162    original_checksum: str | None = None
    163    original_size: int | None = None
    164    original_mime_type: str | None = None
    165    media_filename: str | None = None
    166    has_archive_version: bool | None = None
    167    original_metadata: list[FileMetadataEntry] = Field(default_factory=list)
    168    archive_checksum: str | None = None
    169    archive_size: int | None = None
    170    archive_metadata: list[FileMetadataEntry] | None = None

Extended file-level metadata for a document.

Returned by `GET /api/documents/{id}/metadata/` and optionally attached to a `Document` when `~easypaperless._internal.resources.documents.DocumentsResource.get()` is called with `include_metadata=True`.

Because reading metadata requires disk I/O it is not included in document list responses; it must be requested explicitly.

###### Attributes:

- original_checksum: MD5 checksum of the original uploaded file.
- original_size: Size of the original file in bytes.
- original_mime_type: MIME type of the original file (e.g. `"application/pdf"`).
- media_filename: Path of the archived file relative to the paperless-ngx media root.
- has_archive_version: `True` when paperless-ngx has produced an archived (post-processed) PDF in addition to the original.
- original_metadata: File-level metadata entries extracted from the original document (PDF XMP/info tags, etc.).
- archive_checksum: MD5 checksum of the archived file, or `None` if no archive version exists.
- archive_size: Size of the archived file in bytes, or `None`.
- archive_metadata: File-level metadata entries from the archived document, or `None`.

original_checksum: str | None = None
original_size: int | None = None
original_mime_type: str | None = None
media_filename: str | None = None
has_archive_version: bool | None = None
original_metadata: list[FileMetadataEntry] = PydanticUndefined
archive_checksum: str | None = None
archive_size: int | None = None
archive_metadata: list[FileMetadataEntry] | None = None
class DocumentNote(pydantic.main.BaseModel): View Source

     82class DocumentNote(BaseModel):
     83    """A user note attached to a document.
     84
     85    Attributes:
     86        id: Unique note ID.
     87        note: Text content of the note.
     88        created: Timestamp when the note was created.
     89        document: ID of the parent document.
     90        user: ID of the user who created the note.
     91    """
     92
     93    model_config = ConfigDict(extra="ignore")
     94
     95    id: int | None = None
     96    note: str
     97    created: datetime | None = None
     98    document: int | None = None
     99    user: int | None = None
    100
    101    @field_validator("user", mode="before")
    102    @classmethod
    103    def _coerce_user(cls, v: object) -> int | None:
    104        if isinstance(v, dict):
    105            return v.get("id")
    106        return v  # type: ignore[return-value]

A user note attached to a document.

###### Attributes:

- id: Unique note ID.
- note: Text content of the note.
- created: Timestamp when the note was created.
- document: ID of the parent document.
- user: ID of the user who created the note.

id: int | None = None
note: str = PydanticUndefined
created: datetime.datetime | None = None
document: int | None = None
user: int | None = None
class DocumentType(pydantic.main.BaseModel): View Source

    11class DocumentType(BaseModel):
    12    """A paperless-ngx document type (e.g. Invoice, Receipt, Contract).
    13
    14    Attributes:
    15        id: Unique document-type ID.
    16        name: Document-type name.
    17        document_count: Number of documents assigned to this document type.
    18    """
    19
    20    model_config = ConfigDict(extra="ignore")
    21
    22    id: int
    23    name: str
    24    slug: str | None = None
    25    match: str | None = None
    26    matching_algorithm: MatchingAlgorithm | None = None
    27    is_insensitive: bool | None = None
    28    document_count: int | None = None
    29    owner: int | None = None
    30    user_can_change: bool | None = None

A paperless-ngx document type (e.g. Invoice, Receipt, Contract).

###### Attributes:

- id: Unique document-type ID.
- name: Document-type name.
- document_count: Number of documents assigned to this document type.

id: int = PydanticUndefined
name: str = PydanticUndefined
slug: str | None = None
match: str | None = None
matching_algorithm: MatchingAlgorithm | None = None
is_insensitive: bool | None = None
document_count: int | None = None
owner: int | None = None
user_can_change: bool | None = None
class FieldDataType(enum.StrEnum): View Source

    12class FieldDataType(StrEnum):
    13    """Allowed data types for a custom field."""
    14
    15    string = "string"
    16    boolean = "boolean"
    17    integer = "integer"
    18    float = "float"
    19    monetary = "monetary"
    20    date = "date"
    21    url = "url"
    22    documentlink = "documentlink"
    23    select = "select"

Allowed data types for a custom field.

string = <FieldDataType.string: 'string'>
boolean = <FieldDataType.boolean: 'boolean'>
integer = <FieldDataType.integer: 'integer'>
float = <FieldDataType.float: 'float'>
monetary = <FieldDataType.monetary: 'monetary'>
date = <FieldDataType.date: 'date'>
url = <FieldDataType.url: 'url'>
documentlink = <FieldDataType.documentlink: 'documentlink'>
select = <FieldDataType.select: 'select'>
class FileMetadataEntry(pydantic.main.BaseModel): View Source

    109class FileMetadataEntry(BaseModel):
    110    """A single embedded metadata key-value pair from a document file.
    111
    112    Paperless-ngx reads file-level metadata (e.g. PDF XMP/info tags) and
    113    exposes each entry in this format.  ``namespace`` and ``prefix`` are
    114    ``None`` for non-namespaced entries.
    115
    116    Attributes:
    117        namespace: XML namespace URI, or ``None``.
    118        prefix: Namespace prefix (e.g. ``"pdf"``), or ``None``.
    119        key: Metadata key (e.g. ``"Producer"``).
    120        value: Metadata value as a string.
    121    """
    122
    123    model_config = ConfigDict(extra="ignore")
    124
    125    namespace: str | None = None
    126    prefix: str | None = None
    127    key: str
    128    value: str

A single embedded metadata key-value pair from a document file.

Paperless-ngx reads file-level metadata (e.g. PDF XMP/info tags) and exposes each entry in this format. `namespace` and `prefix` are `None` for non-namespaced entries.

###### Attributes:

- namespace: XML namespace URI, or `None`.
- prefix: Namespace prefix (e.g. `"pdf"`), or `None`.
- key: Metadata key (e.g. `"Producer"`).
- value: Metadata value as a string.

namespace: str | None = None
prefix: str | None = None
key: str = PydanticUndefined
value: str = PydanticUndefined
class PermissionSet(pydantic.main.BaseModel): View Source

    7class PermissionSet(BaseModel):
    8    users: list[int] = Field(default_factory=list)
    9    groups: list[int] = Field(default_factory=list)

!!! abstract "Usage Documentation" Models

A base class for creating Pydantic models.

###### Attributes:

- __class_vars__: The names of the class variables defined on the model.
- __private_attributes__: Metadata about the private attributes of the model.
- __signature__: The synthesized `__init__` [`Signature`][inspect.Signature] of the model.
- __pydantic_complete__: Whether model building is completed, or if there are still undefined fields.
- __pydantic_core_schema__: The core schema of the model.
- __pydantic_custom_init__: Whether the model has a custom `__init__` function.
- __pydantic_decorators__: Metadata containing the decorators defined on the model. This replaces `Model.__validators__` and `Model.__root_validators__` from Pydantic V1.
- __pydantic_generic_metadata__: Metadata for generic models; contains data used for a similar purpose to __args__, __origin__, __parameters__ in typing-module generics. May eventually be replaced by these.
- __pydantic_parent_namespace__: Parent namespace of the model, used for automatic rebuilding of models.
- __pydantic_post_init__: The name of the post-init method for the model, if defined.
- __pydantic_root_model__: Whether the model is a [`RootModel`][pydantic.root_model.RootModel].
- __pydantic_serializer__: The `pydantic-core` `SchemaSerializer` used to dump instances of the model.
- __pydantic_validator__: The `pydantic-core` `SchemaValidator` used to validate instances of the model.
- __pydantic_fields__: A dictionary of field names and their corresponding [`FieldInfo`][pydantic.fields.FieldInfo] objects.
- __pydantic_computed_fields__: A dictionary of computed field names and their corresponding [`ComputedFieldInfo`][pydantic.fields.ComputedFieldInfo] objects.
- __pydantic_extra__: A dictionary containing extra values, if [`extra`][pydantic.config.ConfigDict.extra] is set to `'allow'`.
- __pydantic_fields_set__: The names of fields explicitly set during instantiation.
- __pydantic_private__: Values of private attributes set on the model instance.

users: list[int] = PydanticUndefined
groups: list[int] = PydanticUndefined
class SearchHit(pydantic.main.BaseModel): View Source

    49class SearchHit(BaseModel):
    50    """Full-text search relevance metadata returned alongside a document.
    51
    52    Attributes:
    53        score: Relevance score assigned by the Whoosh FTS engine.
    54        highlights: HTML snippet with matching terms highlighted.
    55        rank: Position in the result set by relevance.
    56    """
    57
    58    model_config = ConfigDict(extra="ignore")
    59
    60    score: float | None = None
    61    highlights: str | None = None
    62    note_highlights: str | None = None
    63    rank: int | None = None

Full-text search relevance metadata returned alongside a document.

###### Attributes:

- score: Relevance score assigned by the Whoosh FTS engine.
- highlights: HTML snippet with matching terms highlighted.
- rank: Position in the result set by relevance.

score: float | None = None
highlights: str | None = None
note_highlights: str | None = None
rank: int | None = None
class SetPermissions(pydantic.main.BaseModel): View Source

    12class SetPermissions(BaseModel):
    13    view: PermissionSet = Field(default_factory=PermissionSet)
    14    change: PermissionSet = Field(default_factory=PermissionSet)

!!! abstract "Usage Documentation" Models

A base class for creating Pydantic models.

###### Attributes:

- __class_vars__: The names of the class variables defined on the model.
- __private_attributes__: Metadata about the private attributes of the model.
- __signature__: The synthesized `__init__` [`Signature`][inspect.Signature] of the model.
- __pydantic_complete__: Whether model building is completed, or if there are still undefined fields.
- __pydantic_core_schema__: The core schema of the model.
- __pydantic_custom_init__: Whether the model has a custom `__init__` function.
- __pydantic_decorators__: Metadata containing the decorators defined on the model. This replaces `Model.__validators__` and `Model.__root_validators__` from Pydantic V1.
- __pydantic_generic_metadata__: Metadata for generic models; contains data used for a similar purpose to __args__, __origin__, __parameters__ in typing-module generics. May eventually be replaced by these.
- __pydantic_parent_namespace__: Parent namespace of the model, used for automatic rebuilding of models.
- __pydantic_post_init__: The name of the post-init method for the model, if defined.
- __pydantic_root_model__: Whether the model is a [`RootModel`][pydantic.root_model.RootModel].
- __pydantic_serializer__: The `pydantic-core` `SchemaSerializer` used to dump instances of the model.
- __pydantic_validator__: The `pydantic-core` `SchemaValidator` used to validate instances of the model.
- __pydantic_fields__: A dictionary of field names and their corresponding [`FieldInfo`][pydantic.fields.FieldInfo] objects.
- __pydantic_computed_fields__: A dictionary of computed field names and their corresponding [`ComputedFieldInfo`][pydantic.fields.ComputedFieldInfo] objects.
- __pydantic_extra__: A dictionary containing extra values, if [`extra`][pydantic.config.ConfigDict.extra] is set to `'allow'`.
- __pydantic_fields_set__: The names of fields explicitly set during instantiation.
- __pydantic_private__: Values of private attributes set on the model instance.

view: PermissionSet = PydanticUndefined
change: PermissionSet = PydanticUndefined
class StoragePath(pydantic.main.BaseModel): View Source

    11class StoragePath(BaseModel):
    12    """A paperless-ngx storage path — controls where archived files are stored.
    13
    14    Attributes:
    15        id: Unique storage-path ID.
    16        name: Storage-path name.
    17        path: Template string used to build the storage path, e.g.
    18            ``"{created_year}/{correspondent}/{title}"``.
    19        document_count: Number of documents using this storage path.
    20    """
    21
    22    model_config = ConfigDict(extra="ignore")
    23
    24    id: int
    25    name: str
    26    slug: str | None = None
    27    path: str | None = None
    28    match: str | None = None
    29    matching_algorithm: MatchingAlgorithm | None = None
    30    is_insensitive: bool | None = None
    31    document_count: int | None = None
    32    owner: int | None = None
    33    user_can_change: bool | None = None

A paperless-ngx storage path — controls where archived files are stored.

###### Attributes:

- id: Unique storage-path ID.
- name: Storage-path name.
- path: Template string used to build the storage path, e.g. `"{created_year}/{correspondent}/{title}"`.
- document_count: Number of documents using this storage path.

id: int = PydanticUndefined
name: str = PydanticUndefined
slug: str | None = None
path: str | None = None
match: str | None = None
matching_algorithm: MatchingAlgorithm | None = None
is_insensitive: bool | None = None
document_count: int | None = None
owner: int | None = None
user_can_change: bool | None = None
class Tag(pydantic.main.BaseModel): View Source

    11class Tag(BaseModel):
    12    """A paperless-ngx tag.
    13
    14    Attributes:
    15        id: Unique tag ID.
    16        name: Tag name.
    17        color: Hex colour code used in the UI (e.g. ``"#ff0000"``).
    18        is_inbox_tag: If ``True``, newly ingested documents receive this tag
    19            automatically until they are processed.
    20        document_count: Number of documents currently assigned to this tag.
    21        parent: ID of the parent tag for hierarchical tag trees, or ``None``.
    22        children: IDs of child tags, or ``None``.
    23    """
    24
    25    model_config = ConfigDict(extra="ignore")
    26
    27    id: int
    28    name: str
    29    slug: str | None = None
    30    color: str | None = None
    31    text_color: str | None = None
    32    match: str | None = None
    33    matching_algorithm: MatchingAlgorithm | None = None
    34    is_insensitive: bool | None = None
    35    is_inbox_tag: bool | None = None
    36    document_count: int | None = None
    37    owner: int | None = None
    38    user_can_change: bool | None = None
    39    parent: int | None = None
    40    children: list[int] | None = None

A paperless-ngx tag.

###### Attributes:

- id: Unique tag ID.
- name: Tag name.
- color: Hex colour code used in the UI (e.g. `"#ff0000"`).
- is_inbox_tag: If `True`, newly ingested documents receive this tag automatically until they are processed.
- document_count: Number of documents currently assigned to this tag.
- parent: ID of the parent tag for hierarchical tag trees, or `None`.
- children: IDs of child tags, or `None`.

id: int = PydanticUndefined
name: str = PydanticUndefined
slug: str | None = None
color: str | None = None
text_color: str | None = None
match: str | None = None
matching_algorithm: MatchingAlgorithm | None = None
is_insensitive: bool | None = None
is_inbox_tag: bool | None = None
document_count: int | None = None
owner: int | None = None
user_can_change: bool | None = None
parent: int | None = None
children: list[int] | None = None
class Task(pydantic.main.BaseModel): View Source

    24class Task(BaseModel):
    25    """A paperless-ngx background processing task (e.g. document ingestion).
    26
    27    Attributes:
    28        task_id: Unique Celery task identifier.
    29        task_file_name: Original file name submitted for processing.
    30        status: Current task status as a :class:`TaskStatus` enum value.
    31        result: Human-readable result or error message, set on completion.
    32        related_document: String representation of the resulting document ID
    33            on success, ``None`` otherwise.
    34    """
    35
    36    model_config = ConfigDict(extra="ignore")
    37
    38    task_id: str
    39    task_file_name: str | None = None
    40    date_created: datetime | None = None
    41    date_done: datetime | None = None
    42    type: str | None = None
    43    status: TaskStatus | None = None
    44    result: str | None = None
    45    acknowledged: bool | None = None
    46    related_document: str | None = None

A paperless-ngx background processing task (e.g. document ingestion).

###### Attributes:

- task_id: Unique Celery task identifier.
- task_file_name: Original file name submitted for processing.
- status: Current task status as a `TaskStatus` enum value.
- result: Human-readable result or error message, set on completion.
- related_document: String representation of the resulting document ID on success, `None` otherwise.

task_id: str = PydanticUndefined
task_file_name: str | None = None
date_created: datetime.datetime | None = None
date_done: datetime.datetime | None = None
type: str | None = None
status: TaskStatus | None = None
result: str | None = None
acknowledged: bool | None = None
related_document: str | None = None
class TaskStatus(enum.StrEnum): View Source

    13class TaskStatus(StrEnum):
    14    """Status values for a paperless-ngx background processing task."""
    15
    16    PENDING = "PENDING"
    17    STARTED = "STARTED"
    18    SUCCESS = "SUCCESS"
    19    FAILURE = "FAILURE"
    20    RETRY = "RETRY"
    21    REVOKED = "REVOKED"

Status values for a paperless-ngx background processing task.

PENDING = <TaskStatus.PENDING: 'PENDING'>
STARTED = <TaskStatus.STARTED: 'STARTED'>
SUCCESS = <TaskStatus.SUCCESS: 'SUCCESS'>
FAILURE = <TaskStatus.FAILURE: 'FAILURE'>
RETRY = <TaskStatus.RETRY: 'RETRY'>
REVOKED = <TaskStatus.REVOKED: 'REVOKED'>
class PaperlessError(builtins.Exception): View Source

     7class PaperlessError(Exception):
     8    """Base exception for all easypaperless errors.
     9
    10    Attributes:
    11        status_code: The HTTP status code associated with the error, or
    12            ``None`` for non-HTTP errors (e.g. timeouts, local validation).
    13    """
    14
    15    def __init__(self, message: str, status_code: int | None = None) -> None:
    16        """Create a PaperlessError.
    17
    18        Args:
    19            message: Human-readable error description.
    20            status_code: HTTP status code, if applicable.
    21        """
    22        super().__init__(message)
    23        self.status_code = status_code

Base exception for all easypaperless errors.

###### Attributes:

- status_code: The HTTP status code associated with the error, or `None` for non-HTTP errors (e.g. timeouts, local validation).

PaperlessError(message: str, status_code: int | None = None) View Source

    15    def __init__(self, message: str, status_code: int | None = None) -> None:
    16        """Create a PaperlessError.
    17
    18        Args:
    19            message: Human-readable error description.
    20            status_code: HTTP status code, if applicable.
    21        """
    22        super().__init__(message)
    23        self.status_code = status_code

Create a PaperlessError.

###### Arguments:

- message: Human-readable error description.
- status_code: HTTP status code, if applicable.

status_code
class AuthError(easypaperless.PaperlessError): View Source

    26class AuthError(PaperlessError):
    27    """Raised on 401 or 403 responses.
    28
    29    Indicates that the API key is missing, invalid, or lacks permission for
    30    the requested operation.
    31    """

Raised on 401 or 403 responses.

Indicates that the API key is missing, invalid, or lacks permission for the requested operation.

class NotFoundError(easypaperless.PaperlessError): View Source

    34class NotFoundError(PaperlessError):
    35    """Raised on 404 responses or when a name lookup fails."""

Raised on 404 responses or when a name lookup fails.

class ValidationError(easypaperless.PaperlessError): View Source

    38class ValidationError(PaperlessError):
    39    """Raised on 422 responses or bad input supplied by the caller."""

Raised on 422 responses or bad input supplied by the caller.

class ServerError(easypaperless.PaperlessError): View Source

    42class ServerError(PaperlessError):
    43    """Raised on 5xx responses or unrecoverable transport errors."""

Raised on 5xx responses or unrecoverable transport errors.

class UploadError(easypaperless.PaperlessError): View Source

    46class UploadError(PaperlessError):
    47    """Raised when file submission or document processing fails.
    48
    49    Typically raised when paperless-ngx reports a ``FAILURE`` status on the
    50    Celery task created by
    51    :meth:`~easypaperless.client.PaperlessClient.upload_document`.
    52    """

Raised when file submission or document processing fails.

Typically raised when paperless-ngx reports a `FAILURE` status on the Celery task created by `~easypaperless.client.PaperlessClient.upload_document()`.

class TaskTimeoutError(easypaperless.PaperlessError): View Source

    55class TaskTimeoutError(PaperlessError):
    56    """Raised when upload polling exceeds the configured timeout.
    57
    58    Raised by :meth:`~easypaperless.client.PaperlessClient.upload_document`
    59    (with ``wait=True``) when the document processing task does not reach a
    60    terminal state within ``poll_timeout`` seconds.
    61    """
    62
    63    def __init__(self, message: str) -> None:
    64        super().__init__(message, status_code=None)

Raised when upload polling exceeds the configured timeout.

Raised by `~easypaperless.client.PaperlessClient.upload_document()` (with `wait=True`) when the document processing task does not reach a terminal state within `poll_timeout` seconds.

TaskTimeoutError(message: str) View Source

    63    def __init__(self, message: str) -> None:
    64        super().__init__(message, status_code=None)

Create a PaperlessError.

###### Arguments:

- message: Human-readable error description.
- status_code: HTTP status code, if applicable.