Panel — Overview & Permissions
- 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
- Every endpoint is bound to an RBAC permission code; codes are given per endpoint below.Four-eyes: the requester and the approver cannot be the same person — this is enforced by identity comparison, not by a role gate.
- Cross-surface
- The endpoints on this page have NO equivalent in the s2s API; you cannot call them from your own panel. These capabilities exist only in the merchant panel, behind a panel session.
The merchant panel is where you operate your wallet program: program settings, customer management, operational intervention, limit and fee schemes, campaigns, bulk payouts, terminals and reports.
The panel surface lives under /api/panel/v1/wallet/* and runs on your panel session (JWT). For server-to-server integration use the external API; for the end-user app use the portal. 132 panel endpoints have no s2s counterpart — see the surface comparison matrix.
Permission codes
Every panel action is bound to an RBAC permission code. You delegate authority by granting codes to team roles. The wallet surface currently defines 30 permission codes:
Program & policy
| Permission code | What it opens |
|---|---|
wallet:program:read | Program list and detail, the live program, the wallet-provider catalogue |
wallet:program:manage | Creating and editing programs — branding, currencies, onboarding mode, status |
wallet:sponsor-policy:manage | Sponsor-policy drafts, bank integrations, provider switches, integration catalogue, merchant wallet providers |
wallet:sponsor-policy:approve | Sponsor-policy version approve/reject, completing a provider switch, QR producer-code approve/retire — four eyes |
wallet:config:manage | Agent (dealer) definitions |
End user & corporate account
| Permission code | What it opens |
|---|---|
wallet:enduser:read | Reading customers, corporate accounts, wallets, balances, limits, KYC level, deposit instructions and crypto balances |
wallet:enduser:manage | Creating customers, freeze/unfreeze/close, corporate account and employee management, assigning a merchant category |
wallet:enduser:kyc-override | Requesting a KYC level change — the change is applied once another person approves it |
wallet:enduser:kyc-approve | Approving a KYC level change request — a separate permission; enduser:manage is not enough; four eyes |
wallet:legal-hold:manage | Adding legal holds, viewing holds and the retention status, requesting the release of a hold — see Data Retention and Legal Holds |
wallet:legal-hold:approve | Approving a hold release request — a different person than the requester; four eyes |
Operations & intervention
| Permission code | What it opens |
|---|---|
wallet:operation:read | Operation list/detail, receipts, suspense funds, invoice and bill-payment monitoring, ops-health |
wallet:operation:intervene | Manual operation intervention, suspense match/return, top-up refund, stuck withdrawals, cash-out holds — opening intervention requests and approving other people's requests; four eyes |
Limits, fees & commission
| Permission code | What it opens |
|---|---|
wallet:limit:manage | Limit schemes, assigning a scheme to a program, shared caps, OTP policy, spend-policy rules |
wallet:fee:manage | Fee and commission schedules, the version submit/approve chain (four eyes), branch fees, the fee report |
Campaigns & loyalty
| Permission code | What it opens |
|---|---|
wallet:campaign:manage | Campaign and segment management, version submit and approve — approval is not a separate permission; four eyes is enforced by principal comparison |
wallet:loyalty:read | Reading the loyalty program, earn rules, tier scheme, badges, point balance and history |
wallet:loyalty:manage | Writing the loyalty program, earn rules, tier scheme, badges and badge rules |
Bulk payouts
| Permission code | What it opens |
|---|---|
wallet:bulk:create | Creating, listing, items, preview, statement, counters, submit |
wallet:bulk:approve | Approve, reject, process, cancel, retry failed — a different person from create, four eyes |
QR & terminals
| Permission code | What it opens |
|---|---|
wallet:qr:read | Listing and reading QR codes |
wallet:qr:manage | Issuing and revoking QR codes |
wallet:terminal:read | Terminal list, detail, event history and the terminal report |
wallet:terminal:manage | Creating terminals, issuing activation codes, issue/rotate/revoke credentials, suspend/resume/retire, bulk actions |
Cards
| Permission code | What it opens |
|---|---|
wallet:card:read | Card list, detail and authorization history |
wallet:card:operate | Issuing, freezing, unfreezing and cancelling cards |
wallet:card:authorize | Issuer event endpoints: authorization, clearing, reversal (/card-events) |
Cash-out
Cash-out endpoints live under /api/panel/v1/wallet/cash-out.
| Permission code | What it opens |
|---|---|
wallet:cashout:read | Cash-out request detail |
wallet:cashout:operate | Generating and cancelling a cash-out code |
wallet:cashout:dispense | Confirming that the cash was dispensed |
Invoices & reports
| Permission code | What it opens |
|---|---|
wallet:invoice:manage | Issuing and cancelling invoices |
wallet:report:read | Overview, operations, campaign and custody reports, the campaign report, operations export |
There are NO permission codes called wallet:campaign:approve or wallet:card:manage. Both were listed on this page before, but neither ever existed in the code; granting them to a role opens nothing. Campaign approval runs on wallet:campaign:manage (four eyes still applies) and card actions on wallet:card:operate.
The four-eyes rule
On money-critical actions, the requester and the approver cannot be the same person. This is enforced not by a role gate but by principal comparison in the service layer: even when OWNER or ADMIN holds both permissions, the same user cannot approve their own request.
Four eyes is enforced in eleven places in the service layer:
| Action | Related permission |
|---|---|
| Manual operation intervention (stuck operation, withdrawal) | wallet:operation:intervene |
| Suspense fund match | wallet:operation:intervene |
| Top-up refund | wallet:operation:intervene |
| Releasing a cash-out hold | wallet:operation:intervene |
| Bulk payout approval | wallet:bulk:approve |
| Fee schedule version approval | wallet:fee:manage |
| Commission schedule version approval | wallet:fee:manage |
| Campaign version approval | wallet:campaign:manage |
| Sponsor policy version approval | wallet:sponsor-policy:approve |
| QR producer-code approval | wallet:sponsor-policy:approve |
| KYC level change | request wallet:enduser:kyc-override, approval wallet:enduser:kyc-approve |
| Legal hold release | request wallet:legal-hold:manage, approval wallet:legal-hold:approve |
The first four rows, the KYC change and the legal hold release run as stored intervention requests: one operator opens a request and another person approves it on the Four-Eyes Approvals screen; the requester and the approver are taken from their panel sessions. Details: Four-eyes requests.
Note that four eyes does not always pair with a separate "approve" permission. For campaigns and fee schedules the preparer and the approver hold the same permission code; what keeps the rule standing is not the permission but the principal comparison in the service layer. You are still expected to hand those roles to different people operationally.
Step-up verification
Some actions require step-up verification on top of the panel session. This stops a hijacked operator session from moving money on its own.
Versioning and the approval chain
Configuration that changes money behaviour — fees, commission, campaigns — is never edited in place; it is versioned:
Past operations remain traceable to their own version. When a report shows an unexpected fee, the operation's scheduleVersionId tells you which version was in force at the time.
Sections
When delegating permissions
- Give maker and checker to different people.
bulk:createandbulk:approveare separate codes — put them in separate roles. Campaigns and fee schedules have no separate code; there you draw the line by giving the same code to two different people. - Keep
operation:intervenenarrow. It is the authority to touch funds in suspense — and it is also the second eye of the four-eyes check. - Separate
sponsor-policy:managefromsponsor-policy:approve. Bank integration and provider policy changes affect every money flow;config:manageonly opens agent definitions. - Keep
terminal:manageaway from field staff. It is the authority to issue and rotate credentials;terminal:readis enough in the field. - Give
enduser:kyc-overrideandenduser:kyc-approveto different people. One requests the change, the other approves it;enduser:managecarries neither. The same applies tolegal-hold:manageandlegal-hold:approve. - Define read-only roles. Most support work is served by the
*:readcodes (program,enduser,operation,loyalty,qr,terminal,card,cashout,report).