Friends of Risk

Friends of Risk Open API

Free, keyless, read-only JSON API for community data: users, badges, tournaments, the RISK calendar, game settings, leaderboards and game statistics. Please be gentle — cache what you can and don't hammer it.

How it works

  • Base URL: https://friendsofrisk.com/openapi/
  • Call a command as /openapi/<command>, with one parameter as /openapi/<command>/<param>/<value>, or classic query-string style /openapi.php?command=<command>&param=value.
  • Commands marked GET/POST also accept the parameters as a JSON body: curl -X POST -H "Content-Type: application/json" -d '{"userid":"..."}' https://friendsofrisk.com/openapi/getUserProfile
  • Responses are JSON (UTF-8). Errors come back as {"error": "..."} with a 400/404 status.
  • All ids are Discord snowflakes handled as strings — they overflow ordinary 64-bit floats, so never parse them as numbers.
  • No authentication and no write operations — everything here is public community data.
  • Rate limit: 60 requests per minute per client. Exceeding it returns HTTP 429 with a Retry-After header — back off and cache responses on your side.

getUsers GET

Every registered Friends of Risk user with their public profile basics.

Parameters: —

Example request
https://friendsofrisk.com/openapi/getUsers
Example response (trimmed)
[
  {
    "discordid": "796768778977148938",
    "name": "eirik",
    "color": "Purple",
    "country": "NO",
    "avail_lastupdate": "2026-08-12 19:33:41",
    "timezone": "Europe/Oslo",
    "bestplace_ffa": "rankno1",
    "bestplace_1v1": "first",
    "bestplace_team": ""
  }, ...
]

getUser GET

One user by Discord id, including their registered availability (the next gamecount preferred game times).

Parameters: userid (Discord id, required), gamecount (optional, default 1)

Example request
https://friendsofrisk.com/openapi/getUser/userid/796768778977148938
Example response (trimmed)
{
  "discordid": "796768778977148938",
  "name": "eirik",
  "color": "Purple",
  "country": "NO",
  "timezone": "Europe/Oslo",
  "bestplace_ffa": "rankno1",
  "availability": ["2026-08-30 19:00:00"]
}

getUserProfile GET/POST

Everything public from a player's profile in one call: the user record, every badge they have earned, their placement on every leaderboard they appear on, tournament signup count and their aggregated tournament-game stats.

Parameters: userid (Discord id, required)

Example request
https://friendsofrisk.com/openapi/getUserProfile/userid/796768778977148938
Example response (trimmed)
{
  "discordid": "796768778977148938",
  "name": "eirik",
  "country": "NO",
  "bestplace_ffa": "rankno1",
  "badges": [
    { "id": 219, "name": "Discord member 5 years", "category": "Discord", "earned": "2026-08-29" }, ...
  ],
  "leaderboards": {
    "sabrffa": { "rank": 12, "score1": 431, "score2": 25, "title": "Sabr FFA ranking" },
    "ffaelo": { "rank": 4, "score1": 1287, "score2": 210, "title": "FFA ELO ranking" }
  },
  "tournament_signups": 31,
  "allgames_stats": { "games": 208, "won": 45, "winrate": "21.63", "favmap": "The Classic Board", ... }
}

getBadge GET/POST

One badge by id: name, category, description, how many players hold it and the ten latest recipients.

Parameters: id (badge/merit id, required)

Example request
https://friendsofrisk.com/openapi/getBadge/id/219
Example response (trimmed)
{
  "id": 219,
  "sysname": "discord_streak_30",
  "name": "Discord streak 30 days",
  "category": "Discord",
  "description": "Chatted on Discord 30 days in a row",
  "holders": 143,
  "latest_recipients": [
    { "discordid": "3383326805...", "name": "Strafe", "earned": "2026-08-29" }, ...
  ]
}

getSetting GET/POST

One game setting from the community settings database, with the URL of its rendered settings image.

Parameters: id (setting id, required)

Example request
https://friendsofrisk.com/openapi/getSetting/id/1093
Example response (trimmed)
{
  "id": 1093,
  "map": "The Classic Board",
  "gametype": "World Domination",
  "blizzards": "Off",
  "fog": "Off",
  "portals": "Off",
  "placement": "Random",
  "cards": "Progressive",
  "turntimer": "Normal",
  "dicerolls": "Balanced Blitz",
  "image": "https://friendsofrisk.com/setting/1093.png"
}

getRandomSetting GET

One random setting from the community settings database. Same shape as getSetting.

Parameters: —

Example request
https://friendsofrisk.com/openapi/getRandomSetting
Example response (trimmed)
{ "id": 4711, "map": "Halloween Village", "gametype": "Capital Conquest", ..., "image": "https://friendsofrisk.com/setting/4711.png" }

