Generated banner for Build Zoom Meeting SDK App
Generated logo for Build Zoom Meeting SDK App

Build Zoom Meeting SDK App

AnthropicOfficialCreated by ZoomDistributed by Anthropic

  • Skill
  • Tool integration
  • Software development
  • MIT
  • No issues found

From the author

Reference skill for Zoom Meeting SDK. Use after routing to a meeting-embed workflow when implementing real Zoom meeting joins, platform-specific SDK behavior, auth and join flows, waiting room issues, or meeting bot patterns.
— the description by Zoom

AutoGineer summary

Written by AutoGineer from the skill’s own files, not by the author

This skill provides a comprehensive reference for developers embedding the Zoom Meeting SDK into their applications. It covers platform-specific implementation details, authentication flows, UI customization options, and critical security practices like server-side signature generation. It serves as a central hub for navigating the SDK's various platform-specific guides, troubleshooting runbooks, and official sample repositories.

What it does

  • Provides implementation patterns for embedding Zoom meetings in web, mobile, and desktop apps.
  • Outlines the mandatory server-side process for generating secure SDK signatures.
  • Distinguishes between Client View and Component View for web integrations.
  • Offers guidance on handling platform-specific SDK behaviors and common UI conflicts.
  • Links to specialized documentation for Android, iOS, macOS, Windows, and Linux environments.
  • Includes troubleshooting resources for common join, auth, and waiting room issues.

When to use it

  • When you need to embed a live Zoom meeting experience directly into your application UI.
  • When implementing programmatic meeting joins or bot-based meeting interactions.
  • When troubleshooting SDK authentication, signature errors, or meeting join failures.
  • When you need to determine the correct SDK view type (Client vs. Component) for your web project.
  • When setting up development environments for specific platforms like Unreal, Electron, or mobile.

Advantages

  • Centralizes complex documentation for multiple platforms into a single reference point.
  • Enforces security best practices by mandating server-side signature generation.
  • Provides clear architectural guidance to avoid common pitfalls like CSS conflicts.
  • Facilitates rapid troubleshooting with dedicated runbooks and triage guides.
  • Maintains clear separation between official Zoom UI and custom integration requirements.

Usage examples

“How do I securely generate a signature for the Zoom Meeting SDK in Node.js?”
The agent provides a server-side code example using jsrsasign to sign a JWT with your SDK Secret, ensuring credentials remain hidden from the client.
“I am getting a CSS conflict where my app UI breaks when the Zoom meeting loads. How do I fix this?”
The agent suggests scoping your CSS and provides specific CSS overrides to ensure the Zoom UI renders correctly without affecting your application shell.
“What is the difference between Client View and Component View in the Web SDK?”
The agent explains that Client View provides the full-page Zoom experience, while Component View allows for embedding the meeting within a specific div for a more integrated look.

Install

  1. Download the skill as a ZIP:

    https://mp-staging.autogineer.com/agent-skills/anthropics/build-zoom-meeting-sdk-app/download
  2. Unzip it into the cross-client skills folder of your project:

    mkdir -p .agents/skills && unzip build-zoom-meeting-sdk-app.zip -d .agents/skills

Documentation by Zoom

/build-zoom-meeting-sdk-app

Background reference for embedded Zoom meetings across web, mobile, desktop, and Linux bot environments. Prefer build-zoom-meeting-app or build-zoom-bot first, then route here for platform detail.

Zoom Meeting SDK

Embed the full Zoom meeting experience into web, mobile, desktop, and headless integrations.

Hard Routing Guardrail (Read First)

  • If the user asks to embed/join meetings inside their app UI, route to Meeting SDK implementation.

  • Do not switch to REST-only meeting link flow unless the user explicitly asks for meeting resource management or browser join_url links.

  • Meeting SDK join path requires SDK signature + SDK join call; REST join_url is not a Meeting SDK join payload.

Prerequisites

  • Zoom app with Meeting SDK credentials

  • SDK Key and Secret from Marketplace

  • Platform-specific development environment (Web, Android, iOS, macOS, Unreal, Electron, Linux, or Windows)

Need help with OAuth or signatures? See the zoom-oauth skill for authentication flows.

Need pre-join diagnostics on web? Use probe-sdk before Meeting SDK init/join to gate low-readiness devices/networks.

Start troubleshooting fast: Use the 5-Minute Runbook before deep debugging.

Quick Start (Web - Client View via CDN)

