Exports & API Reference

Complete API documentation for Oxide Chat.

Overview

Oxide Chat provides full compatibility with the standard FiveM chat API, plus additional functionality.

Dual Export Names

Both export names work identically:

-- These are equivalent:
exports['oxide-chat']:addMessage(...)
exports['chat']:addMessage(...)

The chat export works because Oxide Chat uses provide 'chat' in its manifest.


Client-Side Exports

addMessage(message)

Display a message in chat.

exports['oxide-chat']:addMessage(message)

Parameters

NameTypeDescription
messagetable/stringMessage data or simple string

Message Table Properties

PropertyTypeDescription
argstable{ author, message } or { message }
colortable/stringRGB array {r, g, b} or hex string #RRGGBB
templateIdstringChat type for styling
chatTypestringAlternative to templateId

Examples

-- Simple message
exports['oxide-chat']:addMessage('Hello world!')

-- With author
exports['oxide-chat']:addMessage({
    args = { 'System', 'Welcome to the server!' }
})

-- With color (RGB)
exports['oxide-chat']:addMessage({
    args = { 'Alert', 'Low health!' },
    color = { 255, 0, 0 }
})

-- With color (hex)
exports['oxide-chat']:addMessage({
    args = { 'Success', 'Transaction complete' },
    color = '#00FF00'
})

-- With chat type styling
exports['oxide-chat']:addMessage({
    args = { '', 'Server restarting...' },
    chatType = 'announcement'
})

addSuggestion(name, help, params)

Add a command suggestion to autocomplete.

exports['oxide-chat']:addSuggestion(name, help, params)

Parameters

NameTypeDescription
namestringCommand name with / prefix
helpstringDescription text
paramstableArray of parameter definitions

Param Properties

PropertyTypeDescription
namestringParameter name
helpstringParameter description

Example

exports['oxide-chat']:addSuggestion('/pay', 'Pay a player money', {
    { name = 'id', help = 'Player server ID' },
    { name = 'amount', help = 'Amount to pay' }
})

addSuggestions(suggestions)

Add multiple suggestions at once.

exports['oxide-chat']:addSuggestions(suggestions)

Parameters

NameTypeDescription
suggestionstableArray of suggestion objects

Example

exports['oxide-chat']:addSuggestions({
    { name = '/job', help = 'Check your current job' },
    { name = '/money', help = 'Check your balance' },
    { name = '/inventory', help = 'Open inventory', params = {} },
})

removeSuggestion(name)

Remove a command suggestion.

exports['oxide-chat']:removeSuggestion(name)

Parameters

NameTypeDescription
namestringCommand name with / prefix

Example

exports['oxide-chat']:removeSuggestion('/secretcommand')

clearChat()

Clear all messages from chat.

exports['oxide-chat']:clearChat()

isEnabled()

Check if chat is enabled.

local enabled = exports['oxide-chat']:isEnabled()

Returns

TypeDescription
booleanWhether chat is enabled

setEnabled(enabled)

Enable or disable chat.

exports['oxide-chat']:setEnabled(enabled)

Parameters

NameTypeDescription
enabledbooleanEnable/disable chat

Example

-- Disable chat during cutscene
exports['oxide-chat']:setEnabled(false)

-- Re-enable after cutscene
exports['oxide-chat']:setEnabled(true)

getSuggestions()

Get all registered suggestions.

local suggestions = exports['oxide-chat']:getSuggestions()

Returns

TypeDescription
tableMap of command name to suggestion data

Server-Side Exports

addMessage(target, message)

Send a message to one or all players.

exports['oxide-chat']:addMessage(target, message)
-- or
exports['oxide-chat']:addMessage(message)  -- Broadcasts to all

Parameters

NameTypeDescription
targetnumberPlayer server ID or -1 for all
messagetableMessage data

Examples

-- Send to specific player
exports['oxide-chat']:addMessage(source, {
    args = { 'Bank', 'You deposited $1,000' },
    color = { 0, 255, 0 }
})

