Forge API

Docs

Forge API

HTTP API for games and backends. Use the API key from your linked group.

Base URL

https://api.rankforge.top/api/v1

Auth header

X-API-Key: your-key

Rate limits

60/min · 10/5s burst

Get live in four moves

  1. Buy or claim a key from pricing.
  2. Link your group and authorize RankForge on the group page.
  3. Enable HTTP requests in Studio (Game Settings → Security).
  4. Call routes with X-API-Key.

Quick status check

lua
local HttpService = game:GetService("HttpService")
local BASE_URL = "https://api.rankforge.top/api/v1"

local response = HttpService:RequestAsync({
    Url = BASE_URL .. "/status",
    Method = "GET"
})

local data = HttpService:JSONDecode(response.Body)
print("API Status:", data.status)

Roblox SDK (ForgeAPISDK v2)

For games, drop the ForgeAPISDK ModuleScript under ServerScriptService (keep Core, Extras, and Samples). Pass your RankForge API key from the dashboard.

lua
local ForgeAPISDK = require(game.ServerScriptService.ForgeAPISDK)
local api = ForgeAPISDK.new({
    ApiKey = "YOUR_API_KEY_HERE",
})

local status = api.System:Status()
print(status.ok, status.data and status.data.status)

local ranked = api.Ranking:Set(player, 5)
if ranked.ok then
    print(ranked.data.message)
else
    warn(ranked.error.code, ranked.error.message)
end

-- Namespaces: System, Ranking, Groups, Xp, Gamepass, Quota, Moderation, Events, Applications
-- Extras.QuotaDuty.bind({ api = api, dutyTeamName = "On Duty" })

Endpoints

Status

GET/api/v1/status

Ping the Forge API and confirm it is online.

Response

json
{
  "success": true,
  "status": "online",
  "timestamp": "2026-01-01T00:00:00.000Z"
}

Ranking

POST/api/v1/rankAuth required

Hard-set a Roblox user to a rank in the group bound to your key. Authorize RankForge on the group page first.

Request body

json
{
  "userId": 123456789,
  "rankId": 5
}

Response

json
{
  "success": true,
  "message": "Successfully ranked user 123456789 in group 12345 to 5.",
  "performedBy": "1234567890",
  "result": { "name": "Member", "rank": 5 }
}

Lua example

lua
local HttpService = game:GetService("HttpService")

local API_KEY = "your-api-key-here"
local BASE_URL = "https://api.rankforge.top/api/v1"

local function rankUser(userId, rankId)
    local response = HttpService:RequestAsync({
        Url = BASE_URL .. "/rank",
        Method = "POST",
        Headers = {
            ["Content-Type"] = "application/json",
            ["X-API-Key"] = API_KEY
        },
        Body = HttpService:JSONEncode({
            userId = userId,
            rankId = rankId
        })
    })

    return HttpService:JSONDecode(response.Body)
end

local result = rankUser(123456789, 5)
print(result.success, result.message)
GET/api/v1/groups/:groupId/rolesAuth required

List roles for a group your key is authorized for.

Response

json
{
  "success": true,
  "roles": [
    { "id": 123, "name": "Guest", "rank": 0 },
    { "id": 124, "name": "Member", "rank": 1 },
    { "id": 125, "name": "Admin", "rank": 255 }
  ]
}
GET/api/v1/groups/:groupId/members/:userIdAuth required

Read a member’s current rank in your group.

Response

json
{
  "success": true,
  "userId": 123456789,
  "groupId": 12345,
  "rank": {
    "id": 5,
    "name": "Member"
  }
}

XP & progression

POST/api/v1/xpAuth required

Add or subtract XP for a Roblox user. May auto-promote when thresholds clear.

Request body

json
{
  "userId": 123456789,
  "amount": 25
}

Response

json
{
  "success": true,
  "xp": 125,
  "promotion": null
}
GET/api/v1/xp/:userIdAuth required

Read a member’s XP and quota points.

Response

json
{
  "success": true,
  "userId": 123456789,
  "xp": 125,
  "quotaPoints": 3,
  "quotaPeriod": "2026-W18"
}
POST/api/v1/gamepass/claimAuth required

Check gamepass ownership and rank the user to the linked progression role. Omit gamePassId to sync all configured passes.

Request body

json
{
  "userId": 123456789,
  "gamePassId": 987654321
}

Response

json
{
  "success": true,
  "claimed": true,
  "rank": { "name": "VIP", "rank": 50 }
}

Quota (in-game playtime)

GET/api/v1/quota/configAuth required

Minutes per point (owner setting) and which ranks require a weekly quota.

Response

json
{
  "success": true,
  "minutesPerPoint": 30,
  "period": "2026-W18",
  "ranks": [{ "robloxRank": 10, "required": 5 }]
}
GET/api/v1/quota/:userIdAuth required

Weekly quota status for a player (points, required, Fulfilled / Not fulfilled).

Response

