Zoom SDK Integration for Video Conferencing on Website
Zoom offers two embedding paths: Meeting SDK (full Zoom client in iframe/widget) and Video SDK (low-level API for custom UI). Meeting SDK deploys faster; Video SDK provides full UI control.
Meeting SDK—Embedding Ready Interface
npm install @zoom/meetingsdk
import { ZoomMtg } from '@zoom/meetingsdk';
// Initialize once on load
ZoomMtg.setZoomJSLib('https://source.zoom.us/3.9.5/lib', '/av');
ZoomMtg.preLoadWasm();
ZoomMtg.prepareWebSDK();
async function joinZoomMeeting(params: {
meetingNumber: string;
userName: string;
signature: string;
password: string;
}) {
ZoomMtg.init({
leaveUrl: `${window.location.origin}/meeting-ended`,
patchJsMedia: true,
leaveOnPageUnload: true,
success: () => {
ZoomMtg.join({
meetingNumber: params.meetingNumber,
userName: params.userName,
signature: params.signature,
sdkKey: process.env.NEXT_PUBLIC_ZOOM_SDK_KEY!,
password: params.password,
success: () => console.log('Joined meeting'),
error: (err) => console.error('Join error:', err),
});
},
});
}
Signature Generation on Server
import crypto from 'crypto';
export function generateZoomSignature(
sdkKey: string,
sdkSecret: string,
meetingNumber: string,
role: 0 | 1 // 0 = attendee, 1 = host
): string {
const timestamp = new Date().getTime() - 30000;
const msg = Buffer.from(`${sdkKey}${meetingNumber}${timestamp}${role}`).toString('base64');
const hash = crypto.createHmac('sha256', sdkSecret).update(msg).digest('base64');
const signature = Buffer.from(
`${sdkKey}.${meetingNumber}.${timestamp}.${role}.${hash}`
).toString('base64');
return signature;
}
// API endpoint
app.get('/api/zoom/signature', authenticate, (req, res) => {
const { meetingNumber, role = 0 } = req.query;
const signature = generateZoomSignature(
process.env.ZOOM_SDK_KEY!,
process.env.ZOOM_SDK_SECRET!,
meetingNumber as string,
Number(role) as 0 | 1
);
res.json({ signature });
});
Creating Meetings via Zoom API
async function createZoomMeeting(params: {
topic: string;
startTime: Date;
durationMinutes: number;
hostEmail: string;
}): Promise<{ id: string; joinUrl: string; password: string }> {
// Get access token via OAuth Server-to-Server
const tokenResponse = await fetch(
`https://zoom.us/oauth/token?grant_type=account_credentials&account_id=${process.env.ZOOM_ACCOUNT_ID}`,
{
method: 'POST',
headers: {
'Authorization': `Basic ${Buffer.from(
`${process.env.ZOOM_CLIENT_ID}:${process.env.ZOOM_CLIENT_SECRET}`
).toString('base64')}`,
},
}
);
const { access_token } = await tokenResponse.json();
// Create meeting
const meetingResponse = await fetch(
`https://api.zoom.us/v2/users/${params.hostEmail}/meetings`,
{
method: 'POST',
headers: {
'Authorization': `Bearer ${access_token}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
topic: params.topic,
type: 2, // scheduled
start_time: params.startTime.toISOString(),
duration: params.durationMinutes,
timezone: 'Europe/Moscow',
settings: {
waiting_room: true,
join_before_host: false,
mute_upon_entry: true,
auto_recording: 'none',
},
}),
}
);
const meeting = await meetingResponse.json();
return {
id: String(meeting.id),
joinUrl: meeting.join_url,
password: meeting.password,
};
}
Zoom Webhooks
app.post('/api/webhooks/zoom', async (req, res) => {
// Webhook endpoint verification
if (req.body.event === 'endpoint.url_validation') {
const hashForValidate = crypto
.createHmac('sha256', process.env.ZOOM_WEBHOOK_SECRET_TOKEN!)
.update(req.body.payload.plainToken)
.digest('hex');
return res.json({
plainToken: req.body.payload.plainToken,
encryptedToken: hashForValidate,
});
}
const { event, payload } = req.body;
switch (event) {
case 'meeting.started':
await db.meetings.markStarted(payload.object.id);
break;
case 'meeting.ended':
await db.meetings.markEnded(payload.object.id, payload.object.duration);
break;
case 'meeting.participant_joined':
await db.meetings.addParticipant(
payload.object.id,
payload.object.participant.user_name
);
break;
}
res.status(200).end();
});
Timeline
Zoom Meeting SDK integration + signature + creating meetings via API—3–4 days. With webhooks and Video SDK for custom UI—1–1.5 weeks.







