Message schema
A message object is one stored chat message. Message commands and events carry it in message, and history commands return lists of them. Only id, type, user, author_id, content, and timestamp are always present. Every other field appears only when it applies.
{ "id": "b2d4f6a8-1c3e-4a5b-8d7f-0e9c1b2a3d4e", "type": "message", "user": "bob", "author_id": "USR:local_bob", "content": "Agreed, @alice. Shipping it.", "timestamp": 1788177600.412, "reply_to": { "id": "9f3c2a1e-6b1d-4f7a-9c2e-3d4b5a6c7e8f", "user": "alice", "preview": "Should we ship the new theme picker to" }, "ping": true, "pings": { "users": ["alice"], "replies": ["alice"] }, "reactions": { "👍": ["alice", "carol"] }, "edited": true}interface Message { id: string; type: "message"; user: string; author_id: string; content: string; timestamp: number; thread_id?: string; ephemeral?: boolean; edited?: boolean; edited_at?: number; edited_by?: string; pinned?: boolean; reply_to?: { id: string; user: string; preview: string }; ping?: boolean; pings?: { users?: string[]; roles?: string[]; replies?: string[] }; reactions?: Record<string, string[]>; embeds?: Embed[]; attachments?: Attachment[]; alias?: { name: string; avatar?: string; usercolor?: string }; webhook?: { id: string; name: string; avatar: string | null; usercolor?: string }; interaction?: Interaction; signed_at?: number; key_id?: string; signature?: string;}
interface Interaction { username: string; command: string; args?: Record<string, unknown>; author_id?: string; key_id?: string; signature?: string; timestamp?: number; nonce?: string;}Core fields
Section titled “Core fields”| Field | Description |
|---|---|
id |
The message’s ID, a UUID assigned by the server. |
type |
Always "message". |
user |
The author’s username. Messages from webhooks, system announcements, and the server itself use originChats. |
author_id |
The author’s user ID. For a signed message, the Rotur ID in the proof. System and webhook messages use originChats. |
content |
The message text. Can be "" when the message has embeds or attachments. |
timestamp |
When the server saved the message, in Unix seconds with a fraction. |
thread_id |
The thread the message belongs to, for messages in forum threads. |
ephemeral |
true on a private slash command reply that only the invoker sees. Ephemeral messages aren’t stored. |
Edits and pins
Section titled “Edits and pins”| Field | Description |
|---|---|
edited |
true once the message has been edited. Link previews added by the server don’t set it. |
edited_at |
When a signed edit happened, in Unix seconds. Only signed edits set it. |
edited_by |
User ID of the moderator who changed someone else’s signed content. The old signature is removed at the same time. |
pinned |
true while the message is pinned. It can be false after an unpin. |
Replies and mentions
Section titled “Replies and mentions”| Field | Description |
|---|---|
reply_to |
The message this one replies to: its id, its author’s username in user, and the first 40 characters of its text in preview. |
ping |
Present with reply_to. false when the reply was sent with ping: false, so the replied-to author isn’t notified. |
pings.users |
Usernames mentioned with @name. |
pings.roles |
IDs of roles mentioned, when the author was allowed to mention them. |
pings.replies |
The replied-to author’s username, when the reply pings them. |
pings is left out when nothing is mentioned. Clients use it for mention highlights and notifications.
Reactions
Section titled “Reactions”reactions maps each emoji to the usernames that reacted with it. Custom emoji keys use the form originChats:<emoji>//<server>/<id>. The field is left out when there are none. See reactions.
Sender display
Section titled “Sender display”| Field | Description |
|---|---|
webhook |
Set on messages posted through a webhook: the webhook id, and the name, avatar, and optional usercolor to show for this message. |
alias |
A display override the sender chose for this message: name (up to 80 characters), and optional avatar URL (up to 2048) and usercolor (up to 64). Any sender can set it on message_new or message_edit. user still names the real author, so show both. |
interaction |
Set on slash command replies: the command and the invoking user’s username. For signed calls it also has the invoker’s args and proof fields. |
Signature fields
Section titled “Signature fields”Signed messages carry author_id, key_id, signature, and signed_at. The server checks their format but never verifies the signature, so verify it yourself before showing a message as signed. author_id is present on every message, so its presence alone doesn’t mean the message is signed.
Embeds can carry their own author_id, key_id, and signature. They are signed separately from the message.
Attachments
Section titled “Attachments”attachments holds attachment objects. For uploads the server knows, it replaces what the client sent with its stored record.
Embeds
Section titled “Embeds”An embed is a rich block shown with a message, such as a link preview, a card, or a poll.
{ "type": "rich", "title": "Release 2.4", "url": "https://example.com/changelog/2.4", "description": "Faster search and a new theme picker.", "color": 6641909, "author": { "name": "Release bot", "icon_url": "https://example.com/bot.png" }, "fields": [ { "name": "Downloads", "value": "[Windows](https://example.com/win) · [macOS](https://example.com/mac)", "inline": true } ], "image": { "url": "https://example.com/banner.png", "width": 1200, "height": 630 }, "footer": { "text": "Posted automatically" }}| Field | Type | Limits and notes |
|---|---|---|
type |
string | rich (default), poll, link, image, video, audio, or article. |
id |
string | Up to 64 characters. |
title |
string | Up to 256 characters. |
description |
string | Up to 4096 characters. |
url |
string | Link for the title. Required for link embeds. |
canonical_url, timestamp |
string | Free text. timestamp is usually an ISO 8601 date. |
site_name |
string | Up to 2048 characters. |
html |
string | Up to 8192 characters. |
color |
number | A colour from 0 to 16777215 (0xFFFFFF). |
markdown |
boolean | Whether to render text as Markdown. |
generated |
boolean | true on link previews the server created. |
metadata |
object | Free-form data. |
author |
object | name (required, up to 256), url, icon_url, proxy_icon_url. |
footer |
object | text (required, up to 2048), icon_url, proxy_icon_url. |
provider |
object | name (up to 256), url. |
image, thumbnail, video, audio |
media | See below. An image, video, or audio embed requires the matching object. |
images |
media[] | Up to 10 items. |
fields |
object[] | Up to 25 items, each with name (up to 256), value (up to 1024), and optional inline. |
poll |
object | Required for poll embeds. See polls. |
author_id, key_id, signature |
string | Embed signature. Up to 128, 256, and 100 characters. |
A media object needs url. It can also have proxy_url, placeholder, content_type (up to 128), alt (up to 1024), html (up to 8192), and the numbers width, height, placeholder_version, and flags.
Across a whole message:
- At most 10 embeds, and at most one of them a poll.
- Each embed’s visible text must total 6000 characters or fewer. That counts the title, description, field names and values, author name, footer text, provider name, and poll question and options.
Validation errors name the embed, for example Embed 2: fields cannot contain more than 25 items.
To create a poll, send message_new with an embed of type: "poll" and the poll input in poll. The polls concept page describes the input.
In the stored message, the server replaces that input with the live poll, personal to each viewer:
| Field | Description |
|---|---|
id, message_id, channel, thread_id |
Where the poll lives. |
question, options |
The question and its options. The embed’s title is set to the question. |
allow_multiselect |
Whether voters can pick several options. |
created_by |
Username of the poll’s creator. |
created_at, expires_at, ended, ended_at |
Timing and state. |
total_votes |
Number of votes cast across all options. |
results |
One entry per option, with votes, the voters usernames, and voted, whether you picked it. |
user_votes |
Option IDs you voted for. |
See also
Section titled “See also”message_new: send a message.- Messages: how messages, replies, and edits behave.
- Time fields: units for
timestampand related fields.
