# @kody/zoom — agent notes Human setup and intent live in [`README.md`](./README.md). This file is for agents: imports, smoke/dryRun execute snippets, and edge cases. Secrets by **name** only — never paste client secrets. Do not disable live webhooks or jobs (the `upcoming-meetings` job stays **disabled by default** unless an operator explicitly enables it). ## Auth / secrets / integrations | Lane | Credential | Notes | | --- | --- | --- | | User OAuth | integration `zoom` or `zoom-*` | BYO General OAuth app; `me` works for connected user | | Server-to-Server | secrets `zoomClientId`, `zoomS2sClientSecret` + plain `accountId` param | Pass `auth: 's2s'` and `accountId` (required, not a secret); ignores `integrationName` | Hosts: `api.zoom.us`, `zoom.us`. There is no built-in Zoom platform app. Multi-account: `account: 'work'` → `zoom-work` / `zoomClientId-work` / `zoomS2sClientSecret-work`; `integrationName: 'zoom-work'`; S2S overrides via `clientIdSecret` / `clientSecretSecret`. S2S always needs that app's `accountId` (the Zoom token exchange takes it in the form body, where Kody never substitutes secrets, so it is a typed input rather than a secret). Do **not** reuse `zoomClientSecret` (OAuth connect may store that) for S2S — use `zoomS2sClientSecret`. ## Import paths | Export | Import | | --- | --- | | overview | `kody:@kody/zoom` | | accounts | `kody:@kody/zoom/accounts` | | get-current-user | `kody:@kody/zoom/get-current-user` | | smoke-test | `kody:@kody/zoom/smoke-test` | | request / paginate | `kody:@kody/zoom/request` / `.../paginate` | | users/list / users/get | `kody:@kody/zoom/users/list` / `.../users/get` | | meetings/* | `kody:@kody/zoom/meetings/list` (get/create/update/delete) | | recordings/* | `kody:@kody/zoom/recordings/list` / `.../recordings/get` | | webinars/* | `kody:@kody/zoom/webinars/list` (get/create/update/delete) | | scheduled-upcoming-meetings | `kody:@kody/zoom/scheduled-upcoming-meetings` | | types | `kody:@kody/zoom/types` | Prefer static `kody:@kody/zoom/...` imports from `execute`. Do not lead with `packages.invoke`. ## Smoke tests (read-only) ```ts import smokeTest from 'kody:@kody/zoom/smoke-test' export default async function main() { return await smokeTest() // without creds => { ok: true, live: false, setup URLs } // with OAuth/S2S => live /users/me without tokens } ``` Identity (OAuth): ```ts import getZoomCurrentUser from 'kody:@kody/zoom/get-current-user' export default async function main() { return await getZoomCurrentUser() } ``` Identity (S2S): ```ts import getZoomCurrentUser from 'kody:@kody/zoom/get-current-user' export default async function main(params: { accountId: string }) { return await getZoomCurrentUser({ auth: 's2s', accountId: params.accountId }) } ``` ## dryRun / confirm Create / update / delete for meetings and webinars — and REST methods other than `GET` / `HEAD` / `OPTIONS` — require `dryRun: true` (preview) or `confirm: true` (live). Do not create a live meeting from a smoke test. ```ts import createZoomMeeting from 'kody:@kody/zoom/meetings/create' export default async function main() { return await createZoomMeeting({ topic: 'Example meeting', type: 2, start_time: '2030-01-15T17:00:00', duration: 30, timezone: 'UTC', dryRun: true, }) } ``` ## Edge cases / fork notes - Meeting locators: `meetingId` / `meeting_id` / `id` or `meetingUrl: 'https://zoom.us/j/…'`. Webinars: `webinarId` or `https://zoom.us/w/{id}`. - `./users/list` needs account-level / admin scope (`user:read:list_users:admin`); user-managed OAuth often cannot list the whole account — prefer S2S. - Webinar writes need a webinar license plus matching webinar scopes. - Pass meeting/webinar ids at call time — never hard-code personal aliases. - After fork, connect **your** Zoom — do not treat live `@kody/zoom` as a shared calendar. Keep `dryRun` / `confirm` guards. - Do **not** enable the `upcoming-meetings` job unless the operator asks.