> ## Documentation Index
> Fetch the complete documentation index at: https://docs-platform.services-valid.com.br/llms.txt
> Use this file to discover all available pages before exploring further.

# Webhook de status

> Receba no seu sistema cada mudança de status de uma transação do TrustPass, sem precisar consultar o status por polling.

Sempre que o status de uma transação muda, o TrustPass faz um `POST` na URL de webhook cadastrada no seu projeto. Assim você fecha o pedido assim que a validação termina, sem consultar a [API de transação](https://docs-platform.services-valid.com.br/plataforma/trustpass/api/get-transacao.md) em polling. Aqui **o seu serviço é quem recebe a chamada**.

Sem URL cadastrada, nada é enviado e o status fica disponível apenas por consulta.

## Configuração

O webhook é uma configuração **por projeto**, feita no dashboard do TrustPass em **Configurações do Trustpass → Conexões**.

**1. Cadastre a URL**

Em **URL de webhook**, informe o endereço do seu serviço que vai receber os eventos e clique em **Salvar**.

**2. Guarde o segredo de assinatura**

No primeiro cadastro da URL, o dashboard exibe o **segredo de assinatura** (`whsec_...`). Ele só é exibido nesse momento: copie-o e guarde-o no seu cofre de segredos. Ele é usado para [verificar a assinatura](#como-verificar-a-assinatura) de cada chamada.

**3. Teste a URL**

Clique em **Testar webhook** para enviar um evento de teste à URL e ver se o seu serviço responde. Veja [Evento de teste](#evento-de-teste).

Regras da URL:

* A URL precisa ser `https` e pública. Não são aceitos endereços privados, de loopback ou internos, nem credenciais na URL (`https://usuario:senha@...`).
* Trocar a URL depois mantém o mesmo segredo.

Gestão do segredo e da URL:

* Em **Gerar novo segredo**, você cria um novo segredo a qualquer momento. O segredo anterior deixa de valer na hora, inclusive para as novas tentativas de entregas pendentes: atualize o seu sistema logo em seguida.
* Em **Remover webhook**, você apaga a URL e o segredo e descarta as entregas pendentes. Um novo cadastro gera um novo segredo.
* As mudanças da URL ficam registradas na aba **Histórico**.

## Eventos

| Evento | Quando |
| :- | :- |
| `transaction.status_changed` | A cada mudança de status depois da criação da transação: `awaiting_third_party`, `camera_unavailable` e os status finais (`approved`, `reproved_biometric`, `reproved_ownership`, `timeout`, `absent_holder`, `fraud_reported` e `cancelled`). |

A criação da transação (status `pending`) não gera evento. Veja o significado de cada status na [lista completa de status](https://docs-platform.services-valid.com.br/plataforma/trustpass/fluxo-titular-terceiro.md#status-da-transação).

### Evento de teste

O botão **Testar webhook** envia um único `POST` do tipo `webhook.test` para a URL informada, já salva ou não. Ele usa os mesmos headers e o mesmo formato de corpo de um evento real, com `data` igual a `{ "test": true }`.

* O teste não tem novas tentativas: o dashboard mostra na hora se o seu serviço respondeu com 2xx ou qual foi a falha (por exemplo, `405` quando a URL não aceita `POST`, ou ausência de resposta no prazo).
* O teste é assinado com um **segredo descartável**, e não com o seu. Se o seu serviço valida a assinatura, ele vai recusar o teste (por exemplo, com `401` ou `403`): nesse caso a recusa é esperada e confirma que a URL está acessível.
* Ignore eventos `webhook.test` no processamento dos seus pedidos.

## Headers da chamada

**Content-Type** `string`

Sempre `application/json`.

**User-Agent** `string`

Sempre `TrustPass-Webhooks/1.0`.

**x-trustpass-event-id** `string`

Identificador único do evento. É o mesmo em todas as tentativas de entrega: use-o para descartar duplicados.

**Exemplo**: `6f1c2c1e-6a43-4f0e-9a51-0d6f5c1b2a77`

**x-trustpass-event-type** `string`

Tipo do evento: `transaction.status_changed` ou `webhook.test`.

**Exemplo**: `transaction.status_changed`

**x-trustpass-timestamp** `string`

Momento do envio desta tentativa, em segundos Unix.

**Exemplo**: `1791378301`

**x-trustpass-signature** `string`

Assinatura da chamada no formato `v1=<hex>`: HMAC-SHA256 do texto `<timestamp>.<corpo cru>`, calculado com o seu segredo. Veja [como verificar a assinatura](#como-verificar-a-assinatura).

## Corpo

**id** `string`

Identificador do evento. Igual ao header `x-trustpass-event-id`.

**type** `string`

Tipo do evento: `transaction.status_changed` ou `webhook.test`.

**createdAt** `string`

Data e hora em que o evento foi gerado (ISO 8601).

**data** `object`

Dados da mudança de status. No evento `webhook.test`, vale `{ "test": true }`.

**Propriedades de data**

**transactionId** `string`

ID da transação.

**orderNumber** `string`

Identificador do pedido informado em `order_number` na [criação da transação](https://docs-platform.services-valid.com.br/plataforma/trustpass/api/post-transacao.md).

**status** `string`

Novo status da transação.

**previousStatus** `string`

Status anterior à mudança.

**reason** `string`

Motivo associado ao novo status, o mesmo `statusReason` da [consulta de inteligência](https://docs-platform.services-valid.com.br/plataforma/trustpass/api/get-transacao-inteligencia.md). `null` quando não informado.

**flowType** `string`

Tipo de fluxo da transação: `default` ou `third_party_validation` ([fluxo de titular terceiro](https://docs-platform.services-valid.com.br/plataforma/trustpass/fluxo-titular-terceiro.md)).

**sequence** `integer`

Posição desta mudança no histórico de status da transação. A criação é `1`, então o primeiro evento chega com `2`.

**occurredAt** `string`

Data e hora em que a mudança de status aconteceu (ISO 8601).

```json Exemplo theme={"theme":"catppuccin-latte"}
{
  "id": "6f1c2c1e-6a43-4f0e-9a51-0d6f5c1b2a77",
  "type": "transaction.status_changed",
  "createdAt": "2026-10-07T13:05:01.120Z",
  "data": {
    "transactionId": "a1b2c3d4-e5f6-7890-abcd-ef0123456789",
    "orderNumber": "PED-9981",
    "status": "approved",
    "previousStatus": "pending",
    "reason": null,
    "flowType": "default",
    "sequence": 2,
    "occurredAt": "2026-10-07T13:05:00.987Z"
  }
}
```

> [!NOTE]
>
> O evento traz apenas identificadores e status, sem documento, dados de cartão ou nome. Para o detalhe da transação, consulte a [API de transação](https://docs-platform.services-valid.com.br/plataforma/trustpass/api/get-transacao.md) ou a [consulta de inteligência](https://docs-platform.services-valid.com.br/plataforma/trustpass/api/get-transacao-inteligencia.md).

## Como verificar a assinatura

Antes de processar o evento, confirme que ele veio do TrustPass:

1. Leia o **corpo cru** da requisição, exatamente os bytes recebidos. Não use o JSON depois de convertido e serializado de novo.
2. Monte o texto `<x-trustpass-timestamp>.<corpo cru>` e calcule o HMAC-SHA256 com o seu segredo, em hexadecimal.
3. Compare `v1=<hmac>` com o header `x-trustpass-signature` usando uma comparação em tempo constante.
4. Rejeite timestamps muito antigos (por exemplo, mais de 5 minutos) para se proteger contra reenvio da mesma chamada.

```javascript Node.js theme={"theme":"catppuccin-latte"}
const crypto = require('node:crypto');

function isValidSignature(rawBody, headers, secret) {
  const timestamp = Number(headers['x-trustpass-timestamp']);
  if (!Number.isFinite(timestamp) || Math.abs(Date.now() / 1000 - timestamp) > 300) {
    return false;
  }

  const expected =
    'v1=' + crypto.createHmac('sha256', secret).update(`${timestamp}.${rawBody}`).digest('hex');
  const received = String(headers['x-trustpass-signature'] ?? '');

  return (
    received.length === expected.length &&
    crypto.timingSafeEqual(Buffer.from(received), Buffer.from(expected))
  );
}
```

## Resposta, timeout e novas tentativas

* Qualquer resposta **2xx** confirma a entrega. Responda rápido e processe o evento depois.
* Cada tentativa tem **timeout de 5 segundos**. Redirecionamentos não são seguidos e contam como falha.
* A primeira tentativa sai em poucos segundos após a mudança de status. Se ela falhar (resposta fora de 2xx, timeout ou erro de rede), há novas tentativas depois de **30 s, 2 min, 10 min, 30 min, 1 h, 3 h, 6 h, 12 h e 24 h**: 10 tentativas, cerca de 47 horas no total. Esgotadas as tentativas, o evento não é mais reenviado.

## Duplicidade e ordem

A entrega é **pelo menos uma vez**: o mesmo evento pode chegar mais de uma vez, e uma nova tentativa pode chegar depois de um evento mais recente da mesma transação.

* Descarte duplicados pelo `x-trustpass-event-id`.
* Guarde o último `sequence` aplicado por transação e **ignore eventos com `sequence` menor ou igual** a ele.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.