> ## 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.

# エラーコード

> 400から500まで、Sorsa APIの各ステータスコードの意味、原因、解決方法を説明します。

リクエストが失敗すると、Sorsaは標準のHTTPステータスコードと、問題を説明する`message`フィールドを含むJSONを返します。このページでは、返される可能性がある各コード、その原因と解決方法を説明します。

## エラーレスポンスの形式

すべてのエラーレスポンスは同じ構造です。

```json theme={null}
{
  "message": "ApiKey required"
}
```

`message`には、発生した問題が読みやすい文章で記載されます。原因を直接示していることが多いため、調査時にはまずこのフィールドを確認してください。

## 早見表

| コード | 種類        | 意味                         |
| :-- | :-------- | :------------------------- |
| 200 | 成功        | リクエストが正常に完了                |
| 400 | クライアントエラー | 不正なリクエスト：パラメーターが無効または不足    |
| 401 | クライアントエラー | 未認証：認証に失敗                  |
| 403 | クライアントエラー | アクセス拒否：キーは有効だが利用権限または残高がない |
| 404 | クライアントエラー | 見つからない：リソースが存在しないか非公開      |
| 429 | クライアントエラー | リクエスト過多：レート制限を超過           |
| 500 | サーバーエラー   | 内部エラー：Sorsa側で問題が発生         |

## 400 Bad Request

パラメーターが無効または不足しているため、リクエストを処理できませんでした。

**よくある原因**

* 必須パラメーター（例：`link`、`id`、`username`、`query`）がない
* パラメーターの型や形式が違う（数値が必要な箇所に文字列を渡すなど）
* POSTリクエストのJSON本文が不正、または空

