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://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
references/rate-limits.md
REST API - Rate Limits
Understanding and handling Zoom API rate limits for reliable integrations.
Overview
Zoom APIs enforce rate limits to ensure fair usage. Limits vary by endpoint category, account type, and are shared across all apps on an account.
Rate Limit Categories
Main REST API
| Category | Free | Pro | Business+ |
|---|---|---|---|
| Light | 4/sec, 6,000/day | 30/sec | 80/sec |
| Medium | 2/sec, 2,000/day | 20/sec | 60/sec |
| Heavy | 1/sec, 1,000/day | 10/sec* | 40/sec* |
| Resource-Intensive | 10/min, 30,000/day | 10/min* | 20/min* |
* Daily limits (shared):
Pro: 30,000/day (Heavy + Resource-Intensive combined)
Business+: 60,000/day (Heavy + Resource-Intensive combined)
Zoom Phone API
| Category | Pro | Business+ |
|---|---|---|
| Light | 20/sec | 40/sec |
| Medium | 10/sec | 20/sec |
| Heavy | 5/sec, 15,000/day* | 10/sec, 30,000/day* |
| Resource-Intensive | 5/min, 15,000/day* | 10/min, 30,000/day* |
Zoom Contact Center API
| Category | Pro | Business+ |
|---|---|---|
| Light | 20/sec | 40/sec |
| Medium | 10/sec | 20/sec |
| Heavy | 5/sec, 15,000/day* | 10/sec, 30,000/day* |
* Daily limit shared with Resource-Intensive APIs
Endpoint Category Examples
| Light | Medium | Heavy |
|---|---|---|
| Add Meeting Registrant | Create Meeting | Get Daily Usage Report |
| Get A Meeting | Get Past Meeting Participants | List Devices |
| Get Meeting Recordings | List All Recordings | |
| Update A Meeting | List Meetings | |
| Delete Meeting Recordings | List Webinars |
Special Per-User Limits
Meeting/Webinar Operations
| Operation | Limit | Reset |
|---|---|---|
| Meeting/Webinar Create/Update | 100/day per user | 00:00 UTC |
| Registrant Addition | 3/day per registrant | 00:00 UTC |
| Registrant Status Updates | 10/day per registrant | 00:00 UTC |
Note: The 100/day limit applies to all Meeting/Webinar IDs hosted by a specific user.
Lock-Key Limits (Concurrent Operations)
Zoom enforces lock-key limits for user resource operations:
| Scenario | Behavior |
|---|---|
| Multiple DELETE on same userId | Only 1 concurrent DELETE allowed |
POST to /v2/users | Blocks GET/PATCH/PUT/DELETE until complete |
Error Response:
{
"code": 429,
"message": "Too many concurrent requests. A request to disassociate this user has already been made."
}Response Headers
Every API response includes rate limit headers:
| Header | Description |
|---|---|
X-RateLimit-Category | Light, Medium, Heavy, or Resource-intensive |
X-RateLimit-Type | QPS (per-second) or Daily-limit |
X-RateLimit-Limit | Maximum requests in current window |
X-RateLimit-Remaining | Requests remaining in current window |
On Per-Second/Minute Limit Hit
| Header | Description |
|---|---|
X-RateLimit-Reset | Unix timestamp when limit resets |
On Daily Limit Hit
| Header | Description |
|---|---|
Retry-After | ISO8601 datetime when you can retry |
Example Headers
Normal response:
X-RateLimit-Category: Medium
X-RateLimit-Type: QPS
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 55Rate limited (per-second):
HTTP/1.1 429 Too Many Requests
X-RateLimit-Category: Light
X-RateLimit-Type: QPS
X-RateLimit-Limit: 80
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1705312800Rate limited (daily):
HTTP/1.1 429 Too Many Requests
X-RateLimit-Category: Heavy
X-RateLimit-Type: Daily-limit
X-RateLimit-Limit: 60000
X-RateLimit-Remaining: 0
Retry-After: 2025-01-20T00:00:00ZError Responses
Per-Second Limit
{
"code": 429,
"message": "You have reached the maximum per-second rate limit for this API. Try again later."
}Daily Limit
{
"code": 429,
"message": "You have reached the maximum daily rate limit for this API. Refer to the response header for details on when you can make another request."
}Handling Rate Limits
Basic Retry with Backoff
async function callZoomAPI(url, options, maxRetries = 5) {
for (let attempt = 0; attempt < maxRetries; attempt++) {
const response = await fetch(url, options);
if (response.status === 429) {
// Check for Retry-After (daily limit)
const retryAfter = response.headers.get('Retry-After');
if (retryAfter) {
const retryDate = new Date(retryAfter);
const waitMs = retryDate - Date.now();
console.log(`Daily limit hit. Retry after: ${retryAfter}`);
await sleep(waitMs);
continue;
}
// Per-second limit - use exponential backoff
const delay = Math.pow(2, attempt) * 1000;
const jitter = delay * 0.2 * Math.random(); // 20% jitter
console.log(`Rate limited. Retrying in ${delay + jitter}ms`);
await sleep(delay + jitter);
continue;
}
return response;
}
throw new Error('Max retries exceeded');
}Monitor Rate Limit Headers
async function callAPIWithMonitoring(url, options) {
const response = await fetch(url, options);
const remaining = parseInt(response.headers.get('X-RateLimit-Remaining'));
const limit = parseInt(response.headers.get('X-RateLimit-Limit'));
const category = response.headers.get('X-RateLimit-Category');
const type = response.headers.get('X-RateLimit-Type');
console.log(`[${category}/${type}] ${remaining}/${limit} remaining`);
// Proactive throttling
if (remaining < limit * 0.1) { // Less than 10% remaining
console.warn('Approaching rate limit - throttling requests');
await sleep(1000); // Slow down
}
return response;
}Request Queue Pattern
For high-volume applications:
class RateLimitedQueue {
constructor(maxConcurrent = 10, minDelayMs = 100) {
this.queue = [];
this.running = 0;
this.maxConcurrent = maxConcurrent;
this.minDelayMs = minDelayMs;
}
async add(requestFn) {
return new Promise((resolve, reject) => {
this.queue.push({ requestFn, resolve, reject });
this.process();
});
}
async process() {
if (this.running >= this.maxConcurrent || this.queue.length === 0) {
return;
}
const { requestFn, resolve, reject } = this.queue.shift();
this.running++;
try {
const result = await requestFn();
resolve(result);
} catch (error) {
reject(error);
} finally {
this.running--;
await sleep(this.minDelayMs);
this.process();
}
}
}
// Usage
const queue = new RateLimitedQueue(10, 100); // 10 concurrent, 100ms min delay
const results = await Promise.all([
queue.add(() => fetch('/api/users/1')),
queue.add(() => fetch('/api/users/2')),
queue.add(() => fetch('/api/users/3')),
// ... more requests
]);Best Practices
1. Cache GET Responses
const cache = new Map();
const CACHE_TTL = 60000; // 1 minute
async function cachedGet(url, options) {
const cached = cache.get(url);
if (cached && Date.now() - cached.timestamp < CACHE_TTL) {
return cached.data;
}
const response = await fetch(url, options);
const data = await response.json();
cache.set(url, { data, timestamp: Date.now() });
return data;
}2. Use Webhooks Instead of Polling
Instead of polling for changes:
// DON'T: Poll every minute
setInterval(async () => {
const meetings = await getMeetings(); // Uses API quota
}, 60000);Use webhooks:
// DO: Receive webhook events
app.post('/webhook', (req, res) => {
const event = req.body;
if (event.event === 'meeting.started') {
handleMeetingStarted(event.payload);
}
res.status(200).send();
});3. Batch Operations
Use list endpoints with pagination instead of individual fetches:
// DON'T: Fetch users one by one
for (const userId of userIds) {
const user = await getUser(userId); // N API calls
}
// DO: Fetch users in batches
const users = await listUsers({ page_size: 300 }); // 1 API call4. Use QSS for Quality Data
For Quality of Service data, use QSS (push-based) instead of polling:
QSS streams telemetry via webhooks/WebSocket
Pushes data 4-6 times per minute
Reduces need for Reports API polling
5. Distribute Requests Over Time
// DON'T: Burst all requests at once
await Promise.all(users.map(u => updateUser(u))); // May hit rate limit
// DO: Distribute over time
for (const user of users) {
await updateUser(user);
await sleep(100); // 100ms between requests
}Account Type Notes
Rate Limits Are Per-Account
Limits are shared by ALL users and ALL apps on the account
Upgrading account increases limits for everyone
Not per-app - one heavy app can impact others
Business+ Includes
Business
Education
Enterprise
Partners
Video SDK Accounts
| Plan | Uses Limits |
|---|---|
| Pay As You Go (Deprecated) | Pro |
| Annual Prepay Monthly Usage | Pro |
| All other plans | Business+ |
Event Subscription Limits
Maximum 10 event subscriptions per application
No limit on events per subscription
Event subscription API has Heavy rate limit
WebSocket: Only 1 subscription connection at a time (new connection closes previous)
Common Gotchas
| Issue | Solution |
|---|---|
| 429 on first request of the day | Another app on account used quota |
| Different limits than documented | Check account type (Free/Pro/Business+) |
| Meeting create fails at 100/day | Per-user limit - use different host |
| Concurrent DELETE errors | Serialize DELETE operations on same user |
| Daily limit hit unexpectedly | Heavy + Resource-Intensive share quota |
Resources
Rate limits docs: https://developers.zoom.us/docs/api/rest/rate-limits/
Webhooks docs: https://developers.zoom.us/docs/api/rest/webhook-reference/
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