Skip to content
iSmartPay Developers
Esc
↑↓navigate↵open⌘Jpreview
On this page

Wallet transfers

Send money from your wallet to another iSmartPay business.

A wallet transfer moves money from your wallet to another iSmartPay business’s wallet. You find the business by its handle.

Handles

A handle is a business’s public name for receiving transfers. A business needs one to be paid. An owner claims it in the console, and only a verified business can claim one. A key cannot claim or change a handle.

The same handle works in the merchant console and the developer console.

Check the recipient

Look up the handle first, so you can show who you are about to pay:

GET /v1/recipients/acme-stores
{
  "handle": "acme-stores",
  "businessName": "Acme Stores",
  "ownerName": "Ama Mensah",
  "handleSince": "2026-08-14T09:30:00Z"
}
  • The handle must match exactly.
  • businessName is the handle’s display name, else the trading name, else the registered name. It can be missing when it is not known.
  • Your own handle is 400 own_handle. An unknown handle is 404.

Send

POST /v1/transfers
Idempotency-Key: supplier-7731
{
  "reference": "supplier-7731",
  "handle": "acme-stores",
  "amount": "25.00",
  "currency": "GHS"
}
  • reference is yours, and unique for each transfer.
  • Do not send a pin. Unknown fields are refused.
  • Your own handle is 400 own_handle. An unknown handle is 404.

This one request holds the money and confirms it. A 200 with status completed means the money moved:

{
  "reference": "supplier-7731",
  "amount": "25.00",
  "currency": "GHS",
  "status": "completed",
  "recipientHandle": "acme-stores",
  "recipientName": "Acme Stores",
  "createdAt": "2026-10-05T10:00:00Z"
}

recipientName can be missing when it is not known. Other statuses, such as held, can appear.

Retrying

If a request fails, times out or returns 5xx, send the same reference and body again. The transfer carries on from where it stopped and is never sent twice. Use the same Idempotency-Key too.

Do not retry with a new reference. A new reference is a new transfer.

A reference already used for a different transfer is 409 reference_reused.

Fees and limits

Wallet transfers carry no fee. They count toward your outbound limits. Check GET /v1/limits before a large transfer.

Read a transfer

GET /v1/transfers/supplier-7731

This returns the transfer by your reference.

The receiving business

When a transfer completes, the recipient gets a transfer.received webhook:

{
  "id": "evt_8d2c41f07a9e4b3c9d1e6f5a4b3c2d1e",
  "type": "transfer.received",
  "createdAt": "2026-10-05T12:00:00Z",
  "data": {
    "reference": "supplier-7731",
    "amount": "25.00",
    "currency": "GHS",
    "senderName": "Acme Stores",
    "completedAt": "2026-10-05T12:00:00Z"
  }
}
  • reference is the one the sender chose.
  • senderName is the sender’s trading name, else registered name. It can be missing when it is not known.
  • It is sent once per transfer, only when the money is in your wallet.

The transfer also shows in GET /v1/transactions, as a wallet_transfer with direction in. See Transactions and events.

Permissions

To The key needs
Look up a recipient or send wallettransfer.write
Read a transfer wallettransfer.read

Webhooks

Subscribe an endpoint to these events in the console:

Type Sent when
transfer.status_changed A transfer you sent moves to a new status, such as completed or failed.
transfer.received Another business’s transfer to you completed.

transfer.status_changed goes to the sending business only. data is the transfer as it stood when the event was sent. It does not carry the recipient’s handle or name. Fetch the transfer by reference when you need them.

If your webhook endpoints were set up before wallet transfers arrived, edit or add an endpoint in the console once. Until then, transfer events are not sent to your business. See Webhooks.

Errors

As well as the common errors:

Status Code What to do
400 own_handle You cannot pay yourself. Check the handle.
400 transfer_refused The money could not be held. Nothing left your wallet. Read message.
409 reference_reused The reference belongs to another transfer. Use a new one.
409 transfer_not_held The hold can no longer be confirmed. Read the transfer to see where it stands.
403 transaction_limit_exceeded, daily_limit_exceeded, monthly_limit_exceeded The transfer is over your outbound limits. Check GET /v1/limits.

Was this page helpful?