Skip to content

Resource accessors

ApiClient exposes typed accessor methods that return a Resources<'_, T> handle scoped to one resource. The built-in accessors are:

clients(), invoices(), payments(), quotes(), credits(), products(), expenses(), vendors(), projects(), and tasks().

For any other modeled resource family, use the generic resource::<T>(Resource) method with a Resource variant. The generic handle covers resource families even when Koban does not ship a built-in Rust struct for them.

Methods on Resources<T>

MethodReturnsDescription
get(id)TFetch one record (unwraps Data<T>).
list()Vec<T>List records (unwraps the data array).
list_paginated(&query)Paginated<T>List with access to pagination Meta.
create(&body)TCreate a record from a serializable body.
update(id, &body)TUpdate a record.
delete(id)TDelete a record.
resource()ResourceThe resource this handle targets.

Examples

rust
use koban::{ApiClient, Config};
use serde_json::json;

let client = ApiClient::new(Config::from_env()?);

// Typed list and get.
let invoices = client.invoices().list().await?;
let invoice = client.invoices().get("inv_1").await?;

// Create / update / delete round-trip through the Data envelope.
let created = client.clients().create(&json!({ "name": "Acme" })).await?;
let updated = client
    .clients()
    .update(&created.id, &json!({ "name": "Acme Inc" }))
    .await?;
client.clients().delete(&created.id).await?;

// Pagination metadata.
let page = client
    .clients()
    .list_paginated(&[("per_page".to_string(), "20".to_string())])
    .await?;
if let Some(pagination) = page.meta.and_then(|m| m.pagination) {
    println!("total = {:?}", pagination.total);
}

Generic resources & custom types

The generic handle works for any T: DeserializeOwned — a built-in model, your own struct, or serde_json::Value:

rust
use koban::Resource;

// Your own type.
#[derive(serde::Deserialize)]
struct TaxRate {
    name: String,
    rate: f64,
}

let rows = client.resource::<TaxRate>(Resource::TaxRates).list().await?;

// Or untyped.
let raw = client
    .resource::<serde_json::Value>(Resource::TaxRates)
    .list()
    .await?;

Raw JSON escape hatch

When a route is not represented by a Resource variant or does not follow the resource CRUD shape, drop down to the raw ApiClient methods, which return serde_json::Value:

rust
let value = client.get_json("/api/v1/statics", &[]).await?;

post_json, put_json, and delete_json are available too.

Released under the MIT License.