Saltar al contenido principal

Webhooks

Los webhooks te permiten recibir callbacks HTTP en tiempo real cuando ocurren eventos en tus instancias de WhatsApp. En lugar de consultar la API periodicamente, Wappfy envia los eventos a tu servidor a medida que ocurren.

Eventos soportados

Wappfy soporta 12 tipos de eventos de webhook:
EventoDescripcion
message.receivedSe recibio un nuevo mensaje entrante.
message.sentUn mensaje saliente fue enviado exitosamente.
message.deliveredUn mensaje enviado fue entregado al dispositivo del destinatario (doble check).
message.readUn mensaje enviado fue leido por el destinatario (checks azules).
message.failedUn mensaje saliente fallo al enviarse.
message.reactionAlguien reacciono a un mensaje con un emoji.
EventoDescripcion
instance.connectedUna instancia se conecto exitosamente a WhatsApp.
instance.disconnectedUna instancia perdio su conexion con WhatsApp.
instance.qrUn nuevo codigo QR esta disponible para escanear.
EventoDescripcion
group.joinedUn participante se unio a un grupo (incluyendo el bot mismo).
group.leftUn participante salio de un grupo.
contact.createdSe guardo o detecto un nuevo contacto.

Crear un webhook

Registra un endpoint de webhook para comenzar a recibir eventos.
curl -X POST https://api.wappfy.io/api/webhooks \
  -H "X-Api-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://your-server.com/webhooks/wappfy",
    "events": ["message.received", "message.sent", "message.delivered"],
    "instance_id": "inst_abc123",
    "secret": "whsec_my_signing_secret",
    "retry_count": 3,
    "timeout_ms": 10000
  }'
Respuesta:
{
  "data": {
    "id": "wh_xyz789",
    "url": "https://your-server.com/webhooks/wappfy",
    "events": ["message.received", "message.sent", "message.delivered"],
    "instance_id": "inst_abc123",
    "is_active": true,
    "retry_count": 3,
    "timeout_ms": 10000,
    "created_at": "2026-02-10T12:00:00Z"
  }
}

Opciones de configuracion

CampoTipoPredeterminadoDescripcion
urlstringobligatorioLa URL HTTPS que recibira las solicitudes POST del webhook.
eventsstring[]obligatorioArray de tipos de eventos a los que suscribirse.
instance_idstringnullLimita el webhook a una instancia especifica. Si es null, recibe eventos de todas las instancias.
secretstringnullSecreto utilizado para generar firmas HMAC para verificacion del payload.
retry_countnumber3Numero de intentos de reintento en caso de fallo de entrega (0-5).
timeout_msnumber10000Tiempo de espera de la solicitud en milisegundos (1000-30000).
El campo instance_id es opcional. Si se omite, el webhook recibira eventos de todas las instancias de tu cuenta.

Listar webhooks

curl https://api.wappfy.io/api/webhooks \
  -H "X-Api-Key: YOUR_API_KEY"
Respuesta:
{
  "data": [
    {
      "id": "wh_xyz789",
      "url": "https://your-server.com/webhooks/wappfy",
      "events": ["message.received", "message.sent", "message.delivered"],
      "instance_id": "inst_abc123",
      "is_active": true,
      "retry_count": 3,
      "timeout_ms": 10000
    }
  ]
}

Actualizar un webhook

Actualiza la URL, los eventos o la configuracion de un webhook existente.
curl -X PATCH https://api.wappfy.io/api/webhooks/wh_xyz789 \
  -H "X-Api-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "events": ["message.received", "message.sent", "message.delivered", "message.read"],
    "is_active": true
  }'

Eliminar un webhook

curl -X DELETE https://api.wappfy.io/api/webhooks/wh_xyz789 \
  -H "X-Api-Key: YOUR_API_KEY"

Formato del payload de entrega

Cuando ocurre un evento, Wappfy envia una solicitud POST a la URL de tu webhook con la siguiente estructura:
{
  "id": "dlv_abc123def456",
  "event": "message.received",
  "instance_id": "inst_abc123",
  "timestamp": "2026-02-10T14:30:00Z",
  "data": {
    "message_id": "BAE5F2C4D3B2A1",
    "chat_id": "[email protected]",
    "from": "[email protected]",
    "type": "text",
    "text": "Hello!",
    "timestamp": "2026-02-10T14:30:00Z"
  }
}

Campos del payload

CampoDescripcion
idID unico de entrega. Usalo para deduplicacion.
eventEl tipo de evento que disparo esta entrega.
instance_idLa instancia que genero el evento.
timestampMarca de tiempo ISO 8601 de cuando ocurrio el evento.
dataPayload especifico del evento. El contenido varia segun el tipo de evento.

Verificacion de firma HMAC

Si proporcionas un secret al crear un webhook, cada entrega incluira un header X-Wappfy-Signature con una firma HMAC-SHA256 del cuerpo de la solicitud. Verifica siempre esta firma para asegurar que la solicitud proviene de Wappfy y no fue alterada.

Ejemplos de verificacion

const crypto = require("crypto");

