| Crates.io | whatsapp-business-rs |
| lib.rs | whatsapp-business-rs |
| version | 0.5.0 |
| created_at | 2025-07-19 16:23:12.350323+00 |
| updated_at | 2025-11-27 12:21:42.261987+00 |
| description | Rust SDK for the WhatsApp Business API โ bulk messaging, batching, and multi-tenant support. |
| homepage | https://github.com/veecore/whatsapp-business-rs |
| repository | https://github.com/veecore/whatsapp-business-rs |
| max_upload_size | |
| id | 1760363 |
| size | 773,882 |
whatsapp-business-rs is a type-safe, async-ready toolkit for the complete WhatsApp Business Platform โ built with love in Rust ๐ฆ.
Send messages, handle webhooks, manage catalogs, or batch thousands of API calls in one shot. This crate brings it all together in a blazing-fast, developer-first package.
Check out our Bulls & Cows Game Bot example, built entirely with this crate. It showcases an interactive, stateful bot using a state machine pattern.

batch, server, onboarding.# Add the crate and enable the server + message reply extensions
cargo add whatsapp-business-rs --features "server incoming_message_ext"
(Disable features you donโt need for smaller builds.)
Before diving in, youโll need a few things from the Meta for Developers dashboard:
use whatsapp_business_rs::Client;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = Client::new("YOUR_ACCESS_TOKEN").await?;
let business_phone_id = "YOUR_BUSINESS_NUMBER_ID";
let recipient_number = "+16012345678";
client.message(business_phone_id)
.send(recipient_number, "Hello from Rust! ๐ฆ")
.await?;
println!("Text message sent!");
Ok(())
}
This example uses the incoming_message_ext feature for easy replies.
use whatsapp_business_rs::{
client::Client,
server::{Server, WebhookHandler, EventContext, IncomingMessage},
app::SubscriptionField,
};
use std::error::Error;
// Define a simple handler struct
#[derive(Debug, Clone)]
struct EchoHandler;
impl WebhookHandler for EchoHandler {
async fn handle_message(&self, _ctx: EventContext, msg: IncomingMessage) {
println!("Received message from: {}", msg.sender.wa_id);
// Echo the received message back to the sender
msg.reply(msg.clone()).await;
}
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
// Client is needed for registering the webhook
let client = Client::new("YOUR_APP_OR_SYSTEM_USER_TOKEN").await?;
// Build and start the webhook server
Server::builder()
.endpoint("127.0.0.1:8080".parse().unwrap()) // Local address
.verify_payload("YOUR_APP_SECRET") // For payload verification
.build()
.serve(EchoHandler, client.clone()) // Pass client for replying
.register_webhook( // One-time webhook registration
client
.app("YOUR_APP_ID")
.configure_webhook(("YOUR_VERIFY_TOKEN", "https://your-public-url.com"))
.events([SubscriptionField::Messages].into())
.with_auth(client.auth().clone()), // Use client's auth
)
.await?;
Ok(())
}
Batching reduces round-trips and lets you chain dependent requests.
use whatsapp_business_rs::Client;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = Client::new("YOUR_ACCESS_TOKEN").await?;
let sender = client.message("YOUR_BUSINESS_PHONE_ID");
client
.batch()
.include(sender.send("+1234567890", "Hi A!"))
.include(sender.send("+1234667809", "Hi B!"))
.include(sender.send("+1224537891", "Hi C!"))
.execute()
.await?;
Ok(())
}
use whatsapp_business_rs::message::Draft;
use whatsapp_business_rs::Client;
async fn send_cta_example() -> Result<(), Box<dyn std::error::Error>> {
let client = Client::new("YOUR_ACCESS_TOKEN").await?;
let draft = Draft::text("Would you like to continue?")
.add_reply_button("yes_callback", "Yes")
.add_reply_button("no_callback", "No")
.footer("Please select an option.");
client.message("YOUR_BUSINESS_PHONE_ID").send("+16012345678", draft).await?;
Ok(())
}
use whatsapp_business_rs::message::Draft;
use whatsapp_business_rs::Client;
async fn send_option_list_example() -> Result<(), Box<dyn std::error::Error>> {
let client = Client::new("YOUR_ACCESS_TOKEN").await?;
let draft = Draft::new()
.body("Please make a selection.")
.header("Main Menu ๐")
.list("View Options") // The button text that opens the list
.add_list_option("buy_pepperoni", "Pepperoni", "Classic pepperoni pizza.")
.add_list_option("buy_margherita", "Margherita", "Simple and delicious.");
client.message("YOUR_BUSINESS_PHONE_ID").send("+16012345678", draft).await?;
Ok(())
}
use whatsapp_business_rs::{Client, Media};
async fn send_video_example() -> Result<(), Box<dyn std::error::Error>> {
let client = Client::new("YOUR_ACCESS_TOKEN").await?;
let video = Media::from_path("path/to/your/video.mp4")
.await?
.caption("Check out this cool video!");
client.message("YOUR_BUSINESS_PHONE_ID").send("+16012345678", video).await?;
Ok(())
}
use whatsapp_business_rs::{Client, Location};
async fn send_location_example() -> Result<(), Box<dyn std::error::Error>> {
let client = Client::new("YOUR_ACCESS_TOKEN").await?;
let location = Location::new(37.4421, -122.1615)
.name("Philz Coffee")
.address("101 Forest Ave, Palo Alto, CA 94301");
client.message("YOUR_BUSINESS_PHONE_ID").send("+16012345678", location).await?;
Ok(())
}
use whatsapp_business_rs::{client::Client, Waba, waba::CatalogMetadataField};
use futures::TryStreamExt as _;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = Client::new("YOUR_ACCESS_TOKEN").await?;
let mut catalogs = client
.waba("YOUR_WABA_ID")
.list_catalogs()
.into_stream();
println!("Listing catalogs:");
while let Some(catalog) = catalogs.try_next().await? {
println!("{:?}", catalog);
}
Ok(())
}
use whatsapp_business_rs::catalog::{ProductData, Price};
use whatsapp_business_rs::Client;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = Client::new("YOUR_ACCESS_TOKEN").await?;
let product = ProductData::default()
.name("Rust Programming Book")
.description("Learn Rust with this comprehensive guide")
.price(Price(39.99, "USD".into()))
.build("rust-book-001"); // Your retailer ID
let result = client.catalog("YOUR_CATALOG_ID")
.create_product(product)
.await?;
println!("Product created with ID: {}", result.product.product_id());
Ok(())
}
whatsapp-business-rs?reqwest, axum, and tokio for high performance.Contributions are very welcome! Open an issue, suggest features, or send a PR.
Tired of bloated SDKs, missing docs, or inconsistent behavior? With whatsapp-business-rs, you own the stack โ fast, clean, and async-native. Perfect for bots, CRMs, and next-gen commerce apps.