EpicTop100
Top game servers ranked by player votes and popularity.
Incentive Vote Postback Guide
How Epic Top 100 sends vote callbacks (TopG-style p_resp or listing-style postback) to your game server.
1) Add a postback URL in UCP
In your server settings, set Postback URL to your endpoint (for example: https://yourgame.com/vote/postback).
2) Send players to vote with a tracking parameter
Use the vote page URL and append ?p=PLAYER_ID.
https://epictop100.com/vote/123?p=Razor_001
Allowed value format: letters, numbers, underscore, and hyphen only. Max length: 25.
3) Callback sent when vote succeeds
After a successful vote, we send a GET request to your configured postback URL with:
- p_resp (TopG-style): the same value from ?p=... — used when your URL does not include a postback query parameter.
- postback (Top100Arena-style): if your saved URL already has postback= (often empty), we set it to the same tracking value instead of using p_resp.
- ip: voter IP used for that vote (from your reverse proxy / CDN headers when configured).
GET https://yourgame.com/vote/postback?p_resp=Razor_001&ip=203.0.113.8 GET https://yourgame.com/callback?site_id=17&postback=Razor_001&ip=203.0.113.8
4) Recommended server-side checks
- Validate input format for the tracking field your URL uses (p_resp or postback) and for ip before processing.
- Reward only once per vote window for each account.
- Store a postback log row (account, ip, timestamp, reward result).
- Return HTTP 200 quickly after processing.
5) PHP example (with IP allowlist)
Restrict your endpoint so only EpicTop100 can invoke it: allowlist the IP your server sees for the inbound callback (often REMOTE_ADDR when PHP sits behind your reverse proxy correctly). Discover current addresses by resolving epictop100.com (for example dig +short epictop100.com A / AAAA) or use dnschecker.org to view propagation. Our IPs are not fixed—they can change—so refresh your allowlist periodically or resolve DNS at runtime as in the example below.
<?php
declare(strict_types=1);
// Allowlist = current A/AAAA records for our site (epictop100.com). IPs change over time — use DNS Checker
// https://dnschecker.org/ or dig to verify, or resolve on each request as below.
const EPIC_TOP100_HOST = 'epictop100.com';
function epicTop100IpsFromDns(string $hostname): array {
$ips = [];
foreach (dns_get_record($hostname, DNS_A) ?: [] as $r) {
if (!empty($r['ip'])) {
$ips[] = $r['ip'];
}
}
foreach (dns_get_record($hostname, DNS_AAAA) ?: [] as $r) {
if (!empty($r['ipv6'])) {
$ips[] = $r['ipv6'];
}
}
return array_values(array_unique($ips));
}
$allowedEpicTop100Ips = epicTop100IpsFromDns(EPIC_TOP100_HOST);
function callbackClientIp(): string {
// If you terminate TLS on nginx/Cloudflare in front of PHP, only trust forwarded
// headers from that proxy — never trust raw X-Forwarded-For from the public internet.
if (!empty($_SERVER['HTTP_CF_CONNECTING_IP']) && is_string($_SERVER['HTTP_CF_CONNECTING_IP'])) {
return trim($_SERVER['HTTP_CF_CONNECTING_IP']);
}
return $_SERVER['REMOTE_ADDR'] ?? '0.0.0.0';
}
$peer = callbackClientIp();
if ($allowedEpicTop100Ips === []) {
http_response_code(503);
header('Content-Type: text/plain; charset=utf-8');
echo 'Configure allowedEpicTop100Ips (see postback guide)';
exit;
}
if (!in_array($peer, $allowedEpicTop100Ips, true)) {
http_response_code(403);
header('Content-Type: text/plain; charset=utf-8');
echo 'Forbidden';
exit;
}
$tracking = $_GET['p_resp'] ?? $_GET['postback'] ?? null;
$tracking = is_string($tracking) ? $tracking : '';
if (!preg_match('/^[A-Za-z0-9_-]{1,25}$/', $tracking)) {
http_response_code(400);
header('Content-Type: text/plain; charset=utf-8');
echo 'Bad request';
exit;
}
$voterIp = $_GET['ip'] ?? null;
$voterIp = is_string($voterIp) ? $voterIp : '';
if (filter_var($voterIp, FILTER_VALIDATE_IP) === false) {
http_response_code(400);
header('Content-Type: text/plain; charset=utf-8');
echo 'Bad request';
exit;
}
// TODO: grant reward idempotently for $tracking; log $voterIp and outcome.
header('Content-Type: text/plain; charset=utf-8');
http_response_code(200);
echo 'OK';Operational notes
- Callbacks run only when the voter used a valid ?p=... on the vote page (same rules as in step 2). Votes without ?p are still counted; no callback is sent.
- Callbacks are sent only after successful votes and only when that server has `postback_url` configured.
- If your endpoint times out or returns non-2xx, we log it but keep the vote recorded.
- Callback attempts and outcomes are retained internally for operations and support; they are not exposed through a public API.
- Outbound requests use a bounded wait time; very slow endpoints may see timeouts even though the vote is still recorded.
- Whether vote callbacks are enabled for the site is determined by platform configuration, not your server settings.