Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

bot.direct

The bot.direct API handles everything related to private conversations between your bot and users outside of the room. Unlike whispers which happen inside a room, direct messages exist across the entire Highrise platform. A user can message your bot from anywhere and your bot can reply back to that same conversation thread.

What lives on bot.direct

bot.direct.conversations    // list conversations, leave conversations
bot.direct.messages         // fetch message history from a conversation
bot.direct.send()           // send a message to a conversation
bot.direct.broadcast()      // send the same message to multiple users
bot.direct.inviteRoom()     // invite a user to a room
bot.direct.inviteWorld()    // invite a user to a world
bot.direct.broadcastInvite() // invite multiple users at once

This is a larger API than bot.message or bot.whisper. Take it one method at a time.

send()

Sends a direct message to an existing conversation.

await bot.direct.send(convId, 'Hey! I got your message.');
ParameterTypeDescription
convIdstringThe conversation ID from the Direct event
messagestringThe text you want to send

Returns: AcknowledgmentResponse

Where to get the conversation ID

The Direct event gives you the conversation object which contains the ID:

bot.on('Direct', async (user, message, conversation) => {
    const convId = conversation.id;

    await bot.direct.send(convId, 'Thanks for reaching out!');
});

Always use the conversation.id from the event itself or save it for later usage. Do not try to construct one manually.

broadcast()

Sends the same direct message to multiple users at once.

await bot.direct.broadcast(
    ['user_id_1', 'user_id_2', 'user_id_3'],
    'Your daily reward is ready!'
);
ParameterTypeDescription
userIdsstring[]Array of user IDs (1-100 users)
messagestringThe text you want to send

Returns: AcknowledgmentResponse

When to use broadcast

Use this when you need to notify multiple users of the same thing. Examples include event announcements, reward distributions, or system alerts. Keep the list under 100 users per call.

inviteRoom()

Invites a user to a specific room through a direct message conversation.

await bot.direct.inviteRoom(convId, 'room_id_here');
ParameterTypeDescription
convIdstringThe conversation ID
roomIdstringThe ID of the room to invite them to

Returns: AcknowledgmentResponse

inviteWorld()

Invites a user to a specific 3D world through a direct message conversation.

await bot.direct.inviteWorld(convId, 'world_id_here');
ParameterTypeDescription
convIdstringThe conversation ID
worldIdstringThe ID of the world to invite them to

Returns: AcknowledgmentResponse

broadcastInvite()

Sends the same room or world invite to multiple users.

await bot.direct.broadcastInvite(
    ['user_id_1', 'user_id_2'],
    { roomId: 'room_id_here' }
);

// or for a world
await bot.direct.broadcastInvite(
    ['user_id_1', 'user_id_2'],
    { worldId: 'world_id_here' }
);
ParameterTypeDescription
userIdsstring[]Array of user IDs (1-100 users)
inviteDetailsobjectEither { roomId: string } or { worldId: string }

Returns: AcknowledgmentResponse

conversations.list()

Fetches a list of the bot’s direct message conversations.

const inbox = await bot.direct.conversations.list();

// with pagination
const nextPage = await bot.direct.conversations.list(lastId);

// including conversations the bot hasn't joined yet
const withUnjoined = await bot.direct.conversations.list(null, true);
ParameterTypeDescription
lastIdstring | nullCursor for pagination, fetches next 20 conversations
notJoinedbooleanInclude conversations the bot hasn’t joined (default: false)

Returns: GetConversationsResponse

Pagination

The response includes a .next() method for fetching the next page:

const inbox = await bot.direct.conversations.list();

if (inbox.ok) {
    console.log(`Found ${inbox.conversations.length} conversations`);

    // fetch the next 20 conversations
    if (inbox.next) {
        const nextPage = await inbox.next();
        console.log(`Next page has ${nextPage.conversations.length} more`);
    }
}

conversations.leave()

Removes the bot from a conversation.

