Controlling inventory actions with ox_inventory hooks
On the server, exports.ox_inventory:registerHook(event, function(payload) ... end, options) runs your function before an action. Events include swapItems, openInventory, openShop, buyItem, createItem, usingItem and craftItem. Return false to cancel (for createItem, return a table to set metadata). Narrow hooks with itemFilter, inventoryFilter (Lua patterns) and typeFilter, keep them fast, and remove them with removeHooks.
Sooner or later every server needs rules the inventory does not have: no weapons in the evidence locker, no drugs in vehicle gloveboxes, a Discord log for every high-value transfer. ox_inventory’s hooks let your resource inspect an action on the server and cancel it — without editing the inventory itself.

#Hook events
| Event | Runs when |
|---|---|
swapItems | Items move between slots or inventories (move, stack, swap, give) |
openInventory | An inventory (stash, trunk…) is opened |
openShop | A shop is opened |
buyItem | A shop purchase is made |
createItem | An item is created (can return metadata) |
usingItem | An item is about to be used |
craftItem | A crafting recipe is completed |
#Example: no weapons in gloveboxes
local WEAPONS = {}
for name in pairs(exports.ox_inventory:Items()) do
if name:find('^WEAPON_') then WEAPONS[name] = true end
end
exports.ox_inventory:registerHook('swapItems', function(payload)
if payload.toType == 'glovebox' then
TriggerClientEvent('ox_lib:notify', payload.source, { type = 'error', description = 'Weapons do not fit in the glovebox' })
return false
end
end, {
itemFilter = WEAPONS,
print = false,
})itemFilter is a set of item names; the hook only runs when one of them is involved, so everyday item moves cost nothing.
#Filters
| Option | Form | Matches |
|---|---|---|
itemFilter | { water = true, WEAPON_PISTOL = true } | Item names |
inventoryFilter | { '^glove', '^trunk', 'evidence' } | Inventory IDs by Lua pattern |
typeFilter | { player = true, stash = true } | Inventory or shop type |
print | true | Log each time the hook triggers |
#Example: logging high-value transfers
exports.ox_inventory:registerHook('swapItems', function(payload)
if payload.fromInventory ~= payload.toInventory and payload.count >= 10000 then
print(('[inv] %s moved %s x%d from %s to %s'):format(
payload.source, payload.fromSlot.name, payload.count, payload.fromInventory, payload.toInventory))
end
end, { itemFilter = { money = true, black_money = true } })#Performance and cleanup
- Hooks run inside the action — no database calls or HTTP requests in them.
- Use filters instead of
ifchecks at the top of the function. registerHookreturns an ID;exports.ox_inventory:removeHooks(id)removes one, and all of a resource’s hooks are removed when it stops.
Related: stashes, shops and item metadata.
Questions
How do I stop players moving an item in ox_inventory?
swapItems hook with an itemFilter and return false when the move is not allowed.Which events can ox_inventory hooks use?
swapItems, openInventory, openShop, buyItem, createItem, usingItem and craftItem.How do I set metadata when an item is created?
createItem hook.Do hooks slow down the inventory?
Ready to pick a map?
Twelve themes on three base map styles, $8 each, instant download.
Relevant to what you just read
The tool for this
Twenty theme pairs for ox_lib and ox_inventory From $15, built in the browser, exported as a drop-in resource.
Look it up while you work
The reference tables this guide leans on, free and without an account.
- All 921 vehicle spawn namesEvery vanilla model with a picture, its display name, its class and the hash CreateVehicle takes.