TwexAPI で X 投稿を公開する方法
TwexAPI は、X 投稿や返信を作成するための POST https://api.twexapi.io/twitter/tweets/create を提供しています。これは書き込みエンドポイントなので、読み取り専用の検索 API とは扱いを変える必要があります。投稿前に内容を確認し、アカウント認証情報を安全に保存し、すべての公開試行を記録します。
この記事では、承認済みコンテンツを公開するための管理されたワークフローに絞ります。未承諾の返信、低品質な大量投稿、誤解を招く自動化のための手順ではありません。
エンドポイントと必須フィールド
アカウント cookie または auth token を使って公開する場合は、POST /twitter/tweets/create を使います。
| フィールド | 型 | 必須 | 説明 |
|---|---|---|---|
tweet_content | string | はい | 公開する本文。送信前に長さと内容ルールを確認します。 |
cookie | string | はい | X authentication cookie または auth_token。シークレット管理や環境変数に保存します。 |
media_url | string または null | いいえ | 添付するメディア URL。 |
reply_tweet_id | string または null | いいえ | 返信先 tweet ID。 |
schedule | string または null | いいえ | 予約投稿の ISO 時刻。 |
community_name | string または null | いいえ | コミュニティ名またはコミュニティ ID。 |
delegated_account_username | string または null | いいえ | delegated account を使う場合のユーザー名。 |
proxy | string または null | いいえ | 投稿環境で使うネットワーク経路。管理され、準拠したものを使います。 |
TwexAPI には POST /twitter/post-tweet-without-cookie もあります。これはリクエスト body に cookie を渡さず、cookie pool を使うエンドポイントです。管理されたアカウントプールを前提にした運用でのみ使ってください。多くの自社アカウント公開フローでは、明示的に cookie を渡すエンドポイントの方が監査しやすくなります。
基本リクエスト
curl --request POST \
--url https://api.twexapi.io/twitter/tweets/create \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '{
"tweet_content": "Product changelog: the CSV export now includes reply counts and quote counts.",
"cookie": "<x_auth_cookie_or_auth_token>"
}'成功レスポンスには code、msg、data が含まれます。data には tweet_id、user_id、レスポンス code が入ることがあります。
{
"code": 200,
"msg": "success",
"data": {
"tweet_id": "1234567890123456789",
"user_id": "1234567890",
"code": 200
}
}Python クライアント
認証情報をソースコードに書かないでください。このクライアントは Bearer token と X cookie を環境変数から読み、投稿本文を検証してからレスポンスを返します。
1import os
2from typing import Any
3
4import requests
5
6API_URL = "https://api.twexapi.io/twitter/tweets/create"
7BEARER_TOKEN = os.environ["TWEXAPI_BEARER_TOKEN"]
8X_COOKIE = os.environ["TWEXAPI_X_COOKIE"]
9
10def validate_post_text(text: str) -> None:
11 if not text or not text.strip():
12 raise ValueError("tweet_content cannot be empty")
13 if len(text) > 280:
14 raise ValueError(f"tweet_content is too long: {len(text)} characters")
15
16def publish_post(
17 text: str,
18 *,
19 media_url: str | None = None,
20 reply_tweet_id: str | None = None,
21 schedule: str | None = None,
22 community_name: str | None = None,
23) -> dict[str, Any]:
24 validate_post_text(text)
25
26 payload: dict[str, Any] = {
27 "tweet_content": text,
28 "cookie": X_COOKIE,
29 }
30
31 if media_url:
32 payload["media_url"] = media_url
33 if reply_tweet_id:
34 payload["reply_tweet_id"] = reply_tweet_id
35 if schedule:
36 payload["schedule"] = schedule
37 if community_name:
38 payload["community_name"] = community_name
39
40 response = requests.post(
41 API_URL,
42 headers={
43 "Authorization": f"Bearer {BEARER_TOKEN}",
44 "Content-Type": "application/json",
45 },
46 json=payload,
47 timeout=30,
48 )
49 response.raise_for_status()
50 return response.json()
51
52if __name__ == "__main__":
53 result = publish_post(
54 "Product changelog: the CSV export now includes reply counts and quote counts."
55 )
56 print(result["data"]["tweet_id"])返信、メディア、予約、コミュニティ投稿
同じエンドポイントで複数の公開モードを扱えます。ログから公開理由が分かるように、それぞれのモードを明示的に渡します。
1# Reply to an existing post.
2reply_result = publish_post(
3 "Thanks for reporting this. We shipped a fix in the latest export job.",
4 reply_tweet_id="1234567890123456789",
5)
6
7# Attach media by URL.
8media_result = publish_post(
9 "Here is the updated reporting layout.",
10 media_url="https://example.com/reporting-layout.png",
11)
12
13# Schedule a future post with an ISO timestamp.
14scheduled_result = publish_post(
15 "Maintenance window starts in one hour.",
16 schedule="2026-07-01T12:00:00Z",
17)
18
19# Publish inside a community by name or ID.
20community_result = publish_post(
21 "Sharing the release notes for community feedback.",
22 community_name="1234567890123456789",
23)返信では、公開前に対象 tweet が本当に返信先として正しいかを確認します。予約投稿では、API に渡すだけでなく、自分のシステムにも予定時刻を保存します。
承認優先の公開フロー
安全な公開システムでは、API 呼び出しの前に draft 状態を持たせます。少なくとも次を保存します。
draft_idaccount_idtweet_content- 任意の
media_url、reply_tweet_id、schedule、community_name approved_byapproved_at- 公開後の
tweet_id
1def publish_approved_draft(draft: dict[str, Any]) -> dict[str, Any]:
2 if draft.get("status") != "approved":
3 raise ValueError("Draft must be approved before publishing")
4
5 result = publish_post(
6 draft["tweet_content"],
7 media_url=draft.get("media_url"),
8 reply_tweet_id=draft.get("reply_tweet_id"),
9 schedule=draft.get("schedule"),
10 community_name=draft.get("community_name"),
11 )
12
13 return {
14 "draft_id": draft["draft_id"],
15 "tweet_id": result.get("data", {}).get("tweet_id"),
16 "user_id": result.get("data", {}).get("user_id"),
17 "api_code": result.get("code"),
18 "api_msg": result.get("msg"),
19 }こうすると API 呼び出しは小さく保たれ、コンテンツ承認、リトライ方針、監査履歴はアプリケーション側で管理できます。
よくある落とし穴
cookieをスクリプト、ログ、リポジトリに直接書かないでください。- レビューしていない検索結果をそのまま自動投稿しないでください。
- エンドポイント呼び出し前に本文の長さを検証します。
reply_tweet_idを使う前に、対象投稿が本当に返信先か確認します。- レスポンスの
tweet_idを保存し、リトライで重複投稿しないようにします。 - キャンペーン、顧客返信、コミュニティ投稿には人の承認フローを残します。
まとめ
POST /twitter/tweets/create は、TwexAPI で X 投稿や返信を公開する直接のエンドポイントです。最もよい実装は、複雑な自動化ループではなく、監査しやすいシンプルな流れです。draft を作り、承認し、公開し、レスポンスを保存し、失敗を確認します。
この形なら、プログラムからの公開を便利に使いながら、制御できない自動投稿を避けられます。