<script src="https://source.zoom.us/3.1.6/lib/vendor/react.min.js"></script>
<script src="https://source.zoom.us/3.1.6/lib/vendor/react-dom.min.js"></script>
<script src="https://source.zoom.us/3.1.6/lib/vendor/redux.min.js"></script>
<script src="https://source.zoom.us/3.1.6/lib/vendor/redux-thunk.min.js"></script>
<script src="https://source.zoom.us/3.1.6/lib/vendor/lodash.min.js"></script>
<script src="https://source.zoom.us/3.1.6/zoom-meeting-3.1.6.min.js"></script>

<script>
// CDN provides ZoomMtg (Client View - full page)
// For ZoomMtgEmbedded (Component View), use npm instead

ZoomMtg.preLoadWasm();
ZoomMtg.prepareWebSDK();

ZoomMtg.init({
  leaveUrl: window.location.href,
  patchJsMedia: true,
  disableCORP: !window.crossOriginIsolated,
  success: function() {
    ZoomMtg.join({
      sdkKey: 'YOUR_SDK_KEY',
      signature: 'YOUR_SIGNATURE',  // Generate server-side!
      meetingNumber: 'MEETING_NUMBER',
      userName: 'User Name',
      passWord: '',  // Note: camelCase with capital W
      success: function(res) { console.log('Joined'); },
      error: function(err) { console.error(err); }
    });
  },
  error: function(err) { console.error(err); }
});
</script>

Critical Notes (Web)

1. CDN vs npm - Different APIs!
DistributionGlobal ObjectView TypeAPI Style
CDN (zoom-meeting-{ver}.min.js)ZoomMtgClient View (full-page)Callbacks
npm (@zoom/meetingsdk)ZoomMtgEmbeddedComponent View (embeddable)Promises
2. Backend Required for Production

Never expose SDK Secret in client code. Generate signatures server-side:

// server.js (Node.js example)
const KJUR = require('jsrsasign');

app.post('/api/signature', (req, res) => {
  const { meetingNumber, role } = req.body;
  const iat = Math.floor(Date.now() / 1000) - 30;
  const exp = iat + 60 * 60 * 2;
  
  const header = { alg: 'HS256', typ: 'JWT' };
  const payload = {
    sdkKey: process.env.ZOOM_SDK_KEY,
    mn: String(meetingNumber).replace(/\D/g, ''),
    role: parseInt(role, 10),
    iat, exp, tokenExp: exp
  };
  
  const signature = KJUR.jws.JWS.sign('HS256',
    JSON.stringify(header),
    JSON.stringify(payload),
    process.env.ZOOM_SDK_SECRET
  );
  
  res.json({ signature, sdkKey: process.env.ZOOM_SDK_KEY });
});
3. CSS Conflicts - Avoid Global Resets

Global * { margin: 0; } breaks Zoom's UI. Scope your styles:

/* BAD */
* { margin: 0; padding: 0; }

/* GOOD */
.your-app, .your-app * { box-sizing: border-box; }
4. Client View Toolbar Cropping Fix

If toolbar falls off screen, scale down the Zoom UI:

#zmmtg-root {
  position: fixed !important;
  top: 0 !important;
  left: 0 !important;
  right: 0 !important;
  bottom: 0 !important;
  width: 100vw !important;
  height: 100vh !important;
  /* Critical for SPAs (React/Next/etc): ensure Zoom UI isn't behind your app shell/overlays. */
  z-index: 9999 !important;
  transform: scale(0.95) !important;
  transform-origin: top center !important;
}
5. Hide Your App When Meeting Starts

Client View takes over full page. Hide your UI:

