# Server Functions (/docs/es_extended/server/functions)

These are the functions on the shared `ESX` object that only exist on the server. Get the object with `ESX = exports['es_extended']:getSharedObject()` or `@es_extended/imports.lua`, then call them from any server script. Functions that work on both sides (`ESX.GetConfig`, `ESX.GetWeapon`, `ESX.Math`, `ESX.Table`, ...) are on the [shared functions](/docs/es_extended/shared) page.

## Overview [#overview]

| Fact | Value |
| --- | --- |
| Side | Server |
| Source | `es_extended/server/modules/*` |
| Player object | [xPlayer](/docs/es_extended/server/xplayer) |
| Entity helpers | [OneSync functions](/docs/es_extended/server/onesync) |
| Version | ESX Legacy 1.16.4 |

## Global tables [#global-tables]

| Table | Content |
| --- | --- |
| `ESX.Players` | `{ [source] = xPlayer }` for every loaded character. |
| `ESX.Jobs` | `{ [jobName] = job }`, each with a `grades` table keyed by grade as string. |
| `ESX.Items` | `{ [itemName] = { label, weight, rare, canRemove } }`. With ox_inventory this is ox_inventory's item list. |

<Callout type="warn">
Do not read these tables from other resources. The `ESX` object you receive through the export is a copy made at that moment, so the tables can be empty or stale. Use `ESX.GetExtendedPlayers`, `ESX.GetJobs` and `ESX.GetItems` instead.
</Callout>

## Players [#players]

### GetPlayerFromId [#getplayerfromid]

```lua
ESX.GetPlayerFromId(source)
```

| Name | Type | Description |
| --- | --- | --- |
| `source` | `number` or `string` | Server ID. Converted with `tonumber`. |

**Returns:** [`xPlayer`](/docs/es_extended/server/xplayer) or `nil` if the player has no loaded character.

```lua
RegisterNetEvent("myshop:buy", function(itemName)
    local xPlayer = ESX.GetPlayerFromId(source)
    if not xPlayer then return end

    -- validate itemName and price here
end)
```

### GetPlayerFromIdentifier [#getplayerfromidentifier]

```lua
ESX.GetPlayerFromIdentifier(identifier)
```

| Name | Type | Description |
| --- | --- | --- |
| `identifier` | `string` | Character identifier as stored in `users.identifier` (with `charX:` prefix when multicharacter is used). |

**Returns:** `xPlayer` or `nil` if that character is not online.

```lua
local xTarget = ESX.GetPlayerFromIdentifier(row.owner)

if xTarget then
    xTarget.showNotification("Your vehicle was impounded")
end
```

### GetPlayerIdFromIdentifier [#getplayeridfromidentifier]

```lua
ESX.GetPlayerIdFromIdentifier(identifier)
```

| Name | Type | Description |
| --- | --- | --- |
| `identifier` | `string` | Character identifier. |

**Returns:** `number` (server ID) or `nil`.

### IsPlayerLoaded [#isplayerloaded]

```lua
ESX.IsPlayerLoaded(source)
```

| Name | Type | Description |
| --- | --- | --- |
| `source` | `number` | Server ID. Must be a number, strings are not converted. |

**Returns:** `boolean`, `true` if an xPlayer exists for this ID.

### GetExtendedPlayers [#getextendedplayers]

```lua
ESX.GetExtendedPlayers(key, value, minimal)
```

| Name | Type | Description |
| --- | --- | --- |
| `key` | `string?` | Field to filter by. `"job"` compares `job.name`; any other key compares `xPlayer[key]`, for example `"group"`. |
| `value` | `any` or `table` | Value to match. A list of values returns a table grouped by value. |
| `minimal` | `boolean?` | `true` returns server IDs instead of xPlayer objects. |

**Returns:**

- No key: array of all xPlayers (or IDs).
- Single value: array of matching xPlayers (or IDs).
- List of values: `{ [value] = { xPlayer, ... } }`.

```lua
-- All police officers
for _, xPlayer in ipairs(ESX.GetExtendedPlayers("job", "police")) do
    xPlayer.showNotification("Robbery in progress at the Fleeca bank")
end

-- Grouped by job, only IDs
local byJob = ESX.GetExtendedPlayers("job", { "police", "ambulance" }, true)
print(#byJob.police, #byJob.ambulance)
```

