Volver a todas las integraciones
Webhook

Webhooks salientes

Cómo enviar eventos de AppBO a tu propio endpoint: forma de los datos, verificación de firma, reintentos y manejo idempotente.

En esta página
Qué conectaCómo conectarloQué datos se muevenEjemplo prácticoLímites y trampas comunes
¿Necesitas que lo conectemos?

Trae tus herramientas a una llamada: lo conectamos, probamos cada campo en ambas direcciones y te lo entregamos documentado.

Agenda una llamada
01

Qué conecta

Un webhook saliente es la plataforma avisándole a tu sistema que algo pasó. De un lado está AppBO, que emite eventos cuando se crean contactos, las oportunidades cambian de etapa, se reservan o cancelan citas, se envían formularios, llegan mensajes o se liquidan pagos. Del otro lado hay un endpoint HTTP que tú controlas y operas. Una ruta en tu aplicación, una función serverless, un receptor respaldado por una cola, o el gancho de captura (catch hook) de una plataforma de automatización haciendo ese papel.

Los webhooks salientes existen para que nunca tengas que consultar de forma periódica. Consultar así es caro, tarda en notar los cambios y gasta el presupuesto de API de la cuenta solo para enterarse de que no pasó nada. Un webhook envía el cambio a los pocos segundos de que ocurre, y esa es la diferencia entre un espejo casi en tiempo real y un proceso de conciliación nocturno. Para cualquier cosa que vea el usuario. Un panel, una notificación, un acceso que tiene que activarse en el momento en que entra un pago. Esa diferencia de latencia es toda la función.

Hay dos formas de emitirlos. La configuración de webhooks a nivel de cuenta envía un conjunto definido de eventos de la plataforma a una URL para todo lo que pasa en esa cuenta. Un paso de flujo de trabajo, en cambio, dispara un webhook solo para los contactos que llegaron a ese punto de ese flujo, con datos (payload) que tú mismo armas. El primero es una fuente sistemática; el segundo es una señal precisa con la forma de tu lógica de negocio. La mayoría de las integraciones maduras usan los dos: la fuente sistemática para mantenerse sincronizadas, y los webhooks de flujos de trabajo para el puñado de momentos que importan.

02

Cómo conectarlo

  1. Primero construye el endpoint receptor. Tiene que aceptar POST, interpretar JSON y devolver un estado de éxito rápido: en un par de segundos. Cualquier cosa más lenta corre el riesgo de tratarse como una falla y reintentarse.
  2. Sirve el endpoint por HTTPS con un certificado válido. Los certificados autofirmados y las cadenas vencidas se rechazan, y las fallas que resultan son fáciles de confundir con que la plataforma no está enviando.
  3. Haz que el manejador no haga casi nada en línea: validar, encolar, responder. Haz el trabajo real (escrituras en la base de datos, llamadas a otras APIs, emails) en un proceso en segundo plano (worker). Procesar de forma síncrona es la causa más común de que los webhooks se agoten por tiempo.
  4. Decide qué eventos necesitas y de dónde vienen. Usa la configuración de webhooks a nivel de cuenta para el catálogo estándar de eventos; usa un paso de webhook en un flujo de trabajo para todo lo que sea condicional o lleve datos personalizados.
  5. Registra el endpoint. Para los eventos a nivel de cuenta, agrega la URL en la configuración de webhooks de la plataforma y selecciona los tipos de evento. Para los webhooks de flujos de trabajo, agrega la acción de webhook al flujo y define el método, la URL, los encabezados y el cuerpo.
  6. Establece la autenticación en ambas direcciones. Haz que la plataforma envíe una credencial que tu endpoint pueda revisar (un token bearer o un secreto compartido en un encabezado personalizado de un webhook de flujo de trabajo) y rechaza cualquier solicitud que no la traiga.
  7. Verifica la firma cuando la plataforma la proporcione. Los eventos que emite la plataforma suelen venir firmados; consulta la documentación vigente de webhooks para ver el nombre del encabezado y el algoritmo de verificación, e implementa la revisión exactamente como se especifica en lugar de inventar un esquema. Donde no haya firma disponible, el encabezado con el secreto compartido más una lista de permitidos es tu sustituto.
  8. Captura un evento real antes de escribir cualquier código de mapeo. Registra el cuerpo crudo tal cual, completo, y arma tu intérprete a partir de eso y no de una forma supuesta.
  9. Define tu clave de idempotencia. Usa el identificador del evento si los datos lo traen; si no, compón una con el identificador del objeto más el tipo de evento más la marca de tiempo. Guarda las claves procesadas y omite las repetidas.
  10. Maneja los tipos de evento desconocidos y nuevos ignorándolos sin fallar. La plataforma puede agregar campos y tipos de evento; un manejador que lanza un error ante una clave que no reconoce se va a romper con una actualización que tú no pediste.
  11. Devuelve los estados correctos. 2xx significa aceptado y detiene los reintentos. 4xx significa que no vale la pena reintentar, lo cual es correcto para datos que nunca vas a poder procesar. 5xx significa que se vuelva a intentar.
  12. Agrega un camino de mensajes fallidos (dead-letter). Cuando un evento en cola falla al procesarse una y otra vez, apártalo con el cuerpo crudo completo para poder reprocesarlo después de una corrección, en lugar de perderlo.
  13. Verifica que la conexión esté activa: dispara el evento de verdad (crea un contacto, mueve una oportunidad) y confirma que llega la solicitud, que la firma o el secreto se validan y que tu worker produjo el resultado esperado.
  14. Prueba también el camino de falla. Devuelve un 500 a propósito y confirma que ves el comportamiento de reintento que esperabas, para saber cómo se va a ver una caída real.
  15. Monitorea en producción: configura alertas por una caída en el volumen de eventos (un webhook en silencio es peor que uno que falla), por fallas en la verificación de firmas y por la cantidad de mensajes fallidos acumulados.
