Skip to content

Admin panel API ​

Endpoints exposed by admin-backend/mono-backend (Express) behind the admin panel. Paths are written from their mount point; prepend /api in local development. See conventions.

Wallets ​

Mounted at /wallets (routes/WalletRoutes.js → controllers/WalletController.js).

MethodPathPurpose
GET/wallets/:adminIdList all fiat wallets
GET/wallets/all/:adminIdList all category wallets
GET/wallets/bonus/:adminIdList all bonus wallets
PUT/wallets/:walletId/deposit/:adminIdManually credit a wallet
PUT/wallets/:walletId/withdraw/:adminIdManually debit a wallet
PUT/wallets/:walletId/bonus/:adminIdCredit a bonus wallet
POST/wallets/add/:adminIdCreate a wallet

Credit a wallet (manual top-up) ​

PUT /wallets/:walletId/deposit/:adminId — WalletController.deposit.

Request body:

FieldTypeNotes
amountnumberRequired, positive
methodstringfiat | correction | bonus — this is the operator's choice
typestringSent as "Admin" by the panel; stored as the transaction's provider
notestringOptional internal note
idempotency_keystring (UUID)De-duplication

Behaviour:

  • The wallet is credited immediately and a DepositTransaction is written with status: "success", confirmed_at: now, and createdBy resolved from adminId.
  • The stored method is not the same string you send. The controller maps it: correction → "correction", bonus → "bonus", anything else (i.e. fiat) → "cash". The provider field is set to type ("Admin").
  • method === "bonus" sets an internal isBonus flag: the credit is excluded from deposit totals, the Customer.io deposit event, affiliate deposit events, referral FTD and dashboard deposit metrics.
  • A fiat credit is the only one that behaves as a real deposit — it feeds metrics, affiliate attribution and deposit-bonus evaluation. See Crediting and debiting a player.

Responses: 404 wallet not found; 200 with the wallet and transaction.

Permission (panel): players.list.detail.payment.deposit.create.

Debit a wallet (manual withdrawal) ​

PUT /wallets/:walletId/withdraw/:adminId — WalletController.withdrawal.

Request body: same shape as credit, but method is fiat | correction only.

Behaviour:

  • Refuses with 400 Insufficient funds if the wallet total is below the amount — you cannot go negative.
  • Refuses with 409 if the idempotency_key was already used, returning the existing transaction.
  • On success the wallet is debited and a WithdrawalTransaction is written with status: "success", isApproved: true, approved.approved_by: adminId, and retry_count: 5.
  • Stored method: correction → "correction", otherwise → "cash". provider is set to type. addressData is written with null bank fields (there is no payout destination).

Permission (panel): players.list.detail.payment.withdrawal.create.

Wallet transactions ​

Mounted at /wallet-transactions (routes/walletTransactionsRoutes.js). Read-only history and listing, all GET.

PathPurpose
/wallet-transactions/:adminIdAll transactions
/wallet-transactions/deposit/:userId/:adminIdA player's deposits
/wallet-transactions/general-deposits/:adminIdDeposits across players (filter by provider, e.g. manual_bank)
/wallet-transactions/general-withdrawals/:adminIdWithdrawals across players
/wallet-transactions/withdraw-bank-accounts/:adminIdSaved player bank accounts
/wallet-transactions/:walletId/:adminIdOne wallet's transactions
/wallet-transactions/:walletId/all-transactions/:adminIdOne wallet, all transaction types
/wallet-transactions/:walletId/all-transactions-with-casino/:adminIdAs above, including casino play

Withdrawal review ​

Mounted at /withdrawal-transactions (routes/withdrawalTransactionRoutes.js → controllers/withdrawalTransaction.js). This is the queue for player-requested withdrawals.

MethodPathPurpose
GET/withdrawal-transactions/unapproved/:adminIdThe review queue (filtered)
GET/withdrawal-transactions/:walletId/:adminIdOne wallet's withdrawal history
GET/withdrawal-transactions/by-user/:playerId/:adminIdA player's withdrawals (paginated, exportable)
POST/withdrawal-transactions/approve/:transactionId/:adminIdApprove and pay out
PUT/withdrawal-transactions/reject/:transactionId/:adminIdReject and refund
PUT/withdrawal-transactions/approve/retry/:transactionId/:adminIdRetry a failed payout

:transactionId here is the readable tx_id, not the Mongo _id.

The review queue ​

GET /withdrawal-transactions/unapproved/:adminId returns withdrawals that are not settled (pending, plus recent error/rejected). Query filters:

FilterValues
statepending | success | error | rejected
providerCase-insensitive. AlphaPo matches that gateway; Admin (aliases by_admin, offline, manual) matches manual admin adjustments; gateway excludes manual adjustments
paymentSystemNameProvider name (older alias for provider)
paymentSystemIdExternal payment-system transaction id
currencyCurrency code, e.g. EUR
isVerifiedPlayeryes | no
playerId / usernameTarget one player
date rangesrequestStartDate/requestEndDate, updatedStartDate/updatedEndDate, paidStartDate/paidEndDate

