Saltar al contenido

Webhooks: eventos, firmas y reintentos

Los webhooks envían un POST JSON a una URL HTTPS de tu sistema cuando se emite un evento suscrito. Configúralos en Desarrolladores, pestaña Webhooks.

Crear una suscripción

Indica la URL HTTPS, selecciona eventos y guarda el secreto que se muestra al crearla. Conserva ese secreto en tu servidor. En Entregas puedes consultar estado, respuesta HTTP e intentos y reintentar los casos fallidos.

Eventos y cobertura actual

EventoFlujo que lo emite
message.receivedRecepción implementada en WhatsApp, Messenger, Instagram y Telegram.
message.sentRespuesta automática implementada en esos canales.
conversation.handed_offTraspaso humano del flujo de WhatsApp.
order.createdRecepción de eventos de pedidos de Shopify.
order.paidConfirmación de pago mediante eventos de Shopify.
appointment.scheduledFlujo de creación de citas.
appointment.cancelledFlujo de cancelación de citas.

La existencia del nombre del evento no significa que todas las acciones del panel, todos los canales o todas las tiendas lo emitan. No uses order.created para dar por cubierta una creación manual de pedido.

Sobre del evento

{
  "event": "order.paid",
  "data": {
    "order_id": "identificador-del-pedido"
  },
  "timestamp": "2026-09-27T15:00:00.000Z",
  "request_id": "identificador-de-la-entrega"
}

El ejemplo ilustra la estructura; data varía según el evento y el flujo emisor. Conserva el cuerpo que recibes y admite campos adicionales.

Encabezados

EncabezadoUso
X-Synvaxis-Signaturesha256= seguido del HMAC-SHA256 del cuerpo.
X-Synvaxis-EventNombre del evento.
X-Synvaxis-Request-IdIdentificador incluido en el sobre.
X-Synvaxis-Delivery-IdIdentificador del registro de entrega.
X-Synvaxis-AttemptNúmero de intento.

Verifica el cuerpo original

Calcula la firma sobre los bytes originales, antes de parsear o volver a serializar el JSON. El siguiente receptor de Express muestra la verificación completa. Instala express y configura SYNVAXIS_WEBHOOK_SECRET en el entorno.

import express from 'express';
import crypto from 'node:crypto';

const app = express();
const secret = process.env.SYNVAXIS_WEBHOOK_SECRET;
if (!secret) throw new Error('Falta SYNVAXIS_WEBHOOK_SECRET');

app.post('/hooks/synvaxis', express.raw({ type: 'application/json' }), (req, res) => {
  const signature = req.get('X-Synvaxis-Signature') || '';
  if (!/^sha256=[a-f0-9]{64}$/.test(signature) || !Buffer.isBuffer(req.body)) {
    return res.sendStatus(401);
  }
  const expected = crypto.createHmac('sha256', secret).update(req.body).digest();
  const received = Buffer.from(signature.slice(7), 'hex');
  if (!crypto.timingSafeEqual(expected, received)) return res.sendStatus(401);
  try {
    const event = JSON.parse(req.body.toString('utf8'));
    console.log({ event: event.event, requestId: event.request_id });
    return res.sendStatus(204);
  } catch {
    return res.sendStatus(400);
  }
});

app.listen(3000);

Es un receptor de verificación: solo registra el tipo y el identificador. Para procesar operaciones reales, guarda primero el evento en una cola duradera con una clave única basada en request_id y responde 2xx cuando quede aceptado. No registres el cuerpo completo si contiene datos de clientes.

Registra esta ruta antes de un middleware global express.json(). Si ese middleware consume el cuerpo primero, perderás los bytes necesarios para verificarlo.

Reintentos

El tiempo máximo por intento es 8 segundos. Una respuesta fuera de 2xx o un fallo de conexión registra un error. Hay hasta 5 intentos automáticos en total: las esperas entre intentos son 30 segundos, 2 minutos, 10 minutos y 1 hora. Son esperas mínimas; la ejecución depende del proceso de reintentos.

Tras el quinto fallo no se programa otro reintento automático. El endpoint deja de recibir nuevas entregas al acumular 20 fallos consecutivos. Revisa Entregas, corrige el receptor y reintenta un fallo; una entrega exitosa restablece el contador. La interfaz no ofrece editar la URL: si necesitas cambiarla, crea otra suscripción y retira la anterior.

Evita procesar dos veces

Los reintentos conservan request_id. Deduplica en almacenamiento persistente antes de aplicar cobros, crear registros o enviar mensajes. No presupongas un orden global ni entrega exactamente una vez. Usa las consultas REST para reconciliar estados cuando sea necesario.

Ayuda del equipo

¿Necesitas que lo revisemos contigo?

Cuéntanos qué pasó y qué pasos ya probaste. No incluyas contraseñas, claves API ni datos de tus clientes.

Qué información preparar →
Preparar correo

Se abrirá tu aplicación de correo. Revisa el mensaje antes de enviarlo a gerencia@synvaxis.com.