ndeipipayments APIv1 · 0.1.0-draftAPI reference

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_idstringrequired

Starts with usr_.

Headers

Idempotency-Keyheaderrequired

A unique key for this write, up to 255 characters. Send the same key to retry safely; see idempotency.

Body

kyc_statusstringrequired

One of not_started, under_review, incomplete, approved, rejected.

terms_statusstring

Defaults to approved when kyc_status is approved.

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.
Request
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"
  }'
Response 200
{
  "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-Keyheaderrequired

A unique key for this write, up to 255 characters. Send the same key to retry safely; see idempotency.

Body

deposit_account_idstring

Starts with da_.

transfer_idstring

A one-off on-ramp in awaiting_funds.

Starts with trf_.

amountstringrequired

Non-negative decimal string. Precision is limited per asset or currency (see Route).

outcomestring

Force 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.
Request
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"
  }'
Response 200
{
  "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_idstringrequired

Starts with trf_.

Headers

Idempotency-Keyheaderrequired

A unique key for this write, up to 255 characters. Send the same key to retry safely; see idempotency.

Body

outcomestringrequired

One of completed, returned, undeliverable.

reasonobject

Machine-readable reason with a human-readable description.

reason.codestringrequired
reason.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.
Request
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."
    }
  }'
Response 200
{
  "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"
}