FiveM Integration
Connect your FiveM server to CDE CAD for 911 calls, panic alerts, live map tracking, and character synchronization.
https://cdecad.com/api/fivem — All FiveM-specific endpoints are prefixed with /api/fivem. LiveMap and character sync endpoints use their own prefixes as documented below.
Getting Started with FiveM Integration
Generating an API Key
To connect your FiveM server to CDE CAD, you need an API key. Generate one from the Admin Panel:
- Navigate to Admin Panel in your community dashboard.
- Open FiveM Settings.
- Click Generate API Key.
- Copy the key immediately — it is only shown once.
API Key Format
All FiveM API keys follow the format:
fvm_<64 hex characters>
Example: fvm_a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2
Authentication
All authenticated FiveM requests must include the API key in the x-api-key header:
x-api-key: fvm_your_api_key_here
communityId (your Discord guild ID). While this method is still supported, new integrations should use the fvm_ API key format.
Server Registration
Auto-register your FiveM server with CDE CAD. No authentication required — the server is matched to an existing community automatically.
No Auth RequiredRequest Body
| Field | Type | Required | Description |
|---|---|---|---|
serverName | string | Yes | Your FiveM server name |
license | string | Yes | FiveM server license key |
discordId | string | Yes | Discord guild ID for community matching |
ip | string | Yes | Server IP address |
port | number | Yes | Server port |
maxPlayers | number | Yes | Maximum player slots |
Community Matching Priority
The server is matched to a community using the following priority order:
- discordId — Matches against the community's Discord guild ID (most reliable).
- license — Matches against a previously registered FiveM license.
- serverName — Matches against a known server name.
Response
{
"success": true,
"communityId": "abc123def456",
"communityName": "My RP Community",
"apiKey": "fvm_a1b2c3d4..."
}
Lua Example
PerformHttpRequest('https://cdecad.com/api/fivem/register', function(statusCode, response, headers)
if statusCode == 200 then
local data = json.decode(response)
if data.success then
print('[CDE CAD] Registered! Community: ' .. data.communityName)
print('[CDE CAD] API Key: ' .. data.apiKey)
-- Store the API key for future requests
Config.ApiKey = data.apiKey
Config.CommunityID = data.communityId
end
else
print('[CDE CAD] Registration failed: ' .. tostring(statusCode))
end
end, 'POST', json.encode({
serverName = GetConvar('sv_hostname', 'Unknown'),
license = GetConvar('sv_licenseKey', ''),
discordId = '1200664516858495056',
ip = GetConvar('web_baseUrl', '127.0.0.1'),
port = GetConvarInt('sv_port', 30120),
maxPlayers = GetConvarInt('sv_maxClients', 32)
}), {
['Content-Type'] = 'application/json'
})
Server Heartbeat
Send periodic heartbeats to keep your server marked as online in CDE CAD.
Requires x-api-keyRequest Body
| Field | Type | Required | Description |
|---|---|---|---|
playerCount | number | Yes | Current number of players on the server |
serverInfo | object | Yes | Server metadata |
serverInfo.license | string | Yes | FiveM server license key |
Response
{
"success": true
}
Lua Example
-- Send heartbeat every 60 seconds
Citizen.CreateThread(function()
while true do
Citizen.Wait(60000)
PerformHttpRequest(Config.CadUrl .. '/api/fivem/heartbeat', function(statusCode, response, headers)
if statusCode == 200 then
print('[CDE CAD] Heartbeat sent successfully')
else
print('[CDE CAD] Heartbeat failed: ' .. tostring(statusCode))
end
end, 'POST', json.encode({
playerCount = #GetPlayers(),
serverInfo = {
license = GetConvar('sv_licenseKey', '')
}
}), {
['Content-Type'] = 'application/json',
['x-api-key'] = Config.ApiKey
})
end
end)
911 Calls from FiveM
Create a new 911 call from your FiveM server. The call appears on the dispatch board in real time.
Requires x-api-keyRequest Body
| Field | Type | Required | Description |
|---|---|---|---|
callType | string | Yes | Type of emergency (e.g., "Robbery", "Shots Fired", "Traffic Stop") |
location | string | Yes | Street address or area name |
callerName | string | No | Name of the 911 caller |
serverName | string | No | Originating server name |
description | string | No | Detailed description of the emergency |
coordinates | object | No | GTA map coordinates |
coordinates.x | number | No | X coordinate |
coordinates.y | number | No | Y coordinate |
coordinates.z | number | No | Z coordinate |
postal | string | No | Postal code for the location |
communityId | string | No | Community ID (resolved from API key if omitted) |
Response (201 Created)
{
"success": true,
"_id": "665a1b2c3d4e5f6a7b8c9d0e",
"incidentNumber": "911-20240601-0042",
"message": "911 call created successfully"
}
Lua Example
function Send911Call(callType, location, description, callerName)
local playerPed = PlayerPedId()
local coords = GetEntityCoords(playerPed)
local street, _ = GetStreetNameAtCoord(coords.x, coords.y, coords.z)
local streetName = GetStreetNameFromHashKey(street)
local payload = json.encode({
callType = callType,
location = location or streetName,
callerName = callerName or GetPlayerName(PlayerId()),
serverName = Config.ServerName,
description = description or '',
coordinates = {
x = coords.x,
y = coords.y,
z = coords.z
},
postal = GetNearestPostal(coords), -- your postal resource
communityId = Config.CommunityID
})
PerformHttpRequest(Config.CadUrl .. '/api/fivem/911', function(statusCode, response, headers)
if statusCode == 201 then
local data = json.decode(response)
print('[CDE CAD] 911 call created: ' .. data.incidentNumber)
else
print('[CDE CAD] 911 call failed: ' .. tostring(statusCode))
-- Fallback: try x-payload header for Cloudflare compatibility
if statusCode == 400 then
PerformHttpRequest(Config.CadUrl .. '/api/fivem/911', function(sc, res, hdr)
if sc == 201 then
print('[CDE CAD] 911 call created via x-payload fallback')
end
end, 'POST', '', {
['Content-Type'] = 'application/json',
['x-api-key'] = Config.ApiKey,
['x-payload'] = Base64Encode(payload)
})
end
end
end, 'POST', payload, {
['Content-Type'] = 'application/json',
['x-api-key'] = Config.ApiKey
})
end
Legacy alias for the 911 call endpoint. Accepts the same body and returns the same response. Provided for backward compatibility.
Requires x-api-keyPanic Button
Trigger a panic alert for an officer. This emits a panic-button WebSocket event to all connected dispatchers and officers in the community.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
officerName | string | Yes | Name of the officer triggering panic |
officerId | string | No | Officer badge/unit ID |
location | string | No | Current location or street name |
serverName | string | No | Originating server name |
postal | string | No | Postal code for the location |
coordinates | object | No | GTA map coordinates |
coordinates.x | number | No | X coordinate |
coordinates.y | number | No | Y coordinate |
coordinates.z | number | No | Z coordinate |
communityId | string | No | Community ID (resolved from API key if omitted) |
WebSocket Event Emitted
When a panic is triggered, a panic-button event is emitted to the community's WebSocket room containing the officer name, location, coordinates, and timestamp.
Response
{
"success": true,
"message": "Panic alert triggered successfully"
}
Lua Example
function TriggerPanic(officerName, officerId)
local playerPed = PlayerPedId()
local coords = GetEntityCoords(playerPed)
local street, _ = GetStreetNameAtCoord(coords.x, coords.y, coords.z)
local streetName = GetStreetNameFromHashKey(street)
PerformHttpRequest(Config.CadUrl .. '/api/fivem/panic', function(statusCode, response, headers)
if statusCode == 200 then
local data = json.decode(response)
print('[CDE CAD] Panic triggered: ' .. data.message)
else
print('[CDE CAD] Panic failed: ' .. tostring(statusCode))
end
end, 'POST', json.encode({
officerName = officerName,
officerId = officerId or 'UNKNOWN',
location = streetName,
serverName = Config.ServerName,
postal = GetNearestPostal(coords),
coordinates = {
x = coords.x,
y = coords.y,
z = coords.z
},
communityId = Config.CommunityID
}), {
['Content-Type'] = 'application/json',
['x-api-key'] = Config.ApiKey
})
end
-- Keybind example: F9 to trigger panic
RegisterKeyMapping('panic_button', 'CAD Panic Button', 'keyboard', 'F9')
RegisterCommand('panic_button', function()
local name = GetPlayerName(PlayerId())
TriggerPanic(name, Config.OfficerId)
end, false)
LiveMap (Location Updates)
Update a unit's location on the live dispatch map. Send this periodically (every 5-10 seconds) for each active unit.
Requires X-API-Key headerRequest Body
| Field | Type | Required | Description |
|---|---|---|---|
unitId | string | Yes | Unique identifier for the unit |
unitName | string | Yes | Display name (e.g., "1-Adam-12") |
x | number | Yes | GTA V X coordinate (raw) |
y | number | Yes | GTA V Y coordinate (raw) |
z | number | No | GTA V Z coordinate (raw) |
heading | number | No | Unit heading / direction (0-360) |
job | string | No | Unit job type (e.g., "police", "ems", "fire") |
status | string | No | Unit status (e.g., "available", "busy", "en-route") |
postal | string | No | Current postal code |
communityId | string | No | Community ID (resolved from API key if omitted) |
Response
{
"success": true,
"message": "Location updated",
"unitId": "unit_1a2b3c",
"coordinates": {
"x": -432.15,
"y": -29.87
},
"postal": "342"
}
Lua Example
-- Send location updates for on-duty officers every 5 seconds
Citizen.CreateThread(function()
while true do
Citizen.Wait(5000)
if isOnDuty then
local playerPed = PlayerPedId()
local coords = GetEntityCoords(playerPed)
local heading = GetEntityHeading(playerPed)
PerformHttpRequest(Config.CADEndpoint, function(statusCode, response, headers)
if statusCode ~= 200 then
print('[LiveMap] Update failed: ' .. tostring(statusCode))
end
end, 'POST', json.encode({
unitId = Config.UnitId or GetPlayerServerId(PlayerId()),
unitName = Config.UnitName or GetPlayerName(PlayerId()),
x = coords.x,
y = coords.y,
z = coords.z,
heading = heading,
job = PlayerJob or 'police',
status = DutyStatus or 'available',
postal = GetNearestPostal(coords),
communityId = Config.CommunityID
}), {
['Content-Type'] = 'application/json',
['X-API-Key'] = Config.APIKey
})
end
end
end)
Retrieve all active unit locations for a community. Useful for building custom map displays or checking which units are being tracked.
Requires API KeyQuery Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
communityId | string | Yes | The community to retrieve locations for |
Response
[
{
"unitId": "unit_1a2b3c",
"unitName": "1-Adam-12",
"x": -432.15,
"y": -29.87,
"z": 39.12,
"heading": 180.5,
"job": "police",
"status": "available",
"postal": "342",
"lastUpdate": "2024-06-01T12:34:56.789Z"
},
{
"unitId": "unit_4d5e6f",
"unitName": "Medic-3",
"x": 310.22,
"y": -590.88,
"z": 43.29,
"heading": 90.0,
"job": "ems",
"status": "en-route",
"postal": "128",
"lastUpdate": "2024-06-01T12:34:52.123Z"
}
]
Character Sync (FiveM-specific)
Character sync endpoints allow you to push and pull civilian data between your FiveM server and CDE CAD. This keeps character records, vehicles, and identities in sync with the CAD database.
Create or update a civilian record from FiveM. If a civilian with the same SSN exists, it will be updated; otherwise, a new record is created.
Requires API KeyRequest Body
Send the full civilian data object. Fields may include:
| Field | Type | Description |
|---|---|---|
firstName | string | Civilian first name |
lastName | string | Civilian last name |
ssn | string | Social Security Number (unique identifier) |
dateOfBirth | string | Date of birth (YYYY-MM-DD) |
gender | string | Gender |
race | string | Race/ethnicity |
address | string | Residential address |
phone | string | Phone number |
occupation | string | Current occupation |
communityId | string | Community to sync with |
Lua Example
function SyncCharacterToCAD(charData)
PerformHttpRequest(Config.CadUrl .. '/api/civilian/fivem-sync-character', function(statusCode, response, headers)
if statusCode == 200 or statusCode == 201 then
local data = json.decode(response)
print('[CDE CAD] Character synced: ' .. charData.firstName .. ' ' .. charData.lastName)
else
print('[CDE CAD] Character sync failed: ' .. tostring(statusCode))
end
end, 'POST', json.encode({
firstName = charData.firstName,
lastName = charData.lastName,
ssn = charData.ssn,
dateOfBirth = charData.dob,
gender = charData.gender,
race = charData.race,
address = charData.address,
phone = charData.phone,
occupation = charData.job,
communityId = Config.CommunityID
}), {
['Content-Type'] = 'application/json',
['x-api-key'] = Config.ApiKey
})
end
Look up a civilian record by their SSN. Returns the full civilian profile if found.
Requires API KeyPath Parameters
| Parameter | Type | Description |
|---|---|---|
ssn | string | The civilian's Social Security Number |
Lua Example
function LookupCivilian(ssn)
PerformHttpRequest(Config.CadUrl .. '/api/civilian/fivem-civilian/' .. ssn, function(statusCode, response, headers)
if statusCode == 200 then
local civilian = json.decode(response)
print('[CDE CAD] Found: ' .. civilian.firstName .. ' ' .. civilian.lastName)
-- Use civilian data in-game
elseif statusCode == 404 then
print('[CDE CAD] No civilian found with SSN: ' .. ssn)
end
end, 'GET', '', {
['x-api-key'] = Config.ApiKey
})
end
Look up a vehicle record by its license plate. Returns the full vehicle profile including registered owner information.
Requires API KeyPath Parameters
| Parameter | Type | Description |
|---|---|---|
plate | string | The vehicle's license plate number |
Lua Example
function LookupVehicle(plate)
PerformHttpRequest(Config.CadUrl .. '/api/civilian/fivem-vehicle/' .. plate, function(statusCode, response, headers)
if statusCode == 200 then
local vehicle = json.decode(response)
print('[CDE CAD] Vehicle: ' .. vehicle.make .. ' ' .. vehicle.model)
print('[CDE CAD] Owner: ' .. vehicle.ownerName)
elseif statusCode == 404 then
print('[CDE CAD] No vehicle found with plate: ' .. plate)
end
end, 'GET', '', {
['x-api-key'] = Config.ApiKey
})
end
Register a vehicle from FiveM into the CAD database. Links the vehicle to an existing civilian record.
Requires API KeyLua Example
function RegisterVehicleInCAD(vehicleData)
PerformHttpRequest(Config.CadUrl .. '/api/civilian/fivem-register-vehicle', function(statusCode, response, headers)
if statusCode == 200 or statusCode == 201 then
local data = json.decode(response)
print('[CDE CAD] Vehicle registered: ' .. vehicleData.plate)
else
print('[CDE CAD] Vehicle registration failed: ' .. tostring(statusCode))
end
end, 'POST', json.encode(vehicleData), {
['Content-Type'] = 'application/json',
['x-api-key'] = Config.ApiKey
})
end
Delete a civilian character record by SSN. This permanently removes the character from the CAD database.
Requires API KeyPath Parameters
| Parameter | Type | Description |
|---|---|---|
ssn | string | The SSN of the character to delete |
Lua Example
function DeleteCharacterFromCAD(ssn)
PerformHttpRequest(Config.CadUrl .. '/api/civilian/fivem-delete-character/' .. ssn, function(statusCode, response, headers)
if statusCode == 200 then
print('[CDE CAD] Character deleted: ' .. ssn)
else
print('[CDE CAD] Delete failed: ' .. tostring(statusCode))
end
end, 'DELETE', '', {
['x-api-key'] = Config.ApiKey
})
end
FiveM Settings (Admin Panel API)
These endpoints manage FiveM integration settings for a community. They require JWT authentication and community admin permissions.
Retrieve the current FiveM integration settings for a community.
Requires JWT + Community AdminPath Parameters
| Parameter | Type | Description |
|---|---|---|
communityId | string | The community ID |
Response
{
"fivemServerIP": "123.45.67.89",
"fivemServerPort": 30120,
"enableAutoPlateReader": true,
"enablePanicButton": true,
"enable911Integration": true,
"enableTrafficStops": false,
"enableStatusUpdates": true,
"webhookUrl": "https://discord.com/api/webhooks/..."
}
Update FiveM integration settings for a community.
Requires JWT + Community AdminRequest Body
| Field | Type | Description |
|---|---|---|
fivemServerIP | string | FiveM server IP address |
fivemServerPort | number | FiveM server port |
enableAutoPlateReader | boolean | Enable automatic plate reader integration |
enablePanicButton | boolean | Enable panic button alerts |
enable911Integration | boolean | Enable in-game 911 call forwarding |
enableTrafficStops | boolean | Enable traffic stop integration |
enableStatusUpdates | boolean | Enable unit status updates |
webhookUrl | string | Discord webhook URL for notifications |
Response
{
"success": true,
"message": "FiveM settings updated"
}
Generate a new FiveM API key for the community. The previous key is invalidated. The full key is returned only once in the response — store it securely.
Requires JWT + Community AdminResponse
{
"success": true,
"apiKey": "fvm_a1b2c3d4e5f6...full_64_hex_characters"
}
Test the connection to your FiveM server from CDE CAD. Uses a 5-second timeout to verify the server is reachable.
Requires JWT + Community AdminRequest Body
| Field | Type | Required | Description |
|---|---|---|---|
serverIP | string | Yes | IP address of the FiveM server to test |
serverPort | number | Yes | Port of the FiveM server to test |
Response (Success)
{
"success": true,
"message": "Connection successful",
"responseTime": 45
}
Response (Timeout)
{
"success": false,
"message": "Connection timed out after 5000ms"
}
Configuration Examples
Panic Button Script — config.lua
This configuration is used by the CDE CAD panic button resource for FiveM.
Config = {}
Config.CadUrl = 'https://cdecad.com'
Config.ApiKey = 'fvm_your_api_key_here'
Config.CommunityID = '1200664516858495056' -- Discord guild ID
Config.ServerName = 'My RP Server'
LiveMap Script — config.lua
This configuration is used by the CDE CAD live map tracking resource for FiveM.
Config = {}
Config.CADEndpoint = 'https://cdecad.com/api/dispatch/location-update'
Config.CommunityID = '1200664516858495056'
Config.APIKey = 'livemap-cad-key-2024'
CommunityID is your Discord server's guild ID. To find it, enable Developer Mode in Discord settings, then right-click your server name and select "Copy Server ID".
Troubleshooting
400 Bad Request — Empty Body
PerformHttpRequest). If you are receiving 400 errors despite sending a valid body, use the x-payload header as a fallback.
Encode your JSON payload as Base64 and send it in the x-payload header:
-- Fallback for Cloudflare body stripping
local payload = json.encode({
callType = 'Robbery',
location = 'Vinewood Blvd'
})
PerformHttpRequest(Config.CadUrl .. '/api/fivem/911', function(statusCode, response, headers)
print('[CDE CAD] Status: ' .. tostring(statusCode))
end, 'POST', '', {
['Content-Type'] = 'application/json',
['x-api-key'] = Config.ApiKey,
['x-payload'] = Base64Encode(payload)
})
The server will check for the x-payload header, decode it, and use it as the request body if the normal body is empty.
401 Unauthorized
| Cause | Solution |
|---|---|
| Missing API key | Ensure the x-api-key header is included in every request. |
| Invalid API key | Verify the key matches the one generated in the Admin Panel. Keys start with fvm_. |
| Key was regenerated | If someone generated a new key, the old key is invalidated. Update your config.lua with the new key. |
| Wrong header name | Use x-api-key (lowercase). Some endpoints also accept X-API-Key. |
429 Too Many Requests
| Endpoint Group | Limit | Window |
|---|---|---|
| 911 Calls | 10 requests | 1 minute per community |
| General FiveM API | 120 requests | 1 minute per API key |
| High-Impact (panic) | 20 requests | 1 minute per API key |
If you hit rate limits, implement exponential backoff or reduce your request frequency. For location updates, 5-10 second intervals are recommended instead of every frame.
-- Simple retry with backoff
function SafeRequest(url, method, payload, headers, retries)
retries = retries or 3
local attempt = 0
local function doRequest()
attempt = attempt + 1
PerformHttpRequest(url, function(statusCode, response, hdrs)
if statusCode == 429 and attempt < retries then
-- Wait before retrying (exponential backoff)
Citizen.SetTimeout(attempt * 2000, doRequest)
elseif statusCode >= 200 and statusCode < 300 then
print('[CDE CAD] Request succeeded')
else
print('[CDE CAD] Request failed: ' .. tostring(statusCode))
end
end, method, payload, headers)
end
doRequest()
end
Common Debugging Tips
| Issue | Debug Step |
|---|---|
| No response from CAD | Check that Config.CadUrl is correct and includes https://. Test the URL in a browser first. |
| Coordinates not showing on map | Verify you are sending raw GTA coordinates. Do not transform them before sending. |
| 911 calls not appearing | Check that enable911Integration is enabled in the Admin Panel FiveM settings. |
| Panic not triggering alerts | Verify enablePanicButton is enabled and dispatchers are connected to the WebSocket. |
| Community not found | Ensure the communityId matches your Discord guild ID and the community exists in CDE CAD. |