EpicTop100

Top game servers ranked by player votes and popularity.

Time until reset: Calculating...

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.