> ## Documentation Index
> Fetch the complete documentation index at: https://docs.lerian.studio/llms.txt
> Use this file to discover all available pages before exploring further.

# Consumir eventos

> Consuma eventos do Streaming Hub: verifique assinaturas HMAC de webhook, trate a rotação, leia os headers X-Lerian, deduplique entregas e puxe com ack por cursor.

O Streaming Hub entrega eventos de duas formas. Os sinks de **push** (`webhook`, `sqs`, `rabbitmq`, `eventbridge`) enviam cada evento correspondente para um destino seu. Um sink de **pull** mantém os eventos em um cursor do lado do servidor, que seu consumidor lê no ritmo dele. Esta página cobre o que seu consumidor deve fazer em cada caso.

## Verificar uma assinatura de webhook

***

O Streaming Hub assina cada entrega de webhook com um HMAC sobre o timestamp da requisição e o corpo exato dela. A assinatura prova que a requisição veio do Streaming Hub e que ela não foi adulterada nem repetida. Dois headers carregam a assinatura:

| Header                | Valor                                                |
| --------------------- | ---------------------------------------------------- |
| `X-Webhook-Signature` | `v1,sha256=<hex>` — a assinatura.                    |
| `X-Webhook-Timestamp` | O timestamp em segundos Unix embutido na assinatura. |

A fórmula da assinatura é:

```
signature_input = "v1:" + X-Webhook-Timestamp + "." + <raw request body>
X-Webhook-Signature = "v1,sha256=" + hex( HMAC-SHA256(key = signing_secret, message = signature_input) )
```

Para verificar uma entrega:

1. **Leia o corpo cru e o timestamp**: verifique **antes** de fazer o parse do corpo, sobre os bytes exatos recebidos. Qualquer nova serialização muda os bytes e quebra a assinatura.
2. **Verifique o frescor**: rejeite a requisição se o `X-Webhook-Timestamp` estiver a mais de **5 minutos** de agora. Essa é a janela de proteção contra repetição.
3. **Recalcule a assinatura**: monte o `signature_input` como acima com seu signing secret e codifique o HMAC-SHA256 em hexadecimal.
4. **Compare em tempo constante**: compare seu `v1,sha256=<hex>` com o `X-Webhook-Signature` recebido usando uma comparação de tempo constante (segura contra ataques de tempo). Rejeite quando não bater.
5. **Responda**: devolva `2xx` apenas depois que a assinatura e o frescor passarem.

Você recebe o signing secret quando cria a subscription, ou quando faz a última rotação dele. O Streaming Hub nunca envia o segredo em um header. O header carrega apenas a assinatura derivada. Veja [criar uma subscription de webhook](/pt/platform/streaming-hub/managing-subscriptions) para saber de onde vem o segredo.

## Tratar duas assinaturas durante a rotação

***

Quando você [faz a rotação de um signing secret](/pt/platform/streaming-hub/managing-subscriptions), o hub roda uma **sobreposição de assinatura dupla de 24 horas**. Durante a sobreposição, cada entrega carrega **dois headers `X-Webhook-Signature`**, um assinado com o segredo novo e outro com o segredo anterior. O hub os envia como **headers repetidos**, então você pode migrar para o segredo novo sem perder nenhuma entrega.

Verifique contra os dois: recalcule a assinatura esperada com cada segredo que você tem no momento e **aceite a requisição se qualquer uma das assinaturas recebidas bater**. Depois de fazer o deploy do segredo novo e confirmá-lo, aposente o antigo.

<Warning>
  Leia o `X-Webhook-Signature` como uma **lista de valores de header repetidos** usando o acessor multivalor de headers do seu framework (ou a visão de headers crus dele). **Não** quebre uma única string juntada em vírgulas: o próprio valor da assinatura contém uma vírgula (`v1,sha256=…`), então uma quebra ingênua por vírgula o corrompe. Algumas pilhas HTTP juntam headers repetidos com `", "` por padrão. Use o acessor de lista para obter cada valor inteiro.
</Warning>

## Headers de correlação

***

Cada entrega de webhook também carrega um conjunto de headers de contexto `X-Lerian-*`:

