Panel — End Users
- Base path
/api/panel/v1/wallet- Identity
- Panel session (JWT) —
Authorization: Bearer <panel access token>. The token comes from panel login; an s2s signing key does NOT open these endpoints. - Authorization
- RBAC permission:
wallet:enduser:read·wallet:enduser:manage·wallet:enduser:kyc-override·wallet:enduser:kyc-approveFour-eyes: the requester and the approver cannot be the same person — this is enforced by identity comparison, not by a role gate. - Cross-surface
- PARTIAL: 12 of the end-user and corporate-account endpoints also exist in the s2s API (
GET/POST end-users,GET end-users/:id,/balances,/limits,GET /kyc-level,POST end-users/:id/freeze,corporate-accounts…). The remaining 8 are panel-only:end-users/:id/close,/unfreeze,/wallets,/kyc-level/history,/kyc-level/override-requests,/merchant-category,GET corporate-accounts/:id,PATCH corporate-accounts/:id.
Where you view customer records and manage their lifecycle.
Search and detail
GET end-users # filter by programId, accountType, status; cursor pagination
GET end-users/:id # customer detail
GET end-users/:id/wallets # their wallets
GET end-users/:id/balances # their balances
GET end-users/:id/limits # limit status
GET end-users/:id/deposit-instructionsPII is masked in listings. Use the masked value when verifying a customer on a support call; there is no need to display the full number on screen.
Freeze, unfreeze, close
POST end-users/:id/freeze # { reason }
POST end-users/:id/unfreeze # { reason }
POST end-users/:id/close # { reason }| Action | Effect |
|---|---|
| Freeze | The user cannot transact; the balance stays put, reversible |
| Unfreeze | Lifts the freeze |
| Close | Terminates the account — irreversible |
Before closing, check the balance and open operations. Closing an account that holds a balance or has an operation in BANK_PROCESSING / AWAITING_RECON leaves the ownership of that money ambiguous.
The reason field is written to the audit record. Write the real reason rather than "test" or "n/a" — this record is your only support in an audit or a customer dispute.
KYC level
GET end-users/:id/kyc-level
GET end-users/:id/kyc-level/history
POST end-users/:id/kyc-level/override-requests # { kycLevel, sourceRef, reason, effectiveAt?, expectedCurrentLevel? }Changing the level from the panel is a four-eyes request: you open it with the wallet:enduser:kyc-override permission, and the change is applied when another person holding wallet:enduser:kyc-approve approves it. The requester is taken from your session; you cannot approve your own request. Approval flow: Four-eyes requests.
sourceRef (the basis for the decision) and a reason are required. For an upgrade the evidence is verified at approval; if you pass expectedCurrentLevel and the level changed in the meantime, the approval is rejected. The history endpoint shows when, by whom and on what basis the level changed.
To raise a level, enter in sourceRef the id of an approved KYC session belonging to this end user. The level cannot exceed the level the session attests; four-eyes approval does not replace this requirement. To lower a level, a reference to the decision record is sufficient.
Details: KYC Levels.
Crypto balances
GET crypto/balances?swapAccountId=<id>Permission: wallet:enduser:read
An admin view of the crypto asset balances of a swap wallet account.
The panel is read-only here. Quoting, executing a swap and transferring are not in the panel — those are customer money movements and happen through the portal surface. Executed swaps already appear in the normal operation list.
Corporate accounts and the employee roster
POST corporate-accounts
GET corporate-accounts
GET corporate-accounts/:id
PATCH corporate-accounts/:id
POST corporate-accounts/:id/employees/import
POST corporate-accounts/:id/employees/offboard
GET end-users?corporateAccountId=<id> # roster listingCorporate account management uses this section's permissions (wallet:enduser:*); there is no separate permission family.
Bulk import is all-or-nothing, and offboarding an employee does not touch money — their balance stays with them. Full behaviour of both: Corporate Accounts & Employee Management.
Spend policy
PUT end-users/:id/merchant-categoryAssigns a category to a merchant; category-based spend rules read this field. The full rule engine: Spend Policy.
Support scenarios
| Scenario | Where to look |
|---|---|
| "My money never arrived" | Operations → status; AWAITING_RECON means pending |
| "My transfer was rejected" | The user's limit status and KYC level |
| "I can't sign in" | User status (frozen?), session/device records |
| "My balance is short" | Operation list + fee fields (feeTotal, taxTotal) |
| "Suspicious transaction" | Operation detail → fraudDecision; freeze if needed |
Things to watch
| Topic | Why it matters |
|---|---|
| Freeze is reversible, close is not | When in doubt, freeze first |
| Do not close accounts with a balance | Money ownership becomes ambiguous |
Make reason real | It is your only evidence in an audit |
| Level equals authority | Raising it takes effect immediately |