Beta documentation. This is an early preview — content is still in active development. Feedback helps shape the final release. Share your thoughts or join the discussion.

HTTP Client

The `http` library lets your Lua scripts talk to external APIs — payment gateways, email services, weather data, AI models. SSRF protection blocks private IP...

On this page

Call the outside world

The http library lets your Lua scripts talk to external APIs — payment gateways, email services, weather data, AI models. SSRF protection blocks private IPs and internal networks.

Function reference

Function Description
http.get(url, opts?) HTTP GET
http.post(url, opts?) HTTP POST
http.put(url, opts?) HTTP PUT
http.patch(url, opts?) HTTP PATCH
http.delete(url, opts?) HTTP DELETE
http.head(url, opts?) HTTP HEAD
http.request(method, url, opts?) Any HTTP method

Response format

Every call returns a table:

{
    status = 200,                  -- HTTP status code
    body = "response content",     -- raw body string
    headers = {                    -- response headers
        ["content-type"] = "application/json"
    }
}

GET request

local res = http.get("https://api.github.com/users/wapka")

if res.status == 200 then
    local data = decoder.json(res.body)
    return { repos = data.public_repos }
end

return ctx:error("GitHub API failed", 502)

POST with JSON

local res = http.post("https://api.example.com/webhook", {
    body = encoder.json({ event = "user.created", id = 42 }),
    headers = { ["content-type"] = "application/json" }
})

Setting headers and timeout

local res = http.get("https://api.example.com/data", {
    headers = {
        ["authorization"] = "Bearer " .. api_key,
        ["accept"] = "application/json"
    },
    timeout = 10,            -- seconds
    user_agent = "MyWapkaApp/1.0"
})

SSL verification

-- Production: keep SSL verification (default)
http.get("https://api.example.com")

-- Development only: skip SSL check
http.get("https://localhost:8443", { verify_ssl = false })

All options

Option Type Default Description
body string Raw request body
headers table {} Request headers (lowercase keys)
timeout number 10 Seconds before giving up
user_agent string Custom User-Agent header
verify_ssl boolean true Validate SSL certificate

Practical: call a payment API

app:post("/checkout", function(ctx)
    local amount = tonumber(req.post.amount)

    local res = http.post("https://api.stripe.com/v1/charges", {
        body = "amount=" .. (amount * 100) .. "&currency=usd",
        headers = {
            ["authorization"] = "Bearer " .. STRIPE_SECRET,
            ["content-type"] = "application/x-www-form-urlencoded"
        }
    })

    if res.status ~= 200 then
        log.error("Stripe failed: " .. res.body)
        ctx:flash("error", "Payment failed. Please try again.")
        return ctx:redirect("/checkout")
    end

    log.info("Payment successful: $" .. amount)
    ctx:flash("success", "Payment received!")
    return ctx:redirect("/thank-you")
end)

Practical: fetch and display weather

app:get("/weather/:city", function(ctx)
    local city = url.encode(ctx.params.city)
    local res = http.get("https://api.openweathermap.org/data/2.5/weather?q="
        .. city .. "&appid=" .. WEATHER_KEY)

    if res.status ~= 200 then
        return ctx:error("Weather data unavailable", 502)
    end

    local data = decoder.json(res.body)
    return ctx:render("weather", {
        city = data.name,
        temp = math.floor(data.main.temp - 273.15),
        description = data.weather[1].description
    })
end)

Next: URL Utilities — parse, build, and encode URLs.

Previous Standard Library Overview Next URL Utilities