Phone
An iPhone-style smartphone with real calls, texts, socials, email and 20+ apps. One resource, no SQL to import.
Requirements
Required
- qbx_core or qb-core — the bridge detects which you run
- ox_lib
- oxmysql
Optional
- pma-voice — powers call audio. Without it, calls connect but nobody can hear each other.
- screenshot-basic — powers the camera.
- xsound — only the Music app needs it. Everything else works without it.
- ox_inventory is supported but not required.
Installation
- Drop the
XS-Phonefolder into yourresourcesdirectory. - No SQL import needed. Tables create themselves on first start. The file in
sql/is there only if you want to run it yourself. - Add
ensure XS-Phoneto yourserver.cfg, after ox_lib, oxmysql, your framework and pma-voice. - Set up the camera (see below), then restart and open the phone.
Start order matters. XS-Phone has to start after ox_lib, oxmysql, your framework and pma-voice, or calls and callbacks fail on boot.
The phone item
Both frameworks already ship a phone item, and XS-Phone uses it as is — most servers can skip this step. Only add the item if your server doesn't have one, or skip items entirely with Item.enabled = false in the config.
ox_inventory, in data/items.lua:
['phone'] = {
label = 'Phone',
weight = 190,
stack = false,
consume = 0,
},
qb-core, in shared/items.lua:
phone = { name = 'phone', label = 'Phone', weight = 190, type = 'item', image = 'phone.png', unique = true, useable = true, shouldClose = true, description = 'A smartphone' },
Camera
The camera uploads photos to a media host so they can show up in the gallery and on the socials. It uses fivemanage by default.
- Make a free account at fivemanage.com.
- Copy an image API token.
- Paste it into
Config.Phone.Media.apiKey.
That is the whole setup. Until a key is set, the camera says so plainly and the server console prints the reason instead of failing silently.
Business lines
Every business in Config.Phone.Businesses is a real phone line. Calling or texting the number rings a random on-duty worker for that job — no dispatch script needed. If nobody is on duty, there is no answer.
911 and 912 are just business lines with an emergency flag, pointing at your police and ambulance jobs. Change the numbers, labels and jobs to match your server.
Config
Everything lives in config.lua and is commented in plain language. The ones most servers touch:
- Businesses — your job list for the City app and the 911/912 lines.
- AppNames — rename Chirp, Prism, Sparks and the rest if you want your own branding.
- OpenKey — the default is the backtick key.
- Media — your fivemanage key, and which hosts photos may be imported from.
- Garage.table — the vehicles table to read, if yours isn't the default
player_vehicles.
Exports
-- server
exports['XS-Phone']:GetNumber(source)
exports['XS-Phone']:Notify(source, { app = 'mail', title = '...', body = '...' })
exports['XS-Phone']:SendMessage('BANK', number, 'You were paid $2,500.')
exports['XS-Phone']:SendMail(number, { from = 'cityhall@ls.mail', subject = '...', body = '...' })
-- client
exports['XS-Phone']:IsPhoneOpen()
SendMail delivers to whatever mail account is logged in on that player's phone. No account, no delivery — it returns false.
Troubleshooting
"You don't have a phone"
The item is not in your inventory config, or its name does not match Config.Phone.Item.name. Both frameworks ship a phone item that works as is, so most servers can leave this alone, or set Item.enabled to false to skip the item entirely.
Photos won't save
Your fivemanage API key is missing or wrong. Paste an image API token into Config.Phone.Media.apiKey. The server console prints the actual reason when an upload fails.
Calls connect but there is no audio
pma-voice is missing or outdated. Calls route through it, so it has to be started before XS-Phone.
The Garage app is empty
Your server uses a different vehicles table. Point Config.Phone.Garage.table at it. It reads player_vehicles by default and handles builds that store the model as a hash.
The Music app won't play anything
xsound is not installed. Music is the only app that needs it — everything else works without it.
Updating
- Keep a copy of your edited
config.lua. - Replace the resource folder and merge your config back.
- Restart the resource. Any new tables are created automatically.