Every page of the GameCP is drawn from a JSON API served by the same webserver binary, under /api/. Anything the panel does, a script can do by calling the same endpoints: post news from a build pipeline, pull the leaderboard into a Discord bot, or watch player counts from a monitoring system.
This page covers the RF Online versions, DragonSoul and World of Kung Fu, which share one control panel. The Gate to Heavens webservers have their own panel and are covered in Gate to Heavens at the end.
This API is not the OSO API. That one is oldschoolops.com's, uses API keys and lives under /api/v1/. This one runs on your own server and signs in with your game account.
Conventions
- Base URL is wherever your GameCP answers, such as
https://play.example.com. - Requests with a body send JSON with
Content-Type: application/json. - Responses are JSON, except
/healthz, the downloads and the website's own pages. - Timestamps are RFC 3339 in UTC unless a field says otherwise. Rate events and the live history use Unix seconds, and say so.
- Field names are camelCase and are the ones the panel itself reads.
The API is the panel's own backend, not a separately versioned product. Endpoints and fields change between releases as the panel does, and the changelog for each release names the ones that moved. Pin a script to the server version it was written against.
Signing In
There are no API keys on a game server. A script signs in the way the browser does and keeps the session cookie.
curl -c cookies.txt -H "Content-Type: application/json" \
-d '{"email": "[email protected]", "password": "..."}' \
https://play.example.com/api/auth/login
curl -b cookies.txt https://play.example.com/api/admin/overview
The cookie is named after the game, such as rf2232_session, ds_session or wokf_session, so one browser can be signed in to several servers on the same domain at once. It is HttpOnly, SameSite=Lax, and Secure when the request arrived over HTTPS or through a proxy that sent X-Forwarded-Proto: https. Set COOKIE_DOMAIN under [webserver] in settings.cfg to share the cookie across subdomains; it is applied only when the request's host is that domain or under it.
A session lasts 24 hours from sign-in and is not extended by use. Sessions are held in memory, so restarting the webserver signs everyone out. Banning an account or setting its password from the panel ends its sessions at once.
Every staff endpoint reads your access level from the accounts database on each request. A grant taken away takes effect on the next call, not at the next sign-in.
Signing in through oldschoolops.com
On a server with OSO_SERVER_KEY set under [oso], accounts belong to oldschoolops.com: sign in with your oldschoolops.com email and password, and registration, name changes and password changes answer 403 with a pointer to the site. Everything else on this page works the same. Signing in with oldschoolops.com covers turning it on.
Errors
A refusal written by the panel is JSON with an error sentence, written to be shown to a person:
{"error": "that name is already taken"}
The game database, the live map's HTTP fallback and the character profiles answer with a message field instead, as do requests to a path or method that does not exist.
| Status | Means |
|---|---|
| 400 | A field is missing or out of range. The sentence says which. |
| 401 | Not signed in, or the email and password were not accepted. |
| 403 | Signed in, but your access level is too low, or the target outranks you. |
| 404 | No such thing. A support ticket that is not yours also answers 404. |
| 409 | A conflict: the name is taken, someone else saved first, or the character is in the world. |
| 422 | A game data save where some cells were refused. Nothing was saved. |
| 429 | Too many attempts. Wait and retry. |
| 503 | A database this endpoint needs is not connected. |
A feature this server does not have is not an error. The game database, live map, profiles, PvP feed, rate events, rewards and character editor answer 200 with "available": false and a reason, so a script can tell "this server does not do that" from "something went wrong".
Server controls behave the same way. A control request answers 200 with ok and a message whether or not the game server carried it out, because the panel's request succeeded; read ok.
Limits
| What | Limit |
|---|---|
| Failed sign-ins | 20 per address and 10 per email in any 10 minutes. A successful sign-in clears both. |
| Registrations | 5 per address in any 10 minutes. |
| Open support tickets | 10 per account per game. |
limit on a list | Each endpoint caps it, and says where below. A larger value is lowered to the cap. |
Limits are counted per address. Behind a reverse proxy on the same machine or private network, the panel reads the client address from X-Forwarded-For, so the proxy must set it.
Accounts
| Method and path | Access | What it does |
|---|---|---|
POST /api/auth/register | Anyone | Create an account and sign in. email, password (8 to 64 characters), name (2 to 12 letters, digits, spaces, _, - or .). |
POST /api/auth/login | Anyone | email, password. Sets the session cookie. |
POST /api/auth/logout | Anyone | End the session. |
GET /api/auth/me | Signed in | Who you are and your access level on this game. |
PUT /api/account/name | Signed in | {"name": "..."}. |
PUT /api/account/password | Signed in | {"currentPassword": "...", "newPassword": "..."}. Your other sessions stay signed in. |
GET /api/account/characters | Signed in | Your characters on this server: slot, name, level, race, classCode, mapCode. |
Sign-in, registration and me all answer with the same account document:
{"email": "[email protected]", "name": "Kestrel", "accountId": 17, "gmLevel": 3, "gmLevelName": "Administrator"}
me adds emailVerified. gmLevel is there so a page knows what to draw; the server checks the level again on every staff request, so changing it in a client changes nothing.
A wrong password and an unknown email both answer 401 with the same message. A banned account answers 403 with "banned": true, the reason and bannedAt, and only once the password was right. Accounts are shared by every game on the server, so the same email and password work in the launcher and on every game's GameCP.
Support Tickets
The player's side. Each one answers only for the signed-in account's own tickets on this game.
| Method and path | What it does |
|---|---|
GET /api/support/tickets | Your tickets, newest first, up to 200, closed ones included. |
POST /api/support/tickets | Open one: subject (up to 200 bytes), body (up to 16 KiB), optional character, which must be one of yours. |
GET /api/support/tickets/{id} | One ticket with its thread. |
POST /api/support/tickets/{id}/reply | {"body": "..."}. Replying reopens a closed ticket. |
{
"id": 12,
"subject": "Lost my sword",
"character": "Kestrel",
"status": "open",
"createdAt": "2026-10-27T18:02:11Z",
"lastReplyAt": "2026-10-27T18:02:11Z",
"replies": 0,
"waitingOnStaff": true,
"messages": [
{"id": 31, "author": "Kestrel", "fromStaff": false, "body": "It vanished after a relog.", "createdAt": "2026-10-27T18:02:11Z"}
]
}
status is one of open, response_required, answered, escalated or closed. Staff notes marked internal never appear here.
Public Data
No sign-in needed. These are what the public half of the website is drawn from, and each one sets a short Cache-Control so a busy page does not reach the database on every view.
| Method and path | What it does |
|---|---|
GET /api/status | Whether the game server is up, players online, maximum players, uptime, account and character counts, and races: characters per faction. |
GET /api/brand | The game's name, factions, download names and which public features this build has (features.database, features.profiles, features.liveMap). |
GET /api/site | The website settings from Admin -> Site: colours, download links, the Discord link, whether the live map is public. |
GET /api/leaderboard | limit (default 15, at most 50) and race, a faction name spelled as the game spells it. |
GET /api/pvp/recent | Recent player kills: both names, factions and levels, and when. limit (default 20, at most 50). |
GET /api/articles | Published news, newest first. category (a section slug) and limit (default 30, at most 100). |
GET /api/articles/{slug} | One article with its markdown body. |
GET /api/news/categories | The news sections. |
GET /api/players?q= | Up to 10 character names starting with q (at least 2 characters). |
GET /api/players/{name} | A character's profile: race, class, level, guild, whether they are online, PvP standing and visible equipment. |
GET /api/db | The game database's categories, with row counts. |
GET /api/db/{kind} | One category's entries. q to search, offset, limit. |
GET /api/db/{kind}/{table}/{id} | One entry: every field, and what it links to (drops, recipes, rewards). |
GET /healthz | ok in plain text when the webserver process is running. |
/api/status answers whether the game is up. /healthz answers whether the website is up. Point an uptime monitor at the one you mean.
{"online": true, "players": 12, "maxPlayers": 500, "monsters": 8421, "uptimeSeconds": 86400,
"accounts": 311, "characters": 402, "races": {"Bellato": 140, "Cora": 131, "Accretia": 131}}
{"entries": [{"rank": 1, "name": "Kestrel", "level": 55, "race": "Cora", "classCode": "CWB1",
"className": "Warlock", "contribution": 1834.5, "online": true}],
"race": "Cora", "ranked": true, "onlineKnown": true}
On a version that ranks by contribution, ranked is true and race filters the list. Elsewhere the list is by level and race returns nothing. online means something only when onlineKnown is true.
The live map
The map page holds a websocket at /api/world/ws and is pushed a new frame about ten times a second while anyone is watching. After connecting, choose a map:
{"action": "watch", "map": 7}
"map": null watches the whole world. Each frame looks like this:
{"type": "world", "map": 7, "state": "live", "total": 214, "truncated": false,
"entities": [{"kind": 0, "name": "Kestrel", "race": 2, "map": 7, "x": 1032.5, "y": -12.0, "z": 877.25}]}
state is live, pending (the map has not been read yet), offline or disabled, with a message for the last two. kind is 0 player, 1 monster, 2 NPC, 3 animus, 4 object, 5 staff, 6 boss. Which kinds are sent is set under Admin -> Site. The socket accepts connections only from a page on the same host name.
A program that cannot hold a socket can poll GET /api/world?map=7 for the same frame. Polling keeps that map being read for 45 seconds after the last request.
When the live map is set to staff only, a visitor who is not staff gets exactly the answer they would get if it were switched off.
The Control Panel
Everything under /api/admin/. Each endpoint has a minimum access level, from Staff Accounts:
| Level | Name |
|---|---|
| 1 | Moderator |
| 2 | Game Master |
| 3 | Administrator |
| 4 | Super Administrator |
Game Master has no endpoint of its own here: a Game Master can use what a Moderator can.
Anything that acts on another account also follows the outrank rule: the target must hold a lower level than you on this game, and it may not be you. A Moderator can ban a player but not another Moderator. This answers 403.
Overview and live operations
| Method and path | Access | What it does |
|---|---|---|
GET /api/admin/overview | Administrator | Server state, account and staff counts, whether controls are reachable, and the setup checklist. |
GET /api/admin/live | Moderator | Everyone online with their map, players per map, and the game's event timers. |
GET /api/admin/live/history | Moderator | Players online every five minutes over the last day: {"intervalSeconds": 300, "samples": [{"at": 1761580000, "players": 12}]}. |
POST /api/admin/control | Administrator | Operate the game server. See below. |
POST /api/admin/control takes op, and text or seconds where the operation needs them:
op | Does | Fields |
|---|---|---|
reload-settings | The game server re-reads its settings. | |
announce | A system message to everyone in the world. | text, up to 200 bytes |
shutdown | Count down, warning players in game, then stop. | seconds, up to 3600 |
restart | Count down, then restart. RF Online only. | seconds, up to 3600 |
cancel-shutdown | Call off a countdown. RF Online only. |
curl -b cookies.txt -H "Content-Type: application/json" \
-d '{"op": "restart", "seconds": 300}' \
https://play.example.com/api/admin/control
{"ok": true, "message": "restart in 5 minutes"}
The panel talks to the game server over a loopback connection authenticated by the admin-token file the game server writes beside settings.cfg. If the two programs read different folders the token will not match and every control answers ok: false naming the file it expected.
Accounts and staff
| Method and path | Access | What it does |
|---|---|---|
GET /api/admin/accounts | Moderator | Search by email or name: q, limit (default 25, at most 50). Below Administrator, q needs at least 3 characters; an Administrator can leave it empty to list the newest. |
GET /api/admin/accounts/{id} | Moderator | One account: status, characters, ban state, and canAct, which says which actions you may take on it. lastLoginIp is included from Administrator up. |
GET /api/admin/accounts/{id}/bans | Moderator | Ban, unban and kick history, newest 100. |
GET /api/admin/accounts/{id}/logins | Administrator | Sign-ins to this game from the website, launcher and game, with address. Newest 100. |
GET /api/admin/accounts/{id}/addresses | Administrator | The addresses this account used and the other accounts seen on each. |
GET /api/admin/characters/{name} | Moderator | Which account owns a character: {"accountId": 42, "name": "Bob"}. |
POST /api/admin/accounts/{id}/ban | Moderator, outrank | {"reason": "..."}, up to 255 characters. Ends the account's sessions and drops it from the game. |
POST /api/admin/accounts/{id}/kick | Moderator, outrank | reason, and optional character to kick one character instead of the whole account. |
POST /api/admin/accounts/{id}/unban | Administrator, outrank | {"reason": "..."}. |
POST /api/admin/accounts/{id}/password | Administrator, outrank | {"password": "..."}. No current password needed. Signs the account out everywhere. |
GET /api/admin/staff | Administrator | Everyone holding a level on this game. |
PUT /api/admin/accounts/{id}/gm | Super Administrator | level (0 to 4, or the name) and an optional note. Not on yourself, not above your own level, and not removing the last Super Administrator. |
POST /api/admin/accounts/purge-bots | Super Administrator | Delete the test accounts the bot harness created, and their characters. Requires {"confirm": true}. Cannot be undone. |
Accounts are shared by every game on the server, so a ban is too. Banning an account on one game's GameCP stops it signing in to all of them.
curl -b cookies.txt -H "Content-Type: application/json" \
-d '{"reason": "gold spam in global chat"}' \
https://play.example.com/api/admin/accounts/42/ban
{"accountId": 42, "ban": {"banned": true, "reason": "gold spam in global chat", "at": "2026-10-28T12:00:00Z", "byId": 7, "byName": "Kestrel"}}
A kick answers 200 with ok: false when the player is not online.
Settings
| Method and path | Access | What it does |
|---|---|---|
GET /api/admin/settings | Administrator | Every server setting this game exposes, grouped, with its stored value, the value in effect, the default, the bounds and the choices. |
PUT /api/admin/settings | Super Administrator | {"changes": {"key": "value"}}. Every value is validated before anything is written. An empty string clears a setting back to its default. The running server reloads its settings after a save, and applied says whether it did. |
GET /api/admin/site | Administrator | The website's own settings: colours, live map, download links, Discord. |
PUT /api/admin/site | Super Administrator | {"changes": {"key": "value"}}. Answers with the updated settings. |
The setting keys differ between games and are the key fields GET returns. A server with no editable settings answers {"groups": []}.
Rate events and rewards
| Method and path | Access | What it does |
|---|---|---|
GET /api/admin/rate-events | Administrator | Which rates can be boosted, their current values, and the last 100 events. |
POST /api/admin/rate-events | Super Administrator | Schedule a boost. See below. |
POST /api/admin/rate-events/{id}/cancel | Super Administrator | End a running event, or call off a scheduled one. |
GET /api/admin/rewards | Administrator | The newest 200 rewards sent, with who sent them and what was delivered. |
POST /api/admin/rewards | Super Administrator | Mail an item or gold. See below. |
A rate event multiplies the named rates between two times, then puts back any rate nobody has changed in the meantime. Players are told in game when it starts.
{"name": "Double XP weekend", "keys": ["..."], "multiplier": 2, "startsAt": 1793000000, "endsAt": 1793172800}
keys are from the rates list GET returns. multiplier is 0.1 to 100, times are Unix seconds, an event lasts at most 31 days, and two events may not touch the same rate at once. status is scheduled, active, done, cancelled, or missed for an event the server was not running for.
A reward is mailed to one character or to everyone online:
{"to": "Bob", "title": "Sorry!", "body": "For the downtime", "item": "...", "count": 5, "gold": 0}
Set "allOnline": true instead of to for everyone online. title is up to 20 characters and body up to 200; send an item code, gold, or both. The answer says how many characters it reached.
Credits
| Method and path | Access | What it does |
|---|---|---|
GET /api/admin/credits/activity | Administrator | Recent credit movements on this game. scope=all for every game, limit (default 100, at most 500). |
GET /api/admin/credits/{id} | Administrator | One account's balance and ledger. |
POST /api/admin/credits/{id} | Super Administrator | {"delta": -100, "reason": "chargeback"}. Positive adds, negative removes. A removal can take a balance below zero. |
Every movement is a ledger row with the reason and who made it.
News
| Method and path | Access | What it does |
|---|---|---|
GET /api/admin/news/articles | Administrator | status is live, draft, published or trash. |
POST /api/admin/news/articles | Administrator | Write one. See below. |
GET /api/admin/news/articles/{id} | Administrator | One article with its body. |
PUT /api/admin/news/articles/{id} | Administrator | Change any of its fields. Fields you leave out are kept. |
POST /api/admin/news/articles/{id}/trash | Administrator | Move it to the trash. |
POST /api/admin/news/articles/{id}/restore | Administrator | Bring it back. |
GET /api/admin/news/categories | Administrator | The sections, with how many articles each holds. |
POST /api/admin/news/categories | Super Administrator | name, optional slug and sort. |
PUT /api/admin/news/categories/{id} | Super Administrator | The same fields. |
DELETE /api/admin/news/categories/{id} | Super Administrator | Only an empty section, trash included. |
An article takes title (up to 200 characters), body in markdown (up to 256 KiB), categorySlug or categoryId, and optionally slug, author and date. Set "published": true to publish now, or publishedAt to publish with a given date; "publishedAt": "" takes it back to a draft. There is no permanent delete.
curl -b cookies.txt -H "Content-Type: application/json" \
-d '{"title": "Server maintenance tonight", "categorySlug": "news", "body": "Down from 02:00 for an hour.", "published": true}' \
https://play.example.com/api/admin/news/articles
Support tickets, staff side
Every ticket endpoint is open to Moderator and up, with no second level inside it: everyone on staff can read, reply, assign and close.
| Method and path | What it does |
|---|---|
GET /api/admin/tickets | status, assignee (an account id, me or unassigned), account, limit (default 50, at most 200). |
POST /api/admin/tickets | Open a ticket with a player: accountId, subject, body, optional character. |
GET /api/admin/tickets/assignees | Who a ticket can be assigned to. |
GET /api/admin/tickets/{id} | One ticket, internal notes included. |
PUT /api/admin/tickets/{id} | status and/or assigneeId (0 unassigns). |
POST /api/admin/tickets/{id}/reply | body, internal for a note players never see, and optional status. A reply marks the ticket answered unless you say otherwise. |
Game data
On the RF Online versions with a Game Data Editor. Reading is Administrator; anything that saves, and the check that rehearses a save, is Super Administrator.
| Method and path | What it does |
|---|---|
GET /api/admin/gamedata | Where the data is read from, whether it can be written, and its version. |
GET /api/admin/gamedata/tables | Every table, with row counts and whether it can be edited. |
GET /api/admin/gamedata/tables/{table} | One table's columns. |
GET /api/admin/gamedata/tables/{table}/rows | Rows: offset, limit (default 100, at most 200), search, sort, desc, rids. Every value is a string. |
GET /api/admin/gamedata/tables/{table}/rows/{rid}/refs | What refers to this row. |
GET /api/admin/gamedata/kinds | The same categories as the public game database. |
GET /api/admin/gamedata/kinds/{kind} | Search one: q, offset, limit. |
POST /api/admin/gamedata/check | Validate a change without saving it. |
PUT /api/admin/gamedata | Save a change. ?reload=1 also reloads it into the running server. |
POST /api/admin/gamedata/reload | Reload game data into the running server. |
GET /api/admin/gamedata/codepages | The text encoding each data folder is read in. |
PUT /api/admin/gamedata/codepages | {"codepages": {"folder": "name"}}. |
GET /api/admin/gamedata/codepages/{folder}/samples | Raw text samples from a folder, base64, for working out its encoding. Administrator. |
A save names the version it was made against, so two people editing at once cannot overwrite each other:
{
"baseVersion": "<version from GET /api/admin/gamedata>",
"edits": [{"table": "...", "key": {"rid": 1317, "seq": -1}, "column": "...", "value": "120"}],
"rows": [{"table": "...", "op": "append", "values": {"...": "..."}}],
"allowRenumber": false
}
edits changes cells and rows adds or removes rows (append, insert, delete). Inserting or deleting moves every row after it, so it needs "allowRenumber": true. Every cell is checked before anything is written: if one is refused, the answer is 422 with a violations list and nothing is saved. If someone else saved since your baseVersion, the answer is 409; read the data again and redo the change.
A successful save answers with the new version, which tables changed, whether it is live, and any client files it rewrote. Those are copied into the client/ folder the launcher patches from.
Character editor
Every character editor endpoint is Super Administrator, reading included, on the versions that have it.
| Method and path | What it does |
|---|---|
GET /api/admin/chareditor/schema | Which fields and item containers this game's editor can change, with bounds. |
GET /api/admin/chareditor/characters | Find characters: q (name prefix), sort (recent, name or level), offset, deleted=1. |
GET /api/admin/chareditor/characters/{serial} | One character: every field, every item, and whether they are online now. |
GET /api/admin/chareditor/catalog | Items that can be given: table, q, offset. |
POST /api/admin/chareditor/characters/{serial}/check | Validate a change without saving it. |
PUT /api/admin/chareditor/characters/{serial} | Save a change. |
GET /api/admin/chareditor/history | Every edit made with the editor. offset, actor. |
GET /api/admin/chareditor/characters/{serial}/history | Edits to one character. |
A save carries baseVersion from the character you loaded, a reason, and fields and/or items:
{
"baseVersion": "<version from the character>",
"reason": "restore lost sword",
"fields": [{"name": "level", "value": "50"}],
"items": [{"op": "create", "item": {"container": 0, "slot": 3, "tableCode": 6, "itemIndex": 1317}}]
}
A character cannot be edited while their account is in the game: the save answers 409 with the character's presence. When the game server cannot be asked, the save also answers 409 unless you add "acknowledgeOffline": true to confirm the player is offline. Every save is recorded in the history with who made it and the reason.
Downloads
Served when the server has a client/ folder, for the launcher to patch from. Client updates covers building the manifest.
| Path | What it is |
|---|---|
GET /downloads/client/manifest.txt | The patch manifest. Never cached. |
GET /downloads/client/{file} | Any file in client/. |
GET /downloads/launcher | The launcher, zipped with its settings file when one is present. |
Which Games Have What
Accounts, support tickets, news, status, the leaderboard, website settings, staff, the account tools, credits, and reload, announce and shutdown are on every game below. The rest depends on the version:
| Feature | RF Dragonborn | RF Age of Patron | RF 1.5 | RF Golden Age | RF Holystone, Red Army, RF Online | DragonSoul | World of Kung Fu |
|---|---|---|---|---|---|---|---|
| Server settings | Yes | Yes | Yes | Yes | Yes | ||
| Restart and cancel | Yes | Yes | Yes | Yes | Yes | ||
| Game database | Yes | Yes | Yes | Yes | Yes | ||
| Live map | Yes | Yes | Yes | Yes | Yes | Yes | |
| Profiles and PvP feed | Yes | Yes | Yes | Yes | |||
| Leaderboard by contribution | Yes | Yes | Yes | Yes | Yes | ||
| Rate events and rewards | Yes | Yes | Yes | Yes | |||
| Game Data Editor | Yes | Yes | Yes | Yes | |||
| Character editor | Yes | Yes | Yes | Yes | |||
| Sign in through oldschoolops.com | Yes | Yes | Yes | Yes | Yes |
GET /api/brand reports the public features of the server you are talking to, and every feature endpoint answers "available": false where it is missing, so a script does not need this table to behave.
Gate to Heavens
Gate to Heavens and Gate to Heavens Classic run their own GameCP. It signs in the same way and answers errors the same way, but its paths and fields differ. Everything above that this section does not mention is not on a Gate to Heavens server. The live map and the server controls are among the endpoints it does not have.
The session cookie is gth_session on Gate to Heavens and gth_classic_session on Gate to Heavens Classic. A staff endpoint called below its level answers 404, not 403.
Accounts and characters
| Method and path | Access | What it does |
|---|---|---|
POST /api/auth/register | Anyone | As above. displayName is accepted in place of name. |
POST /api/auth/login | Anyone | As above. The answer has no gmLevel; read it from me. |
POST /api/auth/logout | Anyone | As above. |
GET /api/auth/me | Signed in | As above, without gmLevelName. |
PUT /api/account/name, PUT /api/account/password | Signed in | As above. |
GET /api/account/characters | Signed in | slot, name, class, level, mapId, createdAt. |
POST /api/account/characters/create | Signed in | slot, name, class. |
DELETE /api/account/characters/{slot} | Signed in | Delete the character in that slot. |
The launcher and game client sign in through /api/servers, /api/auth/entry-token and /api/auth/remember. Those belong to the client and are not for scripts.
Public data
| Method and path | What it does |
|---|---|
GET /api/stats | Players online, account and character counts, uptime, whether the server is up, per-world counts, and recent kills and deaths. |
GET /api/brand | The game's name, edition, ports and build. |
GET /api/site | Download links, the changelog and Discord links, the footer credit, and class colours. |
GET /api/players/search | q (at least 2 characters), limit (default 20, at most 100). |
GET /api/players/leaderboard | class, limit (default 100, at most 500). |
GET /api/players/{name} | A character's profile: level, map, guild, stats, equipment, inventory, warehouse and skills. |
GET /api/db/items, /api/db/items/{idx} | Items. q, type, wear, level_min, level_max, page, limit. |
GET /api/db/monsters, /api/db/monsters/{idx} | Monsters. q, gen, level_min, level_max, page, limit. |
GET /api/db/skills, /api/db/skills/{id} | Skills. q, job, type, class, page, limit. |
GET /api/db/quests, /api/db/quests/{idx} | Quests. q, level, type, page, limit. |
GET /api/db/options | Item options. |
GET /api/db/classes, /api/db/classes/{id} | Classes and their skills. |
GET /api/articles, /api/articles/{slug}, /api/news/categories | News, as above. Articles also carry a banner. |
GET /healthz | As above. |
Gate to Heavens also tracks every item by its unique id:
| Method and path | What it does |
|---|---|
GET /api/items/uid/{uid} | Where one item is now, and who holds it. |
GET /api/items/uid/{uid}/history | Everything that happened to it, up to 500 events. |
GET /api/items/census/{tableIdx} | Everyone holding an item of that kind, and how many. |
GET /api/items/activity | Recent item events. limit (at most 200) and before to page back. |
Support tickets
The same as above, at /api/tickets instead of /api/support/tickets. The staff side is at /api/admin/tickets as above, without the account filter.
The control panel
| Method and path | Access | What it does |
|---|---|---|
GET /api/admin/overview | Administrator | Who you are, account and character counts, database state and the update status. |
GET /api/admin/staff | Administrator | As above. |
GET /api/admin/settings | Administrator | The website's settings, which the other panel serves at /api/admin/site. |
PUT /api/admin/settings | Super Administrator | {"settings": {"key": "value"}}. |
GET /api/admin/game-settings | Administrator | The server's settings, as /api/admin/settings above. |
PUT /api/admin/game-settings | Super Administrator | {"changes": {"key": "value"}}. Rejected keys come back in rejected. |
GET /api/admin/accounts | Moderator | q, limit. |
GET /api/admin/accounts/{id} | Moderator | As above, with controlAvailable. |
GET /api/admin/accounts/{id}/bans | Moderator | As above. |
GET /api/admin/characters/{name} | Moderator | The character and the account that owns it. |
POST /api/admin/accounts/{id}/ban | Moderator, outrank | As above. |
POST /api/admin/accounts/{id}/kick | Moderator, outrank | As above. |
POST /api/admin/accounts/{id}/unban | Administrator, outrank | As above. |
POST /api/admin/accounts/{id}/password | Super Administrator, outrank | As above. |
PUT /api/admin/accounts/{id}/gm | Super Administrator | As above. |
/api/admin/news/... | As above | As above. Articles also take a banner. |
On Gate to Heavens only, an Administrator can also read GET /api/admin/items/{uid}/history and GET /api/admin/players/{name}/items, the item trail for one item or one character.