Referencia de eventos de webhook
Estructuras de payload, encabezados y definiciones de campos para cada evento de webhook.
Por qué es importante
Cada entrega de webhook encapsula los datos específicos del evento en la misma envoltura. Esta referencia documenta la estructura exacta del payload de cada evento para que puedas analizarlos y actuar sobre ellos con confianza.
Envoltura del payload
{
"event": "application.submitted",
"created_at": "2025-01-15T14:30:00Z",
"data": { }
}
| Campo | Tipo | Descripción |
|---|---|---|
event |
string | El tipo de evento que activó esta entrega |
created_at |
string | Marca de tiempo ISO 8601 de cuándo ocurrió el evento |
data |
object | Payload específico del evento (varía según el tipo de evento) |
Encabezados de la solicitud
Cada solicitud de webhook incluye estos encabezados:
| Encabezado | Ejemplo | Descripción |
|---|---|---|
Content-Type |
application/json |
Siempre JSON |
X-Webhook-Event |
application.submitted |
El tipo de evento |
X-Webhook-Signature |
a1b2c3d4... |
Digest hexadecimal HMAC-SHA256 |
X-Webhook-Timestamp |
2025-01-15T14:30:00Z |
Marca de tiempo ISO 8601 usada en la firma |
User-Agent |
Kit-Webhooks/1.0 |
Identifica a Kit como el emisor |
Consulta Seguridad y entrega de webhooks para ver los detalles de la verificación de firmas.
Eventos de candidatura
Eventos: application.submitted, application.rejected, application.rejection_reverted, application.advanced, application.stage_returned, application.withdrawn, application.offer_extended
application.stage_returned se envía cuando un miembro del equipo devuelve una candidatura a una etapa anterior. Usa la misma carga de candidatura que los demás eventos de candidatura.
{
"event": "application.submitted",
"created_at": "2025-01-15T14:30:00Z",
"data": {
"id": 42,
"candidate": {
"id": 7,
"name": "Jane Smith",
"email": "[email protected]"
},
"job_posting": {
"id": 3,
"title": "Senior Engineer"
},
"current_stage": "Applied",
"submitted_at": "2025-01-15T14:30:00Z",
"rejected": false,
"withdrawn": false,
"offered": false
}
}
| Campo | Tipo | Descripción |
|---|---|---|
id |
integer | ID de la candidatura |
candidate.id |
integer | ID del candidato |
candidate.name |
string | Nombre completo del candidato |
candidate.email |
string | Dirección de email del candidato |
job_posting.id |
integer | ID de la oferta de empleo |
job_posting.title |
string | Título de la oferta de empleo |
current_stage |
string | Nombre de la etapa actual del pipeline |
submitted_at |
string | null | Marca de tiempo ISO 8601 del envío |
rejected |
boolean | Si la candidatura ha sido rechazada |
withdrawn |
boolean | Si el candidato se ha retirado |
offered |
boolean | Si se ha extendido una oferta |
Eventos de oferta
Eventos: offer.accepted, offer.declined
-
offer.accepted/offer.declined: se disparan cuando un administrador acepta o rechaza una oferta
{
"event": "offer.accepted",
"created_at": "2025-01-20T10:00:00Z",
"data": {
"id": 15,
"status": "accepted",
"details": "Senior Engineer — $150k base",
"extended_at": "2025-01-18T09:00:00Z",
"expires_at": "2025-01-25T23:59:59Z",
"accepted_at": null,
"declined_at": null,
"candidate": {
"id": 7,
"name": "Jane Smith",
"email": "[email protected]"
},
"job_posting": {
"id": 3,
"title": "Senior Engineer"
}
}
}
| Campo | Tipo | Descripción |
|---|---|---|
id |
integer | ID de la oferta |
status |
string | Uno de: pending, accepted, declined, candidate_accepted, candidate_declined, expired
|
details |
string | null | Texto con los detalles de la oferta |
extended_at |
string | null | Cuándo se extendió la oferta |
expires_at |
string | null | Cuándo expira la oferta |
accepted_at |
string | null | Cuándo un administrador aceptó la oferta |
declined_at |
string | null | Cuándo un administrador rechazó la oferta |
candidate |
object | Detalles del candidato (misma estructura que en los eventos de candidatura) |
job_posting |
object | Detalles de la oferta de empleo (misma estructura que en los eventos de candidatura) |
Eventos de entrevista
Eventos: interview.scheduled, interview.confirmed, interview.completed, interview.cancelled, interview.no_show, interview.no_show_reverted, interview.rebooked
interview.no_show_reverted se envía cuando se deshace una ausencia. interview.rebooked se envía después de cerrar la entrevista anterior e invitar al candidato a reservar otra. Ambos usan la carga de entrevista que aparece a continuación.
{
"event": "interview.scheduled",
"created_at": "2025-01-16T09:00:00Z",
"data": {
"id": 28,
"status": "pending",
"scheduled_at": "2025-01-20T14:00:00Z",
"duration_minutes": 60,
"candidate": {
"id": 7,
"name": "Jane Smith",
"email": "[email protected]"
},
"job_posting": {
"id": 3,
"title": "Senior Engineer"
}
}
}
| Campo | Tipo | Descripción |
|---|---|---|
id |
integer | ID de la entrevista |
status |
string | Estado de la entrevista (pending, confirmed, completed, cancelled, no_show) |
scheduled_at |
string | null | Marca de tiempo ISO 8601 de la hora programada |
duration_minutes |
integer | Duración de la entrevista en minutos |
candidate |
object | Detalles del candidato |
job_posting |
object | Detalles de la oferta de empleo |
Eventos de ejercicio de código
Eventos: code_assignment.submitted, code_assignment.auto_submitted
{
"event": "code_assignment.submitted",
"created_at": "2025-01-22T16:45:00Z",
"data": {
"id": 11,
"repo_url": "https://github.com/org/assignment-jane-smith",
"submitted_at": "2025-01-22T16:45:00Z",
"submitted_by": null,
"deadline_at": "2025-01-25T23:59:59Z",
"candidate": {
"id": 7,
"name": "Jane Smith",
"email": "[email protected]"
},
"job_posting": {
"id": 3,
"title": "Senior Engineer"
}
}
}
| Campo | Tipo | Descripción |
|---|---|---|
id |
integer | ID del envío de código |
repo_url |
string | URL del repositorio de GitHub |
submitted_at |
string | null | Cuándo se envió el ejercicio |
submitted_by |
object | null | Miembro del equipo (id, name) que marcó el ejercicio como enviado en nombre del candidato; null si lo envió el candidato o si se envió automáticamente al vencer el plazo |
deadline_at |
string | null | Fecha límite del ejercicio |
candidate |
object | Detalles del candidato |
job_posting |
object | Detalles de la oferta de empleo |
Eventos de revisión
Eventos: review.submitted
{
"event": "review.submitted",
"created_at": "2025-01-23T11:00:00Z",
"data": {
"id": 9,
"recommendation": "strong_yes",
"reviewer": "Alex Johnson",
"origin": "web",
"candidate": {
"id": 7,
"name": "Jane Smith",
"email": "[email protected]"
},
"job_posting": {
"id": 3,
"title": "Senior Engineer"
},
"stage": "Technical Interview"
}
}
| Campo | Tipo | Descripción |
|---|---|---|
id |
integer | ID de la revisión |
recommendation |
string | Recomendación del revisor |
reviewer |
string | Nombre del revisor |
origin |
string | Cómo se envió la revisión: web (en Kit) o mcp (registrada por una herramienta de IA mediante hiring_submit_review en nombre del revisor, tras su confirmación) |
candidate |
object | Detalles del candidato |
job_posting |
object | Detalles de la oferta de empleo |
stage |
string | Nombre de la etapa del pipeline donde se envió la revisión |
Eventos de oferta de empleo
Eventos: job_posting.published, job_posting.paused, job_posting.closed, job_posting.reopened
{
"event": "job_posting.published",
"created_at": "2025-01-10T08:00:00Z",
"data": {
"id": 3,
"title": "Senior Engineer",
"status": "published",
"location": "Remote",
"department": "Engineering",
"employment_type": "full_time",
"published_at": "2025-01-10T08:00:00Z",
"closed_at": null,
"public_url": "https://careers.example.com/senior-engineer"
}
}
| Campo | Tipo | Descripción |
|---|---|---|
id |
integer | ID de la oferta de empleo |
title |
string | Título del puesto |
status |
string | Estado actual (published, paused, closed) |
location |
string | Ubicación del puesto |
department |
string | Nombre del departamento |
employment_type |
string | Forma de colaboración (full_time, part_time, b2b, contract o internship) |
published_at |
string | null | Cuándo se publicó la oferta |
closed_at |
string | null | Cuándo se cerró la oferta |
public_url |
string | URL pública del portal de empleo para esta oferta |
Eventos de informes de CSIRT
Eventos: csirt.report.submitted, csirt.report.triaged, csirt.report.validated, csirt.report.resolved, csirt.report.fix_verified, csirt.report.dismissed, csirt.report.informative, csirt.report.assessed, csirt.report.assigned, csirt.report.bounty_approved, csirt.report.paid, csirt.report.sla_breached, csirt.report.escalation_requested
Estos eventos requieren el complemento CSIRT (programa de recompensas). Los eventos que se entregan se envían cuando cambia el estado del informe y usan la carga de informe que aparece a continuación.
Warning
csirt.report.assessed, csirt.report.assigned y csirt.report.bounty_approved aparecen en los ajustes de suscripción, pero están reservados y actualmente no se entregan. No crees automatizaciones que dependan de ellos.
csirt.report.dismissed significa que el informe fue rechazado. csirt.report.informative significa que era válido pero no había nada que corregir, y que aun así se le pudo pagar un bono discrecional: no juntes ambos casos en una única rama de «cerrado».
Dos eventos se disparan al margen de los cambios de estado y usan el mismo payload:
-
csirt.report.sla_breachedse dispara una vez, cuando un informe abierto supera su plazo de acuse de recibo (72 horas por defecto, configurable por programa). Un informe que se cierra y se reabre puede volver a dispararlo. Los informes evaluados como Informativo no lo disparan. -
csirt.report.escalation_requestedse dispara cuando el investigador usa Pedir novedades en el portal del investigador. Su nota nunca se incluye.
{
"event": "csirt.report.submitted",
"created_at": "2026-03-12T10:00:00Z",
"data": {
"id": "rpt_abc123",
"vulnerability_type": "sql_injection",
"severity_tier": "critical",
"cvss_score": 9.8,
"status": "submitted",
"program_name": "Acme Security Program",
"submitted_at": "2026-03-12T10:00:00Z"
}
}
| Campo | Tipo | Descripción |
|---|---|---|
id |
string | ID con prefijo del informe |
vulnerability_type |
string | Categoría de vulnerabilidad notificada |
severity_tier |
string | null | Nivel de severidad evaluado (presente una vez evaluado) |
cvss_score |
number | null | Puntuación CVSS (presente una vez evaluado) |
status |
string | Estado del informe en el momento del evento |
program_name |
string | Nombre del programa de recompensas |
submitted_at |
string | null | Cuándo se envió el informe |
Nota: El título y la descripción del informe se excluyen de los payloads de webhook (cifrados en reposo).
Eventos de Outreach
Eventos: outreach.prospect.drafted, outreach.message.approved, outreach.message.sent, outreach.message.bounced, outreach.message.failed, outreach.message.deferred, outreach.message.delivery_unknown, outreach.message.confirmation_expired, outreach.message.delivery_resolved
Estos eventos requieren el complemento Outreach.
outreach.prospect.drafted
Se dispara cuando la IA termina de investigar a un prospecto y redactar un email.
{
"event": "outreach.prospect.drafted",
"created_at": "2026-03-12T10:00:00Z",
"data": {
"id": "op_abc123",
"campaign_id": "oc_def456",
"company_name": "Acme Corp",
"display_name": "Jane Smith",
"status": "drafted"
}
}
| Campo | Tipo | Descripción |
|---|---|---|
id |
string | ID con prefijo del prospecto |
campaign_id |
string | ID con prefijo de la campaña |
company_name |
string | Nombre de la empresa del prospecto |
display_name |
string | Nombre visible del prospecto |
status |
string | Estado del prospecto en el momento del evento |
Nota: El email del prospecto se excluye de los payloads de webhook (cifrado en reposo).
outreach.message.approved / sent / bounced / failed / deferred / delivery_unknown / confirmation_expired
Se dispara cuando un mensaje pasa al estado approved, sent, bounced, failed, deferred, delivery_unknown o confirmation_expired. failed indica un fallo conocido de autenticación, remitente, contenido o política y abre una revisión para reintentar después de corregirlo o para cerrarla. deferred indica que se agotaron los reintentos seguros tras un fallo conocido antes del envío. delivery_unknown indica que no se pudo confirmar la aceptación SMTP, por lo que Kit detiene el reenvío automático para evitar duplicados. confirmation_expired indica que el destinatario, la identidad del remitente, el asunto o el cuerpo revisado cambió antes de iniciar SMTP. No empezó ningún intento de entrega y hay que revisar y aprobar de nuevo el mensaje actual.
{
"event": "outreach.message.sent",
"created_at": "2026-03-12T10:15:00Z",
"data": {
"id": "om_ghi789",
"campaign_id": "oc_def456",
"prospect_id": "op_abc123",
"step_number": 1,
"subject": "Quick question about Acme's hiring workflow",
"status": "sent",
"sent_at": "2026-03-12T10:15:00Z",
"approved_at": "2026-03-12T09:30:00Z",
"retry_count": 0,
"last_error_code": null
}
}
| Campo | Tipo | Descripción |
|---|---|---|
id |
string | ID con prefijo del mensaje |
campaign_id |
string | ID con prefijo de la campaña |
prospect_id |
string | ID con prefijo del prospecto |
step_number |
integer | Número del paso en la secuencia (1 = inicial, 2+ = seguimientos) |
subject |
string | Asunto del email |
status |
string | Uno de: approved, sent, bounced, failed, deferred, delivery_unknown, confirmation_expired
|
sent_at |
string | null | Cuándo se envió el email |
approved_at |
string | null | Cuándo se aprobó el borrador |
retry_count |
integer | Número de reintentos de envío realizados |
last_error_code |
string | null | Código SMTP o de estado de entrega analizado, si está disponible; null si no empezó ningún intento |
Nota: El cuerpo del email del mensaje se excluye de los payloads de webhook (cifrado en reposo).
outreach.message.delivery_resolved
Se dispara cuando un miembro con permiso para gestionar la campaña registra la decisión inmutable que cierra una revisión delivery_unknown, deferred o failed. El resultado indica si Kit registró una entrega desconocida como enviada, puso en cola un intento autorizado de forma explícita tras aportar pruebas o corregir el problema, o cerró la revisión sin enviar. delivery_attempt_id identifica el intento exacto cuyas pruebas resolvió la decisión.
{
"event": "outreach.message.delivery_resolved",
"created_at": "2026-03-12T10:20:00Z",
"data": {
"id": 84,
"message_id": "om_ghi789",
"delivery_attempt_id": 312,
"campaign_id": "oc_def456",
"prospect_id": "op_abc123",
"outcome": "confirmed_not_sent",
"origin": "web",
"resolved_by_id": 17,
"resolved_at": "2026-03-12T10:20:00Z",
"sent_at": null
}
}
| Campo | Tipo | Descripción |
|---|---|---|
id |
integer | ID del registro de auditoría de la resolución |
message_id |
string | ID con prefijo del mensaje |
delivery_attempt_id |
integer | Intento de entrega que resuelve la decisión |
campaign_id |
string | ID con prefijo de la campaña |
prospect_id |
string | ID con prefijo del prospecto |
outcome |
string |
confirmed_sent, confirmed_not_sent, retry_authorized o closed_without_delivery
|
origin |
string | Origen de la decisión: web, mcp o assistant
|
resolved_by_id |
integer | null | Usuario que confirmó la decisión; null si ese usuario se eliminó más adelante |
resolved_at |
string | Marca de tiempo ISO 8601 de la decisión |
sent_at |
string | null | Hora de envío confirmada; solo aparece con confirmed_sent
|
La nota opcional del responsable se cifra en reposo y se excluye de forma deliberada porque puede contener datos del destinatario copiados del buzón del remitente.
Eventos de prueba
Eventos: test.ping
El evento test.ping se envía cuando haces clic en Send Test Ping en la configuración del webhook. Úsalo para verificar la conectividad del endpoint y la validación de firmas.
{
"event": "test.ping",
"created_at": "2025-01-15T14:30:00Z",
"data": {}
}