**解決方法：** 対象エンドポイントの[APIリファレンス](https://docs.sorsa.io/ja/api-reference-guide)を確認し、必須パラメーターがすべて正しい形式で指定されていることを確かめてください。POSTリクエストでは`Content-Type: application/json`を設定し、本文が有効なJSONであることを確認します。

## 401 Unauthorized

認証に失敗し、APIがアカウントを識別できませんでした。

**よくある原因**

* `ApiKey`ヘッダーがない
* ヘッダー名のスペルが違う。`ApiKey`を使ってください。HTTPヘッダー名の大文字・小文字は区別されませんが、`Api-Key`と`api_key`は別の名前です
* キーの値が間違っている、余分な空白と一緒にコピーされた、または削除済みのキーを使っている

**解決方法：** `ApiKey: your_key_here`という形式でヘッダーが送信されていることと、[ダッシュボード](https://api.sorsa.io/overview/keys)でキーが有効であることを確認してください。不明な場合はダッシュボードから直接キーをコピーします。詳しくは[認証](https://docs.sorsa.io/ja/authentication)を参照してください。

## 403 Forbidden

APIキーは有効ですが、リクエストが拒否されました。

**よくある原因**

* リクエストの割り当て量を使い切った（残り0件）
* サブスクリプションの有効期限が切れた

**解決方法：** `GET /key-usage-info`または[ダッシュボード](https://api.sorsa.io/overview)で残高を確認してください。使い切っている場合は、[請求](https://api.sorsa.io/overview/billing)ページで追加購入またはプランのアップグレードを行います。

## 404 Not Found

要求したリソースが存在しません。

**よくある原因**

* Xユーザーがユーザー名を変更した、アカウントを削除した、または凍結された
* 投稿者がツイートを削除した
* アカウントやツイートが非公開（保護されている）。Sorsaが取得できるのは公開データのみです
* エンドポイントのURL自体が間違っている

**解決方法：** ユーザーやツイートが現在も存在し、X上で一般公開されていることを確認してください。ユーザー名が変わってもユーザーIDは変わりません。保存済みのIDがある場合は、`/id-to-username/{user_id}`で現在のユーザー名を取得するか、対応するエンドポイントに`user_id`を直接渡します。

## 429 Too Many Requests

毎秒20リクエストのレート制限を超えています。

**よくある原因**

* 待機時間のないループでリクエストを送信している
* 同じAPIキーを共有する複数のワーカーを並列実行している

**解決方法：** リクエスト間に短い待機時間を入れるか（単一の順次処理ワーカーなら50ms。キーを共有する場合は全体の速度調整が必要）、1秒待機して再試行する処理を追加してください。方法とコード例は[レート制限](https://docs.sorsa.io/ja/rate-limits)を参照してください。

## 500 Internal Server Error

Sorsa側で問題が発生しました。

**対処方法**

* 1〜2秒待って再試行してください。一時的な500エラーは自然に解消することがよくあります。
* 再試行しても続く場合や、複数のエンドポイントに影響がある場合は、[稼働状況ページ](https://uptime.sorsa.io/status/v3)で障害情報を確認してください。
* 解消しない場合は、エンドポイントURL、リクエスト本文、おおよその発生時刻を添えて、[contacts@sorsa.io](mailto:contacts@sorsa.io)または[Discord](https://discord.com/invite/uwAefKCj7X)でサポートに連絡してください。調査資料からAPIキーと認証ヘッダーを取り除いてください。

## コードでのエラー処理

堅牢な連携では、想定外のレスポンスで停止するのではなく、各エラーコードに適切に対応します。次はPythonとJavaScriptで再利用できる実装例です。

**Python**

```python theme={null}
import time
import requests

def sorsa_request(method, endpoint, api_key, params=None, json_body=None, max_attempts=3):
    """GET/POST data retrieval with bounded retries; max_attempts includes the first call."""
    method = method.upper()
    if method not in {"GET", "POST"}:
        raise ValueError("Use GET or POST")
    if max_attempts < 1:
        raise ValueError("max_attempts must be positive")
    url = f"https://api.sorsa.io/v3{endpoint}"

    for attempt in range(max_attempts):
        try:
            response = requests.request(
                method, url, headers={"ApiKey": api_key},
                params=params, json=json_body, timeout=30,
            )
        except (requests.Timeout, requests.ConnectionError):
            if attempt + 1 == max_attempts:
                raise
        else:
            if response.ok:
                return response.json()
            retryable = response.status_code == 429 or response.status_code >= 500
            if not retryable or attempt + 1 == max_attempts:
                try:
                    message = response.json().get("message", response.reason)
                except (ValueError, AttributeError):
                    message = response.reason
                raise requests.HTTPError(
                    f"HTTP {response.status_code}: {message}", response=response,
                )
        time.sleep(min(2 ** attempt, 8))

data = sorsa_request("GET", "/info", "YOUR_API_KEY", params={"username": "elonmusk"})
print(data["display_name"])
```

**JavaScript**

```javascript theme={null}
async function sorsaRequest(method, endpoint, apiKey, body = null, maxAttempts = 3) {
  method = method.toUpperCase();
  if (!["GET", "POST"].includes(method)) throw new Error("Use GET or POST");
  if (!Number.isInteger(maxAttempts) || maxAttempts < 1) {
    throw new Error("maxAttempts must be a positive integer");
  }
  if (method === "GET" && body !== null) throw new Error("Use query parameters for GET");
  const url = `https://api.sorsa.io/v3${endpoint}`;
  const options = { method, headers: { ApiKey: apiKey } };
  if (body !== null) {
    options.headers["Content-Type"] = "application/json";
    options.body = JSON.stringify(body);
  }

  for (let attempt = 0; attempt < maxAttempts; attempt++) {
    let response;
    try {
      response = await fetch(url, { ...options, signal: AbortSignal.timeout(30000) });
    } catch (error) {
      if (attempt + 1 === maxAttempts) throw error;
      await new Promise((r) => setTimeout(r, Math.min(2 ** attempt, 8) * 1000));
      continue;
    }
    if (response.ok) return await response.json();
    const retryable = response.status === 429 || response.status >= 500;
    if (!retryable || attempt + 1 === maxAttempts) {
      let message = response.statusText;
      try { message = (await response.json()).message || message; } catch {}
      throw new Error(`HTTP ${response.status}: ${message}`);
    }
    await new Promise((r) => setTimeout(r, Math.min(2 ** attempt, 8) * 1000));
  }
}

const data = await sorsaRequest("GET", "/info?username=elonmusk", "YOUR_API_KEY");
console.log(data.display_name);
```

これらの例は、ネットワークのタイムアウト、接続失敗、`429`、`5xx`を再試行します。デフォルトの最大試行回数は3回です。それ以外のHTTPエラーでは直ちに失敗します。成功レスポンスでもJSONが無効なら、内容を調査できるよう失敗として扱います。JavaScriptはNode.js 18以降で実行してください。Pythonでは事前に`requests`パッケージをインストールします。

## 次のステップ

* [レート制限](https://docs.sorsa.io/ja/rate-limits)：毎秒20リクエスト以内に収める方法
* [ページネーション](https://docs.sorsa.io/ja/pagination)：大量のデータをエラーなく取得する
* [APIリファレンス](https://docs.sorsa.io/ja/api-reference-guide)：パラメータースキーマを含む全エンドポイントの一覧
