API reference
Sandbox
Calls that stand in for the real world in the sandbox: identity checks finishing, money arriving and payouts landing. Production keys get 403 sandbox_only.
Set a user's KYC outcome
POST/v1/sandbox/users/{user_id}/kyc
Sets KYC and terms status as if the hosted flow had finished, and fires the same events.
Returns User.
Path parameters
user_idstringrequiredStarts with
usr_.
Headers
Idempotency-KeyheaderrequiredA unique key for this write, up to 255 characters. Send the same key to retry safely; see idempotency.
Body
kyc_statusstringrequiredOne of
not_started,under_review,incomplete,approved,rejected.terms_statusstringDefaults to
approvedwhenkyc_statusisapproved.One of
pending,approved.rejection_reasonsarray of object
Responses
- 200The updated user.
- 401The API key is missing, invalid or revoked.
- 403The key may not perform this action, or the user is not approved.
- 404The object does not exist or belongs to another integrator.
- 422The request is well formed but fails validation or a business rule.
- 429The key is over its rate limit.
- 5XXServer error. Safe to retry with the same idempotency key.
curl -X POST "https://sandbox.api.ndeipi.example/v1/sandbox/users/usr_01JA8Z2F5G6H7J8K9M0N1P2Q3R/kyc" \
-H "Api-Key: $NDEIPI_API_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{
"kyc_status": "approved"
}'{
"id": "usr_01JA8Z2F5G6H7J8K9M0N1P2Q3R",
"object": "user",
"type": "individual",
"external_reference": "crm-1042",
"email": "ama.moyo@example.com",
"phone": "+263771234567",
"first_name": "Ama",
"last_name": "Moyo",
"business_name": null,
"country": "ZW",
"status": "active",
"kyc_status": "approved",
"terms_status": "approved",
"rejection_reasons": [],
"metadata": {
"segment": "retail"
},
"version": 3,
"created_at": "2026-10-16T09:30:00Z",
"updated_at": "2026-10-16T10:12:44Z"
}Simulate an incoming deposit
POST/v1/sandbox/deposits
Simulates fiat arriving at a standing deposit account or against a one-off on-ramp transfer. Returns the on-ramp transfer it moves. The amount may differ from the expected amount to test over- and under-payment.
Returns Transfer.
Headers
Idempotency-KeyheaderrequiredA unique key for this write, up to 255 characters. Send the same key to retry safely; see idempotency.
Body
deposit_account_idstringStarts with
da_.transfer_idstringA one-off on-ramp in
awaiting_funds.Starts with
trf_.amountstringrequiredNon-negative decimal string. Precision is limited per asset or currency (see
Route).outcomestringForce a review or a return to test those paths.
One of
credited,in_review,returned.Default
"credited".
Responses
- 200The on-ramp transfer after the deposit.
- 401The API key is missing, invalid or revoked.
- 403The key may not perform this action, or the user is not approved.
- 404The object does not exist or belongs to another integrator.
- 409The request conflicts with the object's current state or an earlier request.
- 422The request is well formed but fails validation or a business rule.
- 429The key is over its rate limit.
- 5XXServer error. Safe to retry with the same idempotency key.
curl -X POST "https://sandbox.api.ndeipi.example/v1/sandbox/deposits" \
-H "Api-Key: $NDEIPI_API_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{
"deposit_account_id": "da_01JA8ZF5TP0R5B8Z6Y3X2W1V0T",
"amount": "100.00"
}'{
"id": "trf_01JA8ZD7RM8P3Z6X4W1V0T9S8R",
"object": "transfer",
"kind": "onramp",
"state": "completed",
"state_reason": null,
"source": {
"type": "fiat",
"currency": "zar",
"rail": "absa_eft"
},
"destination": {
"type": "wallet",
"wallet_id": "wal_01JA8Z4K2V9QW3H6Y7XKD2M0RS",
"user_id": "usr_01JA8Z2F5G6H7J8K9M0N1P2Q3R",
"asset": "ndeipi-points"
},
"amount": "100.00",
"deposit_instructions": null,
"receipt": {
"amount_received": "100.00",
"amount_credited": "100.00",
"rate": "1",
"fees": [],
"rail_reference": "SANDBOX-1",
"initiated_at": "2026-10-16T09:30:00Z",
"completed_at": "2026-10-16T09:30:00Z"
},
"integrator_reference": null,
"metadata": {},
"version": 2,
"created_at": "2026-10-16T09:30:00Z",
"updated_at": "2026-10-16T09:30:00Z",
"deposit_account_id": "da_01JA8ZF5TP0R5B8Z6Y3X2W1V0T"
}Set an off-ramp's payout outcome
POST/v1/sandbox/transfers/{transfer_id}/payout_outcome
Moves a payout_submitted off-ramp to its final outcome. returned and undeliverable credit the source wallet and end the transfer in refunded.
Returns Transfer.
Path parameters
transfer_idstringrequiredStarts with
trf_.
Headers
Idempotency-KeyheaderrequiredA unique key for this write, up to 255 characters. Send the same key to retry safely; see idempotency.
Body
outcomestringrequiredOne of
completed,returned,undeliverable.reasonobjectMachine-readable reason with a human-readable description.
reason.codestringrequiredreason.messagestringrequired
Responses
- 200The transfer after the outcome.
- 401The API key is missing, invalid or revoked.
- 403The key may not perform this action, or the user is not approved.
- 404The object does not exist or belongs to another integrator.
- 409The request conflicts with the object's current state or an earlier request.
- 429The key is over its rate limit.
- 5XXServer error. Safe to retry with the same idempotency key.
curl -X POST "https://sandbox.api.ndeipi.example/v1/sandbox/transfers/trf_01JA8ZC4QK7N2Y5W3V0T9S8R6P/payout_outcome" \
-H "Api-Key: $NDEIPI_API_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{
"outcome": "returned",
"reason": {
"code": "account_closed",
"message": "The receiving account is closed."
}
}'{
"id": "trf_01JA8ZE2SN9Q4A7Y5X2W1V0T9S",
"object": "transfer",
"kind": "offramp",
"state": "refunded",
"state_reason": {
"code": "account_closed",
"message": "The receiving account is closed."
},
"source": {
"type": "wallet",
"wallet_id": "wal_01JA8Z5B7C1DE2F3G4H5J6K7LM",
"user_id": "usr_01JA8Z3H6J7K8M9N0P1Q2R3S4T",
"asset": "ndeipi-points"
},
"destination": {
"type": "payout_account",
"payout_account_id": "pa_01JA8Z6N3P4Q5R6S7T8U9V0WXY",
"user_id": "usr_01JA8Z3H6J7K8M9N0P1Q2R3S4T",
"currency": "zar",
"rail": "absa_eft"
},
"amount": "20.00",
"deposit_instructions": null,
"receipt": null,
"integrator_reference": "invoice-7781",
"metadata": {
"note": "Lunch"
},
"version": 4,
"created_at": "2026-10-16T09:30:00Z",
"updated_at": "2026-10-16T09:30:00Z"
}