Build Zoom Rest API App
OpenAIOfficialCreated by ZoomDistributed by OpenAI
- Skill
- Tool integration
- Software development
- MIT
- Medium risk
AutoGineer summary
Written by AutoGineer from the skill’s own files, not by the author
This skill provides a structured approach to interacting with the Zoom REST API. It offers guidance on selecting appropriate authentication flows, managing resources such as meetings and users, and implementing robust API interaction patterns like pagination and rate-limit handling. It includes reference documentation for various Zoom product areas, including account management and AI Companion services, to assist developers in building API-integrated applications.
What it does
- Provides endpoint inventories for Zoom API product areas.
- Outlines authentication requirements for user-level, account-level, and server-to-server workflows.
- Defines patterns for implementing API wrappers with pagination and retry logic.
- Offers guidance on webhook processing, including signature verification.
- Assists in troubleshooting common API issues like scope mismatches and rate limits.
When to use it
- When developing applications that need to programmatically manage Zoom meetings, users, or recordings.
- When integrating Zoom account settings or dashboard metrics into custom software.
- When setting up event-driven workflows using Zoom webhooks.
- When debugging authentication or scope-related errors during Zoom API integration.
Advantages
- Centralizes access to official Zoom API endpoint documentation.
- Standardizes the implementation of API interaction patterns.
- Clarifies the selection of correct authentication scopes for different API operations.
- Provides a clear methodology for handling API rate limits and resource management.
Usage examples
- “How do I list meeting participants using the Zoom API?”
- The agent provides the correct endpoint path from the dashboard references and explains the necessary OAuth scopes and pagination requirements.
- “What authentication should I use for an account-level Zoom integration?”
- The agent guides you through the account-level OAuth flow requirements as defined in the authentication documentation.
Install
Download the skill as a ZIP:
https://mp-staging.autogineer.com/agent-skills/openai/build-zoom-rest-api-app/downloadUnzip it into the cross-client skills folder of your project:
mkdir -p .agents/skills && unzip build-zoom-rest-api-app.zip -d .agents/skills
Documentation by Zoom
Build Zoom REST API App
Use this skill when the task needs deterministic Zoom API calls or resource management from application code.
Workflow
Define the resource and actor: user, meeting, webinar, recording, docs, chat, phone, account, or admin-level workflow.
Select the endpoint and required scopes from the reference files before coding.
Confirm auth fit: user-level OAuth for user-owned resources, account-level OAuth for admin workflows, and only use server-to-server OAuth where the target API documents support for it.
Implement narrow API wrappers with explicit pagination, retry, idempotency, and rate-limit handling.
Treat webhook processing as a separate event-ingestion path with signature verification and replay protection.
Debug by checking token audience, missing scopes, resource ownership, account settings, API enablement, and rate-limit headers.
References
Full preserved guide: references/full-guide.md
API architecture: concepts/api-architecture.md
Authentication flows: concepts/authentication-flows.md
Rate limits: references/rate-limits.md
Meetings: references/meetings.md
Recordings: references/recordings.md
Users: references/users.md
Token and scope playbook: troubleshooting/token-scope-playbook.md
Files
- ATTRIBUTION.mdAdded by AutoGineer878 B
- LICENSELicence file added by AutoGineer1.1 KiB
- RUNBOOK.md3.1 KiB
- SKILL.md1.6 KiB
- agents/openai.yaml143 B
- concepts/api-architecture.md8.9 KiB
- concepts/authentication-flows.md9.1 KiB
- concepts/meeting-urls-and-sdk-joining.md1.2 KiB
- concepts/rate-limiting-strategy.md9.6 KiB
- examples/graphql-queries.md465 B
- examples/meeting-lifecycle.md14.6 KiB
- examples/recording-pipeline.md661 B
- examples/user-management.md509 B
- examples/webhook-server.md14.4 KiB
- references/accounts.md7.5 KiB
- references/ai-companion.md1.2 KiB
- references/ai-services.md1.5 KiB
- references/authentication.md11.0 KiB
- references/auto-dialer.md2.6 KiB
- references/calendar.md4.9 KiB
- references/chatbot.md1.4 KiB
- references/clips.md2.9 KiB
- references/cobrowse-sdk-api.md1.4 KiB
- references/commerce.md5.8 KiB
- references/contact-center.md33.1 KiB
- references/crc.md3.5 KiB
- references/environment-variables.md976 B
- references/events.md13.0 KiB
- references/full-guide.md25.5 KiB
- references/graphql.md8.9 KiB
- references/healthcare.md1.3 KiB
- references/mail.md6.9 KiB
- references/marketplace-apps.md4.0 KiB
- references/meetings.md21.3 KiB
- references/number-management.md4.8 KiB
- references/openapi.md4.4 KiB
- references/phone.md45.9 KiB
- references/qss.md1.6 KiB
- references/quality-management.md1.7 KiB
- references/rate-limits.md9.9 KiB
- references/recordings.md1.4 KiB
- references/reports.md1.2 KiB
- references/revenue-accelerator.md9.4 KiB
- references/rooms.md15.3 KiB
- references/scheduler.md3.8 KiB
- references/scim2.md1.9 KiB
- references/tasks.md2.6 KiB
- references/team-chat.md13.5 KiB
- references/users.md7.3 KiB
- references/video-management.md4.0 KiB
- references/video-sdk-api.md5.3 KiB
- references/virtual-agent.md2.2 KiB
- references/webinars.md1.2 KiB
- references/whiteboard.md5.3 KiB
- references/workforce-management.md3.1 KiB
- references/zoom-docs.md3.2 KiB
- troubleshooting/common-errors.md11.6 KiB
- troubleshooting/common-issues.md650 B
- troubleshooting/forum-top-questions.md1.7 KiB
- troubleshooting/token-scope-playbook.md1.5 KiB
concepts/authentication-flows.md
Authentication Flows
All Zoom REST API requests require OAuth 2.0 authentication. This guide covers all supported OAuth flows and when to use each.
Complete OAuth implementation guide: See the zoom-oauth skill for full code examples, token storage, and production patterns.
Flow Selection
| Flow | Use Case | User Interaction | Token Lifetime |
|---|---|---|---|
| Server-to-Server OAuth | Backend automation, bots, integrations | None | 1 hour |
| Authorization Code | User-facing web apps | User consent flow | 1 hour (refresh: 15 years) |
| Authorization Code + PKCE | SPAs, mobile apps | User consent flow | 1 hour (refresh: 15 years) |
| Device Code | TV/IoT devices, CLI tools | User enters code on separate device | 1 hour (refresh: 15 years) |
| DEPRECATED — migrate to S2S OAuth |
Server-to-Server OAuth (Recommended for Backend)
No user interaction required. Best for automation, scheduled tasks, and backend services.
Setup
Go to Zoom App Marketplace → Develop → Build App
Select Server-to-Server OAuth
Note: Account ID, Client ID, Client Secret
Add required scopes (e.g.,
meeting:write:admin,user:read:admin)
Get Access Token
curl -X POST "https://zoom.us/oauth/token" \
-H "Authorization: Basic $(echo -n 'CLIENT_ID:CLIENT_SECRET' | base64)" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=account_credentials&account_id=ACCOUNT_ID"Response
{
"access_token": "eyJhbGciOiJIUzI1NiJ9...",
"token_type": "bearer",
"expires_in": 3600,
"scope": "meeting:read meeting:write user:read",
"api_url": "https://api.zoom.us"
}Node.js — Token Manager with Auto-Refresh
class ZoomS2SAuth {
constructor(accountId, clientId, clientSecret) {
this.accountId = accountId;
this.clientId = clientId;
this.clientSecret = clientSecret;
this.token = null;
this.tokenExpiry = 0;
}
async getAccessToken() {
// Return cached token if valid (with 60s buffer)
if (this.token && Date.now() < this.tokenExpiry - 60000) {
return this.token;
}
const credentials = Buffer.from(
`${this.clientId}:${this.clientSecret}`
).toString('base64');
const response = await fetch('https://zoom.us/oauth/token', {
method: 'POST',
headers: {
'Authorization': `Basic ${credentials}`,
'Content-Type': 'application/x-www-form-urlencoded'
},
body: `grant_type=account_credentials&account_id=${this.accountId}`
});
if (!response.ok) {
const err = await response.json();
throw new Error(`Token error: ${err.error} - ${err.reason}`);
}
const data = await response.json();
this.token = data.access_token;
this.tokenExpiry = Date.now() + (data.expires_in * 1000);
return this.token;
}
async request(method, path, body = null) {
const token = await this.getAccessToken();
const response = await fetch(`https://api.zoom.us/v2${path}`, {
method,
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
},
body: body ? JSON.stringify(body) : undefined
});
if (!response.ok) {
const err = await response.json().catch(() => ({}));
throw new Error(`Zoom API ${response.status}: ${JSON.stringify(err)}`);
}
// Some endpoints return 204 No Content
if (response.status === 204) return null;
return response.json();
}
}
// Usage
const zoom = new ZoomS2SAuth(
process.env.ZOOM_ACCOUNT_ID,
process.env.ZOOM_CLIENT_ID,
process.env.ZOOM_CLIENT_SECRET
);
const users = await zoom.request('GET', '/users?page_size=300');
const meeting = await zoom.request('POST', '/users/[email protected]/meetings', {
topic: 'API Meeting', type: 2, duration: 30
});Python — Token Manager
import requests
import time
from base64 import b64encode
class ZoomS2SAuth:
def __init__(self, account_id, client_id, client_secret):
self.account_id = account_id
self.client_id = client_id
self.client_secret = client_secret
self.token = None
self.token_expiry = 0
def get_access_token(self):
if self.token and time.time() < self.token_expiry - 60:
return self.token
credentials = b64encode(
f'{self.client_id}:{self.client_secret}'.encode()
).decode()
response = requests.post(
'https://zoom.us/oauth/token',
headers={
'Authorization': f'Basic {credentials}',
'Content-Type': 'application/x-www-form-urlencoded'
},
data=f'grant_type=account_credentials&account_id={self.account_id}'
)
response.raise_for_status()
data = response.json()
self.token = data['access_token']
self.token_expiry = time.time() + data['expires_in']
return self.token
def request(self, method, path, json_data=None):
token = self.get_access_token()
response = requests.request(
method,
f'https://api.zoom.us/v2{path}',
headers={'Authorization': f'Bearer {token}'},
json=json_data
)
response.raise_for_status()
return response.json() if response.content else NoneUser OAuth (Authorization Code)
For apps that act on behalf of individual Zoom users.
Flow
1. User clicks "Connect to Zoom"
2. Redirect to: https://zoom.us/oauth/authorize?response_type=code&client_id=XXX&redirect_uri=YYY&state=ZZZ
3. User grants permission
4. Zoom redirects to callback: https://yourapp.com/callback?code=AUTH_CODE&state=ZZZ
5. Exchange code for tokens
6. Use access_token for API calls
7. Refresh when expiredExchange Code for Token
curl -X POST "https://zoom.us/oauth/token" \
-H "Authorization: Basic $(echo -n 'CLIENT_ID:CLIENT_SECRET' | base64)" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=authorization_code&code=AUTH_CODE&redirect_uri=https://yourapp.com/callback"Refresh Token
curl -X POST "https://zoom.us/oauth/token" \
-H "Authorization: Basic $(echo -n 'CLIENT_ID:CLIENT_SECRET' | base64)" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=refresh_token&refresh_token=REFRESH_TOKEN"Important: me Keyword
User OAuth apps must use me instead of userId in API paths:
# CORRECT for user OAuth
GET /v2/users/me/meetings
# WRONG for user OAuth — will return "Invalid access token"
GET /v2/users/abc123/meetingsCommon Scopes
| Scope | Description |
|---|---|
user:read | Read user profile |
user:read:admin | Read all users (admin) |
user:write:admin | Manage all users (admin) |
meeting:read | Read meeting data |
meeting:write | Create/update meetings |
meeting:write:admin | Create/update any user's meetings |
recording:read | Access recordings |
recording:write | Manage recordings |
webinar:read | Read webinar data |
webinar:write | Manage webinars |
report:read:admin | View reports |
Best practice: Request only the scopes you need. Fewer scopes = less user friction and faster app approval.
Token Storage Best Practices
// DO: Encrypt tokens at rest
const encrypted = encrypt(accessToken, process.env.ENCRYPTION_KEY);
await db.tokens.upsert({ userId, encrypted, expiresAt });
// DO: Use httpOnly secure cookies for web apps
res.cookie('zoom_session', sessionId, {
httpOnly: true, secure: true, sameSite: 'strict', maxAge: 3600000
});
// DON'T: Store tokens in localStorage or log them
localStorage.setItem('zoom_token', token); // INSECURE
console.log('Token:', accessToken); // LEAKS CREDENTIALSError Handling
| Error | Cause | Solution |
|---|---|---|
invalid_grant | Expired/used auth code or refresh token | Restart OAuth flow or re-authenticate |
invalid_client | Wrong client ID or secret | Verify credentials |
invalid_scope | Scope not approved for your app | Check app scopes in Marketplace |
access_denied | User denied permission | Handle gracefully in UI |
try {
const token = await refreshAccessToken(refreshToken);
} catch (error) {
if (error.response?.data?.error === 'invalid_grant') {
// Refresh token revoked or expired — re-authenticate
redirectToOAuthFlow();
}
}Migration from JWT (Deprecated)
The JWT app type on Zoom Marketplace is deprecated. This does not affect JWT token signatures used elsewhere (e.g., Video SDK).
Steps:
Create a Server-to-Server OAuth app
Request the same scopes
Replace JWT token generation with OAuth token endpoint
Test all endpoints
Delete the JWT app
Resources
OAuth Guide: https://developers.zoom.us/docs/integrations/oauth/
S2S OAuth: https://developers.zoom.us/docs/internal-apps/s2s-oauth/
Scopes Reference: https://developers.zoom.us/docs/integrations/oauth-scopes/
Full OAuth Skill: See zoom-oauth
Requirements and compatibility
Written for: OpenAI Codex
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
What our scanner noticed· Medium risk
- Possible data-exfiltration endpoints
- Instructions that use the network
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
- OpenAI (Official)
- Distributed by
- OpenAI
- Source
- openai/plugins · plugins/zoom/skills/rest-api · commit d420d13
- Licence
- MIT License (redistribution allowed)
- LICENSE (added by AutoGineer from plugins/zoom/LICENSE)
- ATTRIBUTION.md (written by AutoGineer)
- Synced
AutoGineer is not affiliated with or endorsed by Zoom or OpenAI.
Download ZIP
The ZIP holds the skill’s files, its licence files and an ATTRIBUTION.md. Download build-zoom-rest-api-app.zip