getUpcomingGames GET

Every scheduled, not-yet-completed tournament game (group) across all events, with the players in each group. Groups with a gametime in year 4000 are placeholder entries for games that have not been scheduled yet (unscheduled: true).

Parameters: —

Example request
https://friendsofrisk.com/openapi/getUpcomingGames
Example response (trimmed)
[
  {
    "groupid": 5121,
    "groupname": "Round 2 Group 3",
    "gametime": "2026-09-02 19:00:00",
    "roundname": "Round 2",
    "bracket": 1,
    "eventid": 189,
    "eventname": "Fog of War FFA Season 2",
    "serverid": "465846009164070912",
    "unscheduled": false,
    "players": [
      { "discordid": "796768778977148938", "name": "eirik" }, ...
    ]
  }, ...
]

getLiveSchedule GET/POST

The /liveschedule/ dataset: every scheduled, not-yet-completed tournament game across all events, from 15 minutes before now (games that just started have playing: true) up to the last scheduled one, soonest first. Unscheduled placeholder groups are excluded. Each game lists its players, flags which of them are registered streamers, and includes the Twitch live status of those streamers (live, stream title, viewer count and channel url). Live status is refreshed every minute, so a stream shows up within a minute or two of going live; a streamer counts as live when one of their linked channels is Online and was checked within the last 30 minutes. counts is always for the unfiltered set. All times are UTC.

Parameters: filter (optional: all (default), streamer = only games with a streamer in the lobby, live = only games with a streamer who is live on Twitch right now)

Example request
https://friendsofrisk.com/openapi/getLiveSchedule/filter/live
Example response (trimmed)
{
  "generated_at": "2026-09-05T18:42:10Z",
  "filter": "all",
  "counts": { "all": 14, "streamer": 3, "live": 1 },
  "games": [
    {
      "groupid": 5121,
      "groupname": "Round 2 Group 3",
      "eventid": 189,
      "eventname": "Fog of War FFA Season 2",
      "eventtype": "FFA",
      "serverid": "465846009164070912",
      "roundid": 611,
      "roundname": "Round 2",
      "bracket": 1,
      "threadid": "1412345678901234567",
      "gametime": "2026-09-05 19:00:00",
      "gametime_iso": "2026-09-05T19:00:00Z",
      "gametime_unix": 1788634800,
      "playing": false,
      "url": "https://friendsofrisk.com/eventmanager/189/group/5121",
      "has_streamer": true,
      "any_live": true,
      "players": [
        { "discordid": "796768778977148938", "name": "eirik", "streamer": false, "live": false },
        { "discordid": "123456789012345678", "name": "Nordic_Noob", "streamer": true, "live": true }, ...
      ],
      "streamers": [
        {
          "discordid": "123456789012345678",
          "name": "Nordic_Noob",
          "live": true,
          "channel": "Nordic_Noob",
          "url": "https://www.twitch.tv/nordic_noob",
          "stream_title": "FoR tournament night!",
          "viewers": 42,
          "last_check": "2026-09-05 18:40:12"
        }
      ]
    }, ...
  ]
}

getCalendarEvents GET/POST

All live RISK calendar entries with raw ISO dates, the host server, format type and the linked eventmanager event id when there is one. (The older getCalendar returns pre-formatted dates instead.)

Parameters: upcoming (optional, 1 = only events that have not started yet)

Example request
https://friendsofrisk.com/openapi/getCalendarEvents/upcoming/1
Example response (trimmed)
[
  {
    "eventid": 236,
    "name": "The Feast",
    "description": "...",
    "hostserverid": "RISK: Global Domination",
    "type": "FFA",
    "rules_link": "https://...",
    "status": "DRAFT",
    "signup_start_date": "2026-08-24",
    "signup_close_date": "2026-11-08",
    "start_date": "2026-09-05",
    "end_date": "2026-11-08",
    "eventmanagerid": 194
  }, ...
]

getLeaderboards GET

Every available leaderboard: the type key (for getLeaderboard), title, what the scores mean and a description.

Parameters: —

Example request
https://friendsofrisk.com/openapi/getLeaderboards
Example response (trimmed)
[
  { "type": "ffaelo", "title": "FFA ELO ranking", "score1_name": "Points", "score2_name": "Games", "description": "" },
  { "type": "sabrffa", "title": "Sabr FFA ranking", "score1_name": "Points", "score2_name": "Appearances", "description": "..." }, ...
]

getLeaderboard GET/POST

One leaderboard's entries, best rank first.

Parameters: type (required, see getLeaderboards), limit (optional, default 100, max 1000)

