ndeipipayments APIv1 · 0.1.0-draftAPI reference

API reference

Wallets

A wallet holds one asset for one user. Every user has at most one wallet per asset.

List a user's wallets

GET/v1/users/{user_id}/wallets

Returns a page of Wallet objects.

Path parameters

user_idstringrequired

Starts with usr_.

Query parameters

limitinteger

Default 10.

starting_afterstring

Cursor; an object ID. Returns the page after it. Cannot be combined with ending_before.

ending_beforestring

Cursor; an object ID. Returns the page before it. Cannot be combined with starting_after.

assetstring

A wallet asset code. The set is data on GET /routes. In 1.0 it holds two assets:

  • ndeipi-points: Ndeipi Points, bought with fiat on Absa or PayPal at a fixed price per currency and cashed out the same way. Every user's default asset.
  • ndeipi-coin: NdeipiCoin, opt-in. Its price moves. It is bought and sold only by converting points at a locked quote (POST /quotes), never directly with fiat. A wallet needs acknowledge_price_risk: true to create.

Responses

  • 200A page of wallets.
  • 401The API key is missing, invalid or revoked.
  • 404The object does not exist or belongs to another integrator.
  • 429The key is over its rate limit.
  • 5XXServer error. Safe to retry with the same idempotency key.
Request
curl "https://sandbox.api.ndeipi.example/v1/users/usr_01JA8Z2F5G6H7J8K9M0N1P2Q3R/wallets" \
  -H "Api-Key: $NDEIPI_API_KEY"
Response 200
{
  "data": [
    {
      "id": "wal_01JA8Z4K2V9QW3H6Y7XKD2M0RS",
      "object": "wallet",
      "user_id": "usr_01JA8Z2F5G6H7J8K9M0N1P2Q3R",
      "asset": "ndeipi-points",
      "decimals": 2,
      "status": "active",
      "balance": {
        "object": "wallet_balance",
        "wallet_id": "wal_01JA8Z4K2V9QW3H6Y7XKD2M0RS",
        "asset": "ndeipi-points",
        "available": "75.00",
        "pending": "0.00",
        "cashable": "60.00",
        "as_of": "2026-10-16T09:30:02Z"
      },
      "price_risk_acknowledged_at": null,
      "metadata": {},
      "version": 1,
      "created_at": "2026-10-16T09:30:00Z"
    }
  ],
  "has_more": false
}

Create a wallet

POST/v1/users/{user_id}/wallets

Creates a wallet for an approved user. A user holds at most one wallet per asset in 1.0; a second create for the same asset returns 409 wallet_exists. That wallet is the user's default for the asset, which transfers.send resolves.

Returns Wallet.

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

assetstringrequired

A wallet asset code. The set is data on GET /routes. In 1.0 it holds two assets:

  • ndeipi-points: Ndeipi Points, bought with fiat on Absa or PayPal at a fixed price per currency and cashed out the same way. Every user's default asset.
  • ndeipi-coin: NdeipiCoin, opt-in. Its price moves. It is bought and sold only by converting points at a locked quote (POST /quotes), never directly with fiat. A wallet needs acknowledge_price_risk: true to create.
acknowledge_price_riskboolean

Required and true for ndeipi-coin: the integrator confirms the user has been shown that NdeipiCoin's price moves and a balance can fall in value. Without it the create returns 422 price_risk_not_acknowledged. The time of acknowledgement is recorded on the wallet.

metadataobject

Integrator key-value data, returned unchanged. Up to 50 keys; keys up to 40 characters, values up to 500.

Responses

  • 201Wallet created.
  • 400The request is malformed.
  • 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/users/usr_01JA8Z2F5G6H7J8K9M0N1P2Q3R/wallets" \
  -H "Api-Key: $NDEIPI_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
    "asset": "ndeipi-points"
  }'
Response 201
{
  "id": "wal_01JA8Z4K2V9QW3H6Y7XKD2M0RS",
  "object": "wallet",
  "user_id": "usr_01JA8Z2F5G6H7J8K9M0N1P2Q3R",
  "asset": "ndeipi-points",
  "decimals": 2,
  "status": "active",
  "balance": {
    "object": "wallet_balance",
    "wallet_id": "wal_01JA8Z4K2V9QW3H6Y7XKD2M0RS",
    "asset": "ndeipi-points",
    "available": "0.00",
    "pending": "0.00",
    "cashable": "0.00",
    "as_of": "2026-10-16T09:30:02Z"
  },
  "price_risk_acknowledged_at": null,
  "metadata": {},
  "version": 1,
  "created_at": "2026-10-16T09:30:00Z"
}

Get a wallet

