← 全記事
ケーススタディ

2人チームのエージェンシーが X の従量課金リード料を払わずに4つのクライアントアカウントの DM・メンションを監視している方法 — UnifyPort

2026年1月、リスボンの2人体制のソーシャルメディアエージェンシーが、4つのクライアントの X(Twitter)アカウントを管理していました。EC ブランド2社、SaaS スタートアップ1社、ローカルのレストランチェーン1社です。業務内容はシンプルで、各アカウントの DM とメンションを監視し、数時間以内に返信、クライアント本人の対応が必要なものはエスカレーションする、というもの。技術的にも単純で、Node.js のサービスが各アカウントの X API を30秒ごとにポーリングし、新着メッセージを共有 Slack チャンネルにルーティングしていました。

X の旧料金体系——2023年から続いていた固定月額プラン——では、この構成は Basic ティアで月額 $100。予測可能で予算に組み込みやすく、クライアントが払うリテイナーで余裕をもってカバーできるレベルでした。

そして2月が来ました。

課金メーターが動き出す

2026年2月3日、X は固定ティア料金を従量課金に切り替えました。リード・ライト問わず、すべての API コールにリクエスト単価が付くようになりました。月額の上限はなくなり、「ティア内は呼び放題」前提で設計されたポーリングアーキテクチャが、突然メーターを回し続けることに。

計算は即座でした。4つのクライアントアカウント、それぞれ30秒ごとに DM とメンションをポーリング。毎分8リード(アカウントあたり2エンドポイント × 4アカウント)、1日11,520回、月間約345,600回——これは監視だけのコストで、1通のメッセージも受信していない状態での数字です。

4月20日の料金改定で、自己所有リソースのリードは1回 $0.001 に引き下げられました。月間の監視リードコストは約 $346 に。しかし同じ改定でライトリクエスト(返信)は $0.010 から $0.015 に値上げされました。エージェンシーの月間返信数は4アカウント合計で400〜600通。$0.015 換算で $6〜$9 の増加です。単体では大きくありませんが、方向性が気になりました。クライアントアカウントが1つ増えるたびにポーリングループが増え、返信が増えるたびに両側から請求が膨らむ構造です。

本当に高いのはレートではなく、アーキテクチャ

創業者が仮に Q3 でクライアントを2社追加した場合の試算をしてみました(パイプライン上、十分現実的なシナリオ)。ポーリングリードだけで概ね倍増します。1回あたりのレートは確かに低いのですが、呼び出し量は構造的なもの——メッセージが実際に何通届いたかではなく、サービスが新着メッセージをチェックする頻度で決まります。DM がゼロの日曜日でも、ポーリングループは同じ速度で動き、コストは製品ローンチ当日とまったく同じです。

X の従量課金モデルで、料金比較記事には出てこない部分がこれです。メッセージを待つコストはゼロではない。そしてそれは実際のメッセージ量ではなく、監視アーキテクチャに比例してスケールします。4アカウントを30秒ごとにポーリングすれば、受信メッセージが10通でも10,000通でも月間345,600リードです。

ポーリング間隔を伸ばすのが最も直感的な対策でした。チームは1週間、2分間隔を試しました。レスポンスタイムが明らかに悪化し、DM が最悪4分近く未読になるケースが発生。2社のクライアントとは「2時間以内の応答」SLA を契約していました。SLA 違反にはなりませんでしたが、サービスの質感が「ほぼリアルタイム」から「そのうち」に変わってしまいました。3日後に元に戻しました。

プルからプッシュへ

正しい解決策はポーリングの最適化ではなく、ポーリングの廃止でした。チームは4つのクライアントの X アカウントをすべて UnifyPort に接続し、DM とメンションをリアルタイムで webhook にプッシュする方式に切り替えました。ポーリングループなし、従量リード課金なし、チェック頻度に比例するコストなし。

アーキテクチャの変化は以下のとおりです:

Before(ポーリング):
  サービス ──► X API(DM読取)     ×4アカウント ×2回/分 = 345,600 リード/月
  サービス ──► X API(メンション読取) ×4アカウント ×2回/分 = 345,600 リード/月
  合計:~691,200 課金 API リード/月

After(webhook プッシュ):
  X アカウント ──► UnifyPort ──► POST /webhook ──► Slack(クライアント A)
  X アカウント ──► UnifyPort ──► POST /webhook ──► Slack(クライアント B)
  X アカウント ──► UnifyPort ──► POST /webhook ──► Slack(クライアント C)
  X アカウント ──► UnifyPort ──► POST /webhook ──► Slack(クライアント D)
  合計:0 X API リード

各アカウントのインバウンドメッセージは message.received イベントとして配信されます。同じチームが今後 WhatsApp や Telegram、あるいは日本市場では LINE のアカウントを同じクライアント向けに追加した場合も、まったく同じフォーマットで届きます:

{
  "event": "message.received",
  "account_id": "acct_client_a",
  "provider": "twitter",
  "from": "user_7d2e1f",
  "text": "Hey, is the summer sale still on? Saw a post but the link was broken",
  "timestamp": 1750320000,
  "message_id": "x_msg_8a3b2c"
}

webhook ハンドラーは HMAC-SHA256 で各配信の署名を検証し、account_id に基づいて対応するクライアントの Slack チャンネルにルーティングします:

app.post("/webhook", (req, res) => {
  if (!verifySignature(req)) return res.sendStatus(401);

  const evt = req.body;
  if (evt.event === "message.received") {
    const channel = clientChannelMap[evt.account_id];
    slack.postMessage(channel, {
      text: `[${evt.provider}] ${evt.from}: ${evt.text}`,
      metadata: { messageId: evt.message_id },
    });
  }
  res.sendStatus(200);
});

4アカウント、1エンドポイント、1つの署名キー。ポーリングサービスは完全に停止しました。

何が変わったか

チームの X 関連 API コストは月額約 $350(クライアント追加で増加傾向)からリード課金ゼロに。レスポンスレイテンシーはむしろ改善しました——イベントはメッセージ送信後数秒以内に届き、次のポーリングサイクルを待つ必要がありません。新しいクライアントアカウントの追加も、請求書にポーリングループを1つ追加する作業ではなく、clientChannelMap に1行追加する作業になりました。

2人チームの X DM・メンション返信方法は変わっていません——Slack から、UnifyPort の返信エンドポイント経由でルーティングします。変わったのは、「4つの X アカウントの監視」がモデリングやクライアントへの説明、スケーラビリティの心配が必要な API コストではなくなったこと。Q3 のパイプラインでアカウントが2つ増えても、webhook が4つではなく6つ受け取るだけ。請求書には差が出ません。

複数の X アカウントを管理するエージェンシーやチーム——特に X API コストがメッセージ量ではなくポーリング頻度に比例してスケールするチーム——にとって、アーキテクチャの問いは「最も安いポーリング間隔は何か」ではありません。プッシュ型 webhook がメーターを回さずに同じメッセージを配信できるのなら、プルモデル自体が必要かどうか、という問いです。