W-DevelopmentW-Development
Engineering Updated 9 min read

Calling web APIs from FiveM scripts

Use PerformHttpRequest in FiveM: GET and POST with JSON, headers and auth, awaiting results with promises, error handling and keeping API keys server-side.

Overview

Discord bots, web panels, licence checks, analytics — sooner or later a resource needs to talk to the web. FiveM’s PerformHttpRequest does it from Lua with a callback; wrapped in a promise it reads like a normal function call.

A basic request

server.lualua
PerformHttpRequest('https://api.example.com/status', function(status, body, headers, err)
    if status ~= 200 then
        print(('request failed: %s %s'):format(status, err or ''))
        return
    end
    local data = json.decode(body)
    print('players online on the website:', data.online)
end, 'GET')

POST with JSON and headers

server.lualua
local API_KEY = GetConvar('myres_api_key', '')

local function post(url, payload, cb)
    PerformHttpRequest(url, cb, 'POST', json.encode(payload), {
        ['Content-Type'] = 'application/json',
        ['Authorization'] = 'Bearer ' .. API_KEY,
    })
end

Store the key with set myres_api_key "..." (server-only, not setr) — see convars.

Awaiting the result

server.lualua
local function request(url, method, body, headers)
    local p = promise.new()
    PerformHttpRequest(url, function(status, resBody, resHeaders, err)
        p:resolve({ status = status, body = resBody, headers = resHeaders, error = err })
    end, method or 'GET', body or '', headers or {})
    return Citizen.Await(p)
end

CreateThread(function()
    local res = request('https://api.example.com/status')
    if res.status == 200 then print(res.body) end
end)

Citizen.Await must run inside a thread, event handler or callback. Thread basics: threads and Wait.

Safety and limits

  • Never put API keys in client files — every player can read them.
  • Respect the API’s rate limits; queue or batch requests.
  • Do not make requests per frame or per player action without caching.
  • Validate responses before using them in game logic.
  • For logging to Discord, see webhook logging.

JavaScript alternative

Server-side JavaScript resources run on Node.js and can use fetch or npm HTTP clients directly — see TypeScript scripts.

Frequently asked questions

How do I make an HTTP request in FiveM Lua?

Call PerformHttpRequest(url, callback, method, data, headers); the callback receives status code, body, headers and error data.

How do I send JSON?

Pass json.encode(table) as the data and set the Content-Type: application/json header.

Can I wait for the response?

Yes — resolve a promise in the callback and Citizen.Await it inside a thread.

Should I call APIs from the client?

Not with secrets. Make authenticated requests from the server.

Need this built, not just explained?

Premium ESX, QBCore & Qbox scripts with instant delivery — or a custom resource, React NUI and the web stack around your server, built to spec.

Related guides