ESX items: the items table, RegisterUsableItem and addInventoryItem
Add an item to ESX: the items SQL table, ESX.RegisterUsableItem to make it usable, addInventoryItem, removeInventoryItem, getInventoryItem and canCarryItem, plus the ox_inventory note.
You want a new item on your ESX server: a burger, a phone, a lockpick. In ESX an item is a row in the database, and a script gives, removes and uses it through the player object. This article covers the items table, making an item usable, the xPlayer functions you use every day, and what changes when the server runs ox_inventory.
The items table
ESX reads its items from the items table. Its columns are:
| Column | Meaning |
|---|---|
name |
The item name used in code. Lowercase, no spaces |
label |
The name players see |
weight |
Weight of one item |
rare |
Kept for older uses, normally 0 |
can_remove |
1 if players may drop or remove the item |
Add an item with SQL:
INSERT INTO `items` (`name`, `label`, `weight`, `rare`, `can_remove`)
VALUES ('burger', 'Burger', 1, 0, 1);Restart ESX, or the whole server, so it reloads the table. If your database shows a different set of columns, follow the columns it has, since versions differ a little. If you are unsure how to run a query, see oxmysql queries.
Warning: the item name is the key.
burgerandBurgerare different, and an item added with the wrong spelling fails silently in most scripts.
Make an item usable
Register the item on the server, in a script:
ESX = exports['es_extended']:getSharedObject()
ESX.RegisterUsableItem('burger', function(source)
local xPlayer = ESX.GetPlayerFromId(source)
if not xPlayer then return end
xPlayer.removeInventoryItem('burger', 1)
TriggerClientEvent('my_script:eatBurger', source)
end)The callback runs on the server when the player uses the item. It does not remove the item by itself, so you remove it yourself. Do the removal on the server, then tell the client to play the animation. If the object is nil, see ESX is nil: fixing getSharedObject.
On the client, the event only has to play the effect:
RegisterNetEvent('my_script:eatBurger', function()
-- animation, progress bar, hunger update
end)Give, remove and check items
These are the xPlayer functions you need:
local xPlayer = ESX.GetPlayerFromId(source)
-- give
xPlayer.addInventoryItem('burger', 2)
-- remove
xPlayer.removeInventoryItem('burger', 1)
-- read one item
local item = xPlayer.getInventoryItem('burger')
print(item.count)getInventoryItem returns a table with at least count, label and name. If the item does not exist in the table, the result can be nil on some versions, so check before you read count.
A reliable pattern is to check before you remove:
local item = xPlayer.getInventoryItem('lockpick')
if item and item.count >= 1 then
xPlayer.removeInventoryItem('lockpick', 1)
-- do the action
else
xPlayer.showNotification('You need a lockpick')
endCheck the weight first: canCarryItem
Before giving an item, ask whether the player can carry it. If you do not, addInventoryItem can fail on a full inventory and the player loses the reward:
if xPlayer.canCarryItem('burger', 2) then
xPlayer.addInventoryItem('burger', 2)
else
xPlayer.showNotification('You cannot carry that much')
endcanCarryItem(name, count) compares the item weight with the free weight of the player. Use it everywhere a script rewards an item: jobs, crafting, loot. For other helpers, see ESX job setup.
An example: a shop that sells an item
Put the pieces together on the server, with a check for money and weight:
RegisterNetEvent('my_script:buyBurger', function()
local src = source
local xPlayer = ESX.GetPlayerFromId(src)
if not xPlayer then return end
local price = 10
if xPlayer.getAccount('money').money < price then
return xPlayer.showNotification('Not enough money')
end
if not xPlayer.canCarryItem('burger', 1) then
return xPlayer.showNotification('Your inventory is full')
end
xPlayer.removeAccountMoney('money', price)
xPlayer.addInventoryItem('burger', 1)
end)The price and the item are fixed on the server. The client only says "I want a burger", it never sends the price. See securing server events for why.
ESX with ox_inventory
Many ESX servers run ox_inventory instead of the default inventory. Then:
- items are defined in
ox_inventory/data/items.lua, not in the SQL table - the
xPlayer.addInventoryItemfamily still works, as ESX hands it to ox_inventory ESX.RegisterUsableItemstill works, so older scripts do not need changing- the item must exist in
items.lua, or the call fails
To switch, follow the ox_inventory setup for ESX, and set the custom inventory option in the es_extended config so ESX knows which inventory is in use. For adding an item the ox_inventory way, see how to add items to ox_inventory.
Tip: if you do not want to edit SQL or Lua for every new item, Item Creator lets you create items in game.
Checklist
| Symptom | Fix |
|---|---|
| Item does not exist | Add a row to the items table, or to items.lua with ox_inventory |
| Item does nothing when used | Register it with ESX.RegisterUsableItem on the server |
addInventoryItem gives nothing |
Wrong name, or the player cannot carry it; check xPlayer.canCarryItem |
| Item not removed after use | The callback must call removeInventoryItem itself |
getInventoryItem is nil |
The item name is not in the items table |
| Name mismatch | Names are case sensitive; use the exact name value |
Quick answers
Where do I add a new item in ESX?
In the items table of your database, with a name, a label and a weight. On a server running ox_inventory, items are defined in ox_inventory/data/items.lua instead.
How do I make an ESX item usable?
Register it on the server with ESX.RegisterUsableItem('itemname', function(source) ... end). The item name must match the name in the items table.
Why does addInventoryItem do nothing?
The item name is not in the items table, the player cannot carry it, or you used a name with different capitalisation. Check the item exists and test with xPlayer.canCarryItem first.

