Home · How it works

Orchestration engine · §12–20

The money is never
“inside Oda”.

Oda asks six questions: who pays, who is paid, which source funds it, which destination receives it, which rail can execute, which route is fastest and available. Then we coordinate — we do not vault.

You→Oda route→M-PESA / bank→Merchant

The four hops you can explain to a cashier.

01 Intent

Write the amount once

Integer minor units internally. Humans see KES 2,450.00. Retail still sends major-unit KES. Never floats.

02 Source

Pick a rail you own

M-PESA, linked bank, card. Confirm with the provider. Oda never collects their PIN, OTP, or CVV.

03 Route

Partner executes

Created → source selected → auth → processing → succeeded, failed, or UNKNOWN. Simulator stays sandbox.

04 Settle

Receipt + recon

Merchant PAID. Webhook fires. Shadow ledger explains. It does not authorize the movement.

UNKNOWN is how we refuse to steal from Kenya.

A network timeout is never automatically a failed payment. It becomes UNKNOWN, then RECONCILING. That is how you do not double-charge when M-PESA is slow.

  • CREATED → PROCESSINGThen SUCCEEDED, FAILED, or UNKNOWN. Reversed, refunded, disputed are later terminals.
  • No silent retryUNKNOWN is not a green light to fire the rail again.
  • No fake live railsProduction does not celebrate a payment the partner did not see.
State machine · §13PROCESSING
SUCCEEDEDFAILEDUNKNOWN → reconciling

Why a shadow ledger exists if we hold no cash.

M-PESA may say success while Oda still says processing and the bank has not settled. The transactions table is not the ledger. Debits equal credits. Entries are immutable. Fees and refunds are new rows, never edits.

Independent truth

Payer clearing receivable +2,450. Merchant settlement payable −2,450. We can argue with a partner.

KE-QR, not a sticker we invented

Static QR is merchant identity. Dynamic QR carries amount, expiry, destination, checksum. No customer secrets in the payload.