| Header                    | Carrega                                                                                                                      |
| ------------------------- | ---------------------------------------------------------------------------------------------------------------------------- |
| `X-Lerian-Event-Id`       | O id estável do evento (o `ce-id` do CloudEvents). **A chave de deduplicação** — constante entre reentregas do mesmo evento. |
| `X-Lerian-Event-Type`     | O tipo do evento, como o final `<resource>.<event>` puro (por exemplo, `transaction.created`).                               |
| `X-Lerian-Tenant-Id`      | O id do tenant dono (apenas atribuição).                                                                                     |
| `X-Lerian-Delivery-Id`    | O id por tentativa — **muda a cada nova tentativa** do mesmo evento.                                                         |
| `X-Lerian-Schema-Version` | A versão do schema do payload.                                                                                               |

<Warning>
  A entrega de webhook não carrega header de origem do produtor. O `X-Lerian-Event-Type` é deliberadamente livre de origem, então um consumidor não consegue distinguir dois produtores que emitem a mesma chave, a menos que a subscription fixe `origin`. Crie uma subscription com origin fixo por produtor quando a identidade da origem importa.
</Warning>

## Deduplicar entregas

***

A entrega é **pelo menos uma vez**: o hub pode entregar o mesmo evento mais de uma vez, por novas tentativas ou por uma reentrega depois do reinício de um worker. Deduplique pelo **`X-Lerian-Event-Id`**. Ele é estável em toda reentrega do mesmo evento, enquanto o `X-Lerian-Delivery-Id` difere por tentativa. Trate um `X-Lerian-Event-Id` que você já processou como duplicata: confirme com um `2xx` e não processe de novo. Mantenha seu handler idempotente.

## Responder rápido

***

Devolva um `2xx` assim que tiver verificado e aceito o evento de forma durável. Depois faça o trabalho de verdade de forma assíncrona. O hub trata uma resposta lenta ou com falha como uma entrega falha. Uma entrega falha dispara a [curva de novas tentativas](/pt/platform/streaming-hub/how-streaming-hub-works). Se o destino continuar quebrado por tempo suficiente, o hub em algum momento [desabilita automaticamente](/pt/platform/streaming-hub/how-streaming-hub-works) a subscription.

## Puxar eventos

***

Uma subscription `pull` não recebe push. Em vez disso, seu consumidor lê uma página dos eventos dela com:

```
GET /v1/events?subscription_id=<uuid>
```

Os eventos voltam em ordem crescente de chegada, cada um com seu `seq`, seu `ceId` (para dedup), seu tipo e seu payload. A resposta inclui um `next_cursor`.

**A leitura é a confirmação (cursor como ack).** Buscar uma página avança o cursor durável da subscription até o maior `seq` devolvido. Não existe chamada de ack separada. Ler uma página a confirma. Isso é monotônico, então nunca anda para trás.

Para paginar normalmente, retome a partir do `next_cursor` do servidor e pare quando uma página curta (com menos itens que seu `limit`) devolver `null`. Dois comportamentos a ter em mente:

* **Um salto para frente com `?after=` abre mão do intervalo.** Passar `?after=N` maior que seu cursor atual avança o cursor além de tudo até `N`. Os eventos pulados **nunca são reentregues**. Pedir eventos depois de `N` declara tudo até `N` como consumido. Isso apenas pode acontecer com um salto para frente feito à mão, nunca pela paginação normal com `next_cursor`.
* **Um salto para trás com `?after=` nunca rebobina.** Um `?after=` antigo ou menor que lê uma página mais velha não move o cursor para trás, porque o cursor apenas avança.

A leitura de pull tem rate limit por tenant. Uma leitura negada devolve **`429 rate_limited`**. Faça backoff e tente de novo. Deduplique os eventos puxados pelo `ceId`, assim como um consumidor de webhook deduplica pelo `X-Lerian-Event-Id`.

## Próximos passos

***

<CardGroup cols={2}>
  <Card title="Gerenciar subscriptions" icon="gear" href="/pt/platform/streaming-hub/managing-subscriptions">
    Crie subscriptions, faça a rotação de segredos e recupere destinos desabilitados.
  </Card>

  <Card title="Operar o Streaming Hub" icon="server" href="/pt/platform/streaming-hub/operating-streaming-hub">
    Faça o deploy, configure e observe o hub.
  </Card>
</CardGroup>
