Postback Guide

Reward your players automatically every time they vote for your server.

When a player votes for your server on SroForge, we send a signed HTTP request (a postback) to your server with the player's in-game identifier. Your server checks the signature and gives the reward. In your account this feature is called Vote rewards and the address that receives the requests is your callback URL.

How to turn on vote rewards

Vote link (recommended)

Send logged-in players to your server page with their in-game identifier in the link:

https://sroforge.com/server/your-server-slug?user=PLAYER_ID

Request

We send an HTTP POST request with a JSON body to your callback URL. Your endpoint checks the signature, gives the reward and answers with any 2xx status.

Headers

Body

{
  "event": "vote",
  "delivery_id": "a97d48b9-5161-41cd-9f04-00c8d91fa085",
  "vote_id": 123,
  "server": "your-server-slug",
  "username": "PlayerName",
  "voted_at": "2026-09-21T12:32:06+00:00"
}

Example: verifying the request in PHP

<?php
$secret = 'YOUR_CALLBACK_SECRET';

$body      = file_get_contents('php://input');
$timestamp = $_SERVER['HTTP_X_TOPLIST_TIMESTAMP'] ?? '';
$signature = $_SERVER['HTTP_X_TOPLIST_SIGNATURE'] ?? '';

// 1. Reject old requests (replay protection)
if (! ctype_digit($timestamp) || abs(time() - (int) $timestamp) > 300) {
    http_response_code(400);
    exit('Stale request');
}

// 2. Verify the signature
$expected = 'sha256=' . hash_hmac('sha256', $timestamp . '.' . $body, $secret);
if (! hash_equals($expected, $signature)) {
    http_response_code(401);
    exit('Invalid signature');
}

$data = json_decode($body, true);

// 3. Test requests must not give rewards
if (($data['event'] ?? '') === 'test') {
    exit('OK');
}

// 4. Give the reward only once per delivery_id
$deliveryId = $data['delivery_id'];
$username   = $data['username'];
// ... check $deliveryId in your database, then reward $username ...

http_response_code(200);
echo 'OK';

Retries

Good to know

Add your server