Documentation

Pepper Keys

Vehicle keys as real items with ox_inventory – whoever holds the key drives the car. With locksmith, lock changes and hotwiring.

Overview

Pepper Keys turns the vehicle key into a real item. Whoever has the key in their inventory unlocks the car and starts the engine, even if they stole it. The owner without a key gets nowhere. Stolen? Change the lock at the locksmith and all old keys are worthless. Without a key, only hotwiring is left, with a minigame, a tool and an alarm.

Only player vehicles are locked. Vehicles from job scripts stay free to drive, you do not need to change anything there.

  • Key as an ox_inventory item with plate and vehicle name
  • Changing the lock makes old keys worthless, spare keys at the locksmith
  • Hotwiring with minigame, tool, alarm and difficulty per vehicle class
  • Works with any garage script that uses the framework vehicle table
  • Staff command /pkeys, four server exports and an alarm event for your dispatch script

Requirements

Dependency Required/optional Used for Link
FiveM server build 7290 or newer required Per fxmanifest.lua (/server:7290) https://runtime.fivem.net/artifacts/fivem/
OneSync required Vehicles and state bags on the server https://docs.fivem.net/docs/scripting-reference/onesync/
ESX Legacy, QBCore or Qbox required Owner, money, police jobs (auto-detected) https://github.com/esx-framework/esx_core · https://github.com/qbcore-framework/qb-core · https://github.com/Qbox-project/qbx_core
ox_inventory required The key is an ox_inventory item https://github.com/overextended/ox_inventory
ox_lib required Helpers, key mapping https://github.com/overextended/ox_lib
oxmysql required Table pepper_keys_locks https://github.com/overextended/oxmysql
Garage script optional Taking cars out and parking, as long as it uses the framework vehicle table –
Dispatch script optional Report the car alarm to dispatch (bridge/server/dispatch.lua) –

Without a framework or without a running ox_inventory, Pepper Keys stays inactive and says so in the server console.

Installation

  1. Copy the folder to resources/[pepper]/pepper_keys.

    Do not rename the folder. Other scripts call exports.pepper_keys, which only works with the name pepper_keys.

  2. Add the entry from install/items/ox_inventory.txt to ox_inventory/data/items.lua.

  3. Copy install/images/pepper_carkey.png to ox_inventory/web/images.

  4. In your server.cfg, after your framework, oxmysql, ox_lib and ox_inventory:

ensure oxmysql
ensure ox_lib
ensure es_extended   # or qb-core / qbx_core
ensure ox_inventory
ensure pepper_keys

add_ace group.admin pepper.keys.admin allow
  1. Start the server. The console shows "Pepper Keys 1.0.0 started (esx)" (or your framework).

Database: The script creates the table pepper_keys_locks on start (server/db.lua). You only need install/pepper_keys.sql (same content) if your database user is not allowed to create tables. Then import it once with HeidiSQL or phpMyAdmin.

Items per inventory:

Inventory Item File Image
ox_inventory pepper_carkey (weight 50, not stackable) install/items/ox_inventory.txt → ox_inventory/data/items.lua install/images/pepper_carkey.png → ox_inventory/web/images

Other inventories are not supported. The item entry ships with a German label. On an English server, change label and description in items.lua.

First test

  1. As an admin, type /pkeys give <plate> for one of your vehicles. The key is now in your inventory.
  2. Press U at the vehicle: it locks or unlocks with a light signal.
  3. Get in: with the key the engine starts. Drop the key, get out and back in: the engine stays off.
  4. Without a key and with a lockpick in your inventory, press K and play the minigame.
  5. Drive to the locksmith (default at -205.5, -1313.3) and get a spare key with E.

Configuration

File Controls
config/config.lua Language, framework, admin groups, item, keys, range, accounts, hotwiring, locksmith
config/server.lua Admin ACE, Discord webhook for staff actions (never sent to clients)
locales/de.json, locales/en.json All in-game texts
bridge/server/dispatch.lua Integration with your dispatch script

Basics

Config.Locale = 'de'
Config.Framework = 'auto'
Config.Item = 'pepper_carkey'
Config.Range = 15.0
Config.PayAccounts = { 'bank', 'money' }
Option Default Description
Config.Locale 'de' 'de' or 'en'
Config.Framework 'auto' auto, esx, qbcore, qbox
Config.Debug false Extra console output
Config.AdminGroups { 'admin', 'superadmin', 'god' } Framework groups with admin rights (in addition to the ACE)
Config.AdminCommand 'pkeys' Name of the staff command
Config.Item 'pepper_carkey' Item name of the key
Config.Range 15.0 Lock range in metres
Config.LockKey / HotwireKey / InteractKey U / K / E Default keys
Config.PayAccounts { 'bank', 'money' } Order of accounts when paying

