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:

NameTypeDescription
channelnumberThe frequency (a whole number, 1 or higher). May sit outside the open dial range
deftableThe channel definition (see below)

def shape:

FieldTypeRequiredDescription
labelstringYesName shown on the radio for this frequency
jobstableYesList of allowed job names (case-sensitive). Must contain at least one non-empty string
minRanknumberNoMinimum job grade (default 0)
dutyOnlybooleanNoRequire on-duty (default false)
defaultbooleanNoTune qualifying players to this frequency when they clock on (default false)

Returns: boolean, string|niltrue 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:

NameTypeDescription
channelnumberThe frequency to release

Returns: booleantrue 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:

NameTypeDescription
sourcenumberThe 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:

NameTypeDescription
sourcenumberThe player's server id
channelnumberThe frequency to join

Returns: boolean, string|niltrue 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:

NameTypeDescription
sourcenumberThe player's server id

Returns: booleantrue 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 it

Parameters:

NameTypeDescription
sourcenumberThe player's server id
tagstring | number | nilThe 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 up

Parameters:

NameTypeDescription
sourcenumberThe player's server id
isDeadbooleantrue 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 player
  • olink:server:jobChanged, olink:server:dutyChanged — re-check the player's restricted-channel access
  • olink:server:playerDied, olink:server:playerDowned — flag the player as down on the roster
  • olink: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))
end

Guard 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