F5 StudioF5 Studio
Skip to main content

Configuration

F5 Redeem Code has two configuration files, both inside the config/ folder:

FileLoaded asContents
config/config.luasharedEverything below — general, command, admin, rewards, codes, framework/inventory, money, database, debug
config/config_webhooks.luaserver-onlyDiscord webhook URLs, per-event colors, queue tuning (Webhooks)
Server-only

config/config_webhooks.lua is loaded only on the server. Never put webhook URLs in config.lua — they would leak to clients.

Sections in config.lua are ordered by how often a server owner needs them — general first, advanced tuning last.

General

config/config.lua
F5Cfg.Locale = 'en'
OptionTypeDefaultDescription
Localestring'en'Translation file from locales/<code>.lua. Ships with en and pl. See Localization

Command

config/config.lua
F5Cfg.Command = {
redeem = 'redeem',
admin = 'redeemadmin',
suggestion = true,
}
OptionTypeDefaultDescription
redeemstring'redeem'Chat command players run to open the redeem panel
adminstring'redeemadmin'Chat command admins run to open the management console
suggestionbooleantrueShow both /command hints in the chat suggestion list. false hides them

See Commands.

Admin Panel

config/config.lua
F5Cfg.Admin = {
acePermission = 'f5code.admin',
frameworkGroups = { 'admin', 'god' },
auditWebhook = true,
actionCooldownMs = 800,
pageSize = 25,
}
OptionTypeDefaultDescription
acePermissionstring'f5code.admin'ACE permission that grants access. '' disables the ACE path
frameworkGroupsstring[]{ 'admin', 'god' }Framework groups that grant access. {} disables group-based access
auditWebhookbooleantrueMirror admin actions and redemptions to Discord. When false, no webhooks are sent at all
actionCooldownMsnumber800Per-admin debounce on mutating actions — create / update / delete / clear history (ms)
pageSizenumber25Number of redemption-history rows loaded into the admin panel

Access is granted if the player passes the ACE permission OR belongs to a listed framework group. See Admin Panel → Access Control.

Rewards

Global limits on what a single code can grant.

config/config.lua
F5Cfg.Rewards = {
allowMoney = true,
allowItems = true,
maxMoney = 1000000,
maxItems = 10,
maxItemAmount = 100,
}
OptionTypeDefaultDescription
allowMoneybooleantrueIntended master switch for money rewards. Reserved — see the note below
allowItemsbooleantrueIntended master switch for item rewards. Reserved — see the note below
maxMoneynumber1000000Maximum total money per code (sum across all money accounts). A code exceeding it is rejected with admin_money_over_limit
maxItemsnumber10Maximum number of distinct items per code. Extra items beyond the limit are dropped
maxItemAmountnumber100Maximum amount per single item. Each item amount is clamped to 1 … maxItemAmount
allowMoney / allowItems are reserved

These two flags are present in the config but are not currently enforced by the server. The admin console always offers the Money, Items and Both reward types regardless of their values. maxMoney, maxItems and maxItemAmount are enforced.

See Features → Rewards.

Codes

Rules for the code strings themselves and the redeem flow.

config/config.lua
F5Cfg.Codes = {
maxCodeLength = 32,
minCodeLength = 3,
caseInsensitive = true,
cooldownMs = 2000,
validatePrivateTarget = true,
maxPrivateTargets = 50,
}
OptionTypeDefaultDescription
maxCodeLengthnumber32Codes are truncated to this length on both redeem and create
minCodeLengthnumber3Codes shorter than this are rejected on create (admin_invalid_data)
caseInsensitivebooleantruetrueSUMMER2024 and summer2024 match the same code (lookups and duplicate checks use LOWER()); false → codes are case-sensitive
cooldownMsnumber2000Per-player debounce between redeem attempts (ms). A faster retry returns redeem_cooldown
validatePrivateTargetbooleantruetrue → private-code target Citizen IDs must exist in the player DB (online fast-path, then one batched query). false → skip the DB check and trust the input
maxPrivateTargetsnumber50Maximum target Citizen IDs per private code. Extra targets beyond the cap are dropped

See Features → Code scope and Features → Redeem validation.

Framework & Compatibility

Framework, inventory and notification selection. All default to 'auto'.

config/config.lua
F5Cfg.Framework = {
mode = 'auto', -- 'auto' | 'esx' | 'qb' | 'qbx' | 'custom'
inventory = 'auto', -- 'auto' | 'ox' | 'qb' | 'qs' | 'ps' | 'codem' | 'tgiann' | 'esx_native' | 'custom'
notify = 'auto', -- 'auto' | 'framework' | 'oxlib'
notifyStyle = 'custom', -- 'custom' | 'native'

custom = { base = 'qb', getCore = nil, --[[ ... ]] },
}

