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

Formatting

How your markdown reaches Zoom — the tokens that render, the ones Zoom cannot carry, and the structured fallback.

Zoom Team Chat accepts two kinds of message body: structured segments (plain text plus a per-segment bold or italic flag), and Markdown, which you turn on per message with is_markdown_support: true.

The adapter uses Markdown by default, because it is the only mode that can render links, strikethrough, block quotes, and images. Markdown mode also makes Zoom ignore the structured style field, so everything you want to see has to live in the text itself.

The same message, three ways

You write (Chat SDK markdown)

**Deploy finished**

Shipped `api-gateway` to _production_ in 94s.

Zoom receives

*Deploy finished*

Shipped `api-gateway` to _production_ in 94s.

Zoom shows

Deploy finished

Shipped api-gateway to production in 94s.

What reaches Zoom

What you write What the adapter sends What Zoom renders
**bold** *bold* Bold
_italic_ _italic_ Italic
`code` `code` Monospace
~strikethrough~ ~strikethrough~ Strikethrough
> quote > quote Indented, italic (Zoom’s quote style)
[label](https://example.com) label <https://example.com> Label plus a clickable URL
![alt](https://example.com/a.png) <img:https://example.com/a.png|alt> The image, if its host is trusted
# Heading *Heading* A bold line — Zoom has no heading token
- item or * item • item A bullet line
__underline__ underline Plain text — Zoom has no underline token
A table Pipe-separated rows, bold header Plain text rows — Zoom has no table token

Code spans and fenced blocks are protected while the rest is converted, so code that merely looks like ~strike~ or __underline__ is left exactly as written. An empty message is never sent, because the Zoom API rejects empty content.

Bold is a single asterisk

This is the one place where Zoom’s documentation contradicts itself. Its chatbot Markdown page shows **bold** in the syntax table but *bold* in the request example. The live client follows the example:

Token Result
*bold* bold
***bold*** bold
_italic_ italic
~strike~ strike
**bold** plain text
__underline__ plain text

So **bold** in your Chat SDK markdown arrives at Zoom as *bold*. If you write the Zoom token directly, remember that *text* means emphasis in standard Markdown, so the adapter will read it as italic. Write standard Markdown and let the converter translate.

A markdown link keeps its label and makes the URL clickable:

See [the docs](https://example.com) for more

arrives as See the docs <https://example.com> for more. Zoom documents the bare <url> form; the labelled form also works in current clients.

Images need a trusted host

The image token is sent correctly, but the Zoom client only renders images from domains it trusts. Images from other hosts are dropped client-side, with a [Security] Blocked image from untrusted domain warning in the browser console. Add the host to your app’s trusted-domain list, or use one Zoom already trusts, such as developers.zoom.us.

This is a Zoom client rule. The adapter cannot override it.

Structured fallback

Set markdownSupport: false (or ZOOM_MARKDOWN_SUPPORT=false) to send structured segments instead:

createZoomAdapter({ markdownSupport: false });

That mode bolds a paragraph only when the whole paragraph is bold, including a whole bold heading. Inline bold and italic are flattened, and links, strikethrough, block quotes, and images keep their text but lose their formatting. See Configuration for the option and its environment variable.

Reading an incoming message

Incoming text is parsed with Zoom’s own conventions:

Token Meaning
__text__ Underline, not bold
~text~ Strikethrough with a single tilde

Everything else — **bold**, _italic_, `code`, # headings, * lists — is standard. message.text holds the raw text the person typed, and message.formatted holds the parsed tree.

Was this page helpful?