Integração para desenvolvedores
Receba os votos autorizados e transforme cada um na recompensa definida pelo seu jogo.
1. Reivindique e verifique o jogo Entre com a conta Google ou Discord responsável e conclua a verificação do domínio.
2. Crie o webhook no servidor do jogo Use uma URL HTTPS no domínio oficial ou subdomínio, como https://api.seujogo.com/webhooks/topidle.
3. Gere as credenciais Informe o webhook, deixe as recompensas desligadas e clique em “Salvar e gerar credenciais”.
4. Guarde e teste Copie a chave e o segredo, que aparecem somente uma vez, e clique em “Enviar teste”.
5. Escolha como localizar o jogador Use o e-mail verificado somente se o jogo também identificar a conta por ele. Caso contrário, solicite o nome do personagem ou ID da conta. O login no TopIdle continuará protegendo o voto sem precisar ser o mesmo usado no jogo.
Validação do webhook
Compare
X-TopIdle-Signature com o HMAC SHA-256 de
X-TopIdle-Timestamp + "." + corpo_bruto usando o segredo do webhook. Aceite apenas timestamps recentes e compare as assinaturas em tempo constante.
O mesmo identificador aparece em
eventId,
X-TopIdle-Vote-Id e
Idempotency-Key. Guarde-o antes de creditar a recompensa para que uma retentativa nunca pague duas vezes.
Identificação do jogador
Se o campo de identificador ficar vazio, o evento envia o
email verificado da conta TopIdle. Se o jogo usa outra conta, configure um rótulo como “Nome do personagem” ou “ID da conta”; o evento passará a enviar
playerIdentifier.
O jogo também pode levar o jogador ao TopIdle por
https://topidle.com/jogo/ID_DO_JOGO?playerIdentifier=ID_DO_JOGADOR. O valor será preenchido para o jogador conferir e autorizar antes do voto. Trate-o somente como texto, codifique-o na URL e nunca envie senha, token ou dados de pagamento.
O mesmo
playerIdentifier pode receber um voto por intervalo do jogo, de 24 a 6 horas conforme o plano ativo. Ele não fica vinculado permanentemente a uma conta Google ou Discord.
Recuperação pela API
Se o webhook falhar, consulte
GET /api/v1/votes?after=0 com
Authorization: Bearer SUA_CHAVE. Guarde o último
nextCursor e processe cada
eventId uma única vez.
Consulte o último voto com
GET /api/v1/vote-status?playerIdentifier=NOME ou
?email=EMAIL. Estatísticas públicas ficam em
GET /api/v1/games/ID_DO_JOGO;
dailyRewardsConfirmed informa quantos eventos de recompensa foram aceitos nas últimas 24 horas.
Exemplo de validação (Node/Express)
Use o corpo bruto, valide o HMAC antes do JSON e responda
2xx rapidamente. O banco do jogo deve tornar
eventId único antes de liberar a recompensa.
app.post("/webhooks/topidle", express.raw({ type: "application/json" }), async (req, res) => {
const ts = req.get("X-TopIdle-Timestamp") || "";
const received = req.get("X-TopIdle-Signature") || "";
if (Math.abs(Date.now() / 1000 - Number(ts)) > 300) return res.sendStatus(401);
const digest = crypto.createHmac("sha256", WEBHOOK_SECRET)
.update(ts + ".").update(req.body).digest("hex");
const expected = "sha256=" + digest;
if (received.length !== expected.length ||
!crypto.timingSafeEqual(Buffer.from(received), Buffer.from(expected))) return res.sendStatus(401);
const event = JSON.parse(req.body);
await rewardOnce(event.eventId, event.playerIdentifier || event.email);
return res.sendStatus(204);
});