Conector de Zoom

Conecta Zoom con Brevo a través de Tajo para sincronizar automáticamente a los participantes de reuniones y asistentes a webinars como contactos, disparar secuencias de seguimiento post-reunión y rastrear métricas de engagement para tus automatizaciones de marketing.

Resumen

PropiedadValor
PlataformaZoom
CategoríaVideoconferencia (Personalizada)
Complejidad de configuraciónMedia
Integración oficialNo
Datos sincronizadosParticipantes, Eventos, Webinars, Contactos
Método de autenticaciónOAuth 2.0 / Server-to-Server OAuth

Funcionalidades

  • Sincronización de participantes - Crea automáticamente contactos de Brevo a partir de los participantes en reuniones
  • Captura de asistentes a webinars - Sincroniza los registrantes y asistentes a webinars
  • Triggers por evento de reunión - Dispara automatizaciones al iniciar, finalizar o grabar una reunión
  • Seguimiento de engagement - Rastrea la duración de asistencia y métricas de participación
  • Seguimiento post-webinar - Dispara secuencias de email dirigidas según la asistencia al webinar
  • Notificaciones de grabaciones - Envía enlaces de grabaciones a través de campañas de email de Brevo

Requisitos previos

Antes de empezar, asegúrate de tener:

  1. Una cuenta de Zoom (plan Pro o superior)
  2. Una app Server-to-Server OAuth de Zoom o una app OAuth en el Zoom App Marketplace
  3. Una cuenta de Brevo con acceso a la API
  4. Una cuenta de Tajo con permisos de conector

Autenticación

Server-to-Server OAuth (recomendado)

Terminal window
# Create a Server-to-Server OAuth app at marketplace.zoom.us
export ZOOM_ACCOUNT_ID=your_account_id
export ZOOM_CLIENT_ID=your_client_id
export ZOOM_CLIENT_SECRET=your_client_secret
// Get access token via Server-to-Server OAuth
const tokenResponse = await fetch('https://zoom.us/oauth/token', {
method: 'POST',
headers: {
'Authorization': `Basic ${Buffer.from(
`${process.env.ZOOM_CLIENT_ID}:${process.env.ZOOM_CLIENT_SECRET}`
).toString('base64')}`,
'Content-Type': 'application/x-www-form-urlencoded'
},
body: new URLSearchParams({
grant_type: 'account_credentials',
account_id: process.env.ZOOM_ACCOUNT_ID
})
});
const { access_token } = await tokenResponse.json();

OAuth 2.0 (a nivel de usuario)

// Authorization URL for user-level OAuth
const authUrl = 'https://zoom.us/oauth/authorize?' +
new URLSearchParams({
client_id: process.env.ZOOM_CLIENT_ID,
redirect_uri: 'https://your-app.com/callback',
response_type: 'code'
});
// Exchange code for tokens
const tokenResponse = await fetch('https://zoom.us/oauth/token', {
method: 'POST',
headers: {
'Authorization': `Basic ${Buffer.from(
`${process.env.ZOOM_CLIENT_ID}:${process.env.ZOOM_CLIENT_SECRET}`
).toString('base64')}`,
'Content-Type': 'application/x-www-form-urlencoded'
},
body: new URLSearchParams({
grant_type: 'authorization_code',
code: authorizationCode,
redirect_uri: 'https://your-app.com/callback'
})
});

Configuración

Configuración básica

connectors:
zoom:
enabled: true
account_id: "${ZOOM_ACCOUNT_ID}"
client_id: "${ZOOM_CLIENT_ID}"
client_secret: "${ZOOM_CLIENT_SECRET}"
sync:
participants: true
webinars: true
recordings: true
webhook:
secret_token: "${ZOOM_WEBHOOK_SECRET}"
verification_token: "${ZOOM_VERIFICATION_TOKEN}"
lists:
meeting_participants: 15
webinar_attendees: 16
webinar_registrants: 17

Asignación de campos

field_mapping:
email: email
name: FIRSTNAME
join_time: MEETING_JOIN_DATE
duration: MEETING_DURATION
webinar_title: WEBINAR_NAME
attendance_status: ATTENDANCE_STATUS
registration_source: UTM_SOURCE

Endpoints de la API

EndpointMétodoDescripción
https://api.zoom.us/v2/usersGETListar usuarios
https://api.zoom.us/v2/users/{userId}/meetingsGETListar reuniones
https://api.zoom.us/v2/meetings/{meetingId}GETObtener detalles de la reunión
https://api.zoom.us/v2/past_meetings/{meetingId}/participantsGETListar participantes de una reunión pasada
https://api.zoom.us/v2/users/{userId}/webinarsGETListar webinars
https://api.zoom.us/v2/webinars/{webinarId}/registrantsGETListar registrantes del webinar
https://api.zoom.us/v2/webinars/{webinarId}/participantsGETListar participantes del webinar
https://api.zoom.us/v2/meetings/{meetingId}/recordingsGETObtener grabaciones de la reunión
https://api.zoom.us/v2/webhooksPOSTSuscribirse a webhooks

Ejemplos de código

Inicializar el conector

