Skip to main content

Post an ephemeral message

POST 

/chat.postEphemeral

Post an ephemeral message — visible to a single member of a chat, with an "Only you can see this" header — without posting anything the other members can see. This is the standard way for a bot to respond privately in a shared channel (the Roam equivalent of Slack's chat.postEphemeral).

The target userId must be a member of the chat (for channels: a member of the backing group), otherwise the request fails with user_not_in_chat.

text is always rendered as GitHub-flavored markdown. Mention markup (<@USER_ID>) is not supported in ephemeral messages. Block Kit blocks are not currently supported.

Delivery semantics — read before using:

  • Desktop and web only. Mobile clients do not display ephemeral messages, and no mobile push notification is sent. A recipient who only uses Roam on mobile will never see the message.
  • Best-effort, at-most-once. The message is delivered in real time to the recipient's connected clients, and to recently-active offline clients when they reconnect. A recipient who has been offline for several days (or has never signed in on that device) silently misses it. There are no retries and no delivery receipt.
  • Transient. The message is never stored server-side. It disappears when the recipient restarts their app, and it never appears in /chat.history or /chat.search.
  • Not addressable. It cannot be edited or deleted: /chat.update and /chat.delete against its (chatId, timestamp) return message_not_found.
  • No webhooks. Posting an ephemeral message never triggers a chat.message event, so it cannot leak to org-wide webhook consumers.

Do not use ephemeral messages for anything the recipient must durably receive — use a DM (/chat.post with userIds) for that.

Custom sender (optional): same semantics as /chat.postsender.name / sender.imageUrl apply a per-message display override, and sender.id authors the message as a configured bot persona (unknown ids are accepted and ignored). Personal access tokens reject the sender field. See the Sender Profiles guide.

Required scope: chat:send_message or chat:write

Access: Organization and Personal. The organization bot or personal-token owner must be a member of the chat (403 not_in_chat otherwise) — unlike /chat.post, there is no public-group carveout. Personal tokens send as the user's personal bot and reject the sender field.


OpenAPI Spec: chat-v1.json

Request

Responses

Ephemeral message accepted for delivery. The (chatId, timestamp) pair is the identity the recipient's client renders the message under; it is not addressable by any other endpoint. All success bodies include "ok": true — see Responses and Errors.