Installation Guide
Step-by-step setup for oxide-postaljob — dependencies, start order, the database, first settings, and an in-game check.
Step-by-step setup for oxide-postaljob.
Prerequisites
Required resources
These must be installed and running on your server before the postal job will start:
| Resource | Required | Purpose |
|---|---|---|
ox_lib | Yes | Shared helper library (translations, progress bars, timers) |
oxmysql | Yes | Lets the resource save player progress and settings to your database |
o-link | Yes | Connection layer between this job and your framework (QBCore, Qbox, ESX) |
What this job uses from o-link
You don't need to configure anything here — this is just so you know which parts of your server this job talks to through o-link:
- notifications and on-screen hints
- phone messages, as texts or mail (shift updates, crew news, and the pay summary)
- paying players and charging fines
- player names and identity
- the interaction eye/target on the supervisor, boxes, the van, and drop-off points
- progress bars and menus
- vehicle keys and fuel for the delivery van
- work uniforms (optional)
If o-link is already working with your other Oxide resources, you are good to go.
Installation
Place the resource
Put the oxide-postaljob folder in your server's resources directory, alongside your other resources.
Start it after its dependencies
In your server.cfg, the postal job must start after the resources it needs. Make sure the lines appear in this order:
ensure ox_lib
ensure oxmysql
ensure o-link
ensure oxide-postaljobDatabase — nothing to do
The job creates its own database tables the first time it starts, so there is no SQL script to run. (sql/install.sql is still included if you prefer to create the tables yourself or want to see the schema.)
The progression table below is shared by current Oxide job resources. It is only created if another Oxide job hasn't already created it:
CREATE TABLE IF NOT EXISTS `job_progression` (
`char_id` VARCHAR(60) NOT NULL,
`job` VARCHAR(40) NOT NULL,
`level` TINYINT NOT NULL DEFAULT 1,
`total_count` INT NOT NULL DEFAULT 0,
`daily_streak` INT NOT NULL DEFAULT 0,
`last_activity_date` DATE NULL,
`complaints` TINYINT UNSIGNED NOT NULL DEFAULT 0,
`timeout_until` DATETIME NULL,
PRIMARY KEY (`char_id`, `job`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;The postal job saves its rows in this table with job = 'postal'.
The job creates two more shared tables in the same way:
oxide_settings, where the job saves its settingsjob_pending_payouts, where shift pay waits for a player who disconnected or logged out on shift, until their next login
Migrate old data (only if upgrading)
Skip this step on a fresh install.
If you previously ran an older version of an Oxide job that used its own progression table (for example postaljob_progression), run sql/migrate_unified_progression.sql once. It copies player progress from the old tables of every Oxide job into the shared table, then removes the old tables. If you are updating multiple Oxide jobs, only run it once total.
Back up your database before running the migration script.
Review the settings
The files under shared/ are the job's factory defaults. On the resource's first start every value is imported from them into your database; after that the database is the source of truth, and settings are edited in-game with /postaljob settings (admins only) — changes apply instantly, with no restart. A file edit only takes effect after a restart and Reset to default on that setting. See How Settings Work.
If you want to change defaults before the first start, these are the files:
shared/config.lua— main on/off switchesshared/config/job.lua— pay, crew, complaints, delivery timers, the cancel cooldownshared/config/levels.lua— the five job levels and their rewardsshared/config/locations.lua— the depot, drop-off addresses, and letterboxesshared/config/npcs.lua— the supervisor NPC, map blip, and customer modelsshared/config/outfits.lua— optional work uniformsshared/config/vehicles.lua— the delivery van and the box/mail bag propsshared/config/visuals.lua— markers, animations, and the floating waypointshared/config/tutorials.lua— first-time player hintsshared/config/models.lua— model replacements and the mailbox models the builder scans for
The most important switches, found in shared/config.lua (and under General in the settings editor):
Config.Debug = false -- extra console logging, leave off normally
Config.usePhone = true -- send shift messages to the player's phone
Config.shiftSummary = 'text' -- how the end-of-shift pay summary is shown
Config.menuStyle = 'nui' -- which style of shift menu to use
Config.MaxSlotsPerLocation = 3 -- how many players can work from one depot at onceSee the Configuration Reference for every setting explained.
Verification
Startup check
Start your server and watch the console. The resource should load without any red errors. If a required resource is missing or started in the wrong order, you will see a dependency error naming the missing resource — fix the start order and restart.
In-game check
Confirm that:
- a white delivery van spawns nearby
- you are sent to either a package pallet or a post box (the job picks one at random)
- after loading the van, a route appears on your map and a delivery timer starts
If all of that works, the resource is installed correctly.
Optional Setup
Phone shift messages
With Config.usePhone on (the default), the depot sends players messages on their phone during a shift:
- a welcome message at clock-in, telling them where to load up
- a message to both players when someone joins a crew
- a notice when the delivery van is destroyed, with the repair fee that was taken
- a notice when their deliveries are cancelled because they died or went down, and another when they're clocked out after going to hospital
- the end-of-shift pay summary (see Shift summary mode below)
These are delivered through o-link, which supports these phone resources: qb-phone, lb-phone, gksphone, okokPhone, qs-smartphone, qs-smartphone-pro, yseries, and Oxide Phone (oxide-phone).
How a message arrives depends on the phone:
| Phone | Messages arrive as |
|---|---|
Oxide Phone, gksphone, okokPhone, qs-smartphone (Quasar V3) | A text message from the depot |
qb-phone, lb-phone, yseries, qs-smartphone-pro, older qs-smartphone versions |
If a text can't be sent, the same message arrives as mail instead.
Texts need o-link 1.11.0 or newer. With an older o-link, every message arrives as mail, as before. Update o-link if you want players to get texts.
Oxide Phone's Gigs app
If you run Oxide Phone, its Gigs app shows this job with nothing to set up: the depots and whether each has room, the player's current shift (loading the van or the stop they're on, how many stops are done, their crew role, and the pay so far), and their job level. While a player carries an Oxide Phone and the Gigs app is on (it is by default), shift updates arrive there as Gigs notifications instead of texts. The pay summary at clock-out never goes to the Gigs app — it always arrives as a text or mail.
Servers without a phone
If your server doesn't run a supported phone, the messages simply won't arrive — nothing breaks. Set Config.usePhone = false (the Use phone toggle under General in /postaljob settings) to show these messages as on-screen notifications instead. Important moments (pay received, van destroyed, etc.) always also show as regular on-screen notifications.
Shift summary mode
Config.shiftSummary controls how the end-of-shift pay breakdown is shown at clock-out:
'text'(default): sent to the player's phone as a text or mail (see Phone shift messages above), with a simple clock-out notification on screen. WithConfig.usePhoneoff, a short net-pay notification is shown instead'nui': a pop-up summary on screen, with either menu style. Nothing is sent to the phone
A shift that ends any other way than a clock-out (its depot deleted, or a resource restart) gets the breakdown as with 'text', in either mode.
Menu mode
Config.menuStyle controls what the shift menu looks like:
'nui': the full custom menu with a camera view of the depot (default)'menu': a simple text menu — use this if you prefer something lightweight
Uniforms
Work uniforms are off by default. To turn them on, open /postaljob settings (admins only) → Uniforms and switch Uniforms on (Config.uniformsEnabled). The change saves to your database right away, no restart needed. On a new install that has never started, you can instead set this in shared/config/outfits.lua before the first start:
Config.uniformsEnabled = trueWhen enabled, players get a button in the shift menu to put on a GoPostal uniform while clocked in. Their own clothes are restored when they take it off or clock out. The outfit pieces are under Male outfit and Female outfit in the same part of /postaljob settings (on the Advanced tab) if you want to change the look.
Admin permission
/postaljob settings and the /postalbuilder location builder are limited to admins. To make someone an admin, add them to the admin group and grant that group the admin ace in your server.cfg:
add_principal identifier.license:<their-license> group.admin
add_ace group.admin admin allowIf you already run QBCore, Qbox, or ESX admins, you don't need to do anything extra — your existing framework admins pass automatically. See Admin Tools for how it works.
Note for UI Developers
The resource ships with a ready-built interface in web/dist — you do not need to build anything. Rebuilding is only necessary if you edit the source files under web/src:
cd web && npm install && npm run build