Zoom Plugin
Skill 156 of 200
Reference skill for Zoom WebSockets.
2 minutes · 459 words · 19 sections
Install
npx skills add anthropics/knowledge-work-plugins --skill setup-zoom-websocketsnpx skills add anthropics/knowledge-work-plugins/plugin marketplace add anthropics/knowledge-work-pluginsThe first command installs just this skill, by the name in its SKILL.md; the second installs the whole repository.
Background reference for persistent Zoom event streams. Prefer workflow routing first, then use this file when WebSockets are plausibly better than webhooks.
| Aspect | WebSockets | Webhooks |
|---|---|---|
| Connection | Persistent, bidirectional | One-time HTTP POST |
| Latency | Lower (no HTTP overhead) | Higher (new connection per event) |
| Security | Direct connection, no exposed endpoint | Requires endpoint validation, IP whitelisting |
| Model | Pull (you connect to Zoom) | Push (Zoom connects to you) |
| State | Stateful (maintains connection) | Stateless (each event independent) |
| Setup | More complex (access token, connection) | Simpler (just endpoint URL) |
Choose WebSockets when:
Choose Webhooks when:
Need help with S2S OAuth? See the zoom-oauth skill for complete authentication flows.
Start troubleshooting fast: Use the 5-Minute Runbook (opens in a new tab) before deep debugging.
meeting.created, meeting.started)const WebSocket = require('ws');
const axios = require('axios');
// Step 1: Get access token
async function getAccessToken() {
const credentials = Buffer.from(`${CLIENT_ID}:${CLIENT_SECRET}`).toString('base64');
const response = await axios.post(
'https://zoom.us/oauth/token',
new URLSearchParams({
grant_type: 'account_credentials',
account_id: ACCOUNT_ID
}),
{
headers: {
'Authorization': `Basic ${credentials}`,
'Content-Type': 'application/x-www-form-urlencoded'
}
}
);
return response.data.access_token;
}
// Step 2: Connect to WebSocket
async function connectWebSocket() {
const accessToken = await getAccessToken();
// WebSocket URL from your subscription settings
const wsUrl = `wss://ws.zoom.us/ws?subscriptionId=${SUBSCRIPTION_ID}&access_token=${accessToken}`;
const ws = new WebSocket(wsUrl);
ws.on('open', () => {
console.log('WebSocket connection established');
});
ws.on('message', (data) => {
const event = JSON.parse(data);
console.log('Event received:', event.event);
// Handle different event types
switch (event.event) {
case 'meeting.started':
console.log(`Meeting started: ${event.payload.object.topic}`);
break;
case 'meeting.ended':
console.log(`Meeting ended: ${event.payload.object.uuid}`);
break;
case 'meeting.participant_joined':
console.log(`Participant joined: ${event.payload.object.participant.user_name}`);
break;
}
});
ws.on('close', (code, reason) => {
console.log(`Connection closed: ${code} - ${reason}`);
// Implement reconnection logic
});
ws.on('error', (error) => {
console.error('WebSocket error:', error);
});
return ws;
}
connectWebSocket();Events received via WebSocket have the same format as webhook events:
{
"event": "meeting.started",
"event_ts": 1706123456789,
"payload": {
"account_id": "abcD3ojkdbjfg",
"object": {
"id": 1234567890,
"uuid": "abcdefgh-1234-5678-abcd-1234567890ab",
"host_id": "xyz789",
"topic": "Team Standup",
"type": 2,
"start_time": "2024-01-25T10:00:00Z",
"timezone": "America/Los_Angeles"
}
}
}| Event | Description |
|---|---|
meeting.created | Meeting scheduled |
meeting.updated | Meeting settings changed |
meeting.deleted | Meeting deleted |
meeting.started | Meeting begins |
meeting.ended | Meeting ends |
meeting.participant_joined | Participant joins meeting |
meeting.participant_left | Participant leaves meeting |
recording.completed | Cloud recording ready |
user.created | New user added |
user.updated | User details changed |
WebSocket connections require periodic heartbeats. Zoom will close idle connections.
// Send ping every 30 seconds
setInterval(() => {
if (ws.readyState === WebSocket.OPEN) {
ws.ping();
}
}, 30000);Implement automatic reconnection for reliability:
function connectWithReconnect() {
const ws = connectWebSocket();
ws.on('close', () => {
console.log('Connection lost. Reconnecting in 5 seconds...');
setTimeout(connectWithReconnect, 5000);
});
return ws;
}Important: Only ONE WebSocket connection can be open per subscription at a time. Opening a new connection will close the existing one.
| Type | Repository | Description |
|---|---|---|
| Node.js | just-zoomit/zoom-websockets (opens in a new tab) | WebSocket sample with S2S OAuth |
Don’t confuse WebSockets with RTMS (Realtime Media Streams):
| Feature | WebSockets | RTMS |
|---|---|---|
| Purpose | Event notifications | Media streams |
| Data | Meeting events, user events | Audio, video, transcripts |
| Use case | React to Zoom events | AI/ML, live transcription |
| Skill | This skill | rtms |
For real-time audio/video/transcript data, use the rtms skill instead.
.env keys and where to find each value.Reference skill for Zoom WebSockets. Use after routing to a low-latency event workflow when persistent connections, faster event delivery, or security constraints make WebSockets preferable to webhooks.
The verbatim description from this skill’s front matter — the string an agent matches on to decide whether to load it.
main, last pushed 23 September 2026.SKILL.md, not by matching a directory convention. 27 distinct layouts observed: bio-research/skills/*/SKILL.md, cowork-plugin-management/skills/*/SKILL.md, customer-support/skills/*/SKILL.md, data/skills/*/SKILL.md, design/skills/*/SKILL.md, engineering/skills/*/SKILL.md, enterprise-search/skills/*/SKILL.md, finance/skills/*/SKILL.md, human-resources/skills/*/SKILL.md, legal/skills/*/SKILL.md, marketing/skills/*/SKILL.md, operations/skills/*/SKILL.md, partner-built/apollo/skills/*/SKILL.md, partner-built/brand-voice/skills/*/SKILL.md, partner-built/common-room/skills/*/SKILL.md, partner-built/slack/skills/*/SKILL.md, partner-built/zoom-plugin/skills/*/SKILL.md, partner-built/zoom-plugin/skills/contact-center/*/SKILL.md, partner-built/zoom-plugin/skills/meeting-sdk/*/SKILL.md, partner-built/zoom-plugin/skills/meeting-sdk/web/*/SKILL.md, partner-built/zoom-plugin/skills/video-sdk/*/SKILL.md, partner-built/zoom-plugin/skills/virtual-agent/*/SKILL.md, partner-built/zoom-plugin/skills/zoom-mcp/*/SKILL.md, pdf-viewer/skills/*/SKILL.md, product-management/skills/*/SKILL.md, productivity/skills/*/SKILL.md, sales/skills/*/SKILL.md.h1 and no skipped levels:.claude-plugin/marketplace.json by Anthropic, declaring 120 plugins. It is read for editorial metadata only — never as the skill index, which is always the repository tree./anthropics/knowledge-work-plugins.md, and each skill at its own .md URL.5 files · 26 KB
Everything this skill ships beside its prose. All of it is set here, as subchapters of skill 156.
Documentation the agent loads on demand, rather than up front.
Everything else published alongside the skill.