Skip to the docs
ULTRA WARDevelopers

v1Developers

Galactic Leaderboard API

Show Ultra War’s Galactic Leaderboard on your own site, stream overlay or Discord bot. Free, read-only JSON: no key, no sign-up, open CORS.

Endpoints

GEThttps://ultrawar.io/api/v1/leaderboard

One page of a board: ranks, names and numbers.

GEThttps://ultrawar.io/api/v1/leaderboard/boards

Every board with its name, description, unit and periods, plus the factions: build your menus from it.

Parameters

NameDefaultValues
boardrenownA board id (below, or /boards).
periodthe board’s firstweek (from Monday 00:00 UTC) or all.
factionallall or solari, hegemony, nereid, fungus, synthari, spacers, veilborn, gobbos.
limit25How many rows, 1 to 100.
offset0Rows to skip, 0 to 1000 (for paging).

Anything else, or a parameter given twice, is a 400. Leave out a parameter to get its default.

Boards

idBoardvalue countsPeriods
renownRenownRenownweek all
gcCredits earnedGCweek all
piratesPirates downedpiratesweek all
oreOre soldOreweek all
chartedSystems chartedsystemsweek all
stationColony StationGC dues
extra: Colony Station tier
week all
standingFaction standingstandingall
victoriesSkirmish victoriesvictories
extra: victories at Standard
week all
frontFront contributionwar scoreweek all
worldsWorlds takenworldsweek all

Every board counts only what the game’s servers checked themselves. How each is counted is in description from /boards.

Example

Request
GET https://ultrawar.io/api/v1/leaderboard?board=pirates&period=week&limit=3
Response 200 (sample data)
{
  "v": 1,
  "board": "pirates",
  "period": "week",
  "faction": "all",
  "limit": 3,
  "offset": 0,
  "refreshedAt": "2026-10-05T14:07:00.000Z",
  "weekStart": "2026-10-05",
  "total": 214,
  "unit": "pirates",
  "extra": null,
  "rows": [
    {
      "rank": 1,
      "name": "Halcyon",
      "label": "Halcyon",
      "faction": "solari",
      "value": 48,
      "extra": null,
      "valueText": "48 pirates"
    },
    {
      "rank": 2,
      "name": null,
      "label": "A Nereid Star Captain",
      "faction": "nereid",
      "value": 41,
      "extra": null,
      "valueText": "41 pirates"
    },
    {
      "rank": 3,
      "name": "Scrapjaw",
      "label": "Scrapjaw",
      "faction": "gobbos",
      "value": 39,
      "extra": null,
      "valueText": "39 pirates"
    }
  ],
  "factionTotals": {
    "solari": {
      "value": 412,
      "players": 31
    },
    "nereid": {
      "value": 388,
      "players": 27
    }
  },
  "attribution": "Data from Ultra War (https://ultrawar.io)",
  "docs": "https://ultrawar.io/developers/"
}

Fields

v
Always 1 in this version.
board, period, faction, limit, offset
The query as answered, defaults filled in.
refreshedAt
When the standings were last drawn up (ISO 8601, UTC). They refresh every hour.
weekStart
The Monday (UTC) that starts the current week, YYYY-MM-DD.
total
How many Star Captains are ranked on this board, period and faction.
unit, extra
What value counts, and what extra holds (null when the board has none).
rows[].rank
The rank; ties share one. With a faction filter, the rank within that faction.
rows[].name
The player’s name as the game shows it, or null when they keep it hidden.
rows[].label
What to show: the name, or “A Solari Star Captain” for a hidden name.
rows[].faction
The faction id, or null.
rows[].value, rows[].extra
The numbers (extra: a Colony Station tier or Standard victories; else null).
rows[].valueText
The value as the game words it, e.g. “48 pirates”.
factionTotals
Per faction: the board added up (value; an average for Faction standing) and how many players.
attribution, docs
The credit line to show, and this page.

New fields and boards may be added in v1: ignore what you do not know.

Code

curl
curl "https://ultrawar.io/api/v1/leaderboard?board=renown&period=week&limit=10"
JavaScript (browser or Node 18+)
const url = new URL('https://ultrawar.io/api/v1/leaderboard');
url.search = new URLSearchParams({ board: 'pirates', period: 'week', limit: '10' });

const res = await fetch(url);
const data = await res.json();
if (!res.ok) throw new Error(data.error + ': ' + data.message);

for (const row of data.rows) console.log(row.rank, row.label, row.valueText);
console.log(data.attribution);
Discord bot (discord.js v14)
// /leaderboard [board] [period]: a minimal discord.js v14 slash command
import { Client, GatewayIntentBits, EmbedBuilder, escapeMarkdown } from 'discord.js';

const API = 'https://ultrawar.io/api/v1/leaderboard';
const client = new Client({ intents: [GatewayIntentBits.Guilds] });

client.on('interactionCreate', async (i) => {
  if (!i.isChatInputCommand() || i.commandName !== 'leaderboard') return;
  const q = new URLSearchParams({ board: i.options.getString('board') ?? 'renown', limit: '10' });
  const period = i.options.getString('period');   // week or all; leave it out for the board's default
  if (period) q.set('period', period);

  const res = await fetch(API + '?' + q);
  const data = await res.json();
  if (!res.ok) return i.reply({ content: data.message, ephemeral: true });

  const lines = data.rows.map((r) => `**${r.rank}.** ${escapeMarkdown(r.label)} · ${r.valueText}`);
  await i.reply({ embeds: [new EmbedBuilder()
    .setTitle(`Galactic Leaderboard · ${data.board} (${data.period})`)
    .setDescription(lines.join('\n') || 'No Star Captains ranked yet.')
    .setFooter({ text: data.attribution })] });
});

client.login(process.env.DISCORD_TOKEN);

Caching and limits

Errors

Errors are JSON too: {"v":1,"error":"invalid-limit","message":"…","param":"limit"}.

StatuserrorMeaning
400unknown-paramA parameter the endpoint does not take (me is game-only and never answered here).
400duplicate-paramThe same parameter twice.
400unknown-boardNot a board id from /boards.
400invalid-periodperiod is not week or all.
400period-unavailableThe board has no such period (Faction standing is all time only).
400invalid-factionNot all or a faction id.
400invalid-limitlimit is not a whole number from 1 to 100.
400invalid-offsetoffset is not a whole number from 0 to 1000.
404not-foundNo such endpoint.
405method-not-allowedOnly GET, HEAD and OPTIONS.
429rate-limitedToo many uncached requests from your address; wait for Retry-After seconds.
502unavailableThe leaderboard could not be read just now; try again shortly.
503not-openThe standings are not available yet.

Privacy, credit and stability