Messages

Messages live under their channel: /v1/channels/:channelId/messages. Content is stored as plain text with inline tokens (no HTML, no rich text); the client resolves tokens at render time.


The Message object

  • Name
    id
    Type
    string
    Description

    Snowflake.

  • Name
    channel_id
    Type
    string
    Description
  • Name
    author_id
    Type
    string
    Description
  • Name
    content
    Type
    string
    Description

    1–4000 chars. Plain text containing the inline token syntax.

  • Name
    edited_at
    Type
    string | null
    Description

    Independent timestamp so the UI can render an "edited" indicator without collapsing the row.

  • Name
    deleted_at
    Type
    string | null
    Description

    Soft delete. The row keeps its id so replies and references don't dangle; the UI renders a [deleted] placeholder.

  • Name
    created_at
    Type
    string
    Description
  • Name
    updated_at
    Type
    string
    Description

Hydration fields the API attaches on the wire:

  • Name
    author
    Type
    PublicUser
    Description

    Embedded user row.

  • Name
    type
    Type
    MessageType
    Description
  • Name
    attachments
    Type
    Attachment[]
    Description
  • Name
    message_reference
    Type
    { message_id, channel_id } | null
    Description

    Reply target.


List messages

Keyset-paginated. No offset, no total — just the next page key.

  • Name
    limit
    Type
    integer
    Description

    1–100. Default 50.

  • Name
    before
    Type
    string
    Description

    Snowflake id. Returns messages strictly before this one, newest first.

Request

GET
/v1/channels/:channelId/messages
curl https://api.localuniverse.io/v1/channels/3123.../messages?limit=50 \
  -H "authorization: <token>"

Create a message

  • Name
    content
    Type
    string
    Description

    1–4000 chars. May contain inline tokens.

  • Name
    nonce
    Type
    ?string
    Description

    Client-generated optimistic id. The server echoes it on the HTTP response and on the MESSAGE_CREATE gateway dispatch so the author can reconcile its pending row with the canonical message_id. Recipients with no matching pending row ignore it.

  • Name
    flags
    Type
    ?integer
    Description

    Bitfield.

  • Name
    message_reference_id
    Type
    ?string
    Description

    Id of the message this is replying to. Must live in the same channel.

Request

POST
/v1/channels/:channelId/messages
curl -X POST https://api.localuniverse.io/v1/channels/3123.../messages \
  -H "authorization: <token>" \
  -H "content-type: application/json" \
  -d '{
    "content": "hey <@312323...>, see <#9999...>",
    "nonce": "9182374ab"
  }'

The same payload is dispatched over the Gateway as MESSAGE_CREATE to every subscriber of the channel. See Gateway events.


Read, edit, delete

MethodPathNotes
GET/v1/channels/:channelId/messages/:messageIdSingle message.
PATCH/v1/channels/:channelId/messages/:messageIdEdit content. Author only. Stamps edited_at.
DELETE/v1/channels/:channelId/messages/:messageIdSoft delete. Author can always delete; non-authors need channel.manage_messages.

Inline tokens

User-authored text supports a small token syntax for entity references. The database stores raw tokens; the client resolves them at render time using local cache or fetches as needed.

TokenRenders as
<@USER_ID>@display name, clickable
<#CHANNEL_ID>#channel name, linked
<est:ESTIMATE_ID>Linked estimate reference
<item:ITEM_ID>Linked item reference
<t:UNIX_SECONDS>Localized date/time
<t:UNIX_SECONDS:STYLE>Date/time formatted per style flag

Timestamp styles:

StyleOutput
d04/10/2026
DApril 10, 2026
t2:30 PM
T2:30:00 PM
fApril 10, 2026 2:30 PM (default)
FSaturday, April 10, 2026 2:30 PM
R3 hours ago

Was this page helpful?