RoomScope

Ú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

  1. 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 (escopo webhook:manage).
  2. Copie o segredo de assinatura (whsec_…). Ele é retornado uma única vez, em webhookSecrets[].signingSecret, um por canal de webhook. Guarde-o junto com o seu endpoint.
  3. Responda com um 2xx em 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.
  4. POST /v1/alerts/rules/{id}/test envia uma entrega de exemplo do tipo envelope (sourceEventId começa com test_) 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:

TipoDispara quando
envelopeUm baú do tesouro foi observado em uma sala monitorada. Vale o valor mínimo em diamantes da regra.
goodyBagUma goody bag foi observada em uma sala monitorada. Vale o valor mínimo em diamantes da regra.
giftUm 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çalhoValor
content-typeapplication/json
x-roomscope-alert-id<ruleId>:<eventId>, o mesmo valor de alertId no corpo. Use-o para eliminar duplicatas.
x-roomscope-timestampTempo Unix, em segundos, de quando esta tentativa foi assinada.
x-roomscope-schema-versionVersão do schema do payload, atualmente 2026-11-03 (adiciona `links`).
x-roomscope-signaturesha256=<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.

POST your-endpoint
{  "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);}
Use o corpo bruto
Só interprete o JSON depois que a assinatura for validada, e calcule o HMAC sobre exatamente os bytes que você recebeu. Serializar o objeto de novo altera espaços e escapes e quebra a comparação.

Novas tentativas e falhas

  • Um status abaixo de 300 é sucesso. Um 5xx, 408, 429, erro de rede ou timeout gera nova tentativa; qualquer outro 4xx ou um 3xx é 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 por alertId, não pelo corpo.
  • Depois de uma entrega bem-sucedida, o mesmo alertId nã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.

Esta página foi útil?