How to Check X DM Reachability with TwexAPI
The most underrated part of DM outreach is not writing the message. It is confirming whether the target can receive it right now. Some accounts close DMs, some only accept messages from people they follow, and some depend on extra verification, Premium, or XChat conditions. If you send blindly, it becomes hard to know whether the copy failed or the message never had a path to delivery.
TwexAPI's POST /v2/dm/status is built for this preflight check. Submit a set of usernames or user IDs, then read can_dm, dm_blocking, can_dm_on_xchat, and related verification fields. Put this step before CRM outreach, support queues, or growth automation so the workflow can decide whether to send, switch channels, or ask for human review.
When To Check DM Status First
DM reachability preflight means using an API to batch-confirm whether target accounts are reachable under current conditions before sending messages. It is not a marketing lead score and not a final delivery guarantee. It is an explainable check before the send action.
Useful places to run it:
- Sales or partnership outreach: Filter accounts where
can_dmis nottruebefore they enter a send queue. - Support and community operations: When a user asks for help in public, check whether the conversation can move to DM.
- CRM sync: Save DM reachability as a contact field so teams can choose X, email, or another channel.
- Campaign list cleanup: Snapshot DM reachability when creator, KOL, or partner accounts enter a database.
Do not write can_dm: false as "this account can never be messaged." It only describes the state returned by this query. Account settings, follow relationships, verification conditions, and platform rules can change, so store query time and recheck important contacts.
API Endpoint
API endpoint means the V2 DM status endpoint in the current OpenAPI: POST /v2/dm/status. The request body is a string array. Each item can be an X user ID or username.
POST https://api.twexapi.io/v2/dm/status
Authorization: Bearer <your_token>
Content-Type: application/json
["1696160451770429440", "elonmusk", "openai"]The core response shape is:
1{
2 "code": 200,
3 "msg": "success",
4 "data": [
5 {
6 "user_id": "1696160451770429440",
7 "screen_name": "example_user",
8 "is_blue_verified": false,
9 "is_verified_organization_affiliate": false,
10 "verified": false,
11 "can_dm": true,
12 "can_dm_on_xchat": null,
13 "dm_blocking": false,
14 "passes_premium_check": true
15 }
16 ]
17}Interpret the fields conservatively:
| Field | Use |
|---|---|
user_id | Stable account ID for matching and second checks |
screen_name | Current username for display and manual review |
can_dm | Main signal for whether the account appears reachable |
dm_blocking | DM blocking signal |
can_dm_on_xchat | XChat-related reachability signal, often nullable |
passes_premium_check | Explains Premium-related reachability conditions |
is_blue_verified, is_verified_organization_affiliate, verified | Verification context, not permission by itself |
Python Example
Python example means a server-side batch preflight script: clean input, call the V2 endpoint, normalize the fields, and produce a next action per contact. The example does not send DMs.
1import os
2from datetime import datetime, timezone
3
4import requests
5
6API_URL = "https://api.twexapi.io/v2/dm/status"
7TOKEN = os.environ["TWEXAPI_BEARER_TOKEN"]
8
9def clean_targets(targets):
10 cleaned = []
11 seen = set()
12
13 for target in targets:
14 value = str(target).strip().lstrip("@")
15 if not value or value.lower() in seen:
16 continue
17
18 cleaned.append(value)
19 seen.add(value.lower())
20
21 return cleaned
22
23def check_dm_reachability(targets):
24 cleaned = clean_targets(targets)
25 if not cleaned:
26 return []
27
28 response = requests.post(
29 API_URL,
30 headers={
31 "Authorization": f"Bearer {TOKEN}",
32 "Content-Type": "application/json",
33 "Accept": "application/json",
34 },
35 json=cleaned,
36 timeout=30,
37 )
38 response.raise_for_status()
39 payload = response.json()
40
41 if payload.get("code", 200) >= 400:
42 raise RuntimeError(payload.get("msg", "TwexAPI returned an error"))
43
44 checked_at = datetime.now(timezone.utc).isoformat()
45 rows = []
46
47 for item in payload.get("data") or []:
48 can_dm = item.get("can_dm") is True
49 blocked = item.get("dm_blocking") is True
50
51 if can_dm and not blocked:
52 decision = "READY_TO_MESSAGE"
53 elif blocked:
54 decision = "DO_NOT_MESSAGE"
55 else:
56 decision = "RECHECK_OR_USE_OTHER_CHANNEL"
57
58 rows.append({
59 "user_id": item.get("user_id"),
60 "screen_name": item.get("screen_name"),
61 "can_dm": item.get("can_dm"),
62 "dm_blocking": item.get("dm_blocking"),
63 "can_dm_on_xchat": item.get("can_dm_on_xchat"),
64 "passes_premium_check": item.get("passes_premium_check"),
65 "verified": item.get("verified"),
66 "decision": decision,
67 "checked_at": checked_at,
68 "raw": item,
69 })
70
71 return rows
72
73targets = ["elonmusk", "@openai", "1696160451770429440"]
74
75for row in check_dm_reachability(targets):
76 print(row["screen_name"], row["decision"], row["can_dm"])In production, store both normalized fields and the raw response. Normalized rows are good for CRM, dashboards, and rule engines. Raw JSON helps debug field changes, platform state changes, or incorrect business rules.
Add It To Outreach Workflows
Outreach workflow means checking DM status before sending instead of recovering after failed sends. A practical flow is: list intake, status preflight, rule routing, recheck before send, and result writeback.
- List intake: Store
screen_name,user_id, list source, campaign ID, and owner. - Batch preflight: Call
/v2/dm/status, then storecan_dm,dm_blocking,passes_premium_check, and raw response. - Rule routing: Accounts with
can_dm === trueand no blocking signal can enter the send queue. Others move to email, public reply, or manual review. - Pre-send recheck: Recheck high-value contacts right before sending so stale status does not drive the decision.
- Result writeback: Save send result, failure reason, and last DM status back to CRM.
The value is not only fewer failed sends. Every contact has an explainable reason for entering or leaving the DM queue.
How To Interpret Status
Status interpretation means translating API fields into business actions conservatively. can_dm is the main signal, but do not interpret it without dm_blocking, Premium checks, verification fields, and query time.
| Returned signal | Suggested action |
|---|---|
can_dm === true and dm_blocking !== true | Can enter a DM send queue |
can_dm === false | Do not auto-send; use another channel or recheck later |
dm_blocking === true | Stop sending and record the reason |
passes_premium_check === false | Review account, sender conditions, or X rule requirements |
Verification fields are true | Useful context, but not permission by itself |
Field is null | Treat as unknown; do not auto-approve |
If the sender account, cookie, follow relationship, or Premium state can change, do not cache DM status for too long. For routine outreach lists, refresh by hour or day; for high-value contacts, recheck immediately before sending.
Minimal Production Setup
Minimal production setup means keeping only the required parts: batch request, dedupe, timeout, error handling, status storage, and recheck policy.
Store at least:
| Field | Why |
|---|---|
target_input | Debug username changes or ID/name mixing |
user_id and screen_name | Stable matching and display |
can_dm, dm_blocking, can_dm_on_xchat | Reachability decision |
passes_premium_check | Explains Premium-related reachability |
| Verification fields | Adds sales, support, or risk context |
decision | Business action from your rules |
checked_at | Indicates whether status is stale |
raw_response | Supports reprocessing when fields change |
For errors, 401 usually means a token problem and should stop the job. 422 usually means request-body format issues and should be logged by batch. Network timeouts can be retried, but do not retry the same contacts forever.
Common Mistakes
Common mistakes means treating DM reachability as a permanent fact or treating verification fields as permission.
- Use the current OpenAPI V2 path
/v2/dm/status. - Use V2 response fields such as
can_dm,dm_blocking, and related context fields. - Do not write
can_dm: trueas guaranteed delivery. Sending can still fail if relationships, settings, or platform rules change. - Do not write
can_dm: falseas permanently unreachable. It only means direct DM is not appropriate under this query state.
Summary
Summary means treating DM status as a pre-send reachability check: submit username or user ID arrays to POST /v2/dm/status, read can_dm, dm_blocking, and passes_premium_check, store raw response and query time, then write the result to CRM, support queues, or outreach rules.