Start typing to search packages!
sonoran-lua
By @sonoransoftwaregit
Roblox
MirroredSonoran.lua
Sonoran.lua is a Lua SDK for Sonoran CAD v2 endpoints with shared client code for FiveM and Roblox runtimes.
Installation
FiveM
Install from LuaRocks:
luarocks install sonoran.lua
LuaRocks package: sonoran.lua on LuaRocks
Or use the generated FiveM resource release asset and start it before resources that consume it.
ensure Sonoran.lua
In your consuming resource:
fx_version 'cerulean'
game 'gta5'
lua54 'yes'
server_scripts {
'server.lua'
}
dependency 'Sonoran.lua'
Roblox
Install from Wally:
[dependencies]
Sonoran = "sonoransoftwaregit/sonoran-lua@^0.1.0"
Then require the package module:
local Sonoran = require(ReplicatedStorage.Packages.Sonoran)
Usage
FiveM resource usage:
local Sonoran = require("sonoran")
local sonoran = exports["Sonoran.lua"]:createClient({
product = Sonoran.productEnums.CAD,
apiKey = "your-cad-api-key",
communityId = "your-community-id",
apiUrl = "https://api.sonorancad.com",
defaultServerId = 1,
timeoutMs = 30000,
logLevel = Sonoran.logLevels.ERROR
})
sonoran:setLogLevel(Sonoran.logLevels.DEBUG)
sonoran:setRoomId(1)
Roblox usage:
local sonoran = Sonoran.createClient({
product = Sonoran.productEnums.CAD,
apiKey = "your-cad-api-key",
communityId = "your-community-id",
apiUrl = "https://api.sonorancad.com",
defaultServerId = 1,
timeoutMs = 30000,
logLevel = Sonoran.logLevels.ERROR
})
sonoran:setLogLevel(Sonoran.logLevels.DEBUG)
Config
apiKey: required for authenticated endpoints.product: required; useSonoran.productEnums.CAD,Sonoran.productEnums.CMS, orSonoran.productEnums.RADIO.communityId: optional; used bygetLoginPageV2()when no explicitcommunityIdis supplied.apiUrl: optional; defaults tohttps://api.sonorancad.com.defaultServerId: optional; defaults to1for CAD/CMS-style server-scoped helpers. Radio v2 helpers resolve the community route fromcommunityId.roomId: optional for CAD/CMS and required for Radio v2 room-scoped helpers.headers: optional extra headers merged into every request.timeoutMs: optional timeout for the FiveM adapter; defaults to30000.logLevel: optional;Sonoran.logLevels.ERRORby default. Supported values areOFF,ERROR, andDEBUG.
Debug Logging
Use setLogLevel() to toggle HTTP debug output at runtime:
sonoran:setLogLevel(Sonoran.logLevels.DEBUG)
Use setRoomId() to update the Radio room used by later room-scoped requests without creating a new client:
sonoran:setRoomId(1)
Use ERROR to only print failed requests and rate-limit events:
sonoran:setLogLevel(Sonoran.logLevels.ERROR)
When DEBUG is enabled, Sonoran.lua prints every HTTP request and response to the console, including the method, URL, headers, body, response status, and response headers. Sensitive request values such as Authorization and API-key style fields are redacted in both DEBUG and ERROR logs.
Response Shape
All public methods return:
{ success = true, data = ... }
or:
{ success = false, reason = ... }
Successful JSON responses are decoded automatically. Plain-text error responses are returned as strings. 204 No Content responses return data = nil.
Rate Limit Handling
For CAD v2 endpoints, Sonoran.lua automatically retries 429 Too Many Requests responses up to 2 times when it can safely honor the server's wait window. The client checks Retry-After first, including both delta-seconds and HTTP-date formats, then falls back to RateLimit-Reset, X-RateLimit-Reset, and finally a short exponential backoff. If the server asks for a longer wait than the client's automatic retry limit, or the active adapter cannot sleep, the request fails instead of retrying too early.
Examples
General endpoint:
local version = sonoran.cad:getVersionV2()
if version.success then
print(version.data)
end
Civilian endpoint:
local characters = sonoran.cad:getCharactersV2({
roblox = 1234567890
})
if characters.success then
print(("Found %s character(s)"):format(#characters.data))
end
Emergency endpoint:
local created = sonoran.cad:createDispatchCallV2({
serverId = 1,
origin = 1,
status = 1,
priority = 1,
block = "123",
address = "Main St",
postal = "100",
title = "Traffic Stop",
code = "TS",
description = "Blue sedan heading north",
notes = {},
communityUserIds = { "1234567890" }
})
if not created.success then
print(json.encode(created.reason))
end
Public API
All CAD v2 helpers are available under client.cad.*. The root-level methods are still present for backward compatibility.
General
getLoginPageV2(params?)checkApiIdV2(apiId)applyPermissionKeyV2(data)banUserV2(data)getPenalCodesV2()setPenalCodesV2(codes)setApiIdsV2(data)getTemplatesV2(recordTypeId?)createRecordV2(data)updateRecordV2(recordId, data)removeRecordV2(recordId)sendRecordDraftV2(data)lookupV2(data)lookupByValueV2(data)lookupCustomV2(data)getAccountV2(query?)getAccountsV2(query?)createCommunityLinkV2(data)checkCommunityLinkV2(data)setCommunityLinkV2(data)setAccountPermissionsV2(data)heartbeatV2(serverId, playerCount)getVersionV2()getServersV2()setServersV2(servers, deployMap?)verifySecretV2(secret)authorizeStreetSignsV2(serverId?)setPostalsV2(postals)sendPhotoV2(data)uploadBodycamRecordingV2(data)getInfoV2()
Civilian
getCharactersV2(query?)removeCharacterV2(characterId)setSelectedCharacterV2(data)getCharacterLinksV2(query?)addCharacterLinkV2(syncId, data)removeCharacterLinkV2(syncId, data)
Emergency
getUnitsV2(query?)getCallsV2(query?)getCurrentCallV2(accountUuid)updateUnitLocationsV2(data)setUnitPanicV2(data)setUnitStatusV2(data)kickUnitV2(data)getIdentifiersV2(accountUuid)getAccountUnitsV2(data)selectIdentifierV2(accountUuid, identId)createIdentifierV2(accountUuid, data)updateIdentifierV2(accountUuid, identId, data)deleteIdentifierV2(accountUuid, identId)addIdentifiersToGroupV2(data)createEmergencyCallV2(data)deleteEmergencyCallV2(callId, serverId?)getDispatchTemplatesV2(templateId?)createDispatchCallV2(data)createCustomDispatchCallV2(data)updateDispatchCallV2(callId, data)attachUnitsToDispatchCallV2(callId, data)detachUnitsFromDispatchCallV2(data)setDispatchPostalV2(callId, postal, serverId?)setDispatchPrimaryV2(callId, identId, trackPrimary?, serverId?)addDispatchNoteV2(callId, data)closeDispatchCallsV2(callIds, serverId?)updateStreetSignsV2(data)setStreetSignConfigV2(signs, serverId?)setAvailableCalloutsV2(callouts, serverId?)getPagerConfigV2(serverId?)setPagerConfigV2(data)setStationsV2(config, serverId?)Sends the provided top-level station payload as-is. Passlocations,tones, andunitColorsdirectly on the request body.getBlipsV2(serverId?)createBlipV2(data)updateBlipV2(blipId, data)deleteBlipsV2(ids, serverId?)
Notes
- Account-targeted CAD v2 helpers accept
accountUuid,communityUserId,roblox,discord, and legacyapiIdwhere supported by the backend. updateUnitLocationsV2(data)uses the HTTP v2 endpoint for slower unit location updates, and each update can targetcommunityUserId,roblox, ordiscord.- Unit location updates can target
communityUserId,roblox, ordiscordthrough the v2 HTTP endpoint. - FiveM uses
PerformHttpRequest,promise.new(), andCitizen.Await. - Roblox uses
HttpService:RequestAsync(). - Radio, CMS, and legacy CAD endpoints are intentionally out of scope for this initial port.
Package Details
Install command (Click to copy)
Version
0.1.61
License
MIT
Safe for commercial use
License identified from the packaged LICENSE file; the manifest's declared license ("PolyForm-Noncommercial-1.0.0") is not a recognized identifier.
Automated license review — not legal advice.
