Skip to main content
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.
Config.Target = {
    System   = 'auto',      -- 'auto' | 'ox_target' | 'qb-target' | 'qtarget'
    Distance = 2.5,
    Icon     = 'fa-solid fa-car',
    Label    = 'Browse Vehicles',
}
SystemWhere it wires
ox_targetexports.ox_target:addLocalEntity(ped, { ... })
qb-targetexports['qb-target']:AddTargetEntity(ped, ...)
qtargetexports.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'.
Config.TextUI = {
    System   = 'auto',      -- 'auto' | 'ox_lib' | 'qb' | 'esx' | 'native'
    Key      = 38,          -- E
    KeyLabel = '[E]',
    Distance = 2.0,
    Position = 'right-center'  -- ox_lib only
}
SystemAdapter
ox_liblib.showTextUI / lib.hideTextUI
qbexports['qb-core']:DrawText
esxTriggerEvent('esx:showAdvancedNotification', ...)
nativeBuilt-in DrawText3D over the ped

Notifications

Config.Notify = {
    System          = 'auto',  -- 'auto' | 'ox_lib' | 'qb' | 'esx' | 'okok' | 'native' | 'custom'
    DefaultDuration = 4000,
    Position        = 'top',
}
SystemAdapter
ox_liblib.notify
qbQBCore:Notify event
esxesx:showNotification
okokokokNotify:Alert
nativeBeginTextCommandThefeedPost
For anything else, set Config.NotifyFn:
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.
Config.Keys = { System = 'auto' }
SystemHow keys are given
qb-vehiclekeysTriggerEvent('vehiclekeys:client:SetOwner', plate)
wasabi_carlockserver exports.wasabi_carlock:GiveKey(src, plate)
qs-vehiclekeysserver event qs-vehiclekeys:server:GiveKeys
mk_vehiclekeysclient exports['mk_vehiclekeys']:AddKey(vehicle), falls back to qb-vehiclekeys compat
t1ger_keysserver event t1ger_keys:addNew
jaksam (vehicles_keys)client event vehicles_keys:setOwner
noneDo nothing — useful when a paid script wires keys via DB triggers.
For a custom keys script:
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.
Config.Fuel = { System = 'none', SpawnLevel = 100 }   -- 0-100
SystemHow fuel is set
noneOnly the native fuel level is set.
ox_fuel / lj-fuelEntity(vehicle).state.fuel = level (statebag — the correct API for both).
LegacyFuelexports.LegacyFuel:SetFuel(vehicle, level)
cdn-fuelexports['cdn-fuel']:SetFuel(vehicle, level)
ps-fuelexports['ps-fuel']:SetFuel(vehicle, level)
rcore_fuelexports.rcore_fuel:setFuel(vehicle, level)
For anything else:
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.
Config.Garage = {
    DefaultGarage = 'pillboxgarage',
    State         = 1,    -- 1 = OUT (in the player's pocket), 0 = IN (parked)
}
FrameworkTarget tableCompatible garages
ESXowned_vehiclesesx_garage, esx_advancedgarage, wasabi_advgarage, cgarage, loaf_garage, brutal_advancedgarage, etc.
QBCoreplayer_vehiclesqb-garages, jg-advancedgarages, okokGarage, cd_garage, qs-advancedgarages, etc.
Qboxplayer_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:
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…):
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

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).