Cómo usar webhooks para sincronizar candidaturas con Slack y HubSpot
Qué hace realmente un webhook de ATS
Un webhook es un gancho que lanza el ATS cuando algo sucede — una candidatura es enviada, una prueba se completa, una entrevista se programa. El ATS envía un pequeño payload JSON a una URL que proporcionas. Tu código lo lee e hace algo en cascada: publicar en Slack, crear un contacto en HubSpot, actualizar una etapa en Greenhouse, disparar un Zap.
Los webhooks son económicos, push-based, y orientados a eventos. No haces polling. No reimplementas el modelo de datos. Reaccionas.
Los eventos que vale la pena conectar primero
Once eventos se disparan en la superficie de webhooks de ClarityHire, pero solo algunos importan el primer día:
application.submitted— candidatura nueva en el pipeline. El evento de notificación Slack.test.completed— la evaluación está calificada. El evento de «notificar al recruiter».test.passed/test.failed— triggers para avance automático / archivo automático.interview.scheduledeinterview.completed— sincronización de calendario y CRM.candidate.stage_changed— el evento «dile a HubSpot que el lead se calentó».candidate.hired— cierra el loop con finanzas / provisionamiento de IT.
Conecta application.submitted y candidate.stage_changed primero. Todo lo demás puede esperar hasta que hayas aprendido qué notificaciones quiere realmente tu equipo.
Patrón 1 — Alertas de candidatos en Slack
La versión ingenua: un webhook → una URL de Incoming Webhook en Slack → un mensaje plano en #hiring. Está bien por una semana. Dolor después, porque cada nuevo solicitante avisa a todo el mundo.
El patrón que se mantiene:
- Enruta por job. Mapea cada vacante a un canal Slack (
#hiring-backend,#hiring-design). Recibe el webhook en una función serverless pequeña, busca el mapping job → canal, publica allí. Función de cinco líneas. - Actualizaciones en thread por candidatura. Publica el evento
application.submittedinicial como un mensaje de nivel superior. Publica eventos posteriores (test.completed,interview.scheduled) como respuestas en el mismo thread. Ahora cada canal lee como una línea de tiempo por candidatura. - Un botón accionable. Añade un botón de acción en Slack que enlace al perfil de candidatura en el ATS. No intentes hacer la decisión real en Slack; hazlo donde viven los datos.
La razón de poner una función pequeña en el medio (en lugar de usar directamente el webhook entrante nativo de Slack) es para poder verificar la firma HMAC, buscar estado, y no filtrar una URL de Slack a toda la configuración de ATS de tu organización.
Patrón 2 — Sincronización de contactos HubSpot
El valor de HubSpot en un pipeline de contratación es el mismo que en un pipeline de ventas: mantener un registro de cada persona que haya interactuado alguna vez con tu organización, etiquetada por etapa del ciclo de vida. Los leads de contratación son personas que podrías re-enganchar en tres años.
application.submitted→ crear/actualizar contacto en HubSpot. Establece la etapa del ciclo de vida a Other o una etapa Candidate personalizada. Adjunta la vacante de origen como propiedad.candidate.hired→ actualizar ciclo de vida a Customer/Employee. Suprime correos de marketing recurrentes a personas que ahora trabajan para ti.application.rejected→ etiquetar para redescubrimiento de talento. Una etiqueta «rechazado pero calificado» es el único tag de mayor ROI en un puente HubSpot/ATS. Seis meses después, cuando tengas una requisición similar, tu sourcer consulta la etiqueta.
Usa la API batch de HubSpot para las escrituras si estás en cualquier escala. Las escrituras de un solo contacto están bien para empezar, dolorosas a 50 reqs/min.
Las trampas que te comen en producción
- Verifica la firma HMAC en cada request. La URL del webhook es accesible en internet. Si no verificas, cualquiera que encuentre tu URL puede spamear tu canal Slack. Los webhooks de ClarityHire vienen con un secreto de firma por endpoint — úsalo.
- Haz que los handlers sean idempotentes. Los webhooks se reintentan en respuestas no-2xx. Tu handler verá el mismo evento más de una vez. Clava tus acciones downstream en el ID del evento, no en el tiempo de recepción.
- Responde 2xx rápido, luego haz el trabajo. Un handler de webhook que tarda 30 segundos en llamar a HubSpot antes de devolver 200 vencerá y será reintentado. Reconoce primero, encola el trabajo, hazlo async.
- Registra la entrega, separada de la acción. El ATS te dará un log de entrega; construye el tuyo también. Cuando algo se pierde, la pregunta «¿el ATS lo envió, lo recibimos, actuamos en consecuencia?» necesita tres respuestas separadas.
Cómo está conectada la capa de webhooks de ClarityHire
/dashboard/webhooks te permite registrar un endpoint por organización, elegir qué eventos suscribir, establecer headers personalizados, y ver el log por entrega con firma HMAC, payload, código de respuesta, y botón de replay. Las entregas fallidas se reintentan con backoff exponencial. Para integraciones más ligeras también puedes enrutar a través de Zapier o usar los conectores nativos de Slack + HubSpot y saltarte el endpoint personalizado completamente.
TL;DR
Comienza con dos eventos (application.submitted, candidate.stage_changed), un canal Slack por vacante, y un flujo de sincronización de contactos HubSpot. Verifica HMAC, haz handlers idempotentes, reconoce rápido y encola. Todo lo demás escala desde esa base.