import { TajoClient } from '@tajo/sdk';
const tajo = new TajoClient({
apiKey: process.env.TAJO_API_KEY,
brevoApiKey: process.env.BREVO_API_KEY
});
await tajo.connectors.connect('zoom', {
accountId: process.env.ZOOM_ACCOUNT_ID,
clientId: process.env.ZOOM_CLIENT_ID,
clientSecret: process.env.ZOOM_CLIENT_SECRET
});

Sincronizar participantes de reuniones

// Retrieve past meeting participants
const response = await fetch(
`https://api.zoom.us/v2/past_meetings/${meetingId}/participants`,
{
headers: {
'Authorization': `Bearer ${accessToken}`,
'Content-Type': 'application/json'
}
}
);
const { participants } = await response.json();
for (const participant of participants) {
if (participant.user_email) {
await tajo.contacts.sync({
email: participant.user_email,
attributes: {
FIRSTNAME: participant.name,
MEETING_DURATION: participant.duration,
MEETING_JOIN_DATE: participant.join_time,
ATTENDANCE_STATUS: 'attended'
},
listIds: [15]
});
}
}

Sincronizar asistentes a webinars

// Get webinar attendees and sync to Brevo
const attendeesResponse = await fetch(
`https://api.zoom.us/v2/past_webinars/${webinarId}/participants`,
{
headers: { 'Authorization': `Bearer ${accessToken}` }
}
);
const { participants: attendees } = await attendeesResponse.json();
for (const attendee of attendees) {
await tajo.contacts.sync({
email: attendee.user_email,
attributes: {
FIRSTNAME: attendee.name,
WEBINAR_NAME: webinarTitle,
ATTENDANCE_STATUS: 'attended',
MEETING_DURATION: attendee.duration
},
listIds: [16]
});
}

Gestionar webhooks de Zoom

app.post('/webhooks/zoom', async (req, res) => {
// Handle Zoom URL validation challenge
if (req.body.event === 'endpoint.url_validation') {
const hashForValidation = crypto
.createHmac('sha256', process.env.ZOOM_WEBHOOK_SECRET)
.update(req.body.payload.plainToken)
.digest('hex');
return res.json({
plainToken: req.body.payload.plainToken,
encryptedToken: hashForValidation
});
}
// Verify webhook signature
const message = `v0:${req.headers['x-zm-request-timestamp']}:${JSON.stringify(req.body)}`;
const hash = crypto
.createHmac('sha256', process.env.ZOOM_WEBHOOK_SECRET)
.update(message)
.digest('hex');
const signature = `v0=${hash}`;
if (req.headers['x-zm-signature'] !== signature) {
return res.status(401).send('Unauthorized');
}
const { event, payload } = req.body;
await tajo.connectors.handleWebhook('zoom', {
topic: event,
payload: payload
});
res.status(200).send('OK');
});

Límites de velocidad

CategoríaLímiteNotas
Llamadas API ligeras30 req/sGET de usuario, info de reunión
Llamadas API medias20 req/sListar participantes, webinars
Llamadas API pesadas10 req/sInformes, grabaciones
Límite diario5.000+Depende del nivel del plan

Cabeceras de límite de velocidad

Zoom devuelve las cabeceras X-RateLimit-Limit, X-RateLimit-Remaining y Retry-After. Implementa la lógica de backoff basándote en estas cabeceras para evitar errores 429.

Resolución de problemas

ProblemaCausaSolución
401 UnauthorizedToken expiradoRefresca el token Server-to-Server OAuth
Participantes que faltanLa reunión no ha terminadoEspera a que finalice la reunión para obtener los datos completos
Fallo en la validación del webhookSecret incorrectoVerifica el webhook secret en el Zoom Marketplace
Sin datos de emailParticipantes invitadosActiva el registro para capturar emails
Rate limit 429Demasiadas peticionesAplica exponential backoff

Modo depuración

connectors:
zoom:
debug: true
log_level: verbose
log_webhooks: true

Buenas prácticas

  1. Usa Server-to-Server OAuth - Autenticación más sencilla sin interacción del usuario
  2. Activa el registro en los webinars - Necesario para capturar direcciones de email de los asistentes
  3. Procesa tras el final de la reunión - Los datos de participantes solo están completos al finalizar la reunión
  4. Segmenta por tipo de evento - Asigna distintas listas de Brevo para reuniones y webinars
  5. Rastrea métricas de engagement - Usa la duración y el momento de conexión para puntuar leads
  6. Envía seguimientos con la grabación - Automatiza el envío del enlace de grabación vía Brevo

Seguridad

  • OAuth 2.0 - Autenticación Server-to-Server o OAuth a nivel de usuario
  • Verificación de webhooks - Validación de firma HMAC-SHA256
  • Validación de URL - Verificación challenge-response para endpoints de webhook
  • Permisos limitados - Solicita los scopes de OAuth mínimos necesarios
  • Rotación de tokens - Los tokens Server-to-Server caducan automáticamente (1 hora)
  • Transporte cifrado - TLS 1.2+ para todas las comunicaciones con la API

Recursos relacionados

Subscribe to updates

developer-docs

Drop your email or phone number — we'll send you what matters next.

auto-detect
Asistente AI

¡Hola! Pregúntame lo que quieras sobre la documentación.