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

# Quickstart: recibir su primer webhook

> Elija entre el Webhook Tester, un endpoint webhook registrado y un event sink — luego levante un receptor con túnel, verifique la firma y reenvíe entregas desde la consola.

## Nota de idioma

Esta versión en español es una traducción abreviada: la sección «Step 6 — Move to an event sink when you outgrow HTTP receivers» existe solo en inglés: [/en/guides/first-webhook-quickstart](https://docs.orbit.devotel.io/en/guides/first-webhook-quickstart). Los bloques de código, rutas de endpoints, nombres de campos de API y códigos de error permanecen en inglés.

# Quickstart: recibir su primer webhook

Tres superficies de entrega sacan los eventos de Orbit de la plataforma; esta guía le ayuda a elegir una y luego recorre el bucle completo del endpoint registrado — túnel, registro, verificación, replay.

## Step 1 — Elegir una superficie de entrega

| Superficie | Qué es | Elíjala cuando |
| - | - | - |
| **Webhook Tester** | Herramienta del dashboard (**Developer → Webhook Tester**) que dispara un evento sintético sin firmar a cualquier URL HTTPS y muestra el estado, las cabeceras y el cuerpo que devolvió su servidor | Itera sobre la forma del payload o el manejo de respuestas antes de registrar un endpoint real |
| **Endpoint webhook registrado** | Una suscripción duradera: firmada, reintentada, deduplicada y con dead-letter, apuntando a su receptor HTTPS | Todo lo que importa en producción |
| **Event sink** | Transmite cada evento suscrito a su propio topic de Kafka o colector HTTP por lotes | Consumo de alto volumen hacia infraestructura que ya opera |

Empiece con el Tester mientras experimenta. Pase a un endpoint registrado en cuanto la integración sea real — el tester no firma peticiones, así que nunca ejercita su lógica de verificación.

## Step 2 — Exponer un endpoint local con un túnel

```bash theme={null}
# any tunnel works — ngrok, localtunnel, cloudflared
ngrok http 3000
```

Copie la URL HTTPS de reenvío — esa es la dirección que registrará en el siguiente paso. Mantenga el túnel activo mientras recorre el registro y el replay.

## Step 3 — Registrar el endpoint en la consola (o por la API)

En el dashboard, vaya a **Developer → Webhooks → Add endpoint**. Pegue la URL de su túnel, suscríbase a uno o dos tipos de evento y guarde. La consola muestra el secreto de firma en claro (`whsec_...`) exactamente una vez — cópielo ahora a una variable de entorno.

```bash theme={null}
curl -X POST https://api.orbit.devotel.io/api/v1/webhooks \
  -H "X-API-Key: dv_live_sk_..." \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://your-tunnel-url.ngrok.io/webhooks/orbit",
    "events": ["message.delivered"]
  }'
```

La respuesta lleva el id de su endpoint (`wh_...`) y el secreto en claro de un solo uso (`whsec_...`) — persista ahora, porque todo `GET` posterior sobre el endpoint devuelve solo un valor enmascarado. Las listas `events` estrecas mantienen sano el tráfico de prueba; `*` es una decisión de producción, no de desarrollo.

## Step 4 — Recibir y verificar la firma

Las entregas registradas llegan firmadas con una cabecera `X-Orbit-Signature` en formato `t=<unix>,v1=<hex>`. Su receptor debe verificar `HMAC_SHA256(secret, "<t>.<raw body>")` sobre los bytes crudos de la petición — antes de que cualquier middleware JSON los parsee — y rechazar marcas de tiempo de más de 5 minutos. Una comprobación mínima en Node:

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

function verifySignature(rawBody, header, secret) {
  if (!header) return false;
  let t = null;
  const v1s = [];
  for (const part of header.split(",")) {
    const [key, value] = part.trim().split("=");
    if (key === "t") t = value;
    else if (key === "v1") v1s.push(value);
  }
  if (!t || v1s.length === 0) return false;

  const ageSec = Math.floor(Date.now() / 1000) - Number(t);
  if (!Number.isFinite(ageSec) || ageSec < 0 || ageSec > 5 * 60) return false;

  const expected = crypto
    .createHmac("sha256", secret)
    .update(`${t}.${rawBody.toString("utf8")}`, "utf8")
    .digest("hex");

  return v1s.some((candidate) => {
    const a = Buffer.from(candidate, "hex");
    const b = Buffer.from(expected, "hex");
    return a.length === b.length && crypto.timingSafeEqual(a, b);
  });
}
```

Devuelva `2xx` dentro de la ventana de entrega de 30 segundos y deduplique por el `id` del sobre — los reintentos y replays reentregan el mismo id. El contrato completo (calendario de reintentos, dead-letter queue) está en [Webhooks overview](https://docs.orbit.devotel.io/webhooks/overview.md).

## Step 5 — Reenviar entregas desde la consola

Cada intento de entrega es inspeccionable en **Developer → Webhooks → Events** — elija una fila para ver el payload y la respuesta que devolvió su servidor. Una entrega fallida se reenvía con **Replay** en la fila, para que pueda arreglar su receptor y redirigir el mismo evento firmado sin disparar tráfico nuevo.

Las entregas que agotan el calendario de reintentos caen en la dead-letter queue bajo **Developer → Webhooks → Dead-letter queue**, reenviables durante 7 días.

## Vea también

* [Test webhooks with the Webhook Tester](https://docs.orbit.devotel.io/guides/webhook-tester.md) — envíos sintéticos sin firmar para iterar
* [Build your first webhook receiver](https://docs.orbit.devotel.io/webhooks/first-receiver.md) — recorrido completo del receptor en Node y Python
* [Build a durable webhook consumer](https://docs.orbit.devotel.io/guides/webhook-consumer.md) — receptor de grado producción con procesamiento en cola


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