如何用 TwexAPI 检查 X 私信可达性
私信外联最容易被低估的一步,不是写消息,而是确认对方当前是否能收到这条消息。很多账号关闭了 DM,只允许关注者私信,或者触发了额外的认证、Premium、XChat 条件。直接发送会让流程变得难解释:到底是文案没回应,还是消息根本没送达?
TwexAPI 的 POST /v2/dm/status 适合做发送前预检。你提交一组用户名或 user ID,接口返回每个账号的 can_dm、dm_blocking、can_dm_on_xchat 以及认证相关字段。把这一步放在 CRM、客服队列或增长自动化之前,可以先判断“当前是否适合发 DM”,再决定是发送、换渠道,还是进入人工复核。
什么时候要先查 DM 状态
DM 状态预检 指在发送私信前,用 API 批量确认目标账号在当前条件下是否可达。它不是营销名单质量评分,也不是保证送达的最终凭证,而是发送动作前的一道可解释检查。
适合放在这些场景里:
- 销售或合作外联:名单进入发送队列前,先过滤
can_dm不为true的账号。 - 客服和社群运营:当用户在公开帖里求助时,先判断是否能转入私信沟通。
- CRM 同步:把 DM 可达性保存成联系人字段,帮助销售选择 Twitter/X、邮件或其他渠道。
- 活动名单清洗:达人、KOL、合作账号批量入库时,记录一次可达性快照。
不要把 can_dm: false 写成“这个账号永远不能私信”。它只代表这次查询返回的当前状态。账号设置、关注关系、认证条件和平台规则都可能变化,所以生产流程里要保存查询时间,并给关键联系人设置重新检查规则。
API 端点
API 端点 指当前官方 OpenAPI 中的 V2 DM 状态检查接口:POST /v2/dm/status。请求体是字符串数组,每个元素可以是 X 用户 ID,也可以是用户名。
POST https://api.twexapi.io/v2/dm/status
Authorization: Bearer <your_token>
Content-Type: application/json
["1696160451770429440", "elonmusk", "openai"]响应的核心结构是:
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}字段建议按下面的方式理解:
| 字段 | 用途 |
|---|---|
user_id | 稳定账号 ID,适合做数据库主键或二次校验 |
screen_name | 当前用户名,适合展示和人工复核 |
can_dm | 当前是否可向该账号发起 DM 的主要判断字段 |
dm_blocking | 是否存在 DM 阻断信号 |
can_dm_on_xchat | XChat 相关可达性信号,可能为 null |
passes_premium_check | 是否通过相关 Premium 条件检查 |
is_blue_verified、is_verified_organization_affiliate、verified | 认证相关上下文,不应单独当作可达性结论 |
Python 示例
Python 示例 指一个服务端批量预检脚本:清洗输入、请求 V2 端点、规范化返回字段,并给每个联系人生成下一步动作。示例只做可达性判断,不负责真正发送私信。
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"])生产环境里,建议把返回结果拆成两层保存:规范化字段供 CRM、看板和规则引擎使用;原始 JSON 供后续排查字段变化、平台状态变化或误判。
放进外联流程
外联流程 指把 DM 状态检查放在发送前,而不是发送失败后再补救。最实用的流程通常是“名单入库、状态预检、规则分流、发送前复查、结果回写”。
一个稳定的流程可以这样设计:
- 名单入库:保存
screen_name、user_id、名单来源、活动 ID 和负责人。 - 批量预检:调用
/v2/dm/status,保存can_dm、dm_blocking、passes_premium_check和原始响应。 - 规则分流:
can_dm === true且没有阻断信号的账号进入发送队列;其他账号改走邮件、公开回复或人工复核。 - 发送前复查:对高价值联系人,在真正发送前重新查一次,避免用过期状态决策。
- 结果回写:把发送结果、失败原因和最后一次 DM 状态一起写回 CRM。
这样做的价值不只是减少失败发送。更重要的是,每个联系人为什么进入或退出 DM 队列都有记录,团队可以复盘规则,而不是靠“这批名单效果不好”这种模糊结论。
状态如何解释
状态解释 指把 API 字段转成业务动作时要保守。can_dm 是主要信号,但不要脱离 dm_blocking、Premium 检查、认证字段和查询时间单独解释。
| 返回信号 | 建议动作 |
|---|---|
can_dm === true 且 dm_blocking !== true | 可以进入 DM 发送队列 |
can_dm === false | 不要自动发送,改用其他渠道或稍后复查 |
dm_blocking === true | 阻断发送,并记录原因 |
passes_premium_check === false | 检查当前账号、发送条件或 X 规则要求 |
认证字段为 true | 只能说明认证上下文,不能替代 DM 可达性判断 |
字段为 null | 当作未知状态处理,不要自动放行 |
如果你的发送账号、cookie、关注关系或 Premium 状态会变化,就不要长期缓存 DM 状态。对于普通外联名单,可以按小时或天级别刷新;对于高价值联系人,最好在发送前即时复查。
最小生产实现
最小生产实现 指只保留必要能力:批量请求、去重、超时、错误处理、状态保存和重查策略。不要一开始就把它做成复杂监控系统。
建议至少保存这些字段:
| 字段 | 为什么要保存 |
|---|---|
target_input | 原始输入,方便排查用户名变更或 ID 混用 |
user_id 和 screen_name | 做稳定匹配和展示 |
can_dm、dm_blocking、can_dm_on_xchat | 可达性判断 |
passes_premium_check | 解释 Premium 条件导致的不可达 |
| 认证字段 | 给销售、客服或风控提供上下文 |
decision | 业务规则给出的动作 |
checked_at | 判断状态是否过期 |
raw_response | 后续字段变化时可重新处理 |
错误处理上,401 通常是 Token 问题,应该立即停止任务并提醒配置;422 多半是请求体格式问题,应该记录失败批次;网络超时可以重试,但不要无限重试同一批联系人。
常见误区
常见误区 指把 DM 可达性当作静态事实,或者把认证字段当作发送许可。更稳妥的做法是把它当成“查询时刻的发送前证据”。
- 以当前 OpenAPI 的 V2 路径
/v2/dm/status为准,不要沿用旧版 DM 状态示例。 - 以 V2 响应里的
can_dm、dm_blocking和相关上下文字段为准,不要沿用旧版布尔字段口径。 - 不要把
can_dm: true写成“保证送达”。真正发送时仍可能因为账号关系、平台策略或状态变化失败。 - 不要把
can_dm: false写成“永远不可联系”。它只代表这次查询下不适合直接发 DM。
小结
小结 指把 DM 状态检查当成发送前的可达性预检:向 POST /v2/dm/status 提交用户名或 user ID 数组,读取 can_dm、dm_blocking、passes_premium_check 等字段,保存原始响应和查询时间,再把结果写入 CRM、客服队列或外联规则。这样私信自动化不会只追求“发出去”,而是能解释每一次为什么发、为什么不发、什么时候需要复查。