Browse docs

Vehicle Registry

Read technical inspection and vehicle registration status, access signed records, and receive committed vehicle certificate events.

Use these integrations to check a vehicle in a garage, show its certificates in another police tablet, or log completed workshop paperwork. The shared registry powers Sky Mechanic Job and Sky Police Job. All exports and events on this page belong to sky_jobs_base and run on the server.

Setup

Install a Jobs Base build containing the vehicle registry exports and start it before your integration:

fxmanifest.lua
dependency "sky_jobs_base"

Technical inspection and vehicle registration can each be enabled or disabled in the Mechanic Job Configurator (/jobconfig). Disabling a feature removes its status from query results. If both are disabled, status queries return feature_disabled. These integrations use the existing registry tables and require no additional SQL migration.

Server exports

ExportArgumentsUse case
GetVehicleRegistryFeaturesNoneCheck enabled features and service availability.
GetVehicleRegistryStatusplateCheck inspection and registration status without holder details or signatures.
GetVehicleRegistryDetailsource, plateRead certificates and signed history for an authorized mechanic or police player.

Call database-backed queries when a vehicle is selected or used, rather than every frame. The exports yield while waiting for database results; call them from a server thread, event handler, or callback.

GetVehicleRegistryFeatures()

Returns a new snapshot of the current settings and availability. Changing this table does not change the server configuration.

server.lua
local registry = exports["sky_jobs_base"]:GetVehicleRegistryFeatures()

-- registry.available: boolean; the registry has finished initializing successfully
-- registry.features.kuv: boolean; technical inspection is enabled
-- registry.features.registration: boolean; vehicle registration is enabled
-- registry.version: number; changes whenever registry configuration is applied
-- registry.error: string or nil; reason the service is unavailable

available = true can also mean that both features are deliberately disabled. Read the feature switches before deciding whether your integration should require certificates.

GetVehicleRegistryStatus(plate)

Accepts a string plate. Surrounding whitespace is removed and letters are normalized to uppercase; internal spaces remain part of the plate. The plate must belong to an owned vehicle in the configured framework vehicle database. The vehicle does not need to be spawned or nearby for this read.

server.lua
local result = exports["sky_jobs_base"]:GetVehicleRegistryStatus("SKY123")
if not result.success then
    print(("Vehicle registry query failed: %s"):format(result.error))
    return
end

local vehicle = result.data
local inspection_ok = not vehicle.features.kuv
    or vehicle.kuv.status == "valid"
    or vehicle.kuv.status == "due_soon"
local registration_ok = not vehicle.features.registration
    or vehicle.registration.status == "registered"

print(("Vehicle %s: inspection=%s, registration=%s"):format(
    vehicle.plate, tostring(inspection_ok), tostring(registration_ok)
))

Successful responses have { success = true, data = ... }:

FieldTypeDescription
platestringNormalized current plate.
vehicleIdstring?Stable registry vehicle ID; absent if no registry identity has been assigned yet.
featurestableIndependent kuv and registration switches.
versionnumberRegistry configuration version used by this query.
kuvtable?Enabled inspection: status, optional documentId, issuedAt, validUntil.
registrationtable?Enabled registration: status, optional documentId, issuedAt.

Times are Unix timestamps in seconds. Status responses contain no holder names, player identifiers, notes, reports, or signatures. This export is for trusted server resources and does not require a mechanic or police player. An integration that exposes it to clients must authorize its own vehicle access.

Inspection statusMeaning
missingNo inspection has been issued.
validThe inspection is current.
due_soonStill valid, within the configured warning period.
expiredThe validity deadline has been reached.
failedThe latest inspection failed.
revokedThe current inspection was revoked.
Registration statusMeaning
unregisteredNo registration has been issued.
registeredRegistered to the current framework owner.
transfer_requiredOwnership changed after registration.
deregisteredThe vehicle was deregistered.
revokedThe registration was revoked.

GetVehicleRegistryDetail(source, plate)

Reads the same authorized record used by the job tablets, including the latest certificates and up to 30 history entries. source is the requesting player's server ID, not a job name or persistent identifier. Pass the actual caller from your server handler.

