Skip to the content
Docs

Server Exports

On this page6
lua
exports['5code-recognition']:<Name>(...)

Read-only exports

Any resource may call these. They never change anything.

Recognition

ExportSignatureReturns
IsRecognized(viewerSrc, targetSrc, minPct?, opts?)boolean
GetRecognitionLabel(viewerSrc, targetSrc, minPct?, opts?)string | nil
GetRecognition(viewerSrc, targetSrc, opts?)nil | RecognitionInfo (see below)
GetRecognizers(targetSrc, minPct?, opts?)integer[] — the viewers who recognize this player right now
HasRecognized(observerSrc, targetSrc, minPct?, opts?)boolean — the "may act" check
GetReliability(observerSrc, targetSrc, opts?)integer 0–100

minPct defaults to Config.Scoring.ActThreshold (80).

IsRecognized vs HasRecognized. IsRecognized is the name display question — it follows Config.Api.RecognitionSource, which is 'scene' by default, so it is only true while a live result is open. HasRecognized is the may this character act question, and it always counts a valid Lab ID.

Use IsRecognized for nametags and chat. Use HasRecognized to gate an action.

lua
-- server side
local label = exports['5code-recognition']:GetRecognitionLabel(viewerSrc, speakerSrc)
TriggerClientEvent('chat:addMessage', viewerSrc, { args = { label or 'Stranger', text } })

Appearance

ExportSignatureReturns
IsFaceHidden(targetSrc)boolean — the same for every viewer
GetConcealment(targetSrc)Concealment (see below)

Memories

ExportSignatureReturns
GetMemory(observerKey, targetKey, opts?)nil | MemoryPublic — the best valid memory of the pair
GetMemories(observerKey, targetKey, opts?)MemoryPublic[]

These take character keys, not server ids. Use GetCharacterKey(src).

State

ExportSignatureReturns
IsScanning(src)boolean — a quiet quick look does not count as a scan
IsCameraActive(src)boolean
IsVoiceChangerActive(src)boolean
GetCharacterKey(src)string | nil
GetIdentityGeneration(charKeyOrSrc)integer | nil — goes up after each face implant or identity reset
GetImplantCooldown(charKeyOrSrc)integer seconds left, 0 = ready
OpenAdminPanel(adminSrc, aSrc?, bSrc?)boolean — for an admin-menu button

opts.includeDisguises

Every export that can answer from a saved memory takes opts = { includeDisguises = true }. It defaults to false, and you almost certainly want to leave it there.

A "masked person" memory of somebody must never make IsRecognized true, or supply a label, while that person is standing there bare-faced — that would hand your nametag script exactly the link the disguise system exists to hide.

The one exception is built in: a live result about a disguise does answer while it is open, which is how "the hoodie guy" keeps his label on screen while he is wearing the hoodie.

Set it to true only for staff tooling and incident reporting.

Return shapes

Written in TypeScript notation. Lua tables have the same fields, with nil where a field is optional.

ts
type Channel = 'memory' | 'camera' | 'report' | 'hearsay' | 'lab';

Channel says where the knowledge came from: memory your own eyes, camera your own hidden camera, report a police reading of a camera report, hearsay a description a friend gave you, lab a fingerprint or DNA match.

RecognitionInfo

Returned by GetRecognition (server and client), and carried by the client event onRecognitionChanged.

ts
interface RecognitionInfo {
  pct: number;              // 0-100
  channel: Channel;
  live: boolean;            // is a live result open right now?
  label?: string;           // the memory line, e.g. "Met him on Vinewood Blvd in the evening"
  introducedName?: string;  // the name they gave this viewer, if any
  sceneEndsAt?: number;     // epoch seconds, while live
  expiresAt?: number;       // epoch seconds, server side only
}

Show introducedName or label, and show nothing when both are absent.

MemoryPublic

Returned by GetMemory and GetMemories.

ts
interface MemoryPublic {
  id: number;
  source: Channel;
  reliability: number;      // as saved
  effective: number;        // what it is worth now
  cues: { voice: number; clothing: number; face: number; tattoo: number };
  label?: string;           // the memory line
  claimedName?: string;     // an introduced name
  createdAt: number;        // epoch seconds
  lastScanAt: number;
  expiresAt: number;
}