Example request
https://friendsofrisk.com/openapi/getLeaderboard/type/ffaelo
Example response (trimmed)
{
  "type": "ffaelo",
  "title": "FFA ELO ranking",
  "score1_name": "Points",
  "score2_name": "Games",
  "entries": [
    { "rank": 1, "playerid": "2456819...", "displayname": "SomePlayer", "score1": 1451, "score2": 320, "score3": null }, ...
  ]
}

getEloGames GET/POST

A player's FFA ELO history, newest first: one row per rated game with the ELO before, the change and the ELO after, plus the setting played and the game's player count.

Parameters: userid (Discord id, required), limit (optional, default 100, max 1000)

Example request
https://friendsofrisk.com/openapi/getEloGames/userid/796768778977148938
Example response (trimmed)
[
  {
    "gameid": 16639,
    "gametime": "2026-08-20 14:00:00",
    "prev_elo": "1041.78231",
    "change": "-0.84527",
    "new_elo": "1040.93705",
    "settingid": 13800,
    "eventid": "Speedy Worlddom",
    "playercount": 6
  }, ...
]

getAllgames GET/POST

A player's individual tournament games from the allgames database, newest first: all players in the game with their scores, the setting and which event/round it belonged to.

Parameters: userid (Discord id, required), limit (optional, default 100, max 1000)

Example request
https://friendsofrisk.com/openapi/getAllgames/userid/796768778977148938
Example response (trimmed)
[
  {
    "id": 16645,
    "type": "FOR",
    "eventid": "Speedy Worlddom",
    "roundid": "Round 4",
    "groupid": "17573",
    "gameid": 2,
    "playercount": 6,
    "date": "2026-08-27 18:00:00",
    "player1": "HudsonHornet250", "player1id": "982321622520299601", "player1score": 9,
    "player2": "RobertoLoz",      "player2id": "331761695787712512", "player2score": 6,
    "settingid": 13800,
    "scoring": "POINTS",
    "elo": 1
  }, ...
]

getAllgamesStats GET/POST

A player's aggregated tournament-game stats (rebuilt nightly): games, winrate overall and per settings family, favourite map/mode, per-lobby-size winrates, nemesis and more.

Parameters: userid (Discord id, required)

Example request
https://friendsofrisk.com/openapi/getAllgamesStats/userid/796768778977148938
Example response (trimmed)
{
  "player": "796768778977148938",
  "games": 208,
  "won": 45,
  "winrate": "21.63",
  "favgamemode": "World Domination",
  "favmap": "The Classic Board",
  "winratewd": "24.10",
  "winrateprogwd": "19.00",
  "6plplayed": 150,
  "6plwinrate": "20.00",
  "nemesis": "33833268...",
  "lastgame": "2026-08-28 23:19:48"
}

getEvents GET

Every live eventmanager event (raw table rows, including the Discord channel/role ids the bot needs).

Parameters: —

Example request
https://friendsofrisk.com/openapi/getEvents
Example response (trimmed)
[ { "id": 189, "type": "NORMAL", "name": "Fog of War FFA Season 2", "owner": "...", "serverid": "...", "signupstatus": "OPEN", ... }, ... ]

getEventSignups GET/POST

Current tournament signups, optionally filtered by player and/or event.

Parameters: playerid (optional), eventid (optional)

Example request
https://friendsofrisk.com/openapi/getEventSignups/eventid/189
Example response (trimmed)
[ { "id": 9182, "eventid": 189, "playerid": "796768778977148938", "waitlist": null, "placement": null, ... }, ... ]

getAllSignups GET/POST

The Discord ids of every player with a signup in any live event.

Parameters: serverid (optional)

Example request
https://friendsofrisk.com/openapi/getAllSignups
Example response (trimmed)
[ "796768778977148938", "338332680561360927", ... ]

getCalendar GET

Legacy calendar feed with pre-formatted dates (kept for the Discord bot). Prefer getCalendarEvents for new integrations.

Parameters: —

Example request
https://friendsofrisk.com/openapi/getCalendar
Example response (trimmed)
[ { "hostserverid": "RISK: Global Domination", "name": "The Feast", "daystillsignup": -5, "start_date": "September 5th", ... }, ... ]

getloungestats GET

ELO Lounge winrate toplists for the last 7 days (relaxed and competitive lounges, minimum 3 games).

Parameters: —

Example request
https://friendsofrisk.com/openapi/getloungestats
Example response (trimmed)
{
  "relaxed_winrate": [ { "playerid": "...", "won": "5", "played": 6, "name": "SomePlayer" }, ... ],
  "competitive_winrate": [ ... ]
}

Internal endpoints

A few additional commands exist for the riskbot and the website itself (getEvent, getEventGroupThread, getChannelPingLog, usersearch). They are shaped around bot internals and may change without notice — don't build on them.