// In ZoomMtg.init success callback:
document.documentElement.classList.add('meeting-active');
document.body.classList.add('meeting-active');
body.meeting-active .your-app { display: none !important; }
body.meeting-active { background: #000 !important; }

UI Options (Web)

Meeting SDK provides Zoom's UI with customization options:

ViewDescription
Component ViewExtractable, customizable UI - embed meeting in a div
Client ViewFull-page Zoom UI experience

Note: Unlike Video SDK where you build the UI from scratch, Meeting SDK uses Zoom's UI as the base with customization on top.

Key Concepts

ConceptDescription
SDK Key/SecretCredentials from Marketplace
SignatureJWT signed with SDK Secret
Component ViewExtractable, customizable UI (Web)
Client ViewFull-page Zoom UI (Web)

Detailed References

Platform Guides
Features

Sample Repositories

Official (by Zoom)

Full list: See general/references/community-repos.md

Resources

Environment Variables

Files

references/webinars.md

Meeting SDK - Webinars

Embed webinar experiences using Meeting SDK.

Overview

Meeting SDK can join webinars, not just meetings. This guide covers webinar-specific features and considerations.

Webinar vs Meeting

FeatureMeetingWebinar
Max participants100-1000500-50,000
Participant rolesHost, co-host, participantHost, panelist, attendee
Attendee videoYesNo (view-only)
Attendee audioYesRaise hand to unmute
Q&ANoYes
RegistrationOptionalCommon
Practice sessionNoYes

Joining Webinars

Web SDK
const client = ZoomMtgEmbedded.createClient();

await client.init({
  zoomAppRoot: document.getElementById('meetingSDKElement'),
  language: 'en-US',
});

// Join webinar (same as meeting)
await client.join({
  sdkKey: SDK_KEY,
  signature: signature,
  meetingNumber: webinarId,  // Webinar ID
  userName: 'Attendee Name',
  userEmail: '[email protected]',  // Required for registration
  passWord: password,
  tk: registrantToken,  // If registration required
});
Registration Token

If the webinar requires registration:

// 1. Register via API first
const response = await axios.post(
  `https://api.zoom.us/v2/webinars/${webinarId}/registrants`,
  {
    email: '[email protected]',
    first_name: 'John',
    last_name: 'Doe'
  },
  { headers: { 'Authorization': `Bearer ${accessToken}` }}
);

// 2. Get registrant token
const registrantToken = response.data.registrant_id;

// 3. Use token when joining
await client.join({
  // ... other params
  tk: registrantToken,
});
Native SDKs (iOS/Android/Windows)
// iOS - Join webinar
let joinParam = ZoomSDKJoinWebinarParam()
joinParam.webinarNumber = webinarNumber
joinParam.userName = "Attendee"
joinParam.userEmail = "[email protected]"
joinParam.webinarPassword = password
joinParam.webinarToken = registrantToken  // If registered

meetingService.joinWebinar(with: joinParam)
// Android - Join webinar
val joinParams = JoinMeetingParams().apply {
    meetingNo = webinarId
    displayName = "Attendee"
    password = webinarPassword
}

// Webinar uses same joinMeeting API
meetingService.joinMeetingWithParams(context, joinParams, JoinMeetingOptions())

Attendee vs Panelist

Role Detection
// Web SDK
client.on('user-updated', (payload) => {
  const { userId } = payload;
  const user = client.getUser(userId);
  
  // Check role
  if (user.isHost) {
    console.log('User is host');
  } else if (user.userRole === 'panelist') {
    console.log('User is panelist');
  } else {
    console.log('User is attendee');
  }
});
Attendee Limitations

Attendees in webinars have restricted capabilities:

ActionAttendee Can Do?
View videoYes
Send videoNo
Listen to audioYes
Unmute selfNo (must be promoted)
Send chatTo panelists/everyone (if enabled)
Ask Q&AYes
Raise handYes

Q&A Feature

Web SDK Q&A
// Check if Q&A is enabled
const qaClient = client.getQAClient();
const isQAEnabled = qaClient.isQAEnabled();

// Ask a question
await qaClient.askQuestion('What is the pricing?', false);  // false = public

// Answer a question (panelist/host only)
await qaClient.answerQuestion(questionId, 'The pricing is...');

// Get all questions
const questions = qaClient.getAllQuestions();
questions.forEach(q => {
  console.log(`Q: ${q.text}`);
  console.log(`A: ${q.answerText || 'Unanswered'}`);
});

// Q&A events
client.on('question-created', (payload) => {
  console.log('New question:', payload.question.text);
});

client.on('answer-created', (payload) => {
  console.log('Answer:', payload.answer.text);
});
Native SDK Q&A
// iOS
let qaController = meetingService.getWebinarQAController()

// Ask question
qaController?.askQuestion("What is the pricing?", isAnonymous: false)

// Get questions (host/panelist)
let questions = qaController?.getAllQuestionList()

Raise Hand

Web SDK
// Raise hand
client.raiseHand();

// Lower hand
client.lowerHand();

// Check status
const myself = client.getCurrentUser();
console.log('Hand raised:', myself.bRaiseHand);

// Event
client.on('user-updated', (payload) => {
  if (payload.bRaiseHand !== undefined) {
    console.log(`${payload.userId} ${payload.bRaiseHand ? 'raised' : 'lowered'} hand`);
  }
});
Native SDK
// iOS
let webinarController = meetingService.getWebinarController()
webinarController?.raiseHand()
webinarController?.lowerHand()

Promote/Demote Attendees

Hosts can promote attendees to panelists:

// Web SDK (host only)
const webinarClient = client.getWebinarClient();

// Promote to panelist (allows video/audio)
await webinarClient.promoteAttendee(userId);

// Demote back to attendee
await webinarClient.demoteAttendee(userId);

// Allow attendee to talk (temporary unmute)
await webinarClient.allowAttendeeTalk(userId);
await webinarClient.disallowAttendeeTalk(userId);

Polling

Web SDK Polling
// Get polling client
const pollingClient = client.getPollingClient();

// Check if polling available
const isAvailable = pollingClient.isPollingEnabled();

// Submit poll answer (attendee)
await pollingClient.submitPollAnswer(pollId, [
  { questionId: 'q1', answerIds: ['a1'] }
]);

// Poll events
client.on('poll-started', (payload) => {
  console.log('Poll started:', payload.poll);
  displayPoll(payload.poll);
});

client.on('poll-ended', (payload) => {
  console.log('Poll ended');
});

Practice Session

Before a webinar starts, hosts can run a practice session:

// Detect practice session
client.on('meeting-status-changed', (payload) => {
  if (payload.status === 'practice') {
    console.log('In practice session - attendees cannot join yet');
  } else if (payload.status === 'webinar') {
    console.log('Webinar is live');
  }
});

Chat in Webinars

Chat permissions differ in webinars:

// Get chat privilege
const chatClient = client.getChatClient();
const privilege = chatClient.getPrivilege();

// privilege values:
// 1 = No one
// 2 = Host and panelists only  
// 3 = Everyone publicly
// 4 = Everyone publicly and privately

// Send to panelists (attendee)
await chatClient.send('Question about pricing', /* to all panelists */);

// Send to everyone (if allowed)
await chatClient.sendToAll('Hello everyone!');

Webinar-Specific Events

// Web SDK events
client.on('webinar-invite', (payload) => {
  // Attendee invited to become panelist
});

client.on('webinar-depromote', (payload) => {
  // Demoted from panelist to attendee
});

client.on('webinar-allow-attendee-chat', (payload) => {
  // Chat permissions changed
});

client.on('webinar-attendee-status', (payload) => {
  // Attendee count updated
  console.log('Attendees:', payload.attendeeCount);
});

Best Practices

For Large Webinars
  1. Disable attendee video - Already default for webinars

  2. Use Q&A instead of chat - More organized for large audiences

  3. Pre-register attendees - Better tracking and control

  4. Test with practice session - Verify setup before going live

UI Considerations
// Adjust UI based on role
function setupUI(role) {
  if (role === 'attendee') {
    // Hide video controls (can't send video)
    hideElement('#videoControls');
    
    // Show Q&A and raise hand
    showElement('#qaPanel');
    showElement('#raiseHandButton');
    
    // Disable unmute (until promoted)
    disableElement('#unmuteButton');
  } else if (role === 'panelist' || role === 'host') {
    // Full controls
    showAllControls();
  }
}

Resources

Requirements and compatibility

Written for: Claude Code, Claude apps

Works with: Claude Code, Claude apps, OpenAI Codex, GitHub Copilot, Cursor, Gemini CLI, Kiro, OpenCode, Goose, Amp, Roo Code, JetBrains Junie, Factory Droid, Devin (ex-Windsurf), Mistral Vibe, OpenHands, Letta

“Works with” means the tool reads the open Agent Skills format; a skill written for one tool may use features others lack.

Security

No issues found by our static scan· No issues found

A static scan is not a guarantee. Skills are third-party content: review a skill before you let an agent use it.

Attribution and licence

Created by
Zoom
Publisher
Anthropic (Official)
Distributed by
Anthropic
Source
anthropics/knowledge-work-plugins · partner-built/zoom-plugin/skills/meeting-sdk · commit e050c2e
Licence
MIT License (redistribution allowed)
  • LICENSE (added by AutoGineer from partner-built/zoom-plugin/LICENSE)
  • ATTRIBUTION.md (written by AutoGineer)
Synced

AutoGineer is not affiliated with or endorsed by Zoom or Anthropic.

Download ZIP

The ZIP holds the skill’s files, its licence files and an ATTRIBUTION.md. Download build-zoom-meeting-sdk-app.zip