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
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    PermissionSet,
32    SearchHit,
33    SetPermissions,
34    StoragePath,
35    Tag,
36    Task,
37    TaskStatus,
38)
39from easypaperless.sync import SyncPaperlessClient
40
41logging.getLogger("easypaperless").addHandler(logging.NullHandler())
42
43__all__ = [
44    "__version__",
45    # Clients
46    "PaperlessClient",
47    "SyncPaperlessClient",
48    # Sentinel
49    "UNSET",
50    # Models
51    "MatchingAlgorithm",
52    "Correspondent",
53    "CustomField",
54    "CustomFieldValue",
55    "Document",
56    "DocumentMetadata",
57    "DocumentNote",
58    "DocumentType",
59    "FieldDataType",
60    "FileMetadataEntry",
61    "PermissionSet",
62    "SearchHit",
63    "SetPermissions",
64    "StoragePath",
65    "Tag",
66    "Task",
67    "TaskStatus",
68    # Exceptions
69    "PaperlessError",
70    "AuthError",
71    "NotFoundError",
72    "ValidationError",
73    "ServerError",
74    "UploadError",
75    "TaskTimeoutError",
76]
__version__: str = '0.1.0'
class PaperlessClient(easypaperless.client._ClientCore):
131class PaperlessClient(_ClientCore):
132    """Async client for the paperless-ngx API.
133
134    Resources are accessible as attributes:
135
136    * ``client.correspondents`` — correspondent CRUD + bulk ops - see `easypaperless.resources.CorrespondentsResource`
137    * ``client.custom_fields`` — custom field CRUD - see `easypaperless.resources.CustomFieldsResource`
138    * ``client.document_types`` — document type CRUD + bulk ops - see `easypaperless.resources.DocumentTypesResource`
139    * ``client.documents`` — document CRUD, bulk ops, upload, download - see `easypaperless.resources.DocumentsResource`
140    * ``client.documents.notes`` — document notes - see `easypaperless.resources.NotesResource`
141    * ``client.storage_paths`` — storage path CRUD + bulk ops - see `easypaperless.resources.StoragePathsResource`
142    * ``client.tags`` — tag CRUD + bulk ops - see `easypaperless.resources.TagsResource`
143
144    Use as an async context manager to ensure the underlying HTTP connection
145    pool is closed when you are done:
146
147    Example:
148        async with PaperlessClient(url="http://localhost:8000", api_key="abc") as client:
149            docs = await client.documents.list(max_results=10)
150    """
151
152    def __init__(
153        self,
154        url: str,
155        api_key: str,
156        *,
157        timeout: float = 30.0,
158        poll_interval: float = 2.0,
159        poll_timeout: float = 60.0,
160    ) -> None:
161        """Create an async paperless-ngx client.
162
163        Args:
164            url: Base URL of the paperless-ngx instance
165                (e.g. ``"http://localhost:8000"``).
166            api_key: API token.  Generate one in paperless-ngx under
167                *Settings → API → Generate Token*.
168            timeout: Default request timeout in seconds.  Default: ``30.0``.
169            poll_interval: Seconds between status checks when ``wait=True``
170                is passed to :meth:`documents.upload`.  Default: ``2.0``.
171            poll_timeout: Maximum seconds to wait for a document to finish
172                processing before raising
173                :exc:`~easypaperless.exceptions.TaskTimeoutError`.
174                Default: ``60.0``.
175        """
176        super().__init__(
177            url, api_key, timeout=timeout, poll_interval=poll_interval, poll_timeout=poll_timeout
178        )
179
180    async def __aenter__(self) -> PaperlessClient:
181        return self
182
183    async def __aexit__(self, *args: Any) -> None:
184        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_key="abc") as client: docs = await client.documents.list(max_results=10)