Hotwiring

Config.Hotwire = {
    Enabled = true,
    Item = 'lockpick',
    ItemBreakChance = 40,
    AlarmChance = 70,
    Cooldown = 30,
    MinPolice = 0,
    PoliceJobs = { 'police', 'sheriff' },
}
Option Default Description
Enabled true Hotwiring on/off
Item 'lockpick' Tool, false = none needed
ItemBreakChance 40 Percent chance the tool breaks on failure
AlarmChance 70 Percent chance of the car alarm
Cooldown 30 Seconds to wait after a failed attempt
MinPolice 0 This many people from PoliceJobs must be on duty
Range 3.0 Distance to the vehicle
AlarmSeconds 30 Siren duration
Levels easy 3/22, medium 4/16, hard 5/11 Hits (rounds) and hit zone size in percent (width)
Classes classes 2–5 medium, 6–7 hard GTA vehicle class → level, otherwise easy

Locksmith

Config.Locksmith = {
    CopyFee = 500,
    LockFee = 2500,
    FirstFree = true,
    Places = {
        { label = 'Schlüsseldienst', coords = vec3(-205.5, -1313.3, 31.3), radius = 3.0, blip = true },
    },
}
Option Default Description
CopyFee 500 Spare key
LockFee 2500 Lock change including a new key
FirstFree true First key for existing vehicles is free
Places 1 place Places with label, coordinates, radius and blip

Server

Option Default Description
ServerConfig.AdminAce 'pepper.keys.admin' ACE for the staff command
ServerConfig.Webhook '' Discord webhook for staff actions ('' = off)
ServerConfig.WebhookName 'Pepper Keys' Sender name in the webhook

How it works

Input Purpose
U Lock or unlock the nearest vehicle (range Config.Range)
K Hotwire, from the driver seat or at the door
E Open the locksmith
  • Getting in: As the driver, the script asks the server once. With a matching key the engine starts, otherwise it stays off.
  • Handing over a key: Just give the item. Whoever holds it may drive.
  • If the engine is already running, it keeps running even if the key is taken away.
  • In the inventory, a key shows the plate and the vehicle name.

Locksmith

The locksmith only serves the owner according to the framework vehicle table.

  • Spare key: for a fee (Config.Locksmith.CopyFee), fits the current lock.
  • Change lock: for a fee (Config.Locksmith.LockFee), you get a new key. All old keys stop working.
  • Existing vehicles: vehicles from before Pepper Keys have no key yet. The first one is free (Config.Locksmith.FirstFree).

If the key does not fit into the inventory, the player gets their money back.

Hotwiring

  • Only without a matching key, with the tool Config.Hotwire.Item (default lockpick, false = no tool needed).
  • Minigame: press space when the needle is in the zone. Difficulty depends on the vehicle class (Config.Hotwire.Levels, Classes).
  • Success: the vehicle is open and the engine starts until it is parked or deleted.
  • Failure: a cooldown (Cooldown) and a chance that the tool breaks (ItemBreakChance).
  • Alarm with chance AlarmChance: siren on the vehicle and the server event pepper_keys:alarm.
  • Minimum police on duty: MinPolice, counted with the jobs from PoliceJobs.

Garage scripts

Pepper Keys only reads the framework vehicle table (owned_vehicles on ESX, player_vehicles on QBCore and Qbox) and never writes to it. So it works with any garage script that uses this table. Taking a car out creates no new key, the player keeps using the key they already have.

Garage script Framework Table
esx_garage ESX owned_vehicles
qb-garages QBCore player_vehicles
qbx_garages Qbox player_vehicles
JG Advanced Garages ESX, QBCore, Qbox framework vehicle table
cd_garage ESX, QBCore framework vehicle table
okokGarage ESX, QBCore framework vehicle table
loaf_garage, renzu_garage ESX owned_vehicles
OP Garages v3 (OTHERPLANET) ESX, QBCore, Qbox framework vehicle table (per its docs)

This list follows from the table each script uses. We have not tested Pepper Keys with each of these third-party scripts. If your garage script uses its own table, its vehicles are not locked.

Only one key script: remove other key scripts (e.g. qb-vehiclekeys, qbx_vehiclekeys, wasabi_carlock). If your garage script has a setting for the key system, set it to "none" or enter the Pepper Keys exports there.