03

Qué datos se mueven

De la plataforma a tu endpoint

  • El sobre del evento: tipo de evento, un identificador del evento o de la solicitud, una marca de tiempo y el identificador de la cuenta o ubicación a la que pertenece el evento.
  • El objeto afectado: en los eventos de contacto, el registro del contacto con sus campos estándar y personalizados; en los eventos de oportunidad, la oportunidad con su pipeline, etapa, valor y contacto vinculado; en las citas, el calendario, el usuario asignado, los horarios y el estado.
  • Los envíos de formularios y encuestas, con el conjunto de campos enviados.
  • Los eventos de mensajes y conversaciones, con la dirección, el canal y el cuerpo.
  • En los pasos de webhook de flujos de trabajo, exactamente los datos que armaste, que pueden incluir valores combinados del contacto, el contexto del flujo y campos fijos propios.

De tu endpoint de vuelta a la plataforma

  • Un código de estado HTTP, que controla el comportamiento de reintento. En la práctica, ese es todo el canal.
  • Un webhook a nivel de cuenta no usa el cuerpo de la respuesta como datos del flujo de trabajo. Cuando un paso de flujo de trabajo es capaz de leer una respuesta, trátalo como una capacidad documentada aparte y confírmalo antes de diseñar algo que dependa de ella.

Lo que no se mueve

  • Los eventos históricos de antes de que se registrara el webhook. No se reproduce el pasado; rellena hacia atrás con la API REST.
  • Los objetos relacionados que no aparecen en los datos. Un evento de contacto no trae todo el historial de conversaciones de ese contacto: consulta lo que necesites por identificador.
  • Un orden garantizado. Los eventos pueden llegar fuera de secuencia, y el reintento de un evento viejo puede llegar después de uno más nuevo.
  • La entrega exactamente una vez. Lo realista es suponer una entrega de al menos una vez.
  • Cualquier dato de una cuenta en la que no se configuró el webhook.
04

Ejemplo práctico

Escenario: tu sistema de facturación tiene que dar acceso en el momento en que una oportunidad llega a la etapa Ganada en AppBO.

  1. Despliegas POST /hooks/appbo detrás de HTTPS. El manejador valida, pone el cuerpo en una cola y devuelve 202. La mediana del tiempo de respuesta es de menos de cincuenta milisegundos.
  2. En la plataforma armas un flujo de trabajo que se dispara con el cambio de etapa de una oportunidad, filtrado a la etapa Ganada del pipeline de ventas, y que termina en una acción de webhook.
  3. Configuras la acción de webhook para que haga POST a tu endpoint con un encabezado personalizado que lleva un secreto compartido, y un cuerpo JSON plano: event_type, event_id, occurred_at, contact_id, email, opportunity_id y plan_code tomado de un campo personalizado.
  4. Mueves una oportunidad de prueba a Ganada. Tus registros muestran el cuerpo crudo. Armas el intérprete a partir de ese cuerpo, no de tus notas.
  5. Salida en vivo: un vendedor arrastra una oportunidad real a Ganada. El flujo se dispara en segundos.
  6. Tu manejador compara el encabezado con el secreto compartido contra el valor guardado, encola el cuerpo y devuelve 202.
  7. El worker toma el trabajo, calcula la clave de idempotencia a partir de event_id y no encuentra ningún registro previo de ella.
  8. El worker busca al cliente por email, encuentra la cuenta, activa el acceso para plan_code y escribe el event_id en su tabla de eventos procesados dentro de la misma transacción.
  9. Una falla momentánea de red hace que la plataforma nunca reciba tu 202, así que reintenta el evento. El worker calcula la misma clave de idempotencia, ve que ya se procesó y devuelve éxito sin volver a tocar el acceso.
  10. La semana siguiente, un despliegue rompe el worker. Devuelve un error, el trabajo se reintenta, agota sus intentos y cae en la cola de mensajes fallidos con el cuerpo crudo intacto. Se dispara tu alerta por mensajes fallidos acumulados.
  11. Corriges el error, reprocesas los eventos fallidos y los accesos se otorgan sin perder datos, porque el cuerpo crudo se conservó y el procesamiento era idempotente.
