Skip to content

Direct messages ​

Manage your DMs: inbox, conversations, search, blocking, and more.

These are the old unencrypted DMs, NOT XChat.

dms.inbox(params?) ​

Get your DM inbox initial state. Uses the v1.1 dm/inbox_initial_state endpoint with the same default query parameters x.com sends (groups, reactions, edits, cards, low quality filtering). Anything in params overrides the defaults.

The result has inbox_initial_state.conversations, entries, users, a cursor for dms.userUpdates, and inbox_timelines with one cursor per inbox (trusted, untrusted, untrusted_low_quality). Each inbox cursor has a status (HAS_MORE or AT_END) and a min_entry_id to pass to dms.inboxTimeline.

x.com sorts conversations into its three tabs like this:

TabRule
Primarytrusted is true
Requeststrusted, low_quality and muted are all false
Hidden requeststrusted is false and low_quality or muted is true
js
const { inbox_initial_state: inbox } = await client.dms.inbox();

dms.inboxTimeline(box, maxId?, params?) ​

Load older conversations of one inbox. Uses the v1.1 dm/inbox_timeline/trusted and dm/inbox_timeline/untrusted endpoints.

ParamTypeDescription
boxstringtrusted (primary), untrusted (requests) or untrusted_low_quality (hidden requests)
maxIdstringThe min_entry_id of the previous page
paramsobjectExtra query parameters

There is no untrusted_low_quality endpoint. Like x.com, hidden requests are read from dm/inbox_timeline/untrusted with include_quality=low, and ordinary requests with include_quality=high.

js
const { inbox_initial_state: inbox } = await client.dms.inbox();
const cursor = inbox.inbox_timelines.untrusted.min_entry_id;
const { inbox_timeline: page } = await client.dms.inboxTimeline("untrusted", cursor);

dms.conversation(conversationId, params?) ​

Get one page of a DM conversation, newest entries first. Uses the v1.1 dm/conversation/<id> endpoint. Pass params.max_id (the min_entry_id of the previous page) to load older entries.

The result is conversation_timeline with entries, users, conversations, min_entry_id, max_entry_id and status (HAS_MORE or AT_END). Message entries carry message_data.reply_data for replies and message_reactions for reactions.

js
const { conversation_timeline: page } = await client.dms.conversation("1234567890-9876543210");
const older = await client.dms.conversation("1234567890-9876543210", { max_id: page.min_entry_id });

dms.send(conversationId, text, opts?) ​

Send a message to an existing conversation. Uses the v1.1 dm/new2 endpoint with a JSON body.

OptionTypeDescription
opts.mediaIdstringOne media id uploaded with media.create(file, { type: "dm" })
opts.replyTostringMessage id to reply to (sent as reply_to_dm_id)
opts.tweetIdstringPost id to share
opts.requestIdstringIdempotency key, a random UUID by default
opts.bodyobjectExtra body fields

Legacy DMs take one attachment per message.

js
const { media_id } = await client.media.create("./cat.png", { type: "dm" });
await client.dms.send("1234567890-9876543210", "look", { mediaId: media_id, replyTo: "1111111111111111111" });

dms.accept(conversationId) ​

Accept a message request. Uses the v1.1 dm/conversation/<id>/accept endpoint.

js
await client.dms.accept("1234567890-9876543210");

dms.leave(conversationId) ​

Delete a conversation from your inbox, or leave a group. x.com uses this to decline a message request. Uses the v1.1 dm/conversation/<id>/delete endpoint.

js
await client.dms.leave("1234567890-9876543210");

dms.markRead(conversationId, eventId) ​

Mark a conversation as read up to a message. Uses the v1.1 dm/conversation/<id>/mark_read endpoint.

js
await client.dms.markRead("1234567890-9876543210", "1111111111111111111");

dms.search(query, opts?) ​

Search across all DM conversations. Uses the GraphQL DmAllSearchSlice query with the message, attachment and highlight variables x.com sends. In September 2026 Twitter answered this query with LoadShed: Unspecified for every account tried, so be ready for it to fail.

OptionTypeDescription
querystringSearch query
opts.countnumberNumber of results (default 20)
opts.cursorstringPagination cursor
opts.variablesobjectAdditional GraphQL variables
js
const results = await client.dms.search("meeting");

dms.searchGroups(query, opts?) ​

