Skip to content

message_new

message_new posts a message. It can carry text, embeds, attachments, or any mix of them, and can reply to another message. The same command name is used for the event that tells everyone about the new message.

{
"cmd": "message_new",
"channel": "general",
"content": "Release notes are up: https://example.com/changelog",
"reply_to": "0b6c7f55-4a0f-4f7e-9a53-1a8b0d3d52c1",
"ping": false
}
Field Type Required Description
channel string One of channel or thread_id Channel name. Must be a text or voice channel.
thread_id string One of channel or thread_id Thread ID. Required for forum channels. If you also send channel, it must be the thread’s parent.
content string See below Message text. At most limits.post_content characters (from the handshake; 2000 by default).
embeds array See below Up to 10 embed objects. At most one can be a poll.
attachments array See below Objects with the id of a file you uploaded first. See uploading attachments.
reply_to string No ID of a message in the same channel or thread to reply to.
ping boolean No Set false so a reply does not notify the author of the original message. Defaults to true.
alias object No Show a different name on this message: name (required, up to 80 characters), avatar (URL, up to 2048 characters), and usercolor (up to 64 characters). An empty object means no alias.
author_id string No Signing field. Your own user ID.
key_id string No Signing field. Your Rotur signing key ID, starting with rotur_sk_.
signature string No Signing field. The signature, 80 to 100 characters.
timestamp number No Signing field. When you signed, in Unix seconds. Must be within 5 minutes of the server clock.

The message must have non-empty content, at least one embed, or at least one attachment.

  • Attachments. The server replaces each known attachment ID with the stored attachment record. It keeps width and height from your object if they are numbers. An ID it doesn’t know is saved exactly as you sent it.
  • Polls. To create a poll, add an embed with "type": "poll" and a poll object. The server creates the poll and replaces the embed’s poll with { "id": "<poll id>" }. See polls.
  • Signing. Rotur accounts can sign messages so other clients can prove who wrote them. Send all four signing fields together. The server checks their format and the time window, then stores them on the message. Server-local accounts can’t sign; the server ignores these fields for them. See signing.
  • Mentions. Write @username to mention a user and @&role to mention a role. You can only mention roles you are allowed to mention.

The server sends this event to you and to every other connection that can view the channel:

{
"cmd": "message_new",
"channel": "general",
"message": {
"id": "7d0e4c1a-5b8f-4b0e-8f55-2d3c9a61e7b4",
"user": "alice",
"author_id": "<alice's user ID>",
"timestamp": 1788940000.31,
"content": "Release notes are up: https://example.com/changelog",
"reply_to": {
"user": "bob",
"id": "0b6c7f55-4a0f-4f7e-9a53-1a8b0d3d52c1",
"preview": "When do the release notes go out?"
},
"ping": false
}
}
  • message is the saved message object. Store its id; the server makes it, not you.
  • A thread message has thread_id on both the frame and the message, and channel is the thread’s parent.
  • reply_to.preview is the first 40 characters of the original message.
  • Only your copy carries your request’s listener. Users severed from you don’t receive the event. A moderator can sever two users with the /sever slash command so they no longer see each other.

Some messages cause more frames after message_new:

  • Sticky message. If the channel has a sticky message (set with the built-in /sticky slash command), a new channel message moves it to the bottom. Everyone who can view the channel gets message_delete with the sticky message’s id, then message_new with the sticky message and a newer timestamp. This doesn’t happen for thread messages.
  • Archived thread. Posting in an archived thread unarchives it.
  • Push notifications. If the server has push notifications set up, it queues them for the message’s recipients. They go out through the push service, not the WebSocket. See notifications.
  • Link previews. See below.

When the handshake capabilities include server_side_embeds, the server builds link previews in the background. It looks at up to five http or https URLs in content. It skips URLs inside code blocks, inline code, and angle brackets such as <https://example.com>. Direct links to images, video, and audio become media embeds. For other pages, the server reads the page’s title, description, and image.

If this changes the message’s embeds, the server saves them and sends message_edit to every connection that can view the channel and reported the server_side_embeds capability:

{
"cmd": "message_edit",
"id": "7d0e4c1a-5b8f-4b0e-8f55-2d3c9a61e7b4",
"channel": "general",
"message": {
"id": "7d0e4c1a-5b8f-4b0e-8f55-2d3c9a61e7b4",
"user": "alice",
"author_id": "<alice's user ID>",
"timestamp": 1788940000.31,
"content": "Release notes are up: https://example.com/changelog",
"embeds": [
{
"id": "3f786850e387550fda",
"type": "link",
"url": "https://example.com/changelog",
"generated": true,
"title": "Changelog",
"description": "Everything new in this release."
}
]
}
}
  • A thread message’s frame also has thread_id.
  • Generated embeds have "generated": true. Your own embeds stay first, and the total never goes above 10.
  • The message is not marked as edited.
  • The same process runs after a message_edit that changes the content. Removing a link removes its preview.
  • Previews are best effort. The server skips private network addresses, gives up on slow pages, and drops the job if its queue is full.

Your roles must allow view and send in the channel. In a thread you need the same on the parent channel, and the thread must be unlocked.

Slow mode applies when the channel has a slow_mode_cooldown. Admins and users with the manage_server permission are exempt. A user in a timeout can’t send messages.

val When
Channel not found The channel doesn’t exist, or you sent neither channel nor thread_id.
Thread not found No thread has this ID.
Thread does not belong to this channel channel is not the thread’s parent.
Messages must be sent inside a thread in forum channels channel is a forum and you sent no thread_id.
This channel does not support chat channel is a separator.
Access denied to this channel You can’t view the channel.
You do not have permission to send messages in this channel You can’t send in the channel.
You do not have permission to send messages in this thread You can’t view or send in the parent channel, or the thread is locked.
Signed message author does not match the authenticated user author_id is not your user ID.
Message signature is invalid key_id doesn’t start with rotur_sk_, or signature is not 80 to 100 characters.
Message signed timestamp is outside the allowed window timestamp is more than 5 minutes from the server clock.
Cannot have more than 10 embeds embeds has more than 10 items.
A message can only contain one poll More than one embed has "type": "poll".
Embed <n>: <problem> Embed number n (counting from 1) is invalid. See the message schema for embed rules.
Attachment <n>: id is required Attachment number n has no id.
alias.name is required alias has fields but no name. Other alias. messages report a wrong type or length.
Attachment storage is unavailable The server could not read its attachment records.
Attachment <id> not found or expired The attachment has expired or its file is gone.
Message must have content, attachments, or embeds The message would be empty.
You do not have permission to mention the '@&<role>' role You mentioned a role you can’t mention.
Message too long. Maximum length is <n> characters content is longer than limits.post_content.
Replied message not found reply_to is not a message in this channel or thread.
Message blocked by automod Automod matched the message. You may also be put in a timeout.
Unable to save message The server could not save the message.

Invalid poll data returns the poll validation message. A field with the wrong type returns a validation message.

Slow mode returns a rate_limit frame instead of an error:

{
"cmd": "rate_limit",
"reason": "Slow mode is active in this channel. Wait 3.2 more seconds before sending another message.",
"length": 3200,
"cooldown": 10,
"last_message_timestamp": 1788939996.8
}

length is the wait in milliseconds. A user in a timeout also gets a rate_limit frame; see the protocol model.