FiveM script documentation
Advanced IDs
Permanent employee-issued ID cards and licenses with real photos, an ox_inventory wallet container, a visual card designer, Records Office NPC, and 25 configurable card types.
Overview
Authorized employees issue permanent ID cards with a real photo of the recipient. Cards live in a 6-slot wallet container (ox_inventory), persist in MySQL with a unique serial, and are shown to nearby players with a 3D card prop — including through vehicle windows. Includes 25 built-in card types, a visual card designer, a Records Office NPC for self-service purchases and reissues, and a separate forged-documents flow.
Installation
Install the dependencies first, keep the resource folder named exactly iconix-advancedids, and start everything in the right order.
- Install and start
ox_lib,oxmysqlandscreenshot-basic, plus your framework and inventory. All three are hard dependencies. - Keep the folder name exactly
iconix-advancedids— the supplied item definitions call exports under that name. - Register the inventory items from the
install/folder (see the next section) — these files are merge templates, do not ensure them. - Import
install.sqlonce, or leave AutoCreate enabled and grant theoxmysqlaccount CREATE TABLE for first start. Manual import is preferred on production databases. - Grant issuer access: the government job (grade 0+) or the ACE
iconix-advancedids.issue(see Permissions). - Order your
server.cfgas shown below, then run the two-player test checklist before going live.
ensure oxmysql
ensure ox_lib
ensure screenshot-basic
ensure your_framework
ensure your_inventory
ensure iconix-advancedidsNote
Framework and inventory are auto-detected by default (Config.Framework / Config.Inventory = 'auto'). Set them explicitly if compatibility shims confuse detection.
Note
Native ESX inventory and Qbox without ox_inventory cannot receive permanent employee-issued cards — use ox_inventory with those frameworks.
Inventory items
Merge the supplied item definitions into your inventory before first start — the wallet and every card type are items.
ox_inventory: mergeinstall/ox_inventory_items.luaintoox_inventory/data/items.lua(wallet + card types,stack = false).qb-inventory: mergeinstall/qbcore_items.luaintoQBShared.Items(unique = true) and copy the item images into your inventory image folder.- Restart the FULL server after changing
ox_inventoryitems — restarting only this resource does not rebuild the item registry.
Note
If cards stack or the wallet is never created, the item definitions were not merged correctly.
Permissions
Issuing is granted by job name + minimum grade or by ACE; the card designer and unrestricted checks are admin-gated.
add_ace group.idissuer iconix-advancedids.issue allow
add_principal identifier.license:YOUR_LICENSE group.idissuer
add_ace group.admin iconix-advancedids.admin allow
add_ace group.admin iconix-advancedids.design allowNote
Defaults: the government job (grade 0+) can issue; QBCore/Qbox god + admin and ESX superadmin + admin get unrestricted /checkid and the designer.
Note
Police, sheriff and ambulance jobs can /checkid nearby players.
Commands
All actions are command- or item-driven; every command name is configurable via Config.Commands.
/issueid [player id] [card type]issue a permanent card as an authorized employee; photographs the recipient./idcard [type] [serial]view one of your own cards./showid [type] [serial]present a card to nearby players with the 3D prop./checkid [player id]inspect a nearby player's card (authorized jobs; admins unrestricted)./idcardsopen the owned-cards menu./idadminopen the visual card designer (admin/ACE only).
Key configuration
config.lua stays editable (escrow-ignored). The options server owners most often change:
Config.IssuerNamethe issuing authority printed on cards.Config.CardTypes25 built-in types (identity, license and badge templates); add new types with a config entry plus an item definition.Config.EmployeeIssuingissuer jobs/ACEs, 3 m proximity, 30 s photo token, per-type allowlist.Config.Walletwallet item, 6 slots; issuance fails and rolls back rather than dropping cards loose (FallbackToPlayer = false).Config.Issuingthe Records Office NPC: location, prices, payment account, blip and targeting.Config.Localeen,es,fr,de,pt,nlortr.
Developer API
Server and client exports for integrating your own resources — issue, remove and check cards, read records, and react to issuance events. Server exports must be called server-side.
Note
Card types are the keys of Config.CardTypes: id_card, driver_license, weapon_license, police_badge, ems_badge, and the other built-in or custom entries.
Issuing cards
issueCardToPlayer(source, cardType, options)give a card item.options:metadata(identity overrides),count,show/showNearby(present the card right after issuing). Returns{ ok, cardType, itemName, count, metadata }on success or{ ok = false, code, message }. Alias:giveCardToPlayer.giveCardItem(source, cardType, metadata, count)positional variant of the same operation. Aliases:giveCard,issueCard.issueOfficialCard(source, cardType, { issuerSource })run the full employee flow including the recipient photo; returns{ ok, pending = true, token }. Alias:issueOfficialCardToPlayer.startEmployeeIssuance(issuer, recipient, cardType)the lower-level equivalent of the employee flow.getCardMetadata(source, cardType, metadata)build inventory item metadata for custom flows.getOfficialCardMetadata(source, cardType, metadata)is the official (non-forged) variant.
Checks and removal
hasCard(source, cardType)true when the player carries the card item. Alias:hasCardItem.hasLicense(source, licenseName)check one entry of the player's framework license list.getLicenses(source)the full license list as{ list, map }.removeCardFromPlayer(source, cardType, count)remove cards and fire the removal event. Lower-level:removeCardItem/removeCard.
Card records
getCardRecord(serial)one persisted card row by serial.getPlayerCardRecords(source)all persisted cards owned by the player.setCardStatus(serial, status)set'active','revoked'or'replaced'.validateCardMetadata(metadata)hydrate and validate card metadata against the database.
Important
Records are server-only and include the portrait photo — never forward them to clients.
Introspection
getCardTypes()every configured card type with label, item name and feature flags.getCardConfig(cardType)the resolved config entry for one card type.isCardTypeConfigured(cardType)whether a card type exists. Alias:isCardConfigured.getCardItemName(cardType)the inventory item name behind a card type. Alias:getItemName.getBridgeStatus()reports the detected framework, inventory and card access mode.
Presenting cards
viewCard(source, cardType, serial)show a player their own card. Server-side.showCardToNearby(source, cardType, serial)present a card to nearby players with the 3D prop. Aliases:showCard,showNearbyId.showIdCard(cardType, serial)client export: show your own card.showNearbyId(cardType, serial)client export: present to nearby players.openIdCardMenu()client export: open the owned-cards menu. Alias:openMenu.
Events
iconix-advancedids:cardIssuedfires server-side with the result table ({ source, cardType, itemName, count, ... }) for every issuance, including the built-in commands.iconix-advancedids:cardRemovedfires server-side with the same shape for every removal.
Example
A minimal server-side integration: issue a card, check possession, and listen for issuance.
-- server-side
local ids = exports['iconix-advancedids']
local result = ids:issueCardToPlayer(source, 'driver_license', {
show = true -- present the card right after issuing
})
if not result.ok then
print(result.code, result.message)
end
if ids:hasCard(source, 'weapon_license') then
-- player carries a weapon license card
end
AddEventHandler('iconix-advancedids:cardIssued', function(card)
print(('card %s issued to %s'):format(card.cardType, card.source))
end)Testing checklist
Run the two-player verification from the bundled installation guide before production.
- As an authorized employee, run
/issueidon a second player — only the recipient should enter the portrait scene. - Confirm the card lands in the wallet (
ox_inventory) or personal inventory (qb-inventory) and the hover shows exactly seven fields. - Check
/idcardshows the recipient's photo and a row exists iniconix_advancedids_cards. - Reconnect and restart the server — the photo and card must survive both.
- Confirm an unauthorized player's
/issueidis rejected.
Important
The cards table stores identifiers, identity data and facial photos — treat it as sensitive personal data: restrict database access and protect backups.
FAQ
Common questions
Why did the card go to personal inventory instead of the wallet?
Expected on qb-inventory, which has no nested wallet container. On ox_inventory, make sure the wallet item is registered and has free slot space — issuance fails and rolls back rather than dropping cards loose.
Why is issuance rejected on native ESX or Qbox without ox_inventory?
Intentional: those inventories cannot guarantee the unique card serial stays attached to the delivered item. Use ox_inventory with ESX or Qbox for permanent employee issuance.
Why do my cards stack?
The item definitions were not merged correctly: ox_inventory needs stack = false and qb-inventory needs unique = true. Restart the full server after editing ox_inventory items.
Why does /issueid say I'm not authorized?
Authorization is an exact job name + minimum grade, or one of the configured ACEs. There is no built-in on-duty check — the job name must match exactly.
Why does the photo request expire or fail?
screenshot-basic must be started and named exactly as configured. Keep the JPEG under 1 MB and raise the 30-second token TTL for slow clients.
Why does a transferred card still show the original owner's photo?
By design: a card permanently keeps the photo, name and ID captured at issuance — possession never rewrites the subject. Reissue at the Records Office to update a portrait for future cards.
Ready to install Advanced IDs?
Review the installation checklist, test on staging, then purchase or open a support ticket if your framework stack needs confirmation.
