List End Users
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
- The same list exists in the merchant panel. This endpoint requires a wallet read permission (
wallet:enduser:read) on your key.
GET /api/v1/wallet/end-usersLists your end users newest first (by creation time). Phone and name are returned masked only.
Query parameters
All are optional. If you pass several filters, they are applied together.
| Parameter | Type | Rule and meaning |
|---|---|---|
programId | UUID | Only users of this program. |
accountType | string | PERSONAL or BUSINESS. |
status | string | ACTIVE, FROZEN or CLOSED. |
corporateAccountId | UUID | Only employees linked to this employer (corporate account). If the corporate account is not yours, 404 WALLET_NOT_FOUND is returned; the list never falls back to unfiltered. |
merchantCategoryState | string | UNSET = records without a category, SET = records with a category. Personal (PERSONAL) records never have a category; to find uncategorized businesses, combine it with accountType=BUSINESS. |
limit | integer | Page size, 1–100. Defaults to 20. |
cursor | string | The nextCursor value from the previous response. Not sent on the first page. The value is opaque; do not build or modify it. |
A value outside the defined ones, or a parameter not in this list, is rejected with 400 VALIDATION_ERROR.
Example
curl "https://api-gateway.lunixi.com/api/v1/wallet/end-users?programId=5b9e2f3a-7c41-4d8e-a6f2-9e1b3c4d5f60&status=ACTIVE&limit=2" \
-H "X-Key-Id: …" -H "X-Date: …" -H "X-Nonce: …" -H "X-Signature: …"{
"status": "success",
"code": "SUCCESS",
"message": "…",
"data": {
"items": [
{
"id": "8d4c2a1f-3b6e-4f7a-9c5d-2e8b1a0f6c34",
"programId": "5b9e2f3a-7c41-4d8e-a6f2-9e1b3c4d5f60",
"accountType": "PERSONAL",
"externalCustomerId": "crm-88213",
"corporateAccountId": null,
"corporateOffboardedAt": null,
"kycRef": null,
"kycLevelCache": "LOW",
"kycLevelRefreshedAt": "2026-10-11T10:02:44.105Z",
"phoneMasked": "9053******67",
"displayNameMasked": "A*** Y*****",
"merchantCategory": null,
"status": "ACTIVE",
"createdAt": "2026-10-11T09:15:02.418Z",
"updatedAt": "2026-10-11T10:02:44.105Z"
},
{
"id": "3f9a6c2e-1d7b-4e5a-8c4f-6b2d9e0a1c75",
"programId": "5b9e2f3a-7c41-4d8e-a6f2-9e1b3c4d5f60",
"accountType": "BUSINESS",
"externalCustomerId": "crm-77104",
"corporateAccountId": null,
"corporateOffboardedAt": null,
"kycRef": null,
"kycLevelCache": null,
"kycLevelRefreshedAt": null,
"phoneMasked": "9053******09",
"displayNameMasked": "K**** K*****",
"merchantCategory": null,
"status": "ACTIVE",
"createdAt": "2026-10-10T16:41:19.007Z",
"updatedAt": "2026-10-10T16:41:19.007Z"
}
],
"nextCursor": "MjAyNi0xMC0xMCAxNjo0MToxOS4wMDcwMDArMDB8M2Y5YTZjMmU…",
"pageInfo": { "hasMore": true, "nextCursor": "MjAyNi0xMC0xMCAxNjo0MToxOS4wMDcwMDArMDB8M2Y5YTZjMmU…", "totalCount": null }
},
"pageInfo": { "hasMore": true, "nextCursor": "MjAyNi0xMC0xMCAxNjo0MToxOS4wMDcwMDArMDB8M2Y5YTZjMmU…", "totalCount": null },
"requestId": "…"
}Each record has the same fields as endUser on Detail & Lookup.
Pagination
- Records are in
data.items. - When there is a next page,
data.nextCursoris set andpageInfo.hasMoreistrue; send that value ascursorin the next request. Keep the same filters. - On the last page
nextCursorisnullandpageInfo.hasMoreisfalse. - This endpoint does not return a total count (
totalCount: null).
let cursor;
do {
const qs = new URLSearchParams({ programId, limit: '100', ...(cursor && { cursor }) });
const res = await signedGet(`/api/v1/wallet/end-users?${qs}`); // signed request
const { data } = await res.json();
for (const endUser of data.items) handle(endUser);
cursor = data.nextCursor;
} while (cursor);The list cannot be searched by phone. To reach a specific user by your own identifier use by-external; to find out whether a phone is registered in a program use wallet lookup.
Errors
| HTTP | Code | When |
|---|---|---|
| 400 | VALIDATION_ERROR | A parameter breaks a rule (for example limit=500, status=OPEN) |
| 403 | WALLET_INSUFFICIENT_SCOPE | The key has no wallet read permission |
| 404 | WALLET_NOT_FOUND | corporateAccountId is not one of your corporate accounts |