GET/v1/users/{user_id}/wallets/{wallet_id}

Returns Wallet.

Path parameters

user_idstringrequired

Starts with usr_.

wallet_idstringrequired

Starts with wal_.

Responses

  • 200The wallet, with its current balance.
  • 401The API key is missing, invalid or revoked.
  • 404The object does not exist or belongs to another integrator.
  • 429The key is over its rate limit.
  • 5XXServer error. Safe to retry with the same idempotency key.
Request
curl "https://sandbox.api.ndeipi.example/v1/users/usr_01JA8Z2F5G6H7J8K9M0N1P2Q3R/wallets/wal_01JA8Z4K2V9QW3H6Y7XKD2M0RS" \
  -H "Api-Key: $NDEIPI_API_KEY"
Response 200
{
  "id": "wal_01JA8Z4K2V9QW3H6Y7XKD2M0RS",
  "object": "wallet",
  "user_id": "usr_01JA8Z2F5G6H7J8K9M0N1P2Q3R",
  "asset": "ndeipi-points",
  "decimals": 2,
  "status": "active",
  "balance": {
    "object": "wallet_balance",
    "wallet_id": "wal_01JA8Z4K2V9QW3H6Y7XKD2M0RS",
    "asset": "ndeipi-points",
    "available": "75.00",
    "pending": "0.00",
    "cashable": "60.00",
    "as_of": "2026-10-16T09:30:02Z"
  },
  "price_risk_acknowledged_at": null,
  "metadata": {},
  "version": 1,
  "created_at": "2026-10-16T09:30:00Z"
}

Get a wallet's balance

GET/v1/users/{user_id}/wallets/{wallet_id}/balance

Returns WalletBalance.

Path parameters

user_idstringrequired

Starts with usr_.

wallet_idstringrequired

Starts with wal_.

Responses

  • 200Available and pending balances.
  • 401The API key is missing, invalid or revoked.
  • 404The object does not exist or belongs to another integrator.
  • 429The key is over its rate limit.
  • 5XXServer error. Safe to retry with the same idempotency key.
Request
curl "https://sandbox.api.ndeipi.example/v1/users/usr_01JA8Z2F5G6H7J8K9M0N1P2Q3R/wallets/wal_01JA8Z4K2V9QW3H6Y7XKD2M0RS/balance" \
  -H "Api-Key: $NDEIPI_API_KEY"
Response 200
{
  "object": "wallet_balance",
  "wallet_id": "wal_01JA8Z4K2V9QW3H6Y7XKD2M0RS",
  "asset": "ndeipi-points",
  "available": "75.00",
  "pending": "0.00",
  "cashable": "60.00",
  "as_of": "2026-10-16T09:30:02Z"
}

List a wallet's history

GET/v1/users/{user_id}/wallets/{wallet_id}/history

One entry per ledger posting line that touched the wallet. Summing amount (credits positive, debits negative) over all entries for a bucket gives that bucket's balance.

Returns a page of WalletHistoryEntry objects.

Path parameters

user_idstringrequired

Starts with usr_.

wallet_idstringrequired

Starts with wal_.

Query parameters

limitinteger

Default 10.

starting_afterstring

Cursor; an object ID. Returns the page after it. Cannot be combined with ending_before.

ending_beforestring

Cursor; an object ID. Returns the page before it. Cannot be combined with starting_after.

created_aftertimestamp
created_beforetimestamp

Responses

  • 200A page of history entries.
  • 401The API key is missing, invalid or revoked.
  • 404The object does not exist or belongs to another integrator.
  • 429The key is over its rate limit.
  • 5XXServer error. Safe to retry with the same idempotency key.
Request
curl "https://sandbox.api.ndeipi.example/v1/users/usr_01JA8Z2F5G6H7J8K9M0N1P2Q3R/wallets/wal_01JA8Z4K2V9QW3H6Y7XKD2M0RS/history?limit=50" \
  -H "Api-Key: $NDEIPI_API_KEY"
Response 200
{
  "data": [
    {
      "id": "whe_01JA8ZM5AW6Y1H4F2E9D8C7B6A",
      "object": "wallet_history_entry",
      "wallet_id": "wal_01JA8Z4K2V9QW3H6Y7XKD2M0RS",
      "transfer_id": "trf_01JA8ZC4QK7N2Y5W3V0T9S8R6P",
      "bucket": "available",
      "amount": "-25.00",
      "balance_after": "60.00",
      "description": "Transfer to usr_01JA8Z3H6J7K8M9N0P1Q2R3S4T",
      "created_at": "2026-10-16T09:30:02Z"
    }
  ],
  "has_more": false
}