> ## Documentation Index
> Fetch the complete documentation index at: https://docs.sorsa.io/llms.txt
> Use this file to discover all available pages before exploring further.

# API利用の最適化

レスポンスに含まれるプロフィールの再利用、バッチ取得、安定したIDによる保存で、不要なリクエストを減らします。それぞれの使いどころを説明します。

> **ヒント：** 全アカウントにカード不要・有効期限なしの無料100リクエストがあります。以下の方法を試し、実際の利用量を測ってからプランを選べます。

***

## サンプルの準備

Pythonの例はバックエンドで`requests`を使います（`python -m pip install requests`）。実行前にAPIキーと例のIDを置き換えてください。`search_results`は、先のリクエストで取得したTweetオブジェクトの一覧です。

```python theme={null}
import requests

API_KEY = "YOUR_API_KEY"
```

## 原則1：ツイートのレスポンスにはすでにユーザー情報がある

Sorsa APIを効率的に使ううえで最も重要な点です。ツイートを返すすべてのエンドポイント（`/search-tweets`、`/user-tweets`、`/list-tweets`、`/comments`、`/quotes`、`/mentions`）は、各Tweetオブジェクトに**投稿者の完全なプロフィール**を含みます。

```json theme={null}
{
  "tweets": [
    {
      "id": "2029914600217473314",
      "full_text": "Great thread on API design patterns...",
      "likes_count": 142,
      "user": {
        "id": "1422280682240450563",
        "username": "dev_sarah",
        "display_name": "Sarah Chen",
        "description": "Staff engineer @stripe. APIs, distributed systems.",
        "followers_count": 12400,
        "followings_count": 890,
        "tweets_count": 4521,
        "verified": true,
        "location": "San Francisco",
        "created_at": "2021-02-01T09:15:22Z"
      }
    }
  ]
}
```

各ツイートの`user`は、`/info`で取得するものと同じ情報を持ちます。ID、ユーザー名、表示名、自己紹介、フォロワー数、フォロー数、ツイート数、認証状態、所在地、作成日、画像などです。

**実際の使い方：** 話題に関するツイートから、その話題について投稿するユーザーの一覧を作る場合、投稿者ごとに`/info`を呼ぶ必要はありません。レスポンスから直接取り出します。

```python theme={null}
# Collect unique users from a tweet search - zero extra API calls
seen_ids = set()
unique_users = []

for tweet in search_results:
    user = tweet["user"]
    if user["id"] not in seen_ids:
        seen_ids.add(user["id"])
        unique_users.append(user)

print(f"Found {len(unique_users)} unique users from {len(search_results)} tweets")
```

この1つの方法だけで、通常の処理で数百〜数千の不要な`/info`呼び出しを省けます。

***

## 原則2：バッチエンドポイントを使う

よく使う取得操作にはバッチ版があります。単体取得を繰り返す代わりに使うと、リクエスト数を大幅に減らせます。

### `/info`の繰り返しを`/info-batch`に替える

複数アカウントのプロフィールには、`/info`のループではなく`/info-batch`を使い、最大100件をまとめて取得します。

```python theme={null}
# A separate /info call for each account would use 10 requests.

# Efficient: 10 accounts = 1 request
resp = requests.get(
    "https://api.sorsa.io/v3/info-batch",
    headers={"ApiKey": API_KEY},
    params={"usernames": ["NASA", "SpaceX", "Tesla", "OpenAI", "stripe",
                           "shopify", "vercel", "github", "notion", "linear"]},
)
resp.raise_for_status()
profiles = resp.json().get("users", [])
```

**削減効果：** 10アカウントが10回ではなく1リクエストです。1回最大100件まで、件数に比例して削減できます。

### `/tweet-info`の繰り返しを`/tweet-info-bulk`に替える

アーカイブ、メンションの出力、ブックマークなどにあるツイートIDから現在の指標と投稿者を取得する場合、バッチ版で最大100件を1回で取得します。

```python theme={null}
# A separate /tweet-info call for each tweet would use up to 100 requests.

# Efficient: 100 tweets = 1 request
resp = requests.post(
    "https://api.sorsa.io/v3/tweet-info-bulk",
    headers={"ApiKey": API_KEY, "Content-Type": "application/json"},
    json={
        "tweet_links": [
            "https://x.com/user/status/111111",
            "https://x.com/user/status/222222",
            # ... up to 100 links
        ]
    },
)
resp.raise_for_status()
tweets = resp.json().get("tweets", [])
```

