Docs
Checking Raims account
Integrations

Rust SDK

Install from crates.io and use typed services in your Rust backend with Tokio.

The official Rust SDK provides typed services, pagination, and webhook verification for server integrations with the public API. Keep the API key in your backend instead of distributing it in customer applications.

The SDK reference lists each resource's methods and parameters.

Install the SDK

Use Rust 1.90 or later and a Tokio runtime. The official raims crate is available on crates.io. From your application directory:

Shell
cargo add raims
cargo add tokio --features macros,rt-multi-thread

Cargo fetches from crates.io, selects the compatible stable version, and records resolved versions in Cargo.lock. Keep the lockfile for repeatable installation.

GitHub releases continue to provide source code and the .crate archive. For a Git or local path installation, read the repository instructions.

Configure the client

Obtain a key through API keys and keep it in RAIMS_API_KEY or your secret store. It determines company, environment, and permissions. Sandbox and Production use https://api.raims.com.

Rust
use raims::RaimsClient;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = RaimsClient::new(std::env::var("RAIMS_API_KEY")?)?;
    let balance = client.balances().retrieve().await?;
    println!("HTTP status: {}", balance.last_response.status_code);
    Ok(())
}

Reuse the client; clones share its HTTP pool. Other snippets using await belong inside asynchronous functions returning Result. Use RaimsClient::builder with timeout, accepting std::time::Duration, and max_read_retries to configure timeout and read retries. The timeout covers attempts and waits; retries default to zero.

Create a customer and a charge

customer_tax_id, customer_key, and charge_key are application String values. The first is a valid, authorized CPF or CNPJ; the keys are separate and persisted before sending. due_date_unix is an i64 in UTC Unix seconds, chosen and persisted for this charge.

Rust
use raims::{params::{CreateCustomerParams, CreateChargeParams}, Optional, RequestOptions};

let customer_params = CreateCustomerParams {
    tax_id: Optional::Value(customer_tax_id),
    ..Default::default()
};
let customer_options = RequestOptions {
    idempotency_key: Some(customer_key),
    ..Default::default()
};
let customer = client.customers()
    .create_with_options(&customer_params, &customer_options).await?;

let charge_params = CreateChargeParams {
    customer_id: Optional::Value(customer.data.id),
    amount_cents: Optional::Value(15000),
    due_date: Optional::Value(due_date_unix),
    title: Optional::Value("Order 1234".to_owned()),
    ..Default::default()
};
let charge_options = RequestOptions {
    idempotency_key: Some(charge_key),
    ..Default::default()
};
let charge = client.charges()
    .create_with_options(&charge_params, &charge_options).await?;
let pending = charge.last_response.status_code == 202;

15000 represents BRL 150.00. Optional::Unset leaves a field absent, Optional::Null sends null where permitted, and Optional::Value(...) sets a value. For updates, omission preserves a field and null may clear it under the contract. ApiResponse<T> contains data, last_response, and raw; use raw when response absence and null must be distinguished.

Pagination and pending results

Rust
use raims::{params::ListCustomersParams, Optional};

let filters = ListCustomersParams {
    page_size: Optional::Value(50),
    ..Default::default()
};
let mut pages = client.customers().list_pages(&filters)?;
while let Some(response) = pages.next_page().await? {
    for customer in response.data.list {
        process_customer(customer);
    }
}

process_customer represents your application. Creating a pager sends no HTTP; next_page().await fetches the first page and follows its cursors. Reading a response list does not fetch pages itself. The pager preserves filters and options; a failed fetch does not advance its cursor. Use previous_page().await to move backward. Cursors are opaque; do not combine after and before.

HTTP 202 remains pending. Retrieve the resource or follow its appropriate webhook before confirming payment, refund, or cancellation.

Idempotency and errors

Rust
match client.customers().retrieve(&customer_id).await {
    Ok(response) => process_customer(response.data),
    Err(error) => handle_failure(
        error.kind(), error.status_code(), error.code(), error.request_id()
    ),
}

The handlers belong to your application. Requests return Result<ApiResponse<T>, Error>; kind(), status_code(), code(), and request_id() help decide the next action. Do not treat human messages as codes or log complete bodies or secrets.

The SDK does not generate keys or retry writes automatically. After a lost response, reconcile the operation and preserve the original key and parameters if the endpoint permits another attempt. max_read_retries enables eligible read retries only. Retry-After and attempts share the timeout budget; local cancellation does not reverse work accepted by the API. See Idempotency.

Use Sandbox

Use a Sandbox credential and a charge from that environment:

Rust
let sandbox = RaimsClient::new(std::env::var("RAIMS_SANDBOX_API_KEY")?)?;
let result = sandbox.simulations().charges()
    .confirm_payment(&sandbox_charge_id).await?;

sandbox_charge_id is a String obtained in your Sandbox integration. The SDK does not select an environment by header or convert a Production credential. See Simulations. Email requests and webhooks may still reach external destinations; use authorized ones only.

Receive webhooks

Preserve raw_body as &[u8], signing_headers as a list of (&str, &str) pairs, and webhook_secret as the webhook's secret_key string. Include all occurrences of webhook-id, webhook-timestamp, and webhook-signature; do not collapse them before verification.

Rust
use std::time::SystemTime;
use raims::{construct_webhook_event, DEFAULT_WEBHOOK_TOLERANCE};

let event = construct_webhook_event(
    raw_body,
    &signing_headers,
    &webhook_secret,
    DEFAULT_WEBHOOK_TOLERANCE,
    SystemTime::now(),
)?;
persist_event(event);

persist_event belongs to your application. The signature is checked before JSON decoding; do not reserialize the body. The default tolerance is five minutes in either direction; keep the server clock synchronized. verify_webhook_signature authenticates without decoding the event.

Check type and environment, deduplicate the event id, and persist the work before returning success. webhook-id identifies the delivery and does not replace the event ID. See Receive events.

Update the SDK

Read the release notes and update the SDK within the requirement declared in Cargo.toml:

Shell
cargo update -p raims

This command preserves the existing requirement. To select the current stable version outside that requirement or migrate from Git or a local directory, record the dependency options your application uses. Remove only the raims entry from the manifest that declares it and keep Cargo.lock. For an inherited workspace dependency, change its [workspace.dependencies] entry.

If it is optional, preserve and temporarily remove dependency references in [features], such as dep:raims, to keep the manifest valid. After adding the dependency, restore those declarations together with its optional and feature options. From your application directory:

Shell
cargo add raims

Reapply the dependency options, such as features, and review the entry in Cargo.toml: it must use the registry version requirement selected by Cargo, without git, path, branch, tag, or rev.

Review and keep the updated Cargo.lock, and test the flows used by your integration before updating the application. Installation does not apply future updates automatically.