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:
| Tab | Rule |
|---|---|
| Primary | trusted is true |
| Requests | trusted, low_quality and muted are all false |
| Hidden requests | trusted is false and low_quality or muted is true |
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.
| Param | Type | Description |
|---|---|---|
box | string | trusted (primary), untrusted (requests) or untrusted_low_quality (hidden requests) |
maxId | string | The min_entry_id of the previous page |
params | object | Extra 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.
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.
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.
| Option | Type | Description |
|---|---|---|
opts.mediaId | string | One media id uploaded with media.create(file, { type: "dm" }) |
opts.replyTo | string | Message id to reply to (sent as reply_to_dm_id) |
opts.tweetId | string | Post id to share |
opts.requestId | string | Idempotency key, a random UUID by default |
opts.body | object | Extra body fields |
Legacy DMs take one attachment per message.
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.
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.
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.
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.
| Option | Type | Description |
|---|---|---|
query | string | Search query |
opts.count | number | Number of results (default 20) |
opts.cursor | string | Pagination cursor |
opts.variables | object | Additional GraphQL variables |
const results = await client.dms.search("meeting");dms.searchGroups(query, opts?)
Search group DM conversations. Uses the GraphQL DmGroupSearchSlice query.
| Option | Type | Description |
|---|---|---|
query | string | Search query |
opts.count | number | Number of results (default 20) |
opts.cursor | string | Pagination cursor |
opts.variables | object | Additional GraphQL variables |
const groups = await client.dms.searchGroups("project");dms.searchPeople(query, opts?)
Search for people in DMs. Uses the GraphQL DmPeopleSearchSlice query.
| Option | Type | Description |
|---|---|---|
query | string | Search query |
opts.count | number | Number of results (default 20) |
opts.cursor | string | Pagination cursor |
opts.variables | object | Additional GraphQL variables |
const people = await client.dms.searchPeople("john");dms.block(userId)
Block a user from sending you DMs. Uses the GraphQL dmBlockUser mutation.
await client.dms.block("44196397");dms.unblock(userId)
Unblock a user in DMs. Uses the GraphQL dmUnblockUser mutation.
await client.dms.unblock("44196397");dms.deleteConversations(conversationIds)
Delete one or more DM conversations. Uses the v1.1 dm/conversation/bulk_delete endpoint.
// 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.
await client.dms.updateLastSeen("1234567890123456789");dms.muted(opts?)
Get your muted DM conversations. Uses the GraphQL DmMutedTimeline query.
| Option | Type | Description |
|---|---|---|
opts.count | number | Number of results (default 20) |
opts.cursor | string | Pagination cursor |
opts.variables | object | Additional GraphQL variables |
const muted = await client.dms.muted();dms.edit(messageId, conversationId, text)
Edit a DM message. Uses the v1.1 dm/edit endpoint.
| Param | Type | Description |
|---|---|---|
messageId | string | The message ID to edit |
conversationId | string | The conversation ID |
text | string | New text for the message |
await client.dms.edit("111222333", "1234567890-9876543210", "Updated message");dms.permissions(params?)
Check DM permissions. Uses the v1.1 dm/permissions endpoint.
const perms = await client.dms.permissions();dms.nsfwFilter(enabled)
Toggle the NSFW media filter for DMs. Uses the GraphQL DmNsfwMediaFilterUpdate mutation.
// 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.
await client.dms.updateRelationship("44196397", "trust");dms.reportSpam(conversationId, messageId)
Report a DM as spam. Uses the v1.1 direct_messages/report_spam endpoint.
await client.dms.reportSpam("1234567890-9876543210", "111222333");dms.report(conversationId, messageId)
Report a DM message. Uses the v1.1 dm/report endpoint.
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.
const { inbox_initial_state: inbox } = await client.dms.inbox();
const { user_events: events } = await client.dms.userUpdates({ cursor: inbox.cursor });Full example
// 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"]);