F5Cfg.Inventory = {
imageUrl = 'auto',
custom = nil,
}
OptionTypeDefaultDescription
Framework.modestring'auto''auto' detects ESX/QB/QBX by resource; or force a specific adapter, or 'custom' for a fork
Framework.inventorystring'auto''auto' detects the inventory; or force one
Framework.notifystring'auto''auto' uses ox_lib when present, else the framework's native notify; 'framework' forces the framework; 'oxlib' forces ox_lib
Framework.notifyStylestring'custom''custom' = this resource's styled in-NUI toasts; 'native' = hand the message to the notify backend
Framework.customtableCustom-framework adapter config (only when mode = 'custom')
Inventory.imageUrlstring'auto''auto' matches the detected inventory's image path, or set a nui://<resource>/.../%s.png override used for item icons in the panels
Inventory.customtablenilCustom-inventory adapter callbacks (only when Framework.inventory = 'custom')

The full detection logic, the custom adapter fields, and all per-inventory image paths are documented on the Framework Compatibility page.

Money & Currencies

Account-based (non-item) money. A code can pay out to one or several of these accounts at once.

config/config.lua
F5Cfg.Money = {
payoutType = 'bank',

types = {
{ id = 'cash', label = 'Cash', icon = 'fa-solid fa-money-bill-wave', accounts = { qb = 'cash', qbx = 'cash', esx = 'money' } },
{ id = 'bank', label = 'Bank', icon = 'fa-solid fa-building-columns', accounts = { qb = 'bank', qbx = 'bank', esx = 'bank' } },
{ id = 'crypto', label = 'Crypto', icon = 'fa-solid fa-coins', accounts = { qb = 'crypto', qbx = 'crypto' } },
{ id = 'blackmoney', label = 'Black Money', icon = 'fa-solid fa-sack-dollar', accounts = { esx = 'black_money' } },
},
}
OptionTypeDefaultDescription
payoutTypestring'bank'Default account for legacy single-amount codes (codes stored without a per-account list). Must be the id of an active type
types[].idstringInternal currency id (alphanumeric, _ and -)
types[].labelstringDisplay label shown in the admin console and rewards
types[].iconstringA Font Awesome class (e.g. fa-solid fa-coins) or an image path relative to the NUI
types[].accountstableNative account key per framework (qb / qbx / esx)

A type with no account for the active framework is auto-skipped (e.g. crypto has no ESX account, blackmoney has none on QB/QBox). If payoutType resolves to a skipped/invalid type, the bridge falls back to bank, then to the first active type. The active list is what admins see as the per-account money inputs when creating a code. See Framework Compatibility → Money & Currencies.

Database

config/config.lua
F5Cfg.Database = {
autoCreateTables = true,
}
OptionTypeDefaultDescription
autoCreateTablesbooleantrueCreate and migrate the schema on resource start. When false, no tables/columns/indexes are created or migrated — you must import code.sql and manage the schema yourself
caution

When autoCreateTables = true, the built-in schema creates both tables with every column; on installs that predate a column, migrations patch in the newer moneys, target_citizenids, creator_name, creator_steam and steam columns and the code_active generated column. The bundled code.sql is an older base subset missing those, and nothing is created or migrated when autoCreateTables = false. Keep the default unless you manage the schema yourself.

Debug

config/config.lua
F5Cfg.Debug = {
enabled = false,

categories = {
INIT = true, BRIDGE = true, UI = true, CODE = true, REDEEM = true,
ADMIN = true, IO = true, WEBHOOK = true, SECURITY = true,
PERF = false, ERROR = true,
},

colors = { --[[ ANSI color per category ]] },
severityPrefix = { info = '', warn = '[WARN] ', err = '[ERR] ' },
perfThresholdMs = 50,
}
OptionTypeDefaultDescription
enabledbooleanfalseMaster switch for all debug output (server, client, NUI). false → nothing prints regardless of category
categories.<NAME>booleanmixedPer-category toggle
colors.<NAME>string^1..^8FiveM ANSI color code per category (server console)
severityPrefixtable(see above)Prefix per severity (info / warn / err)
perfThresholdMsnumber50DB queries slower than this (ms) log to the PERF category
CategoryWhat it logs
INITResource start, config/schema loading, client readiness
BRIDGEFramework / inventory / money detection and resolution
UINUI open/close, panel requests, frontend events
CODECode lookups and validation during redeem
REDEEMThe reward-granting pipeline
ADMINAdmin panel actions (create / update / delete / clear)
IODatabase queries and the SQL bridge
WEBHOOKDiscord webhook dispatch
SECURITYRejected actions, cooldowns, missing permissions
PERFSlow DB queries above perfThresholdMs
ERRORErrors (always logged when the master switch is on)

The Debug system is unified across server, client and NUI — the NUI receives its own copy of enabled + categories on every panel open, so the browser console mirrors the same category filtering. There are no loose print() calls; everything flows through F5Cfg.Debug.

See Also