easypaperless

easypaperless — Python API wrapper for paperless-ngx.

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

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

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)
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:
 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):
 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.

ANY_WORD = <MatchingAlgorithm.ANY_WORD: 1>
ALL_WORDS = <MatchingAlgorithm.ALL_WORDS: 2>
class PagedResult(pydantic.main.BaseModel, typing.Generic[~T]):
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):
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):
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):
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: int = PydanticUndefined
value: Any = None
class Document(pydantic.main.BaseModel):
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):
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):
 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):
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):
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'>
select = <FieldDataType.select: 'select'>
class FileMetadataEntry(pydantic.main.BaseModel):
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):
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):
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):
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):
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):
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):
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):
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):
 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)
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):
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):
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):
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):
42class ServerError(PaperlessError):
43    """Raised on 5xx responses or unrecoverable transport errors."""

Raised on 5xx responses or unrecoverable transport errors.

class UploadError(easypaperless.PaperlessError):
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):
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)
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.