# Integration API Overview

# Integration API Overview

Public, versioned integration surface for trusted FiveM resources.

**Applies to:** `Nord Inventory v2.0.0`
# Nord Inventory — Integration API

Nord Inventory remains a Nord-native inventory. The public API intentionally uses familiar slot-inventory contracts so existing FiveM resources need minimal inventory-specific code.

## Typical migration

A resource that reads an item count can use:

```lua
local count = exports.nord_inventory:GetItemCount(source, 'water')
```

Slot lookup:

```lua
local slot = exports.nord_inventory:GetSlotWithItem(source, 'water', { type = 'clean' })
```

Search:

```lua
local count = exports.nord_inventory:Search(source, 'count', 'water')
local slots = exports.nord_inventory:Search(source, 'slots', 'water')
```

The same read-only search helpers are also available client-side for the local player's inventory:

```lua
local count = exports.nord_inventory:Search('count', 'water')
local items = exports.nord_inventory:GetPlayerItems()
```


## UI bridge exports

Notifications and world prompts are also exposed as a stable Nord gateway. The visual resources are selected only by name in `Config.Notify`, `Config.TextUI` and `Config.Target`; consuming resources do not need to know which notification/TextUI resource is installed.

Server:
- `Notify(source, message, kind?, duration?, title?)`
- `ShowTextUI(source, text, options?)`
- `HideTextUI(source)`
- `ShowTextUIEntry(source, id, data)`
- `HideTextUIEntry(source, id)`

Client:
- `Notify(message, kind?, duration?, title?)`
- `ShowTextUI(text, options?)`
- `HideTextUI()`
- `ShowTextUIEntry(id, data)`
- `HideTextUIEntry(id)`

See `docs/UI_BRIDGE.md` for the minimal resource-name configuration and bridge contracts.

## Server exports

Core catalogue and registry:
- `GetInventoryType()`
- `GetItemDefinition(name)`
- `GetItems()`
- `GetItemList()`
- `Items(itemName?)`
- `ItemList(itemName?)`
- `RegisterItem(name, definition, useHandler?, side?)`
- `RegisterItems(definitions)`
- `RegisterInventory(id, options)`
- `RegisterStash(id, label, slots, maxWeight, owner?, groups?, coords?)`

Inventory operations:
- `AddItem(inv, item, count, metadata?, slot?, cb?)`
- `RemoveItem(inv, item, count, metadata?, slot?, ignoreTotal?, strict?)`
- `CanCarryItem(inv, item, count, metadata?)`
- `CanCarryAmount(inv, item)`
- `CanCarryWeight(inv, weight)`
- `CanSwapItem(inv, firstItem, firstCount, testItem, testCount)`
- `ClearInventory(inv, keep?)`
- `RemoveInventory(inv)`
- `SetMaxWeight(inv, maxWeight)`
- `SetSlotCount(inv, slots)`

Read/search helpers:
- `GetInventory(inv, owner?)`
- `GetInventories(type?, detailed?)`
- `GetInventoryItems(inv, owner?)`
- `GetItem(inv, item, metadata?, returnsCount?)`
- `GetItemCount(inv, item, metadata?, strict?)`
- `GetItemSlots(inv, item, metadata?)`
- `GetSlot(inv, slot)`
- `GetSlotForItem(inv, item, metadata?)`
- `GetSlotWithItem(inv, item, metadata?, strict?)`
- `GetSlotsWithItem(inv, item, metadata?, strict?)`
- `GetSlotIdWithItem(inv, item, metadata?, strict?)`
- `GetSlotIdsWithItem(inv, item, metadata?, strict?)`
- `GetEmptySlot(inv)`
- `Search(inv, 'slots'|'count', item|string[], metadata?)`
- `SearchInventory(inv, 'slots'|'count', item|string[], metadata?)`

Metadata/use:
- `SetMetadata(inv, slot, metadata)`
- `GetMetadata(inv, slot)`
- `UpdateMetadata(inv, slot, patch)`
- `RegisterUsableItem(item, callback|export, side?)`
- `RegisterUseExport(item, export, side?)` / `RegisterUseExport(item, resource, export, side?)`
- `RegisterHook(name, callback)` / `registerHook(name, callback)`

## Inventory identifiers

Player inventories use the server id (`source`). Registered stashes can be addressed by their registered id. Full Nord keys such as `stash:police_armory`, `trunk:ABC123`, and `glovebox:ABC123` are also accepted when they exist.

Metadata strings are normalized to `{ type = value }`. The `strict` flag on slot/count helpers switches between exact metadata matching and partial matching.

## Runtime item registration with an external use export

Trusted server resources can register an item definition without editing `shared/items.lua` and can declare its external use handler in the same definition. A bare `client.export` or `server.export` name is automatically bound to the resource that called `RegisterItem`.

```lua
local ok, def = exports.nord_inventory:RegisterItem('service_token', {
    label = 'Service Token',
    description = 'Issued by another resource',
    weight = 5,
    stack = true,
    close = false,
    category = 'document',
    schema = 'generic',
    image = 'service_token.png',
    metadataDefaults = {
        issuer = '',
        issuedAt = 0
    },

    -- OX-style external use handler. Because the export name is bare,
    -- Nord resolves it as <calling_resource>:UseServiceToken.
    client = {
        export = 'UseServiceToken',
        remove = 0
    }
})

exports('UseServiceToken', function(item, slot)
    -- Return false to cancel the use transaction.
    return true
end)
```

For a server-side handler, use `server` instead of `client`:

```lua
server = {
    export = 'UseServiceToken',
    remove = 1
}

exports('UseServiceToken', function(source, item, slot, definition)
    return true
end)
```

### Important precedence rule