05

Límites y trampas comunes

Límites de uso

Aquí la restricción suele estar de tu lado, no del de la plataforma. Una acción masiva, una importación de contactos, una actualización masiva de un pipeline, un flujo de trabajo que mete a miles de contactos a la vez: produce una ráfaga equivalente de entregas de webhooks. Dimensiona tu receptor para la ráfaga, no para el promedio, y pon una cola delante para que un pico se convierta en trabajo pendiente y no en eventos perdidos. Del lado de la plataforma, ten en cuenta que un paso de webhook en un flujo de trabajo consume ejecuciones del flujo como cualquier otro paso.

Reintentos e idempotencia

La entrega es de al menos una vez. Cualquier respuesta que no sea 2xx, y cualquier respuesta tan lenta que se agote por tiempo, dispara un reintento con un calendario de espera creciente, y como un tiempo agotado puede llegar después de un procesamiento exitoso, los duplicados son parte de la operación normal y no una anomalía. Elimina duplicados por un identificador de evento, y haz que los efectos del procesamiento sean idempotentes por sí mismos: otorgar un acceso en lugar de incrementar un contador, actualizar o crear (upsert) en lugar de insertar. Devuelve 4xx para los datos que nunca vas a poder procesar, para que la plataforma deje de reintentar, y reserva 5xx para las fallas que de verdad son temporales.

Trampas al mapear campos

La forma de los datos es distinta entre los eventos a nivel de cuenta y los pasos de webhook de flujos de trabajo, así que el código escrito para uno no va a interpretar el otro. Los campos personalizados pueden aparecer identificados por su identificador y no por su nombre. Los valores vacíos pueden llegar como una cadena vacía, como null o como una clave ausente: maneja los tres casos. Nunca des por hecho que un campo viene porque venía en tu muestra, y nunca falles de golpe por un campo que no esperabas.

Creación de duplicados en tu sistema

La falla clásica es un webhook que crea un registro en tu sistema con cada entrega. Dos reintentos se convierten en tres clientes. Basa cada escritura en algo estable de los datos, y trata la creación como un upsert.

Pruebas contra producción

Usa endpoints separados para cada entorno, y nunca registres una URL de staging en una cuenta de producción. Un worker de staging conectado a eventos de producción puede enviarles emails reales a clientes reales desde una plantilla a medio terminar. Mantén la lista de registros como un documento revisado, porque los endpoints viejos que nadie administra son un problema de seguridad silencioso.

Vencimiento de la autorización

Los secretos compartidos se rotan, y la rotación tiene que pasar en dos lugares a la vez. Acepta el secreto viejo y el nuevo durante un periodo de traslape y después elimina el viejo. Si verificas una firma de la plataforma, fíjate al algoritmo y al encabezado documentados, y vuelve a leer la documentación de webhooks antes de suponer que nada cambió después de una actualización de la plataforma.

Lo que se rompe con más frecuencia

  • Un certificado TLS vencido en el endpoint receptor, que se ve exactamente igual que si la plataforma hubiera dejado de enviar.
  • El procesamiento síncrono que causa tiempos agotados, reintentos y después duplicados.
  • La falla silenciosa: nadie nota que un webhook se detuvo porque no hay una alerta por ausencia de tráfico.
  • La entrega fuera de orden que deja que un estado viejo sobrescriba uno actual; compara las marcas de tiempo antes de escribir.
  • Un flujo de trabajo editado de forma que una rama nueva se salta el paso de webhook, sin ningún error en ningún lado.
  • Manejadores que lanzan errores ante campos nuevos o tipos de evento desconocidos después de una actualización de la plataforma.

Conéctalo con nosotros.

Conectamos la integración, mapeamos los campos, probamos ambas direcciones y te la entregamos con los procedimientos (SOP) que tu equipo necesita para operarla.

Agenda una llamada