Menú de la documentación

Webhooks de consentimiento: eventos firmados a su servidor

Reciba los eventos consent.recorded y consent.withdrawn en su servidor, verifique la firma HMAC con el SDK y pruebe la entrega con un evento firmado.

En esta página

Los webhooks de consentimiento envían cada decisión a su servidor como un POST HTTP firmado: consent.recorded cuando un visitante otorga al menos una categoría, consent.withdrawn cuando rechaza o se retracta. Esto es lo que hace aplicable el derecho de retirada en el lado servidor; cuando un visitante se retracta, su backend se entera y puede purgar o detener el tratamiento.

Crear un webhook

Dos caminos, el mismo contrato:

  • En la app: el asistente de configuración en la página Integración del Builder: introduzca la URL de su endpoint, con la opción de limitar el webhook a un solo banner (por defecto: todo el espacio de trabajo).
  • Vía MCP: la herramienta configure_consent_webhook, si maneja FlowConsent desde Claude u otro cliente MCP.

En ambos casos recibe un secreto de firma con el formato whsec_….

La firma

Cada entrega lleva una cabecera X-FlowConsent-Signature, al estilo Stripe:

X-FlowConsent-Signature: t=1722326400,v1=5f8a1c…

donde t es una marca de tiempo Unix y v1 = HMAC-SHA256(secreto, "<t>.<cuerpo bruto>"). La marca de tiempo acota el replay: rechace las entregas cuyo t sea demasiado antiguo.

Verificar con el SDK de servidor

@flowconsent/server-sdk incluye verifyWebhookSignature: comparación en tiempo constante, tolerancia de replay de 300 s por defecto:

app/api/flowconsent-webhook/route.ts
ts
import { verifyWebhookSignature } from '@flowconsent/server-sdk'
 
export async function POST(request: Request) {
  const rawBody = await request.text() // cuerpo bruto, antes de cualquier JSON.parse
  const check = await verifyWebhookSignature(
    rawBody,
    request.headers.get('X-FlowConsent-Signature'),
    process.env.FLOWCONSENT_WEBHOOK_SECRET!,
  )
  if (!check.valid) {
    // check.reason: 'missing_header', 'malformed_header',
    // 'timestamp_out_of_tolerance', 'signature_mismatch'
    return new Response('invalid signature', { status: 400 })
  }
 
  const event = JSON.parse(rawBody)
  if (event.test) return new Response('ok') // evento de prueba del asistente: nunca un consentimiento real
 
  if (event.type === 'consent.withdrawn') {
    // detener el tratamiento para event.visitor_id, purgar los sistemas aguas abajo…
  }
  return new Response('ok')
}

Los eventos

consent.recorded: formato exacto de entrega
json
{
  "id": "5f0e0a1c-…",
  "type": "consent.recorded",
  "banner": "FC-A1B2C3",
  "visitor_id": "v_8f3d…",
  "action": "accept_all",
  "categories": {
    "functional": true,
    "analytics": true,
    "marketing": false,
    "preferences": false
  },
  "services": { "google-analytics": true },
  "policy_version": "3",
  "occurred_at": "2026-07-30T09:41:22.000Z"
}
  • type vale consent.recorded cuando al menos una de las categorías analytics, marketing, preferences está otorgada; en caso contrario, consent.withdrawn.
  • banner es el código de licencia público del banner: los identificadores internos nunca se exponen.
  • visitor_id es el identificador seudónimo que también aparece en los registros de consentimiento y en el decision.visitorId del SDK de servidor.
  • occurred_at está en ISO 8601.

Probar la entrega

El «enviar prueba» del asistente manda un evento consent.test a su endpoint, firmado con su secreto real y con un marcador explícito "test": true: nunca lo trate como un consentimiento real. Confirma, de extremo a extremo, que su endpoint recibe, verifica y responde. El resultado de la entrega (estado HTTP, duración) se muestra en la app.

Entrega y reintentos

  • 3 intentos por entrega, backoff exponencial (250 ms, 500 ms, 1 s entre intentos), timeout de 5 s cada uno.
  • Una respuesta 4xx (salvo 429) detiene los reintentos: reintentar no cambiaría nada.
  • Responda 2xx rápido y procese en asíncrono: cualquier otra cosa cuenta como entrega fallida.
  • El estado y la hora de la última entrega son visibles en cada webhook dentro de la app.

Haga que su sitio cumpla la normativa hoy mismo.

Gratis hasta 25.000 sesiones al mes. Sin tarjeta de crédito, sin compromiso.