Quick Start
Get up and running as quickly as possible.
Welcome to the async-stripe documentation. This library provides strongly-typed, safe, and performant Rust bindings for the Stripe API. It is designed to be modular, allowing you to pull in only the specific Stripe resources you need for your application.
API Documentation
Complete API reference and type documentation on docs.rs
Examples
Browse real-world examples for common Stripe operations
Stripe API Reference
Official Stripe API documentation and reference
Stripe Docs
Official guides, tutorials, and integration docs from Stripe
Using an LLM? See llms-full.txt.
API Version
The current API version for async-stripe v1.0.0-alpha.8 is:
pub const VERSION: crate::ApiVersion = crate::ApiVersion::V2025_11_17_clover;This means all API requests will use this version regardless of your Stripe account's default API version. This ensures consistent behavior and prevents breaking changes from affecting your application unexpectedly.
Compatibility
async-stripe is pinned to a specific Stripe API version. Each week, we sync against the official APIs and bump our types to match. It is critically important that you understand which version you're using, as mismatches between the library version and your expectations can lead to unexpected behavior, missing features, or parsing errors. As a result, you should when possible be regularly updating the both this library, and your Stripe account's api, to the latest available version.
We do not currently have the resources to backport fixes to older APIs.
Any webhooks received that to not match this version will publish a warning via tracing.
Quick Start
Here's a quick example of how to create a new Stripe Customer.
1. Add dependencies to your Cargo.toml
You'll need the main async-stripe crate for the client and a resource crate for the APIs you want to use (e.g., stripe-core for customers).
Here's a quick example of how to create a new Stripe Customer.
**1. Add dependencies to your `Cargo.toml`:**2. Create a Customer
The new API uses a builder pattern that flows naturally from request creation to sending.
let customer = CreateCustomer::new()
.name("Alexander Lyon")
.email("test@async-stripe.com")
.description("A fake customer that is used to illustrate the examples in async-stripe.")
.metadata([(String::from("async-stripe"), String::from("true"))])
.send(client)
.await?;Working with Expandable Fields
Many Stripe API responses contain related objects that are returned as IDs by default. You can use the expand parameter to request the full object instead. The library represents these fields using the Expandable<T> type.
Always Get the ID
Regardless of whether a field is expanded or not, you can always safely extract the ID:
use stripe::{Client, Charge};
let client = Client::new(secret_key);
let charge = Charge::retrieve(&client, &charge_id, &[]).await?;
// Works whether customer is an ID or expanded object
let customer_id = charge.customer.id();
println!("Customer ID: {}", customer_id);Accessing the Expanded Object
When you expand a field, you can access the full object:
use stripe::{Client, Charge};
let client = Client::new(secret_key);
// Request the customer object to be expanded
let charge = Charge::retrieve(&client, &charge_id, &["customer"]).await?;
// Check if we got the full object
if let Some(customer) = charge.customer.as_object() {
println!("Customer email: {:?}", customer.email);
} else {
println!("Customer was not expanded");
}Available Methods
The Expandable<T> enum provides several convenience methods:
.id()- Get the ID (always works, whether expanded or not).is_object()- Check if the field contains the full object.as_object()- Get a reference to the object if available.into_object()- Take ownership of the object if available.into_id()- Take ownership of the ID
For more details on object expansion in the Stripe API, see the official documentation.
Known Limitations
Due to the current architecture of the OpenAPI generator, the following Stripe features are not yet supported by async-stripe:
File Uploads
Endpoints requiring multipart/form-data (e.g., uploading Identity verification documents or Dispute evidence) are not currently generated.
Workaround: Use a raw HTTP client like reqwest to upload files directly:
use reqwest::multipart;
let form = multipart::Form::new()
.text("purpose", "dispute_evidence")
.part("file", multipart::Part::bytes(file_data)
.file_name("evidence.pdf")
.mime_str("application/pdf")?);
let response = reqwest::Client::new()
.post("https://files.stripe.com/v1/files")
.bearer_auth(&secret_key)
.multipart(form)
.send()
.await?;Binary Downloads
Endpoints returning binary data (e.g., PDF invoices via /v1/invoices/:id/pdf) are not currently generated.
Workaround: Use a raw HTTP client to download binary content:
let response = reqwest::Client::new()
.get(format!("https://api.stripe.com/v1/invoices/{}/pdf", invoice_id))
.bearer_auth(&secret_key)
.send()
.await?;
let pdf_bytes = response.bytes().await?;
std::fs::write("invoice.pdf", pdf_bytes)?;We're tracking these limitations and plan to add support in future releases. You can use async-stripe for the vast majority of Stripe operations alongside a raw HTTP client for these specific cases.