await bot.direct.conversations.leave(convId);
ParameterTypeDescription
convIdstringThe conversation ID to leave

Returns: AcknowledgmentResponse

messages.list()

Fetches message history from a specific conversation.

const messages = await bot.direct.messages.list(convId);

// with pagination
const olderMessages = await bot.direct.messages.list(convId, lastMessageId);
ParameterTypeDescription
convIdstringThe conversation ID
lastMessageIdstringOptional cursor for older messages

Returns: GetMessagesResponse

Pagination

Works the same as conversations:

const response = await bot.direct.messages.list(convId);

if (response.ok) {
    console.log(`Loaded ${response.messages.length} messages`);

    // fetch older messages
    if (response.next) {
        const older = await response.next();
        console.log(`Found ${older.messages.length} older messages`);
    }
}

Complete example

Here is a Direct handler that responds to commands and uses several parts of the API:

bot.on('Direct', async (user, message, conversation) => {
    const cmd = message.command();
    const convId = conversation.id;

    if (cmd === '!ping') {
        await bot.direct.send(convId, 'Pong! 🏓');
        return;
    }

    if (cmd === '!invite') {
        const roomId = message.args(0);

        if (!roomId) {
            await bot.direct.send(convId, 'Usage: !invite <roomId>');
            return;
        }

        const result = await bot.direct.inviteRoom(convId, roomId);

        if (!result.ok) {
            await bot.direct.send(convId, 'Could not send that invite.');
            return;
        }

        await bot.direct.send(convId, 'Invite sent!');
        return;
    }

    if (cmd === '!broadcast') {
        const text = message.args().join(' ');

        // in a real bot you would get these IDs from somewhere
        const userIds = ['user1', 'user2', 'user3'];

        await bot.direct.broadcast(userIds, text);
        await bot.direct.send(convId, `Broadcast sent to ${userIds.length} users.`);
        return;
    }
});

Response Types

AcknowledgmentResponse

Returned by send(), broadcast(), inviteRoom(), inviteWorld(), broadcastInvite(), and conversations.leave():

{
    ok: boolean;
    error: string | null;
    hasError(): boolean;
}

GetConversationsResponse

Returned by conversations.list():

{
    ok: boolean;
    error: string | null;
    hasError(): boolean;

    conversations: Conversation[];  // array of conversation objects
    notJoined: number;              // count of unjoined conversations
    recentMessage: MessageSummary | null;
    lastId: string | null;          // cursor for next page
    next(): GetConversationsResponse | null;
}

GetMessagesResponse

Returned by messages.list():

{
    ok: boolean;
    error: string | null;
    hasError(): boolean;
    messages: MessageSummary[];     // array of message objects
    recentMessage: MessageSummary | null;
    lastId: string | null;          // cursor for next page
    next(): GetMessagesResponse | null;
}

Important things to know

Conversation IDs come from the Direct event. Always use conversation.id from the event handler. Do not guess or construct IDs.

Broadcast is limited to 100 users per call. If you need to message more than 100 users, split them into batches and call broadcast() multiple times.

Messages over 2000 characters are split automatically. The same behavior as bot.message.send() applies here.

Leaving a conversation is permanent. Once the bot leaves, it cannot message that user again unless the user starts a new conversation.

Username is always null in Direct events. The Direct event only provides the user ID. If you need the username, you must look it up separately using bot.room.users.find() if they are in the room.

Summary

  • bot.direct.send(convId, message) replies to a DM conversation
  • bot.direct.broadcast(userIds, message) messages up to 100 users at once
  • bot.direct.conversations.list() fetches the bot’s inbox with pagination
  • bot.direct.messages.list(convId) fetches message history from a conversation
  • bot.direct.inviteRoom() and bot.direct.inviteWorld() send invites
  • Always get the conversation ID from the Direct event
  • All send methods return AcknowledgmentResponse
  • List methods return responses with built-in .next() pagination