Generated banner for Build Zoom Rest API App
Generated logo for Build Zoom Rest API App

Build Zoom Rest API App

OpenAIOfficialCreated by ZoomDistributed by OpenAI

  • Skill
  • Tool integration
  • Software development
  • MIT
  • Medium risk

From the author

Use when calling REST APIs.
— the description by Zoom

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

  1. Download the skill as a ZIP:

    https://autogineer.com/agent-skills/openai/build-zoom-rest-api-app/download
  2. Unzip 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

  1. Define the resource and actor: user, meeting, webinar, recording, docs, chat, phone, account, or admin-level workflow.

  2. Select the endpoint and required scopes from the reference files before coding.

  3. 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.

  4. Implement narrow API wrappers with explicit pagination, retry, idempotency, and rate-limit handling.

  5. Treat webhook processing as a separate event-ingestion path with signature verification and replay protection.

  6. Debug by checking token audience, missing scopes, resource ownership, account settings, API enablement, and rate-limit headers.

References

Files

references/graphql.md

Zoom GraphQL API (Beta)

Flexible data queries with GraphQL as an alternative to REST.

Overview

Zoom GraphQL API provides a single endpoint for querying and mutating Zoom data. Unlike REST APIs with fixed endpoints, GraphQL allows you to request exactly the data you need.

Status: Beta (requires signup)

Key URLs

ResourceURL
Playgroundhttps://nws.zoom.us/graphql/playground
Beta Signuphttps://beta.zoom.us/key/GRAPHQL
Endpointhttps://api.zoom.us/graphql

GraphQL vs REST

FeatureREST APIGraphQL API
Endpoints600+ endpointsSingle endpoint
Data fetchingFixed data per endpointClient specifies exact fields
Multiple resourcesMultiple requestsSingle request
Over-fetchingCommonEliminated
SchemaOptional (OpenAPI)Mandatory, strongly typed
Learning curveLowerHigher

Authentication

Same OAuth 2.0 as REST API:

const headers = {
  'Authorization': `Bearer ${accessToken}`,
  'Content-Type': 'application/json'
};
  • Server-to-Server OAuth supported

  • User-authorized OAuth supported

  • Access tokens valid for 1 hour

Available Entities

EntityQueryMutation
Users✅✅
Meetings✅Partial
Webinars✅Partial
Chat ChannelsPartial-
Cloud Recordings✅-
Dashboards✅-
GroupsPartial-
ReportsPartial-

Note: Not all REST endpoints are available in GraphQL yet (beta).

Query Examples

List Users
query ListUsers {
  users(first: 100) {
    edges {
      node {
        id
        firstName
        lastName
        email
        department
        type
        status
      }
    }
    pageInfo {
      hasNextPage
      endCursor
    }
  }
}
Get User Details
query GetUser($userId: ID!) {
  user(id: $userId) {
    id
    firstName
    lastName
    email
    department
    timezone
    type
    createdAt
    lastLoginTime
  }
}

Variables:

{
  "userId": "user_abc123"
}
List Meetings
query ListMeetings($userId: ID!) {
  user(id: $userId) {
    meetings(first: 50) {
      edges {
        node {
          id
          topic
          type
          startTime
          duration
          timezone
          joinUrl
        }
      }
    }
  }
}
Get Meeting with Participants
query GetMeetingDetails($meetingId: ID!) {
  meeting(id: $meetingId) {
    id
    topic
    type
    startTime
    duration
    host {
      id
      firstName
      lastName
      email
    }
    participants {
      edges {
        node {
          id
          name
          email
          joinTime
          leaveTime
        }
      }
    }
  }
}
Get Recordings
query GetRecordings($userId: ID!, $from: DateTime!, $to: DateTime!) {
  user(id: $userId) {
    recordings(from: $from, to: $to, first: 50) {
      edges {
        node {
          id
          topic
          startTime
          duration
          totalSize
          recordingFiles {
            id
            fileType
            fileSize
            downloadUrl
          }
        }
      }
    }
  }
}

Mutation Examples

Create User
mutation CreateUser($input: UserCreateInput!) {
  createUser(input: $input) {
    id
    email
    firstName
    lastName
    type
  }
}

Variables:

{
  "input": {
    "action": "CUST_CREATE",
    "userInfo": {
      "email": "[email protected]",
      "firstName": "John",
      "lastName": "Doe",
      "type": "BASIC"
    }
  }
}
Update User
mutation UpdateUser($userId: ID!, $input: UserUpdateInput!) {
  updateUser(id: $userId, input: $input) {
    id
    firstName
    lastName
    department
  }
}

Variables:

{
  "userId": "user_abc123",
  "input": {
    "firstName": "Jonathan",
    "department": "Engineering"
  }
}

Making Requests

JavaScript/Node.js
async function graphqlQuery(query, variables = {}) {
  const response = await fetch('https://api.zoom.us/graphql', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${accessToken}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      query: query,
      variables: variables
    })
  });

  const result = await response.json();

  if (result.errors) {
    throw new Error(result.errors[0].message);
  }

  return result.data;
}

// Usage
const users = await graphqlQuery(`
  query {
    users(first: 10) {
      edges {
        node {
          id
          email
          firstName
          lastName
        }
      }
    }
  }
`);

console.log(users.users.edges);
Python
import requests

def graphql_query(query, variables=None):
    response = requests.post(
        'https://api.zoom.us/graphql',
        headers={
            'Authorization': f'Bearer {access_token}',
            'Content-Type': 'application/json'
        },
        json={
            'query': query,
            'variables': variables or {}
        }
    )

    result = response.json()

    if 'errors' in result:
        raise Exception(result['errors'][0]['message'])

    return result['data']

# Usage
users = graphql_query('''
    query {
        users(first: 10) {
            edges {
                node {
                    id
                    email
                }
            }
        }
    }
''')
cURL
curl -X POST https://api.zoom.us/graphql \
  -H "Authorization: Bearer ${ACCESS_TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{
    "query": "query { users(first: 10) { edges { node { id email } } } }"
  }'

Pagination

GraphQL uses cursor-based pagination:

query PaginatedUsers($cursor: String) {
  users(first: 100, after: $cursor) {
    edges {
      node {
        id
        email
      }
      cursor
    }
    pageInfo {
      hasNextPage
      endCursor
    }
  }
}

Fetching all pages:

async function fetchAllUsers() {
  let allUsers = [];
  let cursor = null;
  let hasNextPage = true;

  while (hasNextPage) {
    const result = await graphqlQuery(
      `query($cursor: String) {
        users(first: 100, after: $cursor) {
          edges {
            node { id email firstName lastName }
          }
          pageInfo {
            hasNextPage
            endCursor
          }
        }
      }`,
      { cursor }
    );

    allUsers.push(...result.users.edges.map(e => e.node));
    hasNextPage = result.users.pageInfo.hasNextPage;
    cursor = result.users.pageInfo.endCursor;
  }

  return allUsers;
}

Error Handling

GraphQL always returns HTTP 200. Errors are in the response body:

{
  "data": null,
  "errors": [
    {
      "message": "User not found",
      "locations": [{ "line": 2, "column": 3 }],
      "path": ["user"],
      "extensions": {
        "code": "NOT_FOUND"
      }
    }
  ]
}

Handle errors:

async function safeQuery(query, variables) {
  const response = await fetch('https://api.zoom.us/graphql', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${accessToken}`,
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({ query, variables })
  });

  const result = await response.json();

  if (result.errors && result.errors.length > 0) {
    const error = result.errors[0];
    console.error(`GraphQL Error: ${error.message}`);
    console.error(`Code: ${error.extensions?.code}`);
    throw new Error(error.message);
  }

  return result.data;
}

When to Use GraphQL vs REST

Use GraphQL When:
  • Fetching specific fields from complex nested data

  • Making multiple related queries in one request

  • Building mobile apps where bandwidth matters

  • Working with interconnected user, meeting, webinar data

  • Prototyping and exploring the API

Use REST When:
  • Need access to all 600+ endpoints (GraphQL coverage incomplete)

  • Building simple CRUD applications

  • Require HTTP caching

  • Team is unfamiliar with GraphQL

  • Production stability is critical (GraphQL is beta)

Playground

The GraphQL Playground at https://nws.zoom.us/graphql/playground provides:

  • Interactive query editor

  • Auto-complete and syntax highlighting

  • Query history

  • Embedded documentation

  • Schema explorer

Note: Requires beta access.

Limitations (Beta)

LimitationNotes
CoverageNot all REST endpoints available
StabilityBeta - features may change
AccessRequires explicit beta signup
DocumentationLess comprehensive than REST

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