Skip to content

Rust SDK

Add the arbol-sdk crate and call the Arbol API from async Rust.

Updated

arbol-sdk is the Arbol API over HTTPS for Rust services. Its types, operations and client methods are generated from the API’s public OpenAPI document; it uses reqwest with rustls, serde and thiserror, runs on any Tokio runtime and needs Rust 1.85 or newer. The source is on GitHub under the Apache 2.0 license.

Install

The crate isn’t on crates.io yet. Add it as a git dependency, pinned to a commit for reproducible builds:

[dependencies]
arbol-sdk = { git = "https://github.com/getarbol/project-arbol-sdk-rust", rev = "<commit>" }
tokio = { version = "1", features = ["macros", "rt-multi-thread"] }

The library is arbol_sdk. Tokio is listed only for the example’s #[tokio::main]; the crate runs on any Tokio runtime.

Create a client and call an operation

use arbol_sdk::{Client, Credential, types};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let arbol = Client::new(Credential::ApiKey(std::env::var("ARBOL_API_KEY")?))?;
    let input = types::AgendaAppointmentsListInput {
        from: Some("2026-10-12T00:00:00Z".into()),
        to: Some("2026-10-19T00:00:00Z".into()),
        ..Default::default()
    };
    let page = arbol.agenda().appointments().list(&input).await?;
    println!("{page:?}");
    Ok(())
}

Every operation is a method named after its operation id: account.apiKeys.create is arbol.account().api_keys().create(&input), with types::AccountApiKeysCreateInput in and types::AccountApiKeysCreateOutput out.

  • One credential. Credential::ApiKey takes an API key (arb_live_…) for a machine; Credential::AccessToken takes a person’s access token for the audience https://api.getarbol.com. See Authentication.
  • HTTPS only. Client::new calls https://api.getarbol.com, and no redirect is followed.
  • The data, unwrapped. A method returns the data of the success envelope. A response larger than its operation’s limit is refused.

Types

Types follow the schema:

  • An optional field is Option<T> and is left out of the request when None.
  • An optional field that may also be null is Option<Option<T>>: Some(None) sends null.
  • A union is an untagged enum whose members’ literal fields tell them apart.
  • What Rust can’t express exactly is a serde_json::Value.

Errors

Every failure is an arbol_sdk::Error:

Field Meaning
code The API’s stable error code, such as FORBIDDEN, or the client’s own: NETWORK_ERROR, REDIRECT_REFUSED, INVALID_RESPONSE.
message, status, retryable, data The error’s message, the HTTP status, the API’s retry hint and the error’s declared data.
request_id The request id to quote when you report a problem.
outcome Refused: nothing happened. NotSent: stopped before the request left. Unknown: a write or delete that may have happened.

Nothing is retried. A read that fails is Refused or NotSent; only a write or a delete can end Unknown, and then you read the current state before you repeat it:

use arbol_sdk::{Error, Outcome};

fn report(error: &Error) {
    match error.outcome {
        Outcome::Unknown => eprintln!(
            "{} may have been applied; read its state before repeating (request {:?})",
            error.code, error.request_id
        ),
        Outcome::Refused | Outcome::NotSent => eprintln!("{}: {}", error.code, error.message),
    }
}

See Retries.

Versions

The crate is regenerated by hand, so it can trail the API. arbol_sdk::RELEASE names the API release it was generated from, such as 1.20261019.4056, and Cargo.toml records it under [package.metadata.arbol.openapi]. Compare it with the info.version of https://api.getarbol.com/openapi.json: operations added since then aren’t in the crate until it is regenerated. The API is at release 1.20261104.21009 (see Versions and updates).

Type to search…

↑↓ navigate↵ selectEsc close