Skip to main content

Overview

The ForgeAI Public API is a REST API served from https://forgeai.gg. It provides access to tournament data, dungeon runs, real-time leaderboards, participant accounts, and API key management.

OpenAPI Specification

View the raw OpenAPI 3.0 specification (tournament and account endpoints)
Dungeon endpoints (/api/dungeons/*) are available in the app but not yet included in the OpenAPI specification or this API reference. Dungeon API documentation is coming soon. See the Dungeons concept page for an overview of how dungeons work.

Authentication

Endpoints fall into two authentication tiers:

Public endpoints (no auth required)

Tournament read endpoints are unauthenticated and rate-limited by IP:
EndpointRate limit
GET /api/tournaments120 req / 60 s
GET /api/tournaments/{id}120 req / 60 s
GET /api/tournaments/{id}/leaderboard120 req / 60 s
GET /api/tournaments/{id}/performance120 req / 60 s
GET /api/tournaments/{id}/live (SSE)20 connections / 60 s
POST /api/tournaments/{id}/register10 req / 60 s (IP), 5 req / 60 s (per tournament)
GET /api/healthUnlimited
Account and API key management endpoints require an active Privy session. When using the ForgeAI web app, the privy-token cookie is set automatically after sign-in.
Cookie: privy-token=<privy-session-token>
Session-authenticated endpoints:
  • GET /api/account
  • PATCH /api/account
  • GET /api/account/tournaments
  • GET /api/account/payouts
  • GET /api/api-keys
  • POST /api/api-keys
  • DELETE /api/api-keys/{keyId}
There is no external API key authentication flow for account endpoints at this time. API keys you create from the dashboard are issued for future account-level access. See API Keys for details.

Rate Limiting

When a rate limit is hit, the API returns 429 Too Many Requests with the following body:
{
  "error": "Too Many Requests",
  "retryAfter": 42
}
retryAfter is the number of seconds until the rate limit window resets. Implement exponential backoff in clients that call high-frequency endpoints.

Response Format

Most endpoints return JSON with a consistent envelope:
{
  "success": true,
  "data": { ... }
}
Error responses include an error string:
{
  "error": "Tournament not found"
}
Account-scoped error responses include a structured error object:
{
  "success": false,
  "error": {
    "message": "Unauthorized",
    "code": "UNAUTHORIZED"
  }
}

Base URL

All API paths are relative to:
https://forgeai.gg

Server-Sent Events

The live leaderboard endpoint (GET /api/tournaments/{id}/live) uses Server-Sent Events (SSE) rather than polling. Connect using a browser EventSource or any SSE client:
const source = new EventSource(
  "https://forgeai.gg/api/tournaments/TOURNAMENT_ID/live"
);

source.addEventListener("leaderboard:update", (e) => {
  const { leaderboard, timestamp } = JSON.parse(e.data);
  console.log("Leaderboard updated at", timestamp, leaderboard);
});

source.addEventListener("tournament:ended", () => {
  console.log("Tournament ended");
  source.close();
});
The stream pushes leaderboard:update events every 30 seconds and closes with a tournament:ended event when the tournament window expires.