A runtime item **cannot overwrite an authoritative database row** with the same name. `RegisterItem` returns a failure such as `database_authoritative` in that case.

This protects Admin Studio/database definitions from being silently replaced by a third-party resource on restart.

### Runtime lifetime

`RegisterItem` is transient. If you need a definition to be permanently managed by Nord Inventory, create/import it into the database-backed registry or maintain it in the reference Lua files.

## External item use exports

Usable items can delegate their action to another resource while Nord remains responsible for inventory validation and optional removal. See `docs/EXTERNAL_ITEM_USE.md`.

```lua
-- Compact: UseRepairKit belongs to the resource calling this export.
exports.nord_inventory:RegisterUseExport('repair_kit', 'UseRepairKit', 'server')

-- Explicit resource form remains supported.
exports.nord_inventory:RegisterUseExport('repair_kit', 'my_mechanic', 'UseRepairKit', 'server')
```

Or register the definition and export in one call:

```lua
exports.nord_inventory:RegisterItem('repair_kit', {
    label = 'Repair Kit',
    weight = 500,
    use = {
        export = 'my_mechanic:UseRepairKit',
        side = 'server',
        remove = 1
    }
})
```

## Internal durability repair items

A registered item can use Nord's built-in server-authoritative durability repair effect instead of an external use export:

```lua
exports.nord_inventory:RegisterItem('pistol_cleaning_kit', {
    label = 'Pistol Cleaning Kit',
    weight = 200,
    stack = true,
    close = true,
    use = {
        duration = 3000,
        remove = 1,
        repair = {
            item = 'weapon_pistol',
            amount = 30
        }
    }
})
```

`repair.item` is the internal name of the target definition and `repair.amount` is the number of durability percentage points restored. Nord repairs the most damaged matching instance, never exceeds the target maximum, and only consumes the repair item when a repair was actually applied.

## Developer Ecosystem API

For provider-aware integrations, prefer the ecosystem APIs below. Full examples are in `docs/DEVELOPER_ECOSYSTEM.md`.

```lua
-- Feature detection / diagnostics
exports.nord_inventory:HasFeature('integration_manifest')
exports.nord_inventory:GetCapabilities()
exports.nord_inventory:GetRegisteredProvider('item_name')
exports.nord_inventory:GetProviderRegistry()
exports.nord_inventory:DebugItem('item_name')
exports.nord_inventory:GetHealthReport()

-- Full provider manifest
exports.nord_inventory:RegisterIntegration({ ... })
exports.nord_inventory:UnregisterIntegration()

-- Runtime ownership
exports.nord_inventory:UnregisterItem('item_name')
exports.nord_inventory:UnregisterItems({ 'item_one', 'item_two' })
exports.nord_inventory:UnregisterUseHandler('item_name')

-- Context-menu actions
exports.nord_inventory:RegisterItemAction('item_name', { ... })
exports.nord_inventory:UnregisterItemAction('item_name', 'action_id')
exports.nord_inventory:GetItemActions('item_name')

-- Metadata extensions
exports.nord_inventory:RegisterMetadataSchema('item_name', schema, display)
exports.nord_inventory:UnregisterMetadataSchema('item_name')
exports.nord_inventory:GetMetadataSchema('item_name')

-- Provider item images
exports.nord_inventory:RegisterItemImage('path/in/provider.png', 'item_name.png')

-- Item containers
exports.nord_inventory:OpenItemContainer(source, slot)
exports.nord_inventory:GetContainerInventory(source, slot)

-- Durability
exports.nord_inventory:GetDurability(source, slot)
exports.nord_inventory:SetDurability(source, slot, value)
exports.nord_inventory:AddDurability(source, slot, amount)
exports.nord_inventory:RemoveDurability(source, slot, amount)
exports.nord_inventory:RepairItem(source, slot, amount)
```

All provider mutation APIs above are server-side. Provider ownership is resolved from the resource calling the export.


### Hide player metadata details

```lua
exports['nord_inventory']:RegisterItem('example_item', {
    label = 'Example Item',
    weight = 100,
    hideMetadataDetails = true
})
```

`metadata.label` and `metadata.image` remain presentation fields and still affect
the visible item name/image. Other metadata remains available to scripts but is
not shown in the player's item-information metadata section.


### Register category + items in one call

```lua
exports['nord_inventory']:RegisterCategoryItems({
    name = 'mechanic_materials',
    label = 'Mechanic Materials',
    icon = 'fa-screwdriver-wrench',
    order = 80
}, {
    mech_sandpaper = { label = 'Sandpaper', weight = 150 },
    mech_primer = { label = 'Paint Primer', weight = 500 },
    mech_clearcoat = { label = 'Clear Coat', weight = 500 }
})
```

All item definitions inherit `mechanic_materials` automatically.

For multiple folders in the same resource:

```lua
exports['nord_inventory']:RegisterItemCatalog({
    mechanic_paint = {
        label = 'Paint Materials',
        icon = 'fa-spray-can-sparkles',
        items = {
            mech_basecoat = { label = 'Base Coat', weight = 500 }
        }
    },
    mechanic_tools = {
        label = 'Mechanic Tools',
        icon = 'fa-screwdriver-wrench',
        items = {
            mech_wrench = { label = 'Workshop Wrench', weight = 900 }
        }
    }
})
```

### Register categories

```lua
exports['nord_inventory']:RegisterCategory('restaurant_food', {
    label = 'Restaurant Food',
    icon = 'fa-utensils',
    order = 100
})
```

`RegisterCategory` is idempotent. Existing categories are reused.

A `RegisterIntegration` manifest can install `categories = { ... }` before its
`items = { ... }`, or an individual `RegisterItem` can use an inline category
table containing `name`, `label`, `icon`, and `order`.
