> ## Documentation Index
> Fetch the complete documentation index at: https://docs.nexdev.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Optional integrations

> Every external system the resource touches has an adapter in integrations/. All of them are escrow_ignore'd, so you can edit them without re-uploading the asset. Pick the system you want with…

Every external system the resource touches has an adapter in `integrations/`. All of them are `escrow_ignore`'d, so you can edit them without re-uploading the asset. Pick the system you want with `Config.<thing>.System`, or set it to `'auto'` and the resource picks the first installed one.

If your script isn't on the list, every adapter has a `Config.*Fn` override hook — point it at a function and the resource calls yours instead of the built-in branch.

## Target

Used for the salesperson eye-target. Auto-detected from the running resource list.

```lua theme={null}
Config.Target = {
    System   = 'auto',      -- 'auto' | 'ox_target' | 'qb-target' | 'qtarget'
    Distance = 2.5,
    Icon     = 'fa-solid fa-car',
    Label    = 'Browse Vehicles',
}
```

| System      | Where it wires                                   |
| ----------- | ------------------------------------------------ |
| `ox_target` | `exports.ox_target:addLocalEntity(ped, { ... })` |
| `qb-target` | `exports['qb-target']:AddTargetEntity(ped, ...)` |
| `qtarget`   | `exports.qtarget:AddTargetEntity(ped, ...)`      |

Force textui (no target) by setting `Config.Interaction = 'textui'`.

## TextUI

The proximity `[E]` hint, used when target isn't available or `Config.Interaction = 'textui'`.

```lua theme={null}
Config.TextUI = {
    System   = 'auto',      -- 'auto' | 'ox_lib' | 'qb' | 'esx' | 'native'
    Key      = 38,          -- E
    KeyLabel = '[E]',
    Distance = 2.0,
    Position = 'right-center'  -- ox_lib only
}
```

| System   | Adapter                                             |
| -------- | --------------------------------------------------- |
| `ox_lib` | `lib.showTextUI` / `lib.hideTextUI`                 |
| `qb`     | `exports['qb-core']:DrawText`                       |
| `esx`    | `TriggerEvent('esx:showAdvancedNotification', ...)` |
| `native` | Built-in `DrawText3D` over the ped                  |

## Notifications

```lua theme={null}
Config.Notify = {
    System          = 'auto',  -- 'auto' | 'ox_lib' | 'qb' | 'esx' | 'okok' | 'native' | 'custom'
    DefaultDuration = 4000,
    Position        = 'top',
}
```

| System   | Adapter                       |
| -------- | ----------------------------- |
| `ox_lib` | `lib.notify`                  |
| `qb`     | `QBCore:Notify` event         |
| `esx`    | `esx:showNotification`        |
| `okok`   | `okokNotify:Alert`            |
| `native` | `BeginTextCommandThefeedPost` |

For anything else, set `Config.NotifyFn`:

```lua theme={null}
Config.NotifyFn = function(title, message, kind, duration)
    -- kind: 'inform' | 'success' | 'error' | 'warning'
    exports.my_notify:show(title, message, kind, duration)
end
```

The legacy `Config.NotifyLegacy = function(...)` form from older versions still works — the bridge unwraps it at runtime.

## Vehicle keys

Hands the new vehicle's keys to the player after purchase.

```lua theme={null}
Config.Keys = { System = 'auto' }
```

| System                     | How keys are given                                                                      |
| -------------------------- | --------------------------------------------------------------------------------------- |
| `qb-vehiclekeys`           | `TriggerEvent('vehiclekeys:client:SetOwner', plate)`                                    |
| `wasabi_carlock`           | server `exports.wasabi_carlock:GiveKey(src, plate)`                                     |
| `qs-vehiclekeys`           | server event `qs-vehiclekeys:server:GiveKeys`                                           |
| `mk_vehiclekeys`           | client `exports['mk_vehiclekeys']:AddKey(vehicle)`, falls back to qb-vehiclekeys compat |
| `t1ger_keys`               | server event `t1ger_keys:addNew`                                                        |
| `jaksam` (`vehicles_keys`) | client event `vehicles_keys:setOwner`                                                   |
| `none`                     | Do nothing — useful when a paid script wires keys via DB triggers.                      |

For a custom keys script:

```lua theme={null}
Config.KeyFn = function(vehicle, plate, model)
    exports.my_keys:give(plate)
end
```

The legacy `Config.KeyExport = function(...)` form from older versions still works.

## Fuel

Sets the spawn fuel level on the new vehicle.

```lua theme={null}
Config.Fuel = { System = 'none', SpawnLevel = 100 }   -- 0-100
```

| System                | How fuel is set                                                             |
| --------------------- | --------------------------------------------------------------------------- |
| `none`                | Only the native fuel level is set.                                          |
| `ox_fuel` / `lj-fuel` | `Entity(vehicle).state.fuel = level` (statebag — the correct API for both). |
| `LegacyFuel`          | `exports.LegacyFuel:SetFuel(vehicle, level)`                                |
| `cdn-fuel`            | `exports['cdn-fuel']:SetFuel(vehicle, level)`                               |
| `ps-fuel`             | `exports['ps-fuel']:SetFuel(vehicle, level)`                                |
| `rcore_fuel`          | `exports.rcore_fuel:setFuel(vehicle, level)`                                |

For anything else:

```lua theme={null}
Config.FuelFn = function(vehicle, level)
    exports.my_fuel:set(vehicle, level)
end
```

## Garage / persistence

Writes the new vehicle to whichever table the framework expects. Any garage script that reads from that table picks it up automatically — there is no per-garage API to call.

```lua theme={null}
Config.Garage = {
    DefaultGarage = 'pillboxgarage',
    State         = 1,    -- 1 = OUT (in the player's pocket), 0 = IN (parked)
}
```

| Framework | Target table                                                                                                    | Compatible garages                                                                                              |
| --------- | --------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------- |
| ESX       | `owned_vehicles`                                                                                                | `esx_garage`, `esx_advancedgarage`, `wasabi_advgarage`, `cgarage`, `loaf_garage`, `brutal_advancedgarage`, etc. |
| QBCore    | `player_vehicles`                                                                                               | `qb-garages`, `jg-advancedgarages`, `okokGarage`, `cd_garage`, `qs-advancedgarages`, etc.                       |
| Qbox      | `player_vehicles` via `exports.qbx_vehicles:CreatePlayerVehicle` when present, else the QB-style direct insert. |                                                                                                                 |

`DefaultGarage` just needs to be a garage name that exists in your garage script's config. For non-standard schemas:

```lua theme={null}
Config.GiveVehicleFn = function(source, player, model, plate, ctx)
    -- ctx = { garage, state, dealership }
    -- Return true to short-circuit the built-in DB insert.
    return MyGarage.Give(player, model, plate, ctx)
end
```

The ESX writer tries three insert shapes in order — wide schema, `stored`-only, then bare-minimum — so most ESX garages work without a custom hook.

## Custom purchase gate

To gate buying on a custom condition (an in-game licence item, a Discord role, a quest flag…):

```lua theme={null}
Config.CanPurchaseFn = function(source, dealershipKey, vehicle)
    local hasLicence = exports.ox_inventory:Search(source, 'count', 'driver_licence') > 0
    if not hasLicence then
        return false, "You don't have a driver's licence."
    end
    return true
end
```

The second return value is shown to the player as an error toast.

## Custom plate generator

```lua theme={null}
Config.PlateFn = function()
    return string.format('NEX%05d', math.random(0, 99999))
end
```

Overrides the built-in plate generator (which uses `Config.Purchase.PlatePrefix`, `PlateLength`, and `UpperPlate`).