OP Garages v3: taking cars out and parking them works without changes; OP Garages gives no key there (Config.KeysDependency falls back to none). Car contracts, fake plates and job or gang vehicles need their own integration in the OP Garages "editable" files: after a contract, call ChangeLock + CreateKey for the new owner so the old key stops working.

Other scripts that should hand out keys themselves (dealership, rental, fleet) call the exports below.

Commands and permissions

Command Who What
/pkeys give <plate> Admin Create a key
/pkeys lock <plate> Admin Change the lock (old keys worthless)
/pkeys open <plate> Admin Unlock a vehicle

Permissions: Admin = ACE pepper.keys.admin (ServerConfig.AdminAce) or a group from Config.AdminGroups. The command only works in game, not in the server console. Every action is logged, optionally to a Discord webhook (ServerConfig.Webhook). The command name is set in Config.AdminCommand.

Keys: U lock, K hotwire, E locksmith. Players can change them in their FiveM settings (Key Bindings → FiveM); the defaults are Config.LockKey, HotwireKey and InteractKey.

Exports and events

Server exports:

exports.pepper_keys:CreateKey(src, plate, label) -- put a key into the inventory
exports.pepper_keys:HasKey(src, plate)           -- does the player hold a matching key?
exports.pepper_keys:ChangeLock(plate)            -- new lock, old keys worthless
exports.pepper_keys:RemoveKeys(src, plate)       -- take away the keys for this plate

Events:

Event Side Payload Purpose
pepper_keys:alarm server { plate, coords } Car alarm while hotwiring, e.g. for your dispatch script
AddEventHandler('pepper_keys:alarm', function(data)
    print(('Car alarm: %s at %.1f, %.1f'):format(data.plate, data.coords.x, data.coords.y))
end)

Alternatively, add your own dispatch integration in bridge/server/dispatch.lua (open file).

FAQ

Pepper Keys does not start or stays inactive – what now?

ox_inventory, ox_lib, oxmysql and your framework must start before pepper_keys. Without ESX, QBCore or Qbox, or without a running ox_inventory, the script reports in the console that it stays inactive.

The key has no image in the inventory.

Copy install/images/pepper_carkey.png to ox_inventory/web/images and restart the server.

My own car does not start.

Vehicles from before Pepper Keys have no key yet. Get one at the locksmith, the first one is free (Config.Locksmith.FirstFree).

A job vehicle is locked.

Only vehicles in the framework vehicle table or in pepper_keys_locks are locked. Check whether the plate is listed there.

"You are missing the right tool" when hotwiring.

The item from Config.Hotwire.Item (default lockpick) must be in your inventory. With Item = false no tool is needed.

/pkeys does nothing.

Set the ACE from the installation (add_ace group.admin pepper.keys.admin allow) or add your group to Config.AdminGroups. The command has no effect in the server console.

Do I need to import the SQL file?

No. The table pepper_keys_locks is created automatically on start. install/pepper_keys.sql is only for database users that cannot create tables.

Does Pepper Keys work with qs-inventory or qb-inventory?

No, the key is an ox_inventory item with metadata. Without ox_inventory the script stays inactive.

Can I use Pepper Keys together with qb-vehiclekeys?

No, use only one key script. Remove the others (qb-vehiclekeys, qbx_vehiclekeys, wasabi_carlock), otherwise they lock and unlock against each other.

How does my dealership or rental script hand out a key?

With the server export exports.pepper_keys:CreateKey(src, plate, label). When a car is resold, call ChangeLock(plate) first, then CreateKey for the new owner.

How do I change texts or the language?

Language via Config.Locale ('de' or 'en'), texts in locales/de.json or locales/en.json. You change the item name in ox_inventory/data/items.lua.

How do I move the locksmith or add more?

Change the coords in Config.Locksmith.Places or add entries with label, coords, radius and blip.

Can cheaters bypass the engine lock?

The engine lock runs on the client and can be bypassed by cheaters. Locking, ownership, item checks, fees and hotwiring are checked by the server.

How do I send the car alarm to my dispatch script?

Listen to the server event pepper_keys:alarm or add the call to your dispatch script in bridge/server/dispatch.lua.

Support

Discord → ticket (category "Script Support") at https://discord.gg/6NaFJWKDYu, link your purchase with /verify first.

Permanently tested on the Pepper Scripts dev server.

Changelog

Current: 1.0.0 (2026-11-08), first release. All changes are listed in CHANGELOG.md in the resource.


Found a mistake? Report it on Discord.