QB / ESX

Agency-Phone

Modern multi-framework phone for FiveM with auto-detection for QBCore and ESX. Full app suite including Dialer with pma-voice calls, Buzz SMS messaging, Snap in-game camera, Pulse social feed, Postbox mail, Wallet with AgencyPay checkout, Gallery, Contacts, and Settings. Supports programmable notifications with accept/deny buttons and integrated payment flows.

v26.4Paid6 Pages
Agency-Phone

🧩 Build a custom app for Agency-Phone

There are two ways to put an app on the phone. Pick the one that fits you:

MethodBest forWhat you touch
A. SDK (external resource)Vendors and scripts adding an app with their own iconOnly your own resource. Zero edits to agency-phone.
B. Drop-in (inside agency-phone)Server owners adding a native screen inside the phone UIconfig.lua + apps/ (+ html/js for a screen)

If you ship an app to other servers, use Method A. It needs no source from us and keeps working across updates.

A SDK — register an app from your own resource

agency-phone exposes exports that let any resource put an app (with its own icon) on the phone home screen at runtime. Your app's UI lives in your own resource; the phone shows the icon and hands control to you when the user taps it. No edits to agency-phone, no unlocked build.

Minimal example

-- client side of YOUR resource
CreateThread(function()
    Wait(1500) -- let agency-phone boot
    exports['agency-phone']:RegisterApp({
        id        = 'myshop',
        label     = 'My Shop',
        icon      = 'fa-solid fa-cart-shopping', -- FontAwesome 6 class
        -- image  = 'https://cfx-nui-myresource/icon.png', -- or your own image instead
        color     = '#ff9500',
        colorDark = '#e08600',
    })
end)

-- fired when the user taps your icon on the phone
AddEventHandler('agency-phone:client:openApp', function(appId)
    if appId ~= 'myshop' then return end
    exports['agency-phone']:ClosePhone()
    -- open your own NUI here
end)

RegisterApp config

FieldTypeRequiredDescription
idstringyesUnique id, lowercase, no spaces.
labelstringyesName shown under the icon.
iconstringFontAwesome 6 class. Ignored if image is set.
imagestringCustom icon image, e.g. https://cfx-nui-<resource>/icon.png.
color / colorDarkstringGradient behind the icon (hex).
slotnumberHome-screen position. Auto-placed if omitted.

SDK exports (client)

ExportDescription
RegisterApp(config)Add or update your app. Returns true, or false, err.
UnregisterApp(id)Remove your app. Also happens automatically when your resource stops.
GetRegisteredApps()Table of all registered external apps.
ClosePhone()Close the phone UI, e.g. before opening your own NUI.

The tap event

When the user taps your icon, agency-phone fires both of these on the client (use whichever you prefer):

EventArgs
agency-phone:client:openAppappId (filter by your id)
agency-phone:client:openApp:<yourId>none (already scoped to your app)

Add dependency 'agency-phone' to your fxmanifest.lua so the start order is correct.

B Drop-in — a native screen inside the phone

For a screen rendered by the phone itself (not your resource). This edits agency-phone's own files.

StepFileEditable in escrow build?
1. App entry in AgencyConfig.Appsconfig.lua✓ yes
2. RegisterNUICallback logicapps/<id>_client.lua (+ _server.lua)✓ yes
3. Screen <div id="app-<id>">html/index.html✗ encrypted
4. case '<id>': in openApp() + loaderhtml/js/phone.js✗ encrypted

Steps 3 and 4 live in escrow-encrypted files, so a native screen needs a source / unlocked build. If you only have the escrow version, use Method A instead (your screen lives in your own resource). Reference files inside the resource: apps/testapp_client.lua and apps/dispatch_client.lua.

📋 Other phone exports

Client

ExportReturnsDescription
IsPhoneOpen()booleanPhone currently open.
IsPhonePoweredOn()booleanDevice powered on.
HasPhone()booleanPlayer owns a phone item.
HasCarrierContract()booleanActive eSIM / contract.
GetPhoneData()tableSnapshot of phone state.
PhoneNotification(title, text, icon, color, timeout, acceptIcon, denyIcon)voidIn-phone notification.
StartCall(contact)voidCall { name, number }.
StartAgencyPayCheckout(opts)voidAgencyPay checkout (see below).

Server

ExportDescription
SendMail(identifier, mailData)Deliver mail to a player (online or offline).
AddChirp(data)Post a message to the Pulse social feed.

NUI ↔ Lua bridge (Method B)

DirectionJS sideLua side
JS → LuafetchNUI('callbackName', data)RegisterNUICallback('callbackName', fn)
Lua → JSlisten for action in window.onmessageSendNUIMessage({ action = '...' })

💳 AgencyPay checkout

Charge the player's wallet from any resource.

exports['agency-phone']:StartAgencyPayCheckout({
    merchant = 'My Shop', title = 'Agency Pay', subtitle = 'Checkout',
    label = 'Premium Coffee', amount = 24.50,
    icon = 'fa-solid fa-mug-hot', accent = '#ff9f0a',
    clientEvent = 'myshop:client:agencyPayResult',
    serverEvent = 'myshop:server:agencyPayResult',
    metadata = { orderId = 'order_2048' },
})

RegisterNetEvent('myshop:client:agencyPayResult', function(result)
    if result.status == 'paid' then
        -- deliver the goods
    end
end)

The result payload includes status (paid / cancelled / failed), amount, cardId, balance and your metadata.

🐛 Troubleshooting

SymptomFix
Icon doesn't appear (SDK)Update agency-phone to the latest Keymaster build, Wait(1500) before RegisterApp, and add dependency 'agency-phone' to your manifest.
Tapping does nothing (SDK)Your agency-phone:client:openApp handler must match your id exactly (case-sensitive).
Custom image not showingUse a full NUI URL https://cfx-nui-<your-resource>/path/icon.png and list the file in files { } in your manifest.
Icon doesn't appear (drop-in)enabled = true and installed = true in the config entry.

Questions, or need a hand? Join the Agency Scripts Discord.

Need help? Join our Discord community for support!

Join Discord