Última atualização
Webhooks
Uma regra de alerta pode entregar a um endpoint HTTPS, além de no app, por e-mail e no Telegram. Cada entrega é um POST JSON assinado com o segredo do canal, que é exibido uma única vez, quando o canal é criado.
Configurar um endpoint
- No painel, abra Alerts → Rules → New rule, escolha os tipos de evento e adicione um canal Webhook com a sua URL HTTPS. Com uma chave de API, envie a mesma regra para
POST /v1/alerts/rules(escopowebhook:manage). - Copie o segredo de assinatura (
whsec_…). Ele é retornado uma única vez, emwebhookSecrets[].signingSecret, um por canal de webhook. Guarde-o junto com o seu endpoint. - Responda com um
2xxem até 10 segundos e faça o processamento de forma assíncrona. Redirecionamentos não são seguidos, e endereços privados, de loopback ou link-local são recusados. POST /v1/alerts/rules/{id}/testenvia uma entrega de exemplo do tipoenvelope(sourceEventIdcomeça comtest_) para você testar o seu handler.
Eventos
Uma regra lista em eventTypes os tipos de evento aos quais reage; uma lista vazia corresponde a todos os tipos. Estes são os tipos que vale a pena alertar:
| Tipo | Dispara quando |
|---|---|
envelope | Um baú do tesouro foi observado em uma sala monitorada. Vale o valor mínimo em diamantes da regra. |
goodyBag | Uma goody bag foi observada em uma sala monitorada. Vale o valor mínimo em diamantes da regra. |
gift | Um presente foi enviado em uma sala monitorada. Dispara a cada presente: o valor mínimo em diamantes não se aplica. |
minDiamondCount tem 49 como padrão e, junto com um piso de 1.51 diamante por espectador, filtra apenas baús do tesouro e goody bags. Eventos de início e fim de LIVE ainda não são entregues.
Cabeçalhos
| Cabeçalho | Valor |
|---|---|
content-type | application/json |
x-roomscope-alert-id | <ruleId>:<eventId>, o mesmo valor de alertId no corpo. Use-o para eliminar duplicatas. |
x-roomscope-timestamp | Tempo Unix, em segundos, de quando esta tentativa foi assinada. |
x-roomscope-schema-version | Versão do schema do payload, atualmente 2026-11-03 (adiciona `links`). |
x-roomscope-signature | sha256=<HMAC-SHA256 em hex de "<timestamp>.<raw body>">. |
Payload
Um evento por requisição, em JSON compacto. diamondCount, peopleCount e unpackAt (segundos Unix) são preenchidos para envelope e goodyBag e são null nos outros tipos.
{ "schemaVersion": "2026-11-03", "alertId": "8f0c…:evt_…", "rule": { "id": "8f0c…", "name": "Big treasure boxes" }, "event": { "type": "envelope", "sourceEventId": "evt_…", "roomId": "7432…", "creatorUniqueId": "room.one", "region": "VN", "diamondCount": 5000, "peopleCount": 120, "score": 5000, "unpackAt": 1793520000, "observedAt": "2026-11-01T10:02:31.123Z" }, "links": { "creator": "https://app.toktokdata.live/creators/room.one", "session": "https://app.toktokdata.live/live?creator=room.one" }, "occurredAt": "2026-11-01T10:02:31.123Z", "deliveredAt": "2026-11-01T10:02:33.456Z"}Verificar assinaturas
A assinatura é um HMAC-SHA256, com o segredo whsec_… completo como chave, calculado sobre o cabeçalho de timestamp, um ponto e o corpo bruto: <timestamp>.<body>. O digest em hex é enviado como sha256=<hex> em x-roomscope-signature. Compare em tempo constante e rejeite timestamps fora de uma janela que você escolher (cinco minutos no exemplo abaixo) para impedir ataques de replay.
import { createHmac, timingSafeEqual } from "node:crypto"; // rawBody: the exact bytes received, e.g. express.raw({ type: "application/json" }).// secret: the full whsec_… value shown when the webhook channel was created.export function verify(rawBody, headers, secret, toleranceSec = 300) { const signature = headers["x-roomscope-signature"]; const timestamp = headers["x-roomscope-timestamp"]; if (!signature || !/^\d+$/.test(timestamp ?? "")) return false; if (Math.abs(Date.now() / 1000 - Number(timestamp)) > toleranceSec) return false; const expected = "sha256=" + createHmac("sha256", secret).update(`${timestamp}.`).update(rawBody).digest("hex"); const a = Buffer.from(signature, "utf8"); const b = Buffer.from(expected, "utf8"); return a.length === b.length && timingSafeEqual(a, b);}Novas tentativas e falhas
- Um status abaixo de 300 é sucesso. Um
5xx,408,429, erro de rede ou timeout gera nova tentativa; qualquer outro4xxou um3xxé uma falha permanente. - Uma entrega tem no máximo 4 tentativas, enviadas uma após a outra, sem intervalo. Cada tentativa é assinada de novo, então
deliveredAt, o timestamp e a assinatura mudam. Elimine duplicatas poralertId, não pelo corpo. - Depois de uma entrega bem-sucedida, o mesmo
alertIdnão é entregue de novo por 7 dias. - Cada webhook entregue custa 1 crédito. Um espaço de trabalho pode receber até 100,000 webhooks por mês civil (UTC); as entregas acima disso são descartadas.
- As entregas que falharam ainda não aparecem no painel. Registre as requisições que você recebe se precisar de uma trilha de auditoria.
Telegram e e-mail
A mesma regra também pode entregar a um chat do Telegram conectado ou a um endereço de e-mail; esses canais não exigem tratamento de assinatura. Conecte o Telegram em Alerts → Channels.