---
term: 'Webhooks'
seoTitle: 'Webhooks: qué son, seguridad HMAC, retries e idempotencia'
headline: '¿Qué son los Webhooks?'
slug: webhooks
category: backend-compute
shortDefinition: 'Un webhook es un callback HTTP automatizado: cuando ocurre un evento, un sistema envía un POST con el payload a una URL que otro sistema registró.'
relatedTerms:
  - event-driven-architecture
  - websockets-real-time-sync
  - cloud-code-serverless-functions
  - pub-sub-pattern
contrastsWith:
  - websockets-real-time-sync
aboutTerms:
  - 'Endpoint de Webhook'
  - 'Verificación de firma HMAC'
  - 'Entrega at-least-once'
faq:
  - question: '¿Qué es un webhook en términos simples?'
    answer: 'Un mensaje HTTP automático que un sistema envía a otro en el momento en que algo sucede — un timbre en lugar de revisar la puerta a cada rato. Le das una URL a un proveedor; cuando el evento se dispara, este hace un POST con los datos del evento hacia allí. El término data de 2007: "user-defined HTTP callbacks".'
  - question: '¿Cuál es la diferencia entre un webhook y una API?'
    answer: 'Dirección e iniciativa. Una API es orientada a solicitudes — el cliente pregunta, el servidor responde. Un webhook es orientado a eventos — el servidor empuja cuando algo sucede, sin que se lo pidan. Un webhook es en realidad un patrón construido sobre APIs, y la mayoría de las integraciones reales usa ambos: webhooks para enterarse de los cambios, llamadas de API para actuar sobre ellos.'
  - question: '¿Cuál es la diferencia entre webhooks y polling?'
    answer: 'El polling pregunta con un timer y casi siempre escucha "nada todavía" — una medición en una gran plataforma de automatización se hizo famosa al encontrar que cerca del 98% de los polls no devuelve datos nuevos. Los webhooks lo invierten: cero solicitudes en reposo, entrega inmediata ante el cambio. El polling sobrevive como red de reconciliación debajo de los webhooks, no como su rival.'
  - question: '¿Cómo recibo un webhook?'
    answer: 'Expón un endpoint HTTPS que acepte POST, registra su URL con el proveedor y selecciona los eventos que quieres. En el handler: verifica la firma, devuelve un 2xx en cuestión de segundos y haz el procesamiento real de forma asíncrona. Prueba con una herramienta de captura antes de cablear la lógica de producción.'
  - question: '¿Los webhooks son seguros?'
    answer: 'No por defecto — el endpoint es una URL pública a la que cualquiera puede hacer POST. La defensa estándar es una firma HMAC: el proveedor firma cada payload con un secreto compartido, y tú recalculas sobre el cuerpo crudo y comparas en tiempo constante, rechazando timestamps viejos para bloquear replays. HTTPS siempre; las allowlists de IP como guarnición.'
  - question: '¿Qué pasa si mi endpoint está caído?'
    answer: 'Los buenos proveedores hacen retry con backoff exponencial, a menudo durante horas o días — por eso la entrega es at-least-once y los duplicados son normales. Los eventos aún pueden perderse más allá de la ventana de retry, así que las integraciones críticas reconcilian con polls periódicos a la API en lugar de confiar solo en los webhooks.'
  - question: '¿Cómo manejo las entregas duplicadas de webhooks?'
    answer: 'Deduplica por el ID único del evento: registra los IDs procesados y salta las resolicitudes, conservando el registro al menos tanto como la ventana de retry del proveedor. Entrega at-least-once más un handler idempotente equivale, en la práctica, a procesamiento exactly-once — la mitad del contrato de confiabilidad que le toca al receptor.'
  - question: '¿Cuál es la diferencia entre un webhook y un WebSocket?'
    answer: 'Un webhook es una notificación HTTP stateless, de un solo sentido, de servidor a servidor; un WebSocket es una conexión persistente y bidireccional, hecha para el tiempo real de cara al cliente, como chat y dashboards en vivo. Un servidor le avisa a otro servidor: webhook. Un servidor transmite a interfaces de usuario: WebSocket.'
codeLanguages: [javascript, dart, swift, kotlin]
externalAuthorities:
  - name: 'webhooks.fyi — webhook best practices'
    url: 'https://webhooks.fyi/'
  - name: 'W3C WebSub Recommendation'
    url: 'https://www.w3.org/TR/websub/'
  - name: 'REST Hooks — resthooks.org'
    url: 'https://resthooks.org/'
  - name: 'OWASP SSRF Prevention Cheat Sheet'
    url: 'https://cheatsheetseries.owasp.org/cheatsheets/Server_Side_Request_Forgery_Prevention_Cheat_Sheet.html'
