messages and private replies
message access is filtered by author, installation scope, history boundary and audience. writing as a user always retains bot attribution.
message fields
Message has id, chat_id, sequence, revision, kind, author, via_bot, content, created_at, edited_at, reply_to, attachment_ids, audience and expires_at. author is {kind:user|bot,id,display_name,avatar_url}; via_bot is null or {application_id,name}. kind is text, sticker, gif, scribble, attachment, poll, game_invitation or call_notice. unread state and read receipts never appear. optional typed payloads are returned only with their field permissions; use null or omitted fields as documented, not fake empty private data. content is at most 4,000 existing weighted characters. message mutations cannot alter author, audience, kind or chat.
reading and search
messages.read_self and messages.read_others select the author sets. history permits earlier messages only within those sets; search applies the same filters before ranking or counting. no unfiltered totals, match highlights or quoted parent bodies may leak. a bot may GET a message it created through the same installation using the matching send/edit/delete grant for narrow readback, but this exception does not expose reactions, voters, human replies or attachments without their grants. exact user-authored message reads still require messages.read_self even when editing/deleting is allowed.
message routes
actor is required for writes and accepts bot or user; the server chooses the corresponding permission and author. recipient_user_id is not accepted. send permissions are 26/48, edit 28/49 and delete 29/50. a supplied reply_to must identify a readable message in the same chat; public replies cannot reference private messages. message deletion also removes associated placements and attachments only when no other authorized reference retains them.
scroll the table horizontally to see all columns.
| method and path | request | result |
|---|---|---|
| GET /chats/{chat}/messages | before or after cursor, limit | Message list; author/history-filtered |
| GET /chats/{chat}/messages/{id} | none | Message + ETag |
| GET /chats/{chat}/messages/search | q:1–200 chars, cursor, limit | Message list + permitted snippets; messages.search |
| POST /chats/{chat}/messages | actor, content, reply_to?:ID | 201 Message |
| PATCH /chats/{chat}/messages/{id} | actor, content; If-Match | MessageReceipt{id,content,revision,edited_at}; owner-only |
| DELETE /chats/{chat}/messages/{id} | actor in JSON; If-Match | 204; owner-only |
| POST /chats/{chat}/ephemeral-messages | content, expires_in?:60–86400 seconds | 201 private Message; permission 27 |
| PATCH /chats/{chat}/ephemeral-messages/{id} | actor:bot, content; If-Match; bot.messages.edit | private MessageReceipt with expires_at |
| DELETE /chats/{chat}/ephemeral-messages/{id} | actor:bot; If-Match; bot.messages.delete | 204; only this installation’s private message |
| POST /dm | none | 200 Chat; permission 7; idempotent reopen/create |
| GET /chats/{chat}/pins | cursor, limit | Pin list filtered to readable messages |
| PUT /chats/{chat}/pins/{message} | actor | Pin; permission 38/60 |
| DELETE /chats/{chat}/pins/{message} | actor in JSON; If-Match | 204; remove only actor’s pin |
| PUT /chats/{chat}/messages/{id}/reactions/{emoji} | actor | own Reaction receipt; permission 39/61 |
| DELETE /chats/{chat}/messages/{id}/reactions/{emoji} | actor in JSON | 204; remove only actor’s reaction |
ephemeral audience and lifetime
ephemeral messages target only the installation owner, in a chat they can currently access within scope or their permitted bot DM. they use a separate audience-bound store with a default one-hour TTL and a maximum 24-hour TTL. they synchronize to that user’s signed-in devices until expiry or dismissal. show a faint background and the exact faint footer “(only visible to you)”, with accessible text contrast. they never appear in other users’ fanout, search, previews, unread counts, push payloads, exports or quoted messages. they cannot be pinned, reacted to, forwarded, polled or used as scribble anchors. v1 ephemeral content is text/Markdown only; no attachments or embedded remote previews. expiry is checked during reads even before physical cleanup.
ownership and attribution
bot identity is stable per application, with a blue bot tag beside the display name wherever it appears. writes also store originating installation ID. bot edit/delete grants are limited to that installation’s resources. user edit/delete grants cover the installer’s own ordinary messages, including manually written ones. system notices and temporary special editing privileges are never exposed. delegated actions show “via [bot]” in message details or the relevant activity surface; edits retain author identity and show bot edit attribution. no API can erase this provenance.
pins and reactions
Pin is {id,message_id,actor,installation_id?,created_at,revision}; actor contains kind and id. each actor may own a pin association; removing that association does not remove another actor’s pin. Reaction is {message_id,emoji,actor,active,revision}; one application identity has one visible reaction per emoji, with separate installation contributions. removing one contribution leaves the reaction visible while another contribution remains. aggregate reaction views filter identities through normal block rules.