# Callbacks (/docs/es_extended/client/modules/callback)

Callbacks let one side ask the other side for data and get an answer back. The client asks the server with `ESX.TriggerServerCallback` or `ESX.AwaitServerCallback`, and the server answers through a handler registered with `ESX.RegisterServerCallback`. The reverse direction works the same way with client callbacks.

## Overview [#overview]

| | |
|---|---|
| Resource | `es_extended` (implemented by `esx_lib`) |
| Side | Client and server |
| Source | `client/modules/callback.lua`, `server/modules/callback.lua` |

In ESX Legacy 1.16 the ESX callback functions are thin wrappers around `xLib.callback` from [esx_lib](/docs/core/esx_lib). The ESX signatures (`cb` as first or second argument) still work, so old scripts do not need changes.

| Direction | Register on | Trigger with |
|---|---|---|
| Client asks server | Server: `ESX.RegisterServerCallback` | Client: `ESX.TriggerServerCallback`, `ESX.AwaitServerCallback` |
| Server asks client | Client: `ESX.RegisterClientCallback` | Server: `ESX.TriggerClientCallback`, `ESX.AwaitClientCallback` |

## Client functions [#client-functions]

### ESX.TriggerServerCallback [#esxtriggerservercallback]

```lua
ESX.TriggerServerCallback(eventName, callback, ...)
```

Calls a server callback and passes the response to `callback`. Does not block.

| Name | Type | Description |
|---|---|---|
| `eventName` | `string` | Callback name. |
| `callback` | `function` | Receives the values the server passed to `cb`. |
| `...` | `any` | Arguments sent to the server handler. |

**Returns:** nothing

```lua title="client/main.lua"
ESX.TriggerServerCallback('garage:getVehicles', function(vehicles)
    for i = 1, #vehicles do
        print(vehicles[i].plate)
    end
end, 'pillbox')
```

### ESX.AwaitServerCallback [#esxawaitservercallback]

```lua
ESX.AwaitServerCallback(eventName, ...)
```

Calls a server callback and waits for the answer. Must run inside a thread (command handler, `CreateThread`, event handler).

| Name | Type | Description |
|---|---|---|
| `eventName` | `string` | Callback name. |
| `...` | `any` | Arguments sent to the server handler. |

**Returns:** every value the server passed to `cb`.

```lua title="client/main.lua"
RegisterCommand('mygarage', function()
    local vehicles = ESX.AwaitServerCallback('garage:getVehicles', 'pillbox')
    print(('You own %d vehicles here'):format(#vehicles))
end, false)
```

<Callout type="warn">
`ESX.AwaitServerCallback` throws an error when the callback does not exist or times out. Wrap it in `pcall` if your code must continue in that case.
</Callout>

### ESX.RegisterClientCallback [#esxregisterclientcallback]

```lua
ESX.RegisterClientCallback(eventName, callback)
```

Registers a callback the server can call on this client. The handler gets `cb` first, then the server's arguments. It is removed when your resource stops.

| Name | Type | Description |
|---|---|---|
| `eventName` | `string` | Callback name (max. 200 characters). |
| `callback` | `function` | `function(cb, ...)`. Call `cb(...)` once with the response. |

**Returns:** nothing

```lua title="client/main.lua"
ESX.RegisterClientCallback('police:getStreetName', function(cb)
    local coords = GetEntityCoords(ESX.PlayerData.ped)
    local street = GetStreetNameFromHashKey(GetStreetNameAtCoord(coords.x, coords.y, coords.z))
    cb(street)
end)
```

### ESX.DoesClientCallbackExist [#esxdoesclientcallbackexist]

```lua
ESX.DoesClientCallbackExist(eventName)
```

**Returns:** `boolean`, whether a callback with this name is registered in the local esx_lib registry.

## Server functions [#server-functions]

These are listed here so both halves are in one place. The full server reference is in [Server functions](/docs/es_extended/server/functions).

### ESX.RegisterServerCallback [#esxregisterservercallback]

```lua
ESX.RegisterServerCallback(eventName, callback)
```

| Name | Type | Description |
|---|---|---|
| `eventName` | `string` | Callback name (max. 200 characters). |
| `callback` | `function` | `function(source, cb, ...)`. Call `cb(...)` once with the response. |

**Returns:** nothing