cta:
  title: 'Webhooks en ambas direcciones'
  text: 'En Back4app, un trigger afterSave es un webhook saliente y una Cloud Function es un receptor listo para usar — verifica la firma, escribe en tu base de datos y deja que las Live Queries lleven el resultado a cada pantalla.'
  linkText: 'Empieza gratis'
  linkUrl: 'https://www.back4app.com/signup'
author: 'Back4app Engineering'
publishedDate: '2026-08-28'
translationKey: webhooks
---

**Un webhook es un callback HTTP automatizado: cuando ocurre un evento, un sistema envía un POST con el payload a una URL que otro sistema registró.** El término — acuñado en 2007 como "user-defined HTTP callbacks" — nombra la inversión que importa: en lugar de que tu sistema pregunte una y otra vez si algo cambió, el otro sistema le avisa al tuyo en el momento en que cambia. Es push construido con las piezas más simples de la web: una URL HTTPS, un POST, un cuerpo JSON y un 2xx de confirmación.

## Puntos clave

| Pregunta | Respuesta |
| --- | --- |
| El mecanismo | Registra una URL → el evento se dispara → el proveedor hace POST del payload → devuelves 2xx |
| vs. una API | Las APIs responden cuando se les pregunta; los webhooks hablan cuando algo sucede |
| La vara de seguridad | HMAC sobre el cuerpo crudo, comparación en tiempo constante, ventana de timestamp |
| La verdad de la entrega | At-least-once, sin orden, con retries — deduplica y reconcilia |
| El mantra del receptor | Verifica · confirma rápido · procesa async · deduplica por ID de evento |

## La entrega, de punta a punta

```text
CONFIG    el receptor expone  https://api.example.com/hooks/payments
          y la registra con el proveedor, eligiendo eventos + un secret

EVENTO    un cobro se aprueba en el proveedor

ENTREGA   POST /hooks/payments
          webhook-id: evt_8fk2            ← clave de deduplicación
          webhook-timestamp: 1767024900   ← guardia anti-replay (dentro de la firma)
          webhook-signature: v1,d2Vio…    ← HMAC-SHA256(secret, id.timestamp.body)
          { "type": "charge.succeeded", "orderId": "o-1187" }

ACK       el receptor verifica la firma → 200 en segundos → el trabajo corre async
RETRY     ¿sin 2xx? backoff exponencial por horas/días → los duplicados son NORMALES
```

Ambas direcciones del patrón en código — un trigger de datos como emisor, una Cloud Function como receptor y el cliente solo mirando el resultado:

**JavaScript:**

```javascript
// JavaScript — Cloud Code (cloud/main.js): both directions of a webhook
// OUTGOING: any data change can notify an external system
Parse.Cloud.afterSave('Order', async (req) => {
  if (req.object.get('status') !== 'paid') return;
  await Parse.Cloud.httpRequest({
    method: 'POST',
    url: 'https://hooks.example.com/orders', // the receiver's registered URL
    headers: { 'Content-Type': 'application/json' },
    body: { event: 'order.paid', id: req.object.id },
  });
});

// INCOMING: a Cloud Function is a ready-made webhook receiver
Parse.Cloud.define('paymentWebhook', async (req) => {
  verifySignature(req.params, process.env.WEBHOOK_SECRET); // HMAC first
  await markOrderPaid(req.params.orderId); // write fast, work async
  return { received: true }; // 2xx before heavy processing
});
```

**Flutter:**

```dart
// Flutter / Dart — Back4app Flutter SDK
// The client's side of a webhook: watch its effect in real time
// (payment platform → Cloud Function receiver → database → Live Query → UI)
final orderQuery = QueryBuilder<ParseObject>(ParseObject('Order'))
  ..whereEqualTo('objectId', orderId);
final sub = await LiveQuery().client.subscribe(orderQuery);
sub.on(LiveQueryEvent.update, (order) {
  if (order.get<String>('status') == 'paid') showReceipt();
});
// The webhook itself was handled server-side — clients just watch the data.
```

**Swift:**

```swift
// iOS / Swift — Back4app Swift SDK
// The client's side of a webhook: watch its effect in real time
// (payment platform → Cloud Function receiver → database → Live Query → UI)
let orderQuery = Order.query("objectId" == orderId)
let sub = try await orderQuery.subscribe()
sub.handleEvent { _, event in
    if case .updated(let order) = event, order.status == "paid" {
        showReceipt()
    }
}
// The webhook itself was handled server-side — clients just watch the data.
```

**Kotlin:**