function verifyWebhookSignature(req, secret) {
  const signature = req.headers["x-wappfy-signature"];
  if (!signature) return false;

  const expectedSignature = crypto
    .createHmac("sha256", secret)
    .update(JSON.stringify(req.body))
    .digest("hex");

  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expectedSignature)
  );
}

// Express middleware
app.post("/webhooks/wappfy", (req, res) => {
  const isValid = verifyWebhookSignature(req, "whsec_my_signing_secret");

  if (!isValid) {
    return res.status(401).json({ error: "Invalid signature" });
  }

  const { event, data } = req.body;
  console.log(`Received event: ${event}`, data);

  // Always respond with 200 quickly to prevent retries
  res.status(200).json({ received: true });
});
Usa siempre comparacion en tiempo constante (como timingSafeEqual o hmac.compare_digest) al verificar firmas para prevenir ataques de temporizado.

Comportamiento de reintentos

Si tu servidor no responde con un codigo de estado 2xx dentro del timeout_ms configurado, Wappfy reintentara la entrega.
IntentoRetraso
1er reintento10 segundos
2do reintento60 segundos
3er reintento5 minutos
4to reintento30 minutos
5to reintento2 horas
Los reintentos se detienen cuando se recibe una respuesta 2xx o se agota el retry_count. El conteo de reintentos predeterminado es 3.

Ver historial de entregas

Consulta el registro de entregas de un webhook para ver los intentos de entrega pasados y sus resultados.
curl https://api.wappfy.io/api/webhooks/wh_xyz789/deliveries \
  -H "X-Api-Key: YOUR_API_KEY"
Respuesta:
{
  "data": [
    {
      "id": "dlv_abc123def456",
      "event": "message.received",
      "status": "delivered",
      "http_status": 200,
      "attempts": 1,
      "created_at": "2026-02-10T14:30:00Z",
      "delivered_at": "2026-02-10T14:30:01Z"
    },
    {
      "id": "dlv_ghi789jkl012",
      "event": "message.sent",
      "status": "failed",
      "http_status": 500,
      "attempts": 3,
      "created_at": "2026-02-10T14:31:00Z",
      "last_error": "Server returned 500 Internal Server Error"
    }
  ]
}

Ejemplos de payload por evento

{
  "id": "dlv_abc123",
  "event": "message.received",
  "instance_id": "inst_abc123",
  "timestamp": "2026-02-10T14:30:00Z",
  "data": {
    "message_id": "BAE5F2C4D3B2A1",
    "chat_id": "[email protected]",
    "from": "[email protected]",
    "type": "text",
    "text": "Hello, I need help with my order",
    "timestamp": "2026-02-10T14:30:00Z"
  }
}
{
  "id": "dlv_def456",
  "event": "message.delivered",
  "instance_id": "inst_abc123",
  "timestamp": "2026-02-10T14:30:05Z",
  "data": {
    "message_id": "BAE5A1B2C3D4E5",
    "chat_id": "[email protected]",
    "status": "delivered"
  }
}
{
  "id": "dlv_ghi789",
  "event": "message.read",
  "instance_id": "inst_abc123",
  "timestamp": "2026-02-10T14:31:00Z",
  "data": {
    "message_id": "BAE5A1B2C3D4E5",
    "chat_id": "[email protected]",
    "status": "read"
  }
}
{
  "id": "dlv_jkl012",
  "event": "message.reaction",
  "instance_id": "inst_abc123",
  "timestamp": "2026-02-10T14:32:00Z",
  "data": {
    "message_id": "BAE5F2C4D3B2A1",
    "chat_id": "[email protected]",
    "from": "[email protected]",
    "reaction": "\u2764\ufe0f"
  }
}
{
  "id": "dlv_mno345",
  "event": "instance.connected",
  "instance_id": "inst_abc123",
  "timestamp": "2026-02-10T12:00:00Z",
  "data": {
    "instance_id": "inst_abc123",
    "status": "connected",
    "phone_number": "5511999998888"
  }
}
{
  "id": "dlv_pqr678",
  "event": "instance.qr",
  "instance_id": "inst_abc123",
  "timestamp": "2026-02-10T11:59:00Z",
  "data": {
    "instance_id": "inst_abc123",
    "qr": "data:image/png;base64,iVBORw0KGgo..."
  }
}
{
  "id": "dlv_stu901",
  "event": "group.joined",
  "instance_id": "inst_abc123",
  "timestamp": "2026-02-10T15:00:00Z",
  "data": {
    "group_id": "[email protected]",
    "participant": "[email protected]"
  }
}

Buenas practicas

Responder rapidamente

Devuelve un estado 200 dentro de 5 segundos. Procesa el evento de forma asincrona para evitar tiempos de espera.

Deduplicar

Usa el id de entrega para detectar y omitir entregas duplicadas causadas por reintentos.

Verificar firmas

Valida siempre el header X-Wappfy-Signature si configuraste un secreto.

Usar HTTPS

Las URLs de webhook deben usar HTTPS. Los endpoints HTTP seran rechazados.