Skip to main content
This guide collects KES 1,000 from a customer’s phone with M-Pesa and sends the USDC to your own Base address. After that, it shows how Nigerian bank transfers work. Before you start, you need:
  • An API key with the onramp switched on. See getting access.
  • A Base address you control to receive the USDC.
1

Get a quote

Give us either the KES amount to charge your customer, or the USDC amount you want to receive. This example charges an exact KES amount.
amount_kes is exactly what your customer will be asked to pay on their phone. amount_usdc is what arrives at your address.
2

Create the order

Add an Idempotency-Key header with a value that’s unique to this collection. If your request times out and you send it again, we’ll recognise it and won’t send your customer a second prompt.
The payment prompt pops up on your customer’s phone as soon as this call succeeds. There’s nothing else to trigger.
3

Your customer approves

They enter their M-Pesa PIN on the prompt. You don’t need to do anything.
Each order is a single attempt. If your customer dismisses the prompt, the order becomes cancelled. If the prompt times out or the payment doesn’t go through, it becomes failed. Either way, create a new order to try again.
4

Check it's done

Check the order’s status, or wait for the webhook:
Once your customer has paid, status becomes completed and receipt_number has the M-Pesa confirmation code. We send onramp.completed at that moment. Then, once the USDC transfer is confirmed, we send onramp.released with its transaction ID in release_tx_hash. See onramp webhooks.

Starting from the USDC amount

If you’d rather receive an exact amount of USDC and let the KES price follow, send amount_usdc instead of amount_kes:
The amount_kes in the response is then what your customer is charged: the USDC you asked for, plus the platform fee. Send the same amount_usdc to POST /api/onramp/orders instead of amount_kes.

Bank transfer (NGN)

Nigerian bank transfers work the same way, with two differences. The payer sends naira from their own bank instead of approving a prompt. And you need their bank details up front, so we can send their money back if the order can’t be completed.
1

Look up the payer's bank code

The code for the payer’s own bank goes in refund_account.institution below. See institutions.
2

Get a quote

amount_ngn is what the payer will be asked to send, fee included. net_ngn is the part that becomes your USDC.
3

Create the order

refund_account is the payer’s own bank account. If the order fails after they’ve paid, their naira goes back there. You can leave out account_name, because we look it up from the bank. You only need it if the bank doesn’t give us one, and in that case you’ll get a 422 asking for it.
4

Show the payment instructions

Show the payer payment_instructions.bank_name, account_number, and account_name as where to send, and payment_instructions.amount as exactly how much.
Show payment_instructions.amount exactly as we give it to you. It’s text and may include kobo (for example "9108.03"). Don’t round it or show a different number, because a different amount won’t be accepted.
Show a countdown to payment_instructions.expires_at. Don’t assume a fixed amount of time: the account only works until then. Once the order is no longer pending, payment_instructions is removed from it.
5

Wait for completion

Once the payer’s transfer arrives, the order becomes deposit_received while we send the USDC, then completed. Check the order’s status, or wait for onramp.completed and then onramp.released, the same events as M-Pesa. See onramp webhooks.
We don’t send a webhook for deposit_received. If you want to show “payment received” before the order completes, check GET /api/onramp/orders/{order_id}.