← Frepi Developers

📡 Webhook de encuestas NPS / CSAT

Versión 2026-07-24 · Autenticación Bearer por fuente · Idempotente por external_id

Cuando tu flujo (Respond.io u otro emisor HTTP) capture una respuesta de encuesta, un POST a este webhook la guarda en la tabla de encuestas del workspace, lista para análisis y dashboards.

1 · Lo que necesitas

2 · La petición

CampoValor
MétodoPOST
URLhttps://{dominio-del-workspace}/api/webhooks/survey/{routing_id} (la URL exacta viene en el diálogo de emisión del secreto)
Header 1Authorization: Bearer svik_…
Header 2Content-Type: application/json
⚠️ El secreto va solo en el header — nunca en la URL ni como query param, aunque tu herramienta lo permita (las URLs quedan en logs de proxies).

Body (JSON — ejemplo con variables de Respond.io):

{
  "external_id": "$contact.id-$workflow.execution_id",
  "survey_type": "nps",
  "contact_id": "$contact.phone",
  "response_value": "$nps_score",
  "response_text": "$nps_comment",
  "question": "¿Qué tan probable es que nos recomiendes?",
  "responded_at": "$system.timestamp"
}

3 · Campos

CampoRegla
external_idObligatorio y único por respuesta. Defensa anti-duplicados: un reintento con el mismo external_id es un no-op (outcome: duplicate). Contacto + id de ejecución del flujo es la combinación natural.
survey_typenps (entero 0–10) o csat (1–5).
contact_idTeléfono del contacto. Se normaliza a solo dígitos.
response_valueNota numérica. NPS fuera de 0–10 o no-entero se guarda sin clasificar (promotor/pasivo/detractor queda NULL).
response_textComentario libre. Opcional.
responded_atISO-8601 o epoch (segundos o milisegundos) — ambos aceptados.

4 · Respuestas

CódigoSignificadoQué hacer
200outcome: created (guardada) o outcome: duplicate (ya existía).Nada — ambos son éxito.
401Secreto incorrecto o ausente.Revisar el header; rotar el secreto si se perdió.
403La fuente no tiene secreto activo (revocado o nunca emitido).Emitir uno desde el panel de administración.
404routing_id desconocido.Verificar la URL emitida.
422Body inválido (falta external_id, nota no numérica…).Revisar el mapeo de variables.
503Base de datos no alcanzada a tiempo.Reintentar es seguro — external_id evita duplicados.

Presupuesto de tiempo: respondemos en ~6 s o devolvemos 503 (Respond.io corta pasos HTTP a los 10 s; el reintento es seguro).

5 · Prueba de humo

  1. Dispara una respuesta real con nota 9 y un comentario reconocible (ej. "prueba humo NPS").
  2. Verifica 200 con "outcome": "created".
  3. Re-ejecuta el mismo envío: debe devolver "outcome": "duplicate" y en Frepi sigue habiendo UNA sola fila.
  4. Confirma con tu contacto Frepi que la fila llegó con teléfono, fecha y nota correctos.
✅ created / duplicate / fila verificada = integración validada de punta a punta.

6 · Seguridad