KES
The Kenyan rails, rail by rail and direction by direction: which reach your KES balance, which a transfer can pay out on, and what each tells you about who paid.
Kenyan shillings reach you, or leave you, on the rails below. This page takes them one at a time and in one direction at a time, because a rail that is open in one direction is not necessarily open in the other.
Everything here moves through one place: the KES balance your partner
account holds with us. Payments in top it up; transfers out, and USDT buy
orders, are paid from it. GET /v1/balances reads
it.
The status vocabulary is defined on the Rails index.
Inbound: reaching your KES balance
GET /v1/funding is the source of truth for where and how. Every payment is
credited to your balance in general — it is not tied to any order, and there is
no reference of yours for the payer to quote.
| Rail | Status | How the payer sends it | What you learn about the payer |
|---|---|---|---|
| M-PESA | Available | Pay Bill, with your account number as the Account Number | Their M-PESA receipt code, amount, time |
| PesaLink | Available | A transfer to the account number we publish | Their bank's reference, amount, time |
| RTGS | Available | A transfer to the account number we publish | Their bank's reference, amount, time |
| EFT | Available | A transfer to the account number we publish | Their bank's reference, amount, time |
| SWIFT | Not available today | — | — |
| On-us | Not available today | — | — |
On M-PESA you can also raise the payment yourself: POST /v1/funding/mpesa-push
puts a prompt on the payer's phone, and the money lands in the same balance.
Receive money in Kenya is the guide, and
References and attribution covers matching a
credit to one of your own users.
Outbound: where shillings can go
There are two operations here, and they reach different places.
A transfer pays shillings from your KES balance to a destination you name per payment — a mobile number, or a bank account and bank code. Every transfer waits for a one-time code sent to your confirmation contact (or to your webhook, on an account switched to webhook delivery) before anything moves, unless OnLink has enabled confirmation waiving for your account and, in production, you call with an API key that has an IP allowlist. See Send money from your KES account and, for many recipients at once, Send a batch of transfers.
| Rail | rail value | Status | Destination it takes |
|---|---|---|---|
| M-PESA | mpesa | Available | A mobile number |
| PesaLink | pesalink | Available | A bank account and bank code |
| RTGS | rtgs | Available | A bank account and bank code |
| EFT | eft | Available | A bank account and bank code |
| SWIFT | swift | Available | A BIC, an account and a country |
| On-us | internal | Available | An account at the same bank |
Every rail above pays KES from your KES balance. On the collections product,
rtgs, eft and swift can instead pay US dollars from your USD balance to a
USD account; see
Paying out USD.
A sell order's proceeds settle to your own OnLink KES account. Your payout
account is your OnLink KES account: read it with GET /v1/payout-accounts and
pass its payoutAccountId when you create the order. The proceeds land there,
and you pay onward from it with POST /v1/transfers. There is no
POST /v1/payout-accounts; the accounts listed are the ones your business
already holds. An account that cannot receive is refused at order creation with
PAYOUT_ACCOUNT_NOT_PAYABLE.
What tells you a payment is done
- Inbound.
credit.receivedfires for every cleared credit on your KES account, whoever sent it and whichever rail it came in on. - A transfer.
transfer.settledwhen the rail completes it, ortransfer.failedwhen the rail answers and refuses it — in which case the money never left. - A sell order.
order.settledwhen the payout completes.
All of these are signed webhooks, and the matching GET
agrees with them.
Cut-off times, and which rails never close, are on Cut-off times.
The USDT buy leg uses no rail
POST /v1/orders/buy debits the KES directly from your own KES balance the
instant the order is created. Nothing is sent to a payer and there is nothing
to attribute: kesDebit.status on the order tells you where the debit stands.
See Buy USDT with KES.
Precision
KES carries at most 2 decimal places, always as a string. See Money.
Rails
Every rail in the Kenyan corridor, what each one reaches, which of them an API call reaches today, and whether your reference survives the journey.
Cut-off times
Which Kenyan rails observe a banking day and which never close, why we do not publish a clock time, and how to find the one that applies to your account.