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

# Webhooks

> Eventos enviados por TESA, formato del payload, verificación de firma y reintentos

> [!WARNING]
>
> Borrador: especificación en curso. Los endpoints y campos pueden cambiar.

Los webhooks avisan a su integración cuando algo cambia en su posición de caja, sin necesidad de consultar la API de forma periódica. Cada destino se registra con `POST /webhooks` y recibe su propio secreto para verificar la firma.

## Eventos

| Evento | Cuándo se envía |
| - | - |
| `deposito.confirmado` | Un depósito en USDC en una billetera vinculada fue confirmado on-chain |
| `alocacao.proposta` | Una regla de su política generó una transacción, pendiente de aprobación |
| `alocacao.aprovada` | La propuesta fue aprobada y las transacciones están listas para la firma del custodio |
| `resgate.concluido` | El USDC rescatado llegó a la billetera de destino, con confirmación on-chain |
| `rendimento.apurado` | Se cerró el rendimiento de un período |
| `fatura.emitida` | Se emitió la factura de uso de la API del período, según el volumen de llamadas |

La propuesta es que un destino pueda suscribirse a todos los eventos o solo a una lista de ellos.

## Formato del payload

Todos los eventos comparten el mismo sobre. El campo `dados` lleva el recurso en el mismo formato que devuelve la API.

```json Ejemplo ilustrativo theme={null}
{
  "id": "evt_7h2k9q",
  "tipo": "alocacao.proposta",
  "criado_em": "2026-09-01T09:30:05Z",
  "ambiente": "producao",
  "organizacao_id": "org_1a2b",
  "dados": {
    "id": "prop_8f2a1c",
    "tipo": "rebalanceamento",
    "status": "pendente",
    "origem": "regra",
    "regra_id": "rgr_1",
    "movimentos": [
      { "de": "USDY", "para": "BUIDL", "valor": "42105.50" }
    ]
  }
}
```

## Verificación de firma

Cada entrega incluye el encabezado `Tesa-Signature` con el formato `t=<timestamp>,v1=<firma>`. La firma es el HMAC-SHA256 en hexadecimal de la cadena `<timestamp>.<cuerpo bruto>`, usando el secreto del destino.

```javascript Node.js theme={null}
import crypto from "node:crypto";

function verificar(corpoBruto, cabecalho, segredo) {
  const partes = Object.fromEntries(
    cabecalho.split(",").map((p) => p.split("="))
  );
  const esperado = crypto
    .createHmac("sha256", segredo)
    .update(`${partes.t}.${corpoBruto}`)
    .digest("hex");

  const dentroDaJanela = Math.abs(Date.now() / 1000 - Number(partes.t)) < 300;
  const confere = crypto.timingSafeEqual(
    Buffer.from(esperado),
    Buffer.from(partes.v1)
  );
  return dentroDaJanela && confere;
}
```

> [!WARNING]
>
> Verifique la firma sobre el cuerpo bruto, antes de cualquier análisis del JSON, y rechace los eventos con más de 5 minutos de antigüedad.

## Entrega y reintentos

* El destino debe responder con cualquier estado `2xx` en un plazo de 10 segundos. El procesamiento pesado debe hacerse después de la respuesta.
* Sin un `2xx`, TESA reintenta con espera creciente: 1 minuto, 5 minutos, 30 minutos, 2 horas, 6 horas y 12 horas. Después de eso, el evento se marca como fallido.
* Los eventos fallidos pueden verse y reenviarse desde el panel.
* La entrega es al menos una vez: el mismo evento puede llegar más de una vez. Use el `id` del evento para descartar duplicados.
* El orden de llegada no está garantizado. Use `criado_em` y el `status` del recurso, o consulte la API, antes de actuar.

> [!NOTE]
>
> Un webhook es una notificación, no una orden. Un evento `alocacao.aprovada` no mueve fondos por sí solo: los fondos se mueven únicamente después de la firma del custodio de la empresa.


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