```lua title="server/main.lua"
ESX.RegisterServerCallback('garage:getVehicles', function(source, cb, garage)
    local xPlayer = ESX.GetPlayerFromId(source)
    if not xPlayer or type(garage) ~= 'string' then
        return cb({})
    end

    local vehicles = MySQL.query.await(
        'SELECT plate, vehicle FROM owned_vehicles WHERE owner = ? AND parking = ?',
        { xPlayer.identifier, garage }
    )
    cb(vehicles or {})
end)
```

### ESX.TriggerClientCallback [#esxtriggerclientcallback]

```lua
ESX.TriggerClientCallback(player, eventName, callback, ...)
```

| Name | Type | Description |
|---|---|---|
| `player` | `number` | Server id of the target player. |
| `eventName` | `string` | Client callback name. |
| `callback` | `function` | Receives the client's response. |
| `...` | `any` | Arguments for the client handler. |

**Returns:** nothing

```lua title="server/main.lua"
ESX.TriggerClientCallback(source, 'police:getStreetName', function(street)
    print(('Player %s is on %s'):format(source, street))
end)
```

### ESX.AwaitClientCallback [#esxawaitclientcallback]

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

Blocking version of `ESX.TriggerClientCallback`. **Returns:** the values the client passed to `cb`.

### ESX.DoesServerCallbackExist [#esxdoesservercallbackexist]

```lua
ESX.DoesServerCallbackExist(eventName)
```

**Returns:** `boolean`

## Timeouts and limits [#timeouts-and-limits]

| Setting | Default | Description |
|---|---|---|
| `esx:callbackTimeout` / `xLib:callbackTimeout` | `300000` ms | How long the caller waits. `0` disables the timeout. Set on the server; it is replicated to clients. |
| `xLib:callbackValidationGrace` | `15000` ms | How long an unknown callback name is given to appear before the caller gets "does not exist". |
| `xLib:callbackBurst` / `xLib:callbackRate` | `60` / `30` per second | Per-player rate limit for client to server callbacks. |
| `xLib:callbackMaxInFlight` | `8` | Open client to server callbacks per player. |
| `xLib:callbackMaxPayloadBytes` | `65536` | Max size of the arguments a client may send. |

```bash title="server.cfg"
setr esx:callbackTimeout 30000
```

If a client exceeds the rate limit or payload size, or a server handler takes longer than the receiver timeout (30 s unless `esx:callbackTimeout` is set), the client gets `false` as the response.

## Built-in callbacks [#built-in-callbacks]

| Name | Side | Returns |
|---|---|---|
| `esx:getPlayerData` | Server | Identifier, accounts, inventory, job, loadout, money, position and metadata of the caller. |
| `esx:getOtherPlayerData` | Server | Same data for another player id. Admins only, otherwise `nil`. |
| `esx:isUserAdmin` | Server | `true` if the caller is an admin. |
| `esx:getGameBuild` | Server | Value of `sv_enforceGameBuild` (default `1604`). |
| `esx:getPlayerNames` | Server | Character names for a table of player ids. |
| `esx:spawnVehicle` | Server | Deprecated. Admin-only vehicle spawn, prints a warning. |
| `esx:GetVehicleType` | Client | Vehicle type string for a model. Used by the server-side `ESX.GetVehicleType`. |

```lua
local isAdmin = ESX.AwaitServerCallback('esx:isUserAdmin')
```

## Security [#security]

<Callout type="error" title="Never trust callback arguments">
Everything a client sends to `ESX.RegisterServerCallback` can be faked by a cheater. Validate types and ranges, look the player up with `ESX.GetPlayerFromId(source)`, and check permissions and distances on the server. Never let a callback give money or items based on a value the client sent.
</Callout>

## Common issues [#common-issues]

- **Old code calls `cb` twice.** Only the first call is used.
- **Server handler never calls `cb`.** After the receiver timeout (30 s by default) the server answers with `false`, so the client gets `false` instead of your data.
- **"callback 'x' is already owned by resource 'y'".** Two resources use the same name. Prefix names with your resource name.

## Related [#related]

- [Server functions](/docs/es_extended/server/functions)
- [Callbacks guide](/docs/guides/callbacks)
- [esx_lib](/docs/core/esx_lib)
- [Client functions](/docs/es_extended/client/functions)
