Skip to content

About

The official Rust library for the Dodo Payments API

Topics

Resources

Contributing

Security policy

Stars

5 stars

Watchers

0 watching

Forks

Repository files navigation

Dodo Payments Rust API library

The Dodo Payments Rust library provides convenient access to the Dodo Payments REST API from applications written in Rust.

The REST API documentation can be found on docs.dodopayments.com. The full API of this library can be found in api.md.

Installation

cargo add dodopayments

Or add it to your Cargo.toml manually:

[dependencies]
dodopayments = "1.126.0"
tokio = { version = "1", features = ["full"] }
serde_json = "1"

Requirements

Rust 1.75 or later.

Usage

The client reads your API key from the DODO_PAYMENTS_API_KEY environment variable by default:

use dodopayments::Client;

#[tokio::main]
async fn main() -> dodopayments::Result<()> {
    let client = Client::from_env()?;
    let result = client
        .checkout_sessions()
        .create()
        .body(dodopayments::models::CheckoutSessionsCreateParams {
                product_cart: Some(vec![dodopayments::models::ProductItemReq {
                    product_id: "product_id".to_string(),
                    quantity: 0,
                    addons: None,
                    amount: None,
                    credit_entitlements: None,
                }]),
                ..Default::default()
            })
        .await?;
    println!("{result:?}");
    Ok(())
}

You can also configure the client explicitly. Client::new returns a Result, so unwrap it with ? inside a function that returns dodopayments::Result:

use dodopayments::{Client, ClientConfig};

#[tokio::main]
async fn main() -> dodopayments::Result<()> {
    let client = Client::new(ClientConfig::new("https://live.dodopayments.com").with_api_key("My API Key"))?;
    println!("{}", client.base_url());
    Ok(())
}

Pagination

List endpoints return a typed page whose items field holds the current page of results. Fetch the next page with get_next_page, or stream every item across all pages with into_stream:

use futures::StreamExt;

let mut items = Box::pin(client
    .payments()
    .list()
    .query(serde_json::json!({}))
    .await?.into_stream());
while let Some(item) = items.next().await {
    let item = item?;
    println!("{item:?}");
}

Or advance one page at a time:

let mut page = client
    .payments()
    .list()
    .query(serde_json::json!({}))
    .await?;
loop {
    for item in &page.items {
        println!("{item:?}");
    }
    match page.get_next_page().await? {
        Some(next) => page = next,
        None => break,
    }
}

Handling errors

Every method returns a dodopayments::Result<T>. Failures are represented by the dodopayments::Error enum:

let result = client
    .checkout_sessions()
    .create()
    .body(dodopayments::models::CheckoutSessionsCreateParams {
            product_cart: Some(vec![dodopayments::models::ProductItemReq {
                product_id: "product_id".to_string(),
                quantity: 0,
                addons: None,
                amount: None,
                credit_entitlements: None,
            }]),
            ..Default::default()
        })
    .await;

match result {
    Ok(value) => println!("{value:?}"),
    Err(dodopayments::Error::Api { status, message }) => {
        eprintln!("API returned {status}: {message}");
    }
    Err(err) => eprintln!("request failed: {err}"),
}

Timeouts

The default request timeout is 30 seconds. Override it per client:

use std::time::Duration;
use dodopayments::{Client, ClientConfig};

let client = Client::new(
    ClientConfig::new("https://live.dodopayments.com")
        .with_api_key("My API Key")
        .with_timeout(Duration::from_secs(60)),
)?;

Environments

Name Base URL
live_mode https://live.dodopayments.com
test_mode https://test.dodopayments.com

The default base URL is https://live.dodopayments.com. Select another environment with the Environment enum instead of hard-coding URLs:

use dodopayments::{Client, ClientConfig, Environment};

let client = Client::new(
    ClientConfig::from_environment(Environment::TestMode).with_api_key("My API Key"),
)?;

To keep reading the API key from DODO_PAYMENTS_API_KEY via from_env() while targeting a non-default environment, override it on the config:

use dodopayments::{Client, ClientConfig, Environment};

let client = Client::new(ClientConfig::from_env()?.with_environment(Environment::TestMode))?;

Alternatively, Client::from_env() uses the default base URL unless you set the DODO_PAYMENTS_BASE_URL environment variable, e.g. DODO_PAYMENTS_BASE_URL=https://test.dodopayments.com to target test_mode.

Workload identity

The client can exchange an OIDC token from the platform that runs your code for a short-lived access token, in place of an API key:

use dodopayments::workload_identity;
use dodopayments::{Client, ClientConfig, WorkloadIdentity};

let client = Client::new(
    ClientConfig::new("https://live.dodopayments.com").with_workload_identity(
        WorkloadIdentity::new(workload_identity::github_actions(None))
            .with_identity_provider_id("wip_..."),
    ),
)?;
  • Subject token sources in workload_identity: github_actions, gitlab, terraform_cloud, gcp, vercel, vercel_with_audience, kubernetes, file, aws (your function), static_token, and auto. SubjectTokenSource::from_fn accepts any async function.
  • vercel reads VERCEL_OIDC_TOKEN_FILE or VERCEL_OIDC_TOKEN. It exchanges that token at Vercel for a token with the Dodo Payments audience. The Dodo Payments API accepts only that audience.
  • Without with_identity_provider_id, the client reads DODO_PAYMENTS_IDENTITY_PROVIDER_ID. If DODO_PAYMENTS_API_KEY is not set and DODO_PAYMENTS_IDENTITY_PROVIDER_ID is set, Client::from_env() uses workload identity with auto().
  • The client gets a new access token when 5 minutes or less remain. Concurrent requests share one exchange. After a 401, the client gets a new token and retries the request once.
  • client.revoke_workload_identity().await? revokes the cached access token and clears the cache.
  • Do not set with_api_key and with_workload_identity together. Client::new returns Error::Config.
  • client.request(...) does not add the access token. Send the request with client.send(request).await?.

Undocumented endpoints

To call an endpoint not yet exposed as a typed method, use the low-level request builder, which applies authentication and the base URL:

let response = client
    .request(reqwest::Method::GET, "/some/path")
    .send()
    .await?;

Semantic versioning

This package follows SemVer conventions. Breaking changes are released in major versions; minor and patch versions remain backwards compatible.

We take backwards compatibility seriously and work hard to ensure that breaking changes are clearly communicated in the changelog.

Contributing

See the contributing documentation.

About

The official Rust library for the Dodo Payments API

Topics

Resources

Contributing

Security policy

Stars

5 stars

Watchers

0 watching

Forks

Releases

Used by

Contributors

Languages