SocialHub.AI
Centro para desarrolladores · Extensibilidad abierta

Webhooks

Suscribir sus propios sistemas a los eventos Flash. Registrar un punto final HTTPS para los eventos que le interesan y Flash entrega una carga útil firmada y ligera en el momento en que se activa cada evento; sin sondeo ni exportación nocturna. Las firmas siguen la especificación Standard Webhooks, los intentos de entrega se reintentan con retroceso y cada intento queda registrado.

Paso 1: suscribirse

Registrar un punto final

Crea un punto final de webhook con una clave Bearer fl_live_ que contenga el ámbito webhooks:manage. Envía una solicitud HTTPS url y la lista de eventTypes que deseas que se entreguen allí. El secreto de firma en la respuesta y nunca más; guárdalo de forma segura, ya que lo necesitas para verificar cada entrega.

curl -X POST https://flash.socialhub.ai/api/v2/webhooks \
  -H "Authorization: Bearer fl_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://hooks.your-app.com/flash",
    "description": "prod ingest",
    "eventTypes": ["member.created", "loyalty.tier_upgraded"]
  }'

# 201 Created
# {
#   "data": {
#     "id": "whe_...",
#     "url": "https://hooks.your-app.com/flash",
#     "eventTypes": ["member.created", "loyalty.tier_upgraded"],
#     "status": "active",
#     "secret": "whsec_..."   <-- shown ONCE, store it now
#   }
# }

Administre los puntos finales más adelante con GET /api/v2/webhooks (lista, sin secretos), PATCH /api/v2/webhooks/{id} (cambiar URL/eventos/estado o enviar { "action": "rotate_secret" } para rotar el secreto) y DELETE /api/v2/webhooks/{id}. También puedes registrar, probar y reproducir entregas desde Configuración → Webhooks.

Paso 2: descubre eventos

Catálogo de eventos

Pregunte a API a qué eventos puede suscribirse. El catálogo se deriva de la fuente de información en tiempo real de los activadores de automatización, por lo que solo incluye los eventos que se activan hoy, agrupados por etapa del ciclo de vida (adquisición, participación, fidelización, retención, comercio, promoción), cada uno con su clave de evento, una descripción y un ejemplo de carga útil. La respuesta también documenta el sobre de carga útil compartida y los encabezados de firma.

curl https://flash.socialhub.ai/api/v2/events/catalog \
  -H "Authorization: Bearer fl_live_..."

# { "data": { "events": [
#     { "event": "member.created", "label": "Member created",
#       "stage": "acquisition", "examplePayload": { ... } },
#     { "event": "loyalty.tier_upgraded", "label": "Tier upgraded",
#       "stage": "loyalty", "examplePayload": { ... } },
#     ...
#   ],
#   "payload": { "schema": { ... }, "headers": { ... } }
# } }

Introduce la clave event de un evento directamente en eventTypes array al suscribirte. Requiere el alcance webhooks:manage.

la entrega

Una carga útil ligera y sin información personal identificable (PII)

Cada entrega contiene el mismo paquete: un id estable, el type de evento, un created_at timestamp y un bloque data compacto. La carga útil nunca contiene datos personales: ni correo electrónico, ni nombre, ni teléfono, ni dirección. Cuando necesite los datos del miembro, recupérelos a través del API autenticado usando member_ref. Esto mantiene la información de identificación personal en el registro del miembro y fuera de los registros de su webhook.

POST https://hooks.your-app.com/flash
webhook-id:        evt_a1b2c3...              # stable across retries — dedupe on this
webhook-timestamp: 1767225600                 # unix seconds
webhook-signature: v1,K5x0mF...==             # base64 HMAC-SHA256 (may be space-separated during rotation)
Content-Type:      application/json

{
  "id": "evt_a1b2c3...",
  "type": "loyalty.tier_upgraded",
  "created_at": "2026-01-01T00:00:00.000Z",
  "data": {
    "resource_id": "mbr_...",
    "member_ref": "mbr_...",     // opaque member id — fetch PII via the API
    "tier": "Gold",              // present on loyalty / tier events
    "amount_band": "100-500"     // coarse band on commerce events — never the exact amount
  }
}
Seguridad

Verificar cada firma

Flash firma cada entrega con el secreto whsec_ de su punto final usando Webhooks estándar (HMAC-SHA256). Recalcula la firma sobre {webhook-id}.{webhook-timestamp}.{body} y compárala, en tiempo constante, con el encabezado webhook-signature. Rechaza todo lo que no coincida y rechaza un webhook-timestamp que sea demasiado antiguo para protegerse contra repeticiones. La clave de firma son los bytes decodificados en base64 del secreto después del prefijo whsec_, según la especificación. Durante una rotación de secreto, el encabezado lleva múltiples valores v1,… separados por espacios; acepta la entrega si alguno coincide.

import crypto from "node:crypto";

// req.body must be the RAW, unparsed request body string.
function verifyFlashWebhook(headers, rawBody, whsec) {
  const id = headers["webhook-id"];
  const ts = headers["webhook-timestamp"];
  const sigHeader = headers["webhook-signature"]; // "v1,<b64> v1,<b64> ..."

  // reject stale deliveries (5 min tolerance)
  if (Math.abs(Date.now() / 1000 - Number(ts)) > 300) return false;

  const key = Buffer.from(whsec.replace(/^whsec_/, ""), "base64");
  const expected = crypto
    .createHmac("sha256", key)
    .update(`${id}.${ts}.${rawBody}`)
    .digest("base64");

  return sigHeader
    .split(" ")
    .map((p) => p.split(",")[1])
    .some((sig) =>
      sig &&
      sig.length === expected.length &&
      crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(expected)),
    );
}
Fiabilidad

Reintentos, idempotencia y registro de entrega

Regresa 2xx rápidamente

Confirma con cualquier 2xx y realiza tu trabajo de forma asíncrona. Un 429, un 5xx, un tiempo de espera agotado o un error de conexión se tratan como reintentos.

Reintento automático con retroceso

Los fallos que permiten reintentos se reintentan con retroceso exponencial y fluctuación completa. Un 3xx o un 4xx distinto de 429 se trata como un fallo permanente y no se reintenta.

Eliminación de duplicados por webhook-id

El id es idéntico en todos los reintentos, por lo que la entrega al menos una vez está garantizada: un webhook-id repetido se considera ya gestionado.

Registro de entrega y reproducción

Cada intento queda registrado. Si se agotan los reintentos, la entrega se marca como fallida; puedes inspeccionar y reproducir las entregas desde Configuración → Webhooks.