server.lua
local record = exports["sky_jobs_base"]:GetVehicleRegistryDetail(source, "SKY123")
if not record.success then
    print(("Vehicle record unavailable: %s"):format(record.error))
    return
end

for _, entry in ipairs(record.data.history) do
    print(entry.kind, entry.occurredAt, entry.documentId)
    if entry.consent then
        print("Signed by:", entry.consent.signerName)
        print("Signed at:", entry.consent.signedAt)
    end
end

The server checks current job, duty, active organization and registry read permissions. Ordinary vehicle owners do not receive staff records through this export. Detailed inspection or registration rights also grant read access.

data contains vehicle, context, summary, revision, optional inspection and registration, and history. Signed certificates expose their document through snapshot.consent; history entries expose consent. It includes the original declaration, operation title, plate, fee, verified signer, signing time and drawn signature. Older records can have no consent document. Invoice references in history remain restricted to staff with the relevant mechanic rights.

Errors

Status and detail failures return { success = false, error = "code" }. Never treat an unsuccessful query as proof of a valid certificate.

CodeMeaning
invalid_platePlate is empty, invalid, contains control characters, or exceeds 24 bytes.
vehicle_not_foundNo unique owned vehicle matches the plate.
feature_disabledBoth inspection and registration are disabled.
invalid_requestDetail query has an invalid player source.
not_authorizedPlayer lacks current registry access.
configuration_changedConfiguration changed during the database read.
database_unavailableA database query failed.

Initialization and framework lookup failures also return their existing service error, such as migration_required, transaction_driver_required, or registry_unavailable. Use GetVehicleRegistryFeatures() to inspect service readiness.

Server events

Both events are local server notifications. Subscribe with AddEventHandler, not RegisterNetEvent. They are emitted after the database transaction succeeds and the shared write lock has been released, so listeners can immediately query the committed record. They do not issue certificates or grant consent.

sky_jobs_base:vehicleRegistry:operationCompleted

Fires once for a newly committed inspection, registration, or deregistration. A failed validation/write, repeated completion request, or invoice retry does not emit another completion event. A failed inspection still produces a completed operation with result = "failed".

server.lua
AddEventHandler("sky_jobs_base:vehicleRegistry:operationCompleted", function(operation)
    print(("%s: %s completed for %s"):format(
        operation.operationId, operation.kind, operation.plate
    ))

    local current = exports["sky_jobs_base"]:GetVehicleRegistryStatus(operation.plate)
    if current.success then
        -- Update your integration's vehicle display from current.data.
        print("Registry version:", current.data.version)
    end
end)

sky_jobs_base:vehicleRegistry:documentRevoked

Fires after a successful inspection or registration revocation. The existing issuer and revoke permission checks still apply.

server.lua
AddEventHandler("sky_jobs_base:vehicleRegistry:documentRevoked", function(operation)
    print(("Certificate %s revoked for %s: %s"):format(
        operation.documentId, operation.plate, operation.reason
    ))
end)

Event payload

FieldTypeDescription
operationIdstringUnique history operation ID. Use this to deduplicate external processing.
documentIdstringAffected certificate ID. Deregistration refers to the previous registration certificate.
vehicleIdstringStable registry vehicle ID.
platestringCurrent plate when the operation completed.
kindstringCompletion: inspection, registration, deregistration. Revocation: revoke_inspection, revoke_registration.
sourcenumberActing mechanic's server ID at that moment; not a persistent identity.
actorJobstringIssuing workshop job.
occurredAtnumberUnix timestamp in seconds.
resultstring?Inspection completion only: passed, advisory, or failed.
invoiceIdnumber?Completion only: created invoice reference, when present.
billingPendingboolean?Completion only: certificate saved but invoice creation still needs recovery.
reasonstring?Revocation only: recorded explanation.

These events contain no holder identifiers or signature strokes. A completion confirms saved paperwork, not payment of its invoice. Process financial actions through the billing integration rather than charging the player again from these events.

Expiry and ownership changes are calculated when a record is queried. There is no automatic expiry/sale event or replay of old events after a resource restart; query the current status when your integration needs a decision.