# Exports & Commands

Every upstream ox_inventory export, event, callback and hook keeps working.
This page lists what Koja adds, how it changes upstream behaviour, and every command and keybind.

## New server exports

### getClothing

Returns the clothing a player wears.

```lua
local state = exports.ox_inventory:getClothing(source)
```

```lua title="Returns"
{
    enabled = true,
    gender = 'male',
    slots = {
        {
            key = 'torso', label = 'Torso', icon = 'layers', column = 'left',
            kind = 'component', id = 11,
            item = { name = 'clothing', slot = 7, metadata = { ... }, ... }, -- nil when empty
            wear = { drawable = 4, texture = 0, ... },                        -- what the ped wears
        },
        -- one entry per slot of clothing.slots
    },
}
```

### IsSlotLocked

`true` when the slot exists but needs a backpack.

```lua
if exports.ox_inventory:IsSlotLocked(source, slot) then
    -- do not put anything here
end
```

The first argument is anything `exports.ox_inventory:GetInventory` accepts (player id or inventory).

## New client exports

| Export | Returns | What it does |
| --- | --- | --- |
| `getClothingState()` | table | The local clothing state (same shape as `getClothing`) |
| `getStatus()` | `{ health, armor, hunger, thirst }` | Values 0–100, as shown in the clothes panel |
| `throwItem(slot)` | `{ ok, error? }` | Starts the aim of a throw for the item in that slot |
| `fastAction(id, data?)` | — | Runs a fast action: `handsup`, `undress`, `hanger`, `trade` |
| `requestTrade(serverId?, slot?)` | `{ ok, error? }` | Sends a trade request. Without `serverId`, to the closest player |

```lua title="Client"
-- open a trade with the closest player, offering slot 3
exports.ox_inventory:requestTrade(nil, 3)

-- undress the player
exports.ox_inventory:fastAction('undress')
```

## Upstream exports

All exports of ox_inventory 2.48.0 are unchanged. The ones you use most:

**Server:** `AddItem`, `RemoveItem`, `CanCarryItem`, `CanCarryAmount`, `CanCarryWeight`, `CanSwapItem`, `GetItem`, `GetItemCount`, `Search`, `GetSlot`, `GetSlotWithItem`, `GetSlotIdWithItem`, `GetSlotsWithItem`, `GetSlotIdsWithItem`, `GetEmptySlot`, `GetSlotForItem`, `SetMetadata`, `SetDurability`, `SetSlotCount`, `SetItem`, `SetMaxWeight`, `GetInventory`, `GetInventoryItems`, `GetInventories`, `GetContainerFromSlot`, `GetCurrentWeapon`, `RegisterStash`, `CreateTemporaryStash`, `RegisterShop`, `CustomDrop`, `CreateDropFromPlayer`, `ClearInventory`, `ConfiscateInventory`, `ReturnInventory`, `RemoveInventory`, `UpdateVehicle`, `SwapSlots`, `InspectInventory`, `forceOpenInventory`, `setPlayerInventory`, `registerHook`, `removeHooks`, `Items`, `ItemList`, `setContainerProperties`.

**Client:** `openInventory`, `closeInventory`, `openNearbyInventory`, `useItem`, `useSlot`, `getCurrentWeapon`, `setStashTarget`, `giveItemToTarget`, `Search`, `GetItemCount`, `GetPlayerItems`, `GetPlayerWeight`, `GetPlayerMaxWeight`, `GetSlotWithItem`, `GetSlotIdWithItem`, `GetSlotsWithItem`, `displayMetadata`, `notify`, `suppressItemNotifications`, `weaponWheel`, `setGetPlayerNameMethod`, `Items`, `ItemList`, `Keyboard`, `Progress`, `CancelProgress`, `ProgressActive`.

See the [ox_inventory documentation](https://overextended.dev/ox_inventory) for their arguments.

### What behaves differently

| Upstream API | Koja change |
| --- | --- |
| `AddItem`, `GetEmptySlot`, `GetSlotForItem`, `CanCarryItem` | Never use locked (backpack) slots of a player |
| Moving items (`swapItems`) | Moves into locked slots are rejected |
| Player max weight | `inventory:weight` + the weight of the worn backpack |
| Item use | Items marked **Hidden / disabled** in the admin panel cannot be used or created |
| Shops (`openInventory('shop', ...)`, `RegisterShop`) | Open the basket panel; `paymentMethods` and `interaction` are read from the shop definition |
| Crafting (`craftItem`) | Progress runs inside the crafting panel; never crafts into a locked slot |

## Events Koja listens to

| Event | Side | What happens |
| --- | --- | --- |
| `illenium-appearance:server:saveAppearance` | Server | Worn clothing items follow the saved appearance (`externalAppearance`) |
| `fivem-appearance:save` | Server | Same, for fivem-appearance |
| `illenium-appearance:client:reloadSkin` | Client | Clothing is synced again |
| `esx:onPlayerSpawn`, `QBCore:Client:OnPlayerLoaded`, `playerSpawned` | Client | Clothing is synced again after spawning |

:::hint{type="warning" title="Internal events"}
Events and callbacks starting with `ox_inventory:koja:` are used between the inventory's own client, server and UI.
The server re-checks every one of them, but they are not a public API and may change — use the exports above.
:::

## Commands

| Command | Who | What it does |
| --- | --- | --- |
| `/invadmin [page]` | Staff | Opens the [admin panel](/new/inventory/admin-panel). Name from `admin.command` |
| `/additem` (`/giveitem`) `[id] [item] [count] [type]` | `group.admin` | Gives an item |
| `/removeitem [id] [item] [count] [type]` | `group.admin` | Removes an item |
| `/setitem [id] [item] [count] [type]` | `group.admin` | Sets the item count |
| `/viewinv [invId]` | `group.admin` | Inspects an inventory read-only |
| `/clearinv [invId]` | `group.admin` | Wipes an inventory |
| `/takeinv [id]` | `group.admin` | Confiscates a player's inventory |
| `/restoreinv` (`/returninv`) `[id]` | `group.admin` | Gives a confiscated inventory back |
| `/saveinv [lock]` | `group.admin` | Saves all pending changes to the database |
| `/clearevidence [locker]` | Police boss | Clears an evidence locker |
| `/steal` | Everyone | Searches the nearest player (when allowed). Needs `inventory:enablestealcommand` |
| `convertinventory [esx\|esxproperty]` | Console | Upstream conversion of old ESX inventories |
| `clearActiveIdentifier [identifier]` | Console | Upstream workaround for a stuck inventory |

## Keybinds

All keybinds can be rebound by players in **Settings → Key Bindings → FiveM**. The default only applies to players who never changed it.

| Keybind | Default | What it does |
| --- | --- | --- |
| `inv` | F2 | Opens the inventory (`inventory:keys[1]`) |
| `inv2` | K | Opens the other inventory: trunk, dumpster, glovebox (`inventory:keys[2]`) |
| `hotbar` | TAB | Shows the hotbar (`inventory:keys[3]`) |
| `hotkey1` … `hotkey5` | 1 … 5 | Uses the item in pocket 1–5 |
| `reloadweapon` | R | Reloads the weapon |
| `koja_throw_weapon` | Middle mouse | Hold to aim and charge, release to throw the weapon in hand |
| `koja_trade_accept` | Y | Accepts a trade request (inventory closed) |
| `koja_trade_decline` | N | Declines a trade request (inventory closed) |
| `koja_invadmin` | none | Opens the admin panel. Registered only when `admin.key` is set |

While aiming a thrown item: **left mouse** throws, **right mouse** cancels (`throw.keys`).
