Browse docs
Emergency Dispatch
Emergency Dispatch
Trusted server resources can create persistent incidents, connect a phone or voice provider, inspect response plans, or continue using the legacy compatibility API.
| API | Purpose |
|---|---|
CreateDispatchIncident / GetDispatchIncident / CloseDispatchIncident | Preferred resource-owned incident API. |
CreateDispatchCall / GetDispatchCall / CloseDispatchCall | Resource-owned phone and voice call adapter API. |
GetDispatchResponsePlans / EvaluateDispatchResponsePlan | Read and evaluate configured AAO response plans. |
createDispatch / HasDispatch / RemoveDispatchesBySourceAndId | Legacy compatibility API. |
Resource-owned incidents
CreateDispatchIncident(data)
Creates an idempotent, persistent system incident. Reusing the same sourceId from the same resource
returns the existing record instead of creating a duplicate.
| Field | Type | Required | Description |
|---|---|---|---|
sourceId | string | Yes | Stable adapter ID: 1–64 letters, numbers, _, ., :, or -. |
jobs / job | string | string[] | Yes | Covered response job or jobs. |
coords / location.coords | vector3 | table | Yes | Incident position with x, y, and z. |
message / title | string | Yes | At least one incident text field must be present. |
centerId | string | No | Responsible center. Every target job must be covered by it. |
priority | number | No | Incident priority. |
keywordCode / keywordJob | string | No | Configured response-plan keyword and its owner job. |
reporter | table | No | { name?, phone?, anonymous? }. Flat reporter fields remain supported. |
street, address, poi, destination | string | No | Structured location context. |
details | table | No | Additional incident details. |
silent | boolean | No | Suppresses audible delivery when true. |
author | string | No | Trusted display name for the creating system. |
local result = exports["sky_jobs_base"]:CreateDispatchIncident({
sourceId = "bank-alarm:pacific-standard",
jobs = { "police" },
coords = { x = 235.0, y = 216.0, z = 106.0 },
message = "Silent alarm triggered in the main lobby.",
priority = 1,
keywordCode = "ARMED_ROBBERY",
reporter = {
anonymous = true
},
details = {
alarmZone = "Main lobby"
}
})
if not result.success then
print(("Unable to create dispatch incident: %s"):format(result.error))
end
The export returns { success, data?, error? }. The public incident payload omits internal
dispatcher ownership tokens, audit state, and mutable runtime tables.
When reporter.anonymous or the top-level anonymous is exactly true, anonymity wins over every
supplied name and phone number. Jobs Base clears structured caller identity, including
details.callerName and details.callerPhone. Free text is not automatically redacted, so do not
place personal data in message, notes, or details.callerSummary for anonymous reports.
GetDispatchIncident(sourceId)
Returns { success = true, data = incident } for the newest active incident owned by the invoking
resource. If none is active, it returns that resource's newest archived incident for the ID.
local result = exports["sky_jobs_base"]:GetDispatchIncident(
"bank-alarm:pacific-standard"
)
CloseDispatchIncident(sourceId)
Idempotently requests closure of the invoking resource's incident and returns
{ success, error? }.
local result = exports["sky_jobs_base"]:CloseDispatchIncident(
"bank-alarm:pacific-standard"
)
A resource cannot read or close another resource's records. Do not add a provider or resource name to the payload; the export captures it at entry.
Phone and voice call adapters
CreateDispatchCall(data)
Adds an incoming or outgoing provider call to the authoritative queue. sourceId is required and
idempotent per invoking resource. Supply either centerId or one covered job so Jobs Base can
resolve the center.
Optional fields are direction (incoming or outgoing), reporter, the backward-compatible flat
reporter fields, notes, incidentId, author, capabilities, and providerControls. Anonymous
mode discards both reporter name and phone number before persistence.
local result = exports["sky_jobs_base"]:CreateDispatchCall({
sourceId = "call-88421",
job = "police",
direction = "incoming",
reporter = {
name = "Alex Morgan",
phone = "555-0142"
},
notes = "Caller reports suspicious activity near Legion Square."
})
if not result.success then
print(("Unable to create dispatch call: %s"):format(result.error))
end
GetDispatchCall(sourceId) and CloseDispatchCall(sourceId)
GetDispatchCall reads a call created by the same invoking resource. CloseDispatchCall ends it
and releases the responsible dispatcher. Both return { success, data?, error? } envelopes.
local current = exports["sky_jobs_base"]:GetDispatchCall("call-88421")
local closed = exports["sky_jobs_base"]:CloseDispatchCall("call-88421")
sky_jobs_base:dispatch:callStateChanged
This local server event lets a phone or voice adapter mirror the Dispatch lifecycle into its native
line implementation. It is emitted for created, accept, hold, resume, transfer,
link_incident, callback, and finish actions.
| Field | Type | Description |
|---|---|---|
id, number | number | string | Dispatch call identity and display number. |
centerId | string | Responsible center. |
direction, status | string | Current call direction and state. |
adapter | string | Provider-neutral adapter identifier. |
reporterName, reporterPhone | string | Server-stored reporter data. |
incidentId | number? | Linked incident, when present. |
action | string | Lifecycle action that caused the event. |
context | table | Action-specific IDs and provider context. |
AddEventHandler("sky_jobs_base:dispatch:callStateChanged", function(call)
if call.action == "finish" then
exports["my_phone"]:EndDispatchLine(call.number)
end
end)
Response plans
GetDispatchResponsePlans(jobs)
Returns { enabled, plans } for exact configured job names. Each plan contains its owner job,
keyword code, requirements, minimum crew, target jobs, and automatic-alarm setting.
local catalog = exports["sky_jobs_base"]:GetDispatchResponsePlans({
"police",
"ambulance"
})
The export is always registered. When Dispatch is disabled it returns
{ enabled = false, plans = {} }.
EvaluateDispatchResponsePlan(data)
Evaluates a configured plan against currently staffed virtual units. ownerJob and keywordCode
are required; jobs, coords, and minimumCrew are optional.
local evaluation = exports["sky_jobs_base"]:EvaluateDispatchResponsePlan({
ownerJob = "police",
keywordCode = "ARMED_ROBBERY",
jobs = { "police" },
coords = { x = 235.0, y = 216.0, z = 106.0 }
})
if evaluation.eligible then
for _, unit in ipairs(evaluation.units) do
print("Suggested unit:", unit.callsign)
end
else
print("Response plan unavailable:", evaluation.reason)
end
The result includes eligible, reason, unit and crew coverage, requirements, and selected units.
Only available, unassigned units with live crew are considered. With Dispatch disabled the reason
is dispatch_disabled.
Legacy compatibility API
createDispatch(title, message, coords, jobs, meta)
Creates a legacy dispatch entry. With Config.Dispatch.enabled = true, it also creates the
persistent Dispatch App incident and suppresses the legacy top-center notification. With the master
switch disabled, it uses the legacy map dispatch and notification.
jobs accepts one job or group key, or an array of keys. Exact registered job names take precedence
over a group with the same key. meta supports source, sourceKey, sourceId, category,
keywordCode, priority, silent, reporter, flat reporter fields, anonymous, author,
centerId, street, address, poi, destination, and details.
local dispatch = exports["sky_jobs_base"]:createDispatch(
"Vehicle collision",
"Two vehicles are blocking the eastbound lanes.",
vector3(1175.2, 2640.4, 37.8),
{ "police", "ambulance" },
{
sourceKey = "traffic_control",
sourceId = "camera-12:event-458",
category = "traffic_collision",
priority = 2
}
)
Returns: the created dispatch entry, or nil when validation or persistent incident creation
fails. New adapters should use CreateDispatchIncident, whose namespacing and result envelope are
safer and clearer.
HasDispatch(sourceKey, sourceId)
Returns whether a non-completed legacy dispatch exists for the exact source key and ID.
local exists = exports["sky_jobs_base"]:HasDispatch(
"traffic_control",
"camera-12:event-458"
)
RemoveDispatchesBySourceAndId(sourceKey, sourceId)
Removes every matching legacy dispatch, requests closure of linked Dispatch App incidents, and returns the number of removed entries.
local removed = exports["sky_jobs_base"]:RemoveDispatchesBySourceAndId(
"traffic_control",
"camera-12:event-458"
)