Browse docs
Vehicle Registry
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:
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
| Export | Arguments | Use case |
|---|---|---|
GetVehicleRegistryFeatures | None | Check enabled features and service availability. |
GetVehicleRegistryStatus | plate | Check inspection and registration status without holder details or signatures. |
GetVehicleRegistryDetail | source, plate | Read 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.
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.
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 = ... }:
| Field | Type | Description |
|---|---|---|
plate | string | Normalized current plate. |
vehicleId | string? | Stable registry vehicle ID; absent if no registry identity has been assigned yet. |
features | table | Independent kuv and registration switches. |
version | number | Registry configuration version used by this query. |
kuv | table? | Enabled inspection: status, optional documentId, issuedAt, validUntil. |
registration | table? | 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 status | Meaning |
|---|---|
missing | No inspection has been issued. |
valid | The inspection is current. |
due_soon | Still valid, within the configured warning period. |
expired | The validity deadline has been reached. |
failed | The latest inspection failed. |
revoked | The current inspection was revoked. |
| Registration status | Meaning |
|---|---|
unregistered | No registration has been issued. |
registered | Registered to the current framework owner. |
transfer_required | Ownership changed after registration. |
deregistered | The vehicle was deregistered. |
revoked | The 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.
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.
| Code | Meaning |
|---|---|
invalid_plate | Plate is empty, invalid, contains control characters, or exceeds 24 bytes. |
vehicle_not_found | No unique owned vehicle matches the plate. |
feature_disabled | Both inspection and registration are disabled. |
invalid_request | Detail query has an invalid player source. |
not_authorized | Player lacks current registry access. |
configuration_changed | Configuration changed during the database read. |
database_unavailable | A 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".
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.
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
| Field | Type | Description |
|---|---|---|
operationId | string | Unique history operation ID. Use this to deduplicate external processing. |
documentId | string | Affected certificate ID. Deregistration refers to the previous registration certificate. |
vehicleId | string | Stable registry vehicle ID. |
plate | string | Current plate when the operation completed. |
kind | string | Completion: inspection, registration, deregistration. Revocation: revoke_inspection, revoke_registration. |
source | number | Acting mechanic's server ID at that moment; not a persistent identity. |
actorJob | string | Issuing workshop job. |
occurredAt | number | Unix timestamp in seconds. |
result | string? | Inspection completion only: passed, advisory, or failed. |
invoiceId | number? | Completion only: created invoice reference, when present. |
billingPending | boolean? | Completion only: certificate saved but invoice creation still needs recovery. |
reason | string? | 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.