Installation Guide
Step-by-step setup for oxide-dispatch.
Step-by-step setup for oxide-dispatch.
Prerequisites
Required resources
| Resource | Minimum Version | Purpose |
|---|---|---|
ox_lib | latest | Commands, callbacks, locale, input dialogs |
oxmysql | latest | Database driver |
o-link | latest | Framework abstraction used by dispatch |
| Framework | latest | One of qb-core, qbx_core, or es_extended |
| FXServer | a recent version | The resource includes a small Node.js script and needs the server's built-in Node 22 runtime. Old FXServer builds do not have it and the resource will fail to start — update your server artifact if so. |
Supported frameworks
| Framework | Support |
|---|---|
QBCore (qb-core) | Full |
QBX (qbx_core) | Full |
ESX Legacy (es_extended) | Full |
o-link expectations
oxide-dispatch expects your o-link setup to provide:
- Character identifier and name lookup (
olink.character.GetIdentifier,olink.character.GetName) - Character metadata read/write (
olink.character.GetMetadata,olink.character.SetMetadata) — used for callsigns - Job lookup (
olink.job.Get,olink.job.GetPlayersWithJob) - Notify (
olink.notify.Send) - Callbacks (
olink.callback) - Optional radial provider (
olink.radial.AddItem/RemoveItem) — if your radial provider is registered, the single Dispatch menu appears (Call 911 / 311 for everyone, plus status / callsign / panic entries for responders) - Player lifecycle events (
olink:server:playerReady,olink:server:playerUnload,olink:server:jobChanged,olink:server:playerDied)
Installation
Place the resource
Place oxide-dispatch inside your server's resources folder.
Add startup order
Start dependencies in order, then dispatch, then any downstream MDT consumer:
ensure ox_lib
ensure oxmysql
# ensure your framework here (qb-core / qbx_core / es_extended)
ensure o-link
ensure oxide-dispatch
# downstream consumers (e.g. oxide-police) start AFTER oxide-dispatchoxide-dispatch must start after o-link (because it consumes the bridge) and before any resource that reads its alerts (such as an MDT).
Install the SQL schema
Run sql/install.sql against your database before starting the resource.
The install creates:
dispatch_alerts— persistent alert records (audit trail, expiry, closure, replies)dispatch_responders— responder attach/detach history per alert
Review configuration
Adjust the live config files:
shared/config.lua— debug, broadcast policy, popup behavior, auto-expiry, heatmapshared/config/alerts.lua— the dispatch code catalogshared/config/jobs.lua— responder groups and job mappingshared/config/statuses.lua— per-group responder status listsshared/config/detection.lua— automatic crime detection toggles, weapon blacklist, zone blacklistshared/config/panic.lua— panic subsystem and civilian 911/311 categoriesshared/config/compat.lua— legacy QB/ESX compatibility shims
See the Configuration Reference for the full reference.
(Optional) Customize keybinds
oxide-dispatch registers two default keybinds via RegisterKeyMapping:
G— Accept latest dispatch alertF4— Panic / Responder Needs Backup
Players can rebind these from the FiveM key bindings menu (FiveM → Settings → Key Bindings → FiveM).
Verify the packaged UI
The manifest points to web/dist/index.html:
ui_page 'web/dist/index.html'If you are only installing the resource, no UI build step is required. Rebuild the UI only when editing web/src:
cd web && npm install && npm run buildFramework-Specific Setup
oxide-dispatch ships with shims for legacy police-alert events on QBCore and ESX. Follow the guide that matches your framework — you only need the one that matches the framework you actually run.
Recommended Downstream MDT
oxide-police is the recommended downstream MDT consumer. It reads alerts through the olink.dispatch.* namespace and provides a full police MDT, evidence, and case-management UI on top of dispatch. If you use oxide-police, ensure it loads after oxide-dispatch in your server.cfg.
When oxide-police is running, oxide-dispatch automatically:
- Defers police duty checks to
exports['oxide-police']:IsPlayerOnDuty(source)(fail-open if the call errors) - Pulls the active LEO job list from
oxide-police'spolice_departmentstable viaPoliceLookup - Publishes per-player statebags
oxide-dispatch:isLEO(boolean) andoxide-dispatch:responderGroup(string|nil) for downstream consumers
If you want to hide the Dispatch Hub radial entry on servers using oxide-police's MDT, set Config.DispatchHub.RadialEnabled = false in shared/config.lua. Note: this hides the entry for ALL responder groups (EMS / fire / custom) too — leave it true if you want those groups to keep the hub while LEOs use the MDT.
If you do not use oxide-police, dispatch still works standalone — alerts broadcast to on-duty responders via the in-game popup, and the Dispatch Hub is available to all responder groups including police.
Optional: AI Radio Dispatcher
oxide-dispatch includes optional AI-powered dispatchers — one per framework job (LSPD, BCSO, SASP, AMR EMS, fire, etc.). Officers tune to their department's channel, press PTT, and the AI listens, replies verbally, and files structured alerts through the same pipeline as the rest of the resource.
The feature is enabled in config by default but inactive until you provide an OpenAI API key. To enable it:
Add it as a server convar:
set oxide:ai-dispatch:openai_key sk-...Use set, not setr — set keeps the key on the server only; setr would copy it to every player who connects, exposing your key.
Provision each AI radio channel via your radio system — oxide-police's admin panel if you use it, or any other pma-voice-compatible radio UI. Defaults ship with three channels enabled: 911 = police, 921 = EMS (ambulance), 931 = Fire. Enable or remove others (BCSO / SASP / custom) in shared/config/ai_dispatch.lua as needed.
Each channel's job value must match a job that actually exists on your server, spelled exactly as your framework has it (usually lowercase). If your police job isn't called police (for example lspd), edit channel 911's job in shared/config/ai_dispatch.lua — otherwise no officer will be able to use the 911 AI channel.
oxide-dispatch.Officer voice audio is transmitted to OpenAI when enabled. Read the privacy notice in the AI Radio Dispatcher guide before turning the feature on.
Full setup, cost notes, privacy disclosure templates, and troubleshooting live in the AI Radio Dispatcher guide.
Verification
ox_lib, oxmysql, your framework, o-link, and oxide-dispatch all load without dependency errors.ensure oxide-dispatch in the live server console (or check txAdmin's Resources page) and make sure no red error text appears. On a default install the resource prints no startup message of its own (its boot logs are debug-level and hidden) — no news is good news.police).testdispatch 10-71 police from the server console. To use /testdispatch in game instead, the player needs admin permission first — add add_ace group.admin command.testdispatch allow to your server.cfg. Without it, the command silently does nothing.G to accept the alert. Confirm the GPS waypoint sets and the responder list updates./panic from the responder. Confirm a panic alert reaches colleagues in the same group./911 robbery in progress. Confirm an on-duty officer receives the call.Notes
Framework Support
oxide-dispatch works on QBCore, QBX, and ESX through o-link. All exports, callbacks, and events behave identically on every supported framework.
Locales
Locale files live in locales/*.json and are loaded through lib.locale(). The shipped locale is en.json. To add another language, drop a <lang>.json next to it and set setr ox:locale <lang> in your server.cfg.
Database character set
The schema uses utf8mb4. Servers running on utf8 (without mb4) may fail on the JSON columns — match the schema or upgrade the database.