Implements a first vertical slice of the Outline RPC API (auth, documents, collections, users) covering the structural patterns used across the whole API: single object, paginated list, tree, create/update, delete, search. Chosen as the basis for future CLI and GUI clients built on top of this crate. - Handwritten client (not codegen) against the vendored OpenAPI spec, since Outline's API is uniformly POST /api/<resource>.<action> with JSON bodies and inline/anonymous schemas that generators handle poorly - Async (reqwest + tokio) Client, cheaply cloneable, no &mut self methods - thiserror-based Error with ErrorKind classification and boxed API error context; forward-compatible models (unknown fields ignored, unknown string-enum values preserved via a catch-all variant) since the API is unversioned and self-hosted instances vary in age - Pagination via Page<T>/Paginator with next_page/collect_all/into_stream - wiremock-based test suite plus a spec-coverage test guarding against typos in RPC method names
2.1 KiB
outline
An async Rust client library for the Outline knowledge base API.
This crate is the foundation for building Outline clients (CLI, GUI, ...) on top of a shared, well-tested API layer. It only talks to the API — no CLI or GUI code lives here.
Quickstart
use outline::Client;
# async fn run() -> outline::Result<()> {
let client = Client::new("ol_api_...")?;
let me = client.auth().info().await?;
println!("Signed in as {} ({})", me.user.name, me.team.name);
let mut documents = client.documents().list().collection_id("col_123").paginate();
while let Some(page) = documents.next_page().await? {
for document in page.items {
println!("{}", document.title);
}
}
# Ok(())
# }
For a self-hosted instance or an OAuth access token, use [Client::builder]:
use std::time::Duration;
use outline::Client;
# fn run() -> outline::Result<()> {
let client = Client::builder()
.base_url("https://wiki.example.com")
.access_token("...")
.timeout(Duration::from_secs(10))
.build()?;
# let _ = client;
# Ok(())
# }
Design notes
The Outline API is RPC-style: every endpoint is POST /api/<resource>.<action>
with a JSON body and a {ok, data, pagination, policies} envelope. This crate
mirrors that with a single internal request primitive; resources are exposed
as scoped accessors (client.documents(), client.collections(), ...).
Because the API is unversioned and self-hosted instances vary in age, models are deliberately forward-compatible: unknown fields are ignored and unknown string-enum values are preserved rather than causing deserialization to fail.
Status
This crate currently covers a first vertical slice of the API — auth,
documents, collections, users — chosen to validate the request/response
patterns (single object, paginated list, tree, create/update, delete, search)
used across the rest of the API. Broader endpoint coverage, automatic retry
on rate limiting, and streaming exports are planned but not yet implemented.
License
MIT OR Apache-2.0