OnLink
ConceptsRails

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.

A rail is how value actually moves. Constraints live here rather than on a flow page, so each one is stated in exactly one place.

Three tables follow, and they answer three different questions. The first is about the rails themselves and does not change when we ship an endpoint. The second is about this API and changes whenever we do. The third is the one worth reading before you design attribution.

The status vocabulary

Two values, defined once and used in the second table only.

StatusWhat it means
AvailableAn operation on this API reaches the rail in that direction today.
Not available todayNo operation on this API reaches it. This is a statement about the API surface.

Not available today is not a property of the rail

A rail marked that way is a rail this API does not reach in that direction yet. It is not a permanent property of the rail, and it is not a claim that the movement is impossible in the Kenyan market. Read the row as a fact about what you can call, and ask us if your product needs the direction that is missing.

Rail reach at a glance

flowchart TB
    accTitle: Which rails reach you, and which you reach
    accDescr: Two groups. Reaching you, M-PESA, PesaLink, RTGS and EFT pay into your KES balance, USDT on Tron arrives at your deposit address and tops up your USDT balance, and a US deposit to a collection is paid into your USD balance. Leaving you, a transfer pays shillings from your KES balance over M-PESA, PesaLink, RTGS, EFT or SWIFT, a USD transfer pays US dollars from your USD balance over RTGS, EFT or SWIFT, a sell order pays shillings to your own OnLink KES account, and a USDT send pays USDT to a wallet address you registered.
    subgraph out [Leaving you]
        direction TB
        O1[Transfer] --> O2[M-PESA, PesaLink, RTGS, EFT or SWIFT]
        O7[USD transfer] --> O8[RTGS, EFT or SWIFT, to a USD account]
        O3[Sell order] --> O4[Shillings to your own OnLink KES account]
        O5[USDT send] --> O6[USDT to a wallet address you registered]
    end
    subgraph inb [Reaching you]
        direction TB
        I1[M-PESA, PesaLink, RTGS, EFT] --> I2[Your KES balance]
        I3[USDT on Tron] --> I4[Your deposit address, then your USDT balance]
        I5[ACH, FedNow or wire to a collection] --> I6[Your USD balance, net of fee]
    end

Reading it as a list:

  1. Reaching you — four Kenyan rails pay into your KES balance, USDT on Tron arrives at your deposit address and tops up your USDT balance, and a US deposit to one of your collections is paid into your USD balance, net of fee.
  2. Leaving you — a transfer pays shillings from your KES balance to an M-PESA number or a bank account, a USD transfer pays US dollars from your USD balance to a USD account over RTGS, EFT or SWIFT, a sell order pays shillings to your own OnLink KES account, and a USDT send pays USDT to a wallet address you registered and confirmed.
  3. A transfer's destination is chosen per transfer, which is why 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.

1. What each rail is

Every rail here runs in both directions — each one can bring money to you and carry money away. What the API reaches is the next table, and the two are not the same thing.

RailTransfer rail valueDestination shapeCurrency
M-PESAmpesaA Pay Bill and account number in; a mobile number outKES
PesaLinkpesalinkA Kenyan bank account and bank codeKES
RTGSrtgsA Kenyan bank account and bank codeKES, USD
EFTeftA Kenyan bank account and bank codeKES, USD
SWIFTswiftA BIC and an account, with a beneficiary countryNon-KES
On-usinternalAn account at the same bank as oursKES
USDT (Tron)—A Tron address, TRC-20USDT
USD (ACH/FedNow/wire)—A US bank account and routing numberUSD

rail is the field on POST /v1/transfers (and on each item of a batch) that chooses how a payout leaves your KES balance, or, for a USD transfer on rtgs, eft or swift, your USD balance. GET /v1/funding groups the inbound rails by the shape of the instructions instead: mpesa_paybill, and bank_transfer for the three bank rails. A dash means no operation takes a value for that rail.

USDT is on this list because it is a rail like the others from an integration's point of view, even though it carries no rail field: the leg is chosen by the order's side. It has its own page, and sending on any other network loses the funds.

2. What this API reaches today

RailMoney in (to you)Money out (from you)
M-PESAAvailableAvailable
PesaLinkAvailableAvailable
RTGSAvailableAvailable
EFTAvailableAvailable
SWIFTNot available todayAvailable
On-usNot available todayAvailable
USDT (Tron)AvailableAvailable
USD (ACH/FedNow/wire)Available 1Not available today

Money in is a payment arriving in your KES balance, USDT arriving at your deposit address, or a USD deposit to a collection being paid into your USD account — see Receive money in Kenya. Money out is an operation on this API that sends value from you over that rail: a transfer for the Kenyan rails and SWIFT — see Send money from your KES account — and a USDT send for Tron. KES has the detail.

On the collections product, a transfer can also send US dollars from your USD account, over RTGS, EFT or SWIFT only, to a USD account: see Paying out USD. M-PESA, PesaLink and on-us transfers take KES only.

1 Open a collection mints real US deposit details a contributor sends to, and an arrived deposit is paid into your USD account, net of fee. That USD can be converted to KES in your KES account with Convert USD to KES and paid out over the Kenyan rails from there, or paid out as USD over RTGS, EFT or SWIFT as above. Sending USD back out over ACH, FedNow or wire is not available today.

3. Attribution

The table to read before you design how you match a payment to a customer.

An inbound payment is credited to your balance, not to an order, so the question is not which order a payment belongs to but which of your users sent it. This is the table to read before you design that.

RailDoes a reference of yours travel?What you get to identify the payer
M-PESANo 1The payer's M-PESA receipt code, the amount, the time
PesaLinkNoThe payer's bank reference, the amount, the time
RTGSNoThe payer's bank reference, the amount, the time
EFTNoThe payer's bank reference, the amount, the time
SWIFT——
On-us——
USDT (Tron)No 2The arrival, announced by usdt_credit.received
USD (ACH/FedNow/wire)Depends 3A depositMessage code, or the account number itself

Every Kenyan-rail credit reaches you as a credit.received webhook carrying the payer's own rail reference in reference — the one handle a payer can quote back to you. References and attribution has the design options.

1 M-PESA Pay Bill has no narration field, so nothing you or we mint can ride along with the payment. If you need certainty about who paid, raise the M-PESA prompt on the payer's phone yourself — Receive money in Kenya shows how.

2 Your Tron deposit address is the same for every deposit, so it cannot tell two senders apart. It tops up your USDT balance.

3 Most collections share one deposit account, so the contributor has to quote the depositMessage code we mint in their transfer. A small number of collections instead get a dedicated account number with nothing to quote at all. Either way, an arrived deposit is attributed back to your collection and its net amount is paid into your USD account — see Open a collection: what happens when a deposit arrives.

A dash means the direction is not reachable on this API today, so there is nothing true to publish yet. It is not a claim that the rail behaves differently from the ones above it.

On this page