Exports
Resources register routes from the server side. Get a handle to the gateway once and use it for every call:
lua
local api = tm.exports.get('tm_api')A handle waits for tm_api to start, so ensure order does not matter.
registerRoute(method, path, handler, description?)
Registers a route. Both path styles are accepted:
- Short path (endpoint only): the resource name is added in front.
- Full path (starts with
/{resourceName}/): used as is, with no double prefix.
lua
-- Called from a resource named 'myresource'
api:registerRoute('GET', '/status', function(res, params, body, helpers)
helpers.success({ online = true })
end, 'Returns service status')
-- stored as /myresource/status
api:registerRoute('POST', '/action', function(res, params, body, helpers)
if not body or not body.target then
return helpers.fail('Missing target', 400)
end
helpers.success({ done = true })
end, 'Perform an action')
-- stored as /myresource/actionHandler arguments:
| Argument | Type | Description |
|---|---|---|
res | table | The FiveM HTTP response object. |
params | table | Path parameters taken from the URL. |
body | table or nil | The decoded JSON body (POST and PUT only). |
helpers.success | function(data, status?) | Sends { success = true, data = ... } (default status 200). |
helpers.fail | function(message, status?) | Sends { success = false, error = ... } (default status 400). |
Returns true, or false, reason (invalid method or path, handler is not a function, or the route already exists).
registerRouteRaw(method, path, handler, description?, owner?)
Same as registerRoute, except the handler receives only res, params and body (no helpers) and the path is not prefixed, so pass the full path.
lua
api:registerRouteRaw('GET', '/myresource/raw', function(res, params, body)
res.writeHead(200, { ['Content-Type'] = 'text/plain' })
res.send('ok')
end, 'Raw response example')unregisterRoute(method, path)
Removes a route. Only the resource that registered it can remove it. Routes are also removed on their own when the owning resource stops.
lua
api:unregisterRoute('GET', '/status')Path rules
registerRoute and unregisterRoute check whether the first segment already matches the calling resource name.
| Path you pass | Resource name | Stored and served as |
|---|---|---|
/status | myresource | /myresource/status |
/myresource/status | myresource | /myresource/status |
/:id/kick | myresource | /myresource/:id/kick |
Full example
lua
CreateThread(function()
local api = tm.exports.get('tm_api')
api:registerRoute('GET', '/online', function(res, params, body, helpers)
local players = {}
for _, src in ipairs(GetPlayers()) do
players[#players + 1] = { id = tonumber(src), name = GetPlayerName(src) }
end
helpers.success(players)
end, 'List all online players')
api:registerRoute('POST', '/:id/kick', function(res, params, body, helpers)
local src = tonumber(params.id)
if not src or not GetPlayerName(src) then
return helpers.fail('Player not found', 404)
end
DropPlayer(tostring(src), body and body.reason or 'No reason provided')
helpers.success({ kicked = src })
end, 'Kick a player')
end)