Developer documentation
Build against Vuka Bridge without touching real money.
Vuka Bridge ships with simulators for every party in a credit checkout: a merchant storefront, three financiers and both settlement rails (M-Pesa and PESI). They run on the same deployment as the real bridge code, so you can take a shopper from cart to a paid merchant — webhooks, OTPs, payouts and all — without a Daraja or PESI account, a real shortcode or a credit provider agreement.
Merchant
Merchant simulator
"Soko Demo Store" at /sample/mer — categories, product pages, cart, credit checkout (redirect or embedded), webhook receiver and settlement ledger.
Financiers
Financier simulators
Shop na Pesi (cart credit, /sample/fin), Ngao Credit (asset finance, /sample/ngao) and Faraja Credit (lender-settled, /sample/faraja) — each serving the financier API the bridge calls.
Settlement rail
M-Pesa simulator
Daraja-shaped B2B payment, Account Balance, C2B confirmation and account validation at /v1/_sim/mpesa, with a paybill console at /sample/mpesa.
Settlement rail
PESI simulator
PESI B2B paybill and till disbursement, account-name lookup and transfer status at /v1/_sim/pesi — signed callbacks and failure injection.
How the simulators fit together
Each simulator stands alone — run just the merchant sim for a shopper journey, or just a rail sim for a payout test. End to end, a checkout touches all three layers:
┌─────────────────────────┐ ┌─────────────────────────────────┐
│ /sample/mer │ │ Financier simulators │
│ Soko Demo Store │ │ /sample/fin Shop na Pesi │
└────────────┬────────────┘ │ /sample/ngao Ngao Credit │
│ orders API │ /sample/faraja Faraja Credit │
│ (/v1/checkout) └────────────────┬────────────────┘
▼ │ financier API
┌────────────┴─────────────────────────────────────┴────────────────┐
│ Vuka Bridge (real code) │
│ hosted checkout · /admin · /v1/* │
└──────────────┬───────────────────────────────────┬────────────────┘
│ B2B payout (M-Pesa or PESI) │
▼ ▼
┌─────────────────────────┐ ┌─────────────────────────────────┐
│ /v1/_sim/mpesa/* │ │ /v1/_sim/pesi/* │
│ M-Pesa (Daraja) sim │ │ PESI sim │
└─────────────────────────┘ └─────────────────────────────────┘ The merchant creates an order through the orders API and sends the shopper to the hosted
checkout. The bridge calls the shopper's financier to link the account, take the OTP and book
the loan, debits that financier's virtual account, and pays the merchant over M-Pesa or PESI.
The rail's callback marks the payout delivered and the merchant receives order.paid.
A lender-settled financier (Faraja Credit) pays the merchant itself, so no rail is involved.
Quick start
- Copy
.env.exampleto.envand fill in the database connection — every simulator keeps its state in the database. - Run migrations:
npm run migrate. They create the simulator tables, their demo data and the float paybill. Wiring a simulator financier into the bridge is covered in the financier guide. - On a fresh database, create the first platform admin:
npm run bootstrap:admin. - Start the dev server:
npm run dev. - Open one of the simulator pages above and follow its Quick start. For a full checkout you need the merchant simulator, a financier simulator and one rail.
Conventions used across the simulators
| Convention | Details |
|---|---|
URL-parameter sessions (?sid=<uuid>) | The simulator storefronts and lender portals don't use the bridge's login. Their sessions are minted server-side and carried on every URL, so there is no cookie surface and a session is easy to share between tabs or tests. |
| scrypt password hashing | Built-in Node crypto, stored as scrypt$<salt-hex>$<hash-hex>. |
| Signed calls | Each wire has its own signature:
|
| Fixed test OTPs | 222222 — the financier OTP on the lender simulators (linking, booking, express checkout).333333 — the delivery-confirmation OTP for pay-on-delivery orders.111111 — the bridge's own sign-in OTP when SMS is simulated.Lender-sim OTP challenges are listed in each lender console under Links & OTP. |
| Database-backed state | Customers, orders, credit lines, loans, paybill balances and request ledgers live in the database and survive restarts. Timers for pending rail callbacks do not: the M-Pesa sim loses them, while the PESI sim re-fires stalled callbacks. |
| Request logs | Each simulator records what it received: the Soko webhook log, the lender consoles' Wire Inspector, the M-Pesa console's Requests tab and the PESI request ledger. On the bridge side, /fin/logs shows calls to a financier and /admin/transactions traces an order end to end. |
Where to ask questions
Each guide ends with a Troubleshooting section covering the failure modes we
have actually hit. If your issue isn't covered there, the specifications in documentation/requirements/ are the reference for behaviour.