Only this pageAll pages
Powered by GitBook
Couldn't generate the PDF for 101 pages, generation stopped at 100.
Extend with 50 more pages.
1 of 100

Sonoran Radio

Loading...

Loading...

Tutorials

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Pricing

Loading...

Loading...

Roadmap & Changelog

Loading...

Loading...

Loading...

Developer Documentation

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Getting Started

Get started with Sonoran Radio standalone!

Getting started with Sonoran Radio is fast and free!

You can view our 4-part tutorial series covering installation, configuration, and usage here!

1. Register Your Community:

Register a Community

2. Invite and Manage Users

Invite and Manage Users

3. Installing the In-Game Resource

Installing the In-Game Resource

4. Using the Radio

Usage

In-Game Radio

Learn more about Sonoran Radio's in-game usage!

Dispatch & Admin Panel

Learn more about utilizing Sonoran Radio's dispatch panel.

Usage

Learn how to use Sonoran Radio!

IP Whitelisting

My community wants to whitelist only the Sonoran RADIO IP address to send requests to my FiveM server. How can I do this?

You may whitelist the following IPs:

24.199.66.94
198.199.90.248
34.173.36.190

Last Updated : 8/26/2025

Invite and Manage Users

Learn how to invite and manage users in your Sonoran Radio community!

Automatic Join, Kick, Ban, and Permission Sync

Sonoran CMS allows you to automatically add and manage user permissions with user applications, sync them with Discord roles, and more!

Sonoran CMS

If you are building your own integration, Sonoran Radio also exposes API endpoints to approve members, kick members, ban members, update member display names, and set member permissions.

Users

FiveM Management

All user permission management, including inviting and approving members, can be automated with FiveM ACE permissions.

Configuring ACE Permissions

Manual User Management

Inviting Members

Users will need the Community ID located in the Administrator panel. Communities can also customize this community ID.

Sonoran Radio: Community ID

When logged into Sonoran Radio, they can select the + button in the portal to paste in the Community ID.

When a member joins your community with an invite code, they will be pending until approved.

Users with the Approve Pending Members permission can approve in the Members tab

User permissions can be manually set by clicking the shield icon on a user in the Members tab


Installing the In-Game Resource

Download the App

Download the Sonoran Radio app for Windows, OSX, iOS, and Android!

Website

Windows Desktop

Mac OS Desktop

Register a Community

Create your own FREE community on Sonoran Radio!

Creating a Community

  1. Navigate to SonoranRadio.com and login

  2. In your Sonoran Radio Portal, click the green plus button

  3. Click Begin Your Journey! to create a new community

  4. Click Standalone (Alpha) mode at the top

  5. Enter a good nickname, and click Register Server


Now it's time to invite your community members!

Tablet

View the dispatcher panel via in-game tablet!

Using the In-Game Tablet

The in-game tablet allows users to access the dispatch panel.

Via Command

Users in-game can use the /radio tablet to open the tablet. The tablet will display the dispatch panel, also available on the web and desktop applications.

Via Keybind

Users in-game can also specify a custom keybind to open and close the tablet.

Default User Settings

Configure the default settings for your community. Users can personalize their own preferences, but these will serve as the starting defaults.

The radio settings menu offers vast preference options for sound effects, text-to-speech, automatic gain control, and more. Some communities may wish to enable or disable specific settings for users by default.

In the Admin panel, select Customization > Default Settings

Here you can enable, disable, and configure default settings for all users in your community.

Users can still customize their own setting preferences by selecting the gear icon in the dispatch or radio view to override the community defaults.

Under the Advanced

Custom Domain / Vanity URL

Have Sonoran Radio on your own custom domain!

Each community gets their own free vanity URL, visible in the Custom Domain section of your community's customization tab

If your community is Plus or Pro, your vanity URL will match your community's custom ID

To customize your community ID, navigate to Customize > Info > Community ID. Enter in a new, custom community ID.

Transfer or Delete a Community

View more information on transferring or removing your Sonoran Radio community.

To transfer the community ownership to another user, navigate to the Administration > Transfer Community

In the popup, select the user you wish to transfer the community to and enter the community name in the confirmation box.

After selecting the new owner, a confirmation email will be sent. Check your inbox to complete the transfer.

To permanently delete a Sonoran Radio community, navigate to Administration > Delete Community

Client Debug Mode

Learn more about enabling the client-sided debug mode.

At times, our support team may request debug logs from your local radio. This contains important information from the radio webpage (running inside the in-game radio in an iframe).

  1. Select the settings gear and click on the header of the settings panel seven times.

  2. At the bottom, a red section labeled Debug Mode will appear, indicating that it has been correctly enabled.

Multi-Server

Using multiple identical servers for overflow? Multi-server lets each server run independently while sharing the same channel setup, keeping communications separate and organized.

Many communities run multiple game servers to handle user overflow. Sonoran Radio's multi-server support keeps players separated by server while sharing the same channel configurations and customizations across all servers.

The FiveM in-game resource will automatically generate a unique server each for every FiveM server it is ran on.

Communities not using the FiveM resource can manually add and remove servers in the admin under Customization > Info > Community Servers .

The FiveM in-game resource will automatically select and connect users to the proper server.

iOS App Store

Purchase

Google Play Store

Purchase

Visit
Download
Download

Integrations

Learn more about our official integrations with Sonoran Radio!

tab, users can select
Reset Settings
to reset to the community defined defaults.
Sonoran Radio: Reset Settings

Some FiveM specific settings can be customized in the resource configuration.

The server defaults for push-to-talk, AI callouts, etc. can be configured in the config's keybinds property.

The server default for radio escape key handling can be configured in the config's defaultEscapeMode property.

Default User Settings

Setting Defaults

Users: Reset to Default

Sonoran Radio: Default Community Settings

FiveM Default Settings

Keybinds

ESC Behavior

Enter the domain you want Sonoran Radio on, this can be either a root domain (like sonoranroleplay.com) or a subdomain (like radio.sonoranroleplay.com)

Add the shown DNS records shown to you in your domain's administrative panel. If you are using Cloudflare, be sure to disable the proxy!

Having trouble? Contact your domain name provider.

Press Save Custom Domain in the panel to save your new custom domain. If successful, your new custom domain will be visible above your vanity URL

Vanity URLs

Customizing Your Community ID

Custom Community IDs require a plus subscription or higher. Learn more about our paid plans!

Custom Domain

Custom Domain requires a pro subscription. Learn more about our paid plans!

1. Enter your Custom Domain

2. Configure DNS Records for you Domain

3. Save the Custom Domain

Note: Only the community owner can delete the community.

Sonoran Radio: Delete Community

Transferring a Community

1. Select the New Owner

2. Email Confirmation

Delete Community

Sonooran Radio: Transfer Community
Sonoran Radio: Transfer Community
Sonoran Radio: Confirm Transfer

Restart the radio (power on/off) to start capturing fresh logs. Once you have re-created the issue, continue on with sending the logs as described below.

Sonoran Radio: Debug Mode

In some cases, you may be asked to add a timestamp flag when an issue occurs. Once the particular issue occurs press the Flag Timestamp button in the debug menu, enter in a brief description, and press Ok.

This will manually add a debug log to help our developers narrow down the time window.

Flag Timestamp
  1. Open your in-game console by pressing F8

  2. Select Open Log

  3. Send the latest file located at C:\Users\USER\AppData\Local\FiveM\FiveM.app\logs

FiveM: Open Client Log
FiveM: Client Log

FiveM Client Debug logs

Toggle Debug Mode On

Flagging Timestamps

Sending Client Debug logs

The dispatch portal and radios outside of FiveM will contain a drop-down menu prior to connecting.
Sonoran Radio: Server Selection

Configuring Servers

Multiple servers are only available with the Pro version!

Learn more about our paid subscription plans.

Configuring for FiveM

Manual Configuration (Non-FiveM)

Selecting Your Server

FiveM Server Selection

Non-FiveM Server Selection

Sonoran Radio: Multiple Servers

Approving Members

Manage User Permissions

Next Steps

Installing the In-Game Resource
Sonoran Radio: Join Community
Sonoran Radio - Approve Members

Next Steps

Invite and Manage Users
Sonoran Radio - Create a New Community

Background Audio Injection

Background audio injection blends in-game sounds—like sirens, helicopter rotors, boat engines, and gunshots—into your microphone output.

Sonoran Radio - Background Noise Injection

Example Video

The example video shows audio snippets with:

  • Digital Effect: Sirens in Background

  • Vocoder: Helicopter Rotors

Using Background Audio Injection

What is Background Audio Injection?

Background audio injection blends in-game sounds—like sirens, helicopter rotors, boat engines, and gunshots—into your microphone output.

If you're responding with sirens active, others on the radio will hear them in the background of your voice transmissions. The sound effect volume level is determined by the distance to the source.

To enable this feature:

  1. Ensure your community is on the Pro version of Sonoran Radio.

  2. Set enableBackgroundAudio to true in your file.

Background audio sounds can be customized in the event of a specific siren type, gunshot sound, etc.

Communities can override the sound effects with custom files in the admin .

If sirens are not playing in the background of your microphone (when next to a vehicle with one on), follow these troubleshooting steps.

Sonoran Radio integrates with Luxart Vehicle Control to determine when sirens are activated.

  1. Ensure you have configured the Config.luxartResourceName configuration option to match the resource name of your installed Luxart Vehicle Control resource.

  2. Ensure you are on the latest version of Luxart Vehicle Control, as older versions do not contain the developer events needed.

    1. LVC (v3.2.9-Rev2+):

For communities not using LVC, the radio defaults to native siren detection. However, it cannot distinguish between just police lights and lights with sirens. As a result, background siren audio will play whenever police lights are active.

Custom SFX

Learn how to customize your microphone SFX!

Sonoran Radio: Customizable Sound Effects

Community-Wide SFX

Community-wide sound effects can be customized in the Customize > SFX Customization menu.

Sonoran Radio: Community Sound Effect Customization

Community SFX customization requires the plus version or higher.

For more information, view our .

Key Up/Down

When a user presses or releases their push-to-talk key, the Key Up SFX and Key Down SFX audio will play.

Individual users can also customize in their settings menu whether or not to hear their own key up/down SFX and other user's key up/down SFX.

Users can also .

When a channel has and a user is already transmitting, a second user attempting to talk at the same time will hear the Talkover SFX audio.

If a user has talkover override permissions, double-pressing the push-to-talk key and holding will play the Talkover Override Success SFX once they are able to transmit.

When a , dispatchers will hear the Emergency Call SFX audio to alert them of an incoming call.

When a , dispatchers will hear the Panic Button SFX audio.

When a user changes their volume in the or via hotkey, they will hear the Volume Up/Down (Hotkey) SFX audio.

Background audio injection blends in-game sounds—like sirens, helicopter rotors, boat engines, and gunshots—into your microphone output.

If you're responding with sirens active, others on the radio will hear them in the background of your voice transmissions.

When the user is inside of or near a vehicle with a siren activated, this sound effect will be played in the background of their transmissions.

When the user is inside of a boat, this engine and water noise sound effect will be played in the background of their transmissions.

When the user shooting or near someone shooting, this sound effect will be played in the background of their transmissions.


Individual users can customize their key-up and key-down SFX in their user settings dialog in their radio or dispatch portal.

Once configured, the user will override any default or community-wide SFX.

Note: SFX uploads are only available on the web, desktop, or mobile apps and can not be done from in-game.

In-Game Speakers

Configure in-game speakers that dispatchers can send tones to!

Configuring In-Game Speakers

1. Access the Menu

Open the menu with the in-game /radiomenu command and select Toneboard Speaker Menu > Spawn/Move/Delete Speaker

Sonoran Radio - /radiomenu
Sonoran Radio - Toneboard Speaker Menu

2. Configure the Speaker

Menu Options

The spawn (create) and edit menu will allow you to set the speaker type, name, range, and position.

Speaker Types

When spawning a new speaker please select the type you would like to use. See types below:

Small - Wall
Medium
Medium - Wall
Large

Speaker Position

Use the controls displayed on screen to rotate and move the speaker to the desired location.

Speakers can be grouped by a customizable name when placed. Grouped speakers show up as a single option on the tone board.

If you would like to group already placed speakers you can do so by navigating to the speakers.json file and adding a group property. (If the value of the group property is empty, speakers will not group together). See below for more:

Ungrouped Speaker(s)
Grouped Speaker(s)

Dispatchers can now and select one of the in-game speaker options to broadcast tones, microphone recordings, or AI powered text-to-speech to.

Tunnels and Degrade Zones

Configure tunnels, underpasses, and other areas where radio signal will be degraded!

Sonoran Radio - Tunnel Detection System

What are Degrade Zones?

Degradation zones are areas like tunnels, underground areas, or mountain valleys that would experience signal loss in a realistic scenario. Custom voice effects will distort the audio more as signal loss increases.

Creating and Modifying Zones

Via Radio Panel

Degrade Zones via Panel

Use the polygon, square, or circle tool to create a new zone. Select the zone to customize the name, Z coordinates (floor and ceiling height), and the degrade strength.

Via In-Game Menu

1. Accessing the Menu

Open the menu with the in-game /radiomenu command and select Degradation Zones

2. Zone Configuration Options

In the Degradation Zones menu, you can specify the strength and add points to create a 3D zone.

When creating a zone you can visualize via the drawn polygon and manipulate and move your last placed point using the on-screen controls

Strength - The percent the signal strength will be cut by when inside the zone (0-1). - Example: 0.5 = 50% degradation

3. View and Remove Configured Zones

Select Edit Degradation Zone in the menu and toggle on Show Zones. All configured zones on the map will be displayed in green. If the config.lua's debug mode is set to true, all zones will also be made visible.

Use the Select Zone menu option to swap back and forth between zones. Your selected zone will be displayed in red.

Transmission Logs

Coming soon!

Sonoran Radio: Transmission Logs

Community transmission logs are only available on the pro version.

.

Accessing Transmission Logs

The transmission log viewer can be accessed on the dispatch panel by clicking the list icon. Users will be able to view all logs within the last 24 hours transmitted on channels that they have access to.

Transmission logs have the following properties:

  • Play/Pause Recording

  • Username of Transmitter

  • Channel of the Transmission

  • Download the Recording

  • AI Transcript

Audio transcripts can also be automatically generated for each transmission recording.

Communities can optionally enable the Transmission Log STT option in the .

Some users may wish to manually opt-out of submitting their transmissions for recording. This can be toggled in the Settings menu under the Privacy tab.

Connected Users List

View the in-game connected radio list to quickly identify what users are online.

Sonoran Radio - Connected Users

Accessing the Connected Users List

In-game, users can utilize the /radiousers command or a customizable FiveM keybind (F11 by default) to open the connected users window.

This window displays all active users connected to the radio, and the channel they are in. When a user is transmitting, their name will turn green.

Resize and Reposition

Resize

To resize the connected users list, use the command /radiouserssize W H with W being the width in pixels (ex: 500) and H being the height (ex: 500).

To move the connected users list on your screen, click and drag while the in-game radio is in focus.

Communities can restrict access to this command with ACE permissions:

Emergency Calls

In-game players can call 911 and talk to you through Sonoran Radio!

You can join and listen to an emergency call using the microphone and headphone buttons, just like any other channel in Sonoran Radio. The buttons will highlight green and red respectively when enabled

Dispatchers can end an emergency call with the red "End Call" button, and in-game players can end it by using /radio 911 again.

In some cases, the caller may hang up or dispatch needs to call them back for more information.

Once the call has ended, a Re-dial {user} option will appear. Click the green call button to re-dial.

Desktop Overlay

The Sonoran Radio desktop overlay lets you see and control your radio in any game! Perfect for Roblox, ARMA 3, and more!

The user list overlay allows you to quickly view what users are online, what channels they're in, and who is currently transmitting.

Browser Microphone Permissions

Microphone permissions are required to use the radio.

If you see the following error message displayed, the Sonoran Radio website has not gotten microphone access from your browser. This prevents you from connecting to the radio.

Select the icon to the left of the URL bar and ensure Microphone access is enabled.

In Chrome, paste the following into the URL bar and hit enter: chrome://settings/content/microphone

Ensure that sites are allowed to ask for microphone access, and that sonoranradio.com is not blacklisted from microphone access.

Device In Use

Resolve the radio error when connecting "Device In Use".

When connecting to the radio, your microphone may be locked in "exclusive mode" by another program.

  • Open the Control Panel and select Hardware and Sound

  • Select Manage Audio Devices

Windows App Volume

When a default output device is selected Windows may automatically lower the volume of other desktop apps.

If Sonoran Radio lowers the volume of FiveM or other apps on Windows while connected, the most common fix is to change Sonoran Radio’s output from Default to your specific headset or speaker device. Windows can treat the default communications device differently and may duck other app audio while the radio is active, even if nobody is talking.

In the Settings panel, change your output device from Default to a specific input device.

Sonoran CMS

Automate Sonoran Radio permissions with Sonoran CMS!

Sonoran CMS makes managing your community's radio easy and automatic!

  • Sync radio permissions and channel access via CMS ranks and Discord Roles

  • Sync radio display names via CMS and Discord names

Learn more about Sonoran CMS!
Sonoran CMS x Sonoran Radio

Talkover Error and Override

Emergency Call

Panic Button

Volume Up/Down (Hotkey) SFX

Background Audio Injection

In-Game Siren

In-Game Boat Engine

In-Game Pistol & Rifle (Silenced)

Per-User SFX

Per-User SFX customization requires the pro version or higher.

For more information, view our pricing FAQ.

Key Up/Down

customize the key up/down SFX that they hear locally
talkover protection enabled
user places an emergency call
user toggles their panic state
dispatch panel
in-game
pricing FAQ

Reposition

ACE Permission Restrictions

Configuring ACE Permissions

Users

Pricing FAQ

Learn more about Sonoran Radio's paid plans!

Roadmap & Changelog

View our development team's upcoming roadmap and historical changelog.

Developer Documentation

Learn more about our developer endpoints, exports, and events!

Troubleshooting

View our guide on common issues with Sonoran Radio.

AI Audio Transcripts

Disable User Transmission Recording

AI configuration panel
Sonoran Radio: Transmission Logs
Learn more about our paid plans

Channels

Community Server

Play Tone

The play_tone push event is sent to the game server when a dispatcher is sending a tone to one or more in-game speakers.

Play Tone

The play_tone push event is sent to the game server when a dispatcher is sending a tone to one or more in-game speakers.

These in-game speaker IDs are set from the set-server-speakers API endpoint.

{
    "id": "", // Community ID
    "key": "", // Community API Key (Use to authenticate)
    "type": "play_tone",
    "payload": {
        // Tone audio file URLs in the order of "stack"
        "src": [
            "https://s3.sonoransoftware.com/radio/system/tones/signal_100.mp3",
        ],
        "ids": [
            "STATION_123",
            "STATION_456"
        ]
    }
}

LVC Fleet (v1.0.1+): Download

Enabling Background Audio Injection

Customizing Background Audio Sounds

Troubleshooting

Can't Hear Sirens

LVC Users (Luxart Vehicle Control)

Native Fallback

config.lua
SFX Customization panel
Download
Add Point to Zone
- Adds another point to the 3D zone

Undo Last Point - Removes the last place point in the 3D zone

Min Z - The minimum Z value (floor height) of the 3D zone

Max Z - The maximum Z value (ceiling height) of the 3D zone

Finish Zone Creation - Finishes the 3D zone and saves to the tunnels.json file

Cancel Zone Creation - Cancels the 3D zone editor and closes the menu

Use the Delete Zone menu option to delete the selected (red) zone.
Degradation Zone: Visible
Degradation Zone: Selected
voice effect
Sonoran Radio -
Sonoran Radio - Degradation Zone Options
Sonoran Radio - Degradation Zone Poly

By editing the config file you can customize the following options:

  1. Customize 911 to any other number or word by editing the emergencyCommand property.

  2. Hide the user's emergency call banner by setting showEmergencyCallHelp to false.

Sonoran Radio also integrates with popular FiveM phone scripts like LB Phone!

Third-party scripts, such as a phone system, can also programmatically start and end emergency calls.

Creating Emergency Calls

Via Portal/App

Via Portal/App

Users can place emergency calls directly from the web, desktop, or mobile apps.

Permissions

Users can be restricted to accessing the emergency call panel and not the radio with the Call-Only permission.

Emergency Calling In-Game

Emergency Calling In-Game

Players are able to make an emergency call in FiveM with /radio 911. This will place them in a call on the Dispatch Panel waiting for a dispatcher.

Sonoran Radio FiveM - Emergency Call

Caller Microphone

The emergency call will use the caller's default microphone. If the caller can not be heard, they may need to change the input device selection with /radio 911 mic.

Answering the Emergency Call

Mic clicks are disabled in emergency channels

Ending the Emergency Call

Redial the Caller

Sonoran Radio - Emergency Calls
Sonoran Radio - Speaking in 911 Call
Sonoran Radio - End 911 Call

Customize The Emergency Number & Banner

Integrated Phone Scripts

Developer Documentation

FiveM Phone Scripts
Resource API

Error Code

Granting Microphone Permissions

Via Quick Menu

Via Chrome Settings

Select the microphone > Properties > Advanced > Disable (un-check) Allow applications to take exclusive control of this device.

Sonoran Radio: Disable Exclusive Mic Mode

Device In Use Error

1. Access the Sound Tab

Sonoran Radio: Device In Use

2. Disable Exclusive Mode

3. Speaker Grouping

Playing Tones to In-Game Speakers

use the tone board
Sonoran Radio - Speaker Position Controls
Sonoran Radio - In-Game Speaker Broadcast

Radio Overlay

Accessing the Radio Overlay

Accessing the Radio Overlay

With the desktop application opened, select the Open Overlay button on the dispatch or mobile panel. This will close the main dispatch panel and will open up the radio overlay.

The overlay will be displayed on top of any window it's placed on. Pressing the power button Off or selecting Return to Portal will close the overlay and re-open the dispatch panel.

Using the Radio Overlay

Hotkeys

Hotkeys

By selecting the Settings button on the overlay, users can configure a hotkey to hide/show the overlay. Additionally, a hotkey to focus the radio can be used for games with fullscreen mode.

Changing Frames

Changing Frames

Communities can configure custom radio frames to be made available to their users.

Users can change their selected frame in the settings window.

Moving Resizing the Overlay

Click and drag on the radio to move it around the screen. Hold CTRL while clicking and dragging up or down on the overlay to increase or decrease the size.

Customizing Radio Frames

Uploading custom radio frames requires the Pro subscription.

For more information, view our pricing page.

Configuring Custom Overlay Frames

In the admin's Customization > Desktop Frames menu, new frame images can be uploaded. Once uploaded, drag-and-drop the buttons onto the frame and position the screen size.

Connected Users Overlay

Accessing the User List Overlay

Accessing the Connected Users Overlay

To open the connected users overlay, select the Open User List button on the dispatch or mobile panel. Or, create a new hotkey in the Settings panel to Open the Connected Users.

Geo Channels

Automatically change your transmit and scan channels based on in-game location.

Geo channels let you define in-game zones that automatically switch your transmitting and scanned channels based on your location.

For example, entering a downtown area can automatically switch your radio to the City channel, while driving on the highway can switch it to the Highway channel.

Creating Geo Zones

Via Radio Panel

Geo Zones via Radio Panel

In the Geo Zone tab, use the polygon, rectangle, or circle tool to create a custom zone on the map. Select the zone to customize the name, z coordinates (floor and ceiling height), and the channels to automatically transmit and scan when entered.

Additionally, you can enter comma separated ACE permissions for the zone. When configured, the zone will only apply to users with those ACE permissions.

Via In-Game Menu

Accessing the Menu

Open the menu with the in-game /radiomenu command and select Geo Channels

Zone Configuration Options

In the Geo Channels menu, you can specify which channels you want to transmit and scan upon entering, ace perms required to auto switch, add points to create a 3D zone and toggle auto switching on and off.

Add Point to Zone

View and Remove Configured Geo Zones

Select Edit Geo Zones in the menu and toggle on Show Zones. All configured zones on the map will be displayed in green. If the config.lua's debug mode is set to true, all zones will also be made visible.

Use the Select Zone menu option to swap back and forth between zones. Your selected zone will be displayed in red.

Use the Delete Zone

Commands and ACE Permissions

FiveM Geo Channel Config + ACE Permissions

In the 's Config.geoChannels property allows for additional customization.

User Toggle

Users can use /radio geoswitch to toggle the auto-switcher on/off for themselves.

An optional acePermission can be added to restrict this command to specific users.

Radio Jammers

Deploy a signal jammer to disrupt nearby emergency radios for the ultimate heist!

Video Example

Coming soon!

Using the Radio Jammer

Enabling the Jammer

  1. Enable the Config.radioJammers.enabled option in your config.lua.

  2. Add the sonoranradio.jammers ace permission.

Opening in Standalone

You can use /radio jammer command to open a personal scanner. This requires the sonoranradio.jammers .

With the radio jammer item in their inventory, users can double click to open the .

If the jammer item is dropped on the floor, you can interact by being near it and pressing E.

If the jammer is powered on, it will impact radios in the configured radius.

Permanent Jammers are available to everybody at configurable locations across the map.

You can use /radio jammers to easily add, move, or delete persistent jammers

When creating a jammer, you have the ability to choose between many different jammer-like models to best fit your needs.

You can also modify the jammers.json config file for more customization. By default, there are no jammers spawned.

In-game radio screens will reflect a jamming effect, with the intensity based on the jammer strength.

If you have enabled Config.radioJammers.permissionMode, you must add permissions in your server.cfgfor the scanner to work.

The ACE permission for /radio scanner is sonoranradio.jammers.

The ACE permissions for specific jammer types are sonoranradio.jammer_handheld.

  • jammer_handheld and other options are from the names in your .

Learn more about .

Sonoran Radio does not provide a way to get the scanner item independently. You can give the item with any method, but here's an example chat command:

In-Game Microphone Not Working

Fix a common issue causing the in-game microphone to not work.

In-Game Microphone Not Working

Due to an old version of Chromium (web browser) that FiveM utilizes, we are unable to change audio devices in-game. FiveM utilizes your "default" Windows microphone.

To resolve this issue, simply set your desired microphone "as default" in Windows.

1. Control Panel Sound

Open the Control Panel and select Hardware and Sound

2. Manage Audio Devices

Select Manage Audio Devices

3. Set Microphone as Default

  • Select the Recording tab

  • Select your microphone

  • Select Set Default

  • Select Apply

After setting your new default microphone restart your FiveM application.

If you have set your mic as the default device and you are still unable to hear it in game, try the following steps:

  • Ensure device is marked as "Default Communication Device" as well. If the "Set Default" button is greyed out, that means it is both the default device and the default communication device.

  • Reset your audio devices in Windows settings, as shown below.

  1. Open Windows Settings, navigate to System > Sound

  2. Under Advanced sound options, click App volume and device preferences

Set Mic In-game for Radio

Configure and manage your in-game microphone settings for Sonoran Radio, including microphone selection, muting, and Automatic Gain Control configuration.

Set Your Microphone

Sonoran Radio allows you to select and configure your microphone directly in-game.

Step 1: Open the Microphone Menu

In chat, run the following command:

/radio 911 mic

This will open the microphone configuration menu.

Open microphone menu

Step 2: Select Your Microphone

Click the dropdown menu and choose the microphone you want to use.

Select microphone

Step 3: Configure Microphone Settings

Once selected, you can enable or disable your microphone and configure Automatic Gain Control.

  • Blue Microphone = Microphone Enabled

  • Red Microphone = Microphone Muted/Disabled

  • Green Slider = Automatic Gain Control (AGC)

Automatic Gain Control helps balance microphone volume automatically.

Microphone controls

Press ESC to close the menu and return to gameplay.

Mac Keybinds

Resolve issues with desktop keybinds on Mac OSX.

Due to Apple's permission restrictions, and limited support on newer Apple Silicon processors - Sonoran Radio takes a couple of extra steps to setup global keybinds.

1. Modify File Permission

Sonoran Radio must adjust a file permission in order to listen to keybinds while the application is running. You will be prompted to enter your computer's password:

2. Grant Accessibility Access

When first setting a keybind, you will be prompted to add the Accessibility permission for keyboard and mouse input detection.

Click the Open System Preferences button, and toggle the permission on for Sonoran Radio.

If you do not see the Sonoran Radio application as an option, click the + button in the bottom right and select the program from your Applications folder.

After toggling access on, you will be prompted to restart the application.

Libraries

Install links for the official Sonoran SDK libraries used with the v2 API.

The official Sonoran SDK libraries provide package-managed access to Sonoran Radio integrations and v2 API helpers.

Package Manager Links

  • Sonoran.js on npm

  • Sonoran.lua on LuaRocks

Retrieving Your Credentials

All API calls must be authenticated with a community ID and API key.

Radio Community ID and API Key

Your Sonoran Radio community ID and API key are located under Administration > Community ID and Community API Key

Using the Dispatch Panel

Learn more about using the Sonoran Radio dispatch panel.

When you first open a Sonoran Radio community with standalone enabled, you will see this page:

To join the radio, press Connect. After connecting, you will be greeted with a row of channels, and a list of connected users underneath them

Get Server Subscription from IP

Return the highest Sonoran Radio subscription level associated with the caller IP.

GET /v2/server-subscriptions/by-ip

Rate limit: 2 requests per minute

Returns the highest matching subscription level for the caller IP.

This endpoint does not require bearer authentication.

Examples

Ban Members

Ban members from a specific Sonoran Radio server.

POST /v2/servers/:communityId/members/ban

Rate limit: 4 requests per minute

Bans members from the selected server and disconnects them from live radio sessions when applicable.

Headers

Sonoran CAD Integration

Integrate the Radio with your Sonoran CAD!

To enable integrations between Sonoran CAD and Radio, simply .

FiveM Phone Scripts

Sonoran Radio integrates with FiveM phone scripts to allow players to call Sonoran Radio emergency service dispatchers right from their phone

LB Phone support for Sonoran Radio is as easy as changing a configuration variable.

  1. In your , set Config.phoneResource to 'lb-phone'.

  2. Ensure you start the lb-phone

Get Community Channels

Get configured channel groups and channels for a specific Sonoran Radio server.

GET /v2/servers/:communityId/channels

Rate limit: 6 requests per minute Authenticated v2 endpoints are rate limited per API key rather than per IP address.

Returns channel groups and channel definitions for the selected server.

Headers

Get Connected User

This endpoint gets a connected user in a specific room for a specific Sonoran Radio server.

GET /v2/servers/:communityId/rooms/:roomId/users/:identity

Rate limit: 12 requests per minute This endpoint has a small internal gateway buffer, but the published public limit is 12 requests per minute.

Returns a single connected participant.

Headers

Push Events

Learn more about our Backend -> Game Server push events!

Push events are sent to your community's pushUrl (full IP/port) set in the API endpoint. This endpoint should be called on startup.

Push events can be authenticated by comparing the event's id and key to your community ID and API key.

User Connected

The user_connected push event is sent to the game server when a user connects to the radio.

The user_connected push event is sent to the game server when a user connects to the radio.

Open Source Contributions

The Sonoran Radio FiveM resource is open for public contributions!

Just like with Sonoran CAD and CMS, the Sonoran Radio resource is open for public contributions. Pull requests with new functionality or bug fixes will be reviewed and merged when appropriate. When applicable, accepted pull requests may be eligible for Sonoran account credit. for more contact with developers.

Sonoran.Net on NuGet
Sonoran.py on PyPI

Push Event Address

set-server-ip

FiveM Resource Repository

Submitting Pull Requests

