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
troubleshooting/common-errors.md
Common Errors - HTTP Status Codes and Zoom Error Codes
Complete reference for Zoom REST API error codes, HTTP status codes, and solutions.
HTTP Status Codes
2XX - Success
| Status | Description | Action |
|---|---|---|
200 OK | Request succeeded | Parse response body |
201 Created | Resource created | Check Location header for new resource URL |
204 No Content | Request succeeded, no body | Common for UPDATE/DELETE operations |
4XX - Client Errors
| Status | Description | Common Causes | Solution |
|---|---|---|---|
400 Bad Request | Invalid request | Missing required fields, invalid JSON, validation errors | Check request body format and required fields |
401 Unauthorized | Authentication failed | Invalid/expired token, missing Authorization header | Refresh access token, check token format |
403 Forbidden | Permission denied | Missing scopes, user lacks permission, shared access not granted | Add required scopes, check user role |
404 Not Found | Resource doesn't exist | Invalid userId/meetingId, wrong me keyword usage | Verify resource ID, check me keyword rules |
409 Conflict | Resource conflict | Email already exists, duplicate operation | Use unique identifiers |
429 Too Many Requests | Rate limit exceeded | Too many requests per second/day | Implement exponential backoff, throttle requests |
5XX - Server Errors
| Status | Description | Action |
|---|---|---|
500 Internal Server Error | Zoom server error | Retry with exponential backoff |
502 Bad Gateway | Gateway error | Retry after delay |
503 Service Unavailable | Zoom service down | Check status.zoom.us, retry later |
Zoom Error Codes
When an API call fails, Zoom returns an error response:
{
"code": 300,
"message": "Request Body should be a valid JSON object."
}Common Zoom Error Codes
| Code | HTTP | Message | Cause | Solution |
|---|---|---|---|---|
300 | 400 | Invalid request | Bad JSON, validation error | Check request body structure |
124 | 400 | Invalid parameter | Wrong parameter type/value | Validate parameters against API docs |
200 | 401 | Invalid credentials | Incorrect OAuth token | Refresh access token |
201 | 401 | Access token expired | Token expired | Request new token |
1001 | 404 | User does not exist | Invalid userId or wrong me usage | Check userId, review me keyword rules |
300 | 404 | Meeting not found | Invalid meetingId | Verify meeting exists |
3000 | 404 | Cannot access webinar info | Webinar doesn't exist or no access | Check webinarId and scopes |
200 | 429 | Rate limit exceeded | Too many requests | Implement rate limiting |
4700 | 401 | Invalid access token | Token missing scopes | Add required scopes in app config |
3001 | 403 | Not allowed to access | Missing permission | Upgrade user role or add scope |
Detailed Error Scenarios
401 Unauthorized
Scenario 1: Token Expired
{
"code": 201,
"message": "Access token is expired."
}Solution:
async function apiCallWithRetry(url, options) {
try {
const response = await fetch(url, options);
if (response.status === 401) {
const error = await response.json();
if (error.code === 201) {
// Token expired - refresh and retry
const newToken = await refreshAccessToken();
options.headers['Authorization'] = `Bearer ${newToken}`;
return await fetch(url, options);
}
}
return response;
} catch (error) {
console.error('API call failed:', error);
throw error;
}
}Scenario 2: Missing/Invalid Token
{
"code": 200,
"message": "Invalid credentials."
}Solution:
Check
Authorizationheader is present:Authorization: Bearer ACCESS_TOKENVerify token format (should be JWT)
Ensure token is for the correct account
Scenario 3: Missing Scopes
{
"code": 4700,
"message": "Invalid access token, does not contain scopes."
}Solution:
Go to your app on Zoom Marketplace
Add required scopes (e.g.,
meeting:write:admin)Request new access token with updated scopes
403 Forbidden
Scenario 1: Missing Permission
{
"code": 3001,
"message": "This user is not allowed to access this resource."
}Solution:
Verify user has appropriate role (Admin, Owner)
Check if endpoint requires admin-level scopes
Use account-level scope (e.g.,
meeting:write:admininstead ofmeeting:write)
Scenario 2: Shared Access Permissions
{
"code": 3001,
"message": "Authenticated user has not permitted access to the targeted resource."
}Cause: User hasn't authorized shared access permissions for your app.
Solution: Direct user to: Allowing Apps Access to Shared Access Permissions
404 Not Found
Scenario 1: User Not Found (Wrong me Usage)
{
"code": 1001,
"message": "User does not exist: [email protected]"
}Cause: Using userId with User OAuth app (should use me).
Solution:
// WRONG (User OAuth app)
fetch('https://api.zoom.us/v2/users/[email protected]', {
headers: { 'Authorization': `Bearer ${userToken}` }
});
// CORRECT (User OAuth app)
fetch('https://api.zoom.us/v2/users/me', {
headers: { 'Authorization': `Bearer ${userToken}` }
});Scenario 2: Meeting/Resource Not Found
{
"code": 300,
"message": "Meeting not found."
}Causes:
Meeting deleted
Meeting expired (30 days after last use)
Invalid meetingId
Wrong UUID encoding
Solution for UUID:
// UUID starts with / or contains // → double-encode
const uuid = '/xyzAbC123==';
const encoded = encodeURIComponent(encodeURIComponent(uuid));
fetch(`https://api.zoom.us/v2/meetings/${encoded}`, { headers });429 Too Many Requests
{
"code": 200,
"message": "You have reached the maximum per-second rate limit for this API."
}Solution: Implement exponential backoff
async function apiCallWithBackoff(url, options, maxRetries = 3) {
for (let attempt = 1; attempt <= maxRetries; attempt++) {
const response = await fetch(url, options);
if (response.status === 429) {
const retryAfter = response.headers.get('Retry-After') || Math.pow(2, attempt);
console.log(`Rate limited. Retrying after ${retryAfter}s`);
await sleep(retryAfter * 1000);
continue;
}
return response;
}
throw new Error('Max retries exceeded');
}
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}Check rate limit headers:
const remaining = response.headers.get('X-RateLimit-Remaining');
const type = response.headers.get('X-RateLimit-Type');
console.log(`Rate limit remaining: ${remaining} (${type})`);Validation Error Responses
Field Validation Errors
{
"code": 300,
"message": "Validation Failed.",
"errors": [
{
"field": "start_time",
"message": "Invalid field."
},
{
"field": "type",
"message": "Invalid field."
}
]
}Solution:
Check each field's format in API documentation
Verify required fields are present
Ensure data types match (number vs string)
Common Field Errors
| Field | Error | Cause | Fix |
|---|---|---|---|
start_time | Invalid field | Wrong format | Use yyyy-MM-ddTHH:mm:ssZ |
type | Invalid field | Invalid meeting type | Use 1, 2, 3, or 8 |
email | Invalid field | Invalid email format | Check email format |
duration | Invalid field | Duration too long | Max duration varies by plan |
Error Response Structure
Standard Error
{
"code": 300,
"message": "Descriptive error message"
}Validation Error
{
"code": 300,
"message": "Validation Failed.",
"errors": [
{
"field": "field_name",
"message": "Error description"
}
]
}Error Handling Best Practices
1. Parse Error Response
async function handleApiResponse(response) {
if (!response.ok) {
const error = await response.json();
console.error(`API Error ${response.status}:`, error);
// Check for validation errors
if (error.errors && Array.isArray(error.errors)) {
error.errors.forEach(err => {
console.error(`- Field "${err.field}": ${err.message}`);
});
}
throw new Error(`${error.code}: ${error.message}`);
}
return await response.json();
}2. Retry with Exponential Backoff
async function retryWithBackoff(fn, maxRetries = 3, baseDelay = 1000) {
for (let attempt = 1; attempt <= maxRetries; attempt++) {
try {
return await fn();
} catch (error) {
const isRetryable = error.status >= 500 || error.status === 429;
if (!isRetryable || attempt === maxRetries) {
throw error;
}
const delay = baseDelay * Math.pow(2, attempt - 1);
const jitter = Math.random() * 1000; // Add randomness
console.log(`Retry attempt ${attempt} after ${delay + jitter}ms`);
await sleep(delay + jitter);
}
}
}3. Log Errors with Context
function logApiError(error, context) {
const logEntry = {
timestamp: new Date().toISOString(),
status: error.status,
code: error.code,
message: error.message,
context: {
endpoint: context.endpoint,
method: context.method,
userId: context.userId
}
};
console.error('API Error:', JSON.stringify(logEntry, null, 2));
// Send to monitoring service
// monitoring.track(logEntry);
}4. User-Friendly Error Messages
function getUserFriendlyError(error) {
const errorMap = {
1001: 'User not found. Please check the email address.',
300: 'Invalid request. Please check your input.',
201: 'Your session has expired. Please sign in again.',
4700: 'Permission denied. Please contact your administrator.',
200: 'Too many requests. Please try again in a few moments.'
};
return errorMap[error.code] || 'An unexpected error occurred. Please try again.';
}Troubleshooting Checklist
Quick Diagnostic Steps
Check HTTP status code - Indicates error category (auth, validation, server)
Read error message - Provides specific details
Check Zoom error code - Maps to specific issue
Verify authentication - Token valid, scopes present
Check rate limits - Monitor
X-RateLimit-RemainingheaderTest with Postman - Isolate code vs API issue
Check Zoom Status - Visit status.zoom.us
Common Fixes
| Symptom | Check | Fix |
|---|---|---|
| 401 Unauthorized | Token expiry | Refresh access token |
| 404 User not found | me keyword usage | Use me for User OAuth |
| 404 Meeting not found | UUID encoding | Double-encode UUIDs starting with / |
| 403 Forbidden | Scopes | Add required scopes in app config |
| 429 Rate limit | Request rate | Implement throttling |
| 400 Validation error | Request body | Check field formats in docs |
Related Documentation
API Architecture -
mekeyword, UUID encoding, time formatsRate Limiting Strategy - Handle 429 errors
Authentication Flows - Token refresh patterns
Common Issues - Practical troubleshooting
Resources
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