PaperlessClient( url: str, api_key: str, *, timeout: float = 30.0, poll_interval: float = 2.0, poll_timeout: float = 60.0)
152    def __init__(
153        self,
154        url: str,
155        api_key: str,
156        *,
157        timeout: float = 30.0,
158        poll_interval: float = 2.0,
159        poll_timeout: float = 60.0,
160    ) -> None:
161        """Create an async paperless-ngx client.
162
163        Args:
164            url: Base URL of the paperless-ngx instance
165                (e.g. ``"http://localhost:8000"``).
166            api_key: API token.  Generate one in paperless-ngx under
167                *Settings → API → Generate Token*.
168            timeout: Default request timeout in seconds.  Default: ``30.0``.
169            poll_interval: Seconds between status checks when ``wait=True``
170                is passed to :meth:`documents.upload`.  Default: ``2.0``.
171            poll_timeout: Maximum seconds to wait for a document to finish
172                processing before raising
173                :exc:`~easypaperless.exceptions.TaskTimeoutError`.
174                Default: ``60.0``.
175        """
176        super().__init__(
177            url, api_key, timeout=timeout, poll_interval=poll_interval, poll_timeout=poll_timeout
178        )

Create an async paperless-ngx client.

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

Create a synchronous paperless-ngx client.

Arguments:
  • url: Base URL of the paperless-ngx instance (e.g. "http://localhost:8000").
  • api_key: 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 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 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):
172class Document(BaseModel):
173    """A paperless-ngx document.
174
175    Attributes:
176        id: Unique document ID.
177        title: Document title.
178        content: Full OCR text content, if available.
179        tags: List of tag IDs assigned to this document.
180        document_type: ID of the assigned document type, or ``None``.
181        correspondent: ID of the assigned correspondent, or ``None``.
182        storage_path: ID of the assigned storage path, or ``None``.
183        created: Full creation datetime.
184        created_date: Date portion of creation (``date`` object).
185        archive_serial_number: Archive serial number (ASN), or ``None``.
186        custom_fields: List of :class:`CustomFieldValue` instances.
187        notes: User notes attached to this document.
188        search_hit: Full-text search relevance metadata, populated only when
189            the document was returned by a full-text search.
190        metadata: Extended file-level metadata (checksums, sizes, MIME type).
191            ``None`` unless the document was fetched with
192            ``include_metadata=True`` or enriched via
193            :meth:`~easypaperless.PaperlessClient.get_document_metadata`.
194    """
195
196    model_config = ConfigDict(extra="ignore", populate_by_name=True)
197
198    id: int
199    title: str
200    content: str | None = None
201    tags: list[int] = Field(default_factory=list)
202    document_type: int | None = None
203    correspondent: int | None = None
204    storage_path: int | None = None
205    created: datetime | None = None
206    created_date: date | None = None
207    modified: datetime | None = None
208    added: datetime | None = None
209    archive_serial_number: int | None = None
210    original_file_name: str | None = None
211    archived_file_name: str | None = None
212    owner: int | None = None
213    user_can_change: bool | None = None
214    is_shared_by_requester: bool | None = None
215    notes: list[DocumentNote] = Field(default_factory=list)
216    custom_fields: list[CustomFieldValue] = Field(default_factory=list)
217    search_hit: SearchHit | None = Field(default=None, alias="__search_hit__")
218    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: Full creation datetime.
  • created_date: Date portion of creation (date object).
  • 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 enriched via ~easypaperless.PaperlessClient.get_document_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.datetime | 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 :meth:`~easypaperless.PaperlessClient.get_document`
136    is called with ``include_metadata=True``.
137
138    Because reading metadata requires disk I/O it is **not** included in
139    document list responses; it must be requested explicitly.
140
141    Attributes:
142        original_checksum: MD5 checksum of the original uploaded file.
143        original_size: Size of the original file in bytes.
144        original_mime_type: MIME type of the original file
145            (e.g. ``"application/pdf"``).
146        media_filename: Path of the archived file relative to the
147            paperless-ngx media root.
148        has_archive_version: ``True`` when paperless-ngx has produced an
149            archived (post-processed) PDF in addition to the original.
150        original_metadata: File-level metadata entries extracted from the
151            original document (PDF XMP/info tags, etc.).
152        archive_checksum: MD5 checksum of the archived file, or ``None`` if
153            no archive version exists.
154        archive_size: Size of the archived file in bytes, or ``None``.
155        archive_metadata: File-level metadata entries from the archived
156            document, or ``None``.
157    """
158
159    model_config = ConfigDict(extra="ignore")
160
161    original_checksum: str | None = None
162    original_size: int | None = None
163    original_mime_type: str | None = None
164    media_filename: str | None = None
165    has_archive_version: bool | None = None
166    original_metadata: list[FileMetadataEntry] = Field(default_factory=list)
167    archive_checksum: str | None = None
168    archive_size: int | None = None
169    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.PaperlessClient.get_document() 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.