Approve ​

POST /withdrawal-transactions/approve/:transactionId/:adminId. Optional body { note }; for manual bank withdrawals a bank_reference (the UTR / transfer reference) is required and is forwarded to the bank payment step. Only a pending transaction can be approved; anything else returns 400. On success isApproved and approved.* are set and the provider is asked to execute the payout.

Reject ​

PUT /withdrawal-transactions/reject/:transactionId/:adminId. Required body:

FieldPurpose
agentNoteInternal note, agents only
playerMessageThe message shown to the player

Only a pending transaction can be rejected. The handler sets status: "rejected", refunds the held amount to the wallet, records rejection.reject_reason_code: "ADMIN_REJECTED", creates a PlayerNotification with playerMessage, and fires a withdrawal_rejected event. Because the refund is automatic, do not credit the player again. See Reviewing withdrawals.

Retry ​

PUT /withdrawal-transactions/approve/retry/:transactionId/:adminId. Only a transaction in error status can be retried, and only within its retry_count (default 5); otherwise 400.

Manual bank ​

Mounted at /bank-payment (routes/bankPaymentRoutes.js → controllers/bankPaymentController.js). Manages the brand bank accounts players pay into, and receives the approve/reject/refund callbacks. Every route is permissioned.

MethodPathPermission
POST/bank-payment/accountsmanagement.payment.manualBank.create
GET/bank-payment/accountsmanagement.payment.manualBank.view
PUT/bank-payment/accounts/:idmanagement.payment.manualBank.edit
PATCH/bank-payment/accounts/:id/statusmanagement.payment.manualBank.edit
DELETE/bank-payment/accounts/:idmanagement.payment.manualBank.delete
POST/bank-payment/callbackmanagement.payment.manualBank.edit
POST/bank-payment/withdrawal/callbackmanagement.payment.manualBank.edit

Create / update an account ​

Body for POST /bank-payment/accounts (create requires all core fields; update makes them optional):

FieldRequired on createNotes
bank_nameYes
account_numberYesStored encrypted
account_holder_nameYesStored encrypted
ifsc_codeYesStored encrypted
currencyYesUppercased
deposit_min_amount / deposit_max_amountNomax ≥ min enforced
withdrawal_min_amount / withdrawal_max_amountNomax ≥ min enforced
instructionsNoShown to the player
orderNoDisplay order
isActiveNo

DELETE is a soft delete (isDeleted: true, isActive: false) — the record is kept for the history of past transfers.

Deposit callback ​

POST /bank-payment/callback — processDepositCallback. Body: transaction_id, status, and depending on status: amount + bank_reference (for success), reason (for failed/refunded), and optional approved_by / rejected_by / refunded_by (auto-filled if omitted). This is what approve / reject / refund on a manual bank deposit resolve to.

Withdrawal callback ​

POST /bank-payment/withdrawal/callback — processWithdrawalCallback. Body: transaction_id, status, plus bank_reference (success) or reason (failed), and optional actor fields.

Payment settings ​

Mounted at /payment-settings (routes/paymentSettingRoutes.js). The brand-wide master switches — a singleton document keyed global.

MethodPathPermission
GET/payment-settings/management.payment.view
PUT/payment-settings/management.payment.edit

PUT body (all optional, partial updates allowed):

deposit.cryptoEnabled          boolean
deposit.localCurrencyEnabled   boolean
deposit.manualBankEnabled      boolean
withdraw.cryptoEnabled         boolean
withdraw.localCurrencyEnabled  boolean

These map to the player-app flags enableCryptoDeposit, enableLocalCurrencyDeposit, enableManualBankDeposit, allowCryptoWithdraw, enableLocalCurrencyWithdraw.

Payment methods catalogue ​

Mounted at /payment-methods (routes/paymentMethodRoutes.js). The catalogue of methods shown to players.

MethodPathPermission
GET/payment-methods/management.payment.view
POST/payment-methods/syncmanagement.payment.create
PATCH/payment-methods/reordermanagement.payment.edit
PATCH/payment-methods/:id/statusmanagement.payment.edit

sync refreshes the canonical catalogue into the DB, preserving admin order and enabled state; :id/status toggles one entry with { isActive: boolean }.

Per-player payment blocks ​

A single player can be blocked from depositing or withdrawing via Player.restrictions.payment.deposit and .withdrawal (booleans, default false). There are also account-level PUT /players/:id/block/:adminId and /players/:id/unblock/:adminId endpoints.

Not fully traced

The exact endpoint that toggles restrictions.payment.deposit / .withdrawal specifically (versus the whole-account block above) was not pinned down in this pass. The field on the Player model is confirmed; the setter route is not. Confirm in the code before integrating.

Internal documentation. Every page states what has been verified and what has not.