Click here to view the open source FiveM resource.
Join our Discord
Scroll to the bottom and click Reset to reset to the Microsoft recommended defaults.
  • Restart FiveM to ensure it recognizes the changes.

  • 4. Restart your Game

    Further Troubleshooting

    Resetting Windows Audio Devices

    Controls

    Step 4: Return to the Game

    You can also manually open this menu via System Settings > Privacy and Security > Accessibility

    {
        "id": "", // Community ID
        "key": "", // Community API Key (Use to authenticate)
        "type": "user_connected",
        "payload": {
            "identity": "000-000-000-000"
        }
    }

    User Connected

    Adds another point to the 3D zone

    Undo Last Point

    • Removes the last placed point from the 3D zone

    Min Z

    • The minimum Z value (floor height) of the 3D zone

    Max Z

    • The maximum Z value (ceiling height) of the 3D zone

    Finish Zone Creation

    • Finishes the 3D zone creation and saves to the geochannels.json file

    Cancel Zone Creation

    • Cancels the 3D zone editor and closes the menu

    Edit Geo Zones

    • Opens the Geo Zone editor menu

    Select Zone

    • Select the zone you would like to edit

    Transmit Channels

    • The channels you will automatically join and transmit in upon entering the zone, and leave upon exiting the zone

    Scan Channels

    • The channels you will automatically join and scan in upon entering the zone, and leave upon exiting the zone

    ACE Permissions

    • The ACE permission required for the auto switch to happen upon entering/ exiting the zone. If left blank ALL radio users will join and exit the channel upon entering that zone

    menu option to delete the selected (red) zone.
    Degredation Zone: Visible and Selected
    config.lua
    Sonoran Radio - In-game Menu
    local response = client.radio:getServerSubscriptionFromIpV2
    const response = await instance.radio
    response = instance.radio.getServerSubscriptionFromIpV2()
    var response = await sonoran.Radio
    openapi: 3.1.0
    paths:
    
    curl -X GET "https://api.sonoranradio.com/v2/server-subscriptions/by-ip"

    Successful requests return application/json.

    Get Server Subscription from IP

    {
      "subscription": 2
    }

    Response

    Name
    Value

    Authorization

    Bearer <community-api-key>

    Content-Type

    application/json

    Examples

    local response = client.radio:banMembersV2
    
    const response = await instance.radio
    
    response = instance.radio.banMembersV2([
        
    
    var response = await sonoran.Radio
    
    openapi: 3.1.0
    paths:
    
    curl -X POST "https://api.sonoranradio.com/v2/servers/YOUR_COMMUNITY_ID/members/ban" 
    

    Successful requests return application/json.

    Ban Members

    {
      "bannedAccIds": [
        "91de0ce8-c571-11e9-9714-5600023b2434"
      ]
    }

    Response

    resource prior to Sonoran Radio.
  • Customize the emergency call number and hide the call banner.

  • In LB Phone, dial 911 (or your customized number) to connect with a Sonoran Radio dispatcher. Press the end call button to hang up.

    Sonoran Radio: LB Phone Emergency Call
    Sonoran Radio: LB Phone Emergency Call

    LB Phone

    Configuration

    config.lua

    Usage

    Name
    Value

    Authorization

    Bearer <community-api-key>

    Examples

    local response = client.radio:getCommunityChannelsV2
    const response = await instance.radio
    response = instance.radio.getCommunityChannelsV2()
    var response = await sonoran.Radio
    openapi: 3.1.0
    paths:
    
    curl -X GET "https://api.sonoranradio.com/v2/servers/YOUR_COMMUNITY_ID/channels" 
    

    Successful requests return application/json.

    Get Community Channels

    {
      "groups": [],
      "channels": [
        {
          "id": 101,
          "name": "Law Dispatch"
        }
      ]
    }

    Response

    Name
    Value

    Authorization

    Bearer <community-api-key>

    Examples

    local response = client.radio:getConnectedUserV2
    const response = await instance.radio
    response = instance.radio.getConnectedUserV2(1,
    var response = await sonoran.Radio
    openapi: 3.1.0
    paths:
    
    curl -X GET "https://api.sonoranradio.com/v2/servers/YOUR_COMMUNITY_ID/rooms/1/users/91de0ce8-c571-11e9-9714-5600023b2434" 
    

    Successful requests return application/json.

    Get Connected User

    {
      "identity": "91de0ce8-c571-11e9-9714-5600023b2434",
      "name": "Officer Smith",
      "metadata": "{\"sonrad\":true}",
      "state": "ACTIVE"
    }

    Response

    /giveitem <playerId> sonoran_radio_jammer_handheld 1

    Opening in a Framework Server (QBCore, Qbox, etc.)

    Item Drop

    Dropping jammers is not currently supported in OX inventory.

    Support will be added at a later date, pending more information from the OX development team.

    Permanent Jammers

    Configuring Permanent Jammers

    Jamming Radio Effect

    Developers

    Ace Permissions

    Giving the Scanner Item (QBCore)

    ace permission
    scanner menu
    View our complete list of supported FiveM frameworks an inventories.
    config.lua
    ACE Permissions
    Sonoran Radio Jammer Item in Inventory
    Sonoran Radio Jammer Interaction
    "Satellite Jammer"
    "Case Jammer"
    "Suitcase Jammer"
    "Handheld Jammer"

    Dispatch Portal

    Hotkeys (Keybinds)

    Push-to-talk key binds are only global in the desktop application.

    On web, the browser window must be in focus.

    Dispatch Hotkeys

    Hotkeys allow for faster actions at the press of a button. These can be configured by clicking the gear icon to open the settings menu.

    • Push to Talk

    Right click on a hotkey button for the option to clear it.

    Transmitting (Push to Talk)

    Dispatch Push To Talk

    To transmit over Sonoran Radio, you can press the microphone button on the top-left.

    Alternatively, use the PTT hotkey.

    Dispatch: PTT Button

    To temporarily transmit in a single channel, and move back to your original channel afterwards, select the keyboard icon to set a per-channel XMIT hotkey.

    Dispatch: Per-Channel XMIT Hotkey

    Switching Transmit and Scanned Channels

    Switching Transmit and Scanned Channels

    To switch to another channel, click the microphone button on the channel card.

    CTRL + Click on the microphone option to transmit on multiple channels at once.

    You can also change channels via hotkey.

    Scanning (Listen) To Multiple Channels

    Select the headphone icon on each channel to listen in. You can listen to multiple channels at once.

    Drag and Drop Users

    User Drag-And-Drop

    Change a user's channel (requires permission) by dragging and dropping their name into the channel header.

    User Actions

    User Actions (Right Click)

    Right click in the user to:

    • Kick the user from the channel (Requires Permission)

    • Clear the user's panic status

    • Move the user to a different channel ()

    • Adjust the user's volume ()

    • Change the user's display name ()

    • Stun the user from transmissing temporarily ()

    • Ping the user to get their attention

    Unit Panic

    Unit Panic Status

    When a unit toggles their panic status in-game, the dispatch portal will reflect this with a red banner and a red highlight on the panicked unit.

    Dispatchers can right-click the user to clear the panic for them.

    The customizable panic sound effect will also alert dispatchers to an active unit panic.

    Display Names

    Via Dispatch Portal

    To change your display name, users will need the Change Display Name permission. To manage others, users will need the Manage Display Names permission.

    Via Radio Interface

    Right click a user in the radio interface and select Display Name

    Via Members Tab

    Via Members Tab

    In the admin panel's Members tab, select the drop-down and Set Display Name button to edit a user's display name.

    Via Sonoran CMS

    Via Sonoran CMS

    Sonoran CMS can also automatically set and manage your Radio display names and sync them with Discord.

    Via Sonoran CAD Sync

    Learn about automatically setting radio display names to match your unit information in Sonoran CAD.

    Via Command

    Use the in-game command /radio displayname John Doe to update your radio display name.

    In-game commands can also be restircted with ACE permissions.

    Via Developer Export or Endpoint

    Programmatically update a user's display name in FiveM, update a display name via API, or use a custom framework function for guest users.

    Volume Changes

    Volume Sliders

    Adjust the overall voice and sound effect volume by opening the settings menu and selecting the Audio tab.

    In addition to the manual sliders, you can customize how much the volume hotkeys adjust the volume.

    You can also adjust volume for a specific user.

    Per-User Volume

    Right-click on a user to individually increase or decrease their transmission volume.

    Per-Channel Volume

    Right-click on a channel to individually increase or decrease transmission volume.

    Viewing Channel IDs

    Channel IDs

    Some integrations like ACE perm sync or scanner permissions may require you to enter the internal ID number of a specific channel.

    Select the # symbol on the last channel in the dispatch panel to toggle ID visibility.

    Sonoran Radio - Connect to Radio
    Sonoran Radio - Radio Hub

    Sonoran Radio CAD Plugin

    Integration Features

    Panic Toggle

    CAD Panic Toggle

    Triggering your Sonoran Radio panic (by pressing the yellow button at the top of the radio) will also toggle your panic status in Sonoran CAD.

    Dispatch Call Information

    Dispatch Call Information

    When attached to a Sonoran CAD dispatch call, the radio will display a red call info box and set the top status bar to red. Click the call title to expand and collapse the information.

    Sonoran Radio x CAD Call Information
    Call Information - Expanded

    Live Map Blips

    Live Map Radio Tower Information

    Sonoran Radio towers will be displayed on the CAD live map.

    Select one of the blips to view it's repeater type and health.

    Display Name Sync

    CAD To Radio Display Name

    Automatically set your radio's display name based on your CAD unit information.

    In the sonorad submodule's configuration file, set config.syncRadioName.enabled to true and customize the formatting in config.syncRadioName.nameFormat.

    enable the sonrad (Sonoran Radio) submodule in your CAD resource

    Configuring ACE Permissions

    Restrict user access to community approval, permissions, commands and features in-game with ACE permissions.

    Command ACE Permissions

    ACE permissions allow you to restrict what users have access to certain commands.

    ACE permissions are configured in your server.cfg file. To keep them organized, you can also place them in a separate file (e.g., permissions.cfg in the same directory) and then exec permissionss.cfg from within your server.cfg.

    1. Create a Permission Group

    Here, we'll create an admin ACE group that has access to all of the sonoranradio.example categorized permissions.

    # ACE group name 'admin' for 'sonoranradio.example' permission category
    add_principal group.admin sonoranradio.example

    2. Assign Permissions to the Group

    This adds all of the Sonoran Radio permissions (configuring repeaters, using the radio, and repairing repeaters) to the sonoranradio.example category that the admin ACE group has access to.

    This grants a user the admin ACE permission group, specific to their in-game license ID.


    ACE permission sync allows you to automatically approve users in the radio community, grant access to private channels, and give user permissions like name changes, kick, etc.

    This sync is ran whenever you turn the radio on and connect.

    To enable this feature, set your to true.

    ACE permission sync also allows new users to bypass the Sonoran account login and .

    The is false by default.

    • When false: All users can see and use the Login as Guest button.

    • When true: Users must have the sonoranradio.use ACE permission to see the Login as Guest button.

    Once logged in as a guest, radio permissions will be granted based on the.

    You can also use external services like to easily manage ACE permissions via ranks and Discord roles.

    Radio Scanners

    Discretely listen to your community's radio

    Sonoran Radio - In-Game Scanner

    Due to bandwidth usage, this feature is automatically enabled with the Pro version only!

    Video Example

    Using the Radio Scanner

    Enabling the Scanner

    1. Enable the config.chatter option in your config.lua.

    2. Add the sonoranradio.scanner ace permission.

    Opening in Standalone

    You can use /radio scanner command to open a personal scanner. This requires the sonoranradio.scanner .

    With the radio scanner item in their inventory, users can double click to open the .

    If the scanner item is dropped on the floor, you can open its scanner menu by being near it and pressing E.

    If the scanner is powered, transmissions will be heard by nearby users.

    Press the power button and the scanner will auto-connect to the default channel. Use the knob to scroll through all available channels.

    By default, only public radio channels will be available. For , you can .

    Permanent Scanners are scanners that are available to everybody at configurable locations across the map. For example, you can add a scanner in the Sandy Shores Sheriff Station that will always listen the County Patrol Ops channel.

    You can use /radiomenu to easily add, move, or delete persistent scanners

    When creating a scanner, you have the ability to choose between many different scanner-like models to best fit your needs

    You can also modify the scanners.json JSON config file for more customization. By default, scanners connect to the default channel, but you can customize the channel ID it uses.

    The channel IDs can be found in the or .

    If you have enabled Config.acePermsForScanners, you must add permissions in your server.cfgfor the scanner to work.

    The channel IDs can be found in the or .

    Sonoran Radio does not provide a way to get the scanner item independently. You can give the item with any method, but here's an example chat command:

    Please note that if you changed Config.ScannerItem.name, it will not work with sonoran_radio_scanner

    Configure Channels

    Learn more about creating and managing radio channels!

    Creating Channel Groups

    Channel groups allow communities to organize channels in separated categories.

    Channel groups are configured in the Customization > Channels & Groups tab.

    Add a Group

    To add a new channel group, select the green + icon to the right of the group bar.

    Enter in a new group name, and select Ok.

    Sonoran Radio - Add Channel Group

    Edit or Delete a Group

    Select the gear icon on the group to rename it.

    Select the trash icon on the group to remove it.

    Re-order the channel groups via drag-and-drop.

    Shared channels let you create a single channel that exists across multiple groups.

    In this example, there are three radio groups — City, Highway, and County. Each group has its own Interops channel, but these channels are linked together so that any transmission on one Interops channel is heard across all three groups.

    This setup allows seamless communication between departments while maintaining their individual group structures.

    1. Determine the "Primary" Channel

    • One channel must be chosen as the "Primary" channel that the other channels link to. In this example, we will select the City group's Interops.

    1. Link the First Channel to Primary

    • In the Highway group, edit the Highway Interops channel. Toggle the channel mode to Shared and select the City Interops channel (our "primary" channel).

    1. Link the Second Channel to Primary

    • In the County group, edit the County Interops channel. Toggle the channel mode to Shared and select the City Interops channel (our "primary" channel).

    Now, any user in the City, Highway, or County Interops channel will appear in all three and any transmissions in one will be heard in all three.

    Channels are inside of groups and are what users connect to in order to communicate.

    You can create a channel in the Customization > Channels & Groups tab, or right inside of the Dispatch panel.

    • Select the gear icon on the channel to rename it.

    • Select the plus icon in the server settings or dispatch panel to add a new channel.

    • Select the gear icon > trash icon to delete the channel.

    When creating a channel, you only need to provide a name.

    Set User Channels

    Update the transmit and scan channels for a connected user on a specific Sonoran Radio server.

    Set User Channels

    PATCH /v2/servers/:communityId/rooms/:roomId/users/:identity/channels

    Rate limit: 6 requests per minute

    Updates the connected participant's current transmit and scan channel state.

    Headers

    Name
    Value

    Examples

    Successful requests return application/json.

    Set Member Permissions

    Update member permissions for a specific Sonoran Radio server.

    Set Member Permissions

    PATCH /v2/servers/:communityId/members/permissions

    Rate limit: 4 requests per minute

    Updates permission bitmasks and optional profile permissions for one or more server members.

    Headers

    Name
    Value

    Examples

    Successful requests return application/json.

    Set Member Display Names

    Update stored member display names for a specific Sonoran Radio server.

    Set Member Display Names

    PATCH /v2/servers/:communityId/members/display-names

    Rate limit: 4 requests per minute

    Updates member nicknames for the selected server.

    Headers

    Name
    Value

    Examples

    Successful requests return application/json.

    Approve Members

    Approve existing pending members for a specific Sonoran Radio server.

    Approve Members

    POST /v2/servers/:communityId/members/approve

    Rate limit: 12 requests per minute This endpoint has a small internal gateway buffer, but the published public limit is 12 requests per minute.

    Approves pending community members already attached to the selected server.

    Headers

    Name
    Value

    Examples

    Successful requests return application/json.

    Big Daddy Radio Animations

    Sonoran Radio is partnered with Big Daddy Scripts to offer a FREE copy of their radio animations script!

    Sonoran Radio x Big Daddy Scripts

    What is this offer?

    This script requires the pro version of Sonoran Radio standalone.

    Big Daddy's radio animation script enhances your Sonoran Radio experience by adding new in-game animations. As one of the most popular scripts of its kind, it offers versatile options based on where your radio is positioned—whether on your chest, shoulders, or handheld. This provides a more immersive and personalized interaction.

    Download and Installation

    1. Download the Script and Product Key

    Create an account and download the latest script resource from Big Daddy Scripts.

    In the account portal, select your recent order and copy the product key.

    Big Daddy - Account Panel
    Big Daddy - License Key

    2. Install The Script

    A. Extract

    Extract the script to your server's resources folder.

    B. License Key

    In the settings.ini file, paste your license key.

    In your server.cfg file, add the following line after your Sonoran Radio resource lines:

    Sonoran Radio will automatically detect the script named BigDaddy-RadioAnimation, and disable the default Sonoran Radio animation (disableAnimation from the config.lua)

    Once in-game, you can use the /radioanim command to open up the customization menu.

    This script will automatically detect when you are talking on your Sonoran Radio.

    Kick Members

    Remove members from a specific Sonoran Radio server.

    Kick Members

    POST /v2/servers/:communityId/members/kick

    Rate limit: 4 requests per minute

    Removes members from the selected server and disconnects them from live radio sessions when applicable.

    Headers

    Name
    Value

    Examples

    Successful requests return application/json.

    Unban Members

    Unban members from a specific Sonoran Radio server.

    Unban Members

    POST /v2/servers/:communityId/members/unban

    Rate limit: 4 requests per minute

    Unbans members from the selected server so they can rejoin the community.

    Headers

    Name
    Value

    Examples

    Successful requests return application/json.

    Custom Voice Effects

    Customize transmission voice effects for your community, or local user!

    Sonoran Radio lets you create custom voice effect profiles for transmissions. These effects can be independently assigned to specific radio channels and emergency calls. Or, users can also customize their own voice effect preferences!

    By clicking the headphone icon and using the signal strength sliders, you can hear how the effect will sound when users are talking.

    Voice effects can be customized by the individual listener, based on their preferences. Users can open their Settings menu and select the Voice FX tab to customize.

    Toggle Community FX to Local FX mode to .

    Read and Write Permissions

    How to fix SonoranRadio issues caused by read-only file permissions on Windows and Linux servers.


    Log into the game panel where your FiveM server is hosted (e.g. ZAP-Hosting, txAdmin, Pterodactyl, Gamepanel, VPS).


    Navigate to:



    1. Right-click config.lua

    FiveM Inventories

    Sonoran Radio integrates with FiveM inventory systems for physical radio and scanner items.

    QBCore inventory support for the radio and items is automatically detected.

    To restrict radio and scanner access to users with the radio item in their inventory, set config.enforceRadioItem to true.

    Customize your radio and scanner items in your config.lua's Config.RadioItem and Config.ScannerItem objects.

    Currently, the following QBCore inventories are supported:

    Why Sonoran Radio?

    Experience Sonoran Radio, the free, most popular radio transmission software for FiveM, ER:LC & gaming communities alike!

    Sonoran Radio is the most advanced push-to-talk system for gaming communities.

    With customizable voice effects, live emergency calls, and deep FiveM integrations like nearby radio audio, background noise injection, and destructible towers—Sonoran Radio keeps your team connected and in control.

    Sonoran Radio offers a fully-featured free version accessible to anyone!

    With instant setup, you can chat with community members in just minutes!

    Dispatch AI is our most powerful integration ever built. Talk to a live AI dispatcher over the radio to create calls, run license plate lookups, update your status, and so much more!

    Sonoran Radio's desktop overlay works with any game, leaving you with full immersion!

    Get Connected Users

    This endpoint gets all connected users for a specific Sonoran Radio server.

    GET /v2/servers/:communityId/connected-users

    Rate limit: 6 requests per minute

    Returns every currently connected radio participant for the selected server.

    Headers

    Play Tone

    Play one or more tones for a specific Sonoran Radio server.

    POST /v2/servers/:communityId/tones/play

    Rate limit: 12 requests per minute This endpoint has a small internal gateway buffer, but the published public limit is 12 requests per minute.

    Plays one or more saved tone IDs or custom tone payloads to channels, groups, or in-game speaker targets.

    Headers

    Set In-Game Speaker Locations

    Set in-game speaker locations for tone playback on a specific Sonoran Radio server.

    PUT /v2/servers/:communityId/speakers

    Rate limit: 2 requests per minute

    Stores the in-game speaker list used by tone playback targets.

    Headers

    Set Server IP

    Set or update a server room IP and push URL for a specific Sonoran Radio server.

    POST /v2/servers/:communityId/server-ip

    Rate limit: 2 requests per minute

    Adds or updates a room origin and push URL for the selected server.

    Headers

    Logging

    View audit logs from user actions in Sonoran Radio.

    Community user logs can be found in the Administration tab. Logs can be filtered by type, date, and text content.

    ?.
    getServerSubscriptionFromIpV2
    ()
    ;
    .
    getServerSubscriptionFromIpV2
    ();
    /v2/server-subscriptions/by-ip:
    get: {}
    ()
    ?.
    banMembersV2
    ([
    "91de0ce8-c571-11e9-9714-5600023b2434"
    ], 1);
    "
    91de0ce8-c571-11e9-9714-5600023b2434
    "
    ], 1)
    .
    banMembersV2
    (
    new
    []
    {
    "91de0ce8-c571-11e9-9714-5600023b2434"
    });
    /v2/servers/{communityId}/members/ban:
    post:
    security:
    - bearerAuth: []
    \
    -H "Authorization: Bearer your-community-api-key" \
    -H "Content-Type: application/json" \
    -d "{\"accIds\":[\"91de0ce8-c571-11e9-9714-5600023b2434\"]}"
    ({
    "91de0ce8-c571-11e9-9714-5600023b2434"
    }, 1)
    ?.
    getCommunityChannelsV2
    ()
    ;
    .
    getCommunityChannelsV2
    ();
    /v2/servers/{communityId}/channels:
    get:
    security:
    - bearerAuth: []
    \
    -H "Authorization: Bearer your-community-api-key"
    ()
    ?.
    getConnectedUserV2
    (
    1
    ,
    "
    91de0ce8-c571-11e9-9714-5600023b2434
    "
    ,
    "
    YOUR_COMMUNITY_ID
    "
    )
    ;
    "
    91de0ce8-c571-11e9-9714-5600023b2434
    "
    ,
    "
    YOUR_COMMUNITY_ID
    "
    )
    .
    getConnectedUserV2
    (
    "
    91de0ce8-c571-11e9-9714-5600023b2434
    "
    );
    /v2/servers/{communityId}/rooms/{roomId}/users/{identity}:
    get:
    security:
    - bearerAuth: []
    \
    -H "Authorization: Bearer your-community-api-key"
    (
    1
    ,
    "
    91de0ce8-c571-11e9-9714-5600023b2434
    "
    ,
    "
    YOUR_COMMUNITY_ID
    "
    )

    Community Logs

    Sonoran Radio Handheld - Panic Button
    Sonoran Radio: Background Audio Injection

    Authorization

    Bearer <community-api-key>

    Content-Type

    application/json

    Response

    local response = client.radio:setMemberPermissionsV2({
      {
        accId = "91de0ce8-c571-11e9-9714-5600023b2434",
        perm = 34
      }
    }, 1)
    const response = await instance.radio?.setMemberPermissionsV2([
      {
        accId: "91de0ce8-c571-11e9-9714-5600023b2434",
        perm: 34
      }
    ], 1);
    response = instance.radio.setMemberPermissionsV2([
        {
            "accId": "91de0ce8-c571-11e9-9714-5600023b2434",
            "perm": 34
        }
    ], 1)
    var response = await sonoran.Radio.setMemberPermissionsV2(new[]
    {
        new MemberPermissionV2Change
        {
            AccId = "91de0ce8-c571-11e9-9714-5600023b2434",
            Perm = 34
        }
    });

    Authorization

    Bearer <community-api-key>

    Content-Type

    application/json

    Response

    local response = client.radio:setMemberDisplayNamesV2({
      {
        accId = "91de0ce8-c571-11e9-9714-5600023b2434",
        nickname = "Chief Miller"
      }
    }, 1)
    const response = await instance.radio?.setMemberDisplayNamesV2([
      {
        accId: "91de0ce8-c571-11e9-9714-5600023b2434",
        nickname: "Chief Miller"
      }
    ], 1);
    response = instance.radio.setMemberDisplayNamesV2([
        {
            "accId": "91de0ce8-c571-11e9-9714-5600023b2434",
            "nickname": "Chief Miller"
        }
    ], 1)
    var response = await sonoran.Radio.setMemberDisplayNamesV2(new[]
    {
        new MemberDisplayNameV2Change
        {
            AccId = "91de0ce8-c571-11e9-9714-5600023b2434",
            Nickname = "Chief Miller"
        }
    });

    Authorization

    Bearer <community-api-key>

    Content-Type

    application/json

    Response

    local response = client.radio:approveMembersV2({
      "91de0ce8-c571-11e9-9714-5600023b2434"
    }, 1)
    const response = await instance.radio?.approveMembersV2([
      "91de0ce8-c571-11e9-9714-5600023b2434"
    ], 1);
    response = instance.radio.approveMembersV2([
        "91de0ce8-c571-11e9-9714-5600023b2434"
    ], 1)
    var response = await sonoran.Radio.approveMembersV2(new[]
    {
        "91de0ce8-c571-11e9-9714-5600023b2434"
    });
    openapi: 3.1.0
    paths:
      /v2/servers/{communityId}/members/approve:
        post:
          security:
            - bearerAuth: []
    curl -X POST "https://api.sonoranradio.com/v2/servers/YOUR_COMMUNITY_ID/members/approve" \
      -H "Authorization: Bearer your-community-api-key" \
      -H "Content-Type: application/json" \
      -d "{\"accIds\":[\"91de0ce8-c571-11e9-9714-5600023b2434\"]}"

    C. Ensure the Resource

    3. Enjoy!

    This script also makes users talk on their in-game microphone when they talk on the radio.

    To disable this, ensure the Config.talkSync is disabled in the Sonoran Radio config.lua and the TalkSync is set to false in Big Daddy's Animation settings.ini file.

    See the documentation for more information about configuration options and commands.
    Click to learn more about Sonoran Radio standalone!
    Big Daddy - Product Key

    Authorization

    Bearer <community-api-key>

    Content-Type

    application/json

    Response

    local response = client.radio:kickMembersV2({
      "91de0ce8-c571-11e9-9714-5600023b2434"
    }, 1)
    const response = await instance.radio?.kickMembersV2([
      "91de0ce8-c571-11e9-9714-5600023b2434"
    ], 1);
    response = instance.radio.kickMembersV2([
        "91de0ce8-c571-11e9-9714-5600023b2434"
    ], 1)
    var response = await sonoran.Radio.kickMembersV2(new[]
    {
        "91de0ce8-c571-11e9-9714-5600023b2434"
    });
    openapi: 3.1.0
    paths:
      /v2/servers/{communityId}/members/kick:
        post:
          security:
            - bearerAuth: []
    curl -X POST "https://api.sonoranradio.com/v2/servers/YOUR_COMMUNITY_ID/members/kick" \
      -H "Authorization: Bearer your-community-api-key" \
      -H "Content-Type: application/json" \
      -d "{\"accIds\":[\"91de0ce8-c571-11e9-9714-5600023b2434\"]}"

    Authorization

    Bearer <community-api-key>

    Content-Type

    application/json

    Response

    local response = client.radio:unbanMembersV2({
      "91de0ce8-c571-11e9-9714-5600023b2434"
    }, 1)
    const response = await instance.radio?.unbanMembersV2([
      "91de0ce8-c571-11e9-9714-5600023b2434"
    ], 1);
    response = instance.radio.unbanMembersV2([
        "91de0ce8-c571-11e9-9714-5600023b2434"
    ], 1)
    var response = await sonoran.Radio.unbanMembersV2(new[]
    {
        "91de0ce8-c571-11e9-9714-5600023b2434"
    });
    openapi: 3.1.0
    paths:
      /v2/servers/{communityId}/members/unban:
        post:
          security:
            - bearerAuth: []
    curl -X POST "https://api.sonoranradio.com/v2/servers/YOUR_COMMUNITY_ID/members/unban" \
      -H "Authorization: Bearer your-community-api-key" \
      -H "Content-Type: application/json" \
      -d "{\"accIds\":[\"91de0ce8-c571-11e9-9714-5600023b2434\"]}"

    Opening in a Framework Server (QBCore, Qbox, etc.)

    Item Drop

    Dropping scanners is not currently supported in OX inventory.

    Support will be added at a later date, pending more information from the OX development team.

    Radio Scanner Menu

    Permanent Scanners

    Configuring Permanent Scanners

    Example Scanner JSON

    Finding Channel IDs

    Developers

    Ace Permissions

    Giving the Scanner Item (QBCore)

    ace permission
    scanner menu
    View our complete list of supported FiveM frameworks an inventories.
    private channels
    configure ACE permissions to access them
    dispatcher panel
    in-game radio
    dispatcher panel
    in-game radio
    Learn more about our paid subscription plans.
    Sonoran Radio Scanner Item in Inventory
    Sonoran Radio Scanner Item Drop Use Hint

    Click Properties


    1. Under the General tab:

      • ❌ Uncheck Read-only

    2. Click Apply

    3. Click OK

    This allows the file to be both read and written by the server.


    Apply the change to the entire folder:

    1. Right-click the sonoranradio folder

    2. Click Properties

    3. Uncheck Read-only

    4. Click Apply

    5. Select Apply changes to this folder, subfolders, and files

    6. Click OK


    (ZAP-Hosting, Gamepanel, Pterodactyl, VPS)

    Log into the panel where your FiveM server is hosted.



    Set the file permissions so the server can write to it:

    • Recommended: 766

    • If that fails: 666

    If your panel supports it:

    1. Right-click config.lua

    2. Select Permissions

    3. Apply the change

    ⚠️ If your panel does not allow permission changes, contact your hosting provider and ask them to make the file writable.


    Each permission digit is the sum of:

    • 4 = Read (r)

    • 2 = Write (w)

    • 1 = Execute (x)

    • 0 = --- (No access)

    • 4 = r-- (Read only)

    • 6 = rw- (Read + Write)

    • 7 = rwx (Read + Write + Execute)

    Example:

    • 766 → Owner has full access, group/others can read & write

    • 666 → Read & write for everyone (no execute)


    After making changes, restart the resource or server:

    SonoranRadio – Fix “Config File Is Read-Only” Error

    Step 1: Open Your Game Panel

    Step 2: Locate the Config File

    🪟 WINDOWS HOSTS

    Step 1: Locate the file

    Step 2: Open file properties

    Step 3: Allow Read & Write access

    If it keeps reverting to Read-Only

    🐧 LINUX HOSTS

    Step 1: Open your game panel or file manager

    Step 2: Locate the config file

    Step 3: Fix file permissions

    Linux File Permissions – Quick Reference

    Common Permission Values

    Permission Structure

    Final Step: Restart SonoranRadio

    openapi: 3.1.0
    paths:
      /v2/servers/{communityId}/members/permissions:
        patch:
          security:
            - bearerAuth: []
    curl -X PATCH "https://api.sonoranradio.com/v2/servers/YOUR_COMMUNITY_ID/members/permissions" \
      -H "Authorization: Bearer your-community-api-key" \
      -H "Content-Type: application/json" \
      -d "{\"userPerms\":[{\"accId\":\"91de0ce8-c571-11e9-9714-5600023b2434\",\"perm\":34}]}"
    {
      "updatedAccIds": [
        "91de0ce8-c571-11e9-9714-5600023b2434"
      ]
    }
    openapi: 3.1.0
    paths:
      /v2/servers/{communityId}/members/display-names:
        patch:
          security:
            - bearerAuth: []
    curl -X PATCH "https://api.sonoranradio.com/v2/servers/YOUR_COMMUNITY_ID/members/display-names" \
      -H "Authorization: Bearer your-community-api-key" \
      -H "Content-Type: application/json" \
      -d "{\"accNicknames\":[{\"accId\":\"91de0ce8-c571-11e9-9714-5600023b2434\",\"nickname\":\"Chief Miller\"}]}"
    {
      "updatedAccIds": [
        "91de0ce8-c571-11e9-9714-5600023b2434"
      ]
    }
    {
      "approvedAccIds": [
        "91de0ce8-c571-11e9-9714-5600023b2434"
      ]
    }
    # Start the sonoranradio resource
    ensure sonoranradio
    
    # Permissions for auto-updater (REQUIRED)
    add_ace resource.sonoranradio command allow
    add_ace resource.sonoranradio_updatehelper command allow
    
    # ----------------NEW----------------
    # Big Daddy Radio Animation Script
    ensure BigDaddy-RadioAnimation
    {
      "kickedAccIds": [
        "91de0ce8-c571-11e9-9714-5600023b2434"
      ]
    }
    {
      "unbannedAccIds": [
        "91de0ce8-c571-11e9-9714-5600023b2434"
      ]
    }
    # Give the group access to /radio scanner
    add_ace group.admin sonoranradio.scanner allow
    
    # Only public (non-private) channels are accessible
    # Grant access to a private channel with the ID of 123
    add_ace group.admin sonoranradio.channel.123 allow
    /giveitem <playerId> sonoran_radio_scanner 1
    {
        "Id": "036a2ad1-eeae-4519-be4c-67157b8a035d",
        "Note": "Sandy Sheriff Station",
        "Powered": true,
        "ChannelId": 31226,
        "PropModel": "prop_cs_hand_radio",
        "PropPosition": {
            "x": 1853.98,
            "y": 3688.92,
            "z": 34.38054,
            "heading": 32.76,
            "exact": false
        }
    }
    resources/sonoranradio/config.lua
    resources\sonoranradio\config.lua
    resources/sonoranradio/config.lua
    OWNER | GROUP | OTHERS
      X   |   Y   |   Z
    restart sonoranradio
    In the channel editor, you can select the desired voice effect. This voice effect will apply to anyone talking in that channel.

    User-side voice FX can bypass channel effects, but enabling Vocoder FX forces all transmissions through the vocoder, ensuring it still applies to all custom FX.

    Sonoran Radio: Channel Voice Effect

    To apply a custom voice effect for emergency phone calls, toggle the phone icon in the voice effect tab.

    Note: If no custom voice effect is selected for emergency calls, a default "tin can" EQ effect will be applied.

    Sonoran Radio: Emergency Call Voice Effect Selection

    You can import and export voice effect profiles to share with other communities. See some of our public effect examples to import.

    To Export:

    • Click the Import/Export Button.

    • Click Download to save the current voice effect to a JSON file.

    To Import:

    • Click the Import/Export Button.

    • Click the file icon to import a JSON file directly.

    • Or, paste the JSON contents into the Import box and press Import.

    We've pre-configured voice effects for popular use. Copy the JSON code below to import into your voice effects panel.

    These voice effects combines the vocoder with pre and post-effect EQ customizations for the best possible clarity.

    Click to listen to this example.

    Click to listen to this example.

    This voice effect utilizes EQ customizations for the best possible phone call effect.

    Click to listen to this example.

    Available Voice Effects

    Vocoder

    The vocoder effect remains consistent and does not fluctuate based on in-game signal strength

    Vocoder

    The Vocoder voice effect simulates a modern P25-style radio compression using an AMBE-like encoding approach, commonly heard in proprietary digital radio systems. It’s ideal for communities seeking realistic conditions and authentic downsides.

    When enabled, audio is routed through a vocoder for encoding and decoding before broadcast, causing a slight transmission delay.

    The vocoder has optional bitrates of 3200, 2400, 1600, 1400, 1300, 1200, 700 and 450 bit/s. While the suggested bitrate is 2400, the bitrate can be increased for "less effect" or increased for "more effect".

    It is recommended to use the in addition to the vocoder to have in-game signal strength impact the transmission quality.

    Clipping

    Clipping

    The clipping voice effect mutes or "clips" audio intermittently based on in-game signal strength. As the signal weakens, more audio is cut, making transmissions increasingly difficult to understand.

    Digital

    Digital

    The digital voice effect applies bitrate compression to the audio, causing it to sound increasingly robotic and harder to understand as signal quality decreases.

    Analog

    Analog

    The analog voice effect adds static and scratchiness to the audio, making it sound progressively fuzzier and less clear as signal quality deteriorates.

    Equalizer (Pre & Post-Effects)

    This EQ effect remains consistent and does not fluctuate based on in-game signal strength

    Equalizer

    The equalizer effect allows you to boost or reduce frequencies throughout the audio range. &#xNAN;Tip: For a "tin can" effect, increase the mid frequencies while reducing the low and high ranges.

    Pre-Effect EQ

    The pre-effect EQ is a profile applied directly to the mic input before any effects (vocoder, digital, analogue, etc.) are applied. This can help improve clarity with the vocoder, grant a tin-can style effect, and more.

    Post-Effect EQ

    The post-effect EQ is a profile applied to the audio after all effects have been processed. This can help improve clarity and improve the finalized effects.

    Applying the Voice Effect

    On the User-Side

    Enabling the vocoder locally forces your client to encode and decode all incoming transmissions, which can impact performance at higher user counts.

    For better performance, enable the vocoder at the channel level so users pre-process transmissions on their end.

    When a channel has vocoder FX enabled, it cannot be bypassed client-side—all transmissions are already vocoded before playback.

    To Radio Channels

    bypass the community set channel effects
    Sonoran Radio: Voice Effect Customization
    {"id":11,"label":"Vocoder Example #1","vocoder":{"mode":"3200","enabled":true},"equalizer":[{"q":1,"freq":31,"gain":-20,"type":"lowshelf","freqlabel":"<31","bandwidthLabel":"2.5"},{"q":1,"freq":62,"gain":-20,"type":"peaking","freqlabel":"63","bandwidthLabel":"1.8"},{"q":1,"freq":125,"gain":-4,"type":"peaking","freqlabel":"125","bandwidthLabel":"1.2"},{"q":1,"freq":250,"gain":0,"type":"peaking","freqlabel":"250","bandwidthLabel":"0.6"},{"q":1,"freq":500,"gain":0,"type":"peaking","freqlabel":"500","bandwidthLabel":"0.0"},{"q":1,"freq":1000,"gain":-3.5,"type":"peaking","freqlabel":"1k","bandwidthLabel":"0.0"},{"q":1,"freq":2000,"gain":0.5,"type":"peaking","freqlabel":"2k","bandwidthLabel":"1.2"},{"q":1,"freq":4000,"gain":1.5,"type":"peaking","freqlabel":"4k","bandwidthLabel":"1.8"},{"q":1,"freq":8000,"gain":4.5,"type":"peaking","freqlabel":"8k","bandwidthLabel":"2.5"},{"q":1,"freq":16000,"gain":13.5,"type":"highshelf","freqlabel":">16k","bandwidthLabel":"2.5"}],"equalizerGain":{"low":0,"mid":0,"high":0},"postEqualizer":[{"q":1,"freq":31,"gain":-20,"type":"lowshelf","freqlabel":"<31","bandwidthLabel":"2.5"},{"q":1,"freq":62,"gain":-16.5,"type":"peaking","freqlabel":"63","bandwidthLabel":"1.8"},{"q":1,"freq":125,"gain":-12.5,"type":"peaking","freqlabel":"125","bandwidthLabel":"1.2"},{"q":1,"freq":250,"gain":-2,"type":"peaking","freqlabel":"250","bandwidthLabel":"0.6"},{"q":1,"freq":500,"gain":2.5,"type":"peaking","freqlabel":"500","bandwidthLabel":"0.0"},{"q":1,"freq":1000,"gain":3,"type":"peaking","freqlabel":"1k","bandwidthLabel":"0.0"},{"q":1,"freq":2000,"gain":5.5,"type":"peaking","freqlabel":"2k","bandwidthLabel":"1.2"},{"q":1,"freq":4000,"gain":1.5,"type":"peaking","freqlabel":"4k","bandwidthLabel":"1.8"},{"q":1,"freq":8000,"gain":-4,"type":"peaking","freqlabel":"8k","bandwidthLabel":"2.5"},{"q":1,"freq":16000,"gain":-1,"type":"highshelf","freqlabel":">16k","bandwidthLabel":"2.5"}],"clipDistortion":{"max":0.09,"min":0,"enabled":true,"aggressiveness":0.05},"analogDistortion":{"max":2,"min":0,"enabled":false,"aggressiveness":0.05,"constantStatic":0},"digitalDistortion":{"max":0,"min":0,"enabled":false,"aggressiveness":0,"constantStatic":0}}
    {"id":9,"label":"Vocoder Example #2 (More Bass)","vocoder":{"mode":"3200","enabled":true},"equalizer":[{"q":1,"freq":31,"gain":-20,"type":"lowshelf","freqlabel":"<31","bandwidthLabel":"2.5"},{"q":1,"freq":62,"gain":-11.5,"type":"peaking","freqlabel":"63","bandwidthLabel":"1.8"},{"q":1,"freq":125,"gain":-4,"type":"peaking","freqlabel":"125","bandwidthLabel":"1.2"},{"q":1,"freq":250,"gain":-10,"type":"peaking","freqlabel":"250","bandwidthLabel":"0.6"},{"q":1,"freq":500,"gain":-3,"type":"peaking","freqlabel":"500","bandwidthLabel":"0.0"},{"q":1,"freq":1000,"gain":4.5,"type":"peaking","freqlabel":"1k","bandwidthLabel":"0.0"},{"q":1,"freq":2000,"gain":-3.5,"type":"peaking","freqlabel":"2k","bandwidthLabel":"1.2"},{"q":1,"freq":4000,"gain":-4.5,"type":"peaking","freqlabel":"4k","bandwidthLabel":"1.8"},{"q":1,"freq":8000,"gain":-14,"type":"peaking","freqlabel":"8k","bandwidthLabel":"2.5"},{"q":1,"freq":16000,"gain":-18,"type":"highshelf","freqlabel":">16k","bandwidthLabel":"2.5"}],"equalizerGain":{"low":0,"mid":0,"high":0},"postEqualizer":[{"q":1,"freq":31,"gain":3,"type":"lowshelf","freqlabel":"<31","bandwidthLabel":"2.5"},{"q":1,"freq":62,"gain":3,"type":"peaking","freqlabel":"63","bandwidthLabel":"1.8"},{"q":1,"freq":125,"gain":3,"type":"peaking","freqlabel":"125","bandwidthLabel":"1.2"},{"q":1,"freq":250,"gain":3,"type":"peaking","freqlabel":"250","bandwidthLabel":"0.6"},{"q":1,"freq":500,"gain":3,"type":"peaking","freqlabel":"500","bandwidthLabel":"0.0"},{"q":1,"freq":1000,"gain":3,"type":"peaking","freqlabel":"1k","bandwidthLabel":"0.0"},{"q":1,"freq":2000,"gain":3,"type":"peaking","freqlabel":"2k","bandwidthLabel":"1.2"},{"q":1,"freq":4000,"gain":3,"type":"peaking","freqlabel":"4k","bandwidthLabel":"1.8"},{"q":1,"freq":8000,"gain":3,"type":"peaking","freqlabel":"8k","bandwidthLabel":"2.5"},{"q":1,"freq":16000,"gain":3,"type":"highshelf","freqlabel":">16k","bandwidthLabel":"2.5"}],"clipDistortion":{"max":0,"min":0,"enabled":false,"aggressiveness":0},"analogDistortion":{"max":0,"min":0,"enabled":false,"aggressiveness":0,"constantStatic":0},"digitalDistortion":{"max":0,"min":0,"enabled":false,"aggressiveness":0,"constantStatic":0}}
    {"id":10,"label":"Emergency Call Example","vocoder":{"mode":"3200","enabled":false},"equalizer":[{"q":1,"freq":31,"gain":-20,"type":"lowshelf","freqlabel":"<31","bandwidthLabel":"2.5"},{"q":1,"freq":62,"gain":-20,"type":"peaking","freqlabel":"63","bandwidthLabel":"1.8"},{"q":1,"freq":125,"gain":-20,"type":"peaking","freqlabel":"125","bandwidthLabel":"1.2"},{"q":1,"freq":250,"gain":-17,"type":"peaking","freqlabel":"250","bandwidthLabel":"0.6"},{"q":1,"freq":500,"gain":-5,"type":"peaking","freqlabel":"500","bandwidthLabel":"0.0"},{"q":1,"freq":1000,"gain":8.5,"type":"peaking","freqlabel":"1k","bandwidthLabel":"0.0"},{"q":1,"freq":2000,"gain":4,"type":"peaking","freqlabel":"2k","bandwidthLabel":"1.2"},{"q":1,"freq":4000,"gain":-8,"type":"peaking","freqlabel":"4k","bandwidthLabel":"1.8"},{"q":1,"freq":8000,"gain":-13.5,"type":"peaking","freqlabel":"8k","bandwidthLabel":"2.5"},{"q":1,"freq":16000,"gain":-20,"type":"highshelf","freqlabel":">16k","bandwidthLabel":"2.5"}],"equalizerGain":{"low":0,"mid":0,"high":0},"postEqualizer":[{"q":1,"freq":31,"gain":-20,"type":"lowshelf","freqlabel":"<31","bandwidthLabel":"2.5"},{"q":1,"freq":62,"gain":-20,"type":"peaking","freqlabel":"63","bandwidthLabel":"1.8"},{"q":1,"freq":125,"gain":-16.5,"type":"peaking","freqlabel":"125","bandwidthLabel":"1.2"},{"q":1,"freq":250,"gain":-6.5,"type":"peaking","freqlabel":"250","bandwidthLabel":"0.6"},{"q":1,"freq":500,"gain":0,"type":"peaking","freqlabel":"500","bandwidthLabel":"0.0"},{"q":1,"freq":1000,"gain":6.5,"type":"peaking","freqlabel":"1k","bandwidthLabel":"0.0"},{"q":1,"freq":2000,"gain":-4.5,"type":"peaking","freqlabel":"2k","bandwidthLabel":"1.2"},{"q":1,"freq":4000,"gain":-10.5,"type":"peaking","freqlabel":"4k","bandwidthLabel":"1.8"},{"q":1,"freq":8000,"gain":-16,"type":"peaking","freqlabel":"8k","bandwidthLabel":"2.5"},{"q":1,"freq":16000,"gain":-20,"type":"highshelf","freqlabel":">16k","bandwidthLabel":"2.5"}],"clipDistortion":{"max":0.07,"min":0.02,"enabled":true,"aggressiveness":0.02},"analogDistortion":{"max":1,"min":1,"enabled":true,"aggressiveness":0,"constantStatic":0},"digitalDistortion":{"max":0,"min":0,"enabled":false,"aggressiveness":0,"constantStatic":0}}

    To Emergency Calls

    Import and Export Effects

    Voice Profile Examples

    Vocoder Example

    #1 Vocoder

    #2 - Vocoder with Additional Bass

    Emergency Call Example

    QBCore Inventory

  • OX Inventory

  • QS Inventory

  • Core Inventory

  • To restrict radio and scanner access to users with the radio item in their inventory, set config.enforceRadioItem to true.

    Qbox requires you to manually add the following to your /ox_inventory/data/items.lua file. The config.lua's Config.RadioItem and Config.ScannerItem can not be used with Qbox.

    Currently, the following Qbox inventories are supported:

    • OX Inventory

    QBCore

    Configuration

    Inventory Restriction

    Inventory Item

    Config.Lua Properties
    -- Located in the Radio's config.lua
    Config.RadioItem = {		 --
    

    Supported Inventories (QBCore)

    radio scanner

    Qbox

    Configuration

    Inventory Restriction

    Inventory Item

    Ox Inventory Items File

    Supported Inventories (Qbox)

    Known Issues and Limitations

    OX Inventory

    OX Inventory Bugs and Limitations

    QBCore Support

    QS Inventory

    QS Inventory Bugs and Limitations

    Official Support

    While QS inventory has not been officially tested with Sonoran Radio, customers have reported it working with full functionality. Report any issues on our .

    The Sonoran Radio Stream Deck plugin allows you to rotate channels, groups, create custom XMIT and SCAN profiles, adjust system, channel, SFX, and AI volume, toggle overlays, and more. Additional integration for the Stream Deck + with dials offers unique integration.

    The physical in-game towers are able to be destroyed by criminals, which will devastate quality of radios around it.

    With three different in-game model types, Sonoran Radio takes immersion to the next level!

    See our info!

    Cellular Antenna
    Radio Tower
    Server Rack
    Sonoran Radio - Destructible Towers - Promotional Image

    Our 3D vehicle radio display reflects your channel information, transmitting user, and panic status in real time bringing new levels of immersion!

    Sonoran Radio - Vehicle Display

    Configure signal loss in tunnels, underground locations, and more!

    Sonoran Radio - Tunnel Detection

    Configure custom in-game items to jam nearby radio signals.

    Upload and customize dispatch tones for your community!

    Sonoran Radio's dispatch UI allows you to specify specific channels and groups, repeat tones, and more! You can even play tones on in-game speakers!

    Sonoran Radio - Tone Board
    Sonoran Radio - In-Game Speakers

    Customize digital and analog style voice effects for your community!

    Sonoran Radio - Custom Voice Effects

    Easily customize mic clicks, talkover protection tones, and more!

    Sonoran Radio: Custom Sound Effects

    Players in-game can call and speak directly with dispatchers for live emergencies!

    Sonoran Radio: In-Game Emergency Calls

    Customizing your radio has never been easier, with live updates from our easy-to-use configuration panel.

    Sonoran Radio - Customization Panel

    Easily visualize, manage users, play tones, and more!

    Sonoran Radio's dispatch UI is available everywhere on the web and desktop for Windows and OSX.

    Sonoran Radio - Dispatch Panel

    Sonoran Radio offers multiple in-game user interfaces, allowing you to stay connected on-foot, in-vehicle, and more!

    Choose from one of our radio style options, or even add your own!

    Sonoran Radio - Multiple Overlays - Promotional Image
    Sonoran Radio - Custom Frames

    Pulled over in a traffic stop? You'll hear the real radio chatter when an officer has an active radio nearby!

    Sonoran Radio - Nearby Radio Chatter

    In-game scanners allow you and others nearby to listen in on radio traffic!

    Sonoran Radio - In-Game Scanner

    Responding to a call? Sonoran Radio injects real-time sirens, gunshots, and more directly into your microphone feed for the ultimate immersion.

    Sonoran Radio - Background Noise Injection

    Transmit live AI updates of your location and speed for seamless pursuit coordination.

    Sonoran Radio - AI Pursuit Callouts

    Maintain your exclusive community branding by configuring a custom domain and vanity url!

    Get the most popular in-game radio animation script for FREE!

    Sonoran Radio x Big Daddy Scripts

    Hack into the integrated power grid to disable Sonoran Radio towers in your area! Learn more about this script!

    Sonoran Radio x Sonoran Power Grid - Promotional Image

    Sonoran Radio provides an optional integration to SonoranCAD through the FiveM resource. Turning this on takes the system to a whole new level.

    View dispatch call information on your in-game Sonoran Radio. CAD users can also see in-game towers, health, and signal range on the CAD live map!

    Sonoran CAD x Sonoran Radio

    Sonoran CMS allows you to automatically manage your community's Sonoran Radio permissions based on their CMS ranks and Discord roles!

    Sonoran CMS x Sonoran Radio
    Sonoran Radio x Sonoran MCC - Promotional Image
    Sonoran Radio x Sonoran MCC - Integrated Repeater - Promotional Image

    Sonoran's mobile command center enables you to take command like never before. This one-of-a-kind utility vehicle brings endless possibilities!

    Expand the pop-out sides for a walkable command center interior. Or, raise the radio antenna and scan the scene with 360 degree surveillance cameras!

    Paired with a standalone script, the mobile command center offers an integrated Sonoran Radio repeater and Sonoran CAD ALPR functionality!

    Sonoran Radio is always providing updates to help improve the experience, customizability, and realism of the product. We're always looking for new ideas and suggestions!

    What is Sonoran Radio?

    💸 Free!

    ✨ Dispatch AI

    🎮 Universal Desktop Overlay

    Getting Started

    ⌨️

    💣

    💻

    📶

    📶

    📢

    🎙️

    🔊

    🚨

    ☁️

    🎧

    📡

    🗣

    📻

    🎤️

    📡

    🌐

    🏃

    🔌

    🏆

    📁

    📋

    Name
    Value

    Authorization

    Bearer <community-api-key>

    URL Parameters

    Name
    Type
    Description

    communityId

    string

    Sonoran Radio community ID

    Examples

    local response = client.radio:getConnectedUsersV2
    const response = await instance.radio
    response = instance.radio.getConnectedUsersV2()
    var response = await sonoran.Radio
    openapi: 3.1.0
    paths:
    
    curl -X GET "https://api.sonoranradio.com/v2/servers/YOUR_COMMUNITY_ID/connected-users" 
    

    Successful requests return application/json.

    Get Connected Users

    {
      "connectedUsers": [
        {
          "identity": "91de0ce8-c571-11e9-9714-5600023b2434",
          "name": "Officer Smith",
          "metadata": "{\"sonrad\":true}",
          "roomId": 1
        }
      ]
    }

    Response

    Name
    Value

    Authorization

    Bearer <community-api-key>

    Content-Type

    application/json

    Examples

    local response = client.radio:playToneV2
    
    const response = await instance.radio
    
    response = instance.radio.playToneV2(
        
    
    var response = await sonoran.Radio
    
    openapi: 3.1.0
    paths:
    
    curl -X POST "https://api.sonoranradio.com/v2/servers/YOUR_COMMUNITY_ID/tones/play" \
      -H "Authorization: Bearer your-community-api-key" \
      -H "Content-Type: application/json" \
      -d "{\"roomId\":1,\"tones\":[12],\"playTo\":[{\"type\":\"channel\",\"value\":101}]}"

    Successful requests return application/json.

    Play Tone

    {
      "roomId": 1,
      "played": true
    }

    Response

    Name
    Value

    Authorization

    Bearer <community-api-key>

    Content-Type

    application/json

    Examples

    local response = client.radio:setInGameSpeakerLocationsV2
    
    const response = await instance.radio
    
    response = instance.radio.setInGameSpeakerLocationsV2([
        
    
    var response = await sonoran.Radio
    
    openapi: 3.1.0
    paths:
      /v2/servers/{communityId}/speakers:
        put:
          security:
            - bearerAuth: []
    curl -X PUT "https://api.sonoranradio.com/v2/servers/YOUR_COMMUNITY_ID/speakers" \
      -H "Authorization: Bearer your-community-api-key" \
      -H "Content-Type: application/json" \
      -d "{\"locations\":[{\"label\":\"Fire Station 123\",\"id\":\"STATION_123\"}]}"

    Successful requests return application/json.

    Set In-Game Speaker Locations

    {
      "locationsCount": 1
    }

    Response

    Name
    Value

    Authorization

    Bearer <community-api-key>

    Content-Type

    application/json

    Examples

    local response = client.radio:setServerIpV2
    
    const response = await instance.radio
    
    response = instance.radio.setServerIpV2({
        
    
    var response = await sonoran.Radio.setServerIpV2(new SetServerIpV2Request
    {
        ServerPort = 30120,
        PushUrl = "http://127.0.0.1:30120/sonoranradio",
        Nickname = "Patrol"
    });
    openapi: 3.1.0
    paths:
      /v2/servers/{communityId}/server-ip:
        post:
          security:
            - bearerAuth: []
    curl -X POST "https://api.sonoranradio.com/v2/servers/YOUR_COMMUNITY_ID/server-ip" \
      -H "Authorization: Bearer your-community-api-key" \
      -H "Content-Type: application/json" \
      -d "{\"roomId\":1,\"serverPort\":30120,\"pushUrl\":\"http://127.0.0.1:30120/sonoranradio\",\"nickname\":\"Patrol\"}"

    Successful requests return application/json.

    Set Server IP

    {
      "roomId": 1,
      "pushUrl": "http://127.0.0.1:30120/sonoranradio"
    }

    Response

    add_principal identifier.license:{GTA License} group.admin
    Group Permission Example
    # Add permissions to the ace category "sonoranradio.example"
    
    # Tower Configuration Menu
    add_ace sonoranradio.example command.radiomenu allow
    
    # Radio Access (Optional: If `acePermsForRadio` is `true` in config.lua)
    # If using `acePermSync` in config.lua, this will also auto-approve the user in the community
    add_ace sonoranradio.example sonoranradio.use allow
    
    # Radio Display Name Command Access
    
    

    3. Add Users to the ACE Group

    ACE Permission Sync

    ACE permission sync will override all existing user permissions.

    Any manually granted permissions will be removed, ensuring the user has only the permissions configured through ACE.

    Enable ACE Permission Sync

    Guest Login

    Restrict Guest Logins

    Permission Sync Options

    Community Approval

    Community members must be approved when first joining the radio. The approval behavior is dependent upon your config.lua's acePermsForRadio value.

    If acePermsForRadio is true users will need the sonoranradio.autoapprove permission to be automatically approved in the community.

    If acePermsForRadio is false users will be automatically approved when turning on the radio.

    Private Channels

    Access to private channels can be granted via ACE permissions.

    You will need the channel ID (visible in the dispatch panel or in-game radio) for each channel ACE permission.

    sonoranradio.channel.123

    General Permissions

    General radio community permissions can also be granted via ACE permissions.

    Admin: sonoranradio.admin

    Approve Members: sonoranradio.communityapprove

    Change Display Name: sonoranradio.setmynickname

    Manage Display Name: sonoranradio.setnickname

    Kick from Community: sonoranradio.communitykick

    Kick from Radio: sonoranradio.radiokick

    Move Radio Users: sonoranradio.radiomove

    Play Dispatch Tones: sonoranradio.radiotones

    Override Talkover Protection: sonoranradio.radiotalkover

    Permission Sync Example

    Permission Sync Configuration Example
    # Grant the ADMIN radio permission to everyone in the admin group
    add_ace group.admin sonoranradio.admin allow
    
    # Grant the talkover-override permission to everyone in the admin group
    add_ace group.admin sonoranradio.radiotalkover
    
    # Auto-approve everyone in the leo group
    add_ace group.leo sonoranradio.autoapprove allow

    ACE Permission Tools

    View other ways to manage user permissions.
    config.lua's Config.acePermSync value
    sign in as a guest
    config.lua's acePermsForRadioGuests property
    configured ACE permissions
    Sonoran CMS
    Sonoran CMS - QB Core Panel
    Sonoran CMS - vMenu Panel

    Authorization

    Bearer <community-api-key>

    Content-Type

    application/json

    curl -X PATCH "https://api.sonoranradio.com/v2/servers/YOUR_COMMUNITY_ID/rooms/1/users/91de0ce8-c571-11e9-9714-5600023b2434/channels" \
      -H "Authorization: Bearer your-community-api-key" \
      -H "Content-Type: application/json" \
      -d "{\"transmit\":[101],\"scan\":[101,102,103]}"
    {
      "identity": "91de0ce8-c571-11e9-9714-5600023b2434",
      "roomId": 1,
      "transmit": [101],
      "scan": [102, 103]
    }

    Response

    local response = client.radio:setUserChannelsV2(1, "91de0ce8-c571-11e9-9714-5600023b2434", {
      transmit = { 101 },
      scan = { 101, 102, 103 }
    }, 1)
    const response = await instance.radio?.setUserChannelsV2(
      1,
      "91de0ce8-c571-11e9-9714-5600023b2434",
      { transmit: [101], scan: [101, 102, 103] },
      1
    );
    response = instance.radio.setUserChannelsV2(
        1,
        "91de0ce8-c571-11e9-9714-5600023b2434",
        {"transmit": [101], "scan": [101, 
        1,
    )
    var response = await sonoran.Radio.setUserChannelsV2(
        "91de0ce8-c571-11e9-9714-5600023b2434",
        new { transmit = new[] { 101 }, scan = new[]
    );
    openapi: 3.1.0
    paths:
      /v2/servers/{communityId}/rooms/{roomId}/users/{identity}/channels:
        patch:
          security:
            - bearerAuth: []

    Shared Channels

    Setup

    Channels

    Channel Options

    Preview the AI Text-To-Speech

    In the admin Customize tab, hovering over green the channel audio icon will play the text-to-speech audio stating the channel name.

    A red icon indicates that the AI text-to-speech failed to generate. Simply re-save the channel to regenerate the audio file.

    Users can enable or disable the channel text-to-speech playing when switching channels in their settings menu.

    Customize the AI Pronunciation

    By toggling on the Advanced mode, you can manually adjust how the AI pronounces the channel name, which can be helpful for abbreviations and other non-common words.'

    Setting the Voice Effect

    Use the Voice Effect dropdown to set the custom voice effect style for the channel.

    Toggle Talkover Protection

    Toggle the Talkover prevention button to allow or prevent multiple users from talking at once.

    With talkover prevented, the talkover error sound will play and prevent the user from activating their mic.

    Restrict Channel Visibility

    Switch the channel's visibility to Public (everyone can see and connect) or Private to restrict which users can connect and transmit.

    Private channels will appear in the community member permissions tab, or be automatically managed with Sonoran CMS.

    Customize Channel Frequency

    With Advanced mode toggled, you can also customize the recieve and transmit frequency numbers for more realism.

    Sonoran Radio - Dispatch Panel Configure Channels
    AI Mode Toggle
    Temporary Per-Channel Push to Talk
    Tone Board
    Change Group Tab
    Change Channel
    Volume Change
    Requires Permission
    Requires Permission
    Requires Permission
    Requires Permission
    Sonoran Radio - Scan Channel
    Sonoran Radio - Switch Channel
    Sonoran Radio - Change Display Name

    In-Game Repeaters

    Configure and customize destructible radio towers in-game to impact radio performance.

    Available Repeater Types

    Server Rack

    Server rack style repeaters are found by default inside of police stations and hospitals. These repeaters offer the most interactive destruction experience.

    Press E on the door to open it.

    Each server inside can be individually destroyed and will fall separately out of the rack. These can be configured with 1-5 servers in each. As more of these servers are destroyed, the repeater signal will diminish.

    Server Rack
    Server Rack - Opened
    Server Rack - Destroyed

    Radio Tower

    Tower style repeaters are found by default on hills, mountains, and large rooftops.

    Players can climb the ladder to reach the top.

    There are four dishes inside that each account for 25% of the health. As more of these dishes are destroyed, the repeater signal will diminish.

    Cellular antenna style repeaters are found by default on the side of high-rises and other buildings.

    Destroying this antenna will disable it's repeater range.

    Additional integrations like the , , and offer further customization.


    To add, edit, or remove a repeater, open the configuration menu by typing /radioMenu

    Access to this command requires the sonoranradio.towers .

    Alternatively, you can edit the individual towers.json file in the sonoranradio resource.


    When tower destruction is enabled, users can use any form of weapon to damage the repeaters.

    Once damaged and destroyed, the tower no longer provides radio coverage within that range.

    Players can walk up to a destroyed repeater and press G to being the repair process.

    The repair time can be configured in the config.lua's towerRepairTimer.

    You can also restrict permissions to repairing a tower with by setting acePermsForTowerRepair to true in the config.lua.

    The configuration menu can be used to repair all repeaters on the map at once.

    EnablingConfig.debug in the config.lua file will display a radius around each tower, where the edge represents 50% radio quality.

    View Sonoran Radio repeater signal strength and health on the integrated CAD live map. Or, view dispatch call information on the in-game radio!

    Coming Soon!


    Sonoran Radio also allows you to configure tunnels and other areas where signal will be degraded!


    The also offers a built-in radio repeater to improve reception on a scene.

    Raise the radio antenna by running the /mccradio command.

    Communities can add additional integration support, enabling users to hack a radio repeater's power source instead of destroying it.

    To extend coverage range, communities can also customize what vehicles contain a radio repeater.

    In the config.lua, you can configure vehucle types and the range of a given vehicle's repeater.

    Example Config Structure:

    In-game, you can press G to toggle the mobile repeater on a configured vehicle.

    If a vehicle is destroyed, it will no longer function as a radio repeater.

    Stream Deck Plugin

    Sonoran Radio's official Stream Deck plugin gives you faster, customizable control over channels, volume, presets, and more.

    Introduction

    Sonoran Radio's MacOS and Windows desktop applications offer direct integration with Stream Deck hardware. By installing our official Stream Deck plugin, users can change channels, toggle preset channel groups, change channel and system volumes, and more - faster than ever before.

    Don't have a physical Stream Deck? Download the free Stream Deck Mobile app!

    Installation

    1. Download and Install the Plugin

    Download the official Sonoran Radio Stream Deck plugin from the Elgato Marketplace.

    2. Configure Actions

    Using the Stream Deck desktop application search for Sonoran Radio in the Keys and Dials sections.

    Drag-and-drop an action category to the Stream Deck. Select the action to update the sub-type.

    Ex: Channel key type > Toggle XMIT Channels > Select Channels

    Each action can be configured to control the desktop app (default) or .

    For clients using the in-game radio in FiveM, simply toggle each action from Desktop to FiveM.

    Sonoran Radio then acts as a local bridge between the Stream Deck, the desktop app, and the FiveM radio. The desktop app must be running, but does not have to have any radio community open or selected.

    1. Stream Deck sends the action to Sonoran Radio Desktop on localhost

    2. Sonoran Radio Desktop forwards the command to a localhost WebSocket

    3. your FiveM client script listens to that socket and forwards the event into the radio iframe/NUI

    4. the iframe/NUI sends radio state snapshots back through your FiveM client script to Sonoran Radio Desktop

    This means the normal setup for users is:

    • keep Sonoran Radio Desktop running

    • switch the Stream Deck action target to FiveM

    • run a FiveM client script that connects to the desktop socket and forwards the documented messages

    If you are implementing the FiveM side yourself, use the documented developer contract here:

    Stream Deck hardware with dials have the following supported actions:

    AI Keys

    Integrate Sonoran Radio with OpenAI.

    Sonoran Radio AI

    Sonoran Radio integrates with OpenAI to add additional features and functionality. Each feature can be easily enabled or disabled and have separate AI keys for optimal billing transparency.

    Generating an Open AI Key

    1. Login to the Open AI Platform

    Navigate to platform.openai.com and create an account.

    At the top left, select Create Project for a new category of Sonoran Radio API keys.

    OpenAI: Create Project
    OpenAI: Name Project

    2. Add Billing Information

    OpenAI charges based on usage for each model. You will need to add payment information for AI usage.

    Navigate to Settings > Billing > Add payment details to add a credit or debit card on file. Once added, you can manually add credits and set billing limits.

    With the new project selected, navigate to API Keys > Create new secret key

    Give the new API key a name (we recommend a separate key for for optimal billing transparency) and select your Sonoran Radio project.

    You can also restrict each key's model access based on the .

    In Sonoran Radio, navigate to Customize > AI > toggle on and paste in your new OpenAI API key for the specific feature.

    Dispatch AI offers in-depth integration to manage Sonoran CAD unit statuses, lookups, call creation, emergency calls, and more.

    • gpt-realtime-mini

    • gpt-5-nano

    • gpt-4o-mini-transcribe

    Transmission logs enable dispatchers to review and replay previous transmissions. With AI integration, these logs are enhanced with text transcripts, making it easier to search, reference, and analyze past communications efficiently.

    whisper-1

    Error Codes

    Learn more about specific in-game error and warning codes.

    This page documents the structured error and warning codes emitted by the Sonoran Radio FiveM resource.

    Direct links can target any code on this page using fragments such as #ERR-121.

    Internal Key: ERR_OX_LIB_NOT_STARTED

    Meaning: ox_lib must be started before Sonoran Radio when that dependency path is used.

    First Troubleshooting Step: Start ox_lib before Sonoran Radio and restart the resource.

    Authentication

    Learn how to authenticate requests against the Sonoran Radio v2 API.

    All current v2 API endpoints require bearer authentication.

    Header
    Value
    Description

    Hear Nearby Radio Chatter

    Pulled over in a traffic stop? You'll hear the real radio chatter when an officer has an active radio nearby!

    Pulled over in a traffic stop? You'll hear the real radio chatter when an officer has an active radio nearby!

    If someone nearby has a radio, you'll hear the radio traffic they’re listening to coming from their device. The closer they are the louder the radio traffic will be. However, if they're , the audio won’t be audible to others.

    When someone with a enters a vehicle, the radio audio will become muffled. However, if a door is open, or a window is down or broken, the audio will become clearer and louder again.

    When someone is , nearby users will faintly hear the dispatcher's voice coming from the caller's phone.

    When someone is carrying (or has placed down) , nearby users will hear the channel that the scanner is set to.

    Get Transmissions

    Page through recent transmission logs for a specific Sonoran Radio community.

    GET /v2/servers/:communityId/transmissions

    Rate limit: 12 requests per minute

    Returns paginated recent transmission log rows for the selected community.

    Headers

    In-Game Timeouts

    Learn more about in-game client timeouts throwing error messages.

    Some users may see SonoranRadio::ReceiveRadioStates listed multiple times after receiving a timeout.

    When your client receives a timeout from the server for any reason, it will display a list of the most recent requests. Because Sonoran radio frequently sends client data requests, these will consequently be displayed.

    This is not an issue with or related to Sonoran Radio. This is a general timeout between the client and server listing all recent calls as diagnostic information.

    102
    ,
    103
    ]},
    {
    101
    ,
    102
    ,
    103
    }
    }
    ()
    ?.
    getConnectedUsersV2
    ()
    ;
    .
    getConnectedUsersV2
    ();
    /v2/servers/{communityId}/connected-users:
    get:
    parameters:
    - in: path
    name: communityId
    required: true
    schema:
    type: string
    example: YOUR_COMMUNITY_ID
    security:
    - bearerAuth: []
    \
    -H "Authorization: Bearer your-community-api-key"
    (
    1
    , {
    12
    }, {
    { type = "channel", value = 101 }
    }, 1)
    ?.
    playToneV2
    (
    1,
    [12],
    [{ type: "channel", value: 101 }],
    1
    );
    1
    ,
    [12],
    [{"type": "channel", "value": 101}],
    1,
    )
    .
    playToneV2
    (
    new
    PlayToneV2Request
    {
    Tones = new object[] { 12 },
    PlayTo = new object[] { new { type = "channel", value = 101 } }
    });
    /v2/servers/{communityId}/tones/play:
    post:
    security:
    - bearerAuth: []
    ({
    {
    label = "Fire Station 123",
    id = "STATION_123"
    }
    }, 1)
    ?.
    setInGameSpeakerLocationsV2
    ([
    {
    label: "Fire Station 123",
    id: "STATION_123"
    }
    ], 1);
    {
    "label": "Fire Station 123",
    "id": "STATION_123",
    }
    ], 1)
    .
    setInGameSpeakerLocationsV2
    (
    new
    object
    ?[]
    {
    new { label = "Fire Station 123", id = "STATION_123" }
    });
    ({
    communityId = "YOUR_COMMUNITY_ID",
    roomId = 1,
    serverPort = 30120,
    pushUrl = "http://127.0.0.1:30120/sonoranradio",
    nickname = "Patrol"
    })
    ?.
    setServerIpV2
    (
    {
    communityId: "YOUR_COMMUNITY_ID",
    roomId: 1,
    serverPort: 30120,
    pushUrl: "http://127.0.0.1:30120/sonoranradio",
    nickname: "Patrol"
    });
    "
    communityId
    "
    :
    "
    YOUR_COMMUNITY_ID
    "
    ,
    "roomId": 1,
    "serverPort": 30120,
    "pushUrl": "http://127.0.0.1:30120/sonoranradio",
    "nickname": "Patrol",
    })
    add_ace sonoranradio.example sonoranradio.displayname allow
    # ACE Permission Sync (Optional: If `acePermSync` is `true` in config.lua)
    # See the "ACE Permission Sync" section below this documentation section for more info
    # This example auto-approves the user in the radio community
    add_ace sonoranradio.example sonoranradio.autoapprove allow
    # Tower Repair (Optional: If `acePermsForTowerRepair` is `true` in config.lua)
    add_ace sonoranradio.example sonoranradio.repair allow
    # Connected Users List (Optional: If `acePermsForRadioUsers` is `true` in config.lua)
    add_ace sonoranradio.example sonoranradio.radiousers allow
    # Radio Scanner Menu (Optional: If `chatter` is `true` in config.lua)
    add_ace sonoranradio.example sonoranradio.scanner allow
    # Radio Scanner Channel Access (Optional: If `chatter` is `true` in config.lua)
    # Number is based off of the channel ID
    add_ace sonoranradio.example sonoranradio.channel.123
    # Give the group access to /radio scanner
    add_ace group.admin sonoranradio.jammers allow
    # You can restrict specifc jammer types to specific ace groups
    add_ace group.admin sonoranradio.jammer_handheld allow
    Sonoran Radio - Client Timeouts
    clipping voice effect
    tower destruction and repairing
    Stream Deck Plugin
    In-Game Tower Destruction
    3D Vehicle Display
    Tunnel Signal Loss
    Signal Jammers
    Custom Tone Board
    Custom Voice Effects
    Custom SFX
    In-Game Emergency Calls
    Cloud Configurations
    Dispatch Panel
    Multiple Radio Options
    Hear Nearby Radio Chatter In-Game
    In-Game Scanners
    Background Noise Injection
    AI Pursuit Callouts
    Custom Domain and Vanity URL
    Free Animations Script
    Power Grid Support
    Sonoran CAD Integration
    Sonoran CMS Integration
    🚐
    Mobile Command Center Integration
    Frequent Updates
  • Stream Deck reads those snapshots for channel lists, labels, and action state

  • 3. Optional: FiveM Integration

    4. FiveM Developer Setup

    Capabilities

    Keys

    Channel Category Buttons

    Channel actions allow you to do somethin

    • Next Group

    • Previous Group

    • Next Channel

    • Previous Channel

    • Toggle XMIT Channels

      • Select one or more channels

      • Toggling this action will add and remove the selected channel(s) from your transmit list

    • Temporary XMIT Channel

      • Select a channel

      • Pressing this action will temporarily transmit in the selected channel and return to your previous channel(s) after release

    • Toggle Scan Channels

      • Select one or more channels

      • Toggling this action will add and remove the selected channel(s) from your scan list

    Toggle Category Buttons
    • Push to Talk

    • Toggle AI Mode

    • Toggle Tone Board

    Audio Category Buttons
    • Volume Up

    • Volume Down

    • SFX Volume Up

    • SFX Volume Down

    • AI Volume Up

    • AI Volume Down

    Desktop Category Buttons
    • Connected Users Overlay

    • Focus Radio Overlay

    • Toggle Radio Overlay

    Dials

    Dial Options
    • Cycle Groups (Prev/Next)

    • Cycle Channels (Prev/Next)

    • Adjust Volume

      • Optional Press to Mute

    • Adjust SFX Volume

      • Optional Press to Mute

    • Adjust AI Volume

      • Optional Press to Mute

    • Adjust Current Channel Volume

      • Optional Press to Mute

    FiveM in-game resource
    Stream Deck API

    gpt-4o-mini-tts

    3. Generate an API Key

    4. Add your API Key to Sonoran Radio

    AI Options

    Dispatch AI

    Model Requirements (OpenAI)

    Transmission Log STT (Speech-To-Text)

    Model Requirements (OpenAI):

    each AI feature
    specific feature's requirements
    OpenAI: Payment Details
    OpenAI: Payment Limits
    OpenAI: Generate Key
    OpenAI: Generate Key
    Sonoran Radio: OpenAI API Keys
    Internal Key: ERR_OX_LIB_INIT_LOAD_FAILED

    Meaning: Sonoran Radio could not load @ox_lib/init.lua.

    First Troubleshooting Step: Verify that ox_lib is installed correctly and that init.lua exists.

    Internal Key: ERR_OX_LIB_NOTIFY_UNAVAILABLE

    Meaning: ox_lib notifications were selected, but lib.notify was unavailable.

    First Troubleshooting Step: Confirm ox_lib is running and initialized without errors.

    Internal Key: ERR_RADIO_ITEM_INVENTORY_MISSING

    Meaning: enforceRadioItem is enabled, but no supported inventory resource was detected.

    First Troubleshooting Step: Start qb-inventory or ox_inventory, or disable Config.enforceRadioItem.

    Internal Key: ERR_RADIO_ITEM_FRAMEWORK_MISSING

    Meaning: enforceRadioItem is enabled, but no supported framework resource was detected.

    First Troubleshooting Step: Start qb-core or qbx_core, or disable Config.enforceRadioItem.

    Internal Key: ERR_API_CREDENTIALS_MISSING

    Meaning: The API key or community ID is missing from configuration.

    First Troubleshooting Step: Set apiKey and comId correctly in your config and restart the resource.

    Internal Key: ERR_API_FATAL_DISABLED

    Meaning: A fatal API error disabled radio API functionality until the issue is corrected.

    First Troubleshooting Step: Fix the reported API or community configuration issue, then restart the resource.

    Internal Key: ERR_API_CRITICAL_ABORTED

    Meaning: A request was aborted because the resource is already in a critical API error state.

    First Troubleshooting Step: Resolve the earlier fatal API error before retrying requests.

    Internal Key: ERR_FRAMES_DEPARTMENTS_MISSING

    Meaning: Config.frames.departments is missing for the selected frame permission mode.

    First Troubleshooting Step: Add the required departments list under Config.frames.departments.

    Internal Key: ERR_JAMMERS_PERMISSION_MODE_INVALID

    Meaning: The configured permission mode for radio jammers is invalid.

    First Troubleshooting Step: Review the jammer permission mode in config and change it to a supported option.

    Internal Key: ERR_RADIO_ITEM_CONFIG_MISSING

    Meaning: Radio item enforcement is enabled, but Config.RadioItem is missing.

    First Troubleshooting Step: Define Config.RadioItem or disable radio item enforcement.

    Internal Key: ERR_SCANNER_ITEM_CONFIG_MISSING

    Meaning: Scanner item enforcement is enabled, but Config.ScannerItem is missing.

    First Troubleshooting Step: Define Config.ScannerItem or disable scanner item enforcement.

    Internal Key: ERR_QBOX_OX_RADIO_ITEM_MISSING

    Meaning: The configured radio item does not exist in Ox Inventory on Qbox.

    First Troubleshooting Step: Add the radio item to /ox_inventory/data/items.lua or correct the configured item name.

    Internal Key: ERR_QBOX_OX_SCANNER_ITEM_MISSING

    Meaning: The configured scanner item does not exist in Ox Inventory on Qbox.

    First Troubleshooting Step: Add the scanner item to /ox_inventory/data/items.lua or correct the configured item name.

    Internal Key: ERR_COMMUNITY_CHANNELS_FETCH_FAILED

    Meaning: Community channels could not be fetched from the radio service.

    First Troubleshooting Step: Check the HTTP status in the server log and verify API connectivity.

    Internal Key: ERR_SKIN_SAVE_FAILED

    Meaning: A radio skin configuration file could not be saved.

    First Troubleshooting Step: Verify that the target file path is writable by the server process.

    Internal Key: ERR_CONFIG_SAVE_FAILED

    Meaning: A JSON configuration file could not be saved.

    First Troubleshooting Step: Check file permissions and confirm the resource directory is writable.

    Internal Key: ERR_SERVER_IP_SET_FAILED

    Meaning: Sonoran Radio could not register or update the server IP with the radio service.

    First Troubleshooting Step: Verify apiKey, comId, and outbound API connectivity.

    Internal Key: ERR_SERVER_IP_INVALID_ROOM

    Meaning: The radio service returned an invalid roomId while setting the server IP.

    First Troubleshooting Step: Check the API response and confirm the configured community is valid for radio.

    Internal Key: ERR_FRAMES_CONFIG_MISSING

    Meaning: Config.frames is missing.

    First Troubleshooting Step: Add the Config.frames block to your configuration.

    Internal Key: ERR_SERVER_SPEAKERS_SET_FAILED

    Meaning: Sonoran Radio could not synchronize in-game speaker locations with the radio service.

    First Troubleshooting Step: Check the API response and confirm speaker configuration is valid.

    Internal Key: ERR_SERVER_NAME_SET_FAILED

    Meaning: Sonoran Radio could not update a user display name in the radio service.

    First Troubleshooting Step: Verify API connectivity and confirm the target user exists in the linked community.

    Internal Key: ERR_INVALID_COMMUNITY_ID

    Meaning: The configured community ID is invalid or not enabled for the API.

    First Troubleshooting Step: Confirm the configured community ID belongs to a community with radio API access.

    Internal Key: WRN_LB_PHONE_NOT_STARTED

    Meaning: lb-phone integration is waiting for the lb-phone resource to start.

    First Troubleshooting Step: Start lb-phone if phone integration is expected.

    Internal Key: WRN_LUXART_RESOURCE_DEFAULTED

    Meaning: Config.luxartResourceName was empty, so the default lvc resource name was applied.

    First Troubleshooting Step: Set Config.luxartResourceName explicitly if your Luxart resource uses a different name.

    Internal Key: WRN_API_REQUEST_FAILED

    Meaning: A Sonoran Radio API request failed.

    First Troubleshooting Step: Inspect the logged request type and reason, then verify API connectivity.

    Internal Key: WRN_API_ENDPOINT_UNREGISTERED

    Meaning: An API request was attempted for an endpoint type that is not registered.

    First Troubleshooting Step: Register the endpoint type before making that request.

    Internal Key: WRN_GEO_ZONE_SYNC_FAILED

    Meaning: Geo and degrade zones could not be synchronized with the radio service.

    First Troubleshooting Step: Check the earlier API response details for the zone sync request.

    Internal Key: WRN_COMMUNITY_CHANNELS_FETCH_FAILED

    Meaning: Community channels could not be fetched for a player request.

    First Troubleshooting Step: Check the HTTP status in the warning and verify the player has valid access to radio data.

    Internal Key: WRN_SKIN_SAVE_DEBUG_BLOCKED

    Meaning: A client attempted to save a radio skin while debug mode was disabled.

    First Troubleshooting Step: Verify the caller is expected and only enable this workflow while debugging.

    Internal Key: WRN_CONFIG_RENAME_FAILED

    Meaning: A default configuration file could not be renamed to its writable target path.

    First Troubleshooting Step: Check whether the destination file already exists or is locked.

    Internal Key: WRN_CONFIG_SAVE_FALLBACK

    Meaning: Saving a configuration file failed, so Sonoran Radio fell back to writing the default file.

    First Troubleshooting Step: Check write permissions on the preferred config file path.

    Internal Key: WRN_SERVER_IP_USING_EXISTING_ROOM

    Meaning: The server IP update failed, but an existing roomId was reused while retrying in the background.

    First Troubleshooting Step: Confirm the existing roomId is still valid and investigate the API failure.

    Internal Key: WRN_SERVER_IP_RETRYING

    Meaning: The server IP update failed and will be retried.

    First Troubleshooting Step: Check API availability and confirm the configured credentials are correct.

    Internal Key: WRN_SERVER_ID_CONFIG_WRITE_FAILED

    Meaning: The resolved serverId could not be written back to config.lua.

    First Troubleshooting Step: Check whether config.lua is read-only or locked by the OS.

    Internal Key: WRN_APIKEY_CONVAR_UNINITIALIZED

    Meaning: The apiKey convar was not initialized from sonoranradio.cfg.

    First Troubleshooting Step: Ensure sonoranradio.cfg is executed before the resource starts.

    Internal Key: WRN_CHATTER_EXCLUSIONS_OVERWRITE_DEPRECATED

    Meaning: Config.chatterExclusions overwrote earpieces.json even though that config path is deprecated.

    First Troubleshooting Step: Remove Config.chatterExclusions from config and migrate to earpieces.json.

    Internal Key: WRN_CHATTER_EXCLUSIONS_DEPRECATED

    Meaning: Config.chatterExclusions is deprecated.

    First Troubleshooting Step: Move chatter exclusion management to earpieces.json or the in-game menu.

    The entries below are older support references that may still appear in existing guides, logs, or support replies.

    Sonoran Radio uses your CFX Nucleus Proxy URL to send push events from the radio to your game server. For example, this allows playing a tone on the radio to an in-game speaker.

    In the event that Sonoran Radio cannot obtain or verify your CFX Proxy URL, it tries to use your server's public IP address as a backup for push events. On some hosts, that fallback may also fail.

    If you receive this error, try setting Config.overridePushUrl to http://ip:port/sonoranradio/events, where ip:port is the IP and port of your FiveM server. The default FiveM port is 30120.

    If this does not resolve the issue, contact your host provider. They are likely blocking inbound traffic to your server.

    Sonoran Radio uses your CFX Nucleus Proxy URL to send push events from the radio to your game server.

    1. Check your server console for ERR 101. That error indicates a problem setting or validating the push URL.

    2. If you are using a non-FiveM server but still utilizing push events, ensure the pushUrl property is sent with a full HTTP(S) address with the set-server-ip API endpoint.

    Current Resource Codes

    Errors

    ERR-101

    ERR-102

    ERR-103

    ERR-104

    ERR-105

    ERR-106

    ERR-107

    ERR-108

    ERR-109

    ERR-110

    ERR-111

    ERR-112

    ERR-113

    ERR-114

    ERR-115

    ERR-116

    ERR-117

    ERR-118

    ERR-119

    ERR-120

    ERR-121

    ERR-122

    ERR-123

    Warnings

    WRN-201

    WRN-202

    WRN-203

    WRN-204

    WRN-205

    WRN-206

    WRN-207

    WRN-208

    WRN-209

    WRN-210

    WRN-211

    WRN-212

    WRN-213

    WRN-214

    WRN-215

    Legacy Troubleshooting Codes

    ERR 101: Unable to get a valid pushUrl

    ERR 102: No push event URL set

    Note: Changes to this item will require a server restart to take effect
    name = 'sonoran_radio', -- Item name in your inventory | STRING
    label = 'Sonoran Radio', -- Label for the item in your inventory | STRING
    weight = 1, -- Weight of the item in your inventory | INT
    description = 'Communicate with others through the Sonoran Radio', -- Description of the item in your inventory | STRING
    }
    Config.ScannerItem = {
    name = 'sonoran_radio_scanner', -- Item ID
    label = 'Sonoran Radio Scanner', -- Label for the item in your inventory
    weight = 1, -- Weight of the item in your inventory
    description = 'Listen to radio chatter with the Sonoran Radio Scanner', -- Description of the item in your inventory
    }
    OX inventory has officially dropped QBCore support in sole favor of the Qbox framework. However, full functionality can still work.
    support website
    ['sonoran_radio_scanner'] = {
            label = 'Sonoran Radio Scanner',
            description = 'Listen to radio chatter with the Sonoran Radio Scanner',
            weight = 1,
            client = {
                image = 'radio.png',
                remove = function(total)
                    if total < 1 then
                        TriggerServerEvent('SonoranRadio::DropItem::Scanner')
                    end
                end
            }
        },
        ['sonoran_radio'] = {
            label = 'Sonoran Radio',
            description = 'Communicate with others through the Sonoran Radio',
            weight = 1,
            client = {
                image = 'radio.png'
            }
        },

    Accept

    application/json

    Recommended for all requests

    Content-Type

    application/json

    Required for requests with a JSON body

    Authenticated server-specific requests use:

    For SDK clients, configure Radio with your public community ID. Room-scoped helpers also use the room ID configured on client creation.

    local Sonoran = require("sonoran"
    
    const Sonoran = require('@sonoransoftware/sonoran.js'
    
    from sonoran import Instance, productEnums
    
    instance = Instance(
        apiKey="YOUR_API_KEY",
        communityId="YOUR_COMMUNITY_ID",
        product=productEnums.RADIO,
        roomId=1,
    )
    
    response = instance.radio.getConnectedUsersV2()
    
    print(response.success)
    print(response.data if response.success else response.reason)
    using Sonoran;
    
    using var sonoran = new SonoranClient(new SonoranClientOptions
    {
        product = SonoranProduct.RADIO,
        communityId = "YOUR_COMMUNITY_ID",
        apiKey = "YOUR_API_KEY",
        roomId = 1
    });
    
    var response = await sonoran.Radio.getConnectedUsersV2();
    
    Console.WriteLine(response.success);
    Console.WriteLine(response.data);
    curl --request GET \
      --url "https://api.sonoranradio.com/v2/servers/YOUR_COMMUNITY_ID/connected-users" \
      --header "Authorization: Bearer YOUR_API_KEY" \
      --header "Accept: application/json"

    Successful responses return application/json.

    Authenticated v2 request failures return application/problem+json.

    Example:

    Status
    Cause

    401

    Missing Authorization header

    401

    Authorization header is not using the Bearer scheme

    401

    API key is invalid

    All v2 endpoints are rate limited per API key, not per caller IP. Limits vary by endpoint, so check the individual endpoint page for the current enforced limit.

    When a request is rate limited, the API returns 429 Too Many Requests.

    These retries are intentionally limited. High-frequency integrations should still avoid bursty request patterns and should respect the published per-endpoint limits.

    https://api.sonoranradio.com

    Authorization

    Bearer YOUR_API_KEY

    Authenticates the request

    Base URL

    Required Headers

    /v2/servers/{communityId}/...
    {
      "type": "https://httpstatuses.com/401",
      "title": "Unauthorized",
      "status": 401,
      "detail": "Missing Authorization header.",
      "instance": "/v2/servers/YOUR_COMMUNITY_ID/connected-users",
      "traceId": "00-abc123..."
    }

    Routing

    Example Request

    Response Formats

    Successful Requests

    Failed Requests

    Common Authentication Errors

    Rate Limits

    The volume of nearby radio chatter matches the volume setting of the emitting radio. Users with an active radio can adjust its volume using a hotkey or the settings menu.

    Players can adjust the nearby radio volume in-game using the /radiovolume command.

    Ex: /radiovolume 75 sets the nearby radio to 75% volume.

    Some communities may offer custom EUP (clothing and accessories) that players can use to personalize their characters. For radio users, an option to wear an earpiece (headphones) could be useful, allowing them to listen to radio chatter privately without others nearby overhearing.

    Whenever a user inserts or removes a configured in-game earpiece, a notification will be displayed confirming that others around you can or can not hear your radio.

    Communities can easily select which clothing items will be treated as a radio earpiece.

    Sonoran Radio: In-Game Radio Earpiece
    Sonoran Radio: Configure Earpieces

    Open the earpiece configuration menu via /radiomenu > Configure Earpiece Chatter

    Sonoran Radio Menu

    To add a chatter exclusion click "Add Earpiece Item" and select the component you'd like to add. Additionally, select any specific textures that will be considered an earpiece.

    Once selected, anyone wearing this earpiece will not emit radio chatter to nearby users.

    Add or Remove Earpiece
    Earpiece Item Selection
    Earpiece Texture Selection

    To remove an earpiece option, navigate to the Remove Earpiece Item Menu option > Select the specific earpiece item > and Confirm Removal

    Learn more about in-game radio scanners:

    Due to bandwidth usage, this feature is automatically enabled with the Pro version only!

    Learn more about our paid subscription plans.

    Video Example

    Audio Examples

    Nearby Radio

    Radio in Vehicle

    Nearby Emergency Phone Call

    Nearby Radio Scanner

    Usage

    Default Chatter Volume

    using an earpiece
    nearby radio
    making an emergency call to a dispatcher
    a radio scanner
    Sonoran Radio - Hear Nearby Chatter

    Adjust Volume

    Technical Information

    When a player is within 15 game units of an active radio, they will hear the live chatter from the nearest radio. If multiple radios within range are tuned to different channels, the player will hear all those channels blended, but the sound will primarily emit from the closest radio source.

    This feature is experimental and subject to both change and improvements.

    In-Game Earpiece

    1. Open the Earpiece Menu

    2. Toggle Earpiece Items

    3. Removing Earpieces

    Manual Earpiece IDs (Advanced)

    Manually Configure Earpiece IDs

    The earpieces.json file defines earpiece items (custom EUP prop IDs) that block radio chatter from being heard nearby.

    Component IDs

    Look for the component IDs for props (hats, glasses, earpieces, etc.). To find component IDs for drawables (shirts, pants, backpacks, etc.), look and add 14 to the number.

    For example, to exclude a clothing item under ACCESSORIES, it might look like this:

    Radio Scanners

    Radio Scanners
    Name
    Value

    Authorization

    Bearer <community-api-key>

    URL Parameters

    Name
    Type
    Description

    communityId

    string

    Sonoran Radio community ID

    Query Parameters

    Name
    Type
    Description

    page

    integer

    1-based page number. Defaults to 1.

    perPage

    integer

    Page size. Defaults to 25, maximum 100.

    Examples

    local response = client.radio:getTransmissionsV2
    
    const response = await instance.radio
    
    response = instance.radio.getTransmissionsV2({
        
    
    var response = await sonoran.Radio
    
    openapi: 3.0.3
    info:
    
    curl -G "https://api.sonoranradio.com/v2/servers/YOUR_COMMUNITY_ID/transmissions" \
      -H "Authorization: Bearer your-community-api-key" \
      --data-urlencode "page=1" \
      --data-urlencode "perPage=25"

    Successful requests return application/json.

    Get Transmissions

    {
      "transmissions": [
        {
          "id": "184927",
          "serverId": 12345,
          "account": "91de0ce8-c571-11e9-9714-5600023b2434",
          "channelId": 7,
          "time": "2026-06-18T18:42:31.000Z",
          "audioUrl": "https://cdn.example.com/transmissions/12345/2026-06-18_184231_audio.mp3",
          "transcript": "Unit 12, show me en route."
        }
      ],
      "pagination": {
        "page": 1,
        "perPage": 25,
        "total": 143,
        "totalPages": 6
      }
    }

    Response

    -- Enable mobile repeaters
    Config.enableVehicleRepeaters = true
    -- Mobile repeater spawncodes
    Config.repeaterVehicleSpawncodes = {
        {model = "police", label = "Police Vehicle", range = 200},
        {model = "police2", label = "Police Vehicle", range = 200},
    }

    Cellular Antenna

    Custom Repeaters

    Configuration

    Tower Placement

    Default Positions

    Game Menu Configuration

    Manual Configuration

    towers.json
    [
      // Radio Tower
      {
        // Unique Identifier
        "Id": "74d910e5-5705-4b58-baaf-88a8ca82734c",
        // Type of repeater (tower)
        "type": "radioTower",
        // XYZ Coordinates
        "PropPosition": {
          "x": -577.4769287109375,
          "y": -138.4747314453125,
          "z": 51.9765625
        },
        // Signal range in units
        "Range": 1500,
        // Allow destruction
        "Destruction": true
      },
      // Server Rack
      {
        // Unique Identifier
        "Id": "50a9c40a-e5bb-46b2-9a83-c5164599c64c",
        // Type of repeater (Server Rack)
        "type": "serverRack",
        // XYZ Coordinates
        "PropPosition": {
          "x": 443.3538513183594,
          "y": -983.1824340820312,
          "z": 30.6783447265625
        },
        // 360 degree compass heading for angles
        "heading": 90,
        // Signal range in units
        "Range": 1500,
        // Status of each server in rack: "alive" or "dead"
        "serverStatus": [
          "alive",
          "alive",
          "alive",
          "alive",
          "alive"
        ],
        // Is the repeater on or not
        "Powered": true,
        // Make the repeater invisible by setting to true
        "NotPhysical": false,
        // Temporary repeater
        "DontSaveMe": false,
        // Allow destruction
        "Destruction": true
      },
      // Cell Repeater
      {
        // Unique Identifier
        "Id": "1f68f034-500b-4b29-9356-8c8bf63fda04",
        // Type of repeater (cell repeater)
        "type": "cellRepeater",
        // XYZ Coordinates
        "PropPosition": {
          "x": 152.5,
          "y": -775.9000244140625,
          "z": 264.29998779296877
        },
        // 360 degree compass heading for angles
        "heading": 340.0,
        // Signal range in units
        "Range": 1500.0,
        // Is the repeater on or not
        "Powered": true,
        // Make the repeater invisible by setting to true
        "NotPhysical": false,
        // Temporary repeater
        "DontSaveMe": false,
        // Status of the antenna: "alive" or "dead"
        "AntennaStatus": "alive",
        // Allow destruction
        "Destruction": true
      }
    ]
    

    Using the In-Game Towers

    Destroying a Tower

    Repairing a Tower

    Individual Towers

    All Towers

    Viewing Tower Coverage

    Via In-Game Map

    Via Sonoran CAD Live Map

    Viewing Signal Strength

    Degrade Signals in Tunnels

    Additional Integrations

    Mobile Command Center Repeater

    Hacking Repeaters - Power Grid Integration

    Mobile (Vehicle) Repeaters

    mobile command center
    power grid hacking
    custom vehicle repeaters
    ACE permission
    ACE permissions
    Sonoran CAD Integration
    Tunnels and Degrade Zones
    Sonoran Mobile Command Center
    Sonoran Power Grid
    Radio Tower
    Radio Tower - Destroyed
    Cellular Antenna
    Cellular Antenna - Destroyed
    Sonoran Radio - Default Tower Positions
    Spawn Repeater
    Move/Edit Repeater
    Delete Repeater
    Sonoran Radio: Repair All Repeaters
    Sonoran Mobile Command Center
    Sonoran Mobile Command Center
    Sonoran Power Grid

    Customizing Radio Frames

    Customize your community's radio frames!

    Video Tutorial:

    Selecting Custom Frames

    Custom radio frames can be selected in the radio settings menu. Custom frames allow your community to create more UI options for each department!

    The drop-down menu will appear in your settings menu if you have one or more options available to you.

    Sonoran Radio - High Visibility Frame

    Restricting Custom Frames

    Restrict radio frames by department, job, or job grade, and set admin command permissions. Compatible with ESX, QBCore, or as a standalone.

    You can use CMS to automatically manage in-game ACE permissions, and even sync them with Discord roles!

    Example: SAHP department members with police job grades 1-3 can use frames:

    • default

    • signalpro

    • voxguard

    • hi-vis

    1. Navigate to the sonoranradio\skins directory.

    2. Locate a skin folder, which will contain 2-4 images and a skin.json file, displaying different frames.

    3. Observe the images, which include handheld, mobile, aircraft, and possibly HUD radio types.

    The following are valid as values for type:

    • portable - Used for handheld radios

    • vehicle - Used for mobile radios installed in a vehicle

    • hud - Top-down view of a portable radio

    With vehicle type frames, you can additionally customize the vehicleClasses property to whitelist the frame to specific vehicle types.

    For example, our default skin whitelists one frame to aircraft only: "vehicleClasses": [15, 16]. See available vehicle classes .

    1. In body, specify the image filename for each radio type. For instance, use radio-portable.png for a portable radio.

    2. Additionally, set the width value to define the image's display width in-game.

    1. Assign actions to buttons at specific positions on the radio image.

      • Example: Align a panic button hitbox with the panic button on the image, so clicking it in-game triggers a panic action.

    2. Available action types: power, next_preset, prev_preset

    Specify the position and width of the radio frame screen in Sonoran Radio to display information. Modify values under screen or miniScreen for HUD-type frames.

    For HUD-type frames, controls can be left blank.

    If you would like to use a text-style display instead of the normal radio screen, you can set the style to text. For example:

    Below is an example of a skin.json file:

    The frame placement menu offers rapid configuration of the screen size, location, and button placements.

    With debug mode enabled, open the menu by clicking on the icon in the top right of your screen.

    Select the skin ID and frame that you wish to edit. Then, select each property and utilize the arrow keys to adjust the configuration.

    Once complete, save your changes using the Save skin.json button.

    To get all available frames, utilize the following server-side export:

    To set a users frame, utilize the client-side event:

    In-Game Volume Too Low

    Having trouble hearing the radio in-game? You may need to increase the FiveM subprocess in your volume mixer.

    Sonoran Radio runs in FiveM's Chromium browser in-game. While FiveM is running, ensure that you have the volume for this turned up:

    Open the Volume Mixer via Windows search or right-clicking the sound icon in your taskbar.

    In the Volume Mixer adjust the volume of the FiveM Chromium Subprocess.

    If you're still having issues, you can manually enter a number higher than the 200% limit on the volume slider.

    ({
    page = 1,
    perPage = 25
    }, "YOUR_COMMUNITY_ID")
    ?.
    getTransmissionsV2
    (
    {
    page: 1,
    perPage: 25
    }, 'YOUR_COMMUNITY_ID');
    "
    page
    "
    :
    1
    ,
    "perPage": 25,
    }, "YOUR_COMMUNITY_ID")
    .
    getTransmissionsV2
    (
    new
    GetTransmissionsV2Query
    {
    Page = 1,
    PerPage = 25
    });
    title: Sonoran Radio API v2
    version: "1.0"
    servers:
    - url: https://api.sonoranradio.com
    components:
    securitySchemes:
    bearerAuth:
    type: http
    scheme: bearer
    paths:
    /v2/servers/{communityId}/transmissions:
    get:
    summary: Get paginated transmission logs
    parameters:
    - in: path
    name: communityId
    required: true
    schema:
    type: string
    example: YOUR_COMMUNITY_ID
    - in: query
    name: page
    schema:
    type: integer
    example: 1
    - in: query
    name: perPage
    schema:
    type: integer
    example: 25
    security:
    - bearerAuth: []
    responses:
    "200":
    description: Paginated transmission logs response
    "401":
    description: Missing or invalid bearer token
    "404":
    description: Community not found for this API key
    )
    local client = Sonoran.createClient({
    product = Sonoran.productEnums.RADIO,
    communityId = "YOUR_COMMUNITY_ID",
    apiKey = "YOUR_API_KEY",
    roomId = 1
    })
    local response = client.radio:getConnectedUsersV2()
    print(response.success)
    )
    ;
    (async () => {
    const instance = new Sonoran.Instance({
    communityId: 'YOUR_COMMUNITY_ID',
    apiKey: 'YOUR_API_KEY',
    product: Sonoran.productEnums.RADIO,
    roomId: 1,
    });
    const response = await instance.radio?.getConnectedUsersV2();
    console.log(response);
    })();

    404

    The requested communityId is not configured for the authenticated community

    Create a new skin folder and add your own frame images in the format you've observed in Step 3.

  • Copy over and modify an existing skin.json file to maintain format consistency.

  • In the skin.json file, specify the radio name and configure the frame types and body settings.

  • Configure the skin

    1. In the skin.json file, define the images for each radio type.

    2. Enable debug mode by setting Config.debug to true in your config.lua file.

    3. Use the for easy adjustments.

  • ,
    panic
    ,
    home
    ,
    hide
    .
    "screen": {
      "style": "text",
      "bottom": 17.625,
      "height": 7.875,
      "left": 5.125,
      "right": 5.875,
      "scale": 0.65
    }
    local frames = exports.sonoranradio:GetAvailableFrames(GetResourcePath('sonoranradio').. '/skins')
    print(json.encode(frames))
    -- Returns:
    -- ["default","hi-vis","signalpro","voxguard"]
    -- Array of frame names 
    local frameName = "hi-vis" -- Frame/skin name | i.e. hi-vis, default, voxguard
    local source = 1 -- User's server ID
    TriggerClientEvent('SonoranRadio::AdminSkinChange', source, frameName)
    Config.frames
    Config.frames = {
    	permissionMode = 'ace', -- ace, qbcore, esx or none
    	adminPermission = 'sonoranradio.admin', -- ACE permission required to use admin commands
    	departments = {
    		['sahp'] = {
    			label = 'San Andreas Highway Patrol',
    			permissions = {
    				jobs = { -- Jobs that can use this department
    					['police'] = {
    						grades = { -- Job grades that can use this department
    							1,
    							2,
    							3
    						}
    					}
    				},
    				ace = { -- ACE Permissions that can use this department | ONLY EFFECTIVE IN ACE PERMISSION MODE
    					'sonoranradio.sahp'
    				}
    			},
    			-- Radio frames that can be used by this department
    			allowedFrames = {
    				'default',
    				'signalpro',
    				'voxguard',
    				'hi-vis'
    			}
    		}
    	}
    }

    Customizing Radio Frames

    Frame Types

    Body Settings

    Controls

    Screen and Mini-Screen

    Screen Styles

    Example File

    skin.json
    {
      "name": "Moto AX",
      "frames": [
        {
          "type": "portable",
          "body": { "image": "radio-portable.png", "width": 17 },
          "controls": [
            {
              "action": "power",
              "bottom": 29.6,
              "right": 0.8,
              "width": 2.7,
              "height": 2.7
            },
            {
              "action": "next_preset",
              "bottom": 30,
              "right": 7.25,
              "width": 1.25,
              "height": 4.25
            },
            {
              "action": "prev_preset",
              "bottom": 30,
              "left": 7.125,
              "width": 1.25,
              "height": 4.25
            },
            {
              "action": "panic",
              "bottom": 29.75,
              "left": 4,
              "width": 2,
              "height": 1.25
            },
            {
              "action": "home",
              "bottom": 3.25,
              "left": 6.75,
              "right": 6.75,
              "height": 1.5
            }
          ],
          "screen": {
            "bottom": 5.875,
            "height": 18.125,
            "left": 3.2185,
            "right": 3.2,
            "zIndex": 5
          }
        },
        {
          "type": "vehicle",
          "body": { "image": "radio-mobile.png", "width": 45.125 },
          "controls": [
            {
              "action": "power",
              "top": 2.25,
              "left": 6.15,
              "width": 2,
              "height": 2
            },
            {
              "action": "prev_preset",
              "top": 2.25,
              "right": 17.25,
              "width": 1.5,
              "height": 2
            },
            {
              "action": "next_preset",
              "top": 5,
              "right": 17.25,
              "width": 1.5,
              "height": 2
            },
            {
              "action": "hide",
              "top": 8.25,
              "right": 17.25,
              "width": 1.5,
              "height": 1.5
            },
            {
              "action": "home",
              "top": 11.25,
              "right": 17.25,
              "width": 1.5,
              "height": 1.5
            },
            {
              "action": "panic",
              "top": 2.25,
              "right": 3.75,
              "width": 2,
              "height": 2
            }
          ],
          "screen": {
            "top": 2.65,
            "height": 10.2,
            "left": 11,
            "width": 13.45,
            "zIndex": 5
          }
        },
        {
          "type": "hud",
          "body": { "image": "radio-portable-top.png", "width": 22.25 },
          "controls": [],
          "miniScreen": {
            "bottom": 7.2,
            "height": 3.75,
            "left": 7.75,
            "right": 7.5
          }
        }
      ]
    }

    Frame Placement Menu

    Programmatically Changing Frames

    here
    Sonoran Radio - Vehicle Radio - Debug Mode Enabled
    Sonoran Radio Screen - Default
    Sonoran Radio Screen - Text
    Click the Volume button to change the slider to a number input, and carefully enter a number value higher than 200.
    Radio Volume: Manual Input

    FiveM Volume

    1. Access the Volume Mixer

    2. Adjust the FiveM Chromium Subprocess

    Manually Increase Radio Volume

    Windows Search: Volume Mixer
    Taskbar: Volume Mixer
    FiveM Chromium Subprocess Volume
    {
      componentId = 22, -- accessories (8) + offset (14) is 22
      drawableId = 78,  -- Number in vMenu
      texture = 0,      -- Number in vMenu (or 0 for all textures)
    }
    here
    here

    View and Compare Plans

    Learn more about pricing on Sonoran Radio standalone!

    Subscription Options

    All payment options are monthly or quarterly (3 month) subscriptions.

    Quarterly subscriptions offer a 25% discount.

    Subscription
    Monthly
    Quarterly

    Specific features are limited based on the subscription version. View the details below:

    Depending upon your subscription level, your community is limited to the maximum amount of users connected at one time.

    Subscription
    Limit

    Using multiple identical servers for overflow? Multi-server lets each server run independently while sharing the same channel setup, keeping communications separate and organized.

    Subscription
    Limit

    Customize your desktop overlay with unique radio frames for your community!

    Subscription
    Limit

    Pulled over in a traffic stop? You'll hear the real radio chatter when an officer has an active radio nearby!

    Subscription
    Limit

    Experience immersive, realistic transmissions with in-game sirens, rotor blades, gunfire, and more blended into your microphone audio.

    Subscription
    Limit
    • Key Up/Down SFX

    • Talkover Deny/Override SFX

    • Incoming Emergency Call SFX

    Subscription
    Limit
    • Key Up/Down SFX

    Subscription
    Limit
    Subscription
    Limit
    Subscription
    Limit
    Subscription
    Limit

    Get Members

    This endpoint gets paginated community members for a specific Sonoran Radio community.

    Get Members

    GET /v2/servers/:communityId/members

    Rate limit: 15 requests per minute

    Returns paginated community membership data, including approval state, permission level, and per-profile access.

    Headers

    Name
    Value

    URL Parameters

    Name
    Type
    Description

    Query Parameters

    Name
    Type
    Description

    Examples

    Successful requests return application/json.

    FiveM Keybinds & Commands

    Learn more about customizing your in-game FiveM keybinds.

    FiveM Keybinds

    Sonoran Radio allows you to customize keybinds for in-game actions on the radio.

    To customize these, navigate to your GTA Settings -> Key Bindings -> FiveM -> (sonoranradio)

    Communities can also customize the default keybinds for new users in the configuration's keybind property with the available options.

    FiveM Keybinds: Sonoran Radio

    Radio Power

    This keybind will turn your radio on/off.

    These keybinds will move you to the previous or next channel within the current channel group.

    These keybinds will move you to the previous or next channel group.

    This keybind will transmit your voice on the radio while being held down.

    This keybind will toggle your panic status in the radio, and in .

    Sonoran Radio has a to automatically press a users PTT button for a configurable amount of time when the user :

    This keybind will quickly adjust your volume up/down, .

    This keybind will toggle your .

    This keybind will display the .

    This keybind will toggle on/off the talking animation.


    Stream Deck plugins like can be used to trigger any of the below.


    FiveM commands require channel and scan list IDs. These IDs can be made visible by toggling the # icon in the channel or scan list menus.

    To toggle use the command

    /radio channel ID

    To toggle on/off a specific use the command

    /radio scanlist ID

    To toggle on/off use the command

    /radio scan ID


    Commands for the server console.

    Toggle the with the command

    sonoranradio debugmode

    Note: This mode does not persist through server restarts.

    Run the automatic update with the command

    sonoranradio update

    Set User Display Name

    Update a stored user display name for a specific Sonoran Radio server.

    Set User Display Name

    PATCH /v2/servers/:communityId/users/display-name

    Rate limit: 12 requests per minute This endpoint has a small internal gateway buffer, but the published public limit is 12 requests per minute.

    Updates a single member display name and propagates that update to connected sessions.

    Headers

    Name
    Value

    Examples

    Successful requests return application/json.

    Dispatch AI

    Speak to our AI dispatcher over the radio to manage CAD status, dispatch calls, run record lookups, and more.

    Coming soon!

    Vehicle Radio Display

    View Sonoran Radio on a working, in-vehicle 3D display!

    "Purchase" the free .

    Once purchased, see:

    Extract the script's two folders (sonoran-radiodisplay and sonoran-radiodisplay_helper) to a folder in your server's resources folder called [sonoranradio].

    Inside of the sonoran-radiodisplay

    Free

    $0/mo

    $0/qr

    Plus

    $14.99/mo

    $33.75/qr

    Pro

    $19.99/mo

    $45/qr

    Free

    10 Connected Users

    Plus

    30 Connected Users

    Pro

    Unlimited Connected Users

    Free

    1 Server

    Plus

    1 Server

    Pro

    Unlimited Servers

    Free

    Default three frames

    Plus

    Default three frames

    Pro

    Full frame customization

    Free

    🚫

    Plus

    🚫

    Pro

    ✅

    Free

    🚫

    Plus

    🚫

    Pro

    ✅

    Free

    🚫

    Plus

    ✅

    Pro

    ✅

    Free

    🚫

    Plus

    🚫

    Pro

    ✅

    Free

    🚫

    Standard

    🚫

    Pro

    ✅

    Free

    🚫

    Standard

    🚫

    Pro

    ✅

    Free

    🚫

    Standard

    ✅

    Pro

    ✅

    Subscription Limits

    Connected Users

    Multi-Server

    Desktop Overlay

    Hear Nearby Radio Chatter and Scanners

    In-Game Background Audio

    Community-Wide Sound Effect Customization

    Per-User Sound Effect Customization

    Transmission Logs

    Custom Domain

    Custom Community ID (Vanity URL)

    Sonoran Radio - Hear Nearby Chatter
    Sonoran Radio - Scanners

    status

    string

    Optional filter: pending, approved, or banned.

    sortBy

    string

    Optional sort field: username, displayName, approved, pending, permission, banned, or accId.

    descending

    boolean

    Set to true to sort descending.

    search

    string

    Optional search across username, display name, and account ID.

    Authorization

    Bearer <community-api-key>

    communityId

    string

    Sonoran Radio community ID

    page

    integer

    1-based page number. Defaults to 1.

    perPage

    integer

    Page size. Defaults to 25, maximum 100.

    Response

    local response = client.radio:getMembersV2({
      page = 1,
      perPage = 25,
      status = "approved",
      sortBy = "username",
      search = "dispatch"
    }, "YOUR_COMMUNITY_ID")
    const response = await instance.radio?.getMembersV2({
      page: 1,
      perPage: 25,
      status: 'approved',
      sortBy: 'username',
      search: 'dispatch'
    }, 'YOUR_COMMUNITY_ID');
    response = instance.radio.getMembersV2({
        "page": 1,
        "perPage": 25,
        "status": "approved",
        "sortBy": "username",
        "search": "dispatch",
    }, "YOUR_COMMUNITY_ID")

    Prev/Next Channel (In Group)

    Prev/Next Group

    Radio PTT

    Panic

    Auto PTT on Panic

    Volume Up/Down

    Toggle Radio Repeater

    Toggle Radio Users

    Toggle Radio Talk Animation

    Stream Deck Integration

    FiveM Client Commands

    Copying Channel and Scan List IDs

    Toggle Channel Transmit

    Toggle Scan List

    Toggle Channel Scan

    FiveM Server Commands

    Debug Mode Toggle

    Update Resource Command

    Sonoran CAD
    configurable option
    presses their radio panic button
    based on the percentage set in your settings menu
    vehicle's mobile signal repeater
    current radio connected user list
    FXCommands
    FiveM client commands
    transmitting on a specific channel
    scan list
    scanning a specific channel
    config.debug mode
    Modern UI: Channel and Scan IDs
    Modern UI: Channel IDs

    Authorization

    Bearer <community-api-key>

    Content-Type

    application/json

    Response

    local response = client.radio:setUserDisplayNameV2({
      communityId = "YOUR_COMMUNITY_ID",
      accId = "91de0ce8-c571-11e9-9714-5600023b2434",
      displayName = "Chief Miller"
    })
    const response = await instance.radio?.setUserDisplayNameV2({
      communityId: "YOUR_COMMUNITY_ID",
      accId: "91de0ce8-c571-11e9-9714-5600023b2434",
      displayName: "Chief Miller"
    });
    response = instance.radio.setUserDisplayNameV2({
        "communityId": "YOUR_COMMUNITY_ID",
        "accId": "91de0ce8-c571-11e9-9714-5600023b2434",
        "displayName": "Chief Miller",
    })
    var response = await sonoran.Radio.setUserDisplayNameV2(new SetUserDisplayNameV2Request
    {
        AccId = "91de0ce8-c571-11e9-9714-5600023b2434",
        DisplayName = "Chief Miller"
    });
    openapi: 3.1.0
    paths:
      /v2/servers/{communityId}/users/display-name:
        patch:
          security:
            - bearerAuth: []
    var response = await sonoran.Radio.getMembersV2(new GetMembersV2Query
    {
        Page = 1,
        PerPage = 25,
        Status = "approved",
        SortBy = "username",
        Search = "dispatch"
    });
    openapi: 3.0.3
    info:
      title: Sonoran Radio API v2
      version: "1.0"
    servers:
      - url: https://api.sonoranradio.com
    components:
      securitySchemes:
        bearerAuth:
          type: http
          scheme: bearer
    paths:
      /v2/servers/{communityId}/members:
        get:
          summary: Get paginated community members
          parameters:
            - in: path
              name: communityId
              required: true
              schema:
                type: string
                example: YOUR_COMMUNITY_ID
            - in: query
              name: page
              schema:
                type: integer
                example: 1
            - in: query
              name: perPage
              schema:
                type: integer
                example: 25
            - in: query
              name: status
              schema:
                type: string
                enum: [pending, approved, banned]
            - in: query
              name: sortBy
              schema:
                type: string
                enum: [username, displayName, approved, pending, permission, banned, accId]
            - in: query
              name: descending
              schema:
                type: boolean
                example: false
            - in: query
              name: search
              schema:
                type: string
                example: dispatch
          security:
            - bearerAuth: []
          responses:
            "200":
              description: Paginated members response
            "400":
              description: Validation failed
            "401":
              description: Missing or invalid bearer token
            "404":
              description: Community not found for this API key
    curl -G "https://api.sonoranradio.com/v2/servers/YOUR_COMMUNITY_ID/members" \
      -H "Authorization: Bearer your-community-api-key" \
      --data-urlencode "page=1" \
      --data-urlencode "perPage=25" \
      --data-urlencode "status=approved" \
      --data-urlencode "sortBy=username" \
      --data-urlencode "search=dispatch"
    {
      "members": [
        {
          "accId": "91de0ce8-c571-11e9-9714-5600023b2434",
          "username": "Officer Smith",
          "displayName": "Dispatch 101",
          "permission": 34,
          "profilePerms": [
            {
              "id": 12,
              "profileId": 7,
              "canJoin": true
            }
          ],
          "approved": true,
          "pending": false,
          "banned": false
        }
      ],
      "pagination": {
        "page": 1,
        "perPage": 25,
        "total": 1,
        "totalPages": 1
      }
    }
    Config.autoPttOnPanic = {
    	enabled = true, -- Enable automatic PTT when panic button is pressed
    	duration = 15 -- Duration in seconds to hold PTT when panic button is pressed
    }
    curl -X PATCH "https://api.sonoranradio.com/v2/servers/YOUR_COMMUNITY_ID/users/display-name" \
      -H "Authorization: Bearer your-community-api-key" \
      -H "Content-Type: application/json" \
      -d "{\"accId\":\"91de0ce8-c571-11e9-9714-5600023b2434\",\"displayName\":\"Chief Miller\"}"
    {
      "accId": "91de0ce8-c571-11e9-9714-5600023b2434",
      "displayName": "Officer Smith"
    }
    folder:
    • Rename config.changeme.lua to config.lua

      • See more about the configuration options here.

    • Rename radios.changeme.json to radios.json

    To start the display resource and give the auto-updater permissions to run, paste the following into your server.cfg

    The config.lua file allows you to customize the labels, ACE permissions, and more!

    Use the /radiodisplay command while in a vehicle to spawn a new display.

    • Use the keys displayed at the bottom of your screen to move and rotate the display into position.

    • Select Attach to attach the display to your vehicle.

      • See the config.lua Config.acePerms.aceObjectUseMenu for permission restrictions.

    • Select Apply to all of this vehicle model to have the radio display automatically added whenever the vehicle type is spawned.

      • See the Config.acePerms.aceObjectAdminUseMenu for permission restrictions.

    Property Name
    Example
    Notes

    ID

    2

    ID must be unique. No other radar can share this ID

    Position

    This is a table that contains the x, y, and z coords of the radar

    Command Name
    Command Description
    Required Permissions

    /radiodisplay

    This command will initiate the radar spawning and attaching process

    As configured

    Vehicle Spawncode
    Adds Radio by Default

    FBI

    yes

    FBI2

    yes

    POLICE

    yes

    Loving the radio display? Check out our in-vehicle police radar and radar detector displays!

    Sonoran Store: Radar Display
    Sonoran Store: Radar Detector
    • fix: Duplicate radio items when a passenger is in the vehicle

    • Initial Release

    Vehicle Radio Display (Video Tutorial)

    The vehicle radio display is a free Tebex script fully compatible with the free version of Sonoran Radio.

    Installation (Written)

    1. Download the Script

    2. Install the script

    A. Extract Folders

    B. Rename Config Files

    vehicle radio display from the Sonoran Store
    How to download the script from your Keymaster account.
    Sonoran Radio - Vehicle Display
    Radio Display - Folders
    # Start the Radio Display Resource
    ensure sonoran-radiodisplay
    
    # Grant permissions to the auto-updater
    add_ace resource.sonoran-radiodisplay command allow
    add_ace resource.sonoran-radiodisplay_helper command allow

    C. Start the Resource

    Configuration

    Default config.lua

    Spawning the Radio Display

    radios.json Property Explanation

    Commands

    Default Vehicles

    Additional Display Resources

    Changelog

    v1.0.1

    v1.0.0

    This feature is in a public BETA state.

    Services may be intermittent and unreliable. Some features may experience issues.

    Dispatch AI is not yet approved for full, production use. Utilize dispatch AI at your own risk.

    This feature requires both Sonoran CAD Pro and Sonoran Radio Pro.

    Learn more about our paid subscription plans.

    Setup Documentation

    1. Copy Sonoran CAD API Information

    Copy Sonoran CAD API Information

    Dispatch AI requires a Sonoran CAD community ID, API key, and server ID.

    The community ID and API key are located in the Admin panel > Advanced > In-Game Integration > API.

    The server ID can be found in the Admin panel > Customization > Servers. The default server ID is 1.

    2. Link CAD In Radio

    Link CAD In Radio

    In the radio Customization panel > Info > Select a server (or create one) and click on the Sonoran CAD icon. This will open a popup modal to enter in your CAD's community ID, API key, and server ID.

    3. Prompt Customization

    AI Prompt Phrases

    The AI has a set of tools it can use to take action in the CAD and on the radio—such as running lookups, creating calls, or updating statuses.

    Radio traffic varies by community. One agency might say, “show me out on traffic with a blue sedan,” while another says, “create a traffic stop call with a blue sedan.”

    Prompt phrase customization lets you train the AI to map your agency’s specific radio language to the correct system actions, so it responds appropriately to local lingo.

    Keep your phrases short and direct. Adding too many phrases can eventually overload the AI's context window.

    Enable/Disable the AI

    Manually

    The AI can be manually toggled on or off via the CAD link page.

    Auto Disable w/Human Dispatcher

    The AI can be automatically disabled whenever an active dispatcher is in the CAD.

    When this feature is enabled, the AI will check for a dispatcher once per minute.

    Using the AI

    Invoke the AI

    When first connecting to the radio, if you are the only user in the room, the AI agent may take up to 15 seconds to join.

    When the agent has joined, a brief "Dispatch Online" audio will play.

    FiveM users must be logged into the radio with their Sonoran account (4-digit link code on first use) or have ran /link in-game to link their CAD. Otherwise, Dispatch AI will be unable to determine the CAD user to run the AI actions against.

    Via Wake Work

    When pressing your push-to-talk key, a local AI listens to your microphone feed for the customizable wake word. By default, this is Dispatch.

    Users can customize their wake words by pressing the microphone button and speaking their custom wake words.

    Communities can also customize the default wake word for all users.

    Prompting the AI

    In order to reduce false triggers and conserve local resources, the AI will only listen to the first five seconds of your transmission. This amount can be modified in the Advanced tab of the Audio settings.

    Upon detection of the wake word, an audible beep indicates that the AI has been activated. Users may begin speaking before the beep is heard, as long as the tone occurs at some point during the same transmission.

    Example

    If your wake word is Dispatch, then your transmissions to the AI would be as follows:

    <wake word>, <optional: my unit number>, <action to do> Dispatch, A-10, mark me as available. Dispatch, A-10, run a lookup on the license plate ABC123

    Via Hotkey (Web and Desktop)

    Web and desktop users can also set a customizable hotkey in the settings menu. Pressing this keybind will enable the AI (same as the wake word) for your transmission.

    FiveM: Via Hotkey

    FiveM users can also set a manual keybind in the settings. Pressing this keybind will enable the AI (same as the wake word) for your transmission.

    User Customization

    Transcripts and Overrides

    A local speech-to-text AI generates a text transcript of your transmission. Sometimes, the AI can mishear common phrases resulting in poor performance.

    Users can view their latest transcripts under Settings > AI > Recent Transcripts.

    To improve these common mixups, add a Phrase Override manually.

    AI Commands & Features

    CAD Functionality

    CAD Status

    The AI can update the status of you and other units to the stated, customizable status code.

    Dispatch, A-10, mark my status as available. &#xNAN;Dispatch, A-10, set B-11 and I to 10-8.

    CAD Lookup

    The AI agent can perform a name or plate lookup, send the results to your CAD, and notify you of brief details.

    Dispatch, A-10, run a lookup on the plate ABC123. &#xNAN;Dispatch, A-10, do a record check on first name John last name Doe.

    CAD Dispatch Calls

    Create Call

    The AI can create a call and assign your unit. If your unit has a location, it will be automatically applied to the call unless otherwise specified. If a license plate is provided, it will automatically run a plate lookup and send the results to your CAD.

    Dispatch, A-10, show me out on traffic with a blue four-door sedan. License plate ABC123.


    Attach to Call

    The AI can attach you and other units to an existing call by mentioning the call ID, location, postal, title, etc.

    Dispatch, A-10, attach me to the robbery in progress call. &#xNAN;Dispatch, A-10, attach B-11 to my call.


    Call Notes

    The AI can add a note to your active dispatch call for other units to see.

    Dispatch, A-10, add a note on the call that I am arriving on-scene now, it's a white vehicle.


    Detach from Call

    The AI can lookup your current dispatch call and remove you from it.

    Dispatch, A-10, clear my call.


    Close Call

    The AI can lookup and close your current dispatch call. &#xNAN;Dispatch, A-10, close my call.

    CAD Unit Groups

    Group Units

    The AI can add your unit (and others) to a new or existing group.

    Dispatch, A-10, add me to group 'Ladder 12'. &#xNAN;Dispatch, A-10, add myself and B-11 to group 'Ladder 12'.


    Clear Unit Group

    The AI can remove your unit (and others) from a group.

    Dispatch, A-10, clear my unit group. &#xNAN;Dispatch, A-10, remove B-11 and I's unit group.

    CAD Panic

    Dispatch, A-10, toggle my panic status.

    The AI agent will enable or disable your panic status.

    FIveM: Emergency Call Readout

    In the Radio Zones menu, you can create custom zones and assign radio channels to each. When a 911 call is generated in CAD, the AI automatically creates a new dispatch call, reads the call over the channels configured for that zone, and removes the 911 call.

    FiveM: GPS Route to Postal

    In order to route your GPS to a postal code, the Nearest Postal resource is required. Or, another resource that can handle the command /postal <id>.

    The AI can draw an in-game GPS route to a postal code on the map.

    Raw Postal:

    Dispatch, A-10, route me to postal 123. &#xNAN;Dispatch, A-10, directions to postal 123.


    Postal on a Dispatch Call

    The AI can find an active dispatch call based on the ID, location, title, etc. &#xNAN;Dispatch, A-10, route me to call 123. &#xNAN;Dispatch, A-10, route me to the traffic stop call.

    FiveM: GPS Route to Unit

    The AI will route you to the coordinates of another active unit by providing their unit name, number, etc.

    Dispatch, A-10, route me unit B-11. &#xNAN;Dispatch, A-10, directions to unit J. Doe.

    FiveM: Auto-Status on GPS Route + Arrival

    This feature requires the Nearest Postal resource version v1.5.4 or newer.

    When the AI routes a user to a specific postal code or GPS coordinate (unit location) it will automatically set your status as en-route. Upon arrival, the AI will automatically mark your status as on-scene.

    The radio resource's config.lua contains Config.autoOnSceneStatus with options to tweak the settings.

    Radio Functionality

    Settings

    AI Volume

    The AI's reply volume can be changed in the settings menu.

    Hear AI Replies

    By default, users hear AI replies directed to anyone in their primary or scanned channel. The radio setting allows you to switch from hearing AI replies for all users to hearing only replies addressed to you.

    in-game frame placement menu

    Using the In-Game Radio

    Learn more about the in-game radio resource.

    Initial Setup

    Displaying the In-Game Radio

    By default, the radio display remains visible on-screen at all times. Users can toggle focus on the radio, enabling interaction when needed and un-focusing when done.

    1. Use the customizable keybind (Default is ~ right above tab)

    2. Use the /radio command

    Access to the radio can be restricted with .

    Use the purple button or icon on the radio frames:

    Use the /radio hide command in-game to hide the radio.

    You can also .

    You can logout/un-link your in-game radio via the settings menu (gear icon).


    Sonoran Radio offers three radio platforms: handheld, top-down HUD, and vehicle. All three radio platforms can have .

    When opening the radio via /radio the handheld radio will display on-screen. The vehicle UI will display when opening the radio inside of a vehicle. The top-down HUD style can be viewed with the /radiohud command.

    The settings menu also allows you to customize your radio frame:

    Learn more about customizable radio frames:

    Civilians can place an emergency call to speak directly with dispatchers:

    Unlock multiple more custom radio animations, FREE with Sonoran Radio pro!

    Installing the In-Game Resource

    Learn how to download and install the in-game resource.

    A. One-Click Installation (RocketNode)

    We've partnered with Rocket Node to bring you one-click Sonoran Radio installation for FiveM — making it easier than ever to host your community and connect with Sonoran Radio.

    • Purchase your FiveM Game Server!

    • Use code SONORAN to save big!

    B. Pre-Configured Resource Installation

    1. Download the ZIP

    Download a pre-configured version of the in-game resource from the panel. This download will already have your community ID and API key in the config.lua file.

    Navigate to Customization > FiveM Integration > Download Resource

    Extract the .zip file into your resources directory. Place the sonoranradio and sonoranradio_updatehelper into a folder labeled [sonoranradio]

    In your server.cfg file, add the following:



    ACE permissions allow communities to restrict access to actions like using the radio, adding and removing towers, repairing towers, and more.


    The Sonoran Radio in-game resource will automatically update with the latest features, fixes, and changes upon server restart!


    Learn how to customize and use the dispatch and in-game portals:

    Rotation

    This is a table that contains the x, y, and z rotation of the radar

    Vehicle

    POLICE

    This is the vehicles spawn code

    Bone

    -1

    This is the index of the bone you would like to attach the radar to

    POLICE2

    yes

    POLICE3

    yes

    POLICE4

    yes

    POLICEOLD1

    no

    POLICEOLD2

    no

    SHERIFF

    yes

    SHERIFF2

    yes

    Config = {}
    
    Config.debug_mode = false -- Enable debug mode
    Config.configuration_version = 1.0
    Config.auto_update = true -- Enable auto updates
    
    Config.lang = {
        addNewRadioHelp = 'Open the menu to begin spawning a new in-car model model',
        vehNotCompatible = 'This vehicle is not compatible with the in-car model placement system!',
        vehAlrRadio = 'This vehicle already has a valid in-car radio!',
        radioMenuHeader = 'Sonoran In-Car Radio',
        creditsPanel = 'Made by',
        spawningSubMenu = 'In-Car Radio Spawning',
        attachingSubMenu = 'Attaching',
        deletionSubMenu = 'Are you sure?',
        radioAttachMenuButton = 'Attach In-Car Radio',
        deleteMenuButton = 'Delete Current In-Car Radio',
        spawnMenuButton = 'Spawn In-Car Radio',
        deletionConfirmationButton = 'Yes, remove from all of these vehicles',
        deletionCancelButton = 'Cancel',
        deletionCancelled = 'In-Car Radio deletion cancelled',
        noRadioFound = 'No In-Car Radio is in this vehicle!',
        modelComboBox = 'Model:',
        vehAlrRadioNoti = '~r~This vehicle already has an In-Car Radio of this type',
        notInVeh = '~r~You must be in a vehicle!',
        vehicleBone = 'Radio - Vehicle Bone',
        object = "Object:",
        vehicleBoneComboBox = 'Vehicle Bone',
        objectName = 'Sonoran In-Car Radio',
        attachButton = 'Attach',
        detachButton = 'Detach',
        confirmPlacementButton = 'Apply to all of this vehicle model',
        cannotGoFaster = '~r~You cannot go any faster!',
        cannotGoSlower = '~r~You cannot go any slower!',
    }
    
    Config.commands = {
        carRadioMenu = 'radiodisplay',
        restricted = false -- should the radio display menu be restricted?
    }
    
    Config.permissionMode = "ace" -- Available Options: ace, framework, custom
    
    -- Ace Permissions Section --
    Config.acePerms = {
        aceObjectUseMenu = "sonoran.incarradio", -- Select the ace for placing new In-Car radios
        aceObjectAdminUseMenu = "sonoran.incarradio.admin", -- Select the ace for placing new In-Car radios into all vehicles of the same model
    }
    
    -- Framework Related Settings --
    Config.framework = {
        frameworkType = "qb-core", -- This setting controls which framework is in use options are esx or qb-core
        civilianJobNames = {"unemployed"}, -- An array of job names that should be allowed to use the radio menu
        adminJobNames = {"admin"}, -- An array of job names that should be allowed to use the radio menu as an admin
        useCivilianJobListAsBlacklist = false, -- This will treat the civilian job list as a blacklist rather than a whitelist
    }
    
    -- Configuration For Custom Permissions Handling --
    Config.custom = {
        checkPermsServerSide = true, -- If true the permission event will be sent out to the server side resource, this is recommended
        permissionCheck = function(_, type) -- This function will always be called server side.
            if type == 0 then -- Check permission to use the menu
                return true or false -- Return true if they have admin, return false if they don't
            end
        end
    }
    
    Config.general = {
        notificationType = "native", -- Available options: native, pNotify, okokNotify
        useAllowlistAsBlacklist = false, -- If true, the Config.allowlistedCars will be treated as an blacklist
    }
    
    Config.allowlistedCars = {
        "POLICE",
        "POLICE2",
        "POLICE3",
        "POLICE4",
        "FBI",
        "FBI2",
        "SHERIFF",
        "SHERIFF2",
    }
    
    config.lua
    exec @sonoranradio/sonoranradio.cfg

    2. Extract the ZIP File

    3. Update Your Server Config

    It is very important that the sonoranradio_updatehelper resource is not started manually. Doing so may cause a server crash if updates are available due to a race condition.

    DO NOT start the whole [sonoranradio] folder as that will also start the sonoranradio_updatehelper which might cause crashing if started manually.

    Example of what NOT to do: ensure [sonoranradio]

    Start this resource AFTER your preferred framework and any additional framework core resources such as inventory resources

    Configuration Values

    Configuration Options
    Parameter
    Default
    Description

    comId

    EMPTY

    ACE Permissions (Command Restrictions)

    Updates

    Next Steps

    Configuring ACE Permissions
    Usage
    Sonoran Radio - Folder Structure

    Hiding the In-Game Radio

    A. Via Button

    B. Via Command

    C. ESC Options

    Logging In

    Login with Account

    When you first use the in-game resource, you'll need to log in. A 4-digit code will appear for you to sign in from your browser.

    This will open sradio.link in a web browser, log in if needed, and your radio will be linked automatically with a 4-digit code.

    Sonoran Radio - Activate Link
    Login as Guest

    When you first use the in-game resource, you'll need to log in. If your community has ACE permissions configured, no account creation or link is necessary.

    Select Login as guest to bypass the account link and start using your radio. This guest option will only display if acePermsForGuests is set to true.

    Permission Configuration

    Learn how to configure ACE permissions for the radio.

    Display Name

    Custom display names are saved locally in your cache and automatically restored on future guest logins.

    Guest usernames are set in the following priority order (whichever is found first):

    • Last used guest display name

    • First and last name from QBCore, QBox, or ESX.

    • In-game display name

    .

    Logging Out

    Using the In-Game Radio

    Setting your Push-To-Talk (PTT) Keybind

    Connecting and Switching Channels

    Channel Selection via Knob

    The radio will connect when you turn it on with the power button (unless you need to login first).

    Previous/Next Channel (In Group)

    • Left click the top knob to rotate to the next channel inside the channel group.

    Previous/Next Group

    • Right-click the top knob to change its mode from channel changing to group changing.

    • Left click the top knob to rotate to the next channel group.

    Channel Selection via Menu

    Select the channel menu icon to open the channel selection options. Click on the channel you wish to transmit on.

    CTRL + Click allows you to select multiple channels to transmit on at once.

    Modern UI - Channel Menu Icon
    Text UI - Channel Menu Icon
    Modern UI - Channel Selection
    Text UI - Multi-Channel Selection
    Channel Selection via Hotkeys, Commands, and Stream Deck

    Channels can also be changed via:

    • Channel Change Keybind

    • In-Game Commands (Optional Stream Deck Integration)

    Channel Scanning/Listening

    Scanning Radio Channels

    Scanning a radio channel allows users to hear all transmissions, even if they are not actively transmitting on that channel. However, transmissions on the primary channel (the one you are actively talking on) will take priority, muting transmissions from scanned channels whenever someone speaks on the primary channel.

    Selecting Scanned Channels (Modern or Text Display)

    1. Select the Channel Scan Icon

    2. Select the channel group to view the contained channels

    3. Click on a channel to toggle on/off scanning

    Users can also to swap between multiple scanned channels at once.

    Custom Scan Lists

    Scan Lists

    Users can scan one or more channels to listen without transmitting. For monitoring multiple channels, "Scan Lists" let users group channels and easily switch between them.

    Creating a Scan List (Modern or Text Display)

    1. Toggle scanning on one or more channels.

    2. Select the + icon next to Scan Lists to create a new scan list with the current selection.

    3. Scan lists can be reordered via drag-and-drop.

    4. Select the adjust button to rename or remove the scan list.

    5. Click on the scan list to scan all of the channels inside of it.

    6. Scan lists can be reordered via drag-and-drop

    !

    Adjust Volume

    Your radio volume also controls how loudly nearby users hear the radio chatter.

    Radio Volume

    System-Wide Volume

    In the settings menu (gear icon) you can adjust the radio's total volume output.

    In-Game Radio - Settings

    Per-User Volume

    You can also right-click on any user to adjust their volume specifically.

    Per-Channel Volume

    Select the volume icon to change the current channel's transmission volume.

    Volume Hotkey

    The adjustment amount is customizable in the settings menu.

    Adjust Volume With Sirens

    Automatic Volume Increase w/Sirens

    When in-game, turning on your sirens will increase your overall radio volume by the configured amount. Turning your sirens back off will lower the volume back down.

    This feature is automatically integrated with Luxart Vehicle Control. If the resource is not named LVC, the config.luxartResourceName value must be updated.

    For communities not using LVC, the functionality will fall back to a FiveM native that will trigger the functionality if either lights or sirens are activated.

    Move and Resize the Radio

    If you move your radio too far off of your screen:

    Use /radio reset to reset the size and position.

    Radio Move and Resize

    On the radio screen, open the Settings modal by pressing the gear icon.

    Select Move/Resize

    • Click and drag the radio to change it's position on your screen.

    • Hold ctrl and drag to resize the radio.

    • Press esc to save the new size and position.

    Escape Mode

    ESC Radio Display Behavior

    The Escape Mode selector changes the in-game radio display behavior after pressing ESC. The server default for this setting can be configured in the config's defaultEscapeMode property.

    Keep Radio Visible

    • The radio stays visible on ESC

    Hide Radio

    • The radio closes on ESC

    XMITT (PTT)

    • The radio closes on ESC, but is visible while transmitting

    Panic

    In-Game Panic

    Pressing the orange panic button on the in-game radio toggles your panic status.

    This can also toggle your panic status in Sonoran CAD.

    Dispatchers will also be able to see and clear your panic status.

    Sonoran Radio has a configurable option to automatically press a users PTT button for a configurable amount of time when the user presses their radio panic button:

    Config.autoPttOnPanic = {
    	enabled = true, -- Enable automatic PTT when panic button is pressed
    	duration = 15 -- Duration in seconds to hold PTT when panic button is pressed
    }

    Display Names

    Update User Display Name

    View several different methods to update a user's display name in the radio.

    Radio Types

    Change Radio Frames

    Civilian Usage

    Placing an Emergency (911) Call

    Custom Animations

    ACE permissions
    customize the display behavior when pressing ESC
    You can customize your PTT button in your GTA Settings.
    customizable frame styles
    Customizing Radio Frames
    Emergency Calls
    Big Daddy Radio Animations
    Vehicle Radio: Hide Button
    Handheld Radio: Hide Button
    In-Game Radio - Settings
    In-Game Radio - Unlink
    Sonoran Radio - Custom Frames
    Sonoran Radio x Big Daddy Scripts

    Custom Tone Board

    Customize dispatch tones to broadcast to your units!

    Sonoran Radio: Tone Board

    Configuring the Tone Board

    Under the Customization tab, select Tone Board.

    Here, you can customize the name, icon, and color of existing tones or use the trash icon to remove a tone. Tones are sorted alphabetically.

    Or, use the bottom section to upload and configure a new tone.

    Uploading a Tone File

    Select the upload icon to attach an audio file.

    AI Text-To-Speech

    The tone board also allows you to customize AI generated text-to-speech tones.

    Additionally, you can .

    On the right of the new tone configurator, select the AI Mode button to change from file uploads to AI text-to-speech.

    Add the tone label, specify the text for the voice, and .

    Select the music icon on the left to customize the icon, background color, and text color.

    To quickly toggle the tone board, you may configure a custom hotkey in the settings menu.

    After opening the tone board via hotkey or the music note icon, you will see the following UI.

    • Search: Type-to-filter for available tone names

    • Saved Stacks: Saved, pre-created tone stacks

    • : Type-to-filter and multi-select the desired channels or channel groups

    Tones can be played to a channel, channel group, or an .

    For repeated tones, you can hover over the active tone (or tone stack) to see what channels and groups it's playing to.

    Additionally, the UI will reflect the remaining play count and show a progress bar for the delay until the next play.

    Stacked tones allow you to align multiple tones together and play them in order.

    Toggle on the Stack icon and click on tones in order. You can also drag-and-drop the stack at the bottom left to reorder tones prior to pressing Play.

    Tone stacks can be saved for faster re-use.

    After creating a stack press the Save icon. This will prompt you to enter in a stack name. Saved stacks will display on the Saved Stacks tab. Saved stacks can be "loaded" into the editor, played directly to your current Broadcast To channels, or deleted.

    Shortcuts:

    • Clicking a saved tone stack once will load the stack.

    • Double-clicking a saved tone stack will play it.

    The microphone icon allows you to record local microphone audio to be played as a tone to radios or .

    Click the Audio Recording to start and stop recording. After the recording is completed, a small recording tone button will appear next to it. Click to add it to a stack or play as a single tone.

    Similar to , the AI wand icon allows you to enter in and generate a temporary text-to-speech AI tone to be played as a tone to radios or .

    Enter text into the AI Text-To-Speech input or use the Microphone icon to enter text via voice recording. Press Enter to generate and send the text-to-speech tone to the broadcast or tone stack.

    Sonoran Radio: Customize Frames
    : Optionally toggle tone stacking to play multiple tones in order
  • Repeat: Optionally toggle on a tone repeat with a total play number and a delay between plays

  • Microphone: Record a temporary live audio tone from your microphone

  • AI TTS: Generate a temporary AI-powered text-to-speech tone

  • 1. Toggle AI Tone Mode

    2. Customize And Generate via AI

    Visual Customization

    Using the Tone Board

    Tone Board Hotkey

    Playing a Tone

    Tone Broadcast To Options

    Repeating Tones

    Stacked Tones

    Saved Stacks

    Recording Tones

    AI TTS

    generate temporary AI TTS tones directly inside of the tone board
    customize any other visual options
    Broadcast To
    in-game speaker
    in-game speakers
    pre-configured AI speech tones
    in-game speakers
    Sonoran Radio: Tone Visual Options
    Sonoran Radio - Tone Board Hotkey
    Sonoran Radio - Tone Board Broadcast Options
    Tone Board - Repeated Tones
    Tone Board - Stacked Tones
    Stack

    The Sonoran Radio Community ID

    apiKey

    EMPTY

    The Sonoran Radio Community API Key

    debug

    false

    Display tower ranges on the map and other console prints. This can be toggled live with the debug mode command.

    allowUpdateWithPlayers

    true

    Allow the auto-updater to run while players are still in the server.

    enableCanary

    false

    Allow the auto-updater to pull development branches for early testing.

    allowAutoUpdate

    true

    Allow the auto-updater to run.

    chatter

    true

    Allow civilians to hear radio chatter when one is nearby

    talkSync

    true

    Talk in-game whenever you talk on the radio If using BD Animations, you will also need to disable their TalkSync feature in the settings.ini file.

    emergencyCallCommand

    911

    Command suffix to start or stop an emergency call (i.e. '911' == /radio 911)

    luxartResourceName

    lvc

    Resource name for Luxart Vehicle Control, used for the siren volume integration.

    keybinds

    Config.keybinds = {
    	['toggle'] = '',
    	['ptt'] = 'BACKSLASH',
    ['power'] = '',['panic'] = '',['nextChannel'] = '',['prevChannel'] = '',['talkAnim'] = '',['nextGroup'] = '',['prevGroup'] = '',['volUp'] = '',['volDown'] = '',['toggleAutoCallouts'] = '',['toggleGeoSwitch'] = '',['toggleAi'] = '',
    }

    Default radio keybinds (these can be changed in GTA settings). Use the Input Parameter from the CFX Documentation.

    towerRepairTimer

    20

    Time (in seconds) that it takes a player to repair a destructed tower.

    rackRepairTimer

    15

    Time (in seconds) that it takes a player to repair a destructed server rack.

    antennaRepairTimer

    15

    Time (in seconds) that it takes a player to repair a destructed cellular antenna.

    acePermSync

    false

    Sync ACE permissions to auto-approve and grant radio permissions from in-game.

    acePermsForRadioGuests

    false

    Restricts the Login as Guest button to users with an ACE permission.

    acePermsForServerRepair

    false

    Restrict the ability to repair damaged radio repeaters with ACE permissions.

    ACE Command: sonoranradio.repair

    acePermsForTowerRepair

    false

    Restrict the ability to repair damaged radio repeaters with ACE permissions.

    ACE Command: sonoranradio.repair

    acePermsForAntennaRepair

    false

    Restrict the ability to repair damaged radio repeaters with ACE permissions.

    ACE Command: sonoranradio.repair

    acePermsForRadio

    false

    Restrict the usage of the radio (/radio) with ACE permissions. ACE Command: sonoranradio.use

    enforceRadioItem

    false

    Require the user to have a item in their inventory to be able to use the radio or radio scanner. View supported frameworks and inventories.

    acePermsForRadioUsers

    false

    Restrict the usage of the radio (/radiousers) with ACE permissions. ACE Command: sonoranradio.radiousers

    syncPlayerNameToRadio

    false

    Set the radio user's display name to match their in-game name.

    disableRadioOnDeath

    true

    Disables radio when dead.

    restoreRadioStateWhenAlive

    true

    Restore the radio's power state (on/off) when you are revived or respawn.

    deathDetectionMethod

    auto

    What method to use for death detection. auto, manual, or qbcore

    heavySignalDegradeInWater

    Config.heavySignalDegradeInWater = { -- Heavily degrade radio signal while the player is in water to mimic an IP67-rated handheld
    enabled = true, -- Set to true to enable heavy signal degrade in water
    pedInWaterDegredation = 0.6, -- Signal strength multiplier when the player is simply in water (e.g. 0.6 would reduce signal strength to 60% of normal)
    pedUnderWaterDegredation = 0.3 -- Signal strength multiplier when the player is underwater (e.g. 0.3 would reduce signal strength to 30% of normal)
    }

    Heavily degrade radio signal while the player is in water to mimic an IP67-rated handheld

    disableAnimation

    false

    Disable the radio talking animation for custom animation scripts.

    noPhysicalCellRepeaters

    false

    Hide the in-game cellular antenna repeaters

    noPhysicalRacks

    false

    Hide the in-game server rack repeaters

    noPhysicalTowers

    false

    Hide the in-game tower repeaters

    defaultEscapeMode

    keep

    The default escape behavior for the in-game radio. Options: keep, hide, transmit_only.

    autoCallouts

    {
    enabled = true, -- Whether or not this feature is enabled
    speedUnit = 'mph', -- mph | kmh | none -- The unit of speed provided with the callout
    withPostals = false, -- Whether to include postals with the automatic callouts
    postalResource = 'nearest-postal',
    }

    When enabled, user radios will during a pursuit.

    geoChannels

    Config.geoChannels = {
    enabled = true,
    command = 'sonradgeoswitch', -- command to toggle geo-channel switching | e.g. /sonradgeoswitch
    friendlyCommand = 'geoswitch', -- friendly subcommand of the /radio command to toggle geo-channel switching | e.g. / radio geoswitch
    acePermission = '', -- ACE permission required to use disable geo-channel switching | Leave blank to allow all users
    showNotifications = true -- Show notifications when geo-channel switching is enabled/disabled
    }

    When enabled, configure specific channels to transmit and scan when inside a geographical zone.

    autoOnSceneStatus

    Config.autoOnSceneStatus = {
    enabled = true, -- Enable automatic ON_SCENE status when arriving at a waypoint created by SonoranRadio AI
    distance = 30.0, -- Distance in meters from the waypoint to trigger ON_SCENE status
    statusEnum = 4, -- Status enum for "ON_SCENE" -- See https://docs.sonoransoftware.com/cad/api-integration/api-endpoints/emergency/identifiers/unit-status for more information
    timeout = 300000 -- Time in milliseconds to timeout the auto ON_SCENE status after arriving at the waypoint
    }

    When the AI dispatcher GPS routes a user, automatically update their CAD status to en-route. Upon arrival, update their CAD status to on-scene.

    radioJammers

    Config.radioJammers = {
    enabled = true, -- Enable or disable radio jammers
    menuCommand = 'jammers', -- Subcommand to open the jammers menu | e.g. /sonoranradio jammers
    toggleRange = 3.0, -- Distance in meters required to toggle a jammer on/off
    permissionMode = 'none', -- ace, qbcore, esx or none
    acePermission = 'sonoranradio.jammers', -- ACE permission required to use jammers
    allowedJobs = { -- Jobs that can use jammers | Requires permission mode to be set to 'qbcore' or 'esx'
    ['hacker'] = {
    grades = { -- Job grades that can use jammers
    1,
    2,
    3
    }
    }
    },
    jammers = {
    -- See file for full example
    }
    }

    Configuration for in-game signal jammers.

    Custom framework function
    Users with permission can change this name
    Learn how to toggle a channel scan via command or Stream Deck!
    create a scan list
    Learn how to toggle a scan list via command or Stream Deck
    You can also use the in-game keybind to quickly adjust volume.
    Sonoran Radio: Power Button
    Sonoran Radio: Channel List
    In-Game Radio - Settings
    In-Game Radio - Move/Resize
    In-Game Radio - Adjustment
    In-Game Radio - Per-User Volume

    AI Pursuit Auto-Callouts

    Let Sonoran Radio handle your pursuit location and direction callouts automatically!

    Video Example

    Enabling Auto-Callouts

    Auto-callouts can be enabled using the in-game keybind (configurable in the config.lua) or by using the /sonradtogglecallouts command in-game

    When your radio is powered, auto-callouts are enabled, and you're in a vehicle - Sonoran Radio will automatically callout street and direction changes over the radio. If configured, it will also callout average your speeds

    Example: "Westbound, East Joshua Road, Speeds 85"

    Configuration

    You can change settings for auto-callouts (Config.autoCallouts) in the config.lua file.

    Keybinds

    You can edit the default keybinding under the Config.keybinds['toggleAutoCallouts'] setting. By default, it is unset.

    Speeds

    You can . By default, it is in miles per hour, but can be changed to kilometers per hours (kmh), or speed callouts can be disabled by setting it to none.

    You can . Additionally, you will need to specify the name of your postal code resource in the .

    Below is a complete list of all languages and words. If a street name or language needed is not listed below, to have them added.

    By default, users can hear the AI transmissions locally when their radio is playing them. This can be disabled in the FiveM tab of the radio settings.

    Postal Codes

    Languages

    English
    // Directions
    Northbound
    Eastbound
    Southbound
    Westbound
    
    // GTAV Roads
    Runway1
    Plaice Pl
    Voodoo Place
    Buccaneer Way
    Cavalry Blvd
    El Burro Blvd
    New Empire Way
    Signal St
    Abattoir Ave
    Elysian Fields Fwy
    Exceptionalists Way
    Chupacabra St
    Miriam Turner Overpass
    Chum St
    Hanger Way
    South Shambles St
    Orchardville Ave
    Popular St
    Greenwich Pkwy
    Sustancia Rd
    La Puerta Fwy
    Dry Dock St
    Autopia Pkwy
    Dutch London St
    Great Ocean Hwy
    Davis Ave
    El Rancho Blvd
    Jamestown St
    Carson Ave
    Del Perro Fwy
    Roy Lowenstein Blvd
    Little Bighorn Ave
    Grove St
    Labor Pl
    Covenant Ave
    Red Desert Ave
    Brouge Ave
    Macdonald St
    Bay City Ave
    Tower Way
    Mutiny Rd
    Palomino Ave
    Alta St
    Innocence Blvd
    Amarillo Way
    South Arsenal St
    Strawberry Ave
    Amarillo Vista
    Forum Dr
    Goma St
    Fudge Ln
    Magellan Ave
    Melanoma St
    Rub St
    Capital Blvd
    Aguja St
    Shank St
    Vitus St
    Tug St
    Olympic Fwy
    Crusade Rd
    Tackle St
    Olympic Fwy
    Power St
    Elgin Ave
    South Rockford Dr
    Cortes St
    Calais Ave
    Palomino Fwy
    Invention Ct
    Prosperity St
    Adam's Apple Blvd
    Conquistador St
    Vespucci Blvd
    Sinner St
    Fantastic Pl
    Imagination Ct
    Del Perro Fwy
    Supply St
    Ginger St
    Sandcastle Way
    Lindsay Circus
    Atlee St
    San Andreas Ave
    Decker St
    Low Power St
    Equality Way
    Utopia Gardens
    Peaceful St
    Mirror Park Blvd
    East Mirror Dr
    Sinners Passage
    West Mirror Drive
    North Rockford Dr
    Los Santos Freeway
    Integrity Way
    Mirror Pl
    Marathon Ave
    Nikola Pl
    Las Lagunas Blvd
    Swiss St
    Movie Star Way
    Nikola Ave
    Boulevard Del Perro
    Bay City Incline
    Ineseno Road
    Cougar Ave
    Bridge St
    Liberty St
    Heritage Way
    Playa Vista
    Abe Milton Pkwy
    Morningwood Blvd
    Dorset Dr
    San Vitus Blvd
    Glory Way
    Occupation Ave
    West Eclipse Blvd
    Dorset Pl
    Meteor St
    Rockford Dr
    Hawick Ave
    Boulevard Del Perro
    Carcer Way
    Portola Dr
    South Boulevard Del Perro
    Perth St
    Mad Wayne Thunder Dr
    Eastbourne Way
    Tangerine St
    York St
    Spanish Ave
    Alta Pl
    Laguna Pl
    Mad Wayne Thunder Dr
    Vinewood Park Dr
    Milton Rd
    Sam Austin Dr
    Vinewood Blvd
    Kortz Dr
    Caesars Place
    Strangeways Dr
    Americano Way
    Picture Perfect Drive
    South Mo Milton Dr
    North Archer Ave
    Edwood Way
    Steele Way
    Richman St
    Clinton Ave
    Hardy Way
    Eclipse Blvd
    Fenwell Pl
    Dunstable Dr
    Gentry Lane
    Greenwich Pl
    Dunstable Ln
    North Conker Ave
    Greenwich Way
    Didion Dr
    Ace Jones Dr
    Cox Way
    Cockingend Dr
    Wild Oats Dr
    Baytree Canyon Rd
    Barbareno Rd
    Hillcrest Ridge Access Rd
    Senora Rd
    Whispymound Dr
    Marlowe Dr
    North Sheldon Ave
    Hangman Ave
    Hillcrest Ave
    Kimble Hill Dr
    Lake Vinewood Dr
    Normandy Dr
    Banham Canyon Dr
    Mt Haan Rd
    Lake Vinewood Est
    Mt Haan Dr
    Mt Vinewood Dr
    Tongva Dr
    Galileo Park
    East Galileo Ave
    Senora Way
    West Galileo Ave
    Senora Fwy
    Buen Vino Rd
    Galileo Rd
    Zancudo Grande Valley
    Zancudo Barranca
    Zancudo Rd
    Route 68
    Fort Zancudo Approach Rd
    Joshua Rd
    Chianski Passage
    Route 68 Approach
    Panorama Dr
    Cat-Claw Ave
    Smoke Tree Rd
    Calafia Rd
    Cholla Rd
    Nowhere Rd
    Marina Dr
    East Joshua Road
    Algonquin Blvd
    Alhambra Dr
    Cassidy Trail
    Meringue Ln
    Zancudo Ave
    Lesbos Ln
    Mountain View Dr
    Lolita Ave
    Cholla Springs Ave
    Niland Ave
    Armadillo Ave
    North Calafia Way
    Seaview Rd
    Union Rd
    Grapeseed Main St
    Grapeseed Ave
    Catfish View
    Joad Ln
    O'Neil Way
    Procopio Promenade
    Paleto Blvd
    Duluoz Ave
    Procopio Dr
    Pyrite Ave
    Cascabel Ave
    
    // Florida Roads
    Stockyard Rd
    Sawgrass Expressway
    Davie Blvd
    Flagler St
    Flamingo Rd
    Broward Blvd
    Las Olas Blvd
    Brickell Pl
    Brickell Ave
    Weston Vista Dr
    Weston Rd
    Seminole Way
    Everglades Blvd
    Plantation Rd
    Sawgrass Expy
    Fishing Dock Rd
    A1A Scenic Highway
    Griffin Rd
    Biscayne Blvd
    Biscayne Ramp
    Coconut Palm Dr
    Collins Ave
    Seven Mile Bridge Rd
    Sunrise Blvd
    Buccaneer Blvd
    Ocean Club Dr
    Alligator Alley
    Davie Rd
    Broward County Pkwy
    Justice Blvd
    Commercial Blvd
    Coconut Creek Pkwy
    Everglades Trail
    Panther Pkwy
    Gulf View Rd
    Sheriff Dr
    Marsh Passage
    US-27 Access Rd
    Cypress Preserve Blvd
    Marina Rd
    Gator Rd
    Washington Ave
    Spanish River Rd
    SW 8th St
    Panther Run
    Weston Blvd
    Sawgrass Way
    Volunteer Rd
    NW 27th Ave
    Port Blvd
    Interstate 4
    Brickell Bay Dr
    Drydock Ave
    Cypress Creek Rd
    Weston Hills Dr
    Weston Hills Ln
    PortMiami Tunnel Rd
    Everglades Observatory Rd
    US-98 Alternate
    Lakeview Dr
    Weston Way
    Coral Way
    Pine Island Rd
    NW 79th St
    Big Cypress Rd
    Okeechobee Rd
    Miami Ave
    Dolphin Expressway (SR 836)
    Freedom Blvd
    Le Jeune Rd
    Paradise Blvd
    Plantation Preserve Dr
    Airbase Access Rd
    Convention Center Dr
    Sugar Cane Rd
    Markham Park
    Markham Park Rd
    Plantation Ln
    Little Havana Ave
    Freedom Tower Blvd
    Wynwood Ave
    Belle Glade Rd
    Belle Glade Main St
    Interstate 75
    Biscayne Pkwy
    Biscayne Pl
    Biscayne Way
    Coconut Grove Dr
    Hangar Way
    Outpost Rd
    Coral Gables Blvd
    Hillcrest Dr
    Hillcrest Access Rd
    Paradise Ct
    Everglades Rd
    Brickell Key Dr
    Innovation Court
    Innovation Ct
    NW 36th St
    Farm Rd
    US-98
    Rickenbacker Cswy
    Interstate 95
    Industrial Pl
    Cypress Pl
    Lake Okeechobee Dr
    Lake Estates Dr
    Alton Rd
    Marsh Ln
    Liberty City Blvd
    Palm Circle
    NW 62nd St
    Florida Turnpike
    Utility Rd
    NW 20th St
    Thunder Rd
    Ocean Dr
    Marathon Key Blvd
    Overseas Hwy Frontage Rd
    Coral Gables Dr
    Medical Pkwy
    Orange Grove Ln
    NE 2nd Ave
    Biscayne Overpass
    Biscayne Park Blvd
    Reflection Pl
    Miracle Mile
    Sawgrass Ridge Dr
    Star Island Dr
    Cypress Hill Dr
    Cypress Hill Rd
    Royal Palm Dr
    Pirate Cove Rd
    MacArthur Cswy
    Edison Ave
    Edison Pl
    Normandy Isle Dr
    N Miami Ave
    Key Largo Dr
    Old Cutler Rd
    Coral Gables Ave
    North Bay Ave
    NW 87th Ave
    I-395
    Orange Grove Rd
    Overseas Hwy
    Key Colony Blvd
    University Dr
    Sunset Key Rd
    Gulfstream Dr
    Scenic Overseas Dr
    Tarpon Basin Ct
    Playa Vista
    SE 1st Ave
    Harbor Dr
    FPL Service Rd
    Islamorada Dr
    Key Largo Promenade
    Brickell Heights Blvd
    Prosperity Walk
    Islamorada Ave
    Cypress Pass
    Redland Rd
    US-27
    US-27 Business
    US-27 Connector
    MLK Blvd
    River Rd
    Runway 1
    Florida Ave
    Beachfront Rd
    Ocean Reef Dr
    Tamiami Trail East
    Everglades Way
    Marina Service Rd
    Overseas Causeway
    Harbor St
    Harbor Passage
    South Port Blvd
    South Beach Blvd
    South Bayshore Dr
    South Harbor Industrial Rd
    Española Way
    Weston Industrial Blvd
    Liberty City Ave
    Doral Industrial Blvd
    Quarry Rd
    Palm Ave
    Charter Boat Row
    Little River Rd
    Cypress Preserve Rd
    Freedom Tower Dr
    Harbor Key Rd
    Keys County Rd
    Flamingo Gardens
    Bayfront Park Dr
    Saint Vitus St
    Bayou Place
    West Lake Dr
    Weston Ridge Dr
    Ranch Rd
    SE 2nd St
    Everglades Canal Rd
    Big Cypress Basin
    Tamiami Trail
    
    // Speeds (MPH/KMH - Every 5)
    Zero  
    Five  
    Ten  
    Fifteen  
    Twenty  
    Twenty-five  
    Thirty  
    Thirty-five  
    Forty  
    Forty-five  
    Fifty  
    Fifty-five  
    Sixty  
    Sixty-five  
    Seventy  
    Seventy-five  
    Eighty  
    Eighty-five  
    Ninety  
    Ninety-five  
    One hundred  
    One hundred five  
    One hundred ten  
    One hundred fifteen  
    One hundred twenty  
    One hundred twenty-five  
    One hundred thirty  
    One hundred thirty-five  
    One hundred forty  
    One hundred forty-five  
    One hundred fifty  
    One hundred fifty-five  
    One hundred sixty  
    One hundred sixty-five  
    One hundred seventy  
    One hundred seventy-five  
    One hundred eighty  
    One hundred eighty-five  
    One hundred ninety  
    One hundred ninety-five  
    Two hundred  
    Two hundred five  
    Two hundred ten  
    Two hundred fifteen  
    Two hundred twenty  
    Two hundred twenty-five  
    Two hundred thirty  
    Two hundred thirty-five  
    Two hundred forty  
    Two hundred forty-five  
    Two hundred fifty  
    Two hundred fifty-five  
    Two hundred sixty  
    Two hundred sixty-five  
    Two hundred seventy  
    Two hundred seventy-five  
    Two hundred eighty  
    Two hundred eighty-five  
    Two hundred ninety  
    Two hundred ninety-five  
    Three hundred

    Audio Playback

    configure the type of speed announced in the auto-callout using the Config.autoCallouts.speedUnit config option
    configure the callouts to state the unit's postal code using the Config.autoCallouts.withPostals config option
    Config.autoCallouts.postalResource config option
    create a support ticket
    automatically transmit their heading, road, and speeds

    Migration Guides

    In some cases, the auto-updater requires manual steps from one version to the next.

    2.26.0 (Display Name Sync)

    Version 2.26.0 adds a new configuration option to set user's radio display names to match their in-game name.

    1. Open your existing config.lua

    2. Add the new properties to the configuration file

    If set to true the radio display name will be set to the QBCore, QBox, ESX, or vanilla in-game name.

    2.25.6 (Water Degredation)

    Version 2.25.6 adds a new configuration option to degrade signal strength when the user is underwater.

    1. Open your existing config.lua

    2. Add the new properties to the configuration file

    2.24.0 (Geo Channels, Auto Notifications, Display Name Function, Auto On-Scene Status AI)

    Version 2.24.0 adds a new configuration options to:

    • Create Geo-based channel switching

    • Use new notification frameworks

    • A custom function for guest user display names

    • Allowing the upcoming AI to automatically change your status when you are en-route and arrive on-scene at a GPS routed location.

    1. Open your existing config.lua

    2. Add the new properties to the configuration file

    Geo Channels

    Auto Notifications

    Guest Display Name

    AI GPS Auto-Status

    2.22.0 (Login as Guest)

    Version 2.22.0 adds a new configuration option to use in-game ACE permissions for a guest login, removing the need for a user account.

    1. Open your existing config.lua

    2. Add the new property to the configuration file

    2.21.0 (AI Postal Callouts + Signal Jammers)

    Version 2.21.0 adds a new configuration option for AI Pursuit Postal Callouts.

    1. Open your existing config.lua

    2. Add the new properties (withPostal and postalResource) to your Config.autoCallouts object. The end result should look like:

    Version 2.21.0 adds a new configuration option for Signal Jammers.

    1. Open your existing config.lua

    2. At the bottom of the configuration file, copy and paste the entire Config.radioJammers object.

    2.20.0 (Default ESC Behavior)

    Version 2.20.0 adds a new feature to configure your community's default ESC behavior setting.

    1. Open your existing config.lua

    2. Add the new Config.defaultEscapeMode = 'keep' property. You can enable and configure this feature if desired.

    2.19.0 (PTT on Panic & AI Callouts)

    Version 2.19.0 adds a new feature to automatically press a user's push-to-talk button on panic.

    1. Open your existing config.lua

    2. Add the three new config options:

    A. autoPttOnPanic Config

    B. autoCallouts Config

    C. toggleAutoCallouts Keybind

    Inside of the existing Config.keybinds add a new line for: `['toggleAutoCallouts'] = '',

    2.18.0 (LB Phone, Background Noise)

    Version 2.18.0 adds a new integration for LB phone and feature to inject background noise into your transmissions.

    1. Open your existing config.lua

    2. Add the new Config.showEmergencyCallHelp = true option.

    3. Add the new Config.phoneResource = 'none' option.

    4. Add the new Config.enableBackgroundAudio = true option.

    2.15.0 (ACE Perm Sync)

    Version 2.15.0 adds a new feature to manage radio community approval and permissions via ACE perms.

    1. Open your existing config.lua

    2. Add the new Config.acePermSync = false property. You can enable and configure this feature if desired.

    2.14.0 Release (LVC Resource Name)

    Version 2.14.0 adds a new feature to increase radio volume when in-game sirens are on.

    1. Open your existing config.lua

    2. Add the new Config.luxartResourceName = 'lvc' property.

    2.11.0 Release (Earpieces JSON)

    Version 2.11.0 Migrates the earpiece configuration from the config.luato earpieces.json. Therefore, this property is no longer needed in your config.lua file.

    1. Open the new earpieces.json file to confirm your configuration has been migrated (after resource start).

    2. Open your existing config.lua

    3. Remove the Config.chatterExclusions property.

    2.10.0 Release (Config Values)

    Version 2.10.0 introduces new configuration values to customize the default user keybinds and the emergency call prefix.

    Note: This new default key mapping will only apply to new users who have not joined the server and had their keybind set yet.

    1. Open your existing config.lua

    2. Paste in the two, new default config options:

    This is is also available from the auto-updater's config.CHANGEME.lua

    2.8.1 Release (Mobile Repeater Default Key)

    Version 2.8.1 introduces a new configuration value to customize the default user keybind to toggle mobile repeaters.

    Note: This new default key mapping will only apply to new users who have not joined the server and had their keybind set yet.

    1. Open your existing config.lua

    2. Paste in the new default config option (Config.mobileRepeaterKeybind) This is also available from the auto-updater's config.CHANGEME.lua

    Your config.lua show now look like the following:

    2.7.0 (Speakers, Tunnels, Voice Effects, and Earpiece EUP)

    Version 2.7.0 introduces a new configuration value for EUP earpiece detection (to prevent people from hearing nearby chatter).

    1. Open your existing config.lua

    2. Paste in the new default config option: This is also available from the auto-updater's config.CHANGEME.lua

    1. Your config.lua should now appear like the following after adding in the Config.chatterExclusions property:

    2.6.0 Release (In-Game Nearby Audio & Connected Users List)

    Version 2.6.0 introduces new configuration values.

    1. Open your existing config.lua

    2. Ensure the following lines are set:

      1. Config.chatter = true

      2. Config.acePermsForRadioUsers = false

      3. Config.talkSync = true

    Your config.lua should now look like the following:

    2.3.0-1 Release (In-Game Configuration Menu)

    Configuration File

    Version 2.3.0 introduces a new configuration value.

    1. Open your existing config.lua

    2. Ensure the following lines are set:

      1. Config.radioUrl = 'https://sonoranradio.com'

      2. Config.apiUrl = 'https://api.sonoranradio.com/'

    Your config.lua file should now look like the following:

    Version 2.3.0 introduces a new in-game repeater configuration menu. This allows an easier way to add, edit, or remove in-game repeaters.

    Communities will need to grant the new command.radiomenu permission.

    Communities can remove the old spawn and remove command permissions:

    • command.spawnradiotower

    • command.spawnradiorack

    • command.spawnradiocellrepeater

    2.2.0 Release (In-Game Towers)

    Towers File

    Version 2.2.0 introduces multiple new in-game tower options. This includes a new towers.DEFAULT.json file that is required.

    1. Delete the existing towers.json file in your sonoranradio resource.

    2. Rename the new towers.DEFAULT.json file to towers.json in your sonoranradio resource and save.

    Version 2.2.0 adds a new API key configuration for upcoming features.

    1. Add the following to line to your config.lua file, below the Config.comId line:

    Config.apiKey = 'YOUR API KEY'

    1. Replace YOUR API KEY with the from the Administration panel.

    API Endpoints v2

    Sonoran Radio v2 API endpoints with bearer auth, community-scoped URLs, and documented per-endpoint rate limits.

    Sonoran Radio v2 moves authentication to the Authorization header and scopes community-specific requests with communityId in the URL for /v2/servers/{communityId}/... routes.

    Use the official Sonoran SDK libraries if you want package-managed helpers for the v2 API.

    Start here for bearer authentication, required headers, server-scoped routing, and common error formats.

    User endpoints cover connected users, member approval, moderation, permissions, and channel assignment.

    Channel endpoints cover channel discovery and tone playback operations.

    command.removeradiorepeater

    ACE Permissions

    Configuration File

    Learn more about this new configuration line.
    Setting this to false hides the emergency call banner.
    Setting this to 'lb-phone' enables the LB phone integration.
    Setting this to false disables the background audio injection feature.
    See a complete example of our updated ACE permission structure.
    community API key
    Config.syncPlayerNameToRadio = false -- Sync the player's in-game character name to their Sonoran Radio display name
    Config.heavySignalDegradeInWater = { -- Heavily degrade radio signal while the player is in water to mimic an IP67-rated handheld
    	enabled = true, -- Set to true to enable heavy signal degrade in water
    	pedInWaterDegredation = 0.6, -- Signal strength multiplier when the player is simply in water (e.g. 0.6 would reduce signal strength to 60% of normal)
    	pedUnderWaterDegredation = 0.3 -- Signal strength multiplier when the player is underwater (e.g. 0.3 would reduce signal strength to 30% of normal)
    }
    -- Geo-Channel Settings --
    Config.geoChannels = {
    	enabled = true,
    	command = 'sonradgeoswitch', -- command to toggle geo-channel switching | e.g. /sonradgeoswitch
    	friendlyCommand = 'geoswitch', -- friendly subcommand of the /radio command to toggle geo-channel switching | e.g. / radio geoswitch
    	acePermission = '', -- ACE permission required to use disable geo-channel switching | Leave blank to allow all users
    	showNotifications = true -- Show notifications when geo-channel switching is enabled/disabled
    }
    
    -- Change the type from 'native' to the new 'auto' option
    
    -- OLD:
    Config.notifications = {
    	type = 'native', -- Available options: native, pNotify, okokNotify, ox_lib, chat, or custom
    	notificationTitle = 'SonoranRadio', -- Notification Title for methods that support it
    
    -- NEW:
    Config.notifications = {
    	type = 'auto', -- Available options: auto, native, pNotify, ox_lib, okokNotify, chat, or custom
    	notificationTitle = 'SonoranRadio', -- Notification Title for methods that support it
    -- Customize Radio Guest Display Names
    Config.getGuestDisplayName = function(source)
    	-- return ('Guest %s'):format(source)
    	return nil
    end
    Config.autoOnSceneStatus = {
    	enabled = true, -- Enable automatic ON_SCENE status when arriving at a waypoint created by SonoranRadio AI
    	distance = 30.0, -- Distance in meters from the waypoint to trigger ON_SCENE status
    	statusEnum = 4, -- Status enum for "ON_SCENE" -- See https://docs.sonoransoftware.com/cad/api-integration/api-endpoints/emergency/identifiers/unit-status for more information
    	timeout = 300000 -- Time in milliseconds to timeout the auto ON_SCENE status after arriving at the waypoint
    }
    Config.acePermsForRadioGuests = false -- Restrict users joining the radio as a guest to an ace permission
    Config.autoCallouts = {
    	enabled = true, -- Whether or not this feature is enabled
    	speedUnit = 'mph', -- mph | kmh | none -- The unit of speed provided with the callout
    	withPostals = false, -- Whether to include postals with the automatic callouts
    	postalResource = 'nearest-postal',
    }
    Config.radioJammers = {
    	enabled = true, -- Enable or disable radio jammers
    	menuCommand = 'jammers', -- Subcommand to open the jammers menu | e.g. /sonoranradio jammers
    	toggleRange = 3.0, -- Distance in meters required to toggle a jammer on/off
    	permissionMode = 'none', -- ace, qbcore, esx or none
    	acePermission = 'sonoranradio.jammers', -- ACE permission required to use jammers
    	allowedJobs = { -- Jobs that can use jammers | Requires permission mode to be set to 'qbcore' or 'esx'
    		['hacker'] = {
    			grades = { -- Job grades that can use jammers
    				1,
    				2,
    				3
    			}
    		}
    	},
    	jammers = {
    		-- Define jammers here
    		-- Example:
    		{
    			name = 'Hand Held Jammer', -- Name of the jammer
    			model = 'm23_2_prop_m32_hackdevice_01a', -- Model name for the jammer
    			offModel = 'm23_2_prop_m32_hackdevice_01a', -- Model name for the jammer when off | Optional
    			range = 25, -- Range of the jammer in meters
    			strength = 0.5, -- Strength of the jammer (0.0 to 1.0)
    			permission = 'sonoranradio.jammer_handheld', -- ACE permission required to use this jammer | Optional
    			-- If permission is not set, the jammer will be available to all players that can access the jammers menu
    			type = 'handheld', -- Type of jammer (handheld or static)
    			itemName = 'sonoran_radio_jammer_handheld', -- Item name for the jammer (if Config.enforceRadioItem is true)
    			poweredItemName = 'sonoran_radio_jammer_handheld_on' -- Optional item that replaces the base item while the jammer is powered on
    		},
    		{
    			name = 'Suitcase Jammer', -- Name of the jammer
    			model = 'ch_prop_ch_mobile_jammer_01x', -- Model name for the jammer
    			offModel = 'ch_prop_ch_mobile_jammer_01x', -- Model name for the jammer when off | Optional
    			range = 100, -- Range of the jammer in meters
    			strength = 0.8, -- Strength of the jammer (0.0 to 1.0)
    			permission = '', -- ACE permission required to use this jammer | Optional
    			-- If permission is not set, the jammer will be available to all players that can access the jammers menu
    			type = 'static', -- Type of jammer (handheld or static)
    			itemName = 'sonoran_radio_jammer_suitcase' -- Item name for the jammer (if Config.enforceRadioItem is true)
    		},
    		{
    			name = 'Case Jammer', -- Name of the jammer
    			model = 'h4_prop_h4_jammer_01a', -- Model name for the jammer
    			offModel = 'h4_prop_h4_jammer_01a', -- Model name for the jammer when off | Optional
    			range = 200, -- Range of the jammer in meters
    			strength = 1.0, -- Strength of the jammer (0.0 to 1.0)
    			permission = '', -- ACE permission required to use this jammer | Optional
    			-- If permission is not set, the jammer will be available to all players that can
    			type = 'static', -- Type of jammer (handheld or static)
    			itemName = 'sonoran_radio_jammer_case' -- Item name for the jammer (if Config.enforceRadioItem is true)
    		},
    		{
    			name = 'Satelite Jammer', -- Name of the jammer
    			model = 'm23_2_prop_m32_jammer_01a', -- Model name for the jammer
    			offModel = 'm23_2_prop_m32_jammer_01a', -- Model name for the jammer when off | Optional
    			range = 300, -- Range of the jammer in meters
    			strength = 1.0, -- Strength of the jammer (0.0 to 1.0)
    			permission = '', -- ACE permission required to use this jammer | Optional
    			-- If permission is not set, the jammer will be available to all players that can
    			type = 'static', -- Type of jammer (handheld or static)
    			itemName = 'sonoran_radio_jammer_satelite' -- Item name for the jammer (if Config.enforceRadioItem is true)
    		}
    	}
    }
    Config.autoPttOnPanic = {
    	enabled = true, -- Enable automatic PTT when panic button is pressed
    	duration = 15 -- Duration in seconds to hold PTT when panic button is pressed
    }
    -- Have the radio automatically callout pursuit locations (when toggled with the keybind)
    Config.autoCallouts = {
    	enabled = true, -- Whether or not this feature is enabled
    	speedUnit = 'mph', -- mph | kmh | none -- The unit of speed provided with the callout
    }
    Config.emergencyCallCommand = '999' -- Command suffix to start or stop an emergency call (i.e. '911' == /radio 911)
    -- Default radio keybinds (these can be changed in GTA settings) --
    Config.keybinds = {
    	['toggle'] = '',
    	['ptt'] = '\\',
    	['power'] = '',
    	['panic'] = '',
    	['nextChannel'] = '',
    	['prevChannel'] = '',
    	['talkAnim'] = ''
    }
    -- Mobile repeater keybinds
    Config.mobileRepeaterKeybind = {
    	mapperType = 'keyboard', -- See: https://docs.fivem.net/docs/game-references/input-mapper-parameter-ids/
    	map = 'g', -- See: https://docs.fivem.net/docs/game-references/input-mapper-parameter-ids/
    	label = 'Toggle Radio Repeater'
    }
    -- Radio Chatter Exclusion Settings --
    Config.chatterExclusions = {
    	{
    		componentId = 2, -- Ears
    		drawableId = 1, -- Number in vMenu MP Ped Component list
    		texture = 0 -- Texture ID in vMenu MP Ped Component list
    	},
    	{
    		componentId = 2, -- Ears
    		drawableId = 2, -- Number in vMenu MP Ped Component list
    		texture = 0 -- Texture ID in vMenu MP Ped Component list
    	},
    	{
    		componentId = 2, -- Ears
    		drawableId = 2, -- Number in vMenu MP Ped Component list
    		texture = 0 -- Texture ID in vMenu MP Ped Component list
    	},
    	{
    		componentId = 2, -- Ears
    		drawableId = 42, -- Number in vMenu MP Ped Component list
    		texture = 0 -- Texture ID in vMenu MP Ped Component list
    	},
    }
    Community server endpoints cover server IP registration, subscription lookup, and in-game speaker location updates.

    Successful responses return application/json.

    Authenticated v2 request failures return application/problem+json.

    Example:

    Status
    Cause

    400

    Validation failed for one or more request values

    401

    Missing or invalid bearer token

    404

    communityId is not available to the authenticated API key

    All authenticated v2 endpoints are rate limited per API key, not per caller IP. Limits vary by endpoint, so each endpoint page includes the published limit for that route.

    When a request is rate limited, the gateway returns 429 Too Many Requests.

    High-frequency integrations should respect the published per-endpoint limits even if a small internal buffer exists.

    Available v2 Docs

    Libraries

    Authentication

    Users

    Channels

    Community Server

    Libraries
    Authentication
    Users
    Channels
    {
      "type": "https://httpstatuses.com/401",
      "title": "Unauthorized",
      "status": 401,
      "detail": "Missing Authorization header.",
      "instance": "/v2/servers/YOUR_COMMUNITY_ID/channels",
      "traceId": "00-abc123..."
    }

    Response Formats

    Successful Requests

    Failed Requests

    Common Errors

    Rate Limits

    Full OpenAPI Collection

    OpenAPI v2 Collection (Postman Import)
    Community Server

    404

    Requested room, member, or participant was not found

    429

    Rate limit exceeded for the endpoint

    openapi: 3.0.3
    info:
      title: Sonoran Radio API v2
      version: "1.0"
    servers:
      - url: https://api.sonoranradio.com
    components:
      securitySchemes:
        bearerAuth:
          type: http
          scheme: bearer
    paths:
      /v2/server-subscriptions/by-ip:
        get:
          summary: Get server subscription from IP
          responses:
            "200":
              description: Subscription response
      /v2/servers/{communityId}/channels:
        get:
          summary: Get community channels
          security:
            - bearerAuth: []
          parameters:
            - in: path
              name: communityId
              required: true
              schema:
                type: string
                example: YOUR_COMMUNITY_ID
          responses:
            "200":
              description: Channels response
      /v2/servers/{communityId}/transmissions:
        get:
          summary: Get paginated transmission logs
          security:
            - bearerAuth: []
          parameters:
            - in: path
              name: communityId
              required: true
              schema:
                type: string
                example: YOUR_COMMUNITY_ID
            - in: query
              name: page
              schema:
                type: integer
                example: 1
            - in: query
              name: perPage
              schema:
                type: integer
                example: 25
          responses:
            "200":
              description: Paginated transmission logs response
      /v2/servers/{communityId}/connected-users:
        get:
          summary: Get connected users
          security:
            - bearerAuth: []
          parameters:
            - in: path
              name: communityId
              required: true
              schema:
                type: string
                example: YOUR_COMMUNITY_ID
          responses:
            "200":
              description: Connected users response
      /v2/servers/{communityId}/members:
        get:
          summary: Get paginated community members
          security:
            - bearerAuth: []
          parameters:
            - in: path
              name: communityId
              required: true
              schema:
                type: string
                example: YOUR_COMMUNITY_ID
            - in: query
              name: page
              schema:
                type: integer
                example: 1
            - in: query
              name: perPage
              schema:
                type: integer
                example: 25
            - in: query
              name: status
              schema:
                type: string
                enum: [pending, approved, banned]
            - in: query
              name: sortBy
              schema:
                type: string
                enum: [username, displayName, approved, pending, permission, banned, accId]
            - in: query
              name: descending
              schema:
                type: boolean
                example: false
            - in: query
              name: search
              schema:
                type: string
                example: dispatch
          responses:
            "200":
              description: Paginated members response
      /v2/servers/{communityId}/rooms/{roomId}/users/{identity}:
        get:
          summary: Get connected user
          security:
            - bearerAuth: []
          parameters:
            - in: path
              name: communityId
              required: true
              schema:
                type: string
                example: YOUR_COMMUNITY_ID
            - in: path
              name: roomId
              required: true
              schema:
                type: integer
                example: 1
            - in: path
              name: identity
              required: true
              schema:
                type: string
                example: 91de0ce8-c571-11e9-9714-5600023b2434
          responses:
            "200":
              description: Connected user response
      /v2/servers/{communityId}/rooms/{roomId}/users/{identity}/channels:
        patch:
          summary: Set user channels
          security:
            - bearerAuth: []
          parameters:
            - in: path
              name: communityId
              required: true
              schema:
                type: string
                example: YOUR_COMMUNITY_ID
            - in: path
              name: roomId
              required: true
              schema:
                type: integer
                example: 1
            - in: path
              name: identity
              required: true
              schema:
                type: string
                example: 91de0ce8-c571-11e9-9714-5600023b2434
          requestBody:
            required: true
            content:
              application/json:
                schema:
                  type: object
                  properties:
                    transmit:
                      type: array
                      items:
                        type: integer
                    scan:
                      type: array
                      items:
                        type: integer
                example:
                  transmit: [101]
                  scan: [101, 102, 103]
          responses:
            "200":
              description: User channels updated
      /v2/servers/{communityId}/users/display-name:
        patch:
          summary: Set user display name
          security:
            - bearerAuth: []
          parameters:
            - in: path
              name: communityId
              required: true
              schema:
                type: string
                example: YOUR_COMMUNITY_ID
          requestBody:
            required: true
            content:
              application/json:
                schema:
                  type: object
                  required: [accId, displayName]
                  properties:
                    accId:
                      type: string
                    displayName:
                      type: string
                example:
                  accId: 91de0ce8-c571-11e9-9714-5600023b2434
                  displayName: Dispatch 101
          responses:
            "200":
              description: Display name updated
      /v2/servers/{communityId}/members/approve:
        post:
          summary: Approve members
          security:
            - bearerAuth: []
          parameters:
            - in: path
              name: communityId
              required: true
              schema:
                type: string
                example: YOUR_COMMUNITY_ID
          requestBody:
            required: true
            content:
              application/json:
                schema:
                  type: object
                  required: [accIds]
                  properties:
                    accIds:
                      type: array
                      items:
                        type: string
                example:
                  accIds:
                    - 91de0ce8-c571-11e9-9714-5600023b2434
          responses:
            "200":
              description: Members approved
      /v2/servers/{communityId}/members/kick:
        post:
          summary: Kick members
          security:
            - bearerAuth: []
          parameters:
            - in: path
              name: communityId
              required: true
              schema:
                type: string
                example: YOUR_COMMUNITY_ID
          requestBody:
            required: true
            content:
              application/json:
                schema:
                  type: object
                  required: [accIds]
                  properties:
                    accIds:
                      type: array
                      items:
                        type: string
                example:
                  accIds:
                    - 91de0ce8-c571-11e9-9714-5600023b2434
          responses:
            "200":
              description: Members kicked
      /v2/servers/{communityId}/members/ban:
        post:
          summary: Ban members
          security:
            - bearerAuth: []
          parameters:
            - in: path
              name: communityId
              required: true
              schema:
                type: string
                example: YOUR_COMMUNITY_ID
          requestBody:
            required: true
            content:
              application/json:
                schema:
                  type: object
                  required: [accIds]
                  properties:
                    accIds:
                      type: array
                      items:
                        type: string
                example:
                  accIds:
                    - 91de0ce8-c571-11e9-9714-5600023b2434
          responses:
            "200":
              description: Members banned
      /v2/servers/{communityId}/members/display-names:
        patch:
          summary: Set member display names
          security:
            - bearerAuth: []
          parameters:
            - in: path
              name: communityId
              required: true
              schema:
                type: string
                example: YOUR_COMMUNITY_ID
          requestBody:
            required: true
            content:
              application/json:
                schema:
                  type: object
                  required: [accNicknames]
                  properties:
                    accNicknames:
                      type: array
                      items:
                        type: object
                        properties:
                          accId:
                            type: string
                          nickname:
                            type: string
                example:
                  accNicknames:
                    - accId: 91de0ce8-c571-11e9-9714-5600023b2434
                      nickname: Dispatch 101
          responses:
            "200":
              description: Member display names updated
      /v2/servers/{communityId}/members/permissions:
        patch:
          summary: Set member permissions
          security:
            - bearerAuth: []
          parameters:
            - in: path
              name: communityId
              required: true
              schema:
                type: string
                example: YOUR_COMMUNITY_ID
          requestBody:
            required: true
            content:
              application/json:
                schema:
                  type: object
                  required: [userPerms]
                  properties:
                    userPerms:
                      type: array
                      items:
                        type: object
                        properties:
                          accId:
                            type: string
                          perm:
                            type: integer
                          profilePerms:
                            type: array
                            items:
                              type: object
                              properties:
                                profileId:
                                  type: integer
                                canJoin:
                                  type: boolean
                example:
                  userPerms:
                    - accId: 91de0ce8-c571-11e9-9714-5600023b2434
                      perm: 34
                      profilePerms:
                        - profileId: 12
                          canJoin: true
          responses:
            "200":
              description: Member permissions updated
      /v2/servers/{communityId}/server-ip:
        post:
          summary: Set server IP
          security:
            - bearerAuth: []
          parameters:
            - in: path
              name: communityId
              required: true
              schema:
                type: string
                example: YOUR_COMMUNITY_ID
          requestBody:
            required: true
            content:
              application/json:
                schema:
                  type: object
                  required: [roomId, serverPort]
                  properties:
                    roomId:
                      type: integer
                    serverPort:
                      type: integer
                    overridePushUrl:
                      type: string
                    pushUrl:
                      type: string
                    nickname:
                      type: string
                example:
                  roomId: 1
                  serverPort: 30120
                  pushUrl: http://127.0.0.1:30120/sonoranradio
                  nickname: Patrol
          responses:
            "200":
              description: Server IP updated
      /v2/servers/{communityId}/speakers:
        put:
          summary: Set in-game speaker locations
          security:
            - bearerAuth: []
          parameters:
            - in: path
              name: communityId
              required: true
              schema:
                type: string
                example: YOUR_COMMUNITY_ID
          requestBody:
            required: true
            content:
              application/json:
                schema:
                  type: object
                  required: [locations]
                  properties:
                    locations:
                      type: array
                      items:
                        type: object
                example:
                  locations:
                    - label: Station 1
                      id: station-1
          responses:
            "200":
              description: Speaker locations updated
      /v2/servers/{communityId}/tones/play:
        post:
          summary: Play tone
          security:
            - bearerAuth: []
          parameters:
            - in: path
              name: communityId
              required: true
              schema:
                type: string
                example: YOUR_COMMUNITY_ID
          requestBody:
            required: true
            content:
              application/json:
                schema:
                  type: object
                  required: [roomId, tones, playTo]
                  properties:
                    roomId:
                      type: integer
                    tones:
                      type: array
                      items: {}
                    playTo:
                      type: array
                      items:
                        type: object
                example:
                  roomId: 1
                  tones: [12]
                  playTo:
                    - type: channel
                      value: 101
          responses:
            "200":
              description: Tone played

    Resource API

    Learn more about custom integrations with the in-game resource!

    Push-to-talk

    When a user presses or releases their PTT key, the following event can be used:

    -- Event sent from Sonoran Radio
    TriggerEvent('SonoranRadio::API:ToggleTalking', toggle, inVeh)
    
    -- Event listener in a custom script
    AddEventHandler('SonoranRadio::API:ToggleTalking', function(toggle, inVeh) 
      print(toggle) -- Boolean (Are the talking?)
      print(inVeh) -- Boolean (Are they in a vehicle)
    end)

    Radio Enabled

    You can check if the radio is active (turned on) like so:

    -- In your custom script
    -- true = active
    -- false = inactive
    local isActive = exports['sonoranradio']:isRadioActive()

    Emergency (911) Calls

    You can start, end, and toggle an emergency call with a client resource export:

    -- In your custom script
    -- true     = Start
    -- false    = End
    -- 'toggle' = Toggle
    exports['sonoranradio']:setEmergencyCall('toggle')
    exports['sonoranradio']:setEmergencyCall('toggle', 'My Custom Name')

    The following client events reflect the emergency call status:

    -- Event sent from Sonoran Radio
    TriggerEvent('SonoranRadio::API:EmergencyCall', enabled)
    
    -- Event listener in a custom script
    AddEventHandler('SonoranRadio::API:EmergencyCall', function(enabled)
        print(enabled) -- Boolean (is the call starting (true) or ending (false))
    end)
    -- Event sent from Sonoran Radio
    TriggerEvent('SonoranRadio::API:EmergencyCallDispatcher', dispatcherNames)
    
    -- Event listener in a custom script
    AddEventHandler('SonoranRadio::API:EmergencyCallDispatcher', function(dispatcherNames)
        print(dispatcherNames) -- Table with strings for the dispatcher's names
        -- NOTE: does not receive `{}` if emergency call is ended
        -- (above event will receive that)
    end)

    Signal Quality

    You can read the player's signal quality and apply extra degradation from another client resource.

    -- In your custom script
    exports['sonoranradio']:getSignalQuality() -- raw infrastructure quality from 0.0 to 1.0
    exports['sonoranradio']:getEffectiveSignalQuality() -- final quality after zones + extra degradation
    exports['sonoranradio']:getExtraSignalDegradation() -- total extra degradation from third-party modifiers

    Forcing Extra Degradation

    Use keyed modifiers so multiple resources can affect signal quality without overwriting each other.

    -- Add 25% extra degradation from your resource
    exports['sonoranradio']:setExtraSignalDegradation('my-resource', 0.25)
    
    -- Reduce degradation by 10% for a temporary buff or item
    exports['sonoranradio']:setExtraSignalDegradation('signal-booster', -0.10)
    
    -- Clear your modifier when it is no longer needed
    exports['sonoranradio']:clearExtraSignalDegradation('my-resource')
    exports['sonoranradio']:clearExtraSignalDegradation('signal-booster')

    The amount passed to setExtraSignalDegradation(key, amount) is clamped between -1.0 and 1.0.

    • Positive values add more degradation.

    • Negative values reduce degradation.

    • Passing 0 or nil removes that key's modifier.

    If you need the full breakdown of what the player is experiencing, use:

    You can listen to or active the panic button with an API event

    Programmatically update a user's radio display name (Client Side)

    To customize guest display names without giving permission to change their own name, you can update the Config.getGuestDisplayName

    Get notified when a radio tower is destroyed or repaired

    This document lists the server-side events emitted for developer integrations. Payload sketches use Lua table syntax. Unless noted, timestamps are Unix seconds from os.time(). All payloads are sanitized to contain only primitive values and shallow tables.

    • Player Payload

      Returned by DeveloperEvents.playerContext. position/heading are included when the underlying call requested coordinates.

    • Dispatcher Payload

      Specialised player payload that also embeds the dispatcher’s lb-phone number when available.

    • SonoranRadio::Developer:DispatcherRedial:Requested

      • Fired when a dispatcher starts a redial request.

      • Payload: dispatcher, context

    • SonoranRadio::Developer:Panic:Activated

      • Fired when a user enables panic.

      • Payload:

    • SonoranRadio::Developer:RadioState:Updated

      • Fired whenever a client publishes a new radio state snapshot.

      • Payload:

    • SonoranRadio::Developer:Jammer:Spawned

      • Static jammer placed via the build tools.

      • Payload: player, jammer (static payload),

  • Callee Payload

    Populated only when the lb-phone API exposes the remote party’s information.

  • Static Jammer Payload

  • Handheld Jammer Payload

  • SonoranRadio::Developer:DispatcherRedial:Failed

    • Emitted when a redial cannot be created (missing phone number, lb-phone offline, etc).

    • Payload: dispatcher, context, reason, message

  • SonoranRadio::Developer:DispatcherRedial:Started

    • Indicates the lb-phone call was created successfully.

    • Payload: dispatcher, context, callId, startedAt

  • SonoranRadio::Developer:DispatcherRedial:Answered

    • Emitted when the callee picks up.

    • Payload: dispatcher, context, callId, callee?, answeredAt, call?

  • SonoranRadio::Developer:DispatcherRedial:CancelRequested

    • Fired as soon as the dispatcher manually cancels.

    • Payload: dispatcher, context, callId, callee?, requestedAt

  • SonoranRadio::Developer:DispatcherRedial:Ended

    • Always emitted when the call fully terminates (hang-up, timeout, cancellation).

    • Payload: dispatcher, context, callId, callee?, reason, startedAt, answeredAt?, endedAt, call?

  • player – player payload including coordinates/heading when available

  • active – always true

  • updatedAt – timestamp the server acknowledged the change

  • metadata? – sanitized metadata sent with the panic request (currently nil)

  • SonoranRadio::Developer:Panic:Cleared

    • Emitted when panic is cleared by the user or implicitly (logout/cleanup).

    • Payload:

      • player

      • active – always false

      • updatedAt

      • metadata?

      • reason? – 'playerDropped' when cleared because the player disconnected

  • player

  • state – sanitized copy of the radio state table supplied by the client

  • metadata?
  • SonoranRadio::Developer:Jammer:Moved

    • Static/dynamic jammer repositioned.

    • Payload: player, jammer, from? (position), to? (position), dynamic (boolean)

  • SonoranRadio::Developer:Jammer:Deleted

    • Jammer removed from the world.

    • Payload: player, jammer, dynamic

  • SonoranRadio::Developer:Jammer:PowerToggled

    • Jammer power state flipped (static or dynamic).

    • Payload: player, jammer, dynamic

  • SonoranRadio::Developer:Jammer:HandheldActivated

    • Handheld jammer equipped by a player.

    • Payload: player, jammer (handheld payload), options?

  • SonoranRadio::Developer:Jammer:HandheldDeactivated

    • Handheld jammer unequipped or forcibly cleared.

    • Payload: player, jammer (handheld payload), reason? ('playerDropped' when cleanup triggered)

  • SonoranRadio::Developer:Jammer:HandheldPowerToggled

    • Handheld jammer power state toggled while equipped.

    • Payload: player, jammer

  • SonoranRadio::Developer:Jammer:HandheldPlaced

    • Equipped handheld placed on the ground as a temporary static jammer.

    • Payload: player, handheld (handheld payload prior to placement), groundJammer (static payload)

  • SonoranRadio::Developer:Jammer:HandheldDropped

    • Handheld converted to a ground jammer via inventory drop recovery.

    • Payload: player, handheld?, groundJammer, dropId?

  • Getting Signal Details

    Panic Button

    Set Display Name

    The user must have permission to set their own display name

    Guest Display Names

    Tower Destruction

    Developer Events

    Common Payload Shapes

    Dispatcher Redial Lifecycle

    Panic Button

    Radio State

    Jammer Lifecycle

    {
        serverId = number?,
        name = string?,
        phoneNumber = string?,
        identifier = string?
    }
    {
        id = string?,
        name = string?,
        note = string?,
        type = 'static' | 'handheld' | string,
        range = number?,
        strength = number?,
        active = boolean,
        temporary = boolean?,
        owner = number?,
        position = { x = number?, y = number?, z = number?, heading = number?, exact = boolean? }?
    }
    {
        id = string?,
        owner = number?,
        name = string?,
        range = number?,
        strength = number?,
        active = boolean
    }
    local signal = exports['sonoranradio']:getSignalQualityDetails()
    
    print(signal.baseQuality) -- tower/rack/repeater quality before degradation
    print(signal.zoneDegradation) -- active tunnel/polyzone degradation
    print(signal.extraDegradation) -- third-party modifier total
    print(signal.totalDegradation) -- final degradation after combining both
    print(signal.effectiveQuality) -- final signal quality sent to the radio UI
    print(signal.zoneName) -- current degradation zone name, or nil
    -- Activate the panic button
    TriggerEvent('SonoranRadio::API:PanicButton')
    
    -- Listen to the panic button
    AddEventHandler('SonoranRadio::API:PanicButton', function(status)
        print(status) -- Boolean (whether the panic button is active or not)
        -- your code here
    end)
    -- Set your current display name in the radio
    exports['sonoranradio']:handleNameChange('my new name')
    -- My Custom Guest Display Name Generator
    -- Param `source`: The server id of the user logging in as guest
    -- Returns string or nil (to use default)
    Config.getGuestDisplayName = function(source)
        return ('I am logging in as a guest %s %s'):format(GetDisplayName(source), makeid())
    end
    -- Event sent from Sonoran Radio (server-side)
    TriggerEvent('SonoranRadio::API:TowerDishDestroyed', towerId, tower.DishStatus)
    
    -- Event listener in a custom script
    AddEventHandler('SonoranRadio::API:TowerDishDestroyed', function(playerSource, towerId, dishStatus) 
      print(playerSource) -- The player ID that destroyed the dish
      print(towerId) -- Numerical ID of the tower
      print(dishStatus) -- Array of statuses {'alive', 'alive', 'dead', 'alive'}
    end)
    
    -- Event sent from Sonoran Radio (server-side)
    TriggerEvent('SonoranRadio::API:TowerRepaired', towerId, tower.DishStatus)
    
    -- Event listener in a custom script
    AddEventHandler('SonoranRadio::API:TowerRepaired', function(playerSource, towerId, dishStatus) 
      print(playerSource) -- The player ID that repaired the tower
      print(towerId) -- Numerical ID of the tower
      print(dishStatus) -- Array of statuses {'alive', 'alive', 'alive', 'alive'}
                        -- (NOTE: will always contain all 'alive')
    end)
    {
        serverId = number,
        name = string?,
        identifiers = { string, ... }?,
        position = { x = number, y = number, z = number }?,
        heading = number?
    }
    {
        serverId = number,
        name = string?,
        phoneNumber = string?,
        identifiers = { string, ... }?
    }

    Stream Deck API

    Integrate the Sonoran Radio Stream Deck plugin with desktop or FiveM.

    Sonoran Radio includes a Stream Deck plugin that can control the desktop application directly or control the FiveM radio through the desktop app.

    This document covers the public integration contract for:

    • the built-in desktop bridge exposed by the Electron app

    • the built-in FiveM bridge exposed by the Electron app when Stream Deck actions are set to FiveM

    Each Stream Deck action is configured with a target:

    • Desktop sends commands directly to Sonoran Radio Desktop

    • FiveM sends commands to Sonoran Radio Desktop, which forwards them to a FiveM client over localhost

    The plugin uses the same command and snapshot schema for both targets. The difference is transport:

    • Desktop uses local HTTP requests to Sonoran Radio Desktop

    • FiveM uses local HTTP requests to Sonoran Radio Desktop, and Sonoran Radio Desktop forwards commands and receives snapshots over a local WebSocket connected by your FiveM client script

    When the Stream Deck action target is set to FiveM, the recommended flow is:

    This means the Stream Deck plugin does not need to talk to the FiveM NUI directly anymore. As long as:

    1. Sonoran Radio Desktop is running

    2. the Stream Deck action is set to FiveM

    3. your FiveM client script is connected to the desktop WebSocket

    the plugin will behave the same as normal.

    When Sonoran Radio Desktop is running, it starts a local HTTP bridge on:

    GET /streamdeck/health

    Response:

    GET /streamdeck/labels

    Response:

    POST /streamdeck/command

    Headers:

    Example request:

    Example response:

    If the command is invalid, the radio is not ready, or the payload is malformed, the bridge returns a non-200 response.

    When the Stream Deck action target is set to FiveM, the plugin first talks to the desktop app at:

    The desktop app then talks to your FiveM client over:

    GET /streamdeck/fivem/health

    Response:

    GET /streamdeck/fivem/labels

    Response:

    POST /streamdeck/fivem/command

    Headers:

    Request:

    Response:

    If no FiveM socket clients are connected, the desktop app returns a non-200 response.

    Your FiveM client should connect to:

    Sent immediately after the socket connects.

    Sent when a Stream Deck action is pressed/rotated while targeting FiveM.

    Sent when the FiveM client explicitly requests the latest cached snapshot.

    Send this whenever the iframe publishes a new radio snapshot.

    Optional. Ask the desktop app to send back its current cached snapshot.

    The desktop app may reply with:

    • streamdeck_snapshot_ack

    • streamdeck_command_ack

    These are informational and do not need special handling.

    All commands use the same JSON shape:

    Fields:

    Field
    Type
    Required
    Notes

    Most commands execute on phase: "down".

    The following hold-style commands use both phases:

    • transmit.ptt

    • transmit.tempChannel

    For those commands:

    • send phase: "down" when the button is pressed

    • send phase: "up" when the button is released

    Command
    Extra Fields
    Description

    The plugin reads a snapshot to populate action configuration, channel selectors, and active button state.

    Field
    Type
    Description
    Field
    Type
    Description

    Inside the FiveM web view, Sonoran Radio uses iframe messages for Stream Deck integration.

    Send a standard command payload:

    Request that the iframe publish its latest state:

    The iframe emits this message whenever radio/channel state changes and also in response to streamdeck_snapshot_request.

    The following browser-side example shows the minimum bridge needed in FiveM to make Stream Deck FiveM mode work through Sonoran Radio Desktop.

    This example assumes:

    • your FiveM client script can open a browser WebSocket to ws://127.0.0.1:39112/streamdeck/fivem/socket

    • your client script can forward messages to the Sonoran Radio iframe/NUI

    • your iframe/NUI can send streamdeck_snapshot messages back to this script

    • Use channel IDs exactly as returned by the snapshot.

    • transmit.tempChannel and transmit.ptt should send both press and release phases.

    • Multi-channel commands should send channelIds as an array of numbers.

    your FiveM client script forwards commands to the iframe and forwards snapshots back to desktop

    No

    Defaults to "down" if omitted

    channelId

    number

    Conditional

    Used by single-channel commands

    channelIds

    number[]

    Conditional

    Used by multi-channel commands

    channel.next

    None

    Move to the next channel within the current group

    channel.previous

    None

    Move to the previous channel within the current group

    transmit.toggleChannels

    channelIds

    Toggle one or more transmit channels

    transmit.tempChannel

    channelId, phase

    Temporarily transmit on a single channel while held

    scan.toggleChannels

    channelIds

    Toggle one or more scan channels

    toggle.ai

    None

    Toggle AI on or off

    transmit.ptt

    phase

    Push-to-talk

    toggle.toneBoard

    None

    Open or close the tone board

    audio.volumeUp

    None

    Increase master volume

    audio.volumeDown

    None

    Decrease master volume

    audio.volumeMute

    None

    Toggle master mute

    audio.sfxUp

    None

    Increase SFX volume

    audio.sfxDown

    None

    Decrease SFX volume

    audio.sfxMute

    None

    Toggle SFX mute

    audio.aiUp

    None

    Increase AI volume

    audio.aiDown

    None

    Decrease AI volume

    audio.aiMute

    None

    Toggle AI mute

    audio.currentChannelsUp

    None

    Increase current primary channel volume

    audio.currentChannelsDown

    None

    Decrease current primary channel volume

    audio.currentChannelsMute

    None

    Toggle mute for current primary channels

    desktop.connectedUsers

    None

    Open the connected users window

    desktop.focusRadio

    None

    Focus the Sonoran Radio desktop window

    desktop.toggleRadio

    None

    Show or hide the Sonoran Radio desktop window

    groupId

    number

    Parent group ID

    groupName

    string

    Parent group display name

    micOpen

    boolean

    Whether the microphone/PTT is currently active

    primaryChIds

    number[]

    Current transmit channels

    scannedChIds

    number[]

    Current scan channels

    sfxVolume

    number

    Current SFX volume

    agentGain

    number

    Current AI volume

    Your FiveM client does not need to translate command names or payload fields. Forward them exactly as documented.

  • The desktop app caches the most recent FiveM snapshot, so send streamdeck_snapshot whenever radio state changes inside the iframe.

  • command

    string

    Yes

    One of the supported command IDs listed below

    phase

    group.next

    None

    Move to the next channel group

    group.previous

    None

    Move to the previous channel group

    id

    number

    Channel/profile ID

    label

    string

    Display name shown in the plugin

    connected

    boolean

    Whether the radio is currently connected

    aiEnabled

    boolean

    Whether AI is enabled

    Overview

    Recommended FiveM Architecture

    Desktop Bridge

    Health Check

    Get Current Snapshot

    Send a Command

    FiveM Desktop Bridge

    Health Check

    Get Current FiveM Snapshot

    Forward a Command to FiveM

    WebSocket Message Contract

    Messages Sent From Desktop to FiveM

    hello

    streamdeck_command

    streamdeck_snapshot

    Messages Sent From FiveM to Desktop

    streamdeck_snapshot

    streamdeck_snapshot_request

    Optional Acknowledgements

    Command Payload

    Phase Rules

    Supported Commands

    Snapshot Schema

    Channels

    State

    FiveM Iframe Message Contract

    Messages Sent To Sonoran Radio

    streamdeck_command

    streamdeck_snapshot_request

    Messages Sent From Sonoran Radio

    streamdeck_snapshot

    FiveM JavaScript Example

    Notes

    "down" or "up"

    Stream Deck Plugin
      -> Sonoran Radio Desktop HTTP bridge
      -> local FiveM WebSocket client
      -> FiveM client script
      -> Sonoran Radio iframe/NUI
    
    Sonoran Radio iframe/NUI
      -> FiveM client script
      -> local FiveM WebSocket client
      -> Sonoran Radio Desktop snapshot cache
      -> Stream Deck Plugin label/status polling
    http://127.0.0.1:39112
    {
      "ok": true,
      "appReady": true,
      "snapshotReady": true,
      "attempts": 1,
      "lastError": null
    }
    {
      "ok": true,
      "appReady": true,
      "channels": [
        {
          "id": 101,
          "label": "Law 1",
          "groupId": 10,
          "groupName": "Patrol"
        }
      ],
      "state": {
        "connected": true,
        "aiEnabled": false,
        "micOpen": false,
        "primaryChIds": [101],
        "scannedChIds": [102, 103],
        "sfxVolume": 25,
        "agentGain": 100
      }
    }
    Content-Type: application/json
    {
      "command": "transmit.ptt",
      "phase": "down"
    }
    {
      "ok": true,
      "command": "transmit.ptt"
    }
    http://127.0.0.1:39112
    ws://127.0.0.1:39112/streamdeck/fivem/socket
    {
      "ok": true,
      "socketPath": "/streamdeck/fivem/socket",
      "websocketClients": 1,
      "snapshotReady": true,
      "attempts": 1,
      "lastError": null
    }
    {
      "ok": true,
      "websocketClients": 1,
      "snapshotReady": true,
      "channels": [
        {
          "id": 101,
          "label": "Law 1",
          "groupId": 10,
          "groupName": "Patrol"
        }
      ],
      "state": {
        "connected": true,
        "aiEnabled": false,
        "micOpen": false,
        "primaryChIds": [101],
        "scannedChIds": [102, 103],
        "sfxVolume": 25,
        "agentGain": 100
      }
    }
    Content-Type: application/json
    {
      "command": "transmit.ptt",
      "phase": "down"
    }
    {
      "ok": true,
      "command": "transmit.ptt",
      "delivered": 1
    }
    ws://127.0.0.1:39112/streamdeck/fivem/socket
    {
      "type": "hello",
      "ok": true,
      "snapshot": {
        "channels": [],
        "state": {
          "connected": false,
          "aiEnabled": false,
          "micOpen": false,
          "primaryChIds": [],
          "scannedChIds": [],
          "sfxVolume": 0,
          "agentGain": 0
        }
      }
    }
    {
      "type": "streamdeck_command",
      "payload": {
        "command": "transmit.toggleChannels",
        "channelIds": [101, 102]
      }
    }
    {
      "type": "streamdeck_snapshot",
      "snapshot": {
        "channels": [],
        "state": {
          "connected": false,
          "aiEnabled": false,
          "micOpen": false,
          "primaryChIds": [],
          "scannedChIds": [],
          "sfxVolume": 0,
          "agentGain": 0
        }
      }
    }
    {
      "type": "streamdeck_snapshot",
      "snapshot": {
        "channels": [
          {
            "id": 101,
            "label": "Law 1",
            "groupId": 10,
            "groupName": "Patrol"
          }
        ],
        "state": {
          "connected": true,
          "aiEnabled": false,
          "micOpen": false,
          "primaryChIds": [101],
          "scannedChIds": [102, 103],
          "sfxVolume": 25,
          "agentGain": 100
        }
      }
    }
    {
      "type": "streamdeck_snapshot_request"
    }
    {
      "command": "string",
      "phase": "down",
      "channelId": 101,
      "channelIds": [101, 102]
    }
    {
      "channels": [
        {
          "id": 101,
          "label": "Law 1",
          "groupId": 10,
          "groupName": "Patrol"
        }
      ],
      "state": {
        "connected": true,
        "aiEnabled": false,
        "micOpen": false,
        "primaryChIds": [101],
        "scannedChIds": [102, 103],
        "sfxVolume": 25,
        "agentGain": 100
      }
    }
    {
      "type": "streamdeck_command",
      "payload": {
        "command": "transmit.toggleChannels",
        "channelIds": [101, 102]
      }
    }
    {
      "type": "streamdeck_snapshot_request"
    }
    {
      "type": "streamdeck_snapshot",
      "snapshot": {
        "channels": [
          {
            "id": 101,
            "label": "Law 1",
            "groupId": 10,
            "groupName": "Patrol"
          }
        ],
        "state": {
          "connected": true,
          "aiEnabled": false,
          "micOpen": false,
          "primaryChIds": [101],
          "scannedChIds": [102, 103],
          "sfxVolume": 25,
          "agentGain": 100
        }
      }
    }
    const DESKTOP_SOCKET_URL = 'ws://127.0.0.1:39112/streamdeck/fivem/socket';
    
    let desktopSocket = null;
    let reconnectTimer = null;
    let latestSnapshot = {
      channels: [],
      state: {
        connected: false,
        aiEnabled: false,
        micOpen: false,
        primaryChIds: [],
        scannedChIds: [],
        sfxVolume: 0,
        agentGain: 0,
      },
    };
    
    function postToRadioIframe(message) {
      window.postMessage(message, '*');
    }
    
    function sendToDesktop(message) {
      if (!desktopSocket || desktopSocket.readyState !== WebSocket.OPEN) return;
      desktopSocket.send(JSON.stringify(message));
    }
    
    function scheduleReconnect() {
      if (reconnectTimer) return;
      reconnectTimer = window.setTimeout(() => {
        reconnectTimer = null;
        connectDesktopSocket();
      }, 3000);
    }
    
    function handleDesktopMessage(message) {
      if (!message || typeof message.type !== 'string') return;
    
      if (message.type === 'hello' && message.snapshot) {
        latestSnapshot = message.snapshot;
        return;
      }
    
      if (message.type === 'streamdeck_command' && message.payload) {
        postToRadioIframe({
          type: 'streamdeck_command',
          payload: message.payload,
        });
        return;
      }
    
      if (message.type === 'streamdeck_snapshot') {
        latestSnapshot = message.snapshot || latestSnapshot;
      }
    }
    
    function connectDesktopSocket() {
      if (desktopSocket && (desktopSocket.readyState === WebSocket.OPEN || desktopSocket.readyState === WebSocket.CONNECTING)) {
        return;
      }
    
      desktopSocket = new WebSocket(DESKTOP_SOCKET_URL);
    
      desktopSocket.addEventListener('open', () => {
        sendToDesktop({
          type: 'streamdeck_snapshot',
          snapshot: latestSnapshot,
        });
      });
    
      desktopSocket.addEventListener('message', (event) => {
        try {
          handleDesktopMessage(JSON.parse(event.data));
        } catch (error) {
          console.error('Failed to parse desktop Stream Deck message', error);
        }
      });
    
      desktopSocket.addEventListener('close', scheduleReconnect);
      desktopSocket.addEventListener('error', scheduleReconnect);
    }
    
    window.addEventListener('message', (event) => {
      const data = event.data;
      if (!data || typeof data.type !== 'string') return;
    
      if (data.type === 'streamdeck_snapshot' && data.snapshot) {
        latestSnapshot = data.snapshot;
        sendToDesktop({
          type: 'streamdeck_snapshot',
          snapshot: data.snapshot,
        });
        return;
      }
    
      if (data.type === 'streamdeck_snapshot_request') {
        postToRadioIframe({ type: 'streamdeck_snapshot_request' });
      }
    });
    
    connectDesktopSocket();

    Changelog

    View the changelog for the Sonoran Radio application and in-game resource.

    2.27.2 06/08/2026

    Dispatch AI v2

    • An overhaul to the AI dispatcher, no longer requiring you to bring your own AI API key.

    2.27.0 06/01/2026

    App Emergency Call

    • Added the ability to make emergency calls from the web, desktop, or mobile version instead of only in-game FiveM.

    In-Game Name Sync

    • Added a new config option allowing communities to sync users' in-game names to their radio display name.

    In-Game Emergency Call Mic Setup

    • Added a new command for users to change their microphone input device when placing in-game emergency calls.

    Custom Zone Maps

    • Added the ability to upload custom FiveM maps to the zone editor.

    Permission ID Generator

    • Added a UI in the members panel to generate and copy a bitwise permission ID for external use (Discord bot role sync).

    Admin Permissions

    • Removed the ability for users to remove their own admin permission.

    Tone Voice Effects

    • Tones played on the radio now have the custom voice effects applied to them.

    In-Game Errors

    • Added standardized error codes to the in-game resource complete with short links to specific documentation.

    Permission Removal

    • Restricted the ability to remove permissions from your own account

    Tone Stop on Channel Exit

    • Local tones now stop playing right away when exiting the channel they were playing on

    Framework Startup Retry

    In-Game User List Resize

    • Fixed an issue with the in-game user list not being able to be resized and moved in some cases.

    Translations

    • Added translation support

    Log Search

    • Added the ability to view and search logs from user actions.

    FiveM Guest Login

    Client Side Voice FX

    • Individual users can now customize voice effects on their own, bypassing community channel-level FX.

    Vocoder Preview

    • Added audio preview support to the vocoder in the voice effect editor.

    Voice Effects: Unlimited

    Stream Deck Plugin

    • Added an official Stream Deck plugin for advanced control and integration

    Text-to-Speech Tones

    • Added free, localized text-to-speech tones in the tone board editor (permanent) and in the tone board (temporary)

    Radio Channels: Unlimited for Free

    • Free communities can now configure unlimited channels without limits

    Tone Board: Unlimited for Free

    • Free communities can now configure unlimited tones without limits

    Stun User

    Desktop Overlay Promo

    • Added a check to ensure the community is on Pro before uploading a custom frame.

    • Added a popup promotional to encourage upgrading when uploading a custom frame.

    Desktop Overlay Overflow

    Desktop Overlay

    • Added a desktop overlay with customizable frames to display your radio on top of any game window.

    Geo Channels

    • Communities can now specify custom coordinate zones with specific radio channels to transmit and scan. When a player enters the zones, their radio channels will be automatically updated.

    Degrade/Tunnel Zones - Panel UI

    • Degredation zones can now be viewed and configured via the zones panel in Sonoran Radio.

    AI Emergency Zones

    Recording Filtering

    • Added the ability to filter transmission recordings by user and channel.

    User Ban

    • Added the ability to ban a user account from the members tab, preventing them from re-joining as a pending user.

    Mobile Server Selection

    Dispatch UI Revamp

    • Initial UI revamps for the dispatch panel

    Audio Synchronization

    • Fixed an issue where users could sometimes hear transmissions they were not scanning

    Audio Leak Degradation

    • Fixed an issue where scanning and listening to 50-100 users at once would slowly create a node leak, resulting in laggy or stuttering audio until after a refresh.

    Push-To-Talk Hotmic

    • Fixed an issue where quickly pressing push-to-talk could result in a stuck "hot mic" on.

    FiveM Login as Guest

    • Added a new option for FiveM communities. Allowing users to bypass the need for a linked Sonoran account to login and utilizing ACE permissions for all radio access.

    Audio Node Disposal

    • Improved audio node disposal for temporarily muted users and channels in attempt to resolve an issue with distortion over time.

    AI Pursuit Callout Hear

    • Added a settings option to toggle on the ability to hear your AI pursuit callouts when enabled.

    Community Log Search

    • Added a panel to view user logs for configuration edits and more.

    Translations

    Resource Exports

    • Added and documented several new developer exports in the FiveM resource.

    Shared Channel UI

    • Fixed an issue with shared channels causing the in-game/mini UI to show the user in the main shared channel instead of the per-group subchannel.

    UI Positions

    Custom Domains Cloudflare for SaaS

    • Updated the custom domain setup to use the newer "Cloudflare for SaaS" method, with legacy being depreciated in the near future.

    Reconnection Handling

    • Fixed an issue primarily in-game, where users would be unable to hear other transmissions after a network reconnection.

    Shared Radio Channels

    • Communities can now link multiple radio channels together from separate groups. Useful for shared "Interops" or other communication channels between departments.

    Signal Jammers

    • Added in-game signal jammer items, configurable with QB Core and ESX to block radio signals within a specified radius.

    Emergency Call Redial

    Voice EQ: V2

    • Added a new pre and post-effect advanced EQ in the voice effect settings.

    Persistent Scanners: Model Options

    • Added new model options for in-game persistent scanners.

    Persistent Scanners: Move

    Custom Domain

    • Added the ability to utilize a custom domain, logging users directly into your radio community.

    Vanity URLs

    • Communities now have a free vanity URL located at COMMUNITYID.sonoranradio.com.

    Custom Community ID

    Simulated Background

    • Added new functionality to add in simulated background noise for in-game sirens, boat engines, helicopter rotors, and gunshots.

    Multi-Server

    • Added support for multiple radio servers under one community.

    LB Phone Integration

    Audio Duplication and Static

    • Fixed an issue causing some users to transmit doubled audio (echoing) and/or constant static when not using the vocoder.

    #28123 - Local SFX

    • Fixed an issue causing local custom mic click SFX to not work.

    RocketNode Promotional Images

    Multi-Channel Transmit

    • CTRL + Click on a channel to transmit on multiple at once.

    Chatter: Volume Level from Source Player

    • In-game chatter volume is based on the person's actual radio volume. Turning down your radio on a traffic stop will make it quieter for people around you.

    Qbox & OX Inventory Support

    • Added support for OX inventory in both QBCore and QBox

    Display Name: CAD Sync

    • Added a new CAD integration feature to automatically update your radio display name based on unit information

    Display Name: Command

    ACE Permission Sync (Auto-Approve + Community Perms)

    • Added an ACE permission sync option to automatically approve users and grant community permissions based on in-game ACE permissions.

    In-Game Channel Changer - Group Handling

    • Added a right-click option on the top channel change knob in-game to toggle between changing channels and channel groups.

    Tone Board: Live TTS AI

    Panic: Radio & Dispatch Display

    • Expanded radio panic functionality to reflect in the in-game and dispatch UI with a customizable sound.

    Volume Hotkeys

    • Added in-game and in-app hotkeys to quickly adjust the radio volume by a configurable amount.

    Channel Hotkeys

    AI Tone TTS: Removed Character Limit

    • Removed the 50 character limit for community integrated AI text-to-speech tones.

    Transmission Logs: Vocoder Cutoff

    • Fixed an issue causing transmission logs to be cutoff when using the vocoder effect due to other optimizations.

    Transmission Logs: Download

    In-Game Physical Scanners

    • Added in-game physical scanner items for civilians to hear radio transmissions

    Transmission Logs

    • Added transmission logs in the dispatch panel with optional AI transcriptions

    #26361 Transmit to In-Game Speakers

    Radio Chatter: Vehicle Detection

    • Added vehicle detection to lower and muffle nearby radio chatter if the user enters a vehicle. Chatter volume resumes if the window is down/broken or the door opens.

    Emergency Call: Nearby Chatter

    • When a user is making an emergency call on the phone, nearby users can now faintly hear the dispatcher talking on the other side of the phone.

    Voice Effect: Clipping

    Text Style Display

    • Added a new screen display style with a "text-based" UI for older radio styles

    Settings UI: Tabs

    • Overhauled the settings modal with tabs for each section

    Hide Radio ESC User Config

    #25437 Radio In-Game Display

    • The in-game radio will now persist on the user's screen, until they use /radio hide. Per-user customization will be released in a coming update.

    #25917 - EUP Chatter

    • Added support for drawable items (in addition to the existing prop support) for EUP chatter exclusion.

    In-Game Emergency Calls

    • Added a way for players in-game to place an emergency (911) call to dispatchers

    Developer Export - Radio Signal

    • Added an export to get a user's radio signal quality

    Developer Export - Panic

    CAD Integration

    • Added sonrad integration to display Sonoran CAD call information on the in-game radio, along with panic functionality

    Top-Down HUD Improvements

    • Improved the top-down radio HUD to display the channel name, frequencies, and color changes when a user is transmitting

    Voice Degradation

    • Fixed an issue causing some users to experience gradual voice degradation that was only fixed after refreshing/power toggling the radio

    Digital Voice Effect

    • Smoothed and reduced the initial digital voice filter effect

    Voice Effect Customization

    • Added the ability to create multiple custom voice effect filters and apply them per-channel.

    Tone Board - Play to In-Game Speakers

    • Added the ability configure in-game speakers and play radio tones to them.

    Tunnel Signal Degrade

    In-Game Connected Users

    • Fixed an issue with the connected users list causing some names to not change to green while the user was talking

    In-Game Connected Users

    • When talking, user names will display as green

    • Added proper CSS ellipsis to display names

    • Added tooltip to user display names

    Hear Chatter In-Game

    • Civilians can now hear live radio chatter when there is a nearby radio. This requires the pro version.

    Top-Down HUD

    • Added the top-down radio HUD UI in-game

    Multi-Frame

    Sonoran CMS Integration

    • Added the ability to manage your radio user's joining, permissions, and kicking via Sonoran CMS ranks and Discord roles.

    Input/Output Device Selection

    • Added the ability to customize and test the input and output sources via the settings menu.

    Tone Board

    Channel Groups & Organization

    • Added the ability to create channel groups and easily organize via drag-and-drop

    Custom Talkover Tone

    • Added the ability to customize a community-wide talkover error SFX

    Signal Bars

    Repeaters - UI Menu

    • Added an in-game repeater menu to add, edit, and remove repeaters.

    In-Game Volume

    • Added the ability to adjust the system-wide volume in-game via the settings menu.

    In-Game Per-User Volume

    Tower Distance

    • Fixed an issue causing tower distortion levels to "freeze" in certain cases.

    In-Game Tower Signal

    • Added variable audio distortion based on how close a user in-game is to a radio repeater model.

    User Display Names

    • Added the ability to customize user display names and two new permissions to set who can change their, and others', display name.

    Link UI Refresh

    Desktop Application - Hotkey Setting

    • Improved handling for detecting a wider array of hotkeys in the desktop application, including standard mouse buttons.

    Login Link

    • New login for in-game resource/mobile

    Community ID

    • Use community IDs in URL instead of numeric IDs

    Volume Control

    Community ID

    • Accept community ID in place of standalone ID

    #22925 - ESC Error

    • Fixed ESC with the radio open causing an error, preventing you from leaving the radio

    Initial Release

    Added retry logic when the radio resource starts up if it fails to detect a framework (QB, QBox, ESX) due to startup order.

    Added a login method based on in-game ACE permissions, allowing users to login as guest and not require an account.

    Ban User

    • Added the ability to ban a user, preventing them from re-joining as a pending user.

    Tone Board Improvements

    • Added the ability to save tone stacks and the board now auto-selects your currently transmitting channels.

    Desktop Overlay

    • Added customizable desktop overlays to see your radio in-game on any application.

    Community Image Customization

    • Communities can now set a custom logo for their radio community

    Connected Users Popout

    • Added a new overlay window with a hotkey to show connected users

    Privacy Tab - Recordings

    • Added a tab to toggle on/off the ability to send local transmission recordings

    Stun

    • Added the ability to stun a user from talking temporarily.

    TTS Tone

    • Added AI text-to-speech support for tone board tones.

    Channel Volume

    • Added per-channel volume

    Client FX

    • Added client-sided customizable voice effects.

    Emergency Call Disconnect

    • Fixed an issue where creating an emergency call would cause other users to listen in.

    URL Migration

    • Updated internal S3 storage URLs for newer infrastructure paths.

    Temporary Transmit Channel Change

    • Fixed an issue where using a hotkey to temporarily transmit in another channel resulted in the first channel still hearing you for a few seconds

    Removed paid restrictions, allowing the free tier to create unlimited custom voice effect profiles.

    EQ V1 Depreciation

    • Removed the old, depreciated V1 EQ option from the voice FX customization.

    Tone board users can use speech-to-text to quickly enter text into the text-to-speech input

    Per-Channel Volume

    • Right-click or select the volume icon on a channel to adjust the per-channer volume

    Added a new right-click menu option and permission to stun a user from talking temporarily.

    Ping User

    • Added a new right-click menu option to ping a user

    User List Overlay

    • Added a new desktop overlay option with a hotkey to display the current list of users and channels

    Community Image

    • Added the ability to customize your radio community's logo

    Hotkey Recording

    • Added support for multi-combination hotkeys

    • Hotkeys now auto-save after releasing the combination Open Overlay Mobile Button

    Open Overlay Mobile Button

    • Added a button on the "mobile" (non-dispatch) UI panel for desktop users with smaller windows

    Overlay Back Button

    • Tweaked the close button on the desktop overlay to swap back to the main radio screen instead of the community menu

    Settings Privacy Tab

    • Users can now individually opt-out of having their radio transmissions recorded

    Temporary Transmit

    • Fixed an issue where using a hotkey to temporarily transmit in a specific channel resulted in your current channel still hearing your transmission briefly

    Fixed an issue where users in channel would overflow the screen in the desktop overlay.

    Free Community Upload Overlay Frame

    • Fixed an issue with an undefined error message when a community on the free version would attempt to upload a custom radio frame.

    Communities can now create emergency zones for dispatch AI to read out CAD emergency calls to specific channels based on location.

    AI Auto-Status Routing

    • When the AI GPS routes a user to a specific postal or coordinate locations, the AI will automatically mark the unit as en-route and on-scene.

    FiveM Guest Login - Framework

    • Integrated the guest login with QB-Core, QBox, and ESX to use the player's character name by default.

    FiveM Guest Display Name Function

    • Communities can now use a custom function to set user's guest display names for their framework.

    FiveM Tablet

    • Added an in-game tablet to view the dispatch panel.

    Tone Board Improvements

    • Tone board now auto-selects your currently transmitting channels.

    • Tone stacks can now be saved for faster, repeated use.

    Notifications

    • In-game notifications now support an "auto" mode, automatically detecting any of the new notification options: native, pNotify, ox_lib, okokNotify, chat, lation_ui or custom.

    FiveM Resource Restart Auto-Connect

    • When the FiveM resource is restarted, all users will now automatically re-connect to their radio.

  • Disabled the automatic connect on mobile if the community has multiple servers configured. Allowing the user to select the server prior to connecting.

  • Members Panel Pagination

    • Added pagination to the members table, resolving a timeout issue for communities with several thousand users.

    Added translation support along with several new language examples.

    Custom Domain Removal

    • Added handling on community downgrade to remove the custom domain from Cloudflare.

    Bandwidth

    • Tweaked connection subscription events in an effort to minimize bandwidth usage.

    API Channel

    • Fixed an issue where changing the radio channel via API would result in client side errors.

    Trialing Status

    • Fixed an issue where trial subscription days would still place the user on the free version.

  • Fixed an issue with saving radio UI positions in-game.

  • CF Custom Domains

    • Fixed an issue with newly created custom domains on Cloudflare.

    Desktop Split Error

    • Fixed an error that would popup on the desktop version.

    Added the ability to re-dial an emergency caller after the call has been ended.

    AI Callouts: Postal Code

    • Added postal code text-to-speech in the AI pursuit callouts.

    Earpiece Notifications

    • Added an in-game notification whenever a configured earpiece is inserted or removed, confirming if other players nearby can hear your radio or not.

    Added the ability to move an existing in-game persistent scanner instead of needing to delete and re-add it.

    Radio Frame & User List Size Safety

    • Added checks to prevent users from resizing the radio or connected users list to be off of their screen, reducing the need for the /radio reset command.

    Default Settings: ESC Behavior

    • Added the ability to set the in-game FiveM ESC default behavior.

    VFX Customization: XMIT vs RECV Signal Strength

    • Added two sliders in the voice customization testing menu to better reflect in-game usage for both transmitter and receiver signal strength.

    Desktop Channel Hotkey

    • Fixed an issue with desktop per-channel hotkeys not being able to be re-registered with a new key.

    #29952 - Persist Frame

    • Fixed an issue where frame selection would not persist when in QB item mode.

    Communities can now customize their community ID for easier user joining and vanity URL customization.

    Scanner UI Menu

    • Added a graphical UI to interact with in-game scanners.

    Frame Customization: In-Game Placement Menu

    • Added an in-game menu to easily customize new frames and live adjust the positioning, sizing, etc.

    Aircraft Frame Support

    • Added support to specify custom radio frames for aircraft use.

    Proxy URL - IP Backup

    • In the event that the CFX proxy fails for push events, servers will automatically fall back to a direct IP and port.

    AI Pursuit Callouts

    • Added AI powered pursuit callouts, toggleable with a hotkey. When enabled, your radio will automatically transmit your heading, street, and speed.

    Speaker Grouping

    • Added the ability to group multiple in-game speakers to a single location, cleaning up the dispatch tone board.

    #28477 Panic Open Mic

    • Added the option to automatically leave the user's microphone on for a configurable amount of time after pressing the panic button.

    Desktop: Side Mouse Button Support

    • Overhauled and wrote a custom keybind handler, allowing for better keybind support with side mouse buttons and more.

    QBox Death Support

    • Added death detection support for QBox, allowing the radio to shut off when dead.

    #29110 - CAD Call Info Close

    • Fixed an issue causing radio call information screens to not clear when a CAD call is closed or your unit is unassigned.

    ACE Perm Sync - Don't Require Auto-Approve

    • Fixed an issue causing ACE permission sync to require the auto-approve permission before granting any other permissions.

    User List Improvements

    • Fixed an issue with the in-game online users list not allowing for complete scrolling with large player counts.

    #29490 - Talking while Dead

    • Fixed an issue allowing some users to talk on the radio when the prevent transmission while dead feature was enabled.

    #29213 - Server Rack Positioning

    • Fixed an issue causing server rack repeaters to spawn and save slightly off of their proper position.

    In-Game Chatter - Custom Community PTT SFX

    • Fixed an issue causing in-game chatter to use the default mic clicks instead of the custom community-wide microphone clicks.

    Text UI Condense Improvements

    • Fixed an issue causing the transmitting username on the text based UI to show twice, taking up space and shifting the UI into two parts.

    Multiple Servers - Same IP

    • Fixed an issue where running multiple servers on the same IP (but different ports) and on the same radio community would cause one to override the push url for the other.

    Servers - Admin Delete

    • Fixed an issue where users with the admin permission could not delete servers.

    Added integration with LB phone to call emergency services and hide the emergency call banner from the user's screen.

  • Thank you to IC-Technologies for providing much of the LB Phone integration code!

  • Default Community Settings

    • Added a new customization option for default user settings when joining a community.

    Auto-Gain Control

    • Set automatic microphone gain to be enabled by default.

    Menu: Repair all Repeaters

    • Added a new menu option to repair all radio towers and repeaters at once.

    #28108 - Extended Frequency Options

    • Removed frequency restrictions from radio channels in advanced mode.

    Management Panel Lookups

    • Added new internal tools for faster customer support.

    #28202 Connected Users List

    • Fixed an issue with users transmitting on multiple channels not showing properly on the in-game user list.

    #28418 - Enforce Radio Item

    • Fixed an issue causing the enforce radio inventory item function to not work.

    HF: Chatter Exclusions

    • Fixed an issue with non-props not working properly as earpieces when configured.

    Siren Volume Increase Pop

    • Removed the volume increase/decrease sound effect when toggled via the in-game siren toggle.

    #28572 - Desktop Copy

    • Fixed a permission issue preventing the community ID/key copy function from working on desktop.

    Fixed an issue causing RocketNode promotional images to not load in the app versions of Sonoran Radio.

    Hotkeys: Per-Channel PTT
    • Added customizable per-channel PTT buttons in the dispatcher panel, allowing users to quickly switch and talk in a specific channel with one key.

    Hotkeys: Clear/Un-Set

    • Right-click on a hotkey to clear it.

    Radio Event: 911 Call Answered - Dispatcher Name

    • Added the ability to see the 911 call's dispatcher name both in-game and programmatically with the resource API.

    Tower Destruction Events

    • Added in-game events on tower destruction to help log who damaged the repeaters.

    #27676: Mic Perm Reset

    • If a user clicks deny on the in-game F8 mic permissions, it will reprompt them every time they try and use the radio.

    Modern UI - Remove Scrollbar

    • Hid the vertical scrollbar on the modern UI when in-game.

    Channel TTS Cache Busting

    • Fixed an issue causing the channel AI TTS audio to not clear cache when updated directly from the dispatch panel.

    Added an in-game command to set your radio display name

    Display Name: Export

    • Added a developer export to set your radio display name

    Voice Effects: Import/Export

    • Added a modal to import and export radio voice effect profiles

    Radio Active Export

    • Added a developer export to check if the radio is active (turned on)

    Config.lua Malformat - Throw Clear Error

    • In the event of a malformed config.lua, the resource will throw a clear error message

    Neaby Chatter: Buzz

    • Fixed an issue causing a loud but short "buzz" sound when passing a nearby radio (chatter) at rapid speeds

    HF: #27364 Panic Keybind

    • Fixed an issue throwing an error when pressing the in-game panic keybind

    Scan List Restore Post-Transmit

    • Fixed an issue causing the scan list to not properly restore after a super short transmit (by yourself or others) in your primary channel

    Added the ability to generate temporary AI powered text-to-speech tones directly from the tone board.

    Scanned Channel Audio Indicator

    • Added new UI elements on the in-game radio to indicate a transmission from a scanned channel, along with the user's name and channel.

    #27054 Mute Scanned on Primary Transmission

    • Added the setting option (enabled by default) to mute scanned channels when another user is talking on your primary channel.

    #27143 Group Change Channel Persistence

    • Using hotkeys to change your group from one to another now saves and restores your last used channel when going back to a previous group.

    Volume Hotkey SFX

    • Added customizable hotkey sound effects for the volume hotkeys.

    Tunnels: Menu Expansion

    • Added a toggle visibility button in the tunnel editor menu.

    • Added the ability to select and remove a configured tunnel via menu.

    Dispatch UI: Show Channel IDs

    • Dispatch UI now has a toggle button to view channel IDs for in-game permissions.

    Channel & Group Hotkey: In-Game Notify on No Options

    • Added small in-game notices on channel and group change hotkeys if there is no other group or channel to page to, in order to reduce confusion.

    #27173 Hotkey Resize

    • Fixed an issue causing desktop hotkeys to stop working if the screen was resized down to mobile UI mode and back.

    Added in-game and in-app hotkeys to quickly page through channels in your group.

    Group Hotkeys

    • Added in-game and in-app hotkeys to quickly page through channel groups.

    Sirens On Volume Increase

    • Added automatic, configurable volume adjustment when sirens are toggled on in-game.

    In-Game Channel Transmit Command

    • Added a new in-game command to toggle transmitting on a specific channel.

    In-Game Scan List Command

    • Added a new in-game command to toggle a scan list.

    In-Game Scan Channel Command

    • Added a new in-game command to toggle a channel scan.

    In-Game Stream Deck Integration

    • Documented Stream Deck integration with the new FiveM commands.

    Frame Selection Persist

    • In-game frame selection now persists/saves for the next time you join.

    Emergency Call Export: Answered + Ended

    • Added additional integration values for in-game emergency calls to determine when the call is answered by a dispatcher or ended by a dispatcher.

    Emergency Call Resource Export: Name Parameter

    • Added an additional parameter to customize the caller's name for in-game emergency calls.

    Scan List: Drag-and-Drop Reorder

    • Scan lists can now be reordered via drag-and-drop

    Modern UI: Group Name Display

    • The modern in-game radio style display now also lists the channel group.

    Speaker Menu: Live Updates + JSON Corrupted

    • Fixed issues causing the in-game speaker location menu to not live update in the dispatch tone board and cause the JSON config to become malformed.

    Fixed an issue causing downloaded transmission logs to be corrupt and not playable.

    Added the ability to locally record microphone audio to play over the tone board to radios and in-game speakers

    AI: Tone Text to Speech

    • Added the ability to generate AI text to speech tones

    #26385 Stacked Tones

    • Added the ability to "stack" and play multiple tones in a row

    #26534 In-Game/Mobile Radio Scan Lists

    • Added configurable scan lists to quickly swap between multiple scanned channel groups

    #26414 Persist scanned channels

    • Scanned channels now save locally to be restored when turning the radio back on

    Vocoder Bitrates

    • Added adjustable bitrates to the vocoder voice effect

    Free Vocoder

    • Made the new vocoder available to the free version of Sonoran Radio

    In-Game Text Radio SONORAN Branding

    • Added small branding to the text based display in-game when large enough (vehicle display)

    Vocoder PTT Timing

    • Overhauled and improved vocoder PTT handling to ensure local UIs update much faster without a long delay before and after the transmissions

    #26458 Connect: Permission Denied Mic General Error

    • Added improved notice and handling in the browser version if microphone permissions are not granted

    Hotkey: Prevent Left Mouse

    • Blacklisted the left mouse button from being used as a hotkey

  • Added a new "clipping" voice effect to cut audio in and out when the radio signal is poor. This effect is designed to pair particularly well with the vocoder.

  • Transfer Community

    • Added an option in the administration panel to transfer community ownership to another user.

    Emergency Call: SFX

    • Added a community customizable incoming emergency call sound effect for dispatchers.

    Backend Error API Clearnup

    • Cleaned up general backend errors from the API

    In-Game Debug

    • Removed leftover in-game debug prints

    Added three radio display options for ESC behavior (stay on screen, hide, show only while transmitting)

    Expired Community Removal

    • Added automatic community deletion, if on the free version, after 30 days with a 21 day notice

    Emergency Call: Fix Hear Radio Chatter Nearby

    • Fixed an issue where users could not hear nearby radio chatter while on a 911 call

    Hide/Close Radio when QB Item Gone

    • Fixed an issue where removing the QB/ESX radio item would not turn off and remove the radio from the user's screen

    Permission Reactivity
    • When connected to the radio, user permissions will now update in real time.

    Customize 911 Command

    • Added a new config emergencyCallCommand property to customize the /radio 911 to other numbers or words based on locality.

    Configure Default Keybinds

    • Added new configuration values to customize the default radio keybinds for new in-game users.

    In-Game Unlink via Pending Screen

    • Added an account un-link for the in-game pending community approval screen.

    Community Cards - Leave Community

    • Added a leave community button in the portal.

    In-Game Audio Subprocess Info

    • Added a short URL guide in the in-game volume slider to help users who may be having a hard time hearing people.

    Homepage - Emergency Call Promo

    • Added a promotional tab on the front page for the in-game emergency call feature.

    #25858 Radio Frames

    • Fixed an issue causing some communities to have no frame options available in settings based on their config values.

    HUD Disconnect

    • Fixed an issue causing the HUD view to show as disconnected.

    #25846 - Connected Users API

    • Fixed an API 500 error when requesting the active users, but none are connected.

    #25741 - Radio Inventory

    • Fixed an issue where using enforceRadioItem would throw an error that the radio item is not in your inventory.

    Added an export to listen for a radio panic press

    #24896 Radio Item - Customize ID and Name

    • Added customization options for the in-game radio item's ID and name

    Auto-Join User on URL Load

    • Users automatically join the community if they load a community's specific URL

    Disable PTT SFX For Myself and/or Others

    • Added a settings option to disable hearing mic-clicks for yourself and/or other users

    Mute Scanned When Transmitting

    • Added a settings option to mute scanned channels while transmitting

    Debug Mode Toggle Command

    • Added a toggle command for debug mode

    Sonoran Account Avatar

    • Added the user's Sonoran account avatar in the panel

    Core Security Update

    • Improved credential storage security

    Browser Hotkey Notice - Not Global

    • Added a notice in the settings page, if using the web version, that hotkeys are not "global" and the page must be in focus

    Apple Silicon Hotkey Fix

    • Fixed an issue causing global desktop hotkeys to be unavailable on Apple silicon based computers

    In-Game Channel Selector - Private Channels

    • Fixed an issue allowing users without permissions to access a private channel if they used the channel selector in-game

    Toggle repeater mapping spamming chat

    • Removed debug logs on repeater toggle

    #24958 QB Item Check Function

    • Updated a depreciated QB item check method

    HF: #25273 - PTT/Audio Flicker

    • Fixed an issue causing vMenu Proxychat and Mumble Chat to flicker and stick with TalkSync enabled

    HF: QB Metadata Tower Break

    • Fixed an issue in QB Core mode causing tower signals to always be perfiect if the player had no metadata property.

    HF: Member Tab

    • Fixed an issue causing the members tab to not display if the user had a permission to kick, rename, or approve members but not the admin permission.

    HF: Channel Permissions Owner Bypass

    • Fixed an issue causing private channels to be hidden for the server owner.

    HF: Move User 500

    • Fixed an issue where moving your channel via context menu would throw a 500 error.

    HF: Channel Add in Group via Dispatch

    • Fixed an issue where adding a new channel via dispatch panel would put it in the first channel group, not the group that it was added from.

    HF: TTS Replay On Reconnect

    • Fixed an issue where connecting to a non-default channel, disconnecting by switching radio panel tabs, and re-connecting would start playing the TTS of the old channel name before correcting.

    HF: AI TTS Generation on Create Channel

    • Fixed an issue causing AI TTS generation to fail when creating a new channel.

    Talkover Override
    • Added a new permission granting users the ability to double-press their PTT button to override the talkover protection and silence the other transmitter

    CMS Sync - Talkover Override Permission

    • Added the ability to manage talkover override permission via Sonoran CMS

    Talkover Override Success Tone

    • Added a new, community-customizable talkover override success sound effect

    Homepage Revamp

    • Completely revamped the homepage for feature highlights

    UI Cleanup/Component Optimization

    • General internal cleanup and optimizations, making way for new future UI possibilities

    Community Kick - Disconnect from Radio

    • When a player is kicked from the community (via Radio members tab or CMS) they will now be automatically disconnected from the radio, preventing them from transmitting any further

    Home Button - Auto-Reconnect

    • Pressing the home button on the in-game radio (to hard refresh) will now automatically re-connect the user

    Optimized Signal Quality Reports

    • Optimized in-game tower signal reporting to spam fewer updates across the websockets, only reporting when there is a significant enough change

    Permission Checks

    • Fixed multiple backend permission checks preventing users without the Admin permission from accessing functionality

    Key Input on Power Toggle

    • Fixed an issue causing the in-game "press any key" popup to display every time you turned off/on the radio, instead of just once at the initial game join

    #25095 - TTS Fast

    • AI channel name TTS will now stop playing if you quickly switch to another channel before the audio has finished

    Radio Frame - Persist Selection

    • Fixed an issue where selecting a different radio frame in the settings would not save/persist after closing the radio

    Mobile repeaters won't toggle on

    • Fixed an issue causing the G button in vehicles configured to act as a mobile repeater to not work

    Admin Panels - No Perm Redirect

    • Added local permission checks to prevent users from loading UI panels by changing the browser URL, even though the backend properly prevented data manipulation

    Unable to Leave Pending Community

    • Fixed an unauthorized error from happening when trying to leave a community you were pending in.

    New User - Unknown Display Name

    • Fixed an issue where a user newly joining the community and connecting to the radio would display as "Unknown User" to people already connected

    QB Reference Error

    • Fixed an error causing the in-game resource to fail under certain QB Core modes

    Added the ability to configure in-game tunnels and other 3D areas that reduce radio signal quality.

    AI Channel Text-To-Speech

    • Added automatic AI generated channel name TTS that will play when connecting and switching channels.

    Context Menu Name Change

    • Added the ability to right-click on a connected user to quickly modify their display name.

    Private Channel Permissions

    • Added the ability to toggle channel visibility to private, requiring a user permission to connect.

    CMS x Radio - Private Channel Permissions

    • Added the ability to automatically manage private radio channel permissions via Sonoran CMS.

    CMS x Radio - Name Sync

    • Added the ability to automatically manage radio display names via Sonoran CMS.

    Nearby Radio Chatter - Earpiece

    • Added the ability to configure in-game earpiece EUP that will prevent people nearby from hearing your radio.

    Game Resource Optimization

    • Added multiple new in-game optimizations to improve resource performance.

    Connected Users List - Save Position

    • Added size and position persistence to the in-game connected users list.

    Proxy URL - Retry

    • Added retry logic and UI errors in the event that the in-game resource can not get the proxy URL.

    #24819 - Talkover on Scan

    • Fixed an issue causing talkover protection to prevent someone listening to a channel with someone transmitting from transmitting in their own, clear channel.

    Tone Configuration Fixes

    • Fixed multiple issues with tone files and tone cosmetic customizations not being persisted or removed.

    CAD Livemap Repeater Types

    • Fixed an issue causing only the radio tower type repeaters to show on the CAD livemap.

    Alphabetically sorted display names

    Radio and Connected User Hide

    • Fixed an issue causing the radio and connected user menu to not hide when pressing ESC if no hotkey was set

    Added four radio frame options in-game to choose from, customizable by the community

    In-Game Connected List

    • Added an in-game connected users list

    Cache Busting

    • Added improved cache busting to ensure in-game radio updates are recieved faster by users

    Mic Clicks - For Local Only

    • Per-user custom mic clicks are now only heard by that user, instead of everyone on the radio

    In-Game Talk Sync

    • Talk in-game at the same time you talk in the radio

    Vehicle Radio Blue Screen

    • Fixed an issue causing switching from the handheld to vehicle radio causing a blue radio screen for some users until turned off and back on

    In-Game Talkover

    • Fixed an issue allowing some users to talkover others while talkover protection was enabled

    Added a customizable toneboard allowing dispatchers to play or repeat tones on specific channels and groups.

    Server Customization UI

    • Consolidated the server customization menu into organized tabs and improved the in-game install with a step-by-step tutorial.

    Animation Download

    • Added a tutorial step in the server customization menu to install the custom radio animations.

    New Join 403

    • Hotfix: Fixed an issue causing newly joined members to get an error on the web and desktop versions.

    Added visual signal bars in-game to view your tower connectivity

    SFX Volume

    • Added the ability to customize the sound effect volume in the settings menu

    Auto-Join on Link

    • Users now automatically join the Sonoran Radio community after linking in-game

    In-Game Enhanced Error Handling

    • Improved errors and ensured the resource fails to start without a proper community ID and API key

    Mobile UI improvements

    • Added multiple improvements for mobile users, including a dedicated UI for the radio panel

    Mobile PTT Button

    • Added a push to talk button to the mobile version (web, apps coming soon) to utilize the rado on mobile devices

    Fix: Desktop Updater

    • Fixed an issue causing the desktop application auto-updater from working

    PTT In-Game & Radio

    • Fixed an issue preventing scripts from making the player talk in-game at the same time as they're talking on the radio

    #23608 - Server Members

    • Fixed an issue limiting the number of users visible in the server members tab

    #23542 - Tower Components

    • Fixed an issue causing pieces of a radio tower to be left after removal

    #23758 Discord and Apple Login Window

    • Fixed an issue on the desktop app opening the radio in a second window after login via Discord or Apple

    Added the ability to right click on a user in-game to adjust their volume.

    Panel - Customized Download

    • Added a new download link in the radio panel that includes a pre-configured community ID and API key.

    In-game Radio - Logout

    • Added an option to logout and unlink your radio in-game via the settings menu.

    Startup - Link IP

    • Added an automatic API call to link your server's IP address to your community ID. This will be used for an upcoming integration.

    API Key - Rotate

    • Added the ability to rotate and refresh your API key if leaked.

    Menu CMS Discovery

    • Added the CMS community discovery spotlight to the portal's community selection menu.

    Talkover Protection In-Game

    • Fixed an issue causing talkover protection in-game to fail.

    Distortion Inconsistencies

    • Fixed an issue causing in-game distortion due to tower signal to not work consistently.

    In-Game Permission Re-Request

    • Fixed an issue causing the user to be asked for microphone permissions on every join.

    Improved the /link portal UI with automatic focusing, forward/back navigation, and submission.

    In-Game Towers

    • Added three radio repeater models for in-game signal strength.

    In-Game Resize and Move

    • Added the ability to resize and move the radio UI.

    Custom Animation Support

    • Added the ability to disable in-game animations while talking, for custom animation scripts.

    Developer Exports - PTT

    • Added developer exports when a user activates and deactivates their PTT hotkey.

    #23262 - Desktop Hotkey

    • Fixed an issue with updating your keybind not setting until an application restart

    Added per-user volume controls

    Talkover Protection

    • Added toggleable talkover protection

    Channel Change: Drag-and-drop

    • Move users by dragging and dropping

    • Fixed connecting on another window redirecting to home (which would break the in-game resource)

    2.26.4 04/21/2026

    2.26.3 - 04/07/2026

    2.26.0 - 04/03/2026

    2.25.0 - 03/30/2026

    2.24.5 - 02/18/2026

    2.24.4 - 02/17/2026

    2.24.0 - 01/29/2026

    2.23.2 - 01/07/2026

    2.22.2 - 01/02/2026

    2.22.1 - 12/30/2025

    2.22.0 - 12/29/2025

    2.21.7 - 12/22/2025

    2.21.3 - 10/28/2025

    2.21.2 - 10/21/2025

    2.21.0 - 10/17/2025

    2.20.0 - 07/21/2025

    2.19.0 - 07/10/2025

    2.18.0 - 05/08/2025

    2.17.2 - 04/07/2025

    2.17.0 - 04/03/2025

    2.16.0 - 03/10/2025

    2.15.0 - 02/12/2025

    2.14.0 - 01/30/2025

    2.13.2 - 01/22/2025

    2.13.0 - 01/21/2025

    2.12.0 (Full Release) - 12/31/2024

    2.11.0 (Beta) - 12/19/2024

    2.10.0 (Beta) - 12/03/2024

    2.9.0 (Beta) - 11/07/2024

    2.8.0 (Beta) - 10/10/2024

    2.7.2 (Beta) - 09/27/2024

    2.7.0 (Beta) - 09/25/2024

    2.6.2 (Beta) - 09/13/2024 (In-Game Only)

    2.6.1 (Beta) - 09/11/2024 (In-Game Only)

    2.6.0 (Beta) - 09/11/2024

    2.5.0 (Beta) - 08/16/2024

    2.4.0 (Alpha) - 08/05/2024

    2.3.0 (Alpha) - 7/11/2024

    2.2.1 (Alpha) - 07/03/2024 (In-Game Only)

    2.2.0 (Alpha) - 07/02/2024

    2.1.1 (Alpha) - 06/21/2024

    2.1.0 (Alpha) - 06/18/2024

    2.0.1 (Alpha) - 06/18/2024

    2.0.0 (Alpha) - 06/06/2024