### GetNumPlayers [#getnumplayers]

```lua
ESX.GetNumPlayers(key, value)
```

| Name | Type | Description |
| --- | --- | --- |
| `key` | `string?` | Same as `GetExtendedPlayers`. `"job"` uses a cached per-job counter. |
| `value` | `any` or `table` | Value or list of values. |

**Returns:** `number`, or `{ [value] = count }` when `value` is a list. Without arguments it returns `#GetPlayers()`, which also counts players who are still loading.

```lua
if ESX.GetNumPlayers("job", "police") < 2 then
    return xPlayer.showNotification("Not enough police online", "error")
end
```

### GetPlayers [#getplayers]

```lua
ESX.GetPlayers()
```

Alias of the FiveM native `GetPlayers()`. Returns all connected server IDs as **strings**, including players without a loaded character.

**Returns:** `string[]`

### Player [#player]

```lua
ESX.Player(src)
```

| Name | Type | Description |
| --- | --- | --- |
| `src` | `number` or `string` | Server ID, or a character identifier. |

Only available in resources that load `@es_extended/imports.lua`. Returns a static proxy: every key you index is a function that calls the matching xPlayer method through the `RunStaticPlayerMethod` export. Fields like `.job` are not available, use getters.

**Returns:** static player or `nil` if not loaded.

```lua
local player = ESX.Player(source)

if player then
    player.addAccountMoney("bank", 250, "Daily bonus")
end
```

### ExtendedPlayers [#extendedplayers]

```lua
ESX.ExtendedPlayers(key, value)
```