json
{
  "success": true,
  "userId": 123456789,
  "quota": {
    "points": 2,
    "required": 5,
    "quotaEnabled": true,
    "fulfilled": false,
    "statusLabel": "Not fulfilled"
  }
}
POST/api/v1/quota/session/startAuth required

Call when the player joins the duty team. Starts the playtime timer. No heartbeats needed.

Request body

json
{ "userId": 123456789 }

Response

json
{
  "success": true,
  "sessionActive": true,
  "minutesPerPoint": 30
}

Lua example

lua
local HttpService = game:GetService("HttpService")
local API_KEY = "your-api-key-here"
local BASE = "https://api.rankforge.top/api/v1"

local function quotaRequest(path, body)
    local res = HttpService:RequestAsync({
        Url = BASE .. path,
        Method = "POST",
        Headers = {
            ["Content-Type"] = "application/json",
            ["X-API-Key"] = API_KEY,
        },
        Body = HttpService:JSONEncode(body),
    })
    return HttpService:JSONDecode(res.Body)
end

-- On Team.PlayerAdded (duty team):
quotaRequest("/quota/session/start", { userId = player.UserId })

-- On leave team / PlayerRemoving:
quotaRequest("/quota/session/stop", { userId = player.UserId })
POST/api/v1/quota/session/stopAuth required

Call when the player leaves the duty team (also on PlayerRemoving). Awards floor(elapsed / minutesPerPoint).

Request body

json
{ "userId": 123456789 }

Response

json
{
  "success": true,
  "sessionActive": false,
  "awarded": 2,
  "elapsedSeconds": 3900,
  "minutesPerPoint": 30,
  "quota": { "points": 2, "required": 5, "statusLabel": "Not fulfilled" }
}

Moderation

POST/api/v1/moderationAuth required

Warn, suspend, unsuspend, blacklist, or unblacklist a Roblox user.

Request body

json
{
  "action": "warn",
  "userId": 123456789,
  "reason": "Spam",
  "durationHours": 24
}

Response

json
{
  "success": true,
  "result": { "ok": true }
}

Events

GET/api/v1/eventsAuth required

List events. Optional query: status, limit (default 30).

Response

json
{
  "success": true,
  "events": [
    {
      "_id": "…",
      "name": "Training",
      "status": "active",
      "xpAward": 10,
      "quotaAward": 1
    }
  ]
}
POST/api/v1/eventsAuth required

Create an event.

Request body

json
{
  "name": "Training",
  "type": "drill",
  "startsAt": "2026-05-01T18:00:00.000Z",
  "xpAward": 10,
  "quotaAward": 1
}

Response

json
{
  "success": true,
  "event": { "_id": "…", "name": "Training", "status": "active" }
}
POST/api/v1/events/:eventId/attendAuth required

Mark attendance for a Roblox user.

Request body

json
{
  "userId": 123456789,
  "discordId": "optional"
}

Response

json
{
  "success": true,
  "attended": true
}
POST/api/v1/events/:eventId/finishAuth required

Finish an event and award XP / quota to attendees.

Response

json
{
  "success": true,
  "awarded": 12
}

Applications

GET/api/v1/applicationsAuth required

List application responses. Optional query: status (default pending), limit.

Response

json
{
  "success": true,
  "applications": [
    { "_id": "…", "status": "pending", "robloxUserId": 123456789 }
  ]
}
POST/api/v1/applications/:responseId/reviewAuth required

Pass or fail an application response.

Request body

json
{
  "pass": true,
  "note": "Welcome"
}

Response

json
{
  "success": true,
  "application": { "_id": "…", "status": "passed" }
}

Errors & limits

CodeMeaning
400Bad request, missing or invalid body fields.
401Unauthorized, missing X-API-Key header.
403Forbidden, key expired, revoked, or wrong group.
429Rate limited by RankForge, respect Retry-After / remaining headers. Separate from Roblox Open Cloud limits (those are retried server-side).
500Internal or upstream failure after RankForge already retried Roblox. Safe to retry with backoff.
502Roblox Open Cloud failed after retries (rate limit or outage). Retry later with backoff.

Limits

  • Per API key60 / min
  • Burst10 / 5s
  • Unauthed IP120 / min

Response headers

  • X-RateLimit-Limit

    Max requests in the window

  • X-RateLimit-Remaining

    Requests left in this window

  • X-RateLimit-Reset

    Seconds until the window resets

  • Retry-After

    Wait seconds after a 429

Roblox Open Cloud

Ranking writes (promote, demote, joins) call Roblox Open Cloud from Ranking-API. RankForge retries those upstream calls on 429 and transient 5xx, preferring Roblox's Retry-After header, otherwise exponential backoff with jitter (up to 3 retries). Permanent client errors (400 / 401 / 403 / 404) are not retried.

Still handle RankForge 429s

Server-side Roblox retries do not replace your client backoff. If the Forge API returns 429, wait for Retry-After before calling again.