Wallet
End users
Wallets & Accounts

Wallets & Accounts

Who calls these endpoints?External API (s2s)
Base path
/api/v1/wallet
Identity
Ed25519 request signature — X-Key-Id, X-Date, X-Nonce, Digest (when there is a body), X-Signature. ±5 min clock window, single-use nonce, optional per-key IP allow-list.
Authorization
The key must carry the wallet product and the wallet permission the call requires; a call without it gets 403 WALLET_INSUFFICIENT_SCOPE. Permissions per endpoint: Key permissions.
Cross-surface
Both endpoints require wallet:enduser:manage or wallet:program:manage on your key. The endpoint that lists a user's wallets is merchant-panel only.

When an end user is created, the default wallet opens with a single account. With the two endpoints on this page you:

  • Add an account in another currency to an existing wallet — the most common need.
  • Open an extra wallet for the user — for example to set money aside for a separate purpose.

Both are limited to the currencies enabled in your program.

Open an account

POST /api/v1/wallet/wallets/{walletId}/accounts
HeaderRequiredRule
Idempotency-Key✅1–128 characters
Body fieldTypeRequiredRule
currencystring✅3–8 letters; upper-cased. Must be enabled in your program.

Rules:

  • A wallet can hold only one account per currency. A second account in the same currency gets 409 WALLET_ACCOUNT_EXISTS.
  • If the currency is not enabled in your program: 409 WALLET_CURRENCY_NOT_ALLOWED.
  • If the wallet is not ACTIVE (for example because the user was closed): 409 WALLET_STATE_INVALID.
curl -X POST "https://api-gateway.lunixi.com/api/v1/wallet/wallets/1e7f9a3b-5c2d-4a8e-b6f1-3d9c0e2a7b58/accounts" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: account-crm-88213-usd" \
  -H "X-Key-Id: …" -H "X-Date: …" -H "X-Nonce: …" -H "Digest: …" -H "X-Signature: …" \
  -d '{"currency":"USD"}'
{
  "status": "success",
  "code": "SUCCESS",
  "message": "…",
  "data": {
    "id": "7b4e1c9a-2f6d-4a3b-9e8c-1d5f7a2b6c90",
    "walletId": "1e7f9a3b-5c2d-4a8e-b6f1-3d9c0e2a7b58",
    "currency": "USD",
    "accountCode": 5100,
    "fullWalletNo": "58107634125100",
    "status": "ACTIVE"
  },
  "requestId": "…"
}

data.id is the new account's walletAccountId. fullWalletNo is the wallet number followed by the account code.

Open an extra wallet

POST /api/v1/wallet/end-users/{id}/wallets
HeaderRequiredRule
Idempotency-Key✅1–128 characters
Body fieldTypeRequiredRule
namestring—Wallet name, 1–80 characters. Defaults to Cüzdanım.
currenciesstring[]—Currencies of the accounts to open in the wallet. Values are upper-cased and duplicates count once; each must be enabled in your program. If omitted or empty, the wallet opens without accounts.

Rules:

  • The user must be ACTIVE; a wallet cannot be opened for a FROZEN or CLOSED user (409 WALLET_STATE_INVALID).
  • The new wallet has isDefault: false; the default wallet does not change.
  • Each wallet gets its own 10-digit walletNo.
curl -X POST "https://api-gateway.lunixi.com/api/v1/wallet/end-users/8d4c2a1f-3b6e-4f7a-9c5d-2e8b1a0f6c34/wallets" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: wallet-crm-88213-savings" \
  -H "X-Key-Id: …" -H "X-Date: …" -H "X-Nonce: …" -H "Digest: …" -H "X-Signature: …" \
  -d '{"name":"Savings","currencies":["TRY"]}'
{
  "status": "success",
  "code": "SUCCESS",
  "message": "…",
  "data": {
    "id": "6c2f8e1a-4b9d-4d3e-a7f5-0e1b9c3d2a84",
    "endUserId": "8d4c2a1f-3b6e-4f7a-9c5d-2e8b1a0f6c34",
    "walletNo": "7349028156",
    "name": "Savings",
    "isDefault": false,
    "status": "ACTIVE",
    "accounts": [
      {
        "id": "e9a1d4c7-3b2f-4e6a-8d5c-7f0b1a2e3c69",
        "walletId": "6c2f8e1a-4b9d-4d3e-a7f5-0e1b9c3d2a84",
        "currency": "TRY",
        "accountCode": 5000,
        "fullWalletNo": "73490281565000",
        "status": "ACTIVE"
      }
    ],
    "createdAt": "2026-10-11T12:04:51.330Z"
  },
  "requestId": "…"
}
⚠️

A wallet opened without accounts is invisible to s2s reads: the balances endpoint lists accounts only, and the endpoint that lists a user's wallets is panel-only. Store data.id from the response and use it when opening an account.

Idempotency

Idempotency-Key is required on both endpoints:

  • Repeating the same request with the same key returns the first successful response as is; no second wallet or account is opened.
  • Using the same key with a different request returns 409 WALLET_IDEMPOTENCY_CONFLICT. The comparison uses walletId and currency for opening an account, and the user, name and currencies for opening a wallet, as you sent them.
  • If the first request failed, the key is released.

If you repeat an account opening with a new key, you get 409 WALLET_ACCOUNT_EXISTS because the account already exists; read it from the balances endpoint.

Errors

HTTPCodeWhen
400VALIDATION_ERRORThe body breaks a rule or contains an undefined field
400—A path id is not a UUID; Idempotency-Key missing, empty or longer than 128 characters
400WALLET_VALIDATIONThe currency is not supported by the platform
403WALLET_INSUFFICIENT_SCOPEThe key lacks wallet:enduser:manage or wallet:program:manage
404WALLET_NOT_FOUNDThe user or wallet does not exist or is not yours
409WALLET_ACCOUNT_EXISTSThe wallet already has an account in this currency
409WALLET_CURRENCY_NOT_ALLOWEDThe currency is not enabled in your program
409WALLET_STATE_INVALIDThe user (opening a wallet) or the wallet (opening an account) is not ACTIVE
409WALLET_IDEMPOTENCY_CONFLICTThe same Idempotency-Key was used with a different request
409WALLET_IDEMPOTENCY_IN_PROGRESSThe first request sent with the same key is still being processed