-- Broadcast to all players
exports['oxide-chat']:addMessage({
    args = { 'Server', 'Maintenance in 5 minutes' },
    chatType = 'announcement'
})

-- Using -1 for all
exports['oxide-chat']:addMessage(-1, {
    args = { 'Event', 'Double XP is now active!' }
})

addSuggestion(target, name, help, params)

Send a command suggestion to a player.

exports['oxide-chat']:addSuggestion(target, name, help, params)

Parameters

NameTypeDescription
targetnumberPlayer server ID or -1 for all
namestringCommand name with / prefix
helpstringDescription text
paramstableParameter definitions

removeSuggestion(target, name)

Remove a suggestion for a player.

exports['oxide-chat']:removeSuggestion(target, name)

clearChat(target)

Clear chat for one or all players.

exports['oxide-chat']:clearChat(target)

Parameters

NameTypeDescription
targetnumberPlayer server ID, -1 for all, or nil for all

addTemplate(id, template)

Register a message template.

exports['oxide-chat']:addTemplate(id, template)

Parameters

NameTypeDescription
idstringTemplate identifier
templatestringTemplate format string

registerMessageHook(callback)

Register a hook that fires for unregistered slash-command input — text a player types with a leading / that no resource has registered as a command. It runs from the command-fallback path and lets you observe that input and cancel the default "unknown command" handling. It does not run for regular chat messages, /me, /do, PMs, or any registered command.

local hookId = exports['oxide-chat']:registerMessageHook(callback)

Parameters

NameTypeDescription
callbackfunctionHook function

Returns

TypeDescription
numberHook ID for reference

See Message Hooks for detailed usage.


GetSetting(key)

Read the current value of a chat setting (a Config key) at runtime. Returns whatever value is live in the server's config table for that key — including any change applied through SetSetting since the server started.

local value = exports['oxide-chat']:GetSetting(key)

Parameters

NameTypeDescription
keystringThe config key to read (e.g. 'ProximityDistance')

Returns

TypeDescription
anyThe current value of Config[key], or nil if the key is not set

SetSetting(key, value)

Change a chat setting at runtime. The new value is written to Config, saved to the database so it survives a restart, published to connected clients, and any runtime tables that depend on the key are rebuilt immediately.

exports['oxide-chat']:SetSetting(key, value)

Parameters

NameTypeDescription
keystringThe config key to change (e.g. 'ProximityDistance')
valueanyThe new value to store for that key

Returns

TypeDescription
booleanAlways true once the change is applied

Friends & Blocks Exports

Oxide Chat owns a character-based social graph (friends, friend requests, and a personal block list) and exposes it through plain server-side exports so other resources can read and manage it. These are server-side only.

Character IDs

Every function below is keyed by the character identifier — the stable o-link state_id string, not a server ID. To get the character identifier for an online player, use the o-link bridge:

local charId = olink.character.GetIdentifier(src)

The tables backing these exports (chat_friends, chat_blocks) are created automatically on first start, and the schema also ships in sql/install.sql.


GetFriends(charId)

Return a character's accepted friends.

local friends = exports['oxide-chat']:GetFriends(charId)
NameTypeDescription
charIdstringCharacter identifier

Returns: table — array of friend character identifiers.


ListRequests(charId)

Return the incoming (pending) friend requests for a character.

local requests = exports['oxide-chat']:ListRequests(charId)

Returns: table — array of character identifiers who have requested this character.


ListBlocks(charId)

Return the characters this character has blocked.

local blocks = exports['oxide-chat']:ListBlocks(charId)

Returns: table — array of blocked character identifiers.


IsFriend(a, b)

Check whether two characters are friends.

local ok = exports['oxide-chat']:IsFriend(a, b)
NameTypeDescription
astringCharacter identifier
bstringCharacter identifier

Returns: booleantrue if a has b as an accepted friend.


IsBlocked(a, b)

Check whether one character has blocked another.

local ok = exports['oxide-chat']:IsBlocked(a, b)

