Configuration
wasabi_billing is configured through shared, client, and server config files.
Restart wasabi_billing after changing Lua configuration, providers, or translations. Review existing invoices and back up your database before changing society classification or enabling collection.
config/shared/config.luaβ
Shared settings used by both client and server.
Config = {}
-- Debug mode: verbose lib.print.debug output + the /openbilling dev command
Config.Debug = false
-- Currency
Config.Currency = '$'
Config.CurrencyOnRight = false
-- Invoices
Config.ReferenceIdPrefix = 'IN-'
Config.MaxDaysToPayInvoice = 6
Config.RemoveMoneyAutomaticallyAfterMaxDays = false
Config.MaxCustomAmount = 10000
Config.VATPercentage = 10
Config.EnableReceiveVATSociety = false
Config.SocietyToReceiveVAT = 'judge'
Config.PreferredPaymentMethod = 'bank'
Config.InvoiceItem = 'invoice'
Config.CreateInvoiceDistance = 5.0
Shared optionsβ
| Option | Type | Description |
|---|---|---|
Config.Debug | boolean | Enables verbose debug logging and the /openbilling client command. |
Config.Currency | string | Currency symbol shown in the UI. |
Config.CurrencyOnRight | boolean | Places the currency symbol after the amount when true. |
Config.ReferenceIdPrefix | string | Prefix applied to newly generated invoice references. Existing references are not renamed. |
Config.MaxDaysToPayInvoice | number | Days a new invoice has to be paid before it becomes overdue. Existing deadlines are not recalculated. |
Config.RemoveMoneyAutomaticallyAfterMaxDays | boolean | When false, expired invoices are flagged overdue. When true, the sweep attempts bank/society collection. |
Config.MaxCustomAmount | number | Maximum pre-VAT amount for UI-created invoices. Not enforced by the trusted server creation export or compatibility creation paths. |
Config.VATPercentage | number | VAT added to new invoices. Server creation rounds VAT to the nearest whole unit. |
Config.EnableReceiveVATSociety | boolean | Routes the VAT portion to Config.SocietyToReceiveVAT during settlement. |
Config.SocietyToReceiveVAT | string | Society that receives VAT when routing is enabled. Must have a working account in the banking backend. |
Config.PreferredPaymentMethod | string | Default personal payment account: 'bank' or 'cash'. Automatic collection and society debits still use bank/society money. |
Config.InvoiceItem | string / false | Physical copy item name. Set false to disable item registration and delivery. |
Config.CreateInvoiceDistance | number | Nearby player radius in meters for UI creation. Not an export/compatibility distance limit. |
New invoice amounts are floored to whole units. VAT is calculated as math.floor(amount * (VATPercentage / 100) + 0.5). The create modal currently floors its VAT preview instead of rounding, so a fractional VAT calculation can show a different preview; the created invoice record is authoritative. VAT routing and employee percentages are read at payment time.
Society permissionsβ
Config.SocietiesSettings controls who can send, receive, and manage society invoices.
Config.SocietiesSettings = {
allowedSocietiesToSendInvoices = {
['police'] = 1,
['ambulance'] = 1,
['mechanic'] = 1,
},
allowedSocietiesToReceiveInvoices = {
'police',
'ambulance',
'mechanic',
},
minGradesToCheckAndPaySocietyInvoices = {
['police'] = 4,
['ambulance'] = 1,
['mechanic'] = 1,
},
percentageToPlayerReceiveFromSentInvoice = {
['police'] = 5,
['ambulance'] = 5,
['mechanic'] = 5,
},
}
| Field | Description |
|---|---|
allowedSocietiesToSendInvoices | Job name β minimum grade to issue invoices as that society in the UI. |
allowedSocietiesToReceiveInvoices | Job names that may be billed as society targets. |
minGradesToCheckAndPaySocietyInvoices | Job name β minimum grade to view and manage that society's invoices. |
percentageToPlayerReceiveFromSentInvoice | Job name β percentage of the pre-VAT payout credited to the issuing employee. Missing entries use zero. |
Use raw framework job names, not display labels or ESX society_ account names. Grades are inclusive minimums (grade >= configured grade). A missing send or manage entry denies that action; adding a job to the receive list alone does not grant sending or management access. Create the corresponding account in your banking resource separately.
Example: add a taxi society without replacing the other shipped entries:
Config.SocietiesSettings.allowedSocietiesToSendInvoices.taxi = 1
Config.SocietiesSettings.allowedSocietiesToReceiveInvoices[#Config.SocietiesSettings.allowedSocietiesToReceiveInvoices + 1] = 'taxi'
Config.SocietiesSettings.minGradesToCheckAndPaySocietyInvoices.taxi = 3
Config.SocietiesSettings.percentageToPlayerReceiveFromSentInvoice.taxi = 5
Preset categoriesβ
Config.InvoiceTypes maps category IDs to labels, optional job filters, and preset reasons.
| Field | Description |
|---|---|
name | Category label shown in the UI. |
jobs | Optional array of framework job names. Omit it to make the category available to every job. |
reasons | Map of reason labels to { amount = number }, before VAT. |
Config.InvoiceTypes = {
['traffic'] = {
name = 'Traffic Violations',
jobs = { 'police', 'sheriff' },
reasons = {
['Speeding'] = { amount = 50 },
['Reckless Driving'] = { amount = 75 },
},
},
['hospital'] = {
name = 'Treatment Related',
jobs = { 'ambulance' },
reasons = {
['Medical Treatment'] = { amount = 300 },
},
},
['global'] = {
name = 'Global',
reasons = {
['Vehicle Contract'] = { amount = 300 },
},
},
}
Selecting a preset fills in the reason and amount, but both remain editable. Presets are conveniences, not fixed-price enforcement or a permission boundary. A sheriff category entry does not grant society issuing permission unless that job is also added to the send-grade map.
Add a category after the existing table:
Config.InvoiceTypes['repairs'] = {
name = 'Vehicle Repairs',
jobs = { 'mechanic' },
reasons = {
['Bodywork'] = { amount = 250 },
['Engine repair'] = { amount = 500 },
},
}
config/client/config.luaβ
Client-facing commands, keybind, notification, and UI color settings.
-- Keybind that opens the billing dashboard. Players can rebind it from the
-- FiveM keybind settings. Set to false to register no keybind at all.
Config.OpenBillingKeybind = 'F7'
Config.Commands = {
openBilling = 'billing',
createInvoice = 'createinvoice',
payReference = 'payreference',
inspectCitizen = 'inspectcitizen',
}
-- 'auto' | 'wasabi_notify' | 'wasabi_uikit' | 'lation_ui' | 'ox_lib'
Config.NotificationSystem = 'auto'
Config.UI = {
Colors = {
primary = '#08090b',
secondary = '#101217',
accent = '#31d48f',
accentBackground = '#31d48f29',
text = '#f6f8f7',
muted = '#808080',
warning = '#f4bd45',
error = '#ae1515',
},
}
Client optionsβ
| Option | Type | Description |
|---|---|---|
Config.OpenBillingKeybind | string / false | Toggle the dashboard. Set false to register no keybind. Players can rebind it in FiveM settings. |
Config.Commands.openBilling | string / false | Opens Overview. |
Config.Commands.createInvoice | string / false | Opens the Create Invoice modal. |
Config.Commands.payReference | string / false | Opens Pay by Reference. |
Config.Commands.inspectCitizen | string / false | Opens the admin inspection modal. Server lookups still require admin permission. |
Config.NotificationSystem | string | Force a notify backend, or 'auto' to detect one (wasabi_notify β wasabi_uikit β lation_ui β ox_lib). |
Set any command entry to false to skip its registration. Commands open the UI; unlike F7, they do not toggle it closed. Opening calls do not navigate to another modal when the dashboard is already open.
UI colorsβ
Config.UI.Colors is fetched when the NUI initializes.
| Field | Description |
|---|---|
primary | Primary surface. |
secondary | Secondary surface. |
accent | Brand/accent color. |
accentBackground | Translucent accent surface. |
text | Main text. |
muted | Muted text. |
warning | Warning color. |
error | Error color. |
Change individual fields rather than replacing the whole table:
Config.UI.Colors.accent = '#4a9eff'
Config.UI.Colors.accentBackground = '#4a9eff29'
config/server/config.luaβ
Server-side database, admin, provider, logging, and migration settings.
Config.CheckForUpdates = true
Config.AutomaticAddDatabaseTables = true
Config.AdminAce = 'wsbbilling'
-- 'auto' | 'wasabi_banking' | 'qb-banking' | 'okokBanking' |
-- 'Renewed-Banking' | 'framework' | 'none'
Config.BankingIntegration = 'auto'
Config.LogTransactionsToBanking = true
-- 'auto' | 'ox_inventory' | 'qb-inventory' | 'ps-inventory'
-- | 'codem-inventory' | 'jaksam_inventory' | 'tgiann-inventory'
Config.InventorySystem = 'auto'
Config.OverdueCheckInterval = 60
Config.Logger = {
enabled = false,
type = 'discord', -- 'discord' | 'ox'
webhooks = {
['invoices'] = '',
['payments'] = '',
['admin'] = '',
['default'] = '',
},
}
Config.PlayersTable = 'auto'
Config.IdentifierColumn = 'auto'
Config.MoneyColumn = 'auto'
Config.CompatExports = {
okokBilling = true,
esx_billing = true,
codemBilling = true,
}
Config.CompatImport = false
Loggerβ
| Field | Description |
|---|---|
enabled | Turns audit logging on or off. Unknown type values disable logging with a warning. |
type | 'discord' posts webhook embeds; 'ox' forwards to lib.logger. |
webhooks | Per-bucket Discord webhook URLs: invoices, payments, admin, and default. |
invoices: Creation and cancellation entries.payments: Settlements and overdue sweep changes.admin: Deletion, clearing, and import results.default: Fallback for a missing bucket key. An empty string in a named bucket suppresses that bucket instead of using the fallback.
Keep webhook URLs private in server configuration. The ox backend's wasabi_billing:<bucket> logger names are not gameplay events.
Banking, inventory, and compatibilityβ
| Option | Description |
|---|---|
Config.CheckForUpdates | Checks the Wasabi version service at startup and hourly. Reports version differences; it does not install updates. |
Config.AutomaticAddDatabaseTables | Creates/patches the invoice table, indexes, and receiver classification on boot. See Migration. |
Config.AdminAce | ACE for the admin dashboard and citizen/society inspection. Framework admin checks also apply. |
Config.BankingIntegration | Where society money lives. 'auto' picks a running backend; 'none' disables society invoices. See Dependencies. |
Config.LogTransactionsToBanking | Mirror payment-related entries through Wasabi Banking's Transaction export when that is the selected backend. |
Config.InventorySystem | Inventory backend for the physical invoice item. 'auto' detects a supported inventory. Disable items with Config.InvoiceItem. |
Config.OverdueCheckInterval | Sweep interval in seconds, clamped to a minimum of 15. The first sweep waits 10 seconds after initialization. |
Config.CompatExports | Answers events/exports for replaced billing resources. See Migration. |
Config.CompatImport | Opt-in 'okokBilling' or 'esx_billing' import on startup. There is no CodeM database importer. |
Character storageβ
The built-in storage descriptions are players/citizenid/money for QBCore/QBOX and users/identifier/accounts for ESX.
| Option | Description |
|---|---|
Config.PlayersTable | Character table used by admin directory search. 'auto' uses the framework table. |
Config.IdentifierColumn | Character identifier column used by admin directory search. |
Config.MoneyColumn | Exposed through the custom bridge's storage description; not a global override of built-in money handling. |
PlayersTable and IdentifierColumn override admin character search. That search expects either a charinfo JSON column or firstname/lastname columns. These settings do not redirect every built-in framework query or offline balance update.
Localesβ
Locale files live in:
locales/*.json
Locales are selected through ox_lib, not a billing language setting. For example, set the ox_lib locale in server.cfg before starting the resource:
setr ox:locale en
Shipped locale codes: en, de, es, fr, hi, it, ja, ko, nl, pl, pt, zh-cn, and zh-tw. English is complete; other files rely on English fallback for missing keys.
Only keys beginning with ui_ are sent to the NUI. Preset category and reason labels come from Config.InvoiceTypes.