Exports & API Reference
Server-side exports for integrating with oxide-radio — channel registration, player channel state, roster tags, and settings.
Reference for developers integrating another resource with oxide-radio. All of oxide-radio's integration API is server-side exports — there are no client exports. If you just run the resource as a server owner, you don't need anything here.
Server Exports
All exports are called on the server.
Channels
Register and inspect restricted channels at runtime. A channel you register this way is owner-scoped (tied to your resource), takes priority over any Config.JobChannels entry on the same frequency, and is released automatically when your resource stops.
RegisterChannel
Registers (or updates) a restricted channel owned by the calling resource.
local ok, reason = exports['oxide-radio']:RegisterChannel(9, {
label = 'Fire Dispatch',
jobs = { 'fire', 'lsfd' }, -- case-sensitive job names
minRank = 0, -- optional, default 0 (any grade)
dutyOnly = false, -- optional, default false
default = false, -- optional, default false (tune this job in at clock-on)
})Parameters:
| Name | Type | Description |
|---|---|---|
channel | number | The frequency (a whole number, 1 or higher). May sit outside the open dial range |
def | table | The channel definition (see below) |
def shape:
| Field | Type | Required | Description |
|---|---|---|---|
label | string | Yes | Name shown on the radio for this frequency |
jobs | table | Yes | List of allowed job names (case-sensitive). Must contain at least one non-empty string |
minRank | number | No | Minimum job grade (default 0) |
dutyOnly | boolean | No | Require on-duty (default false) |
default | boolean | No | Tune qualifying players to this frequency when they clock on (default false) |
Returns: boolean, string|nil — true on success. On failure, false and a reason: 'invalid_channel' (bad frequency), 'invalid_definition' (missing/empty label or jobs), or 'taken' (another resource already owns that frequency).
Re-registering a frequency your own resource already owns updates it. Registering a frequency that also has a Config.JobChannels entry logs a warning and shadows the config entry until you release it.
UnregisterChannel
Releases a channel your resource previously registered.
local ok = exports['oxide-radio']:UnregisterChannel(9)Parameters:
| Name | Type | Description |
|---|---|---|
channel | number | The frequency to release |
Returns: boolean — true if your resource owned that frequency and it was released; false otherwise. You can only unregister a channel your own resource registered. (Channels are also released automatically when your resource stops, so you rarely need to call this.)
GetChannels
Returns the effective set of all restricted channels — both Config.JobChannels and every runtime registration merged together.
local channels = exports['oxide-radio']:GetChannels()
-- channels = {
-- [1] = { label = 'Police Dispatch', jobs = {...}, minRank = 0, dutyOnly = false, default = true, source = 'settings' },
-- [9] = { label = 'Fire Dispatch', jobs = {...}, minRank = 0, dutyOnly = false, default = false, source = 'my-fire-resource' },
-- }Returns: table — a map keyed by frequency. Each entry is { label, jobs, minRank, dutyOnly, default, source }, where source is 'settings' for a config channel or the owning resource name for a runtime channel. A runtime registration overrides a config entry on the same frequency.
Player channel state
GetPlayerChannel
Returns the frequency a player is currently on.
local freq = exports['oxide-radio']:GetPlayerChannel(source)Parameters:
| Name | Type | Description |
|---|---|---|
source | number | The player's server id |
Returns: number — the current frequency, or 0 if the player is not on any channel.
JoinChannel
Puts a player on a channel from the server side (for example, auto-joining an officer to their department channel at clock-on). All the normal access checks still apply — a player who doesn't qualify won't be joined.
local ok, reason = exports['oxide-radio']:JoinChannel(source, 9)Parameters:
| Name | Type | Description |
|---|---|---|
source | number | The player's server id |
channel | number | The frequency to join |
Returns: boolean, string|nil — true on success; on failure false and a reason (e.g. 'invalid_source', 'channel_restricted', 'need_radio'). This export does not take a password, so use it for job channels and open frequencies, not for joining a player onto an encrypted frequency.
LeaveChannel
Takes a player off their current channel.
local ok = exports['oxide-radio']:LeaveChannel(source)Parameters:
| Name | Type | Description |
|---|---|---|
source | number | The player's server id |
Returns: boolean — true if the player was on a channel and was removed; false if they weren't on one.
Roster: tags and downed flag
SetMemberTag
Sets a short tag shown next to a player's name on the roster and overlay (e.g. a badge or unit number). oxide-police uses this to show officer badge numbers.
exports['oxide-radio']:SetMemberTag(source, '4021') -- set a tag
exports['oxide-radio']:SetMemberTag(source, nil) -- clear itParameters:
| Name | Type | Description |
|---|---|---|
source | number | The player's server id |
tag | string | number | nil | The tag to show. Trimmed; capped at 20 characters. nil (or empty) clears it |
Returns: nothing. The tag is remembered for the player and re-applied if they switch channels; if they're currently on a channel, the roster updates live.
SetRadioDead
Flags a player as "down" on the roster (or clears the flag). Use this from a death/medical resource.
exports['oxide-radio']:SetRadioDead(source, true) -- mark down
exports['oxide-radio']:SetRadioDead(source, false) -- mark back upParameters:
| Name | Type | Description |
|---|---|---|
source | number | The player's server id |
isDead | boolean | true to show them as down, false to clear |
Returns: nothing. The flag is remembered and re-applied on join. Note that oxide-radio already picks up death/downed state automatically through o-link's death events (see below), so you only need this export if you run a death system that o-link doesn't relay.
Settings
Read and write the resource's database-backed configuration at runtime, keyed by the setting name without the Config. prefix.
local requireItem = exports['oxide-radio']:GetSetting('RequireItem')
local ok = exports['oxide-radio']:SetSetting('RequireItem', false)GetSetting
Parameters: key (string) — the setting name (e.g. 'Item', 'MinFrequency', 'JobChannels').
Returns: any — the current database-backed value.
SetSetting
Parameters: key (string), value (any) — the setting name and its new value.
Returns: boolean — updates the setting live: applies it on the server immediately, saves it to the database, and syncs it to clients. The change persists across restarts. (Editing the database row directly instead needs a resource restart to take effect.)
Events the resource consumes
oxide-radio does not expose custom events for other resources to trigger — use the exports above. For context, it listens to these o-link lifecycle and death events to keep channel membership and the roster correct:
olink:server:playerDropped,olink:server:playerUnload— clean up a leaving playerolink:server:jobChanged,olink:server:dutyChanged— re-check the player's restricted-channel accessolink:server:playerDied,olink:server:playerDowned— flag the player as down on the rosterolink:server:playerRevived,olink:server:playerRespawned— clear the down flag
Because these come from o-link, they work with whatever framework and death system you run. You don't fire these yourself.
Integration Examples
Register a department channel and auto-join officers
This is the pattern a job resource uses. Register the channel when your resource starts, and join officers when they clock on. Use o-link for the framework-side pieces (who's police, who's on duty).
local RADIO = 'oxide-radio'
local FIRE_DISPATCH = 9
-- Register our channel once, on start.
CreateThread(function()
if GetResourceState(RADIO) ~= 'started' then return end
exports[RADIO]:RegisterChannel(FIRE_DISPATCH, {
label = 'Fire Dispatch',
jobs = { 'fire', 'lsfd' },
})
end)
-- When a firefighter clocks on, put them on the channel and show their unit number.
RegisterNetEvent('my-fire:server:clockOn', function()
local src = source
if GetResourceState(RADIO) ~= 'started' then return end
exports[RADIO]:JoinChannel(src, FIRE_DISPATCH)
exports[RADIO]:SetMemberTag(src, getUnitNumber(src)) -- your own lookup
end)Flag a downed player from a custom death system
Only needed if your death system isn't relayed by o-link (most are).
RegisterNetEvent('my-medical:server:playerDown', function()
if GetResourceState('oxide-radio') ~= 'started' then return end
exports['oxide-radio']:SetRadioDead(source, true)
end)Read who is on a channel
-- Which frequency is this player on?
local freq = exports['oxide-radio']:GetPlayerChannel(source)
if freq ~= 0 then
print(('player %d is on frequency %d'):format(source, freq))
endGuard your calls. oxide-radio is an optional dependency for most integrators. Check GetResourceState('oxide-radio') == 'started' before calling its exports so your resource still works when the radio isn't installed.
Next Steps
- Features — how the radio works in game
- Admin Guide — admin commands and the settings menu
- Troubleshooting — fixes for common problems