How to create a job in QBCore
Learn to define a job in QBCore (qb-core/shared/jobs.lua) with label, defaultDuty and grades, assign it with SetJob, and safely check the permission on the server.
The problem
You want to add a new job to your QBCore server (for example mechanic or police), but you don't know where it's defined, how to assign it to a player, or how to check the permission so only that group can open its garage, locker or menu.
The cause
In QBCore jobs are not invented inside each resource: they are declared centrally in `qb-core/shared/jobs.lua`. A job is made of a human-readable `label`, a `defaultDuty` flag and a `grades` table where each grade has its `name`, an optional `isboss` and a `payment` (per-shift salary). If the job doesn't exist in that table, `SetJob` fails silently and `Player.PlayerData.job` never takes the expected name.
The solution
Define the job in qb-core/shared/jobs.lua with its grades and, from a server-side resource, assign it with SetJob. The grade key in the table (0, 1, 2…) is the level the player will receive in job.grade.level:
-- qb-core/shared/jobs.lua
-- Add your job inside the QBShared.Jobs table
QBShared.Jobs = {
-- ... other jobs ...
['mechanic'] = {
label = 'Mechanic',
defaultDuty = true, -- goes on duty (onduty) when loaded
offDutyPay = false, -- no pay while off duty
grades = {
['0'] = {
name = 'Apprentice',
payment = 50,
},
['1'] = {
name = 'Mechanic',
payment = 75,
},
['2'] = {
name = 'Shop Boss',
isboss = true, -- access to the job management (boss menu)
payment = 125,
},
},
},
}
-- Assign the job to a player (SERVER)
-- 'mechanic' = job name, 2 = grade (the grades key)
local Player = QBCore.Functions.GetPlayer(source)
if Player then
Player.Functions.SetJob('mechanic', 2)
end
-- Read the player's job
local job = Player.PlayerData.job
print(job.name) -- 'mechanic'
print(job.grade.level) -- 2
print(job.onduty) -- true/false
-- ALWAYS check the permission on the server before granting access
RegisterNetEvent('myscript:openGarage', function()
local src = source
local Player = QBCore.Functions.GetPlayer(src)
if not Player then return end
if Player.PlayerData.job.name ~= 'mechanic' then return end -- block anyone not in the group
-- ... only now: open the shop garage ...
end)Step by step
- 1.Open `qb-core/shared/jobs.lua` and add your job inside the `QBShared.Jobs` table with its `label`, `defaultDuty` and the `grades` table.
- 2.Define each rank in `grades` with a numeric string key ('0', '1', '2'…); that key is the `grade.level` the player will have. Set `name`, `payment` and `isboss = true` only on the boss rank.
- 3.Restart the server (or `refresh` + `restart qb-core`) so the new job loads into the shared table.
- 4.Assign the job from a server-side resource with `Player.Functions.SetJob('mechanic', 2)`; never trust the client to change the job.
- 5.Read the state with `Player.PlayerData.job.name`, `.grade.level` and `.onduty` for your salary, vehicle or uniform logic.
- 6.Before granting access to any restricted action, check on the SERVER `if Player.PlayerData.job.name ~= 'mechanic' then return end`. This is what separates a job from a job menu/creator: the menu only changes the value via `SetJob`, but the real security lives in these server-side checks.
Related guides
Last updated: 2026-06-29. Crxative-M is not affiliated with Cfx.re or Rockstar Games.
