Skip to main content
Los webhooks te avisan cuando algo cambia en una tienda donde está instalada tu app, para que no tengas que consultar la API todo el tiempo.

Cómo se entregan

Hacemos un POST con un cuerpo JSON a la URL de webhook de tu app.
  • La URL tiene que ser https y pública. No funciona con localhost: para desarrollar usá un túnel (ngrok, cloudflared).
  • Tenemos 5 segundos para recibir tu respuesta y no seguimos redirects.
  • Cualquier respuesta 2xx cuenta como recibido; cualquier otra cosa (o un timeout) se reintenta.
  • El cuerpo pesa como máximo 256 KB. De tu respuesta leemos como mucho 1 KB, sólo para mostrártela en el log del portal.
  • Respondé rápido y procesá después: guardá el evento y devolvé 200 antes de hacer trabajo pesado.

Headers

Cuerpo del evento

data se arma en el momento de enviar, no cuando ocurrió el evento. Tratá cada webhook como un aviso de que “algo cambió”: si dos cambios ocurren seguidos, los dos eventos pueden traer el mismo estado final. Si necesitás el estado exacto, pedilo por la API.

Qué trae meta en cada evento

Ejemplos:
Cuando un cambio masivo toca más de 5.000 productos, en lugar de miles de product.updated mandamos un único products.bulk_updated. Es una señal para que vuelvas a sincronizar con GET /products?updated_since=.... Lo reciben las apps suscriptas a product.updated.

Eventos disponibles

Elegís a qué eventos suscribirte en el portal. Para recibir un evento, tu instalación necesita el scope read_ del recurso (ver Scopes y permisos).

Los 4 webhooks obligatorios

app.uninstalled, store.redact, customers.redact y customers.data_request se entregan siempre, sin que te suscribas y aunque tu instalación no tenga scopes de clientes. Una app sin URL de webhook no se puede publicar. email_hash es el SHA-256 en hexadecimal del email en minúsculas (no mandamos el email en claro, porque estos eventos llegan a todas las apps). Es null si el email ya fue anonimizado. Si el cliente ya no existe, data es sólo { "id": "<id del cliente>" }.

Garantías

  • Al menos una vez. Puede llegarte el mismo evento más de una vez. Deduplicá por X-Commercy-Event-Id.
  • Sin orden garantizado. Un order.updated puede llegar antes que el order.created o después. Guiate por el estado que trae data, no por el orden de llegada.
  • Sin eco. Los cambios que hace tu propia app por la API no te vuelven como webhook.

Reintentos y baja automática

Si tu endpoint no responde 2xx, reintentamos hasta 12 veces más (13 intentos en total, durante unas 44 horas). Los tiempos de espera, con una variación aleatoria de ±10 %, son: 30 s, 1 min, 2 min, 5 min, 15 min, 30 min, 1 h, 2 h, 4 h, 8 h, 12 h, 16 h Después del último intento la entrega queda como dead. Si todas las entregas de tu app fallan durante 48 horas seguidas, damos de baja el webhook y te avisamos por email. Mientras está de baja no se envían eventos. Lo reactivás desde el portal, una vez que tu endpoint esté sano.

Replay y log

En el portal ves el log de entregas de los últimos 30 días, con el código HTTP, el tiempo de respuesta y el inicio de tu respuesta. Desde ahí podés reenviar una entrega puntual o todas las fallidas de un rango de hasta 7 días. El replay conserva el mismo X-Commercy-Event-Id y genera un X-Commercy-Delivery nuevo.

Ping de prueba

Desde el portal podés enviar un evento ping a tu URL. Viene firmado igual que los demás, con store_id: null, data: { "app_id": "..." } y sin el header X-Commercy-Store.

Verificar la firma

Firmamos cada entrega para que puedas comprobar que viene de Commercy y que nadie la alteró. La firma es:
en hexadecimal y con el prefijo v1=. Para verificarla:
  1. Leé el cuerpo crudo (los bytes tal como llegaron, antes de parsear el JSON). Si lo parseás y lo volvés a serializar, la firma no coincide.
  2. Calculá la firma con tu secreto de webhook completo, incluido el prefijo whsec_.
  3. Compará con X-Commercy-Signature con una comparación de tiempo constante.
  4. Rechazá las entregas con un timestamp que difiera más de 5 minutos de tu reloj (protección contra replay).
Con Express, usá el parser raw en esa ruta para conservar el cuerpo crudo:

Vector de prueba

Usalo para comprobar tu implementación sin esperar un webhook real. Con este secreto, timestamp y cuerpo, tu código tiene que generar exactamente la firma indicada. Cuerpo (una sola línea, sin saltos ni espacios extra):

Rotación del secreto

Desde el portal podés rotar el secreto de webhook. Las entregas nuevas se firman con el secreto nuevo desde el momento de la rotación: no hay un período con doble firma. Actualizá el secreto en tu servidor apenas lo rotes; las entregas que fallen en el medio se reintentan y se firman con el secreto vigente.