Production-grade African Payment Aggregator built in Rust. One API connecting African payment providers behind a unified interface.
# Pan-Africa Pay
A pan-African mobile money aggregator: collect and pay out across mobile
money networks and stablecoin rails from a single API.
## What It Does
- **Collect payments** - STK-push style prompts to customer phones
- **Pay out** - send money to customer phones or wallets
- **Cross-border settlement** - USDC-backed transfers via Kotani Pay
- **One integration, many rails** - your application talks to one API;
Pan-Africa Pay handles the network plumbing underneath
## Security
- Idempotent by design: every mutating request carries an idempotency key
so retries can never double-charge a customer
- Monetary values handled as integer minor units - no floating-point drift
- Atomic balance updates with overdraft protection at the database level
- Provider callbacks verified and replay-guarded before state changes
- Secrets managed via environment configuration, never committed
- Append-only audit log for every financial event
- Provider credentials isolated per environment (sandbox vs production)
## Speed
- Asynchronous request handling end-to-end
- Redis-backed idempotency lookups for fast retries
- Pooled database connections with health checking
- Provider OAuth tokens cached and reused until expiry
- Continuous integration verifies format, lints, tests, and offline
SQL checks on every change
## Getting Started
```bash
# 1. Start infrastructure (PostgreSQL + Redis + mock provider)
docker compose up -d postgres redis
# 2. Copy environment template
cp .env.example .env
# 3. Apply migrations
cargo sqlx migrate run --source crates/storage/migrations
# 4. Build and test
cargo build --workspace
cargo test --workspace
```
## API Endpoints
| Method | Path | Purpose |
|--------|------|---------|
| `POST` | `/mpesa/stk/push` | Initiate an M-Pesa STK push prompt |
| `GET` | `/mpesa/stk/query/{checkout_request_id}` | Poll STK push status |
| `POST` | `/kotani/customers` | Register a mobile money customer |
| `POST` | `/kotani/deposit` | Initiate fiat -> st …