Configuration
Navigate to/public/static/config/config.json and locate the AppStore section.
Configuration Properties
Display name of the app
Path to the app icon
Website URL to display (must support iFrame) or a self-hosted HTML file
Unique identifier for your app. Set once and never change it.
Changes header and home button theme
List of jobs that can access this app
List of jobs that cannot access this app
Event configuration with the following properties:
Examples
Website App
Self-Developed App
App Template
Get started quickly with our self-development app template on GitHub
NUI Messaging
Exports
Input Focus Control
Control the NUI focus behavior for the phone:Use
true to enable input focus (keyboard/mouse control) and false to disable it.Overview
RoadPhone exposes a globalwindow.roadphone API that allows developers to build custom applications with full access to phone data, settings, and events.
The API is available globally via
window.roadphone and can be accessed from any iframe-based custom app.Quick Start
App Setup
Run these calls once when your app boots to declare your identity, isolate your data, and verify the phone supports the features you rely on.app.setName(name)
Registers the display name shown in permission and consent dialogs.The human-readable name of your app
app.setNamespace(namespace)
Sets a unique namespace that isolates your app’s stored data from other apps. Set this once and never change it.A unique identifier for your app’s storage
app.getNamespace()
Returns the currently configured namespace.The active storage namespace
minVersion(version)
Validates that the phone meets the minimum required API version. Throws if the installed phone is too old.The minimum semantic version your app requires (e.g.,
"1.3.0")requireFeature(feature)
Ensures a given capability is available before your app uses it. Throws if the feature is missing.The feature key to require (e.g.,
"storage")features
An object describing the API capabilities the current phone exposes. Use it to gracefully degrade when a feature is unavailable.Getter Functions
isDarkMode()
Returns whether dark mode is currently enabled.true if dark mode is enabled, false otherwisegetPhoneNumber()
Returns the current phone number.The player’s phone number (e.g.,
"1234567")getPlayerName()
Returns the player’s character name.The player’s name (e.g.,
"John Doe")getJob()
Returns the player’s current job.The job identifier (e.g.,
"police", "ambulance", "unemployed")getIdentifier()
Returns the player’s unique identifier.The player identifier (format depends on framework)
getBrightness()
Returns the current screen brightness level.Brightness value between
10 and 100isFlightMode()
Returns whether flight mode is enabled.true if flight mode is on, false otherwisegetConfig()
Returns the full phone configuration object.The complete config.json configuration
getLanguage()
Returns the player’s current locale.The active language code (e.g.,
"de_DE", "en_US")Utility Functions
copyToClipboard(text)
Copies text to the clipboard.The text to copy
post(event, data)
Sends data to the Lua backend. Use this to communicate with your server-side scripts.The event name to trigger
Optional data to send with the event
showNotification(options)
Displays a phone notification.Notification configuration object
takePhoto(options)
Opens the phone’s camera and returns the captured media. Resolves once the player confirms or cancels.Capture configuration
The captured photo object (or
null if cancelled)showBottomSheet(options)
Displays a native bottom sheet with grouped, selectable actions and resolves with the player’s choice.Bottom sheet configuration
The selected option (or
null if dismissed)pickEmoji()
Opens the native emoji picker and resolves with the chosen emoji.The selected emoji (or
null if dismissed)Storage
RoadPhone exposes two storage backends scoped to your app’s namespace.Synchronous storage is backed by
localStorage and is fast but local to the device. Metadata storage is asynchronous, server-backed, and persists across character and device changes.Synchronous Storage
Fast, namespace-scoped key/value storage for non-critical data.| Function | Returns | Description |
|---|---|---|
storage.set(key, value) | void | Store a value |
storage.get(key) | any | Read a value |
storage.delete(key) | void | Remove a value |
storage.keys() | string[] | List all stored keys |
storage.clear() | void | Remove everything in the namespace |
Metadata Storage
Asynchronous, persistent storage that survives character and device changes. Requires thestorage.metadata permission.
| Function | Returns | Description |
|---|---|---|
storage.metadata.set(key, value) | Promise<void> | Persist a value |
storage.metadata.get(key) | Promise<any> | Read a persisted value |
storage.metadata.delete(key) | Promise<void> | Remove a persisted value |
Permissions
Sensitive phone data (contacts, messages, bank, alarms) is gated behind a permission system. Request the scopes you need before calling the corresponding APIs — the player is shown a consent dialog.permissions.request(scope)
Requests access to a scope. Resolves totrue if granted; denied requests reject.
The permission scope to request
true if the player granted the permissionpermissions.has(scope)
Checks whether a scope has already been granted.true if the permission is currently grantedpermissions.revoke(scope)
Revokes a previously granted scope.permissions.list()
Returns all permission decisions made for your app.A map of scope strings to their granted/denied state
Available Scopes
| Scope | Grants access to |
|---|---|
contacts.read | Reading the player’s contacts |
messages.read | Reading message threads |
messages.send | Sending messages |
bank.read | Reading balance, IBAN, and accounts |
alarms.read | Reading alarms |
alarms.write | Creating and deleting alarms |
storage.metadata | Persistent metadata storage |
Phone Data APIs
These APIs read and write the player’s phone data and require the matching permission scope. Each method is asynchronous.Contacts
Requirescontacts.read.
Messages
list requires messages.read; send requires messages.send.
Bank
Requiresbank.read.
Alarms
list requires alarms.read; create and delete require alarms.write.
Event System
The API includes a powerful event system that allows your custom app to react to phone state changes in real-time.on(event, callback)
Subscribe to an event.The event name to listen for
Function to call when the event fires
off(event, callback)
Unsubscribe from an event.The event name to unsubscribe from
The same function reference used when subscribing
Available Events
phoneOpened
phoneOpened
Fired when the phone is opened.
phoneClosed
phoneClosed
Fired when the phone is closed.
darkModeChanged
darkModeChanged
Fired when dark mode is toggled.Payload:
boolean - true if dark mode is now enabledbrightnessChanged
brightnessChanged
Fired when screen brightness changes.Payload:
number - Brightness value (10-100)flightModeChanged
flightModeChanged
Fired when flight mode is toggled.Payload:
boolean - true if flight mode is now enabledlanguageChanged
languageChanged
Fired when the player changes the phone language.Payload:
string - The new locale (e.g., "en_US")appOpened
appOpened
Fired when your custom app is opened.
appClosed
appClosed
Fired when your custom app is closed.
incomingCall
incomingCall
Fired when the player receives a call.Payload:
object - Call details (caller number, etc.)callEnded
callEnded
Fired when an active call ends.
notificationReceived
notificationReceived
Fired when the phone receives a notification.Payload:
object - The notification dataSetup
Custom Apps are loaded as external URLs inside an iframe within the phone. To set up your custom app:Create your app
Build your custom app as a standalone HTML page and host it on a web server or locally.
Configure the URL
Open
public/static/config/config.json and find the AppStore section. Set your CustomApp URL:Complete Example
Here’s a complete example of a custom app that displays player information. This app is designed to fit perfectly within the phone’s iframe and usesvh units for proper scaling.
Lua Backend Integration
To handle custom events from your app, register NUI callbacks in your Lua code:API Reference
Core| Function | Returns | Description |
|---|---|---|
isDarkMode() | boolean | Check if dark mode is enabled |
getPhoneNumber() | string | Get the phone number |
getPlayerName() | string | Get the player’s name |
getJob() | string | Get the player’s job |
getIdentifier() | string | Get the player’s identifier |
getLanguage() | string | Get the active locale |
getBrightness() | number | Get brightness (10-100) |
isFlightMode() | boolean | Check if flight mode is on |
getConfig() | object | Get the full config |
copyToClipboard(text) | void | Copy text to clipboard |
post(event, data) | Promise | Send data to Lua backend |
showNotification(opts) | void | Show a notification |
takePhoto(opts) | Promise<object> | Capture a photo/video |
showBottomSheet(opts) | Promise<object> | Show a native action sheet |
pickEmoji() | Promise<string> | Open the emoji picker |
on(event, callback) | void | Subscribe to an event |
off(event, callback) | void | Unsubscribe from an event |
| Function | Returns | Description |
|---|---|---|
app.setName(name) | void | Set the app display name |
app.setNamespace(ns) | void | Set the storage namespace |
app.getNamespace() | string | Get the storage namespace |
minVersion(version) | void | Require a minimum phone version |
requireFeature(feature) | void | Require a capability |
features | object | Available API capabilities |
| Function | Returns | Description |
|---|---|---|
storage.set/get/delete(key, [value]) | any | Synchronous key/value storage |
storage.keys() | string[] | List stored keys |
storage.clear() | void | Clear the namespace |
storage.metadata.set/get/delete(key, [value]) | Promise | Persistent metadata storage |
| Function | Returns | Description |
|---|---|---|
permissions.request(scope) | Promise<boolean> | Request a scope |
permissions.has(scope) | boolean | Check a granted scope |
permissions.revoke(scope) | void | Revoke a scope |
permissions.list() | object | List all decisions |
contacts.list/find/count() | Promise | Read contacts (contacts.read) |
messages.send/list() | Promise | Send/read messages (messages.*) |
bank.getBalance/getIban/getAccounts() | Promise | Read bank data (bank.read) |
alarms.list/create/delete() | Promise | Manage alarms (alarms.*) |
| Event | Payload | Description |
|---|---|---|
phoneOpened | none | Phone was opened |
phoneClosed | none | Phone was closed |
darkModeChanged | boolean | Dark mode toggled |
brightnessChanged | number | Brightness changed |
flightModeChanged | boolean | Flight mode toggled |
languageChanged | string | Language changed |
appOpened | none | Custom app opened |
appClosed | none | Custom app closed |
incomingCall | object | Incoming call received |
callEnded | none | Active call ended |
notificationReceived | object | Notification received |
Version
Current API Version: 1.3.0Access via:
window.roadphone.version