There is deliberately no "this is a disguise" flag: the filtering is ours to do, not yours — see opts.includeDisguises.

Concealment

Returned by GetConcealment(targetSrc).

ts
interface Concealment {
  faceHidden: boolean;      // at or above Config.FaceCoverage.HiddenAt (60)
  facePct: number;          // the VISIBLE share: 100 = fully visible
  faceCategory: 'none' | 'hat' | 'eyes' | 'half' | 'full';
  armsClass: string;        // e.g. 'none' | 'short' | 'sleeveless' | 'bare'
  torsoVisible: boolean;
  handsVisible: boolean;
  skinVisible: boolean;     // any tattoo-capable skin uncovered
}

Concealment is the same for every viewer — everybody can see a mask — so it is safe to use anywhere. A player the script has not read yet counts as hidden.

Write exports

These change state and are restricted. A call from a resource that is not on the trusted list is refused (false, 'not_trusted') and logged.

lua
-- config_server.lua
ServerConfig.Api = {
    TrustedResources = { 'my_surgeon_shop', 'my_idcard' },
}

Our own resource and our bridges are always trusted. Options that skip money or cooldowns (charge = false, ignoreCooldown = true, setCooldown = false, checkDistance = false) are honoured only for trusted callers.

Every write-export call is written to the audit log and posted to the admin Discord channel.

Identity

ExportSignatureReturns
ResetIdentity(charKeyOrSrc, reason?, opts?)ok, err
StartFaceImplant(src, opts?)ok, err

ResetIdentity makes everybody forget this character, with no payment and no editor. opts: rotateVoice, ignoreCooldown, setCooldown, label.

StartFaceImplant runs our full implant flow from your script. opts: charge (default true), price, ignoreCooldown, rename (default true), account, label.

Error codes: unknown_character, implant_busy, implant_cooldown, implant_conflict, not_trusted.

lua
-- your surgeon shop, server side, after you have taken payment yourself
local ok, err = exports['5code-recognition']:StartFaceImplant(src, {
    charge = false,          -- trusted callers only
    rename = true,
    label  = 'Backstreet Clinic',
})
if not ok then print(('implant refused: %s'):format(err)) end

Death

ExportSignatureReturns
ReportDown(src, data?{stage, killer, weapon})boolean
ReportRevived(src, reviverSrc?, method?)boolean
ReportRespawned(src, method?)boolean

Use these when your ambulance script is not one we have an adapter for. stage is 'laststand' or 'dead'. They count as confirmed, exactly like an adapter — so call them from your own server code, never from a client event.

Evidence

ExportSignatureReturns
GrantLabIdentification(officerSrc, targetCharKey, opts?{source, evidenceType, ttlHours})ok, err

Recognition records

ExportSignatureReturns
LogAction(actorSrc, targetSrc, cause, meta?)snapshotId | nil

cause is one of aim, damage, kill, cuff, uncuff, rob, search, escort, kidnap, custom.

It waits until the record is written (2-second timeout) and uses the same cooldowns as the built-in records. meta is capped at 2 KB; meta.detail becomes the record's detail text. Calls are capped per calling resource per minute (Config.Proof.ExportCallsPerMinute).

lua
-- your heist script, when a hostage is taken
exports['5code-recognition']:LogAction(robberSrc, hostageSrc, 'kidnap', {
    detail = 'Fleeca Route 68',
})

Social

ExportSignatureReturns
RecordIntroduction(speakerSrc, listenerSrc, name, opts?{via, checkDistance})ok, code

via is 'idcard' or 'script'. Use it when an ID card is shown, so the name lands on the listener's memory the same way a spoken introduction would.

Items

ExportSignatureReturns
TriggerItemUse(src, itemName, itemData?)boolean — for custom inventories
GiveItem(src, itemName, count?)ok — standalone virtual items
useItem(event, item, inventory, slot, data)the ox_inventory server.export handler

IDs you will see

ThingFormat
Character keyA string from your framework (for example the citizenid on QBCore / Qbox). Treat it as an opaque id
Device serialVC- voice changer · HC- hidden camera · MS- magnetic scanner, plus 9 characters
Paper idRC- camera report · WS- witness statement · DS- description, plus 9 characters
VoiceprintVP-XXXX-XXXX — the same voice changer always produces the same one

See also