Nord Vehicle Keys Official Nord Lab documentation for Nord Vehicle Keys. Covers installation, strict physical keys, vehicle locking, theft systems, stolen-key expiry, recovery NPCs, ghost placement, bridges, developer exports, database, security and troubleshooting. 1 · Getting Started Install Nord Vehicle Keys, understand its core concepts and verify a clean first boot. Overview Nord Vehicle Keys is a server-authoritative vehicle access system for FiveM. It combines physical vehicle keys, vehicle locking, theft gameplay, temporary stolen keys, recovery NPCs and a modular bridge layer for frameworks, inventories and UI providers. Main features Physical vehicle_key items with plate metadata. Server-authoritative lock state using entity state bags. Lock / unlock from keybind, commands or the physical-key remote. Permanent owner keys, shared keys, temporary keys and stolen/session keys. Carjacking of NPC drivers by aiming a valid firearm. Lockpick and hotwire flows with configurable difficulty and alarm chances. Stolen-key expiry when leaving the stolen vehicle plus a safety timeout. Persistent key-recovery NPCs for owned vehicles. In-game admin panel for recovery NPC management. Ghost NPC placement editor with movement, rotation, height and ground snapping. Framework, inventory, notification and Text UI bridges isolated from the core. Server exports for garages, dealerships, rentals and other trusted resources. Design principle Normal access is intentionally strict when physical keys are enabled: If the player no longer has the matching physical key item, the resource does not silently recreate it during an access check. A missing owner key must be deliberately reissued through the recovery NPC, an admin action or a trusted server export. Requirements & Installation Requirements Requirement Status FiveM server Required OneSync Required for authoritative entity checks oxmysql Required when persistence/ownership tables are used QBCore / QBX / ESX Optional nord_inventory Recommended for native physical-key metadata ox_inventory Supported for generic item checks ox_lib Optional notification/Text UI provider Resource installation Copy the folder as nord_vehiclekeys into your resources directory. Start the database resource first. Start your framework and inventory before Nord Vehicle Keys. Add the recovery admin ACE if staff will manage recovery NPCs. Ensure the resource. ensure oxmysql ensure qb-core # or qbx_core / es_extended when used ensure nord_inventory # recommended for physical vehicle_key items ensure nord_vehiclekeys Recovery admin permission: add_ace group.admin nord.vehiclekeys.admin allow Database Auto SQL is enabled by default. The resource creates and validates its own tables at startup. For a manual install, import: sql/install.sql First Boot Checklist After installation, verify these points before opening the server to players. oxmysql is started before Nord Vehicle Keys. The selected framework bridge is detected correctly. The selected inventory bridge is available. OneSync is enabled. No SQL or Lua errors appear during resource startup. The vehicle_key item is registered when Nord Inventory auto-registration is enabled. /vehiclekeysadmin opens for an ACE-authorized admin. Lock/unlock works on an owned test vehicle. Removing the physical owner key removes normal access when strict physical-key mode is enabled. Recovering that key through a recovery NPC reissues access correctly. Recommended start order ensure oxmysql ensure your_framework ensure nord_inventory ensure nord_vehiclekeys If you use another inventory, replace nord_inventory with that resource and configure the Inventory bridge accordingly. Resource Structure The resource is intentionally split so integrations can be changed without editing the core logic. nord_vehiclekeys/ ├─ config/ │ ├─ bridges.lua │ └─ main.lua ├─ client/ │ ├─ bridge/ │ │ ├─ framework.lua │ │ ├─ inventory.lua │ │ ├─ notify.lua │ │ ├─ textui.lua │ │ └─ minigame.lua │ ├─ main.lua │ ├─ theft.lua │ ├─ stolen.lua │ ├─ placement.lua │ └─ recovery.lua ├─ server/ │ ├─ bridge/ │ │ ├─ framework.lua │ │ ├─ inventory.lua │ │ ├─ notify.lua │ │ ├─ textui.lua │ │ ├─ ownership.lua │ │ └─ nord_inventory_registration.lua │ ├─ api.lua │ ├─ main.lua │ ├─ stolen.lua │ ├─ recovery.lua │ └─ storage.lua ├─ shared/ ├─ locales/ ├─ web/ └─ sql/ For normal compatibility work, edit the appropriate file under client/bridge/ or server/bridge/ instead of changing main.lua. 2 · Configuration Configure key behaviour, vehicle state, sharing, recovery, theft systems and persistence. Core Configuration The primary configuration file is: config/main.lua Common options: Config.Debug = false Config.Locale = 'en' Config.Keybinds = { Lock = 'L', Hotwire = 'H' } Distances are controlled separately: Config.Distances = { ToggleLock = 18.0, Action = 7.0, Share = 7.0, Ensure = 35.0 } Vehicle state Config.VehicleState = { OwnedVehiclesSpawnLocked = true, NPCVehiclesSpawnLockedChance = 65, NPCLocksPlayerOnly = true, NPCKeysInsideChance = 15, } NPCLocksPlayerOnly keeps ambient NPC traffic usable by GTA AI while still enforcing the logical player-facing lock state. Physical Keys Physical-key behaviour is configured under Config.PhysicalKeys. Config.PhysicalKeys = { Enabled = true, Item = 'vehicle_key', SyncWithAccess = true, ItemGrantsAccess = true, RequirePhysicalItemForAccess = true, OwnerAccessWithoutPhysicalItem = false, StoredAccessWithoutPhysicalItem = false, AllowClientOwnerClaim = false, IssueForJobAccess = false, } Strict mode behaviour With the default strict settings: A physical key is authoritative for normal owner/shared access. Deleting or losing the item removes that physical access. Ownership alone does not silently recreate a missing key. A client cannot claim an owner key simply because it is near an owned vehicle. Trusted server resources should intentionally call GiveKeys when issuing a new key. This prevents accidental unlimited key regeneration. Remote Configuration Using a physical vehicle_key can open the built-in vehicle remote. Config.PhysicalKeys.Remote = { Enabled = true, Range = 25.0, RefreshMs = 250, AllowTrunk = true, CloseOnAction = false, TrunkDoors = {}, } The remote supports: Lock Unlock Open/close supported trunk Live in-range status Plate display The remote closes with ESC. Its NUI is transparent while closed and does not create a fullscreen dark overlay. TrunkDoors can be used to explicitly map unusual/front-trunk vehicles to a door index. Sharing & Job Access Key sharing Config.ShareKeys = { Enabled = true, AllowReshare = false, DefaultDurationSeconds = 3600, PersistTemporaryKeys = true, } Player commands: /givekey [server id] /revokekey [server id] The player must use the current vehicle or a nearby vehicle within the configured share distance. Job access Job access is empty by default to avoid unintended fleet access. Example: Config.JobAccess.police = { minGrade = 0, requireDuty = true, platePrefixes = { 'LSPD', 'POL' }, models = { 'police', 'police2', 'police3' } } Job access can stay virtual so shared fleet vehicles do not generate large numbers of physical key items. Persistence & Ownership Persistence Config.Persistence = { Enabled = true, Resource = 'oxmysql', AutoInstall = true, QueryTimeoutMs = 10000, StartupTimeoutMs = 60000, RetryIntervalMs = 1000, PersistPermanentSharedKeys = true, PersistTemporaryKeys = true, } Ownership tables Default ownership mappings: Config.Ownership.QB = { table = 'player_vehicles', ownerColumn = 'citizenid', plateColumn = 'plate', vehicleColumn = 'vehicle', } Config.Ownership.ESX = { table = 'owned_vehicles', ownerColumn = 'owner', plateColumn = 'plate', vehicleColumn = 'vehicle', } QBX uses the same default player_vehicles layout as QB. For a custom garage schema, either change the configured table/columns or enable custom ownership and implement the ownership bridge. 3 · Vehicle Keys & Locking Understand key types, lock state and the built-in player commands. Key Types Nord Vehicle Keys uses different key types for different access lifecycles. Key type Typical use Persistence owner Player-owned vehicle Permanent shared Shared access Permanent or timed temporary Rentals/scripts Timed session Stolen/NPC vehicle Temporary session admin Administrative grant Permanent until removed When a physical key item is issued, metadata includes at least: { plate = 'ABC123', keyType = 'owner', expiresAt = 0, sessionToken = '' } Session keys use a session token that is validated server-side and cannot be reused by another player connection. Locking Controls Default lock controls: L Toggle current/nearest vehicle lock /vehiclelock Toggle current/nearest vehicle lock /lockvehicle Lock current/nearest vehicle /unlockvehicle Unlock current/nearest vehicle The lock key is configurable through Config.Keybinds.Lock and FiveM key mappings. Lock state is synchronized using server-controlled vehicle state bags. This allows all clients to apply the same logical lock state while the server remains authoritative for access validation. Admin Key Commands Administrative key commands require the ACE configured in Config.Security.AdminAce. Default ACE: add_ace group.admin nord.vehiclekeys.admin allow Commands: /adminkey [server id] [plate] /adminkeyremove [server id] [plate] /adminkey issues administrative access and synchronizes the matching physical key item when physical keys are active. /adminkeyremove removes stored access and the matching physical key item. 4 · Theft & Stolen Keys Configure and operate carjacking, lockpick, hotwire and stolen-key cleanup. Carjacking Carjacking can start automatically when a player holds aim on an NPC driver with an allowed firearm. Config.Carjacking = { Enabled = true, AimHoldMs = 850, DurationMs = 3200, CooldownMs = 10000, GiveKeysOnSuccess = true, SuccessChance = 100, AlarmChance = 35, RequireWeapon = true, } The NPC/vehicle action is reserved and validated server-side. The finish step validates the reserved vehicle, plate, action token, timing and distance without depending on volatile NPC network ownership. Blocked melee, utility and throwable weapons can be configured through Config.Carjacking.BlockedWeapons. Lockpick Lockpick configuration: Config.Lockpick = { Enabled = true, Item = 'lockpick', DurationMs = 6500, Difficulty = 4, BreakChanceOnFail = 35, AlarmChanceOnFail = 70, AlarmChanceOnSuccess = 15, GiveKeysWhenKeysFoundInside = true, } The configured inventory bridge validates and removes the item when required. Command: /lockpick Developer client export: exports.nord_vehiclekeys:StartLockpick(vehicle) Hotwire Hotwire configuration: Config.Hotwire = { Enabled = true, Item = nil, DurationMs = 9000, Difficulty = 6, FailCooldownMs = 3500, AlarmChanceOnFail = 65, AlarmChanceOnSuccess = 20, } Set Item to an item name if a hotwire kit should be required. When nil, no item is required. Command: /nordkeys_hotwire Developer client export: exports.nord_vehiclekeys:StartHotwire(vehicle) Stolen Key Lifecycle Keys obtained through NPC theft, lockpick-found-keys or hotwire are temporary stolen/session keys. Config.StolenKeys = { RemoveOnVehicleExit = true, MaxDurationSeconds = 900, ExitGraceMs = 1200, ServerCheckMs = 750, } Default behaviour: The stolen key is issued for the specific vehicle. The player can use the vehicle normally while the stolen key is valid. After the player enters the vehicle and later exits it, the stolen key is revoked. The physical vehicle_key item for that stolen access is removed. A safety timeout removes abandoned session keys even if the player never enters the vehicle. Permanent owner/shared/admin keys are not removed by the stolen-key cleanup flow. Blocked Vehicle Classes The theft system can block GTA vehicle classes and models. Default blocked classes: Config.Theft.BlockedClasses = { [14] = true, -- boats [15] = true, -- helicopters [16] = true, -- planes [18] = true, -- emergency [19] = true, -- military [21] = true, -- trains } Specific models can also be blocked: Config.Theft.BlockedModels = { 'rhino', } 5 · Recovery NPC & Placement Manage persistent recovery NPCs and use the ghost placement editor. Recovery Service The recovery NPC allows players to reissue a lost physical owner key for a vehicle the server confirms they own. It does not grant keys for arbitrary plates. Recovery flow: Player approaches a configured recovery NPC. The NPC UI requests the player's owned vehicles from the server. Ownership is read from the configured framework vehicle table/custom ownership bridge. Player selects a vehicle. Ownership is validated again server-side. A permanent owner key and physical vehicle_key item are issued. Configuration: Config.Recovery = { Enabled = true, AdminCommand = 'vehiclekeysadmin', AdminAce = 'nord.vehiclekeys.admin', DefaultModel = 's_m_m_autoshop_01', DefaultLabel = 'Vehicle Key Service', DefaultScenario = 'WORLD_HUMAN_CLIPBOARD', InteractDistance = 2.2, StreamDistance = 90.0, Fee = 0, } Recovery Admin Panel Open the recovery NPC admin panel with: /vehiclekeysadmin Required ACE: add_ace group.admin nord.vehiclekeys.admin allow The panel is in-game only and can be used to: Create recovery NPCs. Edit label/model/scenario. Move an existing NPC. Enter the visual placement editor. Delete recovery NPCs. Recovery NPCs are persisted in the database and respawn after resource/server restarts. Ghost Placement Editor Creating or editing a recovery NPC can open the visual placement editor. The preview NPC is transparent, non-colliding and frozen while being positioned. Controls Control Action W A S D Move relative to camera Left mouse Drag ghost toward the point under the cursor/raycast Arrow Up / Down Raise / lower Arrow Left / Right Rotate Q / E Rotate SHIFT Fast movement/rotation CTRL Precision movement G Snap to ground F Move to raycast point R Face camera direction ENTER Confirm and save ESC / BACKSPACE Cancel Placement configuration: Config.Recovery.Placement = { Enabled = true, GhostAlpha = 145, StartDistance = 2.0, MoveStep = 0.035, VerticalStep = 0.025, RotateStep = 1.0, FastMultiplier = 4.0, PrecisionMultiplier = 0.25, RaycastDistance = 25.0, MaxDistanceFromAdmin = 35.0, SnapToGroundOnStart = true, DrawMarker = true, } The saved X/Y/Z/heading from the ghost is authoritative for the final NPC. The final spawn does not perform a second destructive ground snap. 6 · Bridges & Compatibility Keep custom integrations isolated from the core by using the bridge layer. Bridge Architecture Bridge selection lives in: config/bridges.lua Config.Bridges = { Framework = 'auto', -- auto | qb | qbx | esx | standalone | custom Inventory = 'auto', -- auto | nord | ox | qb | esx | custom Notify = 'auto', -- auto | ox | qb | esx | gta | custom TextUI = 'auto', -- auto | ox | gta | custom } For a custom resource: Set the relevant bridge to custom. Edit only the matching bridge file. Return the values expected by the bridge contract. Leave the core resource logic unchanged. This keeps updates easier because custom integrations stay isolated. Framework Bridge Framework bridge files: client/bridge/framework.lua server/bridge/framework.lua Auto-detection order: qbx_core qb-core es_extended standalone fallback The server bridge provides: Framework detection. Player lookup. Stable identifier lookup. Job lookup. Grade normalization. Duty state handling. Custom integration hooks: NVKServerBridge.CustomGetPlayer(source) NVKServerBridge.CustomGetIdentifier(source) NVKServerBridge.CustomGetJob(source) NVKClientBridge.CustomGetJob() Return your framework's normal player/job objects in those hooks. Inventory Bridge Inventory bridge files: client/bridge/inventory.lua server/bridge/inventory.lua Generic item checks support: Nord Inventory ox_inventory QB/QBX inventory through the framework player object ESX inventory Custom implementation Native physical vehicle keys The full physical vehicle_key metadata flow is native to nord_inventory. Custom inventory hooks are provided for complete physical-key support: NVKInventory.CustomHasItem(source, item, count) NVKInventory.CustomRemoveItem(source, item, count) NVKInventory.CustomHasVehicleKeyItem(source, plate) NVKInventory.CustomResolveVehicleKeyMetadata(source, slot) NVKInventory.CustomGiveVehicleKeyItem(source, plate, keyType, expiresAt, sessionBound) NVKInventory.CustomRemoveVehicleKeyItem(source, plate) NVKInventory.CustomCleanupInvalidVehicleKeyItems(source) Client custom count hook: NVKClientInventory.CustomGetItemCount(item, metadata) If you use a custom inventory with strict physical keys, implement the physical-key hooks rather than modifying the core. Notifications & Text UI Notification and Text UI are independent bridges. Files: client/bridge/notify.lua server/bridge/notify.lua client/bridge/textui.lua server/bridge/textui.lua Supported notification modes: auto | ox | qb | esx | gta | custom Supported Text UI modes: auto | ox | gta | custom Custom notification hook: function NVKNotify.Custom(message, kind, duration, title) -- show your notification return true end Custom Text UI hooks: function NVKTextUI.CustomShow(id, text, options) -- show your UI return true end function NVKTextUI.CustomHide(id) -- hide your UI return true end The recovery interaction uses this bridge instead of hardcoded GTA help text. Custom Ownership Bridge Ownership is isolated in: server/bridge/ownership.lua For custom ownership logic: Config.Ownership.Custom = true Implement: function NVKOwnership.CustomGetOwnerIdentifier(plate) -- Return the framework identifier that owns this plate. end For the recovery UI, you can also implement: function NVKOwnership.CustomGetOwnedVehicles(source, identifier) return { { plate = 'ABC123', model = 'sultan' }, { plate = 'XYZ987', model = 'adder' }, } end Trusted standalone/garage resources can set a runtime owner through the SetVehicleOwner server export. 7 · Developer API Integrate garages, dealerships, rentals and other server resources through stable exports. Server Key Exports Key creation and removal should be performed from trusted server-side resources. Recommended simple API -- Permanent owner key + physical key item. exports.nord_vehiclekeys:GiveKeys(source, plate) -- Remove access/key for the plate. exports.nord_vehiclekeys:RemoveKeys(source, plate) -- Check access. local hasKey, keyType, expiresAt = exports.nord_vehiclekeys:HasKeys(source, plate) Aliases: exports.nord_vehiclekeys:AddKey(source, plate) exports.nord_vehiclekeys:DeleteKey(source, plate) exports.nord_vehiclekeys:GiveOwnerKey(source, plate) Shared and temporary keys: exports.nord_vehiclekeys:GiveSharedKey(source, plate, 0) -- permanent shared exports.nord_vehiclekeys:GiveSharedKey(source, plate, 3600) -- timed shared exports.nord_vehiclekeys:GiveTempKey(source, plate, 900) -- temporary Advanced API: exports.nord_vehiclekeys:GiveKey(source, plate, 'owner', 0) exports.nord_vehiclekeys:GiveKey(source, plate, 'shared', 3600) exports.nord_vehiclekeys:GiveTemporaryKey(source, plate, 900) exports.nord_vehiclekeys:RemoveKey(source, plate) exports.nord_vehiclekeys:HasKey(source, plate) Physical Key Item Exports These exports work directly with the physical key item layer. exports.nord_vehiclekeys:GivePhysicalKeyItem(source, plate, 'owner', 0) exports.nord_vehiclekeys:RemovePhysicalKeyItem(source, plate) exports.nord_vehiclekeys:HasPhysicalKeyItem(source, plate) Normally, use GiveKeys / RemoveKeys instead because they keep permission state and the physical item synchronized. Use the physical-item exports only when you deliberately need low-level control. Server Vehicle Exports Vehicle state exports operate on a network ID. exports.nord_vehiclekeys:SetLockState(netId, true) exports.nord_vehiclekeys:GetLockState(netId) exports.nord_vehiclekeys:ToggleLock(netId) exports.nord_vehiclekeys:LockVehicle(netId) exports.nord_vehiclekeys:UnlockVehicle(netId) exports.nord_vehiclekeys:RegisterOwnedVehicle(netId) exports.nord_vehiclekeys:SetVehicleOwner(netId, identifier) RegisterOwnedVehicle is useful after spawning a framework-owned vehicle so the resource can initialize its authoritative state. SetVehicleOwner creates a runtime ownership override for trusted custom/standalone integrations. Client Exports Client exports are useful for UI, vehicle interactions and custom gameplay. local hasKey = exports.nord_vehiclekeys:HasKey(vehicleOrPlate) local hasLocal = exports.nord_vehiclekeys:HasLocalKey(vehicleOrPlate) exports.nord_vehiclekeys:ToggleLock(vehicle) exports.nord_vehiclekeys:LockVehicle(vehicle) exports.nord_vehiclekeys:UnlockVehicle(vehicle) local vehicle, distance = exports.nord_vehiclekeys:GetClosestVehicle(10.0) exports.nord_vehiclekeys:OpenKeyRemote(slot) The theft module also exposes: exports.nord_vehiclekeys:StartLockpick(vehicle) exports.nord_vehiclekeys:StartHotwire(vehicle) exports.nord_vehiclekeys:StartCarjack(vehicle, driver) Physical item-use handlers are also exposed internally for inventory integration, but normal external resources should use the higher-level key exports. Garage Integration A garage that spawns a player's owned vehicle should register the entity and only issue a key when the garage intentionally wants to hand one to the player. Server example: local netId = NetworkGetNetworkIdFromEntity(vehicle) exports.nord_vehiclekeys:RegisterOwnedVehicle(netId) exports.nord_vehiclekeys:GiveKeys(source, plate) If the garage stores the vehicle and should remove the currently issued key: exports.nord_vehiclekeys:RemoveKeys(source, plate) Do not create an insecure client event that accepts an arbitrary source and plate and forwards them directly to GiveKeys. Dealership Integration When a player purchases a vehicle, issue the key after the purchase and ownership transaction succeeds. -- purchase validated, money removed and ownership row saved first exports.nord_vehiclekeys:GiveKeys(source, plate) When a dealership sells/transfers/removes a vehicle from a player, remove the old holder's key deliberately: exports.nord_vehiclekeys:RemoveKeys(oldOwnerSource, plate) If the new owner is online: exports.nord_vehiclekeys:GiveKeys(newOwnerSource, plate) This keeps physical key ownership explicit and avoids silent regeneration. Rental Integration Rental scripts should normally use temporary keys. Example 30-minute rental: exports.nord_vehiclekeys:GiveTempKey(source, plate, 1800) When the rental ends early: exports.nord_vehiclekeys:RemoveKeys(source, plate) For a shared company vehicle with a known duration: exports.nord_vehiclekeys:GiveSharedKey(source, plate, 3600) Choose temporary for a short-lived one-player rental and shared when the semantics are intentionally shared access. 8 · Database, Security & Troubleshooting Operate the resource safely in production and resolve the most common installation issues. Database Schema Auto SQL creates the resource schema automatically when persistence is enabled. Core tables: nord_vehiclekeys_keys Stores persisted key grants: plate holder identifier key type expiry timestamp created/updated timestamps nord_vehiclekeys_recovery_npcs Stores persistent recovery NPC placement and appearance: label ped model scenario X/Y/Z heading creator identifier nord_vehiclekeys_schema Tracks internal database schema revisions. This is a database schema number, not the resource release number. Manual SQL is included at: sql/install.sql Security Model Nord Vehicle Keys is designed around server authority. Important protections OneSync entity checks are required by default. Lock state is synchronized through entity state bags. Key grants/removals are validated server-side. Physical key metadata is re-read from the authoritative inventory slot. Session/stolen keys are bound to the player connection/session token. Carjacking actions use server-side action reservation and validation. Ownership lookup is server-side. Recovery keys are only issued after ownership validation. Admin actions use ACE permission checks. Sensitive compatibility events are disabled by default. Callback/action rate limits reduce spam and replay abuse. Trusted export rule Exports such as GiveKeys should only be called by trusted server resources after that resource has validated its own business logic. Production Checklist Before production deployment: OneSync enabled. Database backups available. oxmysql starts before Nord Vehicle Keys. Framework bridge detected correctly. Inventory bridge selected correctly. vehicle_key definition is non-stackable when using Nord Inventory. Recovery ACE configured only for staff who need it. Ownership table/columns match your framework schema. Custom bridge code returns valid values and does not trust arbitrary client payloads. Test owner key issue/removal. Test player key sharing and revocation. Test stolen key removal after exiting the vehicle. Test recovery NPC key reissue. Test ghost placement cancel/confirm. Test lock state with multiple players nearby. Common Issues Physical key exists but does not open the remote Check that: nord_inventory starts before nord_vehiclekeys. The vehicle_key item is non-stackable. The slot metadata contains a normalized plate. The key is not expired. The physical-key item use handler is registered. Player keeps getting a key back after deleting it Strict physical-key mode should use: RequirePhysicalItemForAccess = true OwnerAccessWithoutPhysicalItem = false StoredAccessWithoutPhysicalItem = false AllowClientOwnerClaim = false A missing key should then only return through recovery/admin/trusted server exports. Recovery NPC is underground Use the visual placement editor and save the final position. The saved Z is authoritative and the final NPC should not run a second ground snap. Recovery NPC is stuck in a broken scenario pose Use a valid GTA scenario name. The resource applies the scenario without a destructive intro sequence and freezes the NPC after the final placement is applied. Fullscreen dark NUI overlay The key remote NUI should be transparent and hidden while closed. If you replaced the web files, ensure html and body do not force a dark background or color-scheme: dark. "The action is no longer valid" during carjacking Make sure all resource files are from the same build and that OneSync is enabled. The carjack completion validates the reserved vehicle/action rather than relying on the NPC remaining in the same network seat state. Bridge Troubleshooting Framework not detected Force the bridge in config/bridges.lua: Config.Bridges.Framework = 'qb' -- or qbx / esx / standalone / custom Inventory not detected Force the bridge: Config.Bridges.Inventory = 'nord' -- or ox / qb / esx / custom If Config.Inventory.Strict = true, item-requiring actions are denied when no bridge can validate the item. Custom notification not showing Set: Config.Bridges.Notify = 'custom' and make NVKNotify.Custom(...) return true after showing the notification. Custom Text UI not hiding Both custom hooks must be implemented: NVKTextUI.CustomShow(...) NVKTextUI.CustomHide(...) Return true when the action was handled. FAQ Does owning a vehicle automatically recreate a deleted key? No, not with the default strict physical-key settings. The player must recover or be explicitly issued a new key. Can I use the resource without Nord Inventory? Yes for generic access/item checks through supported bridges. The complete physical vehicle_key metadata workflow is native to Nord Inventory; a custom inventory can implement the provided physical-key hooks. Can a player recover a key for a vehicle they do not own? No. Recovery validates ownership server-side before issuing the key. Do stolen keys stay forever? No. They are designed to expire when the player leaves the stolen vehicle and also have a safety timeout. Can a garage or dealership give keys? Yes. Use the trusted server export: exports.nord_vehiclekeys:GiveKeys(source, plate) Can I replace notifications or Text UI without editing the core? Yes. Select custom in config/bridges.lua and edit only the matching bridge file. Is the recovery NPC placement persistent? Yes. NPC definitions and coordinates are stored in the database.