Returns: booleantrue if a has blocked b.


IsBlockedBetween(a, b)

Check whether either character has blocked the other. Useful before delivering a private message.

local blocked = exports['oxide-chat']:IsBlockedBetween(a, b)

Returns: booleantrue if a blocked b or b blocked a.


RequestFriend(a, b)

Send a friend request from a to b. If b has already requested a, the friendship is accepted automatically.

local ok = exports['oxide-chat']:RequestFriend(a, b)

Returns: booleantrue if the request was sent or auto-accepted, false otherwise (for example if they are already friends or a == b).


AddFriend(a, b)

Force an accepted, mutual friendship between two characters, skipping the request step.

local ok = exports['oxide-chat']:AddFriend(a, b)

Returns: booleantrue on success, false if a == b or a value is missing.


AcceptRequest(me, requester)

Accept a pending request that requester sent to me.

local ok = exports['oxide-chat']:AcceptRequest(me, requester)
NameTypeDescription
mestringCharacter accepting the request
requesterstringCharacter who sent the request

Returns: booleantrue if a matching pending request was accepted.


DenyRequest(me, requester)

Deny/remove a pending request that requester sent to me.

exports['oxide-chat']:DenyRequest(me, requester)

Returns: boolean — always true.


RemoveFriend(a, b)

Remove a friendship between two characters (in both directions).

exports['oxide-chat']:RemoveFriend(a, b)

Returns: boolean — always true.


BlockChar(a, b)

Have a block b. Blocking also drops any existing friendship between them.

local ok = exports['oxide-chat']:BlockChar(a, b)

Returns: booleantrue on success, false if a == b or a value is missing.


UnblockChar(a, b)

Have a unblock b.

exports['oxide-chat']:UnblockChar(a, b)

Returns: boolean — always true.


Client Events

chat:addMessage

Display a message.

TriggerEvent('chat:addMessage', {
    args = { 'Author', 'Message' },
    color = { 255, 255, 255 }
})

chat:addSuggestion

Add a suggestion.

TriggerEvent('chat:addSuggestion', '/command', 'Help text', {
    { name = 'param', help = 'Parameter help' }
})

chat:addSuggestions

Add multiple suggestions.

TriggerEvent('chat:addSuggestions', {
    { name = '/cmd1', help = 'Command 1' },
    { name = '/cmd2', help = 'Command 2' },
})

chat:removeSuggestion

Remove a suggestion.

TriggerEvent('chat:removeSuggestion', '/command')

chat:clear

Clear all messages.

TriggerEvent('chat:clear')

chatMessage (Legacy)

Legacy event for simple messages.

TriggerEvent('chatMessage', 'Author', { 255, 0, 0 }, 'Message text')

Server Events

chat:addMessage

Send from server to client.

TriggerClientEvent('chat:addMessage', source, {
    args = { 'Server', 'Welcome!' }
})

chat:addSuggestion

Send suggestion to client.

TriggerClientEvent('chat:addSuggestion', source, '/help', 'Show help')

chat:addSuggestions

Send multiple suggestions.

TriggerClientEvent('chat:addSuggestions', source, suggestions)

chat:removeSuggestion

Remove a suggestion.

TriggerClientEvent('chat:removeSuggestion', source, '/command')

chat:clear

Clear client's chat.

TriggerClientEvent('chat:clear', source)
TriggerClientEvent('chat:clear', -1)  -- All players

Message Format

args Array

The args array determines the message format:

-- Two elements: author and message
args = { 'John', 'Hello everyone!' }
-- Output: "John: Hello everyone!"

-- One element: message only
args = { 'System message' }
-- Output: "System message"

-- Empty author
args = { '', 'Pre-formatted message' }
-- Output: "Pre-formatted message"

Color Formats

Colors can be specified as RGB arrays or hex strings:

-- RGB array
color = { 255, 128, 0 }

-- Hex string
color = '#FF8000'

-- Nested array (legacy support)
color = {{ 255, 128, 0 }}

