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

API reference

Everything the package exports, what each method does, and what it returns or throws.

The package is ESM only and runs on Node. It uses node:crypto and the global fetch, Request, and Response.

import {
  createZoomAdapter,
  ZoomAdapter,
  type ZoomAdapterConfig,
  type ZoomThreadId,
  type ZoomMessageWithReply,
  type ZoomWebhookPayload,
  type ZoomCrcPayload,
  type ZoomBotNotificationPayload,
  type ZoomAppMentionPayload,
} from "zoom-chat-adapter";

createZoomAdapter(config?)

Builds an adapter, filling anything you leave out from the environment. Prefer it over constructing the class: it is where the credential checks live.

const adapter = createZoomAdapter(); // everything from the environment

Each missing credential throws a ValidationError naming the variable to set, at construction time rather than on the first webhook. See Configuration for the full list.

ZoomAdapter

The class behind the factory. Construct it directly only if you already have a fully resolved config, including a logger.

Property Value
name "zoom"
lockScope "thread" — one message at a time per thread
userName The bot’s name, "zoom-bot" unless you set one

handleWebhook(request, options?)

Takes the untouched Request and returns the Response to send back. Answers the setup challenge, verifies the signature, and dispatches the event. With options.waitUntil, processing continues after the response is sent. See Webhooks.

postMessage(threadId, message)

Sends a message to the thread’s channel or DM and resolves to { id, raw, threadId }, where id is Zoom’s message ID. Accepts the standard postable message, plus metadata.replyTo to reply under a parent message. Markdown is converted to Zoom’s dialect and sent with is_markdown_support: true unless markdownSupport is false; { ast } messages are used directly rather than serialized and re-parsed. An empty message is not sent.

editMessage(threadId, messageId, message)

Replaces the content of a message the bot sent, using the same conversion as postMessage. Zoom answers 204 No Content, so the result carries the messageId you passed and an empty body.

deleteMessage(threadId, messageId)

Deletes a message the bot sent. Resolves to nothing.

startTyping(threadId, status?)

Does nothing, quietly. Zoom Team Chat has no typing-indicator API, and the call exists so shared code does not have to special-case Zoom.

encodeThreadId(platformData) · decodeThreadId(threadId)

Convert between { channelId, messageId } and the zoom:… string. See Thread IDs for the exact failure cases.

isDM(threadId)

true unless the channel JID ends in @conference.xmpp.zoom.us.

channelIdFromThreadId(threadId)

Returns the channel-level thread ID — zoom:{channelId} — which is what you post a new message to.

renderFormatted(content)

Renders a Chat formatted-content tree to the Zoom Markdown dialect used on the wire: *bold* (single asterisk — **bold** renders as plain text), _italic_, ~strikethrough~, label <https://url>, <img:url|alt>, and • bullets. Underline becomes plain text because Zoom has no underline token.

getAccessToken()

Returns a Server-to-Server OAuth token, fetched with the client_credentials grant and cached in memory until a minute before it expires. A failed fetch throws an AuthenticationError carrying the HTTP status. Keep one adapter instance alive rather than constructing one per request, so the cache is worth having.

Methods that throw

fetchMessages, fetchThread, addReaction, removeReaction, and parseMessage throw NotImplementedError with the operation name. Zoom’s chatbot API offers no message history and no bot reactions; parseMessage is simply not built, since incoming messages arrive parsed.

Types

Type What it describes
ZoomAdapterConfig The factory’s options, all optional
ZoomThreadId { channelId, messageId }
ZoomMessageWithReply A postable message carrying metadata.replyTo
ZoomWebhookPayload Any webhook body, discriminated on event
ZoomCrcPayload The setup challenge
ZoomBotNotificationPayload A DM, slash command, or message to the bot
ZoomAppMentionPayload An @-mention in a channel

What the message events carry

bot_notification gives you the text as payload.cmd, the conversation JID as payload.toJid, the sender as payload.userJid / payload.userId / payload.userName, and the event time as event_ts — which also becomes the thread’s message ID. payload.channelName is absent for DMs.

team_chat.app_mention nests its content under payload.object: message_id, channel_id, channel_name, message, and timestamp. The sender is payload.operator (an email address) and payload.operator_id.

Both arrive at your handlers as an ordinary Chat Message, with the original payload on message.raw if you need a field the adapter does not map.

Was this page helpful?