```kotlin
// Android / Kotlin — Back4app Android SDK
// The client's side of a webhook: watch its effect in real time
// (payment platform → Cloud Function receiver → database → Live Query → UI)
val orderQuery = ParseQuery.getQuery<ParseObject>("Order")
orderQuery.whereEqualTo("objectId", orderId)
val sub = ParseLiveQueryClient.Factory.getClient().subscribe(orderQuery)
sub.handleEvent(SubscriptionHandling.Event.UPDATE) { _, order ->
    if (order.getString("status") == "paid") showReceipt()
}
// The webhook itself was handled server-side — clients just watch the data.
```

## Webhooks vs. APIs vs. polling

| | Webhook | Llamada de API | Polling |
| --- | --- | --- | --- |
| Iniciativa | El proveedor empuja | El consumidor pregunta | El consumidor pregunta con un timer |
| Timing | En el evento | Bajo demanda | En el siguiente intervalo |
| Tráfico desperdiciado | Ninguno en reposo | Ninguno | ~98% de los polls no encuentra nada |
| Dirección | Notificación de un solo sentido | Request/response de ida y vuelta | Ida y vuelta, repetida |
| Su fuerte | "Avísame cuando" | "Haz esto / dame aquello" | Reconciliación, proveedores sin webhooks |

El debate es en gran parte falso: las integraciones maduras usan los tres — webhooks para enterarse rápido de los cambios, llamadas de [API](/glossary/es/api/) para traer el estado autoritativo y actuar, y un poll lento de reconciliación como la red bajo el trapecio.

## El checklist del receptor

La lista que la documentación de cada proveedor dispersa y ningún explicador reúne:

1. **Verifica el HMAC sobre el cuerpo crudo** — antes de parsear; el JSON re-serializado rompe las firmas.
2. **Compara en tiempo constante** — la igualdad de strings filtra timing; usa el comparador de tu biblioteca de criptografía.
3. **Aplica la ventana de timestamp** — rechaza entregas de más de ~5 minutos; como el timestamp está *dentro* del contenido firmado, un atacante no puede reproducir una solicitud vieja válidamente firmada con un reloj fresco.
4. **Devuelve 2xx rápido** — en segundos, antes del trabajo pesado; los handlers lentos sufren timeout y se reintentan hasta volverse tormentas de duplicados.
5. **Procesa de forma asíncrona** — encola, confirma y luego trabaja.
6. **Deduplica por ID de evento** — con una memoria al menos tan larga como la ventana de retry del proveedor.
7. **No confíes en el payload para acciones críticas** — trata el webhook como un timbre; trae el estado actual desde la API del proveedor antes de despachar mercancía o conceder acceso.
8. **Registra las entregas y alerta sobre fallas** — el silencio es indistinguible de un endpoint roto.

Una nota de desarrollo local que las páginas de definición se saltan: `localhost` es inalcanzable desde internet, así que el desarrollo pasa por una herramienta de túnel que le presta a tu máquina una URL pública, más una herramienta de captura para reproducir payloads reales.

## Semántica de entrega, con honestidad

La entrega de webhooks es **at-least-once**: el proveedor reintenta hasta recibir confirmación, así que los duplicados son una *característica* de la confiabilidad, no un bug en ella — la entrega exactly-once sobre una red no confiable es formalmente imposible, y el equivalente práctico es at-least-once más tu handler idempotente. **El orden no está garantizado**: los retries y los envíos en paralelo se intercalan, así que `updated` puede llegar antes que `created`; aplica los eventos por ID y versión, o vuelve a traer el estado. Y **las ventanas de retry se acaban**: un endpoint caído durante un fin de semana puede perder eventos de forma permanente, y por eso las integraciones críticas donde hay dinero de por medio combinan webhooks con reconciliación periódica — la [misma disciplina de at-least-once](/glossary/pub-sub-pattern/) que los brokers formalizan, llegando por HTTP plano. La comparación generaliza: un webhook es push punto a punto hacia una URL conocida; [pub/sub](/glossary/pub-sub-pattern/) agrega un broker, topics y fan-out; [WebSockets y SSE](/glossary/sse-vs-websockets-vs-polling/) sirven a *clientes*, no a servidores. Los webhooks son la respuesta específicamente cuando dos sistemas que no comparten infraestructura necesitan enterarse de los eventos del otro.

```mermaid
flowchart LR
  accTitle: Entrega de webhook con retries y procesamiento asíncrono
  accDescr: Un evento en el proveedor se encola y se envía por POST con una firma HMAC a la URL registrada del receptor. El receptor verifica la firma, confirma rápido con un 2xx y procesa de forma asíncrona con deduplicación. Las entregas fallidas vuelven a la cola de retry del proveedor con backoff exponencial, y las fallas repetidas van a un log de dead-letter.
  E["Ocurre un evento"] --> Q["Cola del proveedor<br/>+ firma HMAC"]
  Q -->|"POST del payload"| R["Endpoint del receptor"]
  R -->|"verifica → 2xx rápido"| A["Worker asíncrono<br/>deduplica por ID de evento"]
  R -.->|"sin 2xx"| RT["Retry con backoff<br/>horas → días"] --> Q
  RT -.->|"agotado"| DL["Log de dead-letter<br/>+ alerta"]
  A --> DB[("Tu base de datos")]
```

