Zoom 连接器

通过 Tajo 将 Zoom 连接到 Brevo,自动将会议参与者和网络研讨会出席者同步为联系人,触发会议后跟进序列,并追踪营销自动化的互动指标。

概览

属性
平台Zoom
类别视频会议(自定义)
设置复杂度中等
官方集成
同步数据参与者、事件、网络研讨会、联系人
认证方式OAuth 2.0 / 服务器对服务器 OAuth

功能

  • 参与者同步 - 从会议参与者自动创建 Brevo 联系人
  • 网络研讨会出席者捕获 - 同步网络研讨会注册者和出席者
  • 会议事件触发 - 在会议开始、结束和录制事件时触发自动化
  • 互动追踪 - 追踪出席时长和参与度指标
  • 网络研讨会跟进 - 根据出席情况触发精准邮件序列
  • 录制通知 - 通过 Brevo 邮件活动发送录制链接

前提条件

开始之前,请确保您已具备:

  1. Zoom 账户(专业版或以上)
  2. 通过 Zoom 应用市场 创建的 Zoom 服务器对服务器 OAuth 应用或 OAuth 应用
  3. 具有 API 访问权限的 Brevo 账户
  4. 具有连接器权限的 Tajo 账户

认证

服务器对服务器 OAuth(推荐)

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(用户级)

// 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'
})
});

配置

基础设置

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

字段映射

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

API 端点

端点方法描述
https://api.zoom.us/v2/usersGET列出用户
https://api.zoom.us/v2/users/{userId}/meetingsGET列出会议
https://api.zoom.us/v2/meetings/{meetingId}GET获取会议详情
https://api.zoom.us/v2/past_meetings/{meetingId}/participantsGET列出历史会议参与者
https://api.zoom.us/v2/users/{userId}/webinarsGET列出网络研讨会
https://api.zoom.us/v2/webinars/{webinarId}/registrantsGET列出网络研讨会注册者
https://api.zoom.us/v2/webinars/{webinarId}/participantsGET列出网络研讨会参与者
https://api.zoom.us/v2/meetings/{meetingId}/recordingsGET获取会议录制
https://api.zoom.us/v2/webhooksPOST订阅 Webhook

代码示例

初始化连接器

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
});

同步会议参与者

// 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]
});
}
}

同步网络研讨会出席者

// 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]
});
}

处理 Zoom Webhook

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');
});

速率限制

类别限制说明
轻量 API 调用30 请求/秒获取用户、会议信息
中量 API 调用20 请求/秒列出参与者、网络研讨会
重量 API 调用10 请求/秒报告、录制
每日限制5,000+取决于套餐级别

速率限制头部

Zoom 返回 X-RateLimit-LimitX-RateLimit-RemainingRetry-After 头部。根据这些头部实施退避逻辑以避免 429 错误。

故障排除

问题原因解决方案
401 Unauthorized令牌已过期刷新服务器对服务器 OAuth 令牌
参与者缺失会议尚未结束等待会议结束后获取完整数据
Webhook 验证失败密钥错误在 Zoom 应用市场中验证 Webhook 密钥
无邮箱数据访客参与者启用注册以捕获邮箱
速率限制 429请求过多实施指数退避

调试模式

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

最佳实践

  1. 使用服务器对服务器 OAuth - 无需用户交互的更简单认证
  2. 启用网络研讨会注册 - 捕获出席者邮箱地址所必需
  3. 会议结束后处理 - 参与者数据只在会议结束后才完整
  4. 按事件类型细分 - 为会议和网络研讨会分配不同的 Brevo 列表
  5. 追踪互动指标 - 使用时长和加入时间进行线索评分
  6. 发送录制跟进 - 通过 Brevo 自动化投递录制链接

安全

  • OAuth 2.0 - 服务器对服务器或用户级 OAuth 认证
  • Webhook 验证 - HMAC-SHA256 签名验证
  • URL 验证 - Webhook 端点的挑战响应验证
  • 范围权限 - 请求最低所需的 OAuth 范围
  • 令牌轮换 - 服务器对服务器令牌自动过期(1 小时)
  • 加密传输 - 所有 API 通信使用 TLS 1.2+

相关资源

Subscribe to updates

developer-docs

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

auto-detect
AI 助手

你好!关于文档有任何问题都可以问我。