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

# BetterToken API のエラー対処とレート制限

> BetterToken API のエラーを HTTP ステータス、応答本文、リクエスト ID から診断。認証エラー、レート制限、タイムアウトの確認方法と、安全に再試行するための条件・コード例を紹介します。

BetterToken API のエラーは、HTTP ステータスと応答本文を合わせて診断します。`error.message` のリクエスト ID を記録し、認証や設定の誤りは再送信前に修正してください。一時的な障害と確認できた場合だけ再試行します。

## 診断の前に

Model ID、Base URL、失敗した応答を用意します。[BetterToken Dashboard](https://bettertoken.ai/workspace) で Key の状態と現在の残高を確認してください。まだモデルから応答を得ていない場合は、[SDK のサンプル](/ja/guides/sdk-examples.md)か[ツール設定ガイド](/ja/ai-tools/overview.md)から始めます。

## エラー応答を読む

BetterToken は API エラーを JSON 形式で返します。たとえば、Key を付けずにリクエストすると、次の応答が返る場合があります。

```json theme={null}
{
  "error": {
    "code": "",
    "message": "Token not provided (request id: …)",
    "type": "new_api_error"
  }
}
```

`error.message` は `error.code` が空でも読んでください。メッセージ内のリクエスト ID は、失敗した試行の特定に役立ちます。Key なしで `/v1/models` にリクエストすると `401` が返ります。この操作では、モデルが応答を生成できるかは確認できません。

サポートに問い合わせる前に、以下を記録してください。

| 項目 | 記録する内容 |
| - | - |
| HTTP ステータス | 応答ステータス。HTTP 応答がない場合はクライアントのタイムアウトやネットワーク例外 |
| 応答本文 | 機密情報を除いたエラー JSON、または返された本文 |
| リクエスト ID | `error.message` に識別子があれば記録 |
| 時刻 | 試行した日付、時刻、タイムゾーン |
| Model ID | `model` に指定した正確な値 |
| Base URL | 設定した Base URL と最終的なリクエストパス |

スクリーンショット、サポートへのメッセージ、共有ログに BetterToken API Key を含めないでください。

## HTTP ステータスを確認する

以下は一般的な HTTP/API の意味と、リンク先の設定ガイドに基づく表です。BetterToken 固有のエラーコード一覧ではありません。実際の応答を読んでから対処を選んでください。

| ステータス | 一般的な意味 | 最初に確認すること | 再試行の判断 |
| - | - | - | - |
| `400` | リクエスト、フィールド、パラメーターの組み合わせが不正 | JSON の構造、必須フィールド、モデル、エンドポイントの仕様 | まずリクエストを修正 |
| `401` | 認証情報がない、無効、期限切れ、または失効済み | Key の状態、余分な空白、プロトコルに合った認証ヘッダー | まず認証を修正 |
| `403` | リクエストが拒否された | 応答メッセージ、残高、Key の状態、クライアント設定 | まず拒否の原因を解消 |
| `404` | ルートや要求したリソースが見つからない | Base URL、`/v1` の重複や欠落、最終パス、正確な Model ID | まず URL やリソースを修正 |
| `408` / クライアントのタイムアウト | サーバーが時間内にリクエスト全体を受信できなかった、またはクライアントが待機を終了した | HTTP ステータスの有無、タイムアウト設定、ネットワーク、Dashboard の処理状況 | リクエストが完了したか確認して判断 |
| `409` / `422`（返された場合） | 一般に競合、または処理できない内容 | 応答の詳細と送信した状態やフィールド | まず原因を解消 |
| `429` | 制限に達した | 応答本文と再試行ヘッダー。[制限の診断 FAQ](/ja/faq/codex/usage-limit-vs-api-rate-limit.md)を参照 | 一時的なレート制限と確認できた場合のみ |
| `500` | サーバー側の障害 | リクエスト記録、メッセージ、障害が続いているか | 一時的な障害なら回数を制限して再試行 |
| `502` / `503` | ゲートウェイや上流の障害、または一時的に利用できない | 応答本文と `Retry-After` ヘッダーの有無 | 一時的な障害なら回数を制限して再試行 |
| `504` | ゲートウェイが上流の応答を待ってタイムアウトした | Dashboard の記録とリクエストが完了したか | 完了状況を確認してから再試行 |

プロトコルや末尾のパスの誤りは [Base URL の FAQ](/ja/faq/model-calling/base-url-config.md)、キャッシュについては[キャッシュ課金の FAQ](/ja/faq/service-assurance/cache-billing.md)を参照してください。

## 一時的な障害を再試行する

一時的な `429` やサーバー障害と確認できた場合は、ランダムな揺らぎを加えた指数バックオフを上限付きで使います。`Retry-After` があれば従ってください。再試行の待機時間の上限を超える場合は、ループを止めてから待機します。SDK と自作ループの試行回数は合算されるため、自分で再試行を実装する場合は SDK の再試行を無効にします。

原因を修正せずに `400`、`401`、`403`、残高不足、設定エラーを再試行しないでください。クライアントのタイムアウトやストリームの切断だけでは、処理前に失敗したとは判断できません。特に画像生成や同じ操作を繰り返す可能性がある処理では、まず **Dashboard** を確認します。

以下の例では、非ストリーミングの Chat Completions リクエストを最大四回試行します。HTTP `500`、`502`、`503` を再試行します。`429` は一時的なレート制限と確認するまで再試行を無効にしています。タイムアウト、ネットワーク例外、`504` では停止し、完了状況を確認できるようにします。一回あたりの再試行待機時間は最大 30 秒です。

### リクエストを準備する

[モデル広場](https://bettertoken.ai/pricing)から現在の Model ID をコピーし、二つのプレースホルダーを置き換えます。[Chat Completions](/ja/api-reference/chat-completions.md) で利用可能なテキストモデルを使ってください。

```bash theme={null}
export BETTERTOKEN_API_KEY="YOUR_API_KEY"
export BETTERTOKEN_MODEL_ID="YOUR_MODEL_ID"
```

Python の例は標準ライブラリだけを使います。JavaScript の例は `.mjs` ファイルとして保存し、`fetch` と `AbortSignal.timeout` を利用できる Node.js のバージョンで実行してください。

**Python**

```python theme={null}
import json
import os
import random
import time
import urllib.error
import urllib.request
from datetime import datetime, timezone
from email.utils import parsedate_to_datetime

def retry_after_seconds(value):
    try:
        return max(0.0, float(value))
    except ValueError:
        return max(0.0, (
            parsedate_to_datetime(value) - datetime.now(timezone.utc)
        ).total_seconds())

retry_temporary_429 = False  # Enable only after diagnosing the returned limit.
payload = json.dumps({
    "model": os.environ["BETTERTOKEN_MODEL_ID"],
    "messages": [{"role": "user", "content": "Reply with one word: OK"}],
}).encode()
for attempt in range(4):
    request = urllib.request.Request(
        "https://bettertoken.ai/v1/chat/completions", data=payload,
        headers={
            "Authorization": "Bearer " + os.environ["BETTERTOKEN_API_KEY"],
            "Content-Type": "application/json",
        },
    )
    try:
        with urllib.request.urlopen(request, timeout=120) as response:
            print(json.load(response)["choices"][0]["message"]["content"])
        break
    except urllib.error.HTTPError as error:
        body = error.read().decode("utf-8", errors="replace")
        retryable = error.code in (500, 502, 503) or (
            error.code == 429 and retry_temporary_429
        )
        if not retryable or attempt == 3:
            raise RuntimeError(f"HTTP {error.code}: {body}") from error
        delay = random.uniform(0, min(8.0, 2.0 ** attempt))
        retry_after = error.headers.get("Retry-After")
        if retry_after:
            delay = max(delay, retry_after_seconds(retry_after))
        if delay > 30:
            raise RuntimeError("Retry-After exceeds this retry budget") from error
        time.sleep(delay)
```

**JavaScript**

```javascript theme={null}
const retryTemporary429 = false; // Enable only after diagnosing the returned limit.
const payload = {
  model: process.env.BETTERTOKEN_MODEL_ID,
  messages: [{ role: "user", content: "Reply with one word: OK" }],
};
for (let attempt = 0; attempt < 4; attempt++) {
  const response = await fetch("https://bettertoken.ai/v1/chat/completions", {
    method: "POST",
    headers: {
      Authorization: `Bearer ${process.env.BETTERTOKEN_API_KEY}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify(payload),
    signal: AbortSignal.timeout(120000),
  });
  const body = await response.text();
  if (response.ok) {
    console.log(JSON.parse(body).choices[0].message.content);
    break;
  }
  const retryable = [500, 502, 503].includes(response.status) ||
    (response.status === 429 && retryTemporary429);
  if (!retryable || attempt === 3) {
    throw new Error(`HTTP ${response.status}: ${body}`);
  }
  let delay = Math.random() * Math.min(8000, 1000 * 2 ** attempt);
  const retryAfter = response.headers.get("Retry-After");
  if (retryAfter !== null) {
    const seconds = Number(retryAfter);
    const wait = Number.isFinite(seconds)
      ? seconds * 1000 : Date.parse(retryAfter) - Date.now();
    if (!Number.isFinite(wait)) throw new Error("Invalid Retry-After header");
    delay = Math.max(delay, wait, 0);
  }
  if (delay > 30000) throw new Error("Retry-After exceeds this retry budget");
  await new Promise(resolve => setTimeout(resolve, delay));
}
```

応答本文が継続的な設定、残高、アクセスの問題を示す場合は、ステータスだけでは再試行できそうに見えてもループを止めて修正してください。他の操作に応用する前に、この短いテキスト用の例に、アプリに合った完了確認を組み込んでください。

## 症状に合ったガイドを開く

| 症状 | 参照先 |
| - | - |
| Claude Code の認証、URL、モデルのエラー | [Claude Code のよくあるエラー](/ja/ai-tools/claude-code.md#common-errors) |
| Codex がログインを求める、またはプロバイダーの変更が反映されない | [Codex CLI / App のよくあるエラー](/ja/ai-tools/codex.md#common-errors) |
| Cursor で Key を有効にできない、または内蔵モデルが動かなくなった | [Cursor のよくあるエラー](/ja/ai-tools/cursor.md#common-errors) |
| Cline の認証、`404`、モデルのエラー | [Cline のよくあるエラー](/ja/ai-tools/cline.md#common-errors) |
| OpenCode のプロバイダー、モデル、プロジェクト設定による上書きのエラー | [OpenCode のよくあるエラー](/ja/ai-tools/opencode.md#common-errors) |
| Claude Desktop の Gateway に接続できない | [Claude Desktop のよくあるエラー](/ja/faq/claude-desktop-bettertoken-api.md#common-errors) |
| 公式 Codex の使用量の警告、または API の `429` | [使用量上限と API レート制限の違い](/ja/faq/codex/usage-limit-vs-api-rate-limit.md) |
| 変更が反映されない | [競合する環境変数の削除](/ja/best-practices.md#clear-conflicting-environment-variables) |
| 出力が途中で切れる、または出力上限のエラー | [出力トークン上限](/ja/faq/model-calling/max-tokens.md) |

## 修正を確認する

失敗したときと同じクライアント、Base URL、Model ID を使い、影響の小さい短いリクエストを一回送ります。正常な応答を確認し、**Dashboard** で対応する記録を探してください。モデル、状態、トークン使用量、料金を確認してから大きな処理を再開します。

## よくある質問

### 429 が返ったら必ず待って再試行すべきですか？

[使用量上限の診断 FAQ](/ja/faq/codex/usage-limit-vs-api-rate-limit.md)で、確認する内容と再試行が適切かを判断してください。

### 一度失敗したらタイムアウトを延ばすべきですか？

まずクライアント、プロキシ、上流のどこで待機が終了したかを調べます。[タイムアウトの設定ガイド](/ja/best-practices.md#set-a-generous-timeout)に従い、小さなリクエストで検証してください。

## 関連ガイド

* [SDK のリクエスト例](/ja/guides/sdk-examples.md)
* [ストリーミングとツール呼び出し](/ja/guides/streaming-and-tool-calling.md)
* [API リファレンス](/ja/api-reference/introduction.md)
* [対応ツール](/ja/ai-tools/overview.md)
* [キャッシュ課金の FAQ](/ja/faq/service-assurance/cache-billing.md)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.