TwexAPI で X アカウント状態を監査する方法
アカウントリストは自然にはきれいな状態を保ちません。クリエイターが停止される、提携先アカウントが使えなくなる、ホワイトリスト内のユーザーが名前を変える、認証シグナルを失う。支払い、施策、提携が始まってから気づくと遅すぎます。
TwexAPI では、この確認を固定フローにできます。まず POST /twitter/users/status でアカウントが存在するか、suspended かを一括確認し、必要に応じて POST /x/account/verify で Blue Verified や公式組織関連のメタデータを補足します。得られるのは曖昧な「信頼スコア」ではなく、承認やレビューキューに渡せる状態証拠です。
監査の目的
この監査は、資金、権限、ブランド露出が発生するアクションの前に置きます。目的は、X アカウント一覧がまだ利用可能か、suspended または未発見になっていないか、認証情報が業務ルールに合っているかを確認することです。青いチェックマークは参考情報ですが、アカウント状態の証拠そのものではありません。
主な目的は次の 3 つです。
- 停止または利用不能アカウント:支払い、提携、ホワイトリスト承認前に、
suspendedまたは未発見のアカウントを見つける。 - 認証情報の変化:Blue Verified または公式組織関連アカウントであるかを確認する。
- レビュー証拠の保存:原始レスポンス、監査時刻、監査理由、前回状態を保存し、新しいリスクか既存状態かを判断できるようにする。
エンドポイント選択
「アカウントが使えるか」と「認証情報があるか」は分けて処理します。前者は状態エンドポイント、後者は認証エンドポイントを使います。分けることで、認証バッジをアカウントリスクの結論と誤読しにくくなります。
| 目的 | エンドポイント | Body | 判断に向くこと |
|---|---|---|---|
| アカウント状態の一括確認 | POST /twitter/users/status | ユーザー名配列 | suspended、未発見 |
| 認証メタデータ | POST /x/account/verify | ユーザー ID またはユーザー名配列 | is_blue_verified、is_verified_organization_affiliate、is_verified |
どちらも Bearer Token を使います。
Authorization: Bearer <your_token>
Content-Type: application/jsonアカウント状態リクエスト:
POST https://api.twexapi.io/twitter/users/status
Authorization: Bearer <your_token>
Content-Type: application/json
["elonmusk", "sundarpichai", "unknown_handle"]認証情報リクエスト:
POST https://api.twexapi.io/x/account/verify
Authorization: Bearer <your_token>
Content-Type: application/json
["elonmusk", "sundarpichai"]Python の例:一括監査ループ
以下は保守的なサーバー側監査スクリプトです。先にアカウント状態を確認し、次に認証情報を補足し、最後にデータベースや人間のレビューキューへ渡せる結果を作ります。状態レスポンスは配列またはマッピングで返る可能性を考慮して正規化しています。
1import os
2from datetime import datetime, timezone
3
4import requests
5
6API_BASE = "https://api.twexapi.io"
7TOKEN = os.environ["TWEXAPI_BEARER_TOKEN"]
8
9def post_json(path, body):
10 response = requests.post(
11 API_BASE + path,
12 headers={
13 "Authorization": f"Bearer {TOKEN}",
14 "Content-Type": "application/json",
15 "Accept": "application/json",
16 },
17 json=body,
18 timeout=30,
19 )
20 response.raise_for_status()
21 payload = response.json()
22
23 if isinstance(payload, dict) and payload.get("code", 200) >= 400:
24 raise RuntimeError(payload.get("msg", "TwexAPI returned an error"))
25
26 return payload
27
28def normalize_status_payload(payload, usernames):
29 data = payload.get("data", payload) if isinstance(payload, dict) else payload
30
31 if isinstance(data, dict):
32 return {name.lower(): data.get(name) for name in usernames}
33
34 if isinstance(data, list):
35 return {
36 name.lower(): data[index] if index < len(data) else None
37 for index, name in enumerate(usernames)
38 }
39
40 return {name.lower(): None for name in usernames}
41
42def verification_by_username(payload):
43 rows = payload.get("data", []) if isinstance(payload, dict) else []
44 result = {}
45
46 for row in rows:
47 screen_name = (row.get("screen_name") or "").lower()
48 if screen_name:
49 result[screen_name] = row
50
51 return result
52
53def classify_account(status_value, verify_row):
54 status_text = "" if status_value is None else str(status_value).lower()
55
56 if status_value is None:
57 return "REVIEW_NOT_FOUND"
58
59 if "suspended" in status_text:
60 return "BLOCK_SUSPENDED"
61
62 if any(flag in status_text for flag in ("not_found", "not found", "missing", "unavailable")):
63 return "REVIEW_NOT_FOUND"
64
65 if verify_row.get("is_verified"):
66 return "PASS_STATUS_VERIFIED"
67
68 return "PASS_STANDARD"
69
70def audit_accounts(usernames, audit_reason):
71 status_payload = post_json("/twitter/users/status", usernames)
72 verify_payload = post_json("/x/account/verify", usernames)
73
74 statuses = normalize_status_payload(status_payload, usernames)
75 verifications = verification_by_username(verify_payload)
76 audited_at = datetime.now(timezone.utc).isoformat()
77
78 results = []
79 for username in usernames:
80 key = username.lower()
81 verify_row = verifications.get(key, {})
82 status_value = statuses.get(key)
83
84 results.append({
85 "username": username,
86 "status": status_value,
87 "is_blue_verified": verify_row.get("is_blue_verified"),
88 "is_org_affiliate": verify_row.get("is_verified_organization_affiliate"),
89 "is_verified": verify_row.get("is_verified"),
90 "decision": classify_account(status_value, verify_row),
91 "audit_reason": audit_reason,
92 "audited_at": audited_at,
93 })
94
95 return results
96
97accounts = ["elonmusk", "sundarpichai", "unknown_handle"]
98for row in audit_accounts(accounts, "partner_payout_precheck"):
99 print(row)本番環境では、TWEXAPI_BEARER_TOKEN をサーバー側の環境変数に保存し、ソースコードへ書かないでください。監査後は正規化結果と原始レスポンスの両方を保存します。人間のレビューには原始証拠が必要で、ダッシュボードやルールエンジンには正規化フィールドが向いています。
レスポンスフィールド
後から判断を再現できるように、監査時に保存して比較すべきフィールドを決めておきます。/twitter/users/status はアカウント可用性、/x/account/verify は認証メタデータを返します。
認証レスポンスの data 配列でよく使うフィールドは次の通りです。
| フィールド | 意味 |
|---|---|
user_id | X ユーザー ID |
screen_name | ユーザー名 |
is_blue_verified | Blue Verified かどうか |
is_verified_organization_affiliate | 公式組織関連アカウントかどうか |
is_verified | Blue Verified または公式組織関連のどちらかを満たすか |
状態エンドポイントの判断はより単純です。suspended ならブロックまたはレビューへ回します。null または対象と一致しない場合は、「未発見/要レビュー」と扱い、自動承認しないでください。
使うべきフロー
資金、権限、ブランドリスクが発生するアクションの前に確認を入れます。
- 支払い前チェック:クリエイター、KOL、提携アカウントへの支払い前に、停止や失効がないか確認する。
- ホワイトリスト承認:コミュニティ、イベント、プロダクト権限を付与する前に、状態と認証証拠を記録する。
- 提携先の受け入れ:代理店、クリエイター、affiliate をデータベースに入れる前に状態スナップショットを保存する。
- ブランドアカウント監視:役員、ブランド、サポートアカウントを定期確認し、状態変化があれば security または PR に通知する。
- Sybil リスクフィルタ:suspended、未発見、認証変化などを、単独フィールドではなく広いリスクモデルに渡す。
リスク階層
API の戻り値は業務アクションに変換しますが、スクリプトに不可逆な判断を直接実行させないでください。明確な推奨アクションを作り、ワークフロー側で処理します。
| シグナル | 推奨アクション |
|---|---|
suspended | 支払いまたは承認を止め、レビュータスクを作成 |
null または未発見 | 自動承認を保留し、ユーザー名変更の可能性を確認 |
| 未認証だが状態正常 | フローは継続できるが、高信頼権限は付与しない |
| 認証状態の変化 | ブランド、組織、役員アカウントでは二次確認を実施 |
| API エラーが連続 | システム問題として再試行または延期し、アカウントリスクと誤判定しない |
実装時の注意点
監査結果は、再現、説明、復旧できる状態で保存します。状態の原始レスポンス、認証の原始レスポンス、ユーザー名、アカウント ID、監査時刻、監査理由、リストバージョン、ルールバージョンを保存します。
定期監査では、一時的な API エラーとアカウントリスクを分けます。ネットワークタイムアウトはリトライ対象です。suspended、未発見、認証状態変化は、証拠付きの人間レビュータスクにします。支払いと提携では、「通過」「ブロック」「要レビュー」を別々の状態にし、すべての異常を同じエラーにしないでください。
まとめ
アカウント状態監査は、バッジ確認ではなく証拠チェーンとして扱います。アカウントリストを読み込み、/twitter/users/status で可用性を確認し、/x/account/verify で認証情報を補足し、原始データと正規化データを保存して、疑わしい変化を人間レビューへ送ります。これにより、支払い、提携、コミュニティのホワイトリスト、ブランド監視リストが静かに古くなるのを防げます。