Skip to content
Esc
↑↓navigate↵open⌘Jpreview
On this page

Quickstart

Get a Zoom Team Chat bot receiving and sending messages in about ten minutes.

You will need a Zoom account with developer access and somewhere Zoom can reach your app — a deployed URL, or an ngrok tunnel while you are working locally.

Install

pnpm add zoom-chat-adapter chat @chat-adapter/state-memory

chat comes along as a dependency, but install it explicitly: your code imports Chat from it directly. @chat-adapter/state-memory is not a dependency at all, and relying on a transitive copy is fragile.

Collect five credentials

ZOOM_CLIENT_ID=
ZOOM_CLIENT_SECRET=
ZOOM_ACCOUNT_ID=
ZOOM_ROBOT_JID=
ZOOM_WEBHOOK_SECRET_TOKEN=

Marketplace setup shows where each one lives in the Zoom dashboard. All five are required — a missing one stops the app at startup with a message naming the variable.

Create the bot

import { createMemoryState } from "@chat-adapter/state-memory";
import { Chat } from "chat";
import { createZoomAdapter } from "zoom-chat-adapter";

export const bot = new Chat({
  userName: "mybot",
  adapters: { zoom: createZoomAdapter() },
  state: createMemoryState(),
});

bot.onNewMention(async (thread, message) => {
  await thread.post("Hello from Zoom!");
});

A state adapter is not optional: Chat connects to it during initialization and the first webhook crashes without one. In-memory state is fine to start with; swap it for a durable one before you ship.

Add the webhook route

import { after } from "next/server";
import { bot } from "@/lib/bot";

export async function POST(request: Request) {
  return bot.webhooks.zoom(request, { waitUntil: after });
}

Pass the request through untouched and return what comes back. waitUntil (Next.js after, or a Cloudflare ExecutionContext.waitUntil) lets Zoom have its response straight away while your handler keeps working.

Point Zoom at your machine

ngrok http 3000

Use the https:// forwarding URL as both the Bot Endpoint URL and the event subscription URL in your Marketplace app, then @-mention the bot in a channel. A reply in Zoom means all five credentials, the signature check, and your handler are working.

Next

Was this page helpful?