## Construir el lado del emisor

Emitir webhooks con confiabilidad es un pequeño sistema en sí mismo, y ninguna página de ranking lo esboza: una **cola por destino**, para que un endpoint muerto no bloquee al resto; **retries con backoff exponencial y jitter**; un **almacén de dead-letter** con herramientas de reenvío para cuando los intentos se agotan; **firma HMAC** con secretos por endpoint y rotación; **suscripciones por tipo de evento**, para que los receptores opten solo por lo que quieren; y **logs de entrega** que tus clientes puedan leer, porque "¿lo enviaron?" es la primera pregunta de soporte. Un punto de seguridad exclusivo del emisor: los receptores registran URLs arbitrarias, así que valídalas contra rangos de direcciones internas — un atacante que registra `http://10.0.0.5/admin` como su "endpoint de webhook" es [server-side request forgery](https://cheatsheetseries.owasp.org/cheatsheets/Server_Side_Request_Forgery_Prevention_Cheat_Sheet.html) disfrazado de funcionalidad de integración.

## Casos de uso comunes

- **Ciclos de vida de pagos** — cobros, reembolsos y cambios de suscripción anunciados a tu backend a medida que se liquidan.
- **Disparadores de CI/CD** — el cableado canónico del git push que arranca un build.
- **Automatización entre apps** — herramientas de formularios, plataformas de chat y CRMs encadenados a través de los eventos de los demás.
- **Notificaciones operativas** — alertas de monitoreo y actualizaciones de entrega aterrizando en los canales del equipo.
- **Sincronización de datos** — mantener al día un espejo local de un sistema aliado sin hacer polling de toda su API.

## ¿Deberías usar un webhook? Matriz de decisión

| Situación | Elige |
| --- | --- |
| El sistema de otra empresa debe notificar al tuyo | Webhooks — el estándar de interoperabilidad |
| Tus servicios, tu infraestructura | [Pub/sub](/glossary/pub-sub-pattern/) — con broker, buffer y fan-out |
| Navegadores/apps necesitan actualizaciones en vivo | [WebSockets / live queries](/glossary/websockets-real-time-sync/) |
| El proveedor no ofrece webhooks | Polling, con cortesía |
| Dinero o acceso dependen del evento | Webhook + verificar-y-refetch + reconciliación |
| Tú eres la plataforma que emite los eventos | Construye el lado del emisor de arriba — o no prometas confiabilidad |

## Limitaciones y trade-offs

- **La entrega es best-effort más allá de la ventana de retry.** Los webhooks notifican; no garantizan. Los polls de reconciliación respaldan todo lo que no puede perderse.
- **El receptor hereda el deber de uptime.** La disponibilidad de tu endpoint ahora condiciona los eventos de otra persona — deploys, cold starts y timeouts se convierten en bugs de integración.
- **La seguridad es opt-in.** Un endpoint de webhook sin verificación es una API de escritura sin autenticación; el checklist de HMAC es la diferencia entre integración e inyección.
- **El debugging atraviesa dos empresas.** Logs de entrega en ambos lados y herramientas de replay son lo que convierte "no llegó" de un punto muerto en un diff.
- **Los payloads derivan.** Los proveedores versionan los esquemas de eventos; los consumidores anclados a formas exactas se rompen en silencio — parsea a la defensiva e ignora los campos desconocidos.

## Webhooks en Back4app

Back4app es una plataforma open-source de Backend as a Service (BaaS) que combina base de datos gestionada, APIs REST y GraphQL generadas automáticamente, autenticación, almacenamiento de archivos y funciones serverless con Cloud Code. Ambas mitades del patrón están a un constructo de [Cloud Code](/glossary/es/cloud-code-funciones-serverless/) de distancia, como muestran las pestañas de código. **Saliente:** un trigger `afterSave` que observa tus datos llama a `Parse.Cloud.httpRequest` hacia cualquier URL registrada — tu app se convierte en proveedor de webhooks escribiendo la función, y las disciplinas del lado del emisor (retry ante fallas, log de entregas) viven en el mismo archivo. **Entrante:** una Cloud Function expuesta por HTTPS es un receptor listo para usar — verifica el HMAC contra un secreto en la configuración del servidor, escribe el resultado en la base de datos, devuelve rápido — y la actualización luego se propaga a cada pantalla abierta vía [Live Queries](/glossary/real-time-live-queries/), completando el ciclo que va del evento en una plataforma de pagos al recibo del usuario sin un servidor que operar en ninguno de los dos extremos.