Chat Types

Apply styling from a chat type defined in Config.ChatChannels:

-- Using templateId
{ templateId = 'announcement' }

-- Using chatType
{ chatType = 'police' }

Chat type styling includes:

  • Color
  • Prefix (e.g., "[LSPD]")
  • Italic formatting

Message Hooks

Observe unregistered slash-command input — text a player sends with a leading / that does not match any registered command. These hooks run from the command-fallback path only. They do not fire for regular chat messages, proximity commands (/me, /do), private messages, or any registered command, so they cannot be used to filter or modify ordinary chat.

Registering a Hook

-- Server-side
local hookId = exports['oxide-chat']:registerMessageHook(function(source, author, command)
    -- `command` is the raw unregistered input, prefixed with '/'
    -- e.g. a player typing "/foobar hello" -> command == "/foobar hello"
    return { cancel = true }  -- suppress default unknown-command handling
end)

Hook Callback Parameters

ParameterTypeDescription
sourcenumberPlayer server ID
authorstringSender's character name
commandstringThe unregistered slash-command input, including the leading /

Hook Return Values

ReturnEffect
falseCancel — stop remaining hooks and suppress default handling
{ cancel = true }Cancel — stop remaining hooks and suppress default handling
nilTake no action; continue to the next hook

Hook Examples

-- Log unrecognized slash-command attempts for review
exports['oxide-chat']:registerMessageHook(function(source, author, command)
    print(('[%s] typed an unknown command: %s'):format(author, command))
end)

-- Silently swallow unregistered commands from muted players
local mutedPlayers = {}

exports['oxide-chat']:registerMessageHook(function(source, author, command)
    if mutedPlayers[source] then
        return { cancel = true }
    end
end)

Hook Cleanup

Hooks are automatically removed when their registering resource stops.


Integration Examples

Shop Purchase Notification

-- Server-side
RegisterNetEvent('shop:purchase', function(itemName, price)
    local src = source
    exports['oxide-chat']:addMessage(src, {
        args = { 'Shop', 'Purchased ' .. itemName .. ' for $' .. price },
        color = '#00FF00'
    })
end)

Job-Specific Announcement

-- Server-side (framework-agnostic via o-link)
function AnnounceToJob(jobName, message)
    for _, playerId in ipairs(olink.framework.GetPlayers()) do
        local job = olink.job.Get(playerId)
        if job and job.name == jobName then
            exports['oxide-chat']:addMessage(playerId, {
                args = { '', message },
                chatType = jobName
            })
        end
    end
end

-- Usage
AnnounceToJob('police', '[DISPATCH] 10-90 at Legion Square')

Dynamic Suggestion Updates

-- Client-side: Update suggestions based on job (framework-agnostic via o-link)
RegisterNetEvent('olink:client:jobChanged', function(job)
    -- Remove old job suggestions
    exports['oxide-chat']:removeSuggestion('/oldcommand')

    -- Add new job suggestions
    if job.name == 'police' then
        exports['oxide-chat']:addSuggestion('/cuff', 'Handcuff a player')
        exports['oxide-chat']:addSuggestion('/escort', 'Escort a player')
    end
end)

Temporary Chat Disable

-- Client-side: Disable during cutscene
function StartCutscene()
    exports['oxide-chat']:setEnabled(false)
    -- ... cutscene code ...
end

function EndCutscene()
    exports['oxide-chat']:setEnabled(true)
end

Custom Chat Type

Add a custom row to the chat types list — in /chat settingsMessaging → Chat Types, or as a factory default in config/main.lua:

-- Config addition (config/main.lua) — a custom row in Config.ChatChannels
{
    command = 'gang', label = 'Gang Radio',
    id = 'gang', prefix = 'GANG', color = '#9B59B6',
    scope = 'global', restrict = 'none',
}

-- Server-side usage
exports['oxide-chat']:addMessage(source, {
    args = { '', gangName .. ' Radio: ' .. message },
    chatType = 'gang'
})

Next Steps