Idempotent by construction
Every money-moving request carries an Idempotency-Key. Retries, client timeouts, and duplicate submissions collapse to a single effect — a payment is created, and money moves, exactly once.
Architecture
Every transaction on Moja Switch follows the same sequence — collect, screen, route, post, settle, pay out — behind a single API and a single audit trail. This is how it stays correct when money is on the line.
System view
Partners integrate once. Underneath, Moja orchestrates collection, compliance, ledger, and settlement across corridor rails — one regulated sequence, one audit trail.
Guarantees
These are not features you switch on. They are the invariants the platform is built around — the properties that make money movement explainable and safe to build on.
Every money-moving request carries an Idempotency-Key. Retries, client timeouts, and duplicate submissions collapse to a single effect — a payment is created, and money moves, exactly once.
Balances are never inferred from application state. Every collection, FX, and payout leg is a balanced double-entry posting in an immutable journal. Corrections are reversals, never edits.
Sanctions and AML screening sit on the payment path, not beside it. If a check cannot complete, the payment does not proceed. There is no code path that moves money around compliance.
Every state change is captured as an append-only event with 7+ year retention. Any payment can be reconstructed end to end for a regulator, auditor, or dispute — no gaps, no rewrites.
State changes publish through a transactional outbox — only after the database commits. Webhooks are HMAC-signed and retried with backoff, so you never receive an event that didn't happen, and never miss one that did.
Moja holds the minimum data needed to move a payment. No card PANs, no secrets or sensitive PII in logs. Encrypted in transit and at rest; API keys scoped to specific partners, corridors, and entitlements.
Payment lifecycle
Integrators build against exactly two moments: the create response, and the webhook that follows it.
A single request collects funds, screens the parties, selects rails, posts the double-entry legs, and dispatches the payout. It returns PAYOUT_PENDING once money is committed and in flight — no polling required to know it was accepted.
Receive-side rails settle out of band. When the payout is confirmed or fails, Moja emits a signed payment.completed or payment.failed event. Your handler is the single source of truth for terminal state — verify the signature, act idempotently, done.
PAYOUT_PENDING
Returned by create — funds collected, payout dispatched
COMPLETED
Rail confirmed delivery — delivered by webhook
FAILED
Payout could not be delivered — terminal, audited
CANCELLED
Stopped before collection — no funds moved
At each stage
Each step is a bounded context with a clear contract. Corridor-specific rails and adapters plug into a consistent orchestration core.
Funds collected on the send side via partner PSP or bank integration. Every payment enters the switch with a unique idempotency key and audit record.
Sanctions screening, AML monitoring, and identity verification on every transaction. Immutable audit logging for regulatory examination.
Routing engine selects optimal send and receive rails based on corridor, amount, partner entitlements, and rail availability.
Immutable double-entry journal records collection, FX, and payout legs. Reversal-based corrections with full traceability.
Prefunded liquidity on the receive side. Treasury monitors float, rebalancing, and corridor-level settlement obligations.
Delivery to mobile money, bank account, or institutional payee on the receive side. Status webhooks to the partner on completion.
Failure & recovery
Downstream systems fail, time out, and disagree. The architecture assumes it — money is never double-sent, and every payment lands in a defined, audited state.
Every step — collection, ledger posting, payout dispatch — is idempotent and coordinated as a saga, so retries and downstream failures never double-send funds or silently drop a payment. Automatic unwind via compensating reversals is built into the design and is being switched on corridor by corridor.
The ledger is append-only. Corrections and reversals are posted as new balancing entries — never edits to history — so the audit record stays complete and provable.
Rail dispatch and webhook delivery retry with exponential backoff against a durable delivery log. Because every call is idempotent, a retry can never double-send.
Automated reconciliation matches the ledger against rail and settlement statements every day. Exceptions are surfaced for investigation rather than silently absorbed.
Security & data
Security posture an integrating bank's diligence team can check line by line.
Sandbox access, OpenAPI spec, and webhook documentation for technical evaluation.