**削減効果：** 100ツイートが100回ではなく1リクエストになり、99%削減できます。

***

## 原則3：複数の`/user-tweets`を`/list-tweets`に替える

複数アカウントの最近の投稿を監視・収集する場合、個別に確認せずXリストに追加します。`/list-tweets`の1回の呼び出しで、全メンバーの最近の活動をまとめて取得できます。

```python theme={null}
# Separate /user-tweets calls would use 30 requests per polling cycle.
LIST_ID = "YOUR_LIST_ID"

# Efficient: 1 request covers all 30 accounts
resp = requests.get(
    f"https://api.sorsa.io/v3/list-tweets?list_id={LIST_ID}",
    headers={"ApiKey": API_KEY},
    timeout=30,
)
resp.raise_for_status()
```

**最初のページだけの場合の見積もり：** 10秒間隔のリスト取得は30日で259,200リクエストです。30アカウントのタイムラインを個別に取得すると7,776,000件です。追加ページと再試行でどちらも増え、投稿の多いリストでは毎回ページネーションが必要になる場合があります。

詳細は[リアルタイム監視](https://docs.sorsa.io/ja/real-time-monitoring)、Xリストの作成・管理は[リストとコミュニティ](https://docs.sorsa.io/ja/lists-and-communities)を参照してください。

***

## 原則4：`/info`で入力をまとめて解決する

`/info`はユーザー名、ユーザーID、プロフィールリンクを受け付け、永続的なIDを含む完全なプロフィールを返します。混在する入力を正規化するのに柔軟に使えます。

異なる形式の入力から完全なプロフィールが必要な場合、変換（`/username-to-id`、`/link-to-id`）の後に`/info`を呼ばず、1アカウントにつき`/info`を1回だけ使います。

```python theme={null}
# Resolving an ID and then fetching its profile would use two requests.

# Efficient: 1 request per account
response = requests.get(
    "https://api.sorsa.io/v3/info",
    headers={"ApiKey": API_KEY},
    params={"username": "stripe"},       # accepts username, user_id, or user_link
    timeout=30,
)
response.raise_for_status()
profile = response.json()
# profile already contains the user ID, plus everything else
```

**変換エンドポイントを別途使う場合：** IDだけ、またはユーザー名だけが必要で、全プロフィールが不要な場合です。たとえば、保存用に1,000件のユーザー名をIDへ変換するときです。前の処理ですでにプロフィールを得ていれば、その`id`を再利用してください。変換パターンは[ID変換](https://docs.sorsa.io/ja/ID-Conversion)を参照してください。

***

## 原則5：データベースで重複を除去する

検索、フォロワー一覧、メンション、タイムラインなど、複数の情報源には同じユーザーが何度も現れます。永続的なユーザーIDをキーにし、重複挿入せず既存のレコードを更新します。

```python theme={null}
import sqlite3

db = sqlite3.connect("audience.db")
db.execute("""
    CREATE TABLE IF NOT EXISTS users (
        user_id TEXT PRIMARY KEY, username TEXT, display_name TEXT,
        description TEXT, followers_count INTEGER, tweets_count INTEGER,
        verified INTEGER, updated_at TEXT
    )
""")

def upsert_user(db, user):
    """Insert or update a user record keyed by permanent User ID."""
    db.execute("""
        INSERT INTO users (user_id, username, display_name, description,
                          followers_count, tweets_count, verified, updated_at)
        VALUES (?, ?, ?, ?, ?, ?, ?, datetime('now'))
        ON CONFLICT(user_id) DO UPDATE SET
            username = excluded.username,
            display_name = excluded.display_name,
            description = excluded.description,
            followers_count = excluded.followers_count,
            tweets_count = excluded.tweets_count,
            verified = excluded.verified,
            updated_at = datetime('now')
    """, (
        user["id"], user["username"], user.get("display_name", ""),
        user.get("description", ""), user.get("followers_count", 0),
        user.get("tweets_count", 0), user.get("verified", False),
    ))
    db.commit()


# Every time you encounter a user in any API response, upsert:
for tweet in search_results:
    upsert_user(db, tweet["user"])
    # The user's profile data stays fresh without separate /info calls
```

この方法では、検索、メンション、フォロワー、コメント、引用などのレスポンスにユーザーが現れるたび、最新プロフィールに更新されます。再び現れないアカウントは更新されません。一定の鮮度が必要なら、バッチ更新を定期実行してください。

***

## 原則6：すでにあるデータを取り直さない

複数段階の処理では、再取得せずデータを次の段階へ渡してください。

**例：オーディエンスの地域分析。** 手順は（1）フォロワー取得、（2）各人の国を`/about`で取得、です。（1）の時点で自己紹介、フォロワー数、認証状態などの完全なプロフィールがあります。（2）で`/info`を再度呼ばず、標準プロフィールにない国情報だけを`/about`で取得します。詳細は[オーディエンスの地域分布](https://docs.sorsa.io/ja/Audience-Geography)を参照してください。

**例：キャンペーン確認。** フォロー・リツイート・コメントを確認すると、`/check-comment`は`commented: true`のときコメントの完全なツイートを返します。本文の品質を調べるにはそこから取り出し、`/search-tweets`や`/comments`で探し直さないでください。

**例：検索結果からユーザー一覧を作る。** 埋め込みの`user`から500人を抽出し、フォロワー10,000人以上を選びたい場合、取得済みのデータで絞り込みます。500人それぞれに`/info`を呼ぶ必要はありません。

***

## 早見表：適切なエンドポイントを選ぶ

| 手元のデータ      | 必要なデータ              | 推奨する方法                            | 避けたい方法                      |
| :---------- | :------------------ | :-------------------------------- | :-------------------------- |
| ユーザー名の一覧    | 全員の完全なプロフィール        | `GET /info-batch`（1リクエスト）         | `/info`をループ                 |
| ツイートURLの一覧  | 全ツイート情報と投稿者         | `POST /tweet-info-bulk`（最大100件／回） | `/tweet-info`をループ           |
| 監視対象30アカウント | 全員の最近の投稿            | `GET /list-tweets`（1リクエスト）        | `/user-tweets` × 30         |
| ユーザー名       | ID、自己紹介、件数など全プロフィール | `GET /info`                       | `/username-to-id`の後に`/info` |
| ツイート検索結果    | 投稿者プロフィール           | `tweet["user"]`を取り出す              | 投稿者ごとに`/info`               |
| フォロワー一覧     | 各人のプロフィール           | `/followers`にすでに含まれる              | 各人に`/info`                  |

***

## リクエストの予算を見積もる

プロジェクトを始める前に、必要な合計回数を見積もってください。

| タスク                 | 効率的な方法                          | 必要リクエスト数 |
| :------------------ | :------------------------------ | :------- |
| 50アカウントのプロフィール      | `/info-batch`                   | 約1       |
| 1アカウントのフォロワー10,000人 | `/followers`をページネーション（200人／ページ） | 50       |
| その10,000人の国情報       | 各人に`/about`                     | 10,000   |
| 100ツイートの現在の指標       | `/tweet-info-bulk`              | 1        |
| 50アカウントを10秒間隔で1日監視  | `/list-tweets`                  | 8,640    |
| 参加者1,000人の5タスク確認    | 各人に5回の確認                        | 5,000    |

典型的な競合調査とキャンペーン確認なら、50（フォロワー）+ 10,000（地域）+ 1（ツイート一括取得）+ 8,640（監視）+ 5,000（キャンペーン）= 約23,700リクエストです。毎秒20件での理論的な処理時間の下限は約20分ですが、監視自体は丸1日にわたり、順次ページ取得、応答待ち、再試行も経過時間に加わります。プランごとの費用は[料金](https://api.sorsa.io/pricing)を参照してください。

***

## 次のステップ

* [レート制限](https://docs.sorsa.io/ja/rate-limits)：429への対応と処理速度の最適化。
* [ページネーション](https://docs.sorsa.io/ja/pagination)：大規模取得のカーソル処理。
* [料金](https://api.sorsa.io/pricing)：リクエスト単価と予算計画。
* [APIリファレンス](https://docs.sorsa.io/ja/api-reference-guide)：`/info-batch`、`/tweet-info-bulk`を含む全仕様。
