daraja-sdk
A memory-safe Rust SDK for Safaricom Daraja (M-Pesa API 3.0), focused on correctness and type safety.
Experimental: This project is an early experiment. The API is unstable, coverage is limited, and it is not ready for production use.
OAuth authentication
use mpesa;
async
M-Pesa Express (STK Push)
Obtain an access token first, then use MpesaExpress to send a Lipa na M-Pesa Online prompt:
use ;
async
Planned features
- OAuth authentication — generate access tokens for Daraja API requests
- M-Pesa Express (STK Push) — initiate Lipa na M-Pesa Online payments
- STK Push query — query the status of an STK Push request
- B2C — send money from a business shortcode to a customer
- C2B — register validation and confirmation URLs for paybill/till payments
- Transaction status — query the result of a payment request
- Account balance — check balances for a shortcode
- Reversals — reverse a completed transaction
- Production environment — configurable sandbox vs production base URLs
Developing locally
Requires a Rust toolchain that supports edition 2024, plus sandbox credentials from the Daraja Developer Portal.
# add your sandbox credentials to config.toml (see below)
config.toml
Integration tests call the live Daraja sandbox. Copy config.toml.example and fill in:
| Field | Description |
|---|---|
consumer_key |
Daraja app consumer key |
consumer_secret |
Daraja app consumer secret |
passkey |
Lipa Na M-Pesa Online passkey (sandbox or production) |
callback_url |
HTTPS URL where Daraja posts STK Push results |
phone_number |
Safaricom number to receive the STK prompt (2547XXXXXXXX) |
config.toml is gitignored so credentials are not committed.
To reduce repeated OAuth calls during local development, integration tests cache the last successful access token in last_token.txt at the project root. On subsequent runs, tests reuse the cached token if it has not expired instead of requesting a new one from the API. This file is gitignored and contains live credentials — do not commit it. Delete last_token.txt if you want to force a fresh token fetch or if the cache format changes.