Saltar al contenido
0%

¿Qué es un webhook?

Uttam Singh headshot

Escrito por Uttam Singh

Publicado el 29 de octubre de 202610 min de lectura

¿Qué es un webhook?

Un webhook es una notificación de evento que se entrega como un HTTP POST. Cuando algo ocurre en un sistema, ese sistema envía una solicitud a una URL que tú controlas, y el cuerpo de la solicitud describe lo que pasó. Tu app nunca tiene que preguntar si algo cambió.

En las apps de blockchain, los eventos ocurren onchain. La wallet de un usuario recibe USDC, un NFT cambia de dueño o un contrato que desplegaste emite un log. Sin un webhook, tu backend hace polling a un nodo o a una API a intervalos regulares y compara los resultados para detectar esos cambios. Con uno, el cambio se envía a tu servidor en cuanto se detecta.

Esta guía explica qué son una URL, un endpoint y un payload de webhook, en qué se diferencia un webhook de una API, cómo funcionan la entrega y los reintentos, cómo verificar una solicitud y cómo manejar duplicados y reorgs en producción.

¿Qué es un webhook?

Un webhook conecta a dos partes. El emisor vigila los eventos. El receptor es tu app, que expone una URL. Cuando un evento coincide con aquello a lo que te suscribiste, el emisor hace una solicitud HTTP POST a esa URL con un cuerpo JSON que describe el evento, y tu servidor responde con un código de estado 200 para confirmar que llegó. Tu lado no devuelve datos, así que un webhook es un mensaje unidireccional de servidor a servidor.

La alternativa es el polling, que consiste en pedirle actualizaciones a la fuente con una frecuencia fija. La mayoría de esas solicitudes no traen nada nuevo, y un evento puede pasar inadvertido hasta un intervalo de polling completo antes de que tu app lo vea. Un webhook evita ambos problemas, porque solo se hace una solicitud cuando hay un evento que informar.

Piensa en el polling como llamar a una tienda cada hora para preguntar si llegó tu pedido. Un webhook es la tienda que te envía un mensaje de texto cuando llega.

¿Qué es una URL de webhook?

Una URL de webhook es la dirección pública a la que el emisor entrega los eventos, como https://api.example.com/webhooks/alchemy. La registras con el proveedor cuando creas el webhook. Los servidores del proveedor hacen la solicitud, así que la URL tiene que ser accesible desde internet, y debe usar HTTPS porque el payload describe la actividad de tus usuarios. Durante el desarrollo, una herramienta de túneles como ngrok le da a un servidor en tu laptop una URL pública temporal. Nuestra guía de inicio rápido de webhooks explica esa configuración paso a paso.

¿Qué es un endpoint de webhook?

Un endpoint de webhook es la ruta de tu servidor que maneja las solicitudes enviadas a la URL del webhook. Los dos términos se usan como sinónimos. La URL es la dirección, y el endpoint es el código detrás de ella.

Mantén acotada la tarea del endpoint. Comprueba que la solicitud vino del proveedor, guarda el evento y devuelve un 200. El trabajo más lento, como actualizar saldos o enviar notificaciones push, corresponde a un worker en segundo plano. Si ese trabajo se ejecuta dentro de la solicitud, una llamada lenta a la base de datos puede hacer que el proveedor piense que la entrega falló.

¿Qué es un payload de webhook?

El payload es el cuerpo JSON de la solicitud. Todos nuestros webhooks comparten la misma estructura externa, y el campo event contiene los datos de ese tipo de webhook. Este es un payload de un webhook de Address Activity, el tipo que vigila una lista de direcciones de wallet, para una transferencia de USDC en Ethereum. Se recortaron algunos campos por extensión.

