Webhooks salientes

Suscribirte a eventos de tu workspace + verificar la firma HMAC.

Webhooks salientes

Cuando algo cambia en tu workspace (dominio registrado, pago recibido, etc), SOMA9 puede notificar a un endpoint HTTPS de tu app. Las requests vienen firmadas con HMAC SHA-256.

Crear endpoint

POST /webhooks/outbound
{
  "url": "https://your-app.com/webhooks/soma9",
  "events": ["domain.registered", "domain.expiring_soon", "payment.received"]
}

Para suscribirte a todos los eventos: events: ["*"].

La respuesta devuelve el secret UNA sola vez:

{
  "id": "ckxxx",
  "url": "https://your-app.com/webhooks/soma9",
  "events": ["domain.registered", "..."],
  "secret": "whsec_aBcDeF...",
  "active": true
}

Guardá el secret en un lugar seguro — nunca se vuelve a mostrar.

Verificar la firma

Cada request lleva los headers:

X-Soma9-Event: domain.registered
X-Soma9-Signature: sha256=<hex>
X-Soma9-Timestamp: <unix-seconds>
X-Soma9-Webhook-Id: <id>
X-Soma9-Attempt: <n>

Para verificar:

import crypto from 'node:crypto';
 
function verify(rawBody, headers, secret) {
  const ts = headers['x-soma9-timestamp'];
  const sig = headers['x-soma9-signature'];
 
  // 1. timestamp dentro de ±5 min para evitar replay
  const skew = Math.abs(Date.now() / 1000 - Number(ts));
  if (skew > 300) throw new Error('replay attack: timestamp out of range');
 
  // 2. recompute signature
  const expected = 'sha256=' + crypto
    .createHmac('sha256', secret)
    .update(`${ts}.${rawBody}`)
    .digest('hex');
 
  if (!crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(expected))) {
    throw new Error('invalid signature');
  }
}

Eventos disponibles

EventoCuándo se dispara
domain.registeredDominio registrado en el registrar
domain.expiring_soonDominio entra en ventana 30/15/7/1 días
domain.expiredDominio expiró sin renovar
domain.transferredDominio transferido in/out
domain.nameservers_changedNS modificados
domain.dnssec_enabledDS record publicado
domain.dnssec_disabledDS record removido
payment.receivedPago Stripe completado
payment.confirmedCooldown D-20 superado, listo para ejecutar
payment.failedPago falló
payment.refundedPago reembolsado

Retry policy

SOMA9 reintenta entregas fallidas con backoff: 0s, 30s, 5m, 1h, 6h (5 intentos). Tras 10 fallos consecutivos, el endpoint se desactiva automáticamente — vas a tener que reactivarlo desde el panel.

Deliveries log

GET /webhooks/outbound/{id}/deliveries

Devuelve los últimos 100 deliveries con status, statusCode y error si falló.