Guides
Move money between users
A transfer from one user's wallet to another user's wallet in the same asset settles on Ndeipi's ledger in a single step. No bank or provider is involved, so it's final in the response.
Send
curl -X POST "$NDEIPI/transfers" \
-H "Api-Key: $NDEIPI_API_KEY" -H "Idempotency-Key: $PAYMENT_KEY" \
-H "Content-Type: application/json" \
-d '{ "source": { "type": "wallet", "wallet_id": "wal_01JA8Z4K2V9QW3H6Y7XKD2M0RS" },
"destination": { "type": "wallet", "wallet_id": "wal_01JA8Z5B7C1DE2F3G4H5J6K7LM" },
"amount": "25.00",
"integrator_reference": "invoice-7781",
"metadata": { "note": "Lunch" } }'The response is the transfer, normally already completed, with a receipt showing what was debited and credited.
Check before you commit
Add "dry_run": true to run every check (approval, balance, route and limits) and get a preview without moving anything. A failing dry run returns the same error the real request would, so it's a cheap way to validate a payment screen before the user confirms.
Held for review
Large or unusual transfers can come back in_review. Ndeipi's compliance team releases them (completed) or refuses them (failed); you get transfer.state_changed either way. Show the user that the payment is being checked rather than failed.
Points keep their kind
When points move between users, the sender's earned points are spent first and the recipient receives the same split. The receipt's earned_amount shows how much moved as earned points. This keeps rewards from becoming cash by being sent to someone else. See purchased and earned points.
Errors to expect
| Code | Why |
|---|---|
insufficient_funds | The source wallet's available balance is too low. |
same_source_and_destination | The two wallets are the same. |
asset_mismatch | The wallets hold different assets. Use a conversion instead. |
limit_exceeded | A per-user or per-transfer limit; limit names it. |
user_not_approved | One of the users hasn't finished onboarding. |
user_deactivated | One of the users has been deactivated. |
Your references
integrator_reference and metadata come back unchanged on the transfer and in every event about it. You can list transfers by integrator_reference to find the one that belongs to an order or invoice.