Search group DM conversations. Uses the GraphQL DmGroupSearchSlice query.

OptionTypeDescription
querystringSearch query
opts.countnumberNumber of results (default 20)
opts.cursorstringPagination cursor
opts.variablesobjectAdditional GraphQL variables
js
const groups = await client.dms.searchGroups("project");

dms.searchPeople(query, opts?) ​

Search for people in DMs. Uses the GraphQL DmPeopleSearchSlice query.

OptionTypeDescription
querystringSearch query
opts.countnumberNumber of results (default 20)
opts.cursorstringPagination cursor
opts.variablesobjectAdditional GraphQL variables
js
const people = await client.dms.searchPeople("john");

dms.block(userId) ​

Block a user from sending you DMs. Uses the GraphQL dmBlockUser mutation.

js
await client.dms.block("44196397");

dms.unblock(userId) ​

Unblock a user in DMs. Uses the GraphQL dmUnblockUser mutation.

js
await client.dms.unblock("44196397");

dms.deleteConversations(conversationIds) ​

Delete one or more DM conversations. Uses the v1.1 dm/conversation/bulk_delete endpoint.

js
// Single conversation
await client.dms.deleteConversations("1234567890-9876543210");

// Multiple conversations
await client.dms.deleteConversations(["1234567890-9876543210", "1111111111-2222222222"]);

dms.updateLastSeen(eventId) ​

Mark messages as read up to a given event ID. Uses the v1.1 dm/update_last_seen_event_id endpoint.

js
await client.dms.updateLastSeen("1234567890123456789");

dms.muted(opts?) ​

Get your muted DM conversations. Uses the GraphQL DmMutedTimeline query.

OptionTypeDescription
opts.countnumberNumber of results (default 20)
opts.cursorstringPagination cursor
opts.variablesobjectAdditional GraphQL variables
js
const muted = await client.dms.muted();

dms.edit(messageId, conversationId, text) ​

Edit a DM message. Uses the v1.1 dm/edit endpoint.

ParamTypeDescription
messageIdstringThe message ID to edit
conversationIdstringThe conversation ID
textstringNew text for the message
js
await client.dms.edit("111222333", "1234567890-9876543210", "Updated message");

dms.permissions(params?) ​

Check DM permissions. Uses the v1.1 dm/permissions endpoint.

js
const perms = await client.dms.permissions();

dms.nsfwFilter(enabled) ​

Toggle the NSFW media filter for DMs. Uses the GraphQL DmNsfwMediaFilterUpdate mutation.

js
// Enable filter
await client.dms.nsfwFilter(true);

// Disable filter
await client.dms.nsfwFilter(false);

dms.updateRelationship(userId, action) ​

Update your DM relationship state with a user. Uses the v1.1 dm/user/update_relationship_state endpoint.

js
await client.dms.updateRelationship("44196397", "trust");

dms.reportSpam(conversationId, messageId) ​

Report a DM as spam. Uses the v1.1 direct_messages/report_spam endpoint.

js
await client.dms.reportSpam("1234567890-9876543210", "111222333");

dms.report(conversationId, messageId) ​

Report a DM message. Uses the v1.1 dm/report endpoint.

js
await client.dms.report("1234567890-9876543210", "111222333");

dms.userUpdates(params?) ​

Poll for new DM events. Uses the v1.1 dm/user_updates endpoint with the same defaults as dms.inbox. Pass the cursor from dms.inbox (or from the previous poll) to get only what changed since.

js
const { inbox_initial_state: inbox } = await client.dms.inbox();
const { user_events: events } = await client.dms.userUpdates({ cursor: inbox.cursor });

Full example ​

js
// Check your inbox
const inbox = await client.dms.inbox();

// Search for a conversation
const results = await client.dms.search("hello");

// Read a specific conversation
const convo = await client.dms.conversation("1234567890-9876543210");

// Reply to its newest message
const [newest] = convo.conversation_timeline.entries;
await client.dms.send("1234567890-9876543210", "on it", { replyTo: newest.message.id });

// Edit a message
await client.dms.edit("111222333", "1234567890-9876543210", "corrected text");

// Block a spammer in DMs
await client.dms.block("9999999999");

// Check your muted conversations
const muted = await client.dms.muted();

// Clean up old conversations
await client.dms.deleteConversations(["1234567890-9876543210", "1111111111-2222222222"]);

not affiliated with X Corp.