# @kody/zoom Official Zoom wordmark (Simple Icons path from [Zoom brand](https://brand.zoom.us/media-library/)) in white on Zoom Blue `#0B5CFF`. Paths are unmodified. Zoom® is a trademark of Zoom Communications, Inc. This package is not affiliated with or endorsed by Zoom. ## Intent Reusable Zoom REST helpers for Kody agents. One package covers bring-your-own user OAuth applications and Server-to-Server OAuth secrets for users, meetings, recordings, and webinars. Multi-account routing is `zoom` / `zoom-*` via `integrationName` or `account` — there are no hard-coded personal aliases or meeting IDs. This listing is meant to be forked. After you fork, connect **your** Zoom account. Do not treat the live `@kody/zoom` package as a shared meeting calendar. Share this listing at https://kody.codes/@kody/zoom ## What it does - Call the Zoom REST API with the correct saved credential (`request`, `paginate`) - Verify which Zoom identity will perform an action (`get-current-user`) - List and fetch users, meetings, recordings, and webinars - Preview or apply meeting and webinar writes (`meetings/*`, `webinars/*`) It does **not** register a Zoom Marketplace app for you. There is no built-in Zoom platform app. ## Prerequisites / setup | Lane | Credential | When to use | | --- | --- | --- | | **A. User OAuth** | Saved integration `zoom` (or `zoom-*`) | Refreshable user OAuth; `me` works for the connected user | | **B. Server-to-Server OAuth** | Secrets `zoomClientId`, `zoomS2sClientSecret`, plus the plain `accountId` param | Account-level automations; pass `auth: 's2s'` and `accountId` | Required hosts: `api.zoom.us` and `zoom.us`. Approve them in the account secrets UI. Never paste secrets into chat. ### Lane A — bring-your-own OAuth 1. Open [Zoom Marketplace → Build an app](https://marketplace.zoom.us/develop/create) and create a **General** OAuth app. 2. Set the **Redirect URL for OAuth** exactly to `https://kody.codes/connect/oauth`. 3. Add the user-level scopes you need (user / meeting / recording / webinar read+write). 4. Connect: ```text https://kody.codes/connect/oauth?provider=zoom&authorizeUrl=https%3A%2F%2Fzoom.us%2Foauth%2Fauthorize&tokenUrl=https%3A%2F%2Fzoom.us%2Foauth%2Ftoken&flow=confidential&scopes=user%3Aread%3Auser%20meeting%3Aread%3Alist_meetings%20meeting%3Aread%3Ameeting%20meeting%3Awrite%3Ameeting%20meeting%3Aupdate%3Ameeting%20meeting%3Adelete%3Ameeting%20cloud_recording%3Aread%3Alist_user_recordings%20cloud_recording%3Aread%3Arecording%20webinar%3Aread%3Alist_webinars%20webinar%3Aread%3Awebinar%20webinar%3Awrite%3Awebinar%20webinar%3Aupdate%3Awebinar%20webinar%3Adelete%3Awebinar&allowedHosts=api.zoom.us%2Czoom.us&apiBaseUrl=https%3A%2F%2Fapi.zoom.us%2Fv2&dashboardUrl=https%3A%2F%2Fmarketplace.zoom.us%2Fdevelop%2Fcreate ``` 5. Paste the client ID and secret into the Kody form, then authorize Zoom. 6. Reconnect later at `https://kody.codes/connect/oauth?provider=zoom`. ### Lane B — Server-to-Server OAuth 1. Create a **Server-to-Server OAuth** app in the Zoom Marketplace, add admin scopes, and **Activate**. 2. Save the client ID and client secret as secrets (approve `api.zoom.us` and `zoom.us`): ```text https://kody.codes/account/secrets/new?name=zoomClientId&description=Zoom%20Server-to-Server%20client%20ID&allowedHosts=api.zoom.us%2Czoom.us&scope=user ``` ```text https://kody.codes/account/secrets/new?name=zoomS2sClientSecret&description=Zoom%20Server-to-Server%20client%20secret&allowedHosts=api.zoom.us%2Czoom.us&scope=user ``` 3. Copy the app's **Account ID** from its App Credentials page. It is an identifier, not a secret, so it is not saved in Kody: pass it as `accountId` on every S2S call. (Zoom's token exchange only accepts the account ID in the form body or query, and Kody only puts secrets in request headers.) `zoomS2sClientSecret` is intentional — do not reuse `zoomClientSecret` from `/connect/oauth`. Call helpers with `auth: 's2s', accountId: ''`. ### Multi-account / mutations / jobs - `account: 'work'` → `zoom-work` (and matching S2S secret suffixes); S2S calls pass that account's `accountId`. - Meeting/webinar writes need `dryRun: true` or `confirm: true`. - `upcoming-meetings` is declared and **disabled by default**. Agents: import paths, smoke snippets, and confirm examples live in [`AGENTS.md`](./AGENTS.md). ## Done when - OAuth connected **or** both S2S secrets saved (and `accountId` passed on S2S calls); hosts `api.zoom.us` / `zoom.us` approved - Smoke / `get-current-user` returns identity without tokens - Meeting/webinar helpers refuse live writes unless `confirm: true`; `dryRun: true` never writes ## Troubleshooting - Redirect URI mismatch: callback must be exactly `https://kody.codes/connect/oauth`. - `401` with OAuth: reconnect at `https://kody.codes/connect/oauth?provider=zoom`. - `401` on S2S: app activated; `accountId` and both secrets from the same app; hosts approved. - Webinar errors: host needs a webinar license and matching scopes. - Mutation-guard errors: pass `dryRun: true` or `confirm: true`. ## Docs - [Using Zoom APIs](https://developers.zoom.us/docs/api/using-zoom-apis/) - [OAuth 2.0](https://developers.zoom.us/docs/integrations/oauth/) - [Server-to-Server OAuth](https://developers.zoom.us/docs/internal-apps/s2s-oauth/) - [Meetings](https://developers.zoom.us/docs/api/meetings/) - [Cloud recordings](https://developers.zoom.us/docs/api/meetings/#tag/cloud-recording) - [Webinars](https://developers.zoom.us/docs/api/rest/reference/zoom-api/methods/#tag/webinars)