This is the complete reference for Quasar Framework (qs-core): every chat and console command, every default keybind, and the exports and events you use to build your own FiveM roleplay scripts on top of the framework. Server owners and admins will find everything they can type in the first section; developers can jump straight to the exports and events.
Everything on this page comes from the resources that ship with Quasar Framework — [core], [addons] and the ESX / QBCore bridges in [bridge]. Scripts written for ESX (es_extended, ESX Legacy) or QBCore (qb-core) keep using their own API on top of these; see ESX & QBCore Compatibility for how those calls map onto qs-core.
Commands#
Commands marked Admin check the command.qs ACE of the player who types them. The server.cfg written by the txAdmin recipe grants it to everyone in group.admin with add_ace group.admin command allow, and txAdmin puts its own admins in that group. Players who lack it get No permission. — see Administration to add more admins.
Command | Key | Who | Description |
|---|---|---|---|
Player | |||
| — | Everyone | Shows your cash and bank balance in a notification. |
| — | Everyone | Hands that much cash to the nearest player within 3 m. Both players are notified. |
|
| Everyone | Opens or closes the inventory (not while downed). |
|
| Everyone | Item wheel: hold, aim at one of slots 1–5 and release to use it. |
|
| Everyone | Uses the item in quick slot 1–5. |
|
| Everyone | Opens the chat box. |
| — | Everyone | Opens your personal interface colour picker. Name set by |
| — | Everyone | Saves your character and returns you to character selection. Name set by |
| — | Everyone | Deletes your saved colours, so the intro plays again on your next connection. |
| — | Everyone | Setup helper: prints your ped's model, clothes and props to the F8 console in the format of qs-intro's |
Roleplay | |||
| — | Everyone | Describes an action to players within 20 m: |
| — | Everyone | Describes the scene to players within 20 m: |
| — | Everyone | Local out-of-character message within 20 m: |
| — | Everyone | Global out-of-character message to the whole server: |
| — | Everyone | 50/50 roll shown within 20 m as |
| — | Everyone | Private message to a player by server id. |
| — | Everyone | Floating text above your head for 8 seconds, seen by players within 20 m. |
Vehicles | |||
|
| Players with the keys | Locks or unlocks the vehicle you are in, or the closest one within 5 m. |
|
| Driver without keys, carrying a | Starts the lockpick minigame. Success gives you the keys and starts the engine; failure breaks the lockpick, sets off the alarm and can alert the police. |
| — | Players with the keys | Shares the keys of the vehicle you are sitting in with player |
|
| Driver | Toggles the seatbelt indicator on the HUD. |
| — | Admin ( | Gives player |
| — | Admin | Spawns a vehicle, puts you in the driver seat and gives you its keys. |
| — | Admin | Deletes the vehicle you are in, or the closest one within 5 m. |
Jobs | |||
| — | Job | Cuffs or uncuffs the nearest player. Cuffing needs |
| — | Job | Starts or stops escorting the nearest cuffed player. |
| — | Job | Seats the nearest cuffed player in the closest vehicle, rear seats first. |
| — | Job | Takes the nearest cuffed player out of their vehicle. |
| — | Job | Opens the inventory of the nearest player. Confiscating an item needs them cuffed. |
| — | Job | Fines the nearest player within 5 m. The amount (1–50,000) is taken from their bank. |
| — | Job | Removes the closest vehicle within 5 m. |
| — | Job | Opens the injury report of the nearest player within 4 m, or your own. |
| — | Job | Deploys your stretcher, or removes it if you already have one out. |
Administration | |||
|
| Admin | Opens the admin menu (players, money, jobs, items, weather, time, noclip, vehicles). |
| — | Admin | Sets a player's job. Grade defaults to |
| — | Admin | Adds money to |
| — | Admin | Removes money from an account (fails if the balance is too low). |
| — | Admin | Gives an item. Count defaults to |
| — | Admin | Revives a downed player (default: you). |
| — | Admin | Kills a player (default: you); they go down as from any other death. |
| — | Admin | Freezes or unfreezes a player. |
| — | Admin | Toggles god mode on yourself. |
| — | Admin | Shows a notification to everyone for 8 seconds. |
| — | Admin | Prints your position as |
| — | Admin | Teleports you to coordinates. |
| — | Admin | Teleports you to your map waypoint. |
| — | Admin | Teleports you to a player. |
| — | Admin | Teleports a player to you. |
| — | Admin | Toggles noclip (controls below). |
| — | Admin | Kicks a player. |
| — | Admin | Bans and kicks a player. |
| — | Admin | Removes every ban of a full |
| — | Admin | Saves the player's group (e.g. |
| — | Admin | Deletes the player's saved group and removes it at once. |
| — | Admin | Opens the full appearance editor for yourself, tattoos included. |
Commands that ESX scripts register with ESX.RegisterCommand and QBCore scripts register with QBCore.Commands.Add work as well. An ESX command for a group other than user needs the ACE group.<group>, group.admin or command; a QBCore command permission is checked with HasPermission (see the exports below).
Keybinds#
These commands are key mappings, so every player can rebind them in Settings → Key Bindings → FiveM. Changing the default in a config file only affects players who have never bound that command.
Key mapping | Default key | Name in Key Bindings | Default set by |
|---|---|---|---|
|
| Toggle inventory |
|
|
| Item wheel |
|
|
| Use inventory slot 1 … 5 | fixed |
|
| Lock / unlock vehicle |
|
|
| Hotwire vehicle |
|
|
| Toggle seatbelt |
|
|
| Open chat | fixed |
|
| Open admin menu |
|
Fixed controls#
These are game controls read directly by the scripts. They are not key mappings, so they do not appear in Key Bindings.
Key | Where | Action |
|---|---|---|
| Shops, garages, dealership, banks and ATMs, clothing stores, job and drug points, police station, hospital | Interact |
| Downed, after 20 seconds | Respawn at the nearest hospital |
| Downed | Call paramedics (30 second cooldown) |
| Any progress bar that can be cancelled | Cancel |
| Lockpick minigame | Set a pin / give up |
| Next to a stretcher (EMS) | Move or drop / load or unload patient / into the ambulance or store |
| Noclip | Move, up / down |
Mouse wheel / wheel click | Noclip | Change speed / reset speed |
| Noclip | 2× / 4× / 0.25× speed |
| Spectating from the admin menu | Stop spectating |
qs-core server exports#
Call them from any server script with exports['qs-core']:Name(...). source is always the player's server id. When the player has no character loaded, functions return nil, false, 0 or an empty table instead of erroring.
Players and characters#
GetPlayer
exports['qs-core']:GetPlayer(source)Parameters: source — player server id.
Returns: a player table, or nil if no character is loaded. It holds source, citizenid, PlayerData (a copy taken at the moment of the call: citizenid, license, name, charinfo, money, job, inventory, metadata, position, skin, is_dead, cid) and every player method: getCitizenId, getCharInfo, getPed, getCoords, getMoney, addMoney, removeMoney, setMoney, getJob, setJob, setJobDuty, getGang, setGang, isDead, getMetadata, setMetadata, getSkin, setSkin, addItem, removeItem, hasItem, canCarryItem, getItemCount, getSlotView, getItemBySlot, setItemInfo, setBusy, emit and save.
Example: local player = exports['qs-core']:GetPlayer(source); player:addMoney('cash', 100, 'reward')
GetPlayerByCitizenId
exports['qs-core']:GetPlayerByCitizenId(citizenid)Parameters: citizenid — the character id (QS followed by 6 characters).
Returns: the same player table as GetPlayer, or nil when that character is not online. For offline characters use GetOfflinePlayerByCitizenId.
Example: local player = exports['qs-core']:GetPlayerByCitizenId('QSA1B2C3')
GetPlayers
exports['qs-core']:GetPlayers()Parameters: none.
Returns: a list of player tables, one per loaded character.
Example: for _, p in ipairs(exports['qs-core']:GetPlayers()) do print(p.source, p.citizenid) end
GetCharacters
exports['qs-core']:GetCharacters(source)Parameters: source — player server id.
Returns: the account's characters ordered by slot, each { citizenid, cid, name, charinfo, money, job, skin, position }. Empty table if the player has no license identifier.
Example: local chars = exports['qs-core']:GetCharacters(source)
CreateCharacter
exports['qs-core']:CreateCharacter(source, charinfo, skin?, cid?)Parameters: charinfo — { firstname, lastname, dob, sex, nationality }; skin — optional appearance table; cid — optional slot number.
Returns: the new character's data, or nil, err with err = 'no_license', 'max_characters' (limit Config.MaxCharacters) or 'slot_taken'. The character starts with Config.Accounts, Config.DefaultJob and Config.DefaultSpawn. It is not loaded — call LoadCharacter next.
Example: local data, err = exports['qs-core']:CreateCharacter(source, { firstname = 'John', lastname = 'Doe', dob = '1990-01-01', sex = 'male', nationality = 'USA' })
LoadCharacter
exports['qs-core']:LoadCharacter(source, citizenid, isNew?)Parameters: citizenid — a character owned by this player; isNew — true right after creation (starting items, editor).
Returns: true, or false, err with err = 'no_license', 'not_found' or 'not_owner'. Fires qs:server:playerLoaded, qs:server:characterLoaded and spawns the player.
Example: local ok, err = exports['qs-core']:LoadCharacter(source, data.citizenid, true)
Logout
exports['qs-core']:Logout(source)Parameters: source — player server id.
Returns: true, or false if no character was loaded. Saves, unloads the character and fires qs:server:playerUnloaded and qs:client:playerUnloaded. With qs-coremulticharacter the selection screen opens again.
Example: exports['qs-core']:Logout(source)
DeleteCharacter
exports['qs-core']:DeleteCharacter(citizenid)Parameters: citizenid — character to delete.
Returns: nothing. Deletes the row from players without any ownership check, so check it yourself first (for example against GetCharacters).
Example: exports['qs-core']:DeleteCharacter('QSA1B2C3')
GetOfflinePlayerByCitizenId · SaveOfflinePlayer
exports['qs-core']:GetOfflinePlayerByCitizenId(citizenid)
exports['qs-core']:SaveOfflinePlayer(citizenid, patch)Parameters: citizenid — any character; patch — table with the top-level fields to replace (money, job, metadata, charinfo, inventory, position, skin…).
Returns: GetOfflinePlayerByCitizenId returns { Offline = true, citizenid, license, name, charinfo, money, job, inventory, metadata, position, skin, is_dead, cid } read from the database, or nil. SaveOfflinePlayer returns true once written. Use them for offline characters only: an online character is saved over by its own next save.
Example: local row = exports['qs-core']:GetOfflinePlayerByCitizenId(cid); row.money.bank = row.money.bank + 500; exports['qs-core']:SaveOfflinePlayer(cid, { money = row.money })
SetPlayerDead
exports['qs-core']:SetPlayerDead(source, state)Parameters: state — true puts the player in the downed state, false revives them.
Returns: true, or false if no character is loaded.
Example: exports['qs-core']:SetPlayerDead(source, false)
Money and accounts#
GetMoney
exports['qs-core']:GetMoney(source, account)Parameters: account — an account from Config.Accounts: cash, bank or black_money.
Returns: the balance, or 0.
Example: local bank = exports['qs-core']:GetMoney(source, 'bank')
AddMoney
exports['qs-core']:AddMoney(source, account, amount, reason?)Parameters: account — cash, bank or black_money; amount — greater than 0; reason — optional text passed to qs:server:moneyChange.
Returns: true, or false if the account does not exist or the amount is not positive.
Example: exports['qs-core']:AddMoney(source, 'bank', 500, 'bonus')
RemoveMoney
exports['qs-core']:RemoveMoney(source, account, amount, reason?)Parameters: same as AddMoney.
Returns: true, or false if the balance is too low, the account does not exist or the amount is not positive.
Example: if exports['qs-core']:RemoveMoney(source, 'cash', 250, 'shop') then ... end
SetMoney
exports['qs-core']:SetMoney(source, account, amount)Parameters: amount — 0 or more.
Returns: true or false. It does not fire qs:server:moneyChange.
Example: exports['qs-core']:SetMoney(source, 'black_money', 0)
GetAccountMoney · AddAccountMoney · RemoveAccountMoney · SetAccountMoney
exports['qs-core']:GetAccountMoney(source, account)
exports['qs-core']:AddAccountMoney(source, account, amount, reason?)
exports['qs-core']:RemoveAccountMoney(source, account, amount, reason?)
exports['qs-core']:SetAccountMoney(source, account, amount)Parameters: account — cash (alias money) and bank are the same balances as GetMoney; any other name, such as crypto, is an extra account stored in the character's metadata (accounts_extra) and created on first use.
Returns: a number for GetAccountMoney, true/false for the others. These are the functions the ESX and QBCore bridges use. For black_money, use GetMoney / AddMoney — that is the balance qs-coredrugs pays into.
Example: exports['qs-core']:AddAccountMoney(source, 'crypto', 10, 'mining')
Jobs, gangs and duty#
SetJob
exports['qs-core']:SetJob(source, name, grade?)Parameters: name — a job that exists in qs-core/shared/jobs.lua or was registered at runtime; grade — defaults to 0. A grade that does not exist falls back to the lowest grade.
Returns: true, or false for an unknown job. Fires qs:server:jobChange.
Example: exports['qs-core']:SetJob(source, 'police', 1)
RegisterJob · RegisterJobs
exports['qs-core']:RegisterJob(name, def)
exports['qs-core']:RegisterJobs({ [name] = def, ... })Parameters: def — { label, defaultDuty, grades = { [0] = { name, label, salary, isBoss } } }. Missing label becomes the name; missing grades becomes one grade employee with salary 0. Server side only, and only until the next restart.
Returns: true, or false for invalid arguments. Registering an existing name replaces it.
Example: exports['qs-core']:RegisterJob('mechanic', { label = 'Mechanic', grades = { [0] = { name = 'apprentice', label = 'Apprentice', salary = 300 } } })
UpdateJob · RemoveJob · GetJobs
exports['qs-core']:UpdateJob(name, def)
exports['qs-core']:RemoveJob(name)
exports['qs-core']:GetJobs()Parameters: name — an existing job; def — full definition (it replaces, it does not merge).
Returns: UpdateJob and RemoveJob return false if the job does not exist. GetJobs returns every job keyed by name.
Example: local jobs = exports['qs-core']:GetJobs(); print(jobs.police.label)
SetJobDuty
exports['qs-core']:SetJobDuty(source, onDuty)Parameters: onDuty — boolean.
Returns: true or false. Stores the flag in the character's metadata and job, fires qs:server:jobChange and the client qs:client:onDutyUpdate. The QBCore bridge's Player.Functions.SetJobDuty uses it.
Example: exports['qs-core']:SetJobDuty(source, true)
GetPlayersOnDuty
exports['qs-core']:GetPlayersOnDuty(jobName)Parameters: jobName — job name.
Returns: two values: a list of server ids and their count, for players with that job whose duty flag is not false.
Example: local sources, count = exports['qs-core']:GetPlayersOnDuty('police')
SetGang · GetGangForPlayer
exports['qs-core']:SetGang(source, name, grade?)
exports['qs-core']:GetGangForPlayer(source)Parameters: name — a gang name in lower case; grade — defaults to 0.
Returns: SetGang returns true/false and fires qs:server:gangChange. GetGangForPlayer returns { name, label, isboss, grade = { name, level } }, or the none gang.
Example: exports['qs-core']:SetGang(source, 'ballas', 2)
RegisterGang · RegisterGangs · GetGang · GetGangs · RemoveGang
exports['qs-core']:RegisterGang(name, def)
exports['qs-core']:RegisterGangs({ [name] = def, ... })
exports['qs-core']:GetGang(name)
exports['qs-core']:GetGangs()
exports['qs-core']:RemoveGang(name)Parameters: def — { label, grades = { [0] = { name, label, isBoss } } }. Use lower-case names. Missing grades become one grade member.
Returns: true/false; GetGang returns the definition or nil. RemoveGang refuses none. Available on the client too, with its own copy of the list.
Example: exports['qs-core']:RegisterGang('ballas', { label = 'Ballas', grades = { [0] = { name = 'member', label = 'Member' }, [1] = { name = 'boss', label = 'OG', isBoss = true } } })
Metadata and skin#
GetMetadata · SetMetadata
exports['qs-core']:GetMetadata(source, key?)
exports['qs-core']:SetMetadata(source, key, value)Parameters: key — any metadata key (hunger, thirst, gang, onduty, accounts_extra or your own); without a key GetMetadata returns the whole table.
Returns: the value (a stored false comes back as nil); SetMetadata returns true/false and sends qs:metadata:set to the player, which the HUD uses for hunger and thirst.
Example: exports['qs-core']:SetMetadata(source, 'hunger', 100)
GetSkin · SetSkin
exports['qs-core']:GetSkin(source)
exports['qs-core']:SetSkin(source, skin)Parameters: skin — the appearance table used by qs-clothing.
Returns: GetSkin returns the table or nil; SetSkin returns true/false, applies the skin on the player at once and stores it with the next character save.
Example: local skin = exports['qs-core']:GetSkin(source)
Items and inventory#
Item calls are routed to the active inventory: qs-coreinventory, or Quasar Store's qs-inventory when you run it instead of qs-coreinventory. Code written against these exports works with both.
RegisterItem · RegisterItems
exports['qs-core']:RegisterItem(name, def)
exports['qs-core']:RegisterItems({ [name] = def, ... })Parameters: def — { label, weight, useable, description, image, stack, unique, weapon, ammo }. Weight is in grams; useable = true is required for the item to do anything when used; weapon = 'WEAPON_X' makes it equip a weapon. Registering an existing name replaces it.
Returns: RegisterItem returns true/false. Register items on the server: the client keeps a separate catalogue.
Example: exports['qs-core']:RegisterItem('pizza', { label = 'Pizza', weight = 500, useable = true, description = 'A hot slice.' })
GetItem · GetItems · UpdateItemDefinition · RemoveItemDefinition
exports['qs-core']:GetItem(name)
exports['qs-core']:GetItems()
exports['qs-core']:UpdateItemDefinition(name, def)
exports['qs-core']:RemoveItemDefinition(name)Parameters: name — item name; def — full definition (it replaces, it does not merge).
Returns: a definition or nil; the whole catalogue; true/false (false when the item does not exist).
Example: local def = exports['qs-core']:GetItem('water'); print(def.label, def.weight)
AddItem
exports['qs-core']:AddItem(source, item, count?, slot?, info?)Parameters: count — defaults to 1; slot — preferred slot; info — per-item metadata table (serial numbers, evidence data…).
Returns: true or false. With qs-coreinventory it fails for unknown items, when the player would go over the weight limit (Too heavy to carry) or has no room (Inventory full).
Example: exports['qs-core']:AddItem(source, 'water', 2)
RemoveItem
exports['qs-core']:RemoveItem(source, item, count?, slot?)Parameters: count — defaults to 1; slot — take only from that slot.
Returns: true, or false if the player does not have enough.
Example: exports['qs-core']:RemoveItem(source, 'lockpick', 1)
HasItem · GetItemCount · CanCarryItem
exports['qs-core']:HasItem(source, item, count?)
exports['qs-core']:GetItemCount(source, item)
exports['qs-core']:CanCarryItem(source, item, count?)Parameters: count — defaults to 1.
Returns: HasItem and CanCarryItem return booleans (CanCarryItem checks weight and free space without changing anything); GetItemCount returns the total across all slots.
Example: if exports['qs-core']:CanCarryItem(source, 'stone', 3) then exports['qs-core']:AddItem(source, 'stone', 3) end
GetSlotView · GetItemBySlot
exports['qs-core']:GetSlotView(source)
exports['qs-core']:GetItemBySlot(source, slot)Parameters: slot — slot number.
Returns: GetSlotView returns every slot, each false (empty) or { slot, name, label, count, weight, useable, description, image, max, info } with qs-coreinventory. GetItemBySlot returns one of those entries or nil.
Example: local item = exports['qs-core']:GetItemBySlot(source, 1)
SetItemInfo
exports['qs-core']:SetItemInfo(source, slot, info)Parameters: info — the new metadata table for the item in that slot (replaces the old one).
Returns: true or false.
Example: exports['qs-core']:SetItemInfo(source, slot, { serial = 'AB1234' })
RegisterUsableItem
exports['qs-core']:RegisterUsableItem(item, handler)Parameters: handler — with qs-coreinventory, function(source, slot, info). The item must be registered with useable = true. The inventory does not remove the item; do it in the handler if it is consumable. One handler per item: the last registration wins.
Returns: true. Calls made before the inventory has started are queued and applied when it starts.
Example: exports['qs-core']:RegisterUsableItem('pizza', function(source, slot) exports['qs-core']:RemoveItem(source, 'pizza', 1, slot) end)
RegisterStash
exports['qs-core']:RegisterStash(id, label?, slots?, maxWeight?, columns?)Parameters: id — unique stash id. qs-coreinventory defaults: label Stash, 50 slots, 100000 g, 5 columns. Contents are saved in stash_inventories.
Returns: true or false. Players open it through a client stash zone (RegisterStashZone) or qs-coreinventory's OpenStash.
Example: exports['qs-core']:RegisterStash('mechanic_locker', 'Mechanic Locker', 40, 150000, 5)
SetBusy
exports['qs-core']:SetBusy(source, ms)Parameters: ms — milliseconds during which the player cannot use items.
Returns: nothing. Only has an effect with qs-coreinventory.
Example: exports['qs-core']:SetBusy(source, 3000)
GetInventory · SetInventory
exports['qs-core']:GetInventory(source)
exports['qs-core']:SetInventory(source, list)Parameters: list — the raw slot list stored in players.inventory, each entry { name, count, info } or false.
Returns: the list / true. Prefer AddItem and RemoveItem, which also refresh the player's inventory screen.
Example: exports['qs-core']:SetInventory(source, {})
Vehicles#
Owned vehicles live in the vehicles table: citizenid, license, plate, model, garage, state (1 stored, 0 out), fuel, engine, body and props. These exports are what qs-garage and qs-vehicleshop use.
GetCitizenVehicles
exports['qs-core']:GetCitizenVehicles(citizenid)Parameters: citizenid — character id.
Returns: every vehicle row owned by that character, with props already decoded. GetOwnedVehicles(citizenid) is the same function under its older name.
Example: local cars = exports['qs-core']:GetCitizenVehicles(player.citizenid)
GetGarageVehicles
exports['qs-core']:GetGarageVehicles(citizenid, garage)Parameters: garage — a garage id, such as legion_square.
Returns: the character's rows whose garage equals that id.
Example: local cars = exports['qs-core']:GetGarageVehicles(cid, 'pillbox_hill_garage')
GetVehicleByPlate · PlateExists
exports['qs-core']:GetVehicleByPlate(plate)
exports['qs-core']:PlateExists(plate)Parameters: plate — plate text without trailing spaces.
Returns: the row or nil; true/false.
Example: local row = exports['qs-core']:GetVehicleByPlate('QS4F2K9')
CreateOwnedVehicle
exports['qs-core']:CreateOwnedVehicle(data)Parameters: data — { citizenid, license, plate, model, garage, state, fuel, engine, body, props }. Defaults: garage legion, state 1, fuel 100, engine and body 1000.0, props {}. A garage id that is not configured in qs-garage makes the car appear in every garage until it is stored once.
Returns: the new row id.
Example: exports['qs-core']:CreateOwnedVehicle({ citizenid = player.citizenid, license = player.PlayerData.license, plate = 'QS12345', model = 'sultan' })
UpdateOwnedVehicle · SetVehicleState
exports['qs-core']:UpdateOwnedVehicle(plate, data)
exports['qs-core']:SetVehicleState(plate, state, garage?)Parameters: data — { garage, state, fuel, engine, body, props }. UpdateOwnedVehicle writes all six columns, so read the row first and pass every field. SetVehicleState changes only state (and garage when given).
Returns: nothing.
Example: exports['qs-core']:SetVehicleState('QS12345', 1, 'legion_square')
SpawnVehicle
exports['qs-core']:SpawnVehicle(source, model, coords?, warp?)Parameters: model — name or hash; coords — vec4 or { x, y, z, w }, defaults to the player's position; warp — put the player in the driver seat.
Returns: the vehicle's network id, or nil if it could not be created. It does not give keys — see qs-corevehiclekeys below.
Example: local netId = exports['qs-core']:SpawnVehicle(source, 'adder', nil, true)
GetPlayerVehiclesQBShape
exports['qs-core']:GetPlayerVehiclesQBShape(citizenid)Parameters: citizenid — character id.
Returns: the character's vehicles shaped like QBCore's player_vehicles rows: citizenid, license, vehicle, hash, mods, plate, garage, fuel, engine, body, state.
Example: local vehicles = exports['qs-core']:GetPlayerVehiclesQBShape(cid)
Permissions and groups#
HasPermission
exports['qs-core']:HasPermission(source, permission)Parameters: permission — a name such as admin, or a list of names (any match passes).
Returns: true for the console, for user, or when the player has the ACE <permission>, qbcore.<permission> or group.<permission>. admin, god and mod also pass with group.admin or command.
Example: if exports['qs-core']:HasPermission(source, { 'admin', 'mod' }) then ... end
AddPermission · RemovePermission · GetPermission
exports['qs-core']:AddPermission(source, permission)
exports['qs-core']:RemovePermission(source, permission)
exports['qs-core']:GetPermission(source)Parameters: permission — a name such as mod.
Returns: AddPermission / RemovePermission return true/false and add or remove the ACEs qbcore.<permission> and group.<permission> on the player's license until the next restart. GetPermission returns { god = true, admin = true, mod = true } with only the ones the player has. For a group that survives restarts, use /setgroup.
Example: exports['qs-core']:AddPermission(source, 'mod')
Setting a saved group from a script
ExecuteCommand(('setgroup %d %s'):format(targetId, 'admin'))Parameters: there is no export for groups; run the command, which a resource executes with console rights. This is what the admin menu does.
Returns: nothing. The group is stored in player_groups, applied at once and re-applied every time the player connects.
Example: ExecuteCommand(('removegroup %d'):format(targetId))
Bans#
IsPlayerBanned
exports['qs-core']:IsPlayerBanned(licenseOrSource)Parameters: a server id or a full license:… identifier.
Returns: banned, reason, expiresUnix. Every active ban of the license counts, and a permanent ban wins over a temporary one; expiresUnix is the end as a Unix timestamp, or nil for a permanent ban. false when there is no active ban, and always false when Config.EnableBans = false.
Example: local banned, reason, expires = exports['qs-core']:IsPlayerBanned(source)
AddBan
exports['qs-core']:AddBan(source, minutes, reason, adminName)Parameters: minutes — 0 or nil for a permanent ban; adminName — stored as banned_by.
Returns: true, or false if the player has no license. The player is kicked immediately.
Example: exports['qs-core']:AddBan(source, 1440, 'Exploiting', 'Anticheat')
RemoveBan · ExploitBan
exports['qs-core']:RemoveBan(license)
exports['qs-core']:ExploitBan(source, origin?)Parameters: license — full license:… identifier; origin — text stored as the reason.
Returns: RemoveBan deletes every ban of that identifier and returns true. ExploitBan bans permanently with banned_by = 'Anti Cheat'.
Example: exports['qs-core']:ExploitBan(source, 'triggered protected event')
Callbacks and notifications#
RegisterCallback
exports['qs-core']:RegisterCallback(name, function(source, ...) return ... end)Parameters: name — callback name; the handler receives the player and the client's arguments, and whatever it returns is sent back.
Returns: nothing. The client calls it with TriggerCallback.
Example: exports['qs-core']:RegisterCallback('myshop:getCash', function(source) return exports['qs-core']:GetMoney(source, 'cash') end)
RegisterQBCallback
exports['qs-core']:RegisterQBCallback(name, function(source, cb, ...) cb(...) end)Parameters: QBCore-style handler that answers through cb.
Returns: nothing. Clients call it with TriggerQBCallback or QBCore.Functions.TriggerCallback.
Example: exports['qs-core']:RegisterQBCallback('myshop:getBank', function(source, cb) cb(exports['qs-core']:GetMoney(source, 'bank')) end)
Notify a player from the server
TriggerClientEvent('qs:client:notify', source, message, type?, duration?, title?)Parameters: type — success, error, info (default) or primary; duration — milliseconds, default 4000; title — optional, defaults to a localized title for the type. Use -1 as source to notify everyone. There is no server export: this event is the server API.
Returns: nothing.
Example: TriggerClientEvent('qs:client:notify', source, 'Order delivered', 'success', 5000)
Utilities#
GetCoreObject
exports['qs-core']:GetCoreObject()Parameters: none.
Returns: the core table: Players, Config, Jobs, Gangs, Utils and the core functions. Read config values from it; for players, use GetPlayer — player objects taken from this table in another resource have no methods.
Example: local QS = exports['qs-core']:GetCoreObject(); print(QS.Config.MaxCharacters)
RateLimit
exports['qs-core']:RateLimit(key, max, windowMs)Parameters: key — bucket name; max — calls allowed per window; windowMs — window length. Buckets are shared by every resource, so prefix keys with your resource name.
Returns: true while under the limit, false when over it.
Example: if not exports['qs-core']:RateLimit(('myshop:buy:%d'):format(source), 1, 1000) then return end
RegisterFrameworkCommand · RefreshCommands
exports['qs-core']:RegisterFrameworkCommand(name, help, arguments, argsrequired, callback, permission?)
exports['qs-core']:RefreshCommands(source)Parameters: QBCore-style command (this is what QBCore.Commands.Add calls): arguments — { { name, help } } for the chat suggestion; argsrequired — refuse with fewer arguments; callback(source, args, raw); permission — defaults to user, checked with HasPermission.
Returns: nothing. RefreshCommands re-sends every chat suggestion to a player (done automatically when a character loads).
Example: exports['qs-core']:RegisterFrameworkCommand('healme', 'Heal yourself', {}, false, function(source) TriggerClientEvent('qs:client:revive', source) end, 'admin')
GetColors
exports['qs-core']:GetColors()Parameters: none.
Returns: on the server, the default palette Config.Theme (primary, accent, text, panel, health…).
Example: local theme = exports['qs-core']:GetColors()
qs-core client exports#
Call them from client scripts with exports['qs-core']:Name(...). The shared exports — GetCoreObject, RateLimit, GetItem, GetItems, RegisterItem, GetGang, GetGangs and the rest — exist on the client too, each side with its own copy of the data.
GetPlayerData
exports['qs-core']:GetPlayerData()Parameters: none.
Returns: the local character, or nil before a character is loaded: { source, citizenid, license, name, charinfo, money, job, metadata, gang, onduty, position, skin, is_dead, isNew }. Money, job, gang, duty and metadata stay up to date.
Example: local data = exports['qs-core']:GetPlayerData(); print(data.job.label)
Notify
exports['qs-core']:Notify(message, type?, duration?, title?)Parameters: type — success, error, info (default) or primary; duration — milliseconds, default 4000.
Returns: nothing.
Example: exports['qs-core']:Notify('Vehicle repaired', 'success')
Progress
exports['qs-core']:Progress({ duration = 3000, label = '', disableMovement = false, canCancel = false })Parameters: duration — milliseconds; label — text on the bar; disableMovement — block walking, sprinting and jumping; canCancel — allow X to cancel. The call waits until the bar ends.
Returns: true when completed, false when cancelled or when another bar is already running.
Example: if exports['qs-core']:Progress({ duration = 5000, label = 'Repairing', canCancel = true }) then ... end
CancelProgress · IsBusy
exports['qs-core']:CancelProgress()
exports['qs-core']:IsBusy()Parameters: none.
Returns: IsBusy returns true while a progress bar is running.
Example: if exports['qs-core']:IsBusy() then return end
Lockpick
exports['qs-core']:Lockpick(rounds?)Parameters: rounds — 1 to 6, default 3. The player sets pins with SPACE and gives up with ESC or BACKSPACE; 30 seconds of inactivity counts as a failure. The call waits until it ends.
Returns: true on success, false otherwise.
Example: if exports['qs-core']:Lockpick(4) then ... end
HasItem · GetItemCount
exports['qs-core']:HasItem(item, count?)
exports['qs-core']:GetItemCount(item)Parameters: count — defaults to 1.
Returns: boolean / number, read from the active inventory's client copy.
Example: if exports['qs-core']:HasItem('lockpick') then ... end
RegisterStashZone · RemoveStashZone
exports['qs-core']:RegisterStashZone(id, coords, opts?)
exports['qs-core']:RemoveStashZone(id)Parameters: id — a stash registered on the server; coords — vector3; opts.radius — default 2.0 m. With qs-coreinventory, opening the inventory inside the zone shows the stash as the second panel.
Returns: true or false.
Example: exports['qs-core']:RegisterStashZone('mechanic_locker', vector3(-347.2, -133.6, 39.0), { radius = 1.5 })
TriggerCallback · TriggerQBCallback
exports['qs-core']:TriggerCallback(name, function(...) end, ...)
exports['qs-core']:TriggerQBCallback(name, function(...) end, ...)Parameters: name — a callback registered with RegisterCallback / RegisterQBCallback; extra arguments are sent to the handler.
Returns: nothing; the function receives the server's answer.
Example: exports['qs-core']:TriggerCallback('myshop:getCash', function(cash) print(cash) end)
IsDead · SetDownAnimPaused
exports['qs-core']:IsDead()
exports['qs-core']:SetDownAnimPaused(state)Parameters: state — true stops the downed loop from replaying the lying animation while you play your own (the EMS stretcher uses it).
Returns: IsDead returns true while the player is downed.
Example: if exports['qs-core']:IsDead() then return end
IsNoclipActive · ToggleNoclip
exports['qs-core']:IsNoclipActive()
exports['qs-core']:ToggleNoclip(state?)Parameters: call ToggleNoclip() without arguments to toggle, or with true to turn it on. It does not check permissions — only call it for admins.
Returns: IsNoclipActive returns a boolean.
Example: if not exports['qs-core']:IsNoclipActive() then exports['qs-core']:ToggleNoclip() end
GetColors · SetClientColors · HasSavedColors
exports['qs-core']:GetColors()
exports['qs-core']:SetClientColors(palette)
exports['qs-core']:HasSavedColors()Parameters: palette — a table with the same keys as Config.Theme.
Returns: GetColors returns the player's saved palette or Config.Theme; SetClientColors applies a palette for this session only (not saved) and fires qs:client:colorsChanged; HasSavedColors tells whether the player chose their own colours.
Example: SendNUIMessage({ action = 'theme', data = exports['qs-core']:GetColors() })
Other resources' exports#
Exports from the other Quasar Framework resources that are worth calling from your own scripts.
qs-coreinventory (server)
exports['qs-coreinventory']:AddItem(source, item, count, slot?, info?)
exports['qs-coreinventory']:RemoveItem(source, item, count, slot?)
exports['qs-coreinventory']:GetItemCount(source, item)
exports['qs-coreinventory']:HasItem(source, item, count?)
exports['qs-coreinventory']:CanCarryItem(source, item, count?, info?)
exports['qs-coreinventory']:GetSlotView(source)
exports['qs-coreinventory']:GetItemBySlot(source, slot)
exports['qs-coreinventory']:SetItemInfo(source, slot, info)
exports['qs-coreinventory']:RegisterUsableItem(item, function(source, slot, info) end)
exports['qs-coreinventory']:RegisterStash(id, label?, slots?, maxWeight?, columns?)
exports['qs-coreinventory']:SetBusy(source, ms)
exports['qs-coreinventory']:IsBusy(source)The same operations as the qs-core item exports, but tied to this inventory. Prefer the qs-core versions, which keep working if you switch to qs-inventory; IsBusy exists only here.
qs-coreinventory (client)
exports['qs-coreinventory']:OpenStash(id, opts?)
exports['qs-coreinventory']:RegisterStashZone(id, coords, opts?)
exports['qs-coreinventory']:RemoveStashZone(id)
exports['qs-coreinventory']:HasItem(item, count?)
exports['qs-coreinventory']:GetItemCount(item)OpenStash opens the inventory with stash id as the second panel, from anywhere (no zone needed). It returns false if the inventory is already open. opts = { label, slots, maxWeight, columns } is only used for a stash that was not registered on the server.
qs-corevehiclekeys (client)
exports['qs-corevehiclekeys']:GiveKeys(plate)
exports['qs-corevehiclekeys']:RemoveKeys(plate)
exports['qs-corevehiclekeys']:HasKeys(plate)
exports['qs-corevehiclekeys']:GetKeys()Keys are kept per session on the client. Give keys after spawning a vehicle from your own script, or the driver cannot start it. From the server, send TriggerClientEvent('vehiclekeys:client:SetOwner', source, plate) — the same event QBCore scripts use. Example: exports['qs-corevehiclekeys']:GiveKeys(GetVehicleNumberPlateText(vehicle))
qs-clothing (client)
exports['qs-clothing']:ApplyAppearance(skin, sex?)
exports['qs-clothing']:OpenCreator(sex, function(skin) end)
exports['qs-clothing']:IsCreatorOpen()ApplyAppearance sets the freemode model and every clothing, prop and tattoo from a skin table (an empty skin applies the default look for sex). To change a player's saved appearance from the server, use qs-core SetSkin. To open the editor, trigger qs-clothing:client:open.
qs-police (server)
exports['qs-police']:Alert(coords, label?)Sends a dispatch alert — notification and flashing blip for 60 seconds — to every player with the police job. coords must be a plain table { x, y, z }; a vector3 is ignored, so convert it first. Without a label the alert reads Shots fired. Example: local c = GetEntityCoords(GetPlayerPed(source)); exports['qs-police']:Alert({ x = c.x, y = c.y, z = c.z }, 'Store robbery')
qs-banking
qs-banking has no exports. Bank balances are the qs-core bank account, so a script that pays or charges a bank account uses exports['qs-core']:AddMoney(source, 'bank', amount, reason) and RemoveMoney. Account numbers and the transaction history are kept in bank_accounts and bank_transactions.
Bridge exports (ESX, QBCore and friends)
exports['es_extended']:getSharedObject() -- shared
exports['qb-core']:GetCoreObject() -- shared
exports['LegacyFuel']:GetFuel(vehicle) -- client
exports['LegacyFuel']:SetFuel(vehicle, fuel) -- client, 0-100
exports['progressbar']:Progress(data, function(cancelled) end) -- client
exports['qb-management']:AddMoney(job, amount) -- server, also GetAccount, RemoveMoney, GetGangAccount, AddGangMoney, RemoveGangMoney
exports['esx_society']:addMoney(account, amount) -- server, also getSociety, getSocietyMoney, removeMoney
exports['qb-vehiclekeys']:GiveKeys(source, plate) -- server; client: GiveKeys, RemoveKeys, HasKeys, GetKeysThese answer under the names ESX and QBCore scripts already call, and forward to Quasar Framework. The full list is in ESX & QBCore Compatibility.
Events#
Framework events (server)#
Fired by qs-core with TriggerEvent, so listen with AddEventHandler in a server script.
Event | Side | Arguments | When it fires |
|---|---|---|---|
| server |
| A character finished loading. The recommended hook for other resources. |
| server |
| Just before |
| server |
| After |
| server |
| After every save: autosave, disconnect, logout and qs-core stop. |
| server |
| Money added or removed ( |
| server |
| Job or duty changed. |
| server |
| Gang changed. |
| server |
| A useable item that is not a weapon was used, from any inventory. |
| server | — | Once, 500 ms after qs-core starts. The QBCore bridge syncs its shared items and jobs on it. |
AddEventHandler('qs:server:characterLoaded', function(source, data)
if data.isNew then
exports['qs-core']:AddMoney(source, 'bank', 1000, 'welcome bonus')
end
end)
AddEventHandler('qs:server:usedItem', function(source, item, slot, info)
if item ~= 'pizza' then return end
exports['qs-core']:RemoveItem(source, 'pizza', 1, slot)
end)Framework events (client)#
Event | Side | Arguments | When it fires |
|---|---|---|---|
| client (local) |
| The character is placed in the world, just before the screen fades in. |
| client (local) | — | After logout. |
| client (local) |
| Job or duty changed. |
| client (local) |
| Gang changed. |
| client (local) |
| Duty changed. |
| client (local) | — | The player goes down. |
| client (local) | — | The downed state ends (revive or hospital respawn). |
| client (local) | — | A downed player pressed |
| client (local) |
| The player's colours changed: re-send them to your UI. |
| server → client |
| Shows a notification. Server: |
| server → client | — | Revives the player. Prefer |
| server → client | — | Puts the player in the downed state. Prefer |
| server → client |
| A metadata value changed. |
| server → client |
| A balance changed. |
| server → client |
| A balance was set. |
| server → client |
| An extra account (not |
AddEventHandler('qs:client:onPlayerLoaded', function(data)
print(('Welcome back, %s %s'):format(data.charinfo.firstname, data.charinfo.lastname))
end)
AddEventHandler('qs:client:onJobUpdate', function(job)
if job.name == 'police' then
-- create your police blips here
end
end)Resource events#
Events and state bags from the other Quasar Framework resources that integrators need.
Event | Side | Arguments | Use |
|---|---|---|---|
| server (local) |
| Fired by |
| server → client |
| Full inventory snapshot after every change. |
| server → client |
| A weapon item was used. |
| server → client |
| Item added or removed ( |
| client (local) |
|
|
| client (local) |
| Hides or shows the chat. |
| client |
| Standard chat API, handled by |
| client |
| Adds a command hint ( |
| server → client |
| Chat line with a style: |
| client (local) | — | Closes the loading screen. |
| client (local) | — | The loading screen has closed. |
| client (local) | — | The intro is done or skipped; character selection starts. |
| server → client |
| Applies an appearance (sent by |
| client |
| Opens the appearance editor; |
| client (local) |
| The character creator closed. |
| server → client |
| Gives the player keys (same name as qb-vehiclekeys). Also |
| server → client |
| Dispatch alert on a police client. Use the |
| server → client |
| Plays the eat or drink animation only (no hunger or thirst change). |
State bag | Set by | Value |
|---|---|---|
| qs-core | Loaded character id. |
| qs-core | Current job table. |
| qs-core | Player name. |
| qs-core |
|
| qs-police |
|
| LegacyFuel bridge | Fuel level 0–100. |
ESX and QBCore events#
The bridges translate qs-core events into the ones ESX and QBCore scripts listen for, so those scripts run unmodified. The most used:
Event | Side | Arguments | When it fires |
|---|---|---|---|
| server / client | server | A character loaded. |
| client | — | After logout. |
| server / client | server | Job or duty changed. |
| client |
| A balance changed. |
| server |
| A player with a character disconnected. |
| client |
| The player died / spawned again. |
| server |
| A character loaded. |
| client | — | A character loaded. |
| server |
| A player disconnected. |
| server / client |
| Job changed. |
| server |
| Money changed. |
| client |
| Gang changed. |
| client |
| Duty changed. |
| client |
| Player data refreshed. |
The complete list, with what is and is not emitted, is in ESX & QBCore Compatibility.
Calling qs-core from another resource? Prefer the explicit exports —
AddMoney,SetJob,SetMetadata,AddItem— over methods on a player table. Each export works on the live player inside qs-core, so the result is always current and costs a single call.
exports['qs-core']:GetPlayer(source)is fine too: it returnssource,citizenid, bound copies of every player method (player:addMoney(...)andplayer.addMoney(...)both work and act on the live player) and a copy ofPlayerDatataken at that moment. That copy does not update afterwards — callGetPlayeragain, or use a getter such asplayer:getMoney('cash'), when you need fresh values. Player objects reached throughGetCoreObject()in another resource have no methods at all, so always go throughGetPlayer.