Static-player version of [`GetExtendedPlayers`](#getextendedplayers). Same filters, returns static proxies. Only available through `@es_extended/imports.lua`.

```lua
for _, medic in ipairs(ESX.ExtendedPlayers("job", "ambulance")) do
    medic.showNotification("New dispatch call")
end
```

### GetIdentifier [#getidentifier]

```lua
ESX.GetIdentifier(playerId)
```

| Name | Type | Description |
| --- | --- | --- |
| `playerId` | `number` or `string` | Server ID. |

Returns the player's identifier of the type set in `Config.Identifier` (convar `esx:identifier`, default `license`) **without** the `license:` prefix. In FXDK mode it returns `"ESX-DEBUG-LICENCE"`. Asserts if the player has no identifier of that type.

**Returns:** `string`

```lua
AddEventHandler("playerConnecting", function(_, _, deferrals)
    local identifier = ESX.GetIdentifier(source)
    print("Connecting: " .. identifier)
end)
```

<Callout type="info">
With multicharacter, `users.identifier` is `char1:<identifier>`, so `ESX.GetIdentifier` does not equal `xPlayer.identifier`. Use `xPlayer.getIdentifier()` for database lookups.
</Callout>

## Callbacks [#callbacks]

Server callbacks are handled by [esx_lib](/docs/core/esx_lib). See the [callbacks guide](/docs/guides/callbacks) for the full flow with the client side.

### RegisterServerCallback [#registerservercallback]

```lua
ESX.RegisterServerCallback(name, handler)
```

| Name | Type | Description |
| --- | --- | --- |
| `name` | `string` | Unique callback name, up to 200 characters. |
| `handler` | `function` | `function(source, cb, ...)`. Call `cb(...)` with the values to return. |

The resource that registers a name first owns it. Registering the same name from another resource throws an error; registering again from the same resource replaces the handler.

```lua
ESX.RegisterServerCallback("myshop:getBalance", function(source, cb)
    local xPlayer = ESX.GetPlayerFromId(source)
    cb(xPlayer and xPlayer.getAccount("bank").money or 0)
end)
```

The client calls it with `ESX.TriggerServerCallback("myshop:getBalance", function(balance) end)`, see [client functions](/docs/es_extended/client/functions).

### DoesServerCallbackExist [#doesservercallbackexist]

```lua
ESX.DoesServerCallbackExist(name)
```

**Returns:** `boolean`, whether a callback with this name is registered.

### TriggerClientCallback [#triggerclientcallback]

```lua
ESX.TriggerClientCallback(player, name, cb, ...)
```

| Name | Type | Description |
| --- | --- | --- |
| `player` | `number` | Target server ID. |
| `name` | `string` | Client callback name (registered with `ESX.RegisterClientCallback`). |
| `cb` | `function` | Receives the values the client returns. |
| `...` | `any` | Arguments for the client. |

```lua
ESX.TriggerClientCallback(source, "myscript:getStreetName", function(street)
    print("Player is on " .. street)
end)
```

### AwaitClientCallback [#awaitclientcallback]

```lua
ESX.AwaitClientCallback(player, name, ...)
```

Same as `TriggerClientCallback` but yields the current thread and returns the client's values directly.

**Returns:** `...` (whatever the client returned)

```lua
local street = ESX.AwaitClientCallback(source, "myscript:getStreetName")
```

## Events [#events]

### TriggerClientEvent [#triggerclientevent]

```lua
ESX.TriggerClientEvent(eventName, playerIds, ...)
```

| Name | Type | Description |
| --- | --- | --- |
| `eventName` | `string` | Client event name. |
| `playerIds` | `number` or `number[]` | One server ID or an array of IDs. |
| `...` | `any` | Event arguments. |

For an array, the arguments are serialized once and sent to every player, which is cheaper than calling `TriggerClientEvent` in a loop.

```lua
local officers = ESX.GetExtendedPlayers("job", "police", true)
ESX.TriggerClientEvent("dispatch:client:alert", officers, { code = "10-31", coords = coords })
```

## Commands [#commands]

### RegisterCommand [#registercommand]

```lua
ESX.RegisterCommand(name, group, cb, allowConsole, suggestion)
```

| Name | Type | Description |
| --- | --- | --- |
| `name` | `string` or `string[]` | Command name, or a list of aliases that share the same handler. |
| `group` | `string` or `string[]` | Group(s) allowed to use it. ESX adds `add_ace group.<group> command.<name> allow`. |
| `cb` | `function` | `function(xPlayer, args, showError)`. `xPlayer` is `false` when run from the console. |
| `allowConsole` | `boolean?` | Allow the server console to run it. |
| `suggestion` | `table?` | `{ help, validate, arguments }` for chat suggestions and argument parsing. |

Each entry in `suggestion.arguments` is `{ name, help, type, Validator? }`:

| `type` | Parsed into `args[name]` |
| --- | --- |
| `number` | `tonumber(arg)`, error if not numeric |
| `player` | the target's **xPlayer** (`me` = yourself), error if not online |
| `playerId` | the target's server ID (`me` = yourself), error if not online |
| `string` | the raw string; numeric strings are rejected |
| `item` | the item name, error if it is not in `ESX.Items` |
| `weapon` | the upper-case weapon name from `Config.Weapons` |
| `coordinate` | the first number found in the argument |
| `merge` | this argument and everything after it, joined with spaces |
| `any` | the raw string |

Set `validate = true` to require the exact number of arguments. `Validator = { validate = function(value) return true end, err = "message" }` adds a custom check per argument. `showError(msg)` shows a notification to the player, or prints to the console.

Registering an existing name again overrides the previous handler and prints a warning.

```lua title="server/commands.lua"
ESX.RegisterCommand("givecash", "admin", function(xPlayer, args, showError)
    args.target.addMoney(args.amount, "Admin gift")
    showError(("Gave $%d to %s"):format(args.amount, args.target.getName()))
end, true, {
    help = "Give cash to a player",
    validate = true,
    arguments = {
        { name = "target", help = "Player ID", type = "player" },
        { name = "amount", help = "Amount", type = "number", Validator = {
            validate = function(value) return value > 0 end,
            err = "Amount must be positive",
        } },
    },
})
```

The list of built-in commands is on the [commands page](/docs/es_extended/commands).

## Jobs [#jobs]

### GetJobs [#getjobs]

```lua
ESX.GetJobs(jobType)
```

| Name | Type | Description |
| --- | --- | --- |
| `jobType` | `string`, `string[]` or `nil` | Only return jobs of this `type` (for example `"civ"`). |

Waits until jobs are loaded, then returns `{ [jobName] = job }`. Each job contains the columns of its `jobs` row (`name`, `label`, `type`, ...) plus `grades`, keyed by grade as string.

```lua
for name, job in pairs(ESX.GetJobs()) do
    print(name, job.label)
end
```

### DoesJobExist [#doesjobexist]

```lua
ESX.DoesJobExist(job, grade)
```

| Name | Type | Description |
| --- | --- | --- |
| `job` | `string` | Job name. |
| `grade` | `number` or `string` | Grade number. |

Waits until jobs are loaded.

**Returns:** `boolean`

```lua
if ESX.DoesJobExist("police", 4) then
    xPlayer.setJob("police", 4)
end
```

### RefreshJobs [#refreshjobs]

```lua
ESX.RefreshJobs()
```

Reloads every job and grade from the `jobs` and `job_grades` tables. Jobs without grades are skipped. If `unemployed` (or its grade `0`) is missing, a fallback is created. Fires `esx:jobsRefreshed`.

### RefreshJob [#refreshjob]

```lua
ESX.RefreshJob(jobName)
```

| Name | Type | Description |
| --- | --- | --- |
| `jobName` | `string` | Job to reload from the database. |

Reloads one job and calls `xPlayer.refreshJob()` for every online member. Fires `esx:jobRefreshed` (`jobName, job`). If the job or its grades are gone, it is removed, its members become `unemployed` and `esx:jobRemoved` fires.

**Returns:** `boolean`, `true` if the job was refreshed.

```lua
MySQL.update.await("UPDATE job_grades SET salary = ? WHERE job_name = ? AND grade = ?", { 900, "police", 2 })
ESX.RefreshJob("police")
```

### CreateJob [#createjob]

```lua
ESX.CreateJob(name, label, grades, jobType)
```

| Name | Type | Description |
| --- | --- | --- |
| `name` | `string` | Job name. |
| `label` | `string` | Display label. |
| `grades` | `table[]` | `{ grade, name, label, salary, skin_male?, skin_female? }` entries. |
| `jobType` | `string?` | Job type. Defaults to `"civ"`. |

Inserts the job and any missing grades into the database in one transaction and adds them to `ESX.Jobs`. If the job exists, only new grades are added and the existing label and type are kept. Fires `esx:jobCreated`.

**Returns:** `boolean`, `false` if arguments are missing, nothing new was inserted, or the transaction failed.

```lua
ESX.CreateJob("baker", "Baker", {
    { grade = 0, name = "trainee", label = "Trainee", salary = 150 },
    { grade = 1, name = "baker", label = "Baker", salary = 300 },
    { grade = 2, name = "boss", label = "Owner", salary = 500 },
})
```

See [create a job](/docs/guides/create-a-job).

## Items [#items]

### GetItems [#getitems]

```lua
ESX.GetItems()
```

**Returns:** `{ [itemName] = { label, weight, rare, canRemove } }`

### GetItemLabel [#getitemlabel]

```lua
ESX.GetItemLabel(item)
```

**Returns:** `string` or `nil` (prints a warning for unknown items). With ox_inventory the label comes from `exports.ox_inventory:Items(item)`.

```lua
xPlayer.showNotification(("You received %s"):format(ESX.GetItemLabel("bread")))
```

### AddItems [#additems]

```lua
ESX.AddItems(items)
```

| Name | Type | Description |
| --- | --- | --- |
| `items` | `table[]` | `{ name, label, weight?, rare?, canRemove? }` entries. `weight` defaults to `1`, `rare` to `false`, `canRemove` to `true`. |

Inserts new items into the `items` table (`INSERT IGNORE`), registers them in `ESX.Items` and refreshes online inventories. Items that already exist or have invalid fields are skipped. Not available with ox_inventory.

```lua
ESX.AddItems({
    { name = "coffee", label = "Coffee", weight = 0.3 },
    { name = "donut", label = "Donut", weight = 0.2 },
})
```

### RefreshItems [#refreshitems]

```lua
ESX.RefreshItems()
```

Reloads all items from the `items` table and removes unknown items from online players. Not available with ox_inventory.

**Returns:** `number`, the number of items loaded.

### RegisterUsableItem [#registerusableitem]

```lua
ESX.RegisterUsableItem(item, cb)
```

| Name | Type | Description |
| --- | --- | --- |
| `item` | `string` | Item name. |
| `cb` | `function` | `function(source, itemName, ...)`, called when the player uses the item. |

ESX does **not** remove the item for you. Remove it inside the callback.

```lua
ESX.RegisterUsableItem("bandage", function(source)
    local xPlayer = ESX.GetPlayerFromId(source)
    if not xPlayer or not xPlayer.removeInventoryItem("bandage", 1) then return end

    TriggerClientEvent("myhealth:client:heal", source, 25)
end)
```

### UseItem [#useitem]

```lua
ESX.UseItem(source, item, ...)
```

Runs the registered usable callback for `item` as if the player used it. Does not check whether the player owns the item. Errors inside the callback are caught and printed.

### GetUsableItems [#getusableitems]

```lua
ESX.GetUsableItems()
```

**Returns:** `{ [itemName] = true }` for every registered usable item.

### CreatePickup [#createpickup]

```lua
ESX.CreatePickup(itemType, name, count, label, playerId, components, tintIndex, coords, bucket)
```

| Name | Type | Description |
| --- | --- | --- |
| `itemType` | `string` | `"item_standard"`, `"item_account"` or `"item_weapon"`. |
| `name` | `string` | Item, account or weapon name. |
| `count` | `number` | Amount, or ammo for weapons. |
| `label` | `string` | Text shown on the pickup. |
| `playerId` | `number?` | Player that dropped it. Used for position, routing bucket and per-player limits. |
| `components` | `table?` | Weapon components (`item_weapon` only). |
| `tintIndex` | `number?` | Weapon tint (`item_weapon` only). |
| `coords` | `vector3`, `vector4` or `table` | Position. Required when `playerId` is not given. |
| `bucket` | `number?` | Routing bucket. Defaults to the player's bucket, or `0`. |

Pickups expire after 30 minutes. ESX limits them to 50 per player, 250 per 100 m grid cell and 5000 in total. Not available with ox_inventory.

**Returns:** pickup ID (`number`) or `nil` when a limit is reached or no position is known.

```lua
ESX.CreatePickup("item_standard", "bread", 3, "Bread x3", nil, nil, nil, vector3(215.0, -810.0, 30.7))
```

## Vehicles [#vehicles]

### GetVehicleType [#getvehicletype]

```lua
ESX.GetVehicleType(model, player, cb)
```

| Name | Type | Description |
| --- | --- | --- |
| `model` | `string` or `number` | Model name or hash. |
| `player` | `number?` | A player to ask when the type is not cached yet. |
| `cb` | `function?` | Receives the type. Without it the function yields and returns the type. |

Returns the server vehicle type for `CreateVehicleServerSetter`: `"automobile"`, `"bike"`, `"boat"`, `"heli"`, `"plane"`, `"submarine"`, `"trailer"` or `"train"`. Unknown models without a player return `nil`. The server console command `clearvehicletypes` clears the cache.

```lua
local vehicleType = ESX.GetVehicleType("t20", source)
```

### CreateExtendedVehicle [#createextendedvehicle]

```lua
ESX.CreateExtendedVehicle(owner, plate, coords)
```

| Name | Type | Description |
| --- | --- | --- |
| `owner` | `string` | Owner identifier (`owned_vehicles.owner`). |
| `plate` | `string` | Plate of a **stored** owned vehicle. |
| `coords` | `vector4` | Spawn position and heading. |

Spawns an owned vehicle from `owned_vehicles` with its saved properties, marks it as not stored and tracks it. Returns the existing object if that plate is already out. Fires `esx:createdExtendedVehicle`.

**Returns:** extended vehicle object or `nil`.

| Method | Description |
| --- | --- |
| `vehicle:isValid()` | `true` while the entity still exists and matches owner and plate. Deletes the record otherwise. |
| `vehicle:getPlate()` / `getNetId()` / `getEntity()` / `getModelHash()` / `getOwner()` | Getters. |
| `vehicle:setPlate(newPlate)` | Updates the database, entity and state bag. Returns `boolean`. |
| `vehicle:setProps(props)` | Saves new properties and syncs them. Returns `boolean`. |
| `vehicle:setOwner(identifier)` | Transfers ownership in the database. Returns `boolean`. |
| `vehicle:delete(garageName?, isImpound?)` | Deletes the entity and marks the vehicle as stored (in `parking` or `pound`). |

```lua
local vehicle = ESX.CreateExtendedVehicle(xPlayer.identifier, "ESX 123", vector4(215.8, -810.1, 30.7, 160.0))

if vehicle then
    print("Spawned with net ID " .. vehicle:getNetId())
end
```

### GetExtendedVehicleFromPlate [#getextendedvehiclefromplate]

```lua
ESX.GetExtendedVehicleFromPlate(plate)
```

**Returns:** the extended vehicle object for a spawned plate, or `nil`.

```lua
local vehicle = ESX.GetExtendedVehicleFromPlate("ESX 123")

if vehicle then
    vehicle:delete("legion_garage")
end
```

## Player function overrides [#player-function-overrides]

### RegisterPlayerFunctionOverrides [#registerplayerfunctionoverrides]

```lua
ESX.RegisterPlayerFunctionOverrides(index, overrides)
```

| Name | Type | Description |
| --- | --- | --- |
| `index` | `string` | Name of the override set. |
| `overrides` | `table` | `{ [methodName] = function(self) return function(...) end end }` |

Each entry is a factory that receives the xPlayer and returns the new method. All registered sets are applied to every xPlayer created afterwards. ESX uses this for its ox_inventory bridge.

```lua
ESX.RegisterPlayerFunctionOverrides("myOverrides", {
    getName = function(self)
        return function()
            return ("[%s] %s"):format(self.job.label, self.name)
        end
    end,
})
```

### SetPlayerFunctionOverride [#setplayerfunctionoverride]

```lua
ESX.SetPlayerFunctionOverride(index)
```

<Callout type="warn" title="No effect in 1.16.4">
This only stores `index` in `Config.PlayerFunctionOverride`, which es_extended no longer reads. Every registered override set is applied regardless.
</Callout>

## Logging and debug [#logging-and-debug]

### DiscordLog [#discordlog]

```lua
ESX.DiscordLog(name, title, color, message)
```

| Name | Type | Description |
| --- | --- | --- |
| `name` | `string` | Webhook key in `Config.DiscordLogs.Webhooks`. Falls back to `default`. |
| `title` | `string` | Embed title. |
| `color` | `string` | Color key in `Config.DiscordLogs.Colors`. |
| `message` | `string` | Embed description. |

```lua
ESX.DiscordLog("UserActions", "Bank robbery", "red", ("%s started a robbery"):format(xPlayer.getName()))
```

See the [logs config](/docs/es_extended/config/logs).

### DiscordLogFields [#discordlogfields]

```lua
ESX.DiscordLogFields(name, title, color, fields)
```

| Name | Type | Description |
| --- | --- | --- |
| `fields` | `table[]` | Discord embed fields `{ name, value, inline? }`. Values are converted with `tostring`. |

Other parameters are the same as `DiscordLog`.

```lua
ESX.DiscordLogFields("UserActions", "Item sold", "green", {
    { name = "Player", value = xPlayer.getName(), inline = true },
    { name = "Item", value = "gold_bar", inline = true },
    { name = "Price", value = 2500, inline = true },
})
```

### Trace [#trace]

```lua
ESX.Trace(msg)
```

Prints `[TRACE] msg` to the server console only when `Config.EnableDebug` is `true`.

## Common issues [#common-issues]

- **`ESX.Player` is nil**: you did not add `@es_extended/imports.lua` to `shared_scripts`.
- **Empty `ESX.Jobs` in your resource**: read jobs with `ESX.GetJobs()`, which also waits until they are loaded.
- **`AddItems`, `RefreshItems` or `CreatePickup` is nil**: ox_inventory is running, so the default inventory functions are not defined.

## Related [#related]

- [xPlayer](/docs/es_extended/server/xplayer)
- [OneSync functions](/docs/es_extended/server/onesync)
- [Shared functions](/docs/es_extended/shared)
- [Server events](/docs/es_extended/events/server)
- [Callbacks guide](/docs/guides/callbacks)
