Example

Inventory System

A full CRUD inventory using all four HTTP methods. GET fetches with Deflate compression, POST adds items, PUT updates slots, DELETE removes items.

Route map

MethodRouteDescription
GETinventoryFetch all items (compressed)
GETinventory/:slot=intFetch single slot
POSTinventoryAdd item to first free slot
PUTinventory/:slot=intSwap/update a slot
DELETEinventory/:slot=intRemove item from slot

Server: InventoryServer.luau

local RoExpress = require(game.ReplicatedStorage.RoExpress)
local app       = RoExpress.GetApp()
local DS        = game:GetService("DataStoreService"):GetDataStore("Inventory")
local cache     = {}  -- { [userId] = { [slot] = item } }

local function getInv(player)
    return cache[player.UserId] or {}
end

game.Players.PlayerAdded:Connect(function(p)
    local ok, data = pcall(DS.GetAsync, DS, tostring(p.UserId))
    cache[p.UserId] = (ok and data) or {}
end)

game.Players.PlayerRemoving:Connect(function(p)
    pcall(DS.SetAsync, DS, tostring(p.UserId), cache[p.UserId])
    cache[p.UserId] = nil
end)

-- GET all items (large table | compress it)
app:Get("inventory", function(req, res)
    res:Send(getInv(req.player))
end, { compress = true })

-- GET single slot
app:Get("inventory/:slot=int[1,40]", function(req, res)
    local inv = getInv(req.player)
    res:Send(inv[req.params.slot])
end)

-- POST add item to first free slot
app:Post("inventory", function(req, res)
    local inv  = getInv(req.player)
    local item = req.data
    for slot = 1, 40 do
        if not inv[slot] then
            inv[slot] = item
            res:Send({ slot = slot })
            return
        end
    end
    res:Status(409):Error("Inventory full")
end)

-- PUT update/swap slot
app:Put("inventory/:slot=int[1,40]", function(req, res)
    getInv(req.player)[req.params.slot] = req.data.item
    res:Send()
end)

-- DELETE remove item
app:Delete("inventory/:slot=int[1,40]", function(req, res)
    getInv(req.player)[req.params.slot] = nil
    res:Send()
end)

Client: InventoryClient.luau

local network = RoExpress.GetNetwork()

-- Load full inventory on spawn (auto-decompressed)
network:GetAsync("inventory")
    :Then(function(res)
        buildInventoryUI(res.data)
    end)

-- Add item to server
local function addItem(itemData)
    network:Post("inventory", itemData, function(res)
        if res.type == "success" then
            setUISlot(res.data.slot, itemData)
        end
    end)
end

-- Remove item
local function removeItem(slot)
    network:Delete("inventory/" .. slot, nil, function(res)
        if res.type == "success" then
            clearUISlot(slot)
        end
    end)
end

See also

App | routing API  ·  Network | client requests  ·  Codec | compression  ·  Router | typed params & range constraints