Tutorial 2026-05-04

ox_inventory Complete Guide for FiveM

OntelMonke

OntelMonke

Developer at Agency Scripts

What is ox_inventory?

ox_inventory is a modern, high-performance inventory system for FiveM that has become the standard choice for serious roleplay servers. Built by the Overextended team, it replaces older inventory solutions with a system that is faster, more flexible, and easier to extend. It features a sleek React-based UI, built-in weapon management, crafting support, shops, stashes, and a powerful API that script developers can use to create custom item interactions. Whether you are building a new server or migrating from another inventory, understanding ox_inventory deeply will make you a better FiveM developer.

Installation and Configuration

ox_inventory requires ox_lib as a dependency and works with both ESX and QBCore frameworks, as well as standalone setups. The installation involves downloading the resource, importing the SQL schema into your database, and configuring the framework bridge. The configuration file controls everything from inventory weight limits to item decay timers.

-- Configuration snippet from ox_inventory
return {
    playerslots = 50,
    playerweight = 30000,
    playerweaponslots = 5,

    decay = true,
    decayInterval = 60,

    trunkslots = 50,
    trunkweight = 60000,
    gloveboxslots = 5,
    gloveboxweight = 5000,
}

Registering Custom Items

Items in ox_inventory are defined in the data/items.lua file. Each item needs a unique name, a label, a weight, and optionally a stack size, decay rate, description, and client-side or server-side event handlers. Understanding the full item definition schema lets you create items that do exactly what your scripts need.

-- data/items.lua
return {
    ['water_bottle'] = {
        label = 'Water Bottle',
        weight = 500,
        stack = true,
        close = true,
        description = 'A refreshing bottle of water',
        client = {
            image = 'water_bottle.png',
        }
    },

    ['lockpick'] = {
        label = 'Lockpick',
        weight = 200,
        stack = true,
        close = true,
        degrade = 300,
        description = 'Used to pick locks. Breaks after use.',
    },

    ['driver_license'] = {
        label = 'Driver License',
        weight = 0,
        stack = false,
        consume = 0,
        description = 'Issued by the DMV',
        client = {
            image = 'driver_license.png',
        }
    },
}

Using the ox_inventory Server API

The server-side exports are the most commonly used part of ox_inventory, allowing you to add items, remove items, check inventory contents, and manipulate metadata. Always use server-side API for item manipulation to prevent exploitation by cheaters.

-- Server-side: Adding items to a player
RegisterNetEvent('myresource:giveReward', function(itemName, count)
    local src = source
    local success = exports.ox_inventory:AddItem(src, itemName, count)

    if success then
        TriggerClientEvent('ox_lib:notify', src, {
            title = 'Item Received',
            description = count .. 'x ' .. itemName,
            type = 'success'
        })
    else
        TriggerClientEvent('ox_lib:notify', src, {
            title = 'Inventory Full',
            description = 'Could not add item to inventory',
            type = 'error'
        })
    end
end)

-- Server-side: Check if player has required items
local function HasRequiredItems(src, requirements)
    for _, req in ipairs(requirements) do
        local count = exports.ox_inventory:GetItemCount(src, req.name)
        if count < req.amount then
            return false, req.name, req.amount - count
        end
    end
    return true
end

-- Server-side: Remove multiple items in a transaction
local function ConsumeRecipeItems(src, recipe)
    for _, ingredient in ipairs(recipe.ingredients) do
        local removed = exports.ox_inventory:RemoveItem(
            src, ingredient.name, ingredient.amount
        )
        if not removed then
            print(('[ERROR] Failed to remove %s from player %d'):format(
                ingredient.name, src
            ))
            return false
        end
    end
    return true
end

Working with Item Metadata

Item metadata is one of the most powerful features of ox_inventory. It allows you to attach arbitrary data to individual item instances, enabling unique serial numbers on weapons, expiration dates on food, player names on ID cards, and custom properties on any item.

-- Server: Create a driver license with metadata
RegisterNetEvent('myresource:issueLicense', function(targetId, licenseType)
    local src = source

    local metadata = {
        type = licenseType,
        issued = os.date('%Y-%m-%d'),
        issuedBy = GetPlayerName(src),
        holder = GetPlayerName(targetId),
        expires = os.date('%Y-%m-%d', os.time() + 30 * 86400),
    }

    exports.ox_inventory:AddItem(targetId, 'driver_license', 1, metadata)
end)

-- Client: Reading metadata when using an item
exports('driver_license', function(data, slot)
    local item = exports.ox_inventory:GetSlot(slot)
    if not item or not item.metadata then return end

    local meta = item.metadata
    lib.notify({
        title = 'Driver License',
        description = ('Holder: %s\nType: %s\nExpires: %s'):format(
            meta.holder or 'Unknown',
            meta.type or 'Standard',
            meta.expires or 'N/A'
        ),
        type = 'inform'
    })
end)

Creating Custom Shops

ox_inventory includes a built-in shop system that you can configure with custom item catalogs, pricing, job restrictions, and locations. Shops are defined in data/shops.lua and can be attached to ped vendors, blip locations, or triggered programmatically.

-- data/shops.lua
return {
    ['hardware_store'] = {
        name = 'Hardware Store',
        inventory = {
            { name = 'lockpick',    price = 150,  count = 10 },
            { name = 'screwdriver', price = 80,   count = 20 },
            { name = 'radio',       price = 250,  count = 5  },
            { name = 'repairkit',   price = 1000, count = 5  },
        },
        locations = {
            vec3(45.6, -1749.3, 29.6),
            vec3(2747.8, 3472.9, 55.7),
        },
        targets = {
            ped = 's_m_y_hardware_01',
            scenario = 'WORLD_HUMAN_STAND_IMPATIENT',
            distance = 2.5,
        },
    },
}

Stash System and Custom Containers

Stashes are persistent storage containers that players can access at specific locations. ox_inventory supports personal stashes tied to a player identifier, shared stashes accessible by anyone, and job-restricted stashes for police evidence rooms and hospital storage.

-- Server: Register a custom stash for a property
local function CreatePropertyStash(propertyId, owner)
    local stashId = ('property_%s'):format(propertyId)

    exports.ox_inventory:RegisterStash(
        stashId,
        ('Property #%s Storage'):format(propertyId),
        100,     -- slots
        200000,  -- max weight
        owner    -- owner identifier (or false for shared)
    )

    return stashId
end

-- Client: Open a stash when interacting with a storage point
RegisterNetEvent('myresource:openPropertyStorage', function(propertyId)
    local stashId = ('property_%s'):format(propertyId)
    exports.ox_inventory:openInventory('stash', stashId)
end)

Best Practices for ox_inventory Integration

  • Always validate server-side. Never trust client-side inventory checks. Use server exports like GetItemCount and RemoveItem for all critical game logic.
  • Use metadata sparingly. While metadata is powerful, storing excessive data on every item increases database size and network traffic. Only store what you actually need.
  • Handle full inventories gracefully. Always check the return value of AddItem and provide clear feedback to the player when their inventory is full.
  • Use item degrade for realism. The degrade property creates natural item sinks that keep your economy balanced. Set appropriate decay times for perishable goods and tools.
  • Leverage the built-in crafting system. Instead of building your own crafting logic, use ox_inventory crafting benches that handle checks, removal, and creation automatically.
  • Keep item images consistent. Place all item images in web/images/ with matching filenames. Use 100x100 PNG files with transparent backgrounds for the cleanest look.

Share this article

Ready to upgrade your server?

Check out our premium FiveM scripts in the Agency Scripts store or join our Discord community for support and updates.