XTREMETOP300

Oy ödülü API'si

Oy veren oyuncularınıza oyun içinde ödül verin. Oyları almanın iki yolu var; ikisi de tek bir anahtar kullanır ve ikisi de NAT arkasındaki ya da günde iki kez yeniden başlatılan bir sunucuda çalışacak şekilde tasarlanmıştır.

Hangisini kullanmalıyım?

Pull — buradan başlayın

Sunucunuz bir iki dakikada bir bize hangi ödülleri vermesi gerektiğini sorar. Açık port, alan adı veya TLS sertifikası gerektirmez. Ev internetinden bile çalışır.

Push — bir web endpoint'iniz varsa

Bir oy geldiği anda URL'nize POST isteği göndeririz; isteğin bizden geldiğini kanıtlayabilmeniz için imzalıdır. Anında çalışır, ama yalnızca size ulaşabiliyorsak.

İkisini birlikte de kullanabilirsiniz. Callback'inize push edilen bir ödül pull ile de alınabilir durumda kalır; yani kaçırılan bir push asla kaybolan bir ödül anlamına gelmez.

1. Anahtarınızı alın

Sunucu kaydınızı Sunucularım → Oy ödülleri altından açın, ödülleri etkinleştirin ve API anahtarını kopyalayın. Anahtarı her istekte bir header olarak gönderin:

Authorization: Bearer YOUR_API_KEY

Anahtarı asla bir URL'ye koymayın. Erişim log'larına, proxy log'larına ve tarayıcı geçmişine düşer.

2. Bekleyen ödülleri okuyun

POST /api/v1/rewards/pending alınmamış ödülleri en eskiden başlayarak döndürür.

curl -X POST https://xtremetop300.com/api/v1/rewards/pending \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"limit": 50}'

{
  "server":  { "id": 1234, "name": "My Server" },
  "count":   2,
  "more":    false,
  "rewards": [
    { "token": "8f2c...", "player": "Steve",  "server_id": 1234, "voted_at": "2026-08-25T09:14:02+00:00" },
    { "token": "1a90...", "player": "Alexia", "server_id": 1234, "voted_at": "2026-08-25T09:31:44+00:00" }
  ]
}

Okumak hiçbir şeyi tüketmez. Ödülleri verin, ardından onaylayın:

curl -X POST https://xtremetop300.com/api/v1/rewards/claim \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"tokens": ["8f2c...", "1a90..."]}'

{ "claimed": ["8f2c...", "1a90..."], "already_claimed": [], "unknown": [] }
Neden iki istek? Sunucunuz okuma ile ödülü verme arasında çökerse, ödül bir sonraki döngüde hâlâ oradadır. “Oyuncu ödülünü aldı” diyen şey claim isteğidir. Tek istekle yetinmek isterseniz, pending isteğiyle birlikte "claim": true gönderin — ödülleri alırsınız ve hemen verilmiş olarak işaretlenirler; ama yanlış anda yaşanan bir çökme onları kaybettirir.

3. Ya da sadece evet/hayır sorusu sorun

Çoğu plugin yalnızca bir oyuncuya girişte oy hatırlatması yapıp yapmayacağını bilmek ister. GET /api/v1/rewards/check oyuncu adına veya IP adresine göre yanıt verir.

curl "https://xtremetop300.com/api/v1/rewards/check?player=Steve&hours=24" \
  -H "Authorization: Bearer YOUR_API_KEY"

{ "voted": true, "voted_at": "2026-08-25T09:14:02+00:00", "window_hours": 24 }

4. Anında olsun istiyorsanız push

Ödül ayarlarınızda bir callback URL'si belirleyin; her oy geldiğinde bu adrese şunu POST ederiz:

POST /your-callback HTTP/1.1
Content-Type: application/json
X-Xtreme300-Signature: sha256=4f1e...
X-Xtreme300-Timestamp: 1787654321
X-Xtreme300-Delivery: 8f2c...

{
  "event":   "vote.reward",
  "sent_at": 1787654321,
  "reward":  { "token": "8f2c...", "player": "Steve", "server_id": 1234, "voted_at": "..." }
}

Herhangi bir 2xx durum koduyla yanıt verin. Diğer her yanıtta istek sonraki bir saat içinde 5 kez yeniden denenir; bundan sonra ödül yalnızca pull ile alınmayı bekler. 4xx yanıtı ret olarak kabul edilir ve yeniden denenmez; bu yüzden geçici bir sorun için 4xx döndürmeyin.

