Portal — Account & Operations
- Base path
/api/portal/v1/wallet/me- Identity
- Publishable key (
pk_live_…) → OTP → customer session. The session belongs to the end user, not to the merchant, and reaches only that user's own data. - Authorization
- The session itself is the authorization; a user reaches only their own record.Step-up: for money-out actions the session alone is not enough; an OTP code or a trusted action token is required.
- Cross-surface
- This surface is for the end user; your merchant server does not call it. For the server-side counterpart see the s2s API.
These endpoints live under /api/portal/v1/wallet/me/* and reach only the session owner's own data. The user identity is not carried in the request — it is resolved from the session.
Do not expect an endUserId-style field in the request body. Portal endpoints take the target user from the session, which makes it structurally impossible for one user to target another's wallet.
Account and balance
GET /me # profile
GET /me/balances # balances of all accounts
GET /me/wallets # wallets
POST /me/wallets/{id}/accounts # new currency account { currency }
GET /me/limits # limit status (filter by operationType, currency)
GET /me/kyc-level # level and unlocked capabilitiesTop-up
POST /me/topups/card # { creditWalletAccountId, amount, currency, returnUrl?, saved…Token? }
GET /me/topups/{id}
GET /me/deposit-instructions
POST /me/deposit-instructions # { walletAccountId, currency? }Card top-up returns hosted form content or a 3D Secure redirect; see Top-up.
The deposit-instructions endpoints require a connected bank integration. Without one, instructions cannot be issued. Status: Roadmap.
Transfers
POST /me/transfers/w2w/quote
POST /me/transfers/w2w
POST /me/transfers/w2w/{id}/completeThe same three-step pattern applies to IBAN transfers (/me/transfers/w2iban/*) — see Transfers.
Withdrawals
POST /me/withdrawals/bank/quote
POST /me/withdrawals/bank
POST /me/withdrawals/bank/{id}/complete
GET /me/withdrawals/{id}Requires a connected bank integration. Status: Roadmap.
Payments
POST /me/payment-code # generate a single-use code to show at the till
DELETE /me/payment-code # revoke it
POST /me/payments/{requestId}/approve
GET /me/payments/{id}QR
POST /me/qr # generate a collection code
GET /me/qr # my codes
GET /me/qr/{id}
GET /me/qr/{id}/image
DELETE /me/qr/{id} # revoke
POST /me/qr/parse # parse a scanned code
POST /me/qr/pay # pay by QR
POST /me/qr/pay/{qrId}/completeSaved contacts
GET /me/contacts
POST /me/contacts # { alias, contactPhone? | contactWalletNo? }
PUT /me/contacts/{id}
DELETE /me/contacts/{id}
POST /contacts/phonebook-check # { phone? | walletNo? }phonebook-check exists to show which of the user's phone contacts have a wallet.
Do contact matching with the user's explicit consent and never upload the whole phone book at once. Read responses return phone numbers masked.
Authorizations (mandates)
A user grants a business the right to collect from them on a recurring basis:
GET /me/authorizations/consent-text # the consent text to display
GET /me/authorizations # granted authorizations
POST /me/authorizations # { businessEndUserId? | businessWalletNo?, channel?, otpDestination, locale? }
POST /me/authorizations/{id}/confirm # { otpCode }
DELETE /me/authorizations/{id} # revokeAlways use the consent-text endpoint — the consent text you show must match the authorization's actual scope exactly. Text you author yourself silently becomes wrong when the scope changes.
Give users a list of granted authorizations and one-tap revocation.
Loyalty
GET /me/cashback
GET /me/cashback/eligible
GET /me/loyalty/balance
GET /me/loyalty/history
POST /me/loyalty/redeem # { loyaltyProgramId, walletAccountId, points, idempotencyKey }
GET /me/tier
GET /me/badgesDetails: Loyalty & Cashback.
Invoices and bill pay
GET /me/invoices
GET /me/invoices/{id}
POST /me/invoices/{id}/pay
POST /me/bills/inquire # { billerCode, subscriberNo }
POST /me/bills/pay
GET /me/billsInvoices await release and bill pay awaits a biller integration. Status: Roadmap.
Operations and receipts
GET /me/operations # cursor pagination, status/walletAccountId filters
GET /me/operations/{id}
GET /me/operations/{id}/receipt
GET /me/operations/exportFee quotes
POST /me/fees/quote # { operationType, currency, amount }Call it as the amount is typed and show the user the total.
Common mistakes
| Symptom | Cause | Fix |
|---|---|---|
| Another user's data is not returned | Expected behaviour | The portal returns only own data; use s2s for tenant-wide access |
| Money operations rejected | Missing step-up | Send otpCode / trustedActionToken |
| Consent text does not match scope | You authored your own text | Use the consent-text endpoint |
| Some endpoints never work | That capability's integration is not connected | Roadmap |