Skip to main content

paperless_api/
lib.rs

1//! A small async client for interacting with the Paperless-ngx API.
2//!
3//! This crate provides [`PaperlessClient`] for talking to a Paperless instance and
4//! convenience types for working with documents, tags, custom fields, correspondents,
5//! document types, and tasks.
6//!
7//! # Getting started
8//!
9//! Create a client with your Paperless base URL and API token:
10//!
11//! ```no_run
12//! use paperless_api::PaperlessClient;
13//!
14//! # async fn run() -> Result<(), Box<dyn std::error::Error>> {
15//! let client = PaperlessClient::new(
16//!     "https://paperless.example.com",
17//!     "your-api-token",
18//!     None,
19//! )?;
20//! # let _ = client;
21//! # Ok(())
22//! # }
23//! ```
24//!
25//! # Refreshing cached metadata
26//!
27//! The client keeps some metadata cached locally, such as tags, custom fields,
28//! correspondents, and document types.
29//!
30//! You can refresh individual caches:
31//!
32//! ```no_run
33//! use paperless_api::PaperlessClient;
34//!
35//! # async fn run() -> Result<(), Box<dyn std::error::Error>> {
36//! let mut client = PaperlessClient::new(
37//!     "https://paperless.example.com",
38//!     "your-api-token",
39//!     None,
40//! )?;
41//!
42//! client.refresh_tags().await?;
43//! client.refresh_custom_fields().await?;
44//! # Ok(())
45//! # }
46//! ```
47//!
48//! Or refresh multiple datasets at once:
49//!
50//! ```no_run
51//! use paperless_api::{PaperlessClient, RefreshData};
52//!
53//! # async fn run() -> Result<(), Box<dyn std::error::Error>> {
54//! let mut client = PaperlessClient::new(
55//!     "https://paperless.example.com",
56//!     "your-api-token",
57//!     None,
58//! )?;
59//!
60//! client.refresh([RefreshData::Tags, RefreshData::CustomFields]).await?;
61//! # Ok(())
62//! # }
63//! ```
64//!
65//! # Working with tags
66//!
67//! After refreshing tags, you can look them up from the local cache:
68//!
69//! ```no_run
70//! use paperless_api::PaperlessClient;
71//!
72//! # async fn run() -> Result<(), Box<dyn std::error::Error>> {
73//! let mut client = PaperlessClient::new(
74//!     "https://paperless.example.com",
75//!     "your-api-token",
76//!     None,
77//! )?;
78//!
79//! client.refresh_tags().await?;
80//!
81//! if let Some(tag) = client.find_tag_by_name("invoice") {
82//!     let docs = client.get_documents_by_tags(&[tag.id], true).await?;
83//!     println!("found {} documents", docs.len());
84//! }
85//! # Ok(())
86//! # }
87//! ```
88
89pub mod client;
90pub mod correspondent;
91pub mod custom_field;
92pub mod document;
93pub mod document_type;
94pub mod tag;
95pub mod task;
96pub mod user;
97
98pub use client::{PaperlessClient, RefreshData};
99pub use custom_field::{CustomField, DocumentCustomField};
100pub use document::Document;
101pub use tag::Tag;
102pub use task::Task;
103pub use user::User;
104
105#[derive(Debug, thiserror::Error)]
106pub enum Error {
107    #[error("response error: status code {status_code}, body: {body}")]
108    Response { status_code: u16, body: String },
109
110    #[error(transparent)]
111    Request(#[from] Box<dyn std::error::Error + Send + Sync + 'static>),
112
113    #[error("other error: {0}")]
114    Other(String),
115
116    #[error("invalid json: {0}")]
117    InvalidJson(String),
118
119    #[error("not found")]
120    NotFound,
121
122    #[error("not changeable")]
123    NotChangeable,
124}
125
126type Result<T> = std::result::Result<T, Error>;