Browse docs
Server Exports
Player Interaction Whitelist
Shared player interactions are job-whitelisted. Register the jobs owned by your resource before using any player-interaction client or server export. Registration authorizes existing jobs only; it does not create framework jobs or Sky Jobs groups.
sky_policejob automatically registers its configured Police jobs with the police policy from Config.JobPlayerInteractions. sky_crimesystem does the same for its Crime jobs and the crime policy. Both refresh their registration after Job Configurator updates.
registerInteractionJobs(groupKey, jobs, permissions?)
groupKey(string) - unique key owned by the calling resource.jobs(string[] | table[]) - job names or job definitions containing aname.permissions(table?) - required for custom groups. It may be omitted whengroupKeyalready has a policy inConfig.JobPlayerInteractions.groups.- Returns
boolean, string?.
Supported permission fields:
| Field | Purpose |
|---|---|
requireOnDuty | Requires the current player to be on duty for every enabled action. |
cuffs | Apply and remove handcuffs. |
zipties | Apply, remove, and cut zipties. |
legRestraints | Apply and remove leg restraints. |
escort | Start and stop escorting a restrained player. |
vehicle | Place escorted players in vehicles or remove restrained players from vehicles. |
headBag | Apply and remove head bags. |
search | Open and transfer items through player search. |
local registered, reason = exports["sky_jobs_base"]:registerInteractionJobs(
"security",
{
"security",
{ name = "security_night" }
},
{
requireOnDuty = true,
cuffs = true,
zipties = false,
legRestraints = true,
escort = true,
vehicle = true,
headBag = false,
search = true
}
)
if not registered then
print(("Unable to register security interactions: %s"):format(reason))
end
Registering jobs only grants the selected interaction capabilities to players whose current job matches the registration. It does not execute an action, bypass item requirements, or trust client input.
unregisterInteractionJobs(groupKey)
Removes a group registered by the calling resource.
exports["sky_jobs_base"]:unregisterInteractionJobs("security")
The export returns false, "not_owner" if another resource owns the group.
hasInteractionAccess(sourceId, permission)
Checks the same server-authoritative job and duty policy used by the interaction actions.
local allowed, reason = exports["sky_jobs_base"]:hasInteractionAccess(source, "search")
Possible failure reasons include not_authorized, not_on_duty, and invalid_permission.
Player Interaction Actions
Every action export below validates the acting player's current whitelist access. Target existence, distance, vehicle state, restraint state, items, and inventory operations are also validated where applicable.
Handcuffs and zipties
| Export | Returns | Purpose |
|---|---|---|
cuffPlayer(sourceId, targetId, cuffType, options?) | boolean, string? | Applies cuffs or zipties. |
uncuffPlayer(sourceId, targetId, options?) | boolean, string? | Removes the target's current cuffs or zipties. |
cutZipties(sourceId, targetId, options?) | boolean, string? | Cuts the target's zipties with the configured cutter. |
isPlayerCuffed(targetId) | boolean | Reads the shared cuff state. |
getCuffConfig() | table | Returns a read-only snapshot of Config.PoliceCuffs. |
Trusted options for cuffPlayer are ignoreItemCheck, allowSelf, and forceNormal. uncuffPlayer and cutZipties accept allowSelf and forceNormal. Whitelist and distance validation cannot be disabled.
local success, reason = exports["sky_jobs_base"]:cuffPlayer(
source,
targetId,
"cuffs"
)
Escape opportunities are not exposed as a forceable integration API. The server rolls and validates them from Config.PoliceCuffs.escape, including timing, expected keys, round progression, cooldowns, and final restraint removal.
Leg restraints
| Export | Returns | Purpose |
|---|---|---|
applyLegRestraints(sourceId, targetId) | boolean, string? | Applies leg restraints after all access and target checks. |
removeLegRestraints(sourceId, targetId) | boolean, string? | Removes the target's leg restraints. |
isPlayerLegRestrained(targetId) | boolean | Reads the shared leg-restraint state. |
getLegRestraintsTargetState(targetId) | table | Returns the target's validated cuff and leg-restraint state. |
getLegRestraintsConfig() | table | Returns a read-only snapshot of Config.LegRestraints. |
Escort and vehicles
| Export | Returns | Purpose |
|---|---|---|
escortToggle(sourceId, targetId) | boolean, string? | Starts or stops escorting a cuffed target. |
escortPutInVehicle(sourceId, targetId, netId, seat) | boolean, string? | Places an escorted target into a nearby networked vehicle. |
escortTakeOutVehicle(sourceId, targetId) | boolean, string? | Removes a nearby cuffed target from a vehicle. |
escortToggle requires escort; the two vehicle exports require vehicle.
Head bag
| Export | Returns | Purpose |
|---|---|---|
useHeadBag(sourceId, targetId, action) | boolean, string? | Uses apply, remove, or toggle. |
applyHeadBag(sourceId, targetId) | boolean, string? | Applies a head bag. |
removeHeadBag(sourceId, targetId) | boolean, string? | Removes a head bag. |
isPlayerHeadBagged(targetId) | boolean | Reads the shared head-bag state. |
getHeadBagTargetState(targetId) | table | Returns success, hooded, and restrained. |
getHeadBagConfig() | table | Returns a read-only snapshot of Config.HeadBag. |
Player search
| Export | Returns | Purpose |
|---|---|---|
getSearchTargetInventory(sourceId, targetId) | table | Returns the validated target inventory and weapons. |
searchTransfer(sourceId, targetId, transferType, name, amount, metadata?) | table | Transfers a validated item from the target to the acting player. |
searchTransfer currently accepts only transferType = "storage". The target must remain nearby and restrained for the initial read and every transfer.
Dispatch
createDispatch(title, message, coords, jobs, meta)
- Purpose: Creates a dispatch entry and broadcasts it to all on-duty members of the target jobs.
- Arguments:
title(string) — dispatch title. Required.message(string) — dispatch description.coords(vector3 | table) — location{x, y, z}. Required.jobs(string | string[]) — job name or array of job names.meta(table?) — optional metadata:source(number?) — source player ID.sourceId(string?) — additional source identifier.category(string?) — dispatch category.
- Returns:
table | nil— the dispatch entry on success,nilon validation failure.
local dispatch = exports["sky_jobs_base"]:createDispatch(
"Bank Robbery",
"Silent alarm triggered at Pacific Standard",
vector3(235.0, 216.0, 106.0),
{ "police" },
{ category = "robbery", source = source }
)
if dispatch then
print("Dispatch created:", dispatch.id)
end
Dispatch Entry Structure
| Field | Type | Description |
|---|---|---|
id | string | Unique dispatch identifier |
title | string | Dispatch title |
message | string | Dispatch description |
coords | table | Location {x, y, z} |
jobs | table | Target job names |
status | string | "active" on creation |
createdAt | number | Timestamp |
HasDispatch(sourceKey, sourceId)
- Purpose: Checks if an active dispatch exists for the given source.
- Arguments:
sourceKey(string) — source identifier key.sourceId(string) — source ID value.
- Returns:
boolean—trueif a non-done dispatch exists.
local exists = exports["sky_jobs_base"]:HasDispatch("player", "license:abc123")
if exists then
print("Active dispatch already exists")
end
Gallery
takeServerImage(rawDataUrl, cameraMetadata)
- Purpose: Uploads a base64 image to the configured image provider.
- Arguments:
rawDataUrl(string) — base64-encoded image data URL.cameraMetadata(table) — metadata about the camera/capture context.
- Returns:
boolean—trueon success,falseon failure.table | string— on success:{ data = { url, id, image_id } }. On failure: error message.
local ok, result = exports["sky_jobs_base"]:takeServerImage(imageData, {
type = "bodycam",
timestamp = os.time()
})
if ok then
print("Uploaded:", result.data.url)
end
Creator
openCreatorByJob(source, jobKey)
- Purpose: Opens the registered station creator for a player by job key after validating the creator permission.
- Arguments:
source(number) - server ID of the player who should receive the creator UI.jobKey(string) - registered job key.
- Returns:
boolean-trueon success.string?- failure reason such as"creator_not_found"or"no_permission".
local ok, reason = exports["sky_jobs_base"]:openCreatorByJob(source, "mechanic")
openCreatorByJobWithoutPermission(source, jobKey)
- Purpose: Opens the registered station creator for a player by job key without running the creator permission check. Use only from trusted server-side integrations that already authorized the player.
- Arguments:
source(number) - server ID of the player who should receive the creator UI.jobKey(string) - registered job key.
- Returns:
boolean-trueon success.string?- failure reason such as"creator_not_found"or"invalid_source".
local ok, reason = exports["sky_jobs_base"]:openCreatorByJobWithoutPermission(source, "mechanic")
Storage
GetStorageItemCount(stationId, itemName)
- Purpose: Counts how many items with the given name are currently available in one station storage. Metadata does not split the result; matching stacks are added together.
- Arguments:
stationId(string | number) - target station ID.itemName(string) - item name to count.
- Returns:
number- total available amount, or0when the station or item is missing.
local wheels = exports["sky_jobs_base"]:GetStorageItemCount("station_1", "wheels")
if wheels > 0 then
print(("Storage has %d wheel kits"):format(wheels))
end
RemoveStorageItem(stationId, itemName, amount)
- Purpose: Removes a trusted amount of an item directly from station storage. This is intended for server-side job resources that already validated the player, station, and workflow.
- Arguments:
stationId(string | number) - target station ID.itemName(string) - item name to remove.amount(number) - positive item count.
- Returns:
boolean-truewhen the requested amount was removed.
local removed = exports["sky_jobs_base"]:RemoveStorageItem("station_1", "wheels", 1)
if not removed then
print("Not enough wheel kits in storage")
end
AddStorageItem(stationId, jobName, grade, name, amount, metadata)
- Purpose: Adds one item stack directly to a station storage. The export validates basic input and storage capacity before inserting.
- Arguments:
stationId(string | number) - target station ID.jobName(string) - job name used for storage restrictions.grade(number?) - job grade context.name(string) - item name.amount(number) - positive item count.metadata(table?) - optional item metadata.
- Returns:
boolean-truewhen the item was added.
local ok = exports["sky_jobs_base"]:AddStorageItem(
"station_1",
"mechanic",
2,
"repair_crate",
1,
{ quality = 100 }
)
AddStorageItems(stationId, jobName, grade, items)
- Purpose: Adds multiple item stacks directly to a station storage in one call. The export validates all items and checks total capacity before inserting.
- Arguments:
stationId(string | number) - target station ID.jobName(string) - job name used for storage restrictions.grade(number?) - job grade context.items(table[]) - array of items withname,amountorquantity, and optionalmetadata.
- Returns:
boolean-truewhen all valid items were added.
local ok = exports["sky_jobs_base"]:AddStorageItems("station_1", "mechanic", 2, {
{ name = "repair_crate", amount = 1, metadata = { quality = 100 } },
{ name = "cleaning_kit", quantity = 2 }
})
External Garage Integration
These exports allow third-party garage systems to register and unregister vehicles so the trunk inventory and prop system works for externally-spawned job vehicles.
registerExternalVehicle(plate, jobName, model, netId, ownerSource, trunkCapacity)
- Purpose: Registers an externally-spawned vehicle in the sky_jobs_base vehicle tracking system. This enables trunk inventory, prop placement, and all trunk-related server callbacks for the vehicle.
- Arguments:
plate(string) — the vehicle license plate. Required.jobName(string) — the job this vehicle belongs to (e.g."ambulance","police"). Required.model(string?) — vehicle model name (e.g."ambulance"). Defaults to"unknown".netId(number?) — network ID of the spawned vehicle entity.ownerSource(number?) — server ID of the player who spawned the vehicle.trunkCapacity(number?) — trunk weight capacity. Defaults to50.
- Returns:
boolean—trueon success,falseif plate or jobName is missing.
-- After spawning the vehicle on the server:
local plate = GetVehicleNumberPlateText(vehicle)
local netId = NetworkGetNetworkIdFromEntity(vehicle)
exports["sky_jobs_base"]:registerExternalVehicle(
plate,
"ambulance",
"ambulance",
netId,
source,
80
)
unregisterExternalVehicle(plate)
- Purpose: Removes an externally-registered vehicle from the tracking system. Call this when the vehicle is despawned or parked by the external garage.
- Arguments:
plate(string) — the vehicle license plate. Required.
- Returns:
boolean—trueon success,falseif plate is invalid.
exports["sky_jobs_base"]:unregisterExternalVehicle(plate)
Full Usage Example
-- When spawning the vehicle
RegisterNetEvent("mygarage:vehicleSpawned", function(plate, model, netId)
exports["sky_jobs_base"]:registerExternalVehicle(
plate, "ambulance", model, netId, source, 80
)
end)
-- When despawning / parking the vehicle
RegisterNetEvent("mygarage:vehicleDespawned", function(plate)
exports["sky_jobs_base"]:unregisterExternalVehicle(plate)
end)
-- After the vehicle entity exists on the client
local vehicle = NetToVeh(netId)
exports["sky_jobs_base"]:registerExternalTrunkVehicle(vehicle)
-- When despawning
exports["sky_jobs_base"]:unregisterExternalTrunkVehicle(vehicle)
Salary
These exports allow external resources to temporarily pause and resume salary payouts for a player.
pausePlayerSalary(playerId)
- Purpose: Pauses salary payouts for the given player. While paused, the player will not receive any automatic salary payments.
- Arguments:
playerId(number) — the server ID of the player. Required.
- Returns:
boolean—trueon success,falseif the player ID is invalid.
exports["sky_jobs_base"]:pausePlayerSalary(playerId)
resumePlayerSalary(playerId)
- Purpose: Resumes salary payouts for the given player after they were paused.
- Arguments:
playerId(number) — the server ID of the player. Required.
- Returns:
boolean—trueon success,falseif the player ID is invalid.
exports["sky_jobs_base"]:resumePlayerSalary(playerId)
isPlayerSalaryPaused(playerId)
- Purpose: Checks whether salary payouts are currently paused for the given player.
- Arguments:
playerId(number) — the server ID of the player.
- Returns:
boolean—trueif paused,falseotherwise.
local paused = exports["sky_jobs_base"]:isPlayerSalaryPaused(playerId)
getGradeSalary(jobName, grade)
- Purpose: Reads the salary configuration of a job grade as configured in the boss menu.
- Arguments:
jobName(string) — the job name. Required.grade(number) — the job grade. Required.
- Returns:
number— salary amount per interval (0if none configured).number— payout interval in minutes.
local amount, intervalMinutes = exports["sky_jobs_base"]:getGradeSalary("ambulance", 3)
print(("Grade 3 earns $%d every %d minutes"):format(amount, intervalMinutes))
Duty
These exports allow external resources (e.g. admin menus, multijob scripts) to read and change a player's duty state.
setPlayerDuty(playerId, onDuty)
- Purpose: Sets a player's duty state externally. Runs the full duty pipeline: on/off-duty job switch, duty event for all job scripts, and salary work-time session handling — exactly as if the player toggled duty themselves.
- Arguments:
playerId(number) — the server ID of the player. Required.onDuty(boolean) —trueto set on duty,falseto set off duty.
- Returns:
boolean—truewhen the resulting duty state matches the request,falsewhen the player is invalid or their job cannot go on duty.
-- Force a player off duty (e.g. from an admin menu)
local ok = exports["sky_jobs_base"]:setPlayerDuty(playerId, false)
if not ok then
print("Player is not on a duty-capable job")
end
isPlayerOnDuty(playerId)
- Purpose: Checks whether a player is currently on duty.
- Arguments:
playerId(number) — the server ID of the player.
- Returns:
boolean—trueif on duty.
local onDuty = exports["sky_jobs_base"]:isPlayerOnDuty(playerId)
getOnDutyPlayers(jobName)
- Purpose: Returns all currently on-duty players of a job.
- Arguments:
jobName(string) — the job name. Required.
- Returns:
number[]— array of server IDs.
local medics = exports["sky_jobs_base"]:getOnDutyPlayers("ambulance")
print(("%d medics on duty"):format(#medics))
Players & Members
These exports let external resources (admin menus, whitelist systems, other job scripts) manage job members without going through the boss menu.
getPlayerJobInfo(playerId)
- Purpose: Returns the cached job state of an online player in one call.
- Arguments:
playerId(number) — the server ID of the player. Required.
- Returns:
table | nil—{ job, grade, gradeLabel, onDuty }, ornilif the player is not loaded.
local info = exports["sky_jobs_base"]:getPlayerJobInfo(playerId)
if info then
print(("%s — grade %d (%s), on duty: %s"):format(info.job, info.grade, info.gradeLabel, tostring(info.onDuty)))
end
setJobMember(jobName, playerOrIdentifier, grade)
- Purpose: Hires a player into a job or changes the grade of an existing member. Works for online players (server ID) and offline players (identifier). Updates the framework job, the player cache, and notifies open boss menus.
- Arguments:
jobName(string) — the job name. Required.playerOrIdentifier(number | string) — server ID or framework identifier. Required.grade(number?) — target grade. Defaults to the job's lowest grade (hire).
- Returns:
boolean—trueon success.string?— error message on failure (e.g."Invalid grade").
-- Hire an online player at the default grade
local ok, err = exports["sky_jobs_base"]:setJobMember("ambulance", playerId)
-- Promote an offline player to grade 2
local ok, err = exports["sky_jobs_base"]:setJobMember("ambulance", "license:abc123", 2)
removeJobMember(jobName, playerOrIdentifier)
- Purpose: Fires a member from a job. Sets the player to
unemployed, ends their duty, and removes their member stats. Works for online and offline players. - Arguments:
jobName(string) — the job name. Required.playerOrIdentifier(number | string) — server ID or framework identifier. Required.
- Returns:
boolean—trueon success.string?— error message on failure.
local ok, err = exports["sky_jobs_base"]:removeJobMember("ambulance", "license:abc123")
getJobMembers(jobName)
- Purpose: Returns all members of a job (online and offline) with their boss-menu stats.
- Arguments:
jobName(string) — the job name. Required.
- Returns:
table[]— array of member entries.
Member Entry Structure
| Field | Type | Description |
|---|---|---|
identifier | string | Framework identifier |
license | string | Stored license identifier |
name | string | Character name |
grade | number | Job grade |
grade_label | string | Grade label |
onduty | boolean | Current duty state |
last_online_timestamp | number | Unix timestamp of last online |
total_work_time_seconds | number | Accumulated on-duty time |
actions_done | number | Job action counter |
image_url | string? | Member image if set |
local members = exports["sky_jobs_base"]:getJobMembers("ambulance")
for _, member in ipairs(members) do
print(member.name, member.grade_label, member.onduty)
end
Society Money
Direct access to the job's shared account (the same account used by the boss menu finance tab).
getJobMoney(jobName)
- Purpose: Returns the current shared account balance of a job.
- Arguments:
jobName(string) — the job name. Required.
- Returns:
number— balance (0on invalid job).
local balance = exports["sky_jobs_base"]:getJobMoney("ambulance")
addJobMoney(jobName, amount)
- Purpose: Adds money to the job's shared account.
- Arguments:
jobName(string) — the job name. Required.amount(number) — positive amount. Required.
- Returns:
boolean—trueon success.
exports["sky_jobs_base"]:addJobMoney("ambulance", 5000)
removeJobMoney(jobName, amount)
- Purpose: Removes money from the job's shared account.
- Arguments:
jobName(string) — the job name. Required.amount(number) — positive amount. Required.
- Returns:
boolean—trueon success,falsewhen the account is invalid or the withdrawal fails.
if exports["sky_jobs_base"]:removeJobMoney("ambulance", 2500) then
print("Invoice paid from society funds")
end
Permissions
hasJobPermission(playerId, permission, jobName)
- Purpose: Checks whether a player's grade has a boss-menu permission. Useful for external resources that gate features behind management permissions.
- Arguments:
playerId(number) — the server ID of the player. Required.permission(number | string) — Permission enum value or key name (e.g.3or"MANAGE_MEMBERS"). Required.jobName(string?) — when set, the check additionally requires the player to be on this job.
- Returns:
boolean—trueif the grade has the permission (or theALLpermission).
Permission Keys
VIEW_LOGS, MANAGE_ROLES, MANAGE_MEMBERS, MANAGE_WAREHOUSE, MANAGE_MONEY, EDIT_OUTFITS, CREATE_OUTFITS, DELETE_OUTFITS, PURCHASE_SUPPLIES, PURCHASE_VEHICLES, GARAGE_VEHICLES, SELL_VEHICLES, TABLET_APPS, DOCUMENT_CLASSIFICATIONS, ALL
if exports["sky_jobs_base"]:hasJobPermission(playerId, "MANAGE_MONEY", "ambulance") then
-- allow external payout action
end
Support
Need help? Our support team is always ready to assist
Join Discord