json
Copied
{ "webhookId": "wh_k63lg72rxda78gce", "id": "whevt_vq499kv7elmlbp2v", "createdAt": "2024-01-23T07:42:26.411977228Z", "type": "ADDRESS_ACTIVITY", "event": { "network": "ETH_MAINNET", "activity": [ { "blockNum": "0xdf34a3", "hash": "0x7a4a39da2a3fa1fc2ef88fd1eaea070286ed2aba21e0419dcfb6d5c5d9f02a72", "fromAddress": "0x503828976d22510aad0201ac7ec88293211d23da", "toAddress": "0xbe3f4b43db5eb49d1f48f53443b9abce45da3b79", "value": 293.092129, "asset": "USDC", "category": "token", "rawContract": { "address": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", "decimals": 6 }, "log": { "logIndex": "0x6e", "removed": false } } ] } }

webhookId indica qué webhook se disparó, id identifica este evento y type indica el tipo de webhook. Cada entrada de activity es una transferencia que involucró a una dirección vigilada. Para identificar el token, usa rawContract.address, la dirección del contrato del token. El símbolo asset proviene del propio contrato del token, y cualquiera puede desplegar un token que se haga llamar USDC.

¿En qué se diferencia un webhook de una API?

Una API espera a que la llames. Tu app envía una solicitud y recibe datos. Un webhook invierte la dirección, porque el proveedor llama a tu app cuando tiene algo que informar. Por esa inversión, a los webhooks a veces se les llama APIs inversas.

Solicitud a la API
Polling
Webhook
Quién inicia el intercambio
Tu app
Tu app, a intervalos regulares
El proveedor
Cuándo se mueven los datos
Cuando tú los pides
En cada intervalo, aunque no haya cambios
Solo cuando ocurre un evento
Uso típico
Leer el estado actual bajo demanda
Comprobaciones simples en las que se acepta cierto retraso
Reaccionar a eventos en tu servidor

La mayoría de las apps en producción usan ambos. El webhook te avisa que algo ocurrió, y una llamada a la API completa el resto. Un backend de pagos podría recibir un webhook de depósito y luego llamar a la Token API para leer el saldo actual de la wallet antes de mostrárselo al usuario.

Los webhooks encajan cuando el consumidor es un endpoint de servidor. Si el consumidor es un proceso de larga duración, como un bot de trading o un dashboard en vivo, una suscripción WebSocket mantiene abierta una sola conexión y transmite los eventos por ella. Nuestra comparación de webhooks, WebSockets y gRPC explica cómo elegir entre ellos.

¿Cómo funcionan los webhooks?

Una entrega de webhook pasa por las mismas etapas cada vez:

  • Te suscribes. Creas un webhook con una URL de destino y un filtro que indica qué red vigilar y qué vigilar en ella, como una lista de direcciones o los eventos de un contrato.
  • Un evento coincide. Un bloque nuevo contiene actividad que coincide con tu filtro.
  • El proveedor envía un POST. La solicitud lleva el payload y un encabezado de firma que tu servidor puede comprobar.
  • Tu servidor confirma la recepción. Una respuesta 200 marca el evento como entregado.
  • Las entregas fallidas se reintentan. Si tu servidor está caído, excede el tiempo de espera o devuelve cualquier otro estado, el proveedor vuelve a intentarlo más tarde.

En Alchemy, los reintentos usan backoff exponencial, lo que significa que la espera entre intentos aumenta después de cada fallo. Seguimos reintentando durante hasta 10 minutos en los planes Free y Pay As You Go, y hasta una hora en Enterprise, como describe nuestra guía de inicio rápido de webhooks en la sección sobre el comportamiento de entrega.

Las notificaciones se entregan en orden en su primer intento en todas las cadenas, sin importar qué tan rápido produzcan bloques. Esa garantía aplica a los primeros intentos, así que un evento reintentado puede llegar después de otros más recientes. Guarda el número de bloque con cada evento y ordena tus registros por él, no por la hora de llegada.

Si tu servidor sigue caído después de la ventana de reintentos, los eventos de ese período no se vuelven a entregar, así que cubre el hueco con el historial de la cadena. En Ethereum y las L2 compatibles, consulta la Transfers API con las direcciones y el rango de bloques que te perdiste. En Stellar, el endpoint de transferencias de Stellar devuelve las transferencias de una cuenta filtradas por rango de ledgers. En Solana, pagina hacia atrás por las transacciones de cada dirección vigilada con getSignaturesForAddress.

¿Para qué se usan los webhooks en las apps de blockchain?

Ofrecemos cuatro tipos de webhook, y el adecuado depende de lo que necesites vigilar.

Tipo de webhook
Qué rastrea
Redes
Address Activity
Transferencias de token nativo, ERC-20, ERC-721 y ERC-1155 hacia o desde hasta 100,000 direcciones
Más de 30 cadenas EVM y Solana
NFT Activity
Transferencias de un NFT, de una colección completa o de todos los NFT de una cadena
Ethereum, Arbitrum, Optimism y Polygon
Custom
Cualquier dato de bloques, transacciones o logs que selecciones con una consulta GraphQL
Una red por webhook
Stellar Address Activity
Transferencias de XLM y de activos de Stellar, órdenes ejecutadas en DEX y eventos de contratos Soroban para hasta 100,000 cuentas
Stellar

Los webhooks de Address Activity cubren la tarea más común, que es vigilar un conjunto de wallets. Un backend de pagos vigila sus direcciones de depósito y le acredita el depósito al usuario cuando llega USDC. Una app de wallet envía una notificación push cuando un usuario recibe tokens. Las transferencias ERC-20 incluyen la dirección del contrato del token, que es como el backend de pagos confirma que un depósito es USDC real.

Los webhooks de NFT Activity hacen lo mismo con los contratos de NFT, lo que conviene a marketplaces y dashboards de colecciones. Los webhooks Custom cubren todo lo demás. Escribes una consulta GraphQL que selecciona los datos de bloque que quieres, como los logs de tu propio contrato con una firma de evento específica, y el webhook se dispara en cada bloque nuevo solo con esos datos. Los webhooks de Stellar Address Activity llevan el seguimiento de direcciones a Stellar, incluidos los eventos de contratos Soroban.

Cada webhook vigila una red. Para cubrir varias cadenas, crea un webhook por red y apúntalos todos a la misma URL. Los webhooks también sirven para agentes de IA onchain, que pueden activarse cuando una wallet vigilada mueve fondos en lugar de hacer polling en un bucle.

¿Cómo se verifica la firma de un webhook?

Cualquiera que encuentre la URL de tu webhook puede enviarle una solicitud, así que tu endpoint tiene que confirmar que cada solicitud vino del proveedor antes de actuar en consecuencia. Firmamos cada solicitud de webhook con HMAC-SHA256, un hash con clave que solo puede reproducir quien tenga la clave secreta. La clave es la clave de firma de tu webhook, la entrada es el cuerpo de la solicitud y el resultado en hexadecimal va en el encabezado X-Alchemy-Signature. Tu servidor calcula el mismo hash sobre el cuerpo que recibió y compara los dos valores.

Cada webhook tiene su propia clave de firma, que aparece en la página de ese webhook en el dashboard de Alchemy. Tres detalles determinan si la comprobación te protege:

  • Calcula el hash sobre los bytes sin procesar. La firma cubre el cuerpo exactamente como se envió. Si tu framework parsea el JSON y tu código lo vuelve a serializar, los espacios y el orden de las claves pueden cambiar, y los hashes no van a coincidir.
  • Compara en tiempo constante. Usa crypto.timingSafeEqual en Node o hmac.compare_digest en Python en lugar de === o ==, para que el tiempo de respuesta no revele qué parte de una firma falsificada era correcta.
  • Rechaza antes de hacer cualquier otra cosa. Devuelve un 401 y detente. No parsees ni guardes un payload que no hayas verificado.

Este es un endpoint mínimo de Express que cumple con los tres:

typescript
Copied
import express from "express"; import { createHmac, timingSafeEqual } from "node:crypto"; // enqueue is your own durable queue (a database table, SQS, BullMQ). // It should resolve only after the event is safely stored. import { enqueue } from "./queue"; const signingKey = process.env.ALCHEMY_WEBHOOK_SIGNING_KEY ?? ""; if (!signingKey) throw new Error("Set ALCHEMY_WEBHOOK_SIGNING_KEY"); function isValidSignature(rawBody: Buffer, signature: string | undefined): boolean { if (!signature) return false; const expected = createHmac("sha256", signingKey).update(rawBody).digest(); const received = Buffer.from(signature, "hex"); return received.length === expected.length && timingSafeEqual(received, expected); } const app = express(); // express.raw() keeps the exact bytes Alchemy signed, so don't parse JSON on this route first. app.post("/webhooks/alchemy", express.raw({ type: "*/*" }), async (req, res) => { if (!isValidSignature(req.body, req.get("x-alchemy-signature"))) { res.sendStatus(401); return; } await enqueue(JSON.parse(req.body.toString("utf8"))); res.sendStatus(200); }); app.listen(8080);

Como segunda capa, puedes permitir en tu firewall solo las direcciones IP de nuestros webhooks. La sección de seguridad de la guía de inicio rápido de webhooks las enumera.

¿Cómo debe tu app manejar webhooks duplicados, tardíos o afectados por reorgs?

Trata la entrega de webhooks como una garantía de al menos una vez. Un reintento tras agotarse el tiempo de espera puede entregar un evento que tu servidor ya guardó, así que el handler tiene que ser idempotente. Procesar el mismo evento dos veces debe tener el mismo efecto que procesarlo una vez.

  • Deduplica por transferencia, no por solicitud. Un payload puede llevar varias transferencias, y una transacción también puede contener varias. Construye una clave a partir de la red, el hash de la transacción y la posición de la transferencia dentro de la transacción, que es log.logIndex para transferencias de tokens y typeTraceAddress para transferencias internas. Una transferencia externa solo necesita el hash, ya que una transacción tiene una sola. Guarda la clave en una tabla con una restricción de unicidad, y omite una entrega solo cuando su clave y su valor de log.removed coincidan con el registro guardado.
  • Guarda primero, confirma después. Devuelve el 200 una vez que el evento esté guardado de forma duradera, y haz el trabajo real en un worker. Un handler que hace el trabajo antes de responder se arriesga a exceder el tiempo de espera, y eso provoca el reintento de un evento sobre el que quizá ya actuaste.
  • Revierte las transferencias afectadas por reorgs. Una reorganización de la cadena, o reorg, reemplaza bloques recientes, y las transacciones de los bloques reemplazados salen de la cadena. Las transferencias de tokens incluyen un campo log.removed, y true significa que la transacción ya no está en la cadena canónica. Una entrega con log.removed en true lleva la misma clave que la transferencia original, así que trátala como una actualización del registro guardado. Marca el registro como eliminado y deshaz lo que tu app haya hecho por esa transferencia.
  • Espera la finalidad antes de acciones irreversibles. Mostrar un depósito pendiente de inmediato es razonable. Liberar fondos, enviar productos o acreditar un saldo retirable debería esperar hasta que el bloque esté finalizado. En Ethereum, la etiqueta de bloque finalized te indica qué bloques llegaron a ese punto.

¿Cómo se configura un webhook en Alchemy?

Empieza por el servidor receptor. Nuestra guía de inicio rápido de webhooks tiene servidores base en JavaScript, Python, Go y Rust con la verificación de firma incluida, y el repositorio de ejemplos de webhooks tiene proyectos completos que puedes ejecutar localmente.

Luego crea el webhook. El dashboard de webhooks es la vía más rápida. Elige el tipo y la red, agrega las direcciones o el filtro, pega tu URL y usa el botón Test Webhook para enviar un evento de ejemplo a tu endpoint.

Para crear webhooks desde código, llama a la Notify API con el token de autenticación que aparece en la parte superior de tu dashboard de webhooks:

bash
Copied
curl -X POST https://dashboard.alchemy.com/api/create-webhook \ -H "X-Alchemy-Token: $ALCHEMY_WEBHOOK_AUTH_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "network": "BASE_MAINNET", "webhook_type": "ADDRESS_ACTIVITY", "webhook_url": "https://api.example.com/webhooks/alchemy", "addresses": ["0xYOUR_DEPOSIT_ADDRESS"] }'

Puedes agregar y quitar direcciones más adelante con la misma API, así que una app que crea una dirección de depósito para cada usuario nuevo mantiene un solo webhook en lugar de crear miles. La Alchemy CLI ofrece la misma API a través de alchemy webhook create, list, update y delete, lo que resulta útil cuando un agente de programación gestiona tus webhooks.

Demo del dashboard de Alchemy
Free video demo

Mira el dashboard de Alchemy en acción

Recorrido guiado de 30 minutos: cada herramienta del dashboard, demostrada en vivo.

Watch the demo

Empieza a usar webhooks en Alchemy

Los Alchemy Webhooks están disponibles en el plan Free, sin contrato ni compromiso mínimo. Un buen primer webhook es uno de Address Activity sobre una wallet que controles. Envía una transferencia pequeña a esa wallet y observa cómo llega el payload a tu endpoint. A partir de ahí, los webhooks Custom te permiten vigilar los eventos de tus propios contratos con el mismo comportamiento de entrega, reintentos y firma.

Preguntas frecuentes

¿Qué es un webhook en términos simples?

Un webhook es un mensaje automático que una app le envía a otra cuando algo ocurre. La app emisora hace una solicitud HTTP POST a una URL que tú proporcionas, con los detalles del evento en el cuerpo de la solicitud. Tu app no tiene que pedir actualizaciones una y otra vez, porque la actualización se le envía.

¿Cuál es la diferencia entre un webhook y una API?

Con una API, tu app envía una solicitud y el servidor responde con datos. Con un webhook, el servidor le envía una solicitud a tu app cuando ocurre un evento, sin que se la pidan. Las APIs sirven para leer datos bajo demanda, y los webhooks, para reaccionar a eventos. La mayoría de las apps usan ambos: reciben un webhook y luego llaman a una API para obtener los detalles.

¿Cómo recibo una notificación por webhook cuando llega USDC a mi wallet?

Crea un webhook de Address Activity de Alchemy en la cadena donde recibes USDC, agrega la dirección de tu wallet y apúntalo a la URL de tu servidor. Cada transferencia entrante llega con el remitente, el monto y la dirección del contrato del token. Filtra por la dirección del contrato de USDC y no por el símbolo "USDC", porque cualquiera puede desplegar un token con ese nombre.

¿Cómo recibo notificaciones por webhook de la actividad de wallets en Solana?

El webhook de Address Activity de Alchemy es compatible con Solana, además de más de 30 cadenas EVM, así que puedes vigilar un conjunto de direcciones de wallet de Solana y recibir una solicitud POST cuando tengan actividad. La documentación del webhook de Address Activity enlaza a la guía de configuración específica para Solana. Verifica la firma de cada solicitud antes de procesarla.

¿Un webhook puede notificarme cuando mi contrato inteligente emite un evento?

Sí. Los webhooks Custom de Alchemy reciben una consulta GraphQL, así que puedes filtrar los logs de la dirección de tu contrato con una firma de evento específica. Luego el webhook se dispara en cada bloque nuevo solo con los logs que coinciden. Cada webhook Custom vigila una red, así que crea uno por cada cadena donde esté desplegado tu contrato.

¿Qué pasa si mi servidor está caído cuando se dispara un webhook?

Alchemy reintenta las entregas fallidas con backoff exponencial, durante hasta 10 minutos en los planes Free y Pay As You Go y hasta una hora en Enterprise. Una entrega falla cuando tu servidor no devuelve un 200. Si tu servidor está caído por más tiempo, recupera la actividad perdida con el historial de la cadena, usando la Transfers API en Ethereum y las L2 compatibles, y el endpoint de historial propio de cada cadena en Solana y Stellar.

¿Cuántas direcciones puede rastrear un webhook?

Un webhook de Address Activity de Alchemy rastrea hasta 100,000 direcciones, igual que un webhook de Stellar Address Activity. Puedes agregar y quitar direcciones con la Notify API sin volver a crear el webhook, lo que conviene a las apps que crean una dirección de depósito nueva para cada usuario.

Background gradient

Construye magia blockchain

Alchemy combina los productos y herramientas de desarrollo Web3 más potentes con recursos, comunidad y un soporte legendario.