Documentation
Vote API & Votifier setup
Everything needed to reward players for voting and show live player counts. Grab an API key from your listing settings first — every authenticated endpoint below needs one.
Authentication#
Send your key however your plugin finds easiest — all three forms are accepted:
X-Api-Key: tl_xxxxxxxxxxxxxxxxxxxxxxxx
Authorization: Bearer tl_xxxxxxxxxxxxxxxxxxxxxxxx
?key=tl_xxxxxxxxxxxxxxxxxxxxxxxxKeys are shown once at creation and stored only as a hash. If you lose one, revoke it and issue another.
Checking whether a player voted#
The endpoint your plugin calls when a player types /vote or logs in. By default it collects: the reward is marked handed out in the same atomic step, so a plugin that crashes mid-reward cannot pay twice.
GET https://api.voterank.net/api/v1/incentive/check?player=Notch
X-Api-Key: tl_xxxxA waiting reward:
{
"success": true,
"listing": "my-server",
"voted": true,
"claimed": true,
"player": "Notch",
"votedAt": "2026-08-22T14:31:01.776Z"
}Nothing to collect:
{ "success": true, "voted": false, "claimed": false, "player": "Notch", "votedAt": null }Give the reward when claimed is true. Add &peek=true to look without collecting — useful for showing a “reward waiting” indicator.
Checking the cooldown#
Cooldown is tracked per voter IP, so pass the player’s address — your server’s own IP is not theirs.
GET https://api.voterank.net/api/v1/vote/status?ip=203.0.113.9
X-Api-Key: tl_xxxx
{ "success": true, "canVote": false, "secondsRemaining": 20411, "nextVoteAt": "..." }HTTP postbacks#
Set a callback URL in your listing settings and we POST to it the moment a vote lands. Failures retry with exponential backoff (1m, 2m, 4m …) up to six times, and every attempt is visible in your dashboard.
POST https://your-server.example/vote-callback
Content-Type: application/json
X-Toplist-Event: vote
{
"event": "vote",
"listingId": "f55be4bf-...",
"listingSlug": "my-server",
"voteId": "19deb7e3-...",
"player": "Notch",
"claimToken": "9Jcnr9R3...",
"country": "US",
"timestamp": "2026-08-22T14:31:01.776Z"
}Reply 2xx to stop retries. player is null when the voter did not go through the incentive flow.
Votifier (Minecraft)#
With Votifier configured we push the vote straight into your server, so rewards land while the player is still online. Both protocol versions are supported and the version is detected from your server’s greeting.
NuVotifier (v2, recommended)
Copy the token from plugins/NuVotifier/config.yml into the NuVotifier token field, along with your host and port (default 8192).
Votifier (v1)
Paste the contents of plugins/Votifier/rsa/public.key into the Votifier public key field. Strip the -----BEGIN…----- header lines; the base64 body is enough.
Press Run test in your listing settings after saving — it performs a real query and reports the exact error if the port is closed or the key is wrong.
Live player counts#
Player counts are polled every few minutes. What we need depends on the platform:
- Minecraft — host and port; queried over Server List Ping.
- Rust, CS, GMod — host and query port (usually 27015), over A2S.
- FiveM — host and HTTP port (usually 30120), or a cfx.re join code.
- Tibia — an official world name, or a URL to your OTS status JSON.
- Steam games — the app id; concurrents come from Steam directly.
- Twitch / Kick / YouTube — the channel name or id; viewers count as players.
For anything else (RSPS, Metin2, custom emulators), expose a JSON endpoint and select Custom JSON endpoint:
GET https://your-server.example/status.json
{ "online": 412, "max": 1000, "version": "Revision 317" }players and playersOnline are accepted as aliases for online.
Pushing your player count#
If your server cannot expose a status endpoint — no web server, behind NAT, or it is an emulator with no HTTP layer at all — push the number to us instead. This is the option most RSPS use: there is no standard status protocol for a RuneScape emulator, which is why almost no toplist shows live counts for them, and the few that do just print whatever the owner typed into a form.
POST https://api.voterank.net/api/v1/players
authorization: Bearer tl_your_key
content-type: application/json
{ "players": 412, "max": 1000, "version": "Revision 317" }Only players is required. The reply tells you how long to wait before the next report:
{
"success": true,
"listing": { "slug": "my-server", "name": "My Server" },
"recorded": { "players": 412 },
"nextReportInSeconds": 300
}Report at most 4 times a minute — beyond that you get a 429. Once every five minutes is the intended rhythm, and matches how often we poll everything else. A count that stops arriving simply ages out and the listing falls back to showing nothing, so a crashed script never leaves a fake number on your page.
Ready-made scripts
Both do the same thing: call your own count, POST it, sleep, repeat. Replace one function with however your server counts players and leave it running.
- voterank-players.js — Node 18+, no dependencies.
- voterank-players.sh — bash and curl, for anything with a shell.
Treat the key like a password. Anyone holding it can report numbers as your server — if it leaks, revoke it from your listing’s API keys tab and issue a new one.
Signatures & buttons#
Every listing has a banner you can paste into a forum signature, and a small button for a website footer or README. Both are live SVGs: the votes and player numbers on them update themselves, so you paste once.
https://api.voterank.net/api/listings/YOUR-SLUG/signature.svg?theme=dark&size=large
https://api.voterank.net/api/listings/YOUR-SLUG/button.svg?theme=dark&style=votetheme— dark, light, midnight, forest or ember.size— large (500×100) or compact (350×70), signatures only.address=0— hides your IP:port on the banner.style— vote or view, buttons only.
The builder at /signature/YOUR-SLUG previews every combination and gives you the HTML, BBCode and Markdown to copy. Signature views are not counted as listing views — it is your advertisement on your own forum, not our traffic.
Public listing stats#
No key required — use it to show your rank and vote count on your own site.
GET https://api.voterank.net/api/v1/listing/my-server
{
"success": true,
"listing": {
"slug": "my-server", "name": "My Server",
"votesMonth": 1842, "votesTotal": 7368,
"playersOnline": 412, "isOnline": true,
"voteUrl": "https://voterank.net/vote/my-server"
}
}GraphQL#
Everything the website itself uses is available at https://api.voterank.net/graphql, with an interactive explorer in development. The REST endpoints above exist because plugin ecosystems are far happier with query strings than with GraphQL documents.
Advertising#
Banners are bought per list. A slot above the Minecraft toplist runs there and nowhere else, so you are not paying for impressions from people browsing Twitch streamers. The home page has its own strip.
How rotation works
Each strip shows five banners at once. You buy into the strip, never into a numbered position — on every page load the server draws five campaigns from the eligible pool, weighted by your bid, and shuffles their order. With more demand than inventory everyone gets exposure, and nobody permanently owns the top row.
What you are charged
- Per click at your CPC bid, or per thousand views at your CPM bid — whichever the slot is priced on.
- One IP counts once per banner every 30 minutes for views, and once a day for clicks. Refreshes are never billed twice.
- Spend is debited from your balance the moment it happens. A campaign stops the instant it reaches its budget, and an optional daily cap spreads it out.
Bids below a slot’s floor price are raised to the floor rather than rejected, so a campaign can never fail to serve because of a typo.
Getting started
Top up your balance in the dashboard, create a campaign with a budget and a bid, then upload a banner for the list you want. Banners are reviewed before they serve — usually within a day. Sizes are shown next to every slot on the advertising page.