Wallet API
Developer reference for the Wallet app. Server exports let another resource read a player’s cards, show one to a nearby player, issue and revoke membership cards and set the ID photo. Below the exports: the callbacks the phone itself uses, the two client events, the card schema and the Events app callbacks.Three ways to get a card into a player’s wallet from your own resource:
- A condition card in
Config.Wallet.Cards— give an item, a license or a job grade and the card appears on the next open. No code. issueWalletCard— a membership card with label, business, colour and expiry, for online and offline players.- Code inside the
roadphoneresource (server/serverAPI/*.lua, addons) may call the global functions directly.
Return shape
Write exports return a table:Reading
getWalletCards
Every card of an online player, built live from the framework and the wallet tables.number
required
The player’s server ID.
table
Array of card objects. Empty when the player is offline or has no identifier.
getWalletCard
One card by id.number
required
The player’s server ID.
string
required
'id', 'license:<id>', 'job', 'gang', 'custom:<id>', 'member:<row id>' or 'ticket:<row id>'.table | nil
The card object, or
nil when the player does not hold it.hasWalletCard
Does the player hold this card right now? The cheapest way to gate something on a license, a pass or a job card.number
required
The player’s server ID.
string
required
A card id, see
getWalletCard.boolean
true when the card exists for the player at this moment.getWalletMemberships
Active membership cards (rows ofroadshop_wallet_cards that are not revoked), newest first. Expired cards are included with valid = false.
number | string
required
A server ID (online player) or an identifier string (the player may be offline).
string
Only cards issued under this business name. Omit for all.
table
Membership cards
issueWalletCard
Issue a membership card. The holder gets a notification and their wallet refreshes while they are online; an offline player finds the card on the next open.number | string
required
A server ID (online player) or an identifier string. The identifier must be the one RoadPhone stores for the character:
xPlayer.identifier on ESX, citizenid on QBCore / Qbox.table
required
table
{ ok = true, id = number, expiresAt = number | nil } or { ok = false, error = string }. Keep id — it is what revokeWalletCard needs.revokeWalletCard
Revoke a membership card. The row stays for the records (revoked = 1); the card leaves the holder’s wallet immediately when they are online.
number
required
The
id returned by issueWalletCard or listed by getWalletMemberships.table
{ ok = true, id = number, identifier = string } or { ok = false, error = 'not_found' } (unknown id or already revoked).Showing and photos
showWalletCard
Show one of a player’s cards to another player nearby — the same flow as the Show button, without the per-player rate limit. Use it for scripted ID checks.number
required
Server ID of the card holder.
number
required
Server ID of the receiver. Must be within
Config.Wallet.ShowRadius and in the same routing bucket.string
required
A card id the holder owns right now.
table
table
{ ok = true, showId = number, duration = number } or { ok = false, error = string }.setWalletPhoto
Set or clear the ID photo of a character — for example from a character creator or a mugshot system.number | string
required
A server ID or an identifier string.
string | nil
required
An
http(s):// URL of at most 255 characters, or nil to remove the photo (the app then offers Take photo again).table
{ ok = true, photo = string | nil } or { ok = false, error = string }.The export trusts the URL you pass. Only the in-app capture is restricted to the upload host allow-list, because that URL comes from the client.
refreshWallet
Tell an online player’s phone to reload its cards. Needed only after you changed something the Wallet reads that is not covered by the exports above — for example aConfig.Wallet.Cards condition that flipped through your own inventory code.
number
required
The player’s server ID.
boolean
true when the player is online.Callbacks
Registered inserver/wallet.lua. The phone calls them through the NUI proxies listed further down; the server never trusts a player id or identifier from the client — every distance is measured server-side and every identity is re-read from the framework.
Every failure answers
{ ok = false, reason = … }:
Client events
Both are networked client events (
RegisterNetEvent). refreshWallet triggers the second one for you; do not trigger roadphone:wallet:incoming yourself — the phone treats its payload as an already-verified card, the checks live in showWalletCard.
NUI callbacks
Registered inclient/wallet.lua, for reference when you read the phone UI or write a custom app that reuses the flow.
Card schema
Every card — from the exports, fromgetCards and in roadphone:wallet:incoming — has this shape:
meta per type:
Field
kind values: date, datetime (unix seconds), dob (YYYY-MM-DD), sex (m / f), height (centimetres); without kind the value is shown as text.
Global functions (inside the roadphone resource)
Plain globals of server/wallet.lua — the same functions the exports wrap. They are not exports; use them from server/serverAPI/*.lua, addons or other scripts that run inside the resource. They return reason instead of error on failure.
The boss actions of the Events app (Business tab) go through
WalletIssueCard and WalletRevokeCard as well, so a card issued by a boss and a card issued by your resource behave the same.
Events app callbacks
The Events app supplies the tickets and membership cards the Wallet shows. Registered inserver/events.lua; every one answers { ok = false, reason = … } on failure.
roadphone:events:changed (Server → Client) tells the phone to reload the Events app.
Rate limits
Only the phone’s own callbacks are rate-limited; the exports are not.Related Resources
Wallet
Configuration, card types, player flow and troubleshooting
Export Index
Every client and server export of RoadPhone Pro