Webhooks em tempo real

A publicação sai. Os webhooks voltam.

Os clientes subscrevem e desconectam-se sem nunca chegar ao seu backend, o que significa que o seu backend não faz ideia de que alguém está a ouvir. Os webhooks fecham esse ciclo: o edge publica um evento assinado quando um canal enche ou esvazia, quando um membro chega ou sai, e quando um canal de cache não tem nada para servir.

webhooks.ts
signed
app.post("/webhooks/bird", express.raw({ type: "*/*" }), (req, res) => {
  const event = bird.webhooks.unwrap(req.body, req.headers);
  res.sendStatus(200);

  switch (event.type) {
    case "realtime.channel_occupied":
      startStreaming(event.data.channel);
      break;
    case "realtime.channel_vacated":
      stopStreaming(event.data.channel);
      break;
    case "realtime.cache_miss":
      backfill(event.data.channel);
      break;
    default:
      break;
  }
});

Pare de pagar por uma audiência de ninguém.

Esta é a otimização mais barata do Bird Realtime. Um evento channel-occupied é o sinal para iniciar o trabalho pesado — a subscrição de dados de mercado, o loop de publicação por segundo; channel-vacated é o sinal para o parar. Nada é disparado para os subscritores que chegam e saem entretanto, portanto os dois eventos marcam exatamente os limites da vida de um canal e nada mais.

Cinco grupos. Subscreva o que precisa.

Subscreve um grupo; o grupo entrega os tipos de evento individuais. Um endpoint pode transportar eventos Realtime juntamente com o resto da plataforma, portanto email.bounced e realtime.presence podem chegar à mesma rota com o mesmo signing secret.

POST /webhooks/bird
realtime.member_added
{
  "type": "realtime.member_added",
  "timestamp": "2026-07-31T09:00:00Z",
  "data": {
    "channel": "presence-room-1",
    "member_id": "u_42"
  }
}
  • realtime.channel_existenceChannel occupied e vacated: os dois limites da vida de um canal, e nada entre eles.
  • realtime.presenceMember added e removed. Segue a identidade, portanto um segundo separador da mesma pessoa não produz nada.
  • realtime.connection_countQuantas conexões um canal contém. Requer a contagem de conexões ativada na app.
  • realtime.cache_channelsUm cache miss, que é o seu sinal para ler o estado atual e publicá-lo.
  • realtime.client_eventsUma entrega por evento de cliente, nomeada a partir dele: client-typing chega como realtime.client-typing.

O que as pessoas constroem com eles

Quatro padrões que precisam de um servidor para saber o que os clientes estão a fazer.

  1. 01

    Trabalho que só corre enquanto é observado.

    Inicie o feed upstream, o poller ou o render job com channel occupied e encerre-o com channel vacated. Um dashboard que ninguém tem aberto não custa nada manter ativo.

  2. 02

    Uma cópia do roster no backend.

    Member added e removed mantêm a sua própria visão de quem está numa sala — é disso que um indicador de disponibilidade de agente ou uma contagem de lugares é realmente feito. Seguem identidades, portanto uma pessoa que fecha um de três separadores não produz nada.

  3. 03

    Preencher uma cache fria.

    Um cliente que subscreve um canal de cache sem nada em cache aciona um miss no seu endpoint. Leia o estado atual, publique-o, e o cliente que causou o miss recebe-o, porque já está subscrito nessa altura.

  4. 04

    Monitorizar o tráfego peer-to-peer.

    Os eventos de cliente viajam entre clientes sem a sua API. Subscreva o grupo client-events e o seu servidor recebe uma cópia, com o canal, o connection id e, em canais de presença, o member id. Vale a pena saber antes de subscrever: um sinal de alta frequência como a posição do cursor produz uma entrega por evento.

Assinado como qualquer outro webhook Bird.

As entregas seguem o Standard Webhooks, com os headers webhook-id, webhook-timestamp e webhook-signature que verifica contra o signing secret do endpoint. O SDK desempacota e verifica numa única chamada. Verifique o body em bruto em vez de uma cópia re-parseada, uma vez que re-serializar JSON pode alterar os bytes assinados, e mantenha um branch predefinido para que um novo tipo de evento não quebre a rota.

As garantias de entrega, explicadas de forma clara.

Trate estes como notificações de mudança e não como um registo. Uma resposta não-2xx é retentada com backoff exponencial durante até cinco minutos, após o que o evento desaparece: os eventos Realtime não têm replay e não aparecem no log de delivery-attempts do endpoint. As entregas não são ordenadas e não transportam recibo por evento, portanto após uma entrega atrasada ou em falta, leia o estado atual a partir da API de channel-state em vez de o reconstruir. Retorne 2xx assim que tiver aceite o evento de forma durável e faça o trabalho depois.

Configurado no dashboard.

As subscrições Realtime são configuradas na página de Webhooks: crie ou edite um endpoint, escolha uma app Realtime e selecione os grupos. A app não pode ser alterada depois, mas os grupos podem. Esta é a única parte da superfície de webhooks da plataforma que hoje é exclusiva do dashboard, e um pedido de API pública que inclua um tipo de evento realtime é rejeitado em vez de silenciosamente aceite.

Aprofunde na documentação.

Webhooks em tempo real lista todos os tipos entregues e os seus campos de dados. Eventos de cliente cobre o grupo que nomeia, canais de cache explica o que fazer com um miss, e webhooks e eventos é o contrato da plataforma para endpoints, assinaturas e rotação de secrets.

Coloque em prática.

Continue com a documentação, guias e exemplos sobre este tópico. Os recursos estão em inglês.

Experimente na prática e obtenha um resumo de implementação

Descubra quando alguém começa a ouvir.

Aponte um único endpoint para o Realtime e para o resto da plataforma. Mesmo envelope, mesmo segredo de assinatura, mesma chamada de verificação.

Comece com um canal.
Adicione os outros quando estiver pronto.

Uma chave API de teste é sua imediatamente. A produção é desbloqueada quando você adiciona um método de pagamento e verifica um remetente.

Usa Claude Code, Cursor ou Codex? Copie um prompt de configuração e o seu agente instala o Bird CLI e as skills por si. Escolha o seu:

Cursor