5. İmzayı doğrulayın

Callback URL'nize herkes POST isteği gönderebilir. Gerçek bir oyu, kendine elmas veren bir yabancıdan ayıran şey imzadır. API anahtarınızla HMAC-SHA256(timestamp + "." + rawBody) değerini hesaplayın ve header ile karşılaştırın.

// PHP
$body      = file_get_contents('php://input');   // the raw body, before json_decode
$timestamp = (int) $_SERVER['HTTP_X_XTREME300_TIMESTAMP'];
$signature = $_SERVER['HTTP_X_XTREME300_SIGNATURE'];

// Reject old requests first. A valid signature on a captured request replayed
// a thousand times is the whole attack.
if (abs(time() - $timestamp) > 300) {
    http_response_code(400);
    exit;
}

$expected = 'sha256=' . hash_hmac('sha256', $timestamp . '.' . $body, $apiKey);

// hash_equals, not ==. A normal comparison returns faster the earlier it finds
// a difference, which is enough to guess the signature one byte at a time.
if (! hash_equals($expected, $signature)) {
    http_response_code(401);
    exit;
}
// Java (Bukkit / Paper / Spigot)
Mac mac = Mac.getInstance("HmacSHA256");
mac.init(new SecretKeySpec(apiKey.getBytes(StandardCharsets.UTF_8), "HmacSHA256"));

byte[] digest = mac.doFinal((timestamp + "." + rawBody).getBytes(StandardCharsets.UTF_8));

StringBuilder hex = new StringBuilder("sha256=");
for (byte b : digest) hex.append(String.format("%02x", b));

if (!MessageDigest.isEqual(hex.toString().getBytes(), signatureHeader.getBytes())) {
    return; // not from us
}

6. Oyunculara onları zaten tanıyan bir bağlantı gönderin

Oyuncunun adını oy bağlantısına ekleyin; alan dolu gelir ve oyuncunun yalnızca tıklaması yeterli olur. player, pingUsername, username veya nick parametrelerinden herhangi biri çalışır — fazladan olanlar, başka bir toplist için hazırladığınız bir butonu hiç değiştirmeden buraya yönlendirebilmeniz için var.

https://xtremetop300.com/vote/1234?player=Steve

Bilinmesi gereken kurallar

  • Ödül yalnızca sayılan bir oy için oluşturulur. Sahtecilik kontrollerimizin işaretlediği oylar hiçbir şey kazandırmaz; böylece bir oy çiftliği, sıralamanıza dokunmadan oyun içi paranızı sömüremez.
  • Her oyuncu 24 saatte bir oy verebilir; bu, toplist'in kendi limitiyle aynıdır.
  • Her token'ın en az bir kez gelebileceğini, yani tekrar edebileceğini varsayın. Ödemesini yaptıklarınızı saklayın ve tekrarları yok sayın. Bir plugin'in mutlaka doğru yapması gereken tek şey budur.
  • Bir oyuncu adını asla doğrudan bir konsol komutuna yapıştırmayın. Adları harf, rakam, boşluk, nokta, tire ve alt çizgiyle sınırlıyoruz; yine de sunucunuz ödülü vermeden önce adın gerçek bir hesaba ait olduğunu kontrol etmelidir.
  • Varsayılan olarak pull başına 50 ödül, en fazla 200. more alanını takip edin ve true ise tekrar istek gönderin.
  • Sunucu kaydı başına dakikada 60 istek. Dakikada bir sorgulamak bunlardan yalnızca birini kullanır.
  • Alınmayan ödüller 14 gün sonra silinir.

Hatalar

401
Anahtar eksik veya hatalı. Bearer önekini kontrol edin.
403
Anahtar doğru, ancak sunucu kaydı yayında değil veya ödüller kapalı.
422
Bir parametre eksik veya hatalı; hangisi olduğu yanıt gövdesinde belirtilir.
429
Çok fazla istek. Biraz bekleyip tekrar deneyin — hiçbir şey kaybolmaz.

Sunucunuz zaten listede mi? Ödülleri açmak için sunucu ayarlarınızı açın. Henüz listede değil mi? Sunucunuzu ekleyin.