DM Inbox API
List the DM conversations (inbox) for the account behind your session. Returns each conversation's ID, type, and participant user IDs. Pass a conversation_id to GET /dm/conversation to read its messages. Authenticate with a registered session (POST /customer/session) or per-call x-auth-token and x-ct0 headers, so one API key can poll the inboxes of many accounts. Read-only: this does not send DMs. It reads X's standard DM inbox, so conversations X has moved to end-to-end encrypted chat may not appear, and conversations still in the message-requests folder may be missing. Cost: $0.0016 per call.
GET dm/list returns the Direct Message inbox for the account behind your session: a list of DM conversations, each with its conversation_id, type, and participant user IDs. It is read-only and does not send messages or return message content. The response includes a count field alongside the conversations array. Use the returned conversation_id values with GET /dm/conversation to read a specific thread's messages.
Authorization
bearerAuth Pass your API key as a bearer token on every request: Authorization: Bearer <API_KEY>.
In: header
Query Parameters
Comma-separated list of dotted field paths to keep in the response (one parameter, never repeated), applied to every object in the returned lists and to nested objects (for example fields=id,text,author.username; the list's own name may prefix a path, fields=tweets.id). A path prefix that lands on an array applies to each element (media.media_url_https). Pagination and envelope keys (next_cursor, cursor, has_more, count, partial, error, message, reason) are always kept. Unknown paths are ignored; up to 50 paths of up to 6 segments. Projection never changes status codes or billing, and applies to data reads only: account, feedback, session status, monitor (other than deliveries), webhook and stream-compat reads return their bodies unchanged.
Set to 1 (or true) to apply the built-in compact preset: ids, url, text, created_at, lang, the engagement counts, the is_retweet/is_reply/is_quote flags, conversation ids, the author's id/username/name/followers_count/verification, and the quoted or retweeted tweet's id/url/author username. The preset trims what it recognises and leaves alone what it would empty, so it never turns a body into {}. Combine with fields to add paths on top of the preset. Typically cuts a tweet page by 70 to 90 percent for LLM tool callers.
Response Body
application/json
application/json
application/json
application/json
application/json
application/json
application/json
application/json
curl -X GET "https://example.com/dm/list?fields=id%2Ctext%2Ccreated_at%2Cauthor.username&compact=1"{ "count": 2, "conversations": [ { "conversation_id": "1749154312754794496-1972455697997824000", "type": "ONE_TO_ONE", "participants": [ "1749154312754794496", "1972455697997824000" ] }, { "conversation_id": "1796873533852692480-1972455697997824000", "type": "ONE_TO_ONE", "participants": [ "1796873533852692480", "1972455697997824000" ] } ], "inbox_timelines": { "trusted": { "status": "HAS_MORE", "cursor": "GRwmkMDXkuGjpbUXFoCAwMDX" }, "untrusted": { "status": "AT_END", "cursor": null } }}{ "error": "bad_request", "message": "Missing or malformed parameter. Fix the request before retrying."}{ "error": "unauthorized", "message": "The API key is missing, malformed, or revoked. Check the Authorization header."}{ "error": "insufficient_credits", "message": "Your balance is exhausted. Top up your credits to continue."}{ "error": "forbidden", "message": "X refused this resource for the acting account: on a read, the account is not a participant in the DM thread, the target is protected or has blocked it, or the session was attestation-blocked for calling from a datacenter or rotating IP; on a write, the account is not authorized for the action or has no logged-in session. The credentials are still valid, so do not re-register."}{ "error": "not_found", "message": "The resource does not exist, for example a deleted tweet or a private account."}{ "error": "rate_limited", "message": "Too many requests. Back off and retry with exponential backoff."}{ "error": "server_error", "message": "Something failed on our side. Retry with backoff; if it persists, contact support."}Pricing
| Unit | Price |
|---|---|
| Per call | $0.0016 |
| Per 1,000 calls | $1.60 |
When to use
Use GET dm/list to enumerate the DM inbox itself, the set of conversations, their IDs, types, and participants, before drilling into any single thread. Once you have a conversation_id from this response, pass it to GET /dm/conversation to pull that thread's actual messages.
Notes
- Needs a session for the account you are reading: either register one once (POST /customer/session), or pass per-call inline credentials as x-auth-token and x-ct0 request headers, which let a single API key act as many accounts. Returns 409 session_required if neither is supplied, 401 session_dead when the session has expired.
- Not cursor-paginated: the inbox is returned in a single page.
- Read-only: lists conversations; it does not send DMs.
Related endpoints
- Send DM: Send a direct message from your authenticated account.
- DM Conversation: Read the message history of one DM conversation by conversation_id.
FAQ
Does it include encrypted chats and message requests?
Not reliably. GET dm/list reads X's standard DM inbox, so conversations X has moved to end-to-end encrypted chat may not appear, and conversations still in the message-requests folder may be missing.
Does dm/list return the actual message text inside each conversation?
No. Each entry in the conversations array only carries conversation_id, type, and participants. To read the messages in a specific conversation, take its conversation_id and call GET /dm/conversation.
What account's inbox does this endpoint read, and can I pass a target user?
There are no params on this endpoint, it always returns the DM conversations for the account tied to your current session, not an arbitrary user's inbox. Each call costs $0.0016 and returns a count field plus the conversations array.
Overview
Direct Messages: Read your account's DM inbox and the message history of a single conversation, and send new messages, all acting as the account behind your registered session.
DM Conversation GET
Fetch the messages inside a single DM conversation. Pass a conversation_id from GET /dm/list. Each message carries its ID, sender ID, timestamp, and text. Authenticate with a registered session (POST /customer/session) or per-call x-auth-token and x-ct0 headers. Read-only: this does not send DMs. Cost: $0.0016 per call.