27 questions,
answered straight.
These are the ones that come up in the first ten minutes of a first call, which is a different list from the ones a marketing department would choose. Several of the answers are "no" or "not yet".
These are the ones that come up in the first ten minutes of a first call, which is a different list from the ones a marketing department would choose. Several of the answers are "no" or "not yet".
01The basics
Two things, through one API and one dashboard. It takes money in from M-Pesa (an STK push to a customer's phone, your paybill, your till, a payment link, a hosted checkout page) and it sends money back out to phone numbers. Underneath both sits a double-entry ledger, so every shilling that moves leaves two postings, and your balance is a number we can show you the arithmetic for rather than a number we remember.
A gateway with a real ledger behind it. We are not a bank and we do not take your money as a deposit. Funds move through settlement accounts, and your balance is the ledger's view of what is yours at this moment. The short version for your lawyer: we are an aggregator, Safaricom moves the money, and keeping the books straight is our job.
Kenyan shillings, and only Kenyan shillings. Amounts are stored as integer cents from the API through to the ledger, because a floating-point number in a money column is a bug with a long fuse. Multi-currency is not on the roadmap we would show you yet.
No, but you can use one. Start on the platform shortcode and you can take a payment the same day. Bring your own shortcode later and your collections are pushed from yours instead, with the credentials encrypted at rest and never displayed back to you in full once saved.
Yes. An STK push arrives as a prompt on any phone that can do M-Pesa, a feature phone included, and paybill and till payments work the way your customers already know them. A payment link gives you a checkout page for the people who would rather tap a link than type a business number from memory.
No. NOSTREL is pre-launch. The API, both consoles, the ledger, reconciliation, settlement and webhook delivery are built and under test, and every figure in a screenshot on this site is seeded development data from a local environment. We would rather you read that on the first page than work it out later from a changelog.
02Money and timing
A collection reaches a confirmed state once Safaricom confirms it, usually seconds after your customer enters their PIN. We do not credit the ledger on the callback alone: we ask the provider to confirm the transaction independently first. That costs a moment and removes an entire category of fraud, which we think is a reasonable trade. Payouts leave as soon as they are approved, subject to Safaricom's own processing on the other side.
It gets chased, not forgotten. Collections still unconfirmed past a deadline are picked up by a scheduled job that asks the provider for the real outcome. Payouts with no result callback are resolved by a transaction-status query against the identifier we held from the original request, which is the one thing we still have when a callback is lost in transit. Nothing sits in limbo because a POST to us failed.
Per rail, as a percentage plus a fixed component, with a floor and an optional ceiling, and dated so that a change applies from a day forward and never retroactively. Each merchant has their own schedule. The shape of it is set out on the pricing page; the numbers come out of a short conversation about your volume and your mix, because a card-style flat rate would be wrong for almost everyone.
Every fee is a ledger posting attached to the transaction that caused it, so the answer to "where did that go" is a row you can point at rather than an estimate. Statements export for any date range and they reconcile with the transaction list, because both are drawn from the same postings rather than computed twice.
We reconcile. A daily job matches the ledger against the provider's record of the same window and opens an exception for anything that does not line up, with a state of its own so that a person closes it instead of it quietly becoming a line in a log file. Unexplained money is the one thing in this business you cannot let age.
03Building on it
About ten minutes, most of which is you finding a phone. Create a key in the dashboard, POST to /v1/api/collections with an amount and a phone number, answer the prompt, read the webhook. The quickstart is written for someone impatient and assumes you would rather copy a curl than read an introduction.
REST over HTTPS, JSON in and JSON out, a key in a header, routes under /v1. Three endpoints cover the money: create a collection, create a payout, read your balance. Everything the dashboard does sits on the same API, so there is nothing you can see in a browser that you cannot automate.
An Idempotency-Key header is required on every call that moves money, not merely honoured if you send one. Replay the same key with the same body and you get the first result back rather than a second payment. Replay it with a different body and you get an error, because that is a bug in your code and guessing which of the two you meant would be worse than telling you.
Every delivery carries a NOSTREL-Signature header holding a timestamp and an HMAC over the exact body, in the shape most webhook libraries already recognise. Verify the HMAC with your endpoint secret, reject a timestamp outside your tolerance, and compare in constant time. The webhooks page works through it, including the mistake almost everyone makes once, which is verifying a re-serialised object instead of the bytes that actually arrived.
We retry on a backoff, and nothing is lost while we do. Deliveries are written in the same database transaction as the thing that happened, so there is no window in which the payment is recorded and the notification is not. Deliveries that exhaust their retries land somewhere you can see them and replay them once you are back on your feet.
Yes, and it runs against Safaricom's own sandbox rather than a mock we wrote, which means the failure modes are the real ones instead of the ones we imagined. You can trigger a timeout, a cancelled prompt, an insufficient-balance result and a deliberately lost callback. Testing those four is the step nearly everyone skips, and then meets for the first time on a Friday afternoon.
04When things go wrong
Your request is either accepted or refused, never silently half-done. A collection we cannot start comes back as an error you can retry with the same idempotency key. One already in flight is resolved by the sweeper as soon as the provider can answer again. The reliability page sets out what we watch, what we do while it is happening, and what we will tell you before you have to ask.
Not one person acting alone. Payouts use maker and checker: whoever creates one cannot be the one who releases it, the funds are reserved against your balance while it waits, and the reservation is released if it is rejected. A separate transaction PIN sits in front of the sensitive actions on top of that, because a stolen session should not be enough to move money.
The audit log is hash-chained: each entry commits to the one before it, a scheduled job walks the chain, and staff can run the verifier on demand. Editing an old entry breaks every hash after it, which is precisely the point. Tamper-evident is a weaker claim than tamper-proof, and it is the honest one.
A stable code, a message written for a human, and nothing else: no stack traces, no internal identifiers, no hint about which provider sits behind which rail. An error response is an information-disclosure surface as much as it is a debugging aid. The errors page lists every code with what it means, whether a retry helps, and what to change when it does not.
05Compliance and access
Your business identity and the documents behind it, the people who ultimately control the company, and a destination for settlement. Submission is a wizard that saves as you go, review is done by a person, and the outcome is a set of capabilities that visibly switch on rather than a vague change of status you have to interpret.
Capabilities are gated on verification and on tier, and the console shows you what you can do today alongside what unlocks next, so you never build against a feature that will refuse you in production. You can draft a payment link before you are approved, for instance; you simply cannot collect on it until you are.
Under the Data Protection Act, 2019, with the practical consequences that implies: documents live in object storage reached through short-lived signed access rather than a public bucket, identity data is held because the law requires us to hold it, and we do not collect what we have no use for. The compliance page has the detail, including screening against sanctions and PEP lists at submission.
Access is role-based and every tenant boundary is enforced on the server rather than in a browser. Platform staff roles are entirely separate from merchant roles, sensitive actions are written to the audit chain, and the console's own cache is scoped per tenant so that switching accounts cannot leave one merchant's rows on screen in front of another.
06Us
A small team in Nairobi who have spent more time reading Daraja documentation than is strictly healthy, and who got tired of watching good businesses reconcile M-Pesa by hand in a spreadsheet at the end of every month. The about page is the honest version, including the parts we have not built yet.
Because most of it is checkable. The test counts on the landing page come from a real run and not a marketing round-up, the screenshots are the actual consoles rather than a design file, and the security page lists the findings we went looking for and what each fix was. Where something is not finished, it is written in the future tense. That is the whole trick.