API y avisos de voto

Para dueños de hoteles: da recompensas por votar y muestra tu puesto en tu web.

Avisos de voto (callbacks)

Si el jugador escribe su nombre de Habbo al votar, enviamos un POST con JSON a la dirección que configures en tu panel. Solo enviamos el nombre que escribió, nunca su IP ni datos de su conexión.

Cuerpo

{
  "id": "6f1d8d5e-2c1f-4c55-9b0a-8a6f4f1b7a10",
  "type": "vote.created",
  "createdAt": "2026-11-02T20:15:00.000Z",
  "hotel": { "slug": "tu-hotel" },
  "username": "NombreEnHabbo",
  "period": "2026-11"
}

Cabeceras

  • X-HabboRank-Signature: t=<segundos unix>,v1=<hex>. El valor v1 es HMAC-SHA256 de t + "." + cuerpo con tu clave secreta.
  • X-HabboRank-Event-Id: el mismo id del cuerpo. Úsalo para no dar la recompensa dos veces.

Qué debe responder tu servidor

Cualquier código 2xx en menos de 8 segundos. Si no, reintentamos tras 1 minuto, 5 minutos, 30 minutos, 2 horas y 12 horas (6 intentos en total) y dejamos de insistir. No seguimos redirecciones y solo enviamos a direcciones https públicas.

Verificar la firma (Node)

import { createHmac, timingSafeEqual } from "node:crypto"

// body = el cuerpo EXACTO recibido (texto), header = valor de X-HabboRank-Signature
function firmaValida(secreto, body, header) {
  const partes = Object.fromEntries(header.split(",").map((p) => p.trim().split("=")))
  const t = Number(partes.t)
  if (!Number.isFinite(t) || Math.abs(Date.now() / 1000 - t) > 300) return false
  const esperada = createHmac("sha256", secreto).update(t + "." + body).digest("hex")
  const a = Buffer.from(esperada)
  const b = Buffer.from(partes.v1 ?? "")
  return a.length === b.length && timingSafeEqual(a, b)
}

Verificar la firma (PHP)

<?php
$body = file_get_contents('php://input');
$header = $_SERVER['HTTP_X_HABBORANK_SIGNATURE'] ?? '';
parse_str(str_replace(',', '&', $header), $p);   // t=...&v1=...
$esperada = hash_hmac('sha256', ($p['t'] ?? '') . '.' . $body, $SECRETO);
if (abs(time() - (int)($p['t'] ?? 0)) > 300 || !hash_equals($esperada, $p['v1'] ?? '')) {
  http_response_code(401); exit;
}
$evento = json_decode($body, true);
// Evita duplicados guardando $evento['id'] y responde 200

Probar

En tu panel pulsa «Enviar prueba»: mandamos un evento vote.test con el usuario PruebaHabboRank. Si pierdes la clave, crea una nueva desde el panel; la anterior deja de funcionar al instante.

API pública (solo lectura)
  • GET /api/v1/ranking?limit=10&month=2026-10: clasificación del mes actual o de un mes cerrado.
  • GET /api/v1/hotels/{slug}: datos públicos de un hotel.
  • GET /api/badge/{slug}.svg: insignia con tu puesto del mes.

Sin claves. Máximo 120 peticiones por minuto. Las respuestas llevan ETag y CORS abierto. Especificación completa: OpenAPI 3.1.