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

# 認可コードの交換またはリフレッシュトークンのローテーション

> パブリッククライアントの S256 認可コード、または現在のリフレッシュトークンを使用して、有効期間の短い MCP アクセストークンを取得します。

パブリッククライアントの S256 認可コード、または現在のリフレッシュトークンを使用して、有効期間の短い MCP アクセストークンを取得します。

```http theme={null}
POST https://api.voicecheap.ai/oauth/token
```

## 認証

HTTPクライアント認証は行いません。URLエンコードされた本文に client\_id を送信してください。Authorization ヘッダー、client\_secret、client\_assertion はすべて拒否します。

## リクエストボディ

<Expandable title="grant_type: authorization_code">
  <ParamField body="client_id" type="string" required>
    動的登録で返された client\_id、またはクライアントメタデータドキュメントの正確な公開 HTTPS URL。

    最小文字数: 1. 最大文字数: 2048. パターン: `^[^\u0000-\u001F\u007F]+$`.
  </ParamField>

  <ParamField body="resource" type="string" required>
    リソースオーディエンスは完全一致が必要です。この環境の保護対象リソースのメタデータから resource の値を使用してください。本番環境では [https://api.voicecheap.ai/mcp](https://api.voicecheap.ai/mcp) です。異なるオリジン、パス、末尾のスラッシュは拒否されます。

    形式: "uri".
  </ParamField>

  <ParamField body="grant_type" type="field" required>
    完全な入力スキーマで定義された値。

    必須の値: "authorization\_code".
  </ParamField>

  <ParamField body="code" type="string" required>
    登録されたコールバックに完全一致する宛先へ返される、1 回限りのコード。

    最小文字数: 1. 最大文字数: 256. パターン: `^mcp_code_[A-Za-z0-9_-]{43}$`.
  </ParamField>

  <ParamField body="redirect_uri" type="string" required>
    このコードと登録に関連付けられたコールバックと、完全に一致する必要があります。

    最小文字数: 1. 最大文字数: 2048. パターン: `^[^\u0000-\u001F\u007F]+$`.
  </ParamField>

  <ParamField body="code_verifier" type="string" required>
    認可リクエストの S256 code\_challenge の計算に使用した、元のPKCE検証値。

    最小文字数: 43. 最大文字数: 128. パターン: `^[A-Za-z0-9._~-]{43,128}$`.
  </ParamField>
</Expandable>

<Expandable title="grant_type: refresh_token">
  <ParamField body="client_id" type="string" required>
    動的登録で返された client\_id、またはクライアントメタデータドキュメントの正確な公開 HTTPS URL。

    最小文字数: 1. 最大文字数: 2048. パターン: `^[^\u0000-\u001F\u007F]+$`.
  </ParamField>

  <ParamField body="resource" type="string" required>
    リソースオーディエンスは完全一致が必要です。この環境の保護対象リソースのメタデータから resource の値を使用してください。本番環境では [https://api.voicecheap.ai/mcp](https://api.voicecheap.ai/mcp) です。異なるオリジン、パス、末尾のスラッシュは拒否されます。

    形式: "uri".
  </ParamField>

  <ParamField body="grant_type" type="field" required>
    完全な入力スキーマで定義された値。

    必須の値: "refresh\_token".
  </ParamField>

  <ParamField body="refresh_token" type="string" required>
    refresh\_token を登録済みのクライアントの、現在の未使用リフレッシュトークン。

    最小文字数: 1. 最大文字数: 256. パターン: `^mcp_refresh_[A-Za-z0-9_-]{43}$`.
  </ParamField>

  <ParamField body="scope" type="string">
    元の権限の部分集合を空白区切りで指定します。offline\_access も含められます。未対応の名前、空の値、権限の追加は拒否され、重複は除去されます。scope を明示すると、指定した製品権限と ID 権限のみが保持され、製品権限をすべて削除することもできます。scope を省略すると現在の認可を保持しますが、OpenID Connect が利用できない場合は ID 権限を削除します。

    最小文字数: 1. 最大文字数: 2048. パターン: `^ *(?:account:read|usage:read|settings:read|settings:write|team:read|team:write|projects:read|projects:write|projects:delete|translations:write|transcription:read|transcription:write|subtitles:read|subtitles:write|tts:read|tts:write|voices:read|voices:write|images:read|images:write|thumbnails:read|thumbnails:write|folders:read|folders:write|glossary:read|glossary:write|webhooks:read|webhooks:write|publishing:read|publishing:write|offline_access|openid|email)(?: +(?:account:read|usage:read|settings:read|settings:write|team:read|team:write|projects:read|projects:write|projects:delete|translations:write|transcription:read|transcription:write|subtitles:read|subtitles:write|tts:read|tts:write|voices:read|voices:write|images:read|images:write|thumbnails:read|thumbnails:write|folders:read|folders:write|glossary:read|glossary:write|webhooks:read|webhooks:write|publishing:read|publishing:write|offline_access|openid|email))* *$`.
  </ParamField>
</Expandable>

<Accordion title="技術スキーマ">
  ```json theme={null}
  {
    "oneOf": [
      {
        "type": "object",
        "properties": {
          "client_id": {
            "type": "string",
            "minLength": 1,
            "maxLength": 2048,
            "pattern": "^[^\\u0000-\\u001F\\u007F]+$",
            "description": "The client_id returned by dynamic registration, or the exact public HTTPS URL of the client metadata document."
          },
          "resource": {
            "type": "string",
            "format": "uri",
            "description": "Required exact resource audience: use the resource value from this environment's protected-resource metadata. In production this is https://api.voicecheap.ai/mcp. A different origin, path, or trailing slash is rejected.",
            "examples": [
              "https://api.voicecheap.ai/mcp"
            ]
          },
          "grant_type": {
            "const": "authorization_code"
          },
          "code": {
            "type": "string",
            "minLength": 1,
            "maxLength": 256,
            "pattern": "^mcp_code_[A-Za-z0-9_-]{43}$",
            "description": "Single-use code returned to the exact registered callback."
          },
          "redirect_uri": {
            "type": "string",
            "minLength": 1,
            "maxLength": 2048,
            "pattern": "^[^\\u0000-\\u001F\\u007F]+$",
            "description": "Must exactly equal the callback bound to this code and registration."
          },
          "code_verifier": {
            "type": "string",
            "minLength": 43,
            "maxLength": 128,
            "pattern": "^[A-Za-z0-9._~-]{43,128}$",
            "description": "Original PKCE verifier used to calculate the authorization request's S256 code_challenge."
          }
        },
        "required": [
          "grant_type",
          "client_id",
          "resource",
          "code",
          "redirect_uri",
          "code_verifier"
        ],
        "not": {
          "anyOf": [
            {
              "required": [
                "client_secret"
              ]
            },
            {
              "required": [
                "client_assertion"
              ]
            }
          ]
        },
        "additionalProperties": true
      },
      {
        "type": "object",
        "properties": {
          "client_id": {
            "type": "string",
            "minLength": 1,
            "maxLength": 2048,
            "pattern": "^[^\\u0000-\\u001F\\u007F]+$",
            "description": "The client_id returned by dynamic registration, or the exact public HTTPS URL of the client metadata document."
          },
          "resource": {
            "type": "string",
            "format": "uri",
            "description": "Required exact resource audience: use the resource value from this environment's protected-resource metadata. In production this is https://api.voicecheap.ai/mcp. A different origin, path, or trailing slash is rejected.",
            "examples": [
              "https://api.voicecheap.ai/mcp"
            ]
          },
          "grant_type": {
            "const": "refresh_token"
          },
          "refresh_token": {
            "type": "string",
            "minLength": 1,
            "maxLength": 256,
            "pattern": "^mcp_refresh_[A-Za-z0-9_-]{43}$",
            "description": "The current unconsumed refresh token from a client registered for refresh_token."
          },
          "scope": {
            "type": "string",
            "minLength": 1,
            "maxLength": 2048,
            "pattern": "^ *(?:account:read|usage:read|settings:read|settings:write|team:read|team:write|projects:read|projects:write|projects:delete|translations:write|transcription:read|transcription:write|subtitles:read|subtitles:write|tts:read|tts:write|voices:read|voices:write|images:read|images:write|thumbnails:read|thumbnails:write|folders:read|folders:write|glossary:read|glossary:write|webhooks:read|webhooks:write|publishing:read|publishing:write|offline_access|openid|email)(?: +(?:account:read|usage:read|settings:read|settings:write|team:read|team:write|projects:read|projects:write|projects:delete|translations:write|transcription:read|transcription:write|subtitles:read|subtitles:write|tts:read|tts:write|voices:read|voices:write|images:read|images:write|thumbnails:read|thumbnails:write|folders:read|folders:write|glossary:read|glossary:write|webhooks:read|webhooks:write|publishing:read|publishing:write|offline_access|openid|email))* *$",
            "description": "Space-delimited subset of the original permissions, optionally including offline_access. Unsupported names, empty values, and added permissions are rejected; duplicates are removed. An explicit scope keeps only the listed product and identity permissions and may remove every product permission. Omit scope to retain the current grant, except identity permissions are dropped if OpenID Connect is unavailable.",
            "examples": [
              "account:read projects:read offline_access"
            ]
          }
        },
        "required": [
          "grant_type",
          "client_id",
          "resource",
          "refresh_token"
        ],
        "not": {
          "anyOf": [
            {
              "required": [
                "client_secret"
              ]
            },
            {
              "required": [
                "client_assertion"
              ]
            }
          ]
        },
        "additionalProperties": true
      }
    ]
  }
  ```
</Accordion>

## リクエスト例

このルートに記載されたエンコード方式と認証方法に従ってください。アクション API のエンベロープと冪等性のルールは、アクションの呼び出しにのみ適用されます。

<RequestExample>
  ```bash cURL theme={null}
  curl --request POST 'https://api.voicecheap.ai/oauth/token' \
    --header 'Content-Type: application/x-www-form-urlencoded' \
    --data-urlencode 'grant_type=authorization_code' \
    --data-urlencode 'client_id=mcp_client_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' \
    --data-urlencode 'code=mcp_code_CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC' \
    --data-urlencode 'redirect_uri=https://assistant.example.com/oauth/callback' \
    --data-urlencode 'code_verifier=dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk' \
    --data-urlencode 'resource=https://api.voicecheap.ai/mcp'
  ```

  ```javascript JavaScript theme={null}
  const input = {
    grant_type: 'authorization_code',
    client_id: 'mcp_client_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA',
    code: 'mcp_code_CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC',
    redirect_uri: 'https://assistant.example.com/oauth/callback',
    code_verifier: 'dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk',
    resource: 'https://api.voicecheap.ai/mcp',
  };
  const response = await fetch('https://api.voicecheap.ai/oauth/token', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/x-www-form-urlencoded',
    },
    body: new URLSearchParams(input),
    redirect: 'manual',
  });
  console.log(response.status, await response.text());
  ```

  ```python Python theme={null}
  import os
  import requests

  response = requests.request(
      "POST",
      "https://api.voicecheap.ai/oauth/token",
      headers={"Content-Type":"application/x-www-form-urlencoded"},
      data={"grant_type": "authorization_code", "client_id": "mcp_client_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", "code": "mcp_code_CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC", "redirect_uri": "https://assistant.example.com/oauth/callback", "code_verifier": "dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk", "resource": "https://api.voicecheap.ai/mcp"},
      timeout=120,
      allow_redirects=False,
  )
  print(response.status_code, response.text)
  ```
</RequestExample>

## レスポンス

不透明な Bearer アクセストークン、その残りの有効期間（秒）、付与されたスコープ、およびクライアントが refresh\_token を登録している場合はリフレッシュトークン。expires\_in は最大 900 で、認可の期限が近い場合は短くなることがあります。

```json HTTP 200 theme={null}
{
  "access_token": "mcp_access_DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD",
  "token_type": "Bearer",
  "expires_in": 900,
  "refresh_token": "mcp_refresh_EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE",
  "scope": "account:read projects:read offline_access"
}
```

## レスポンスヘッダー

```json theme={null}
{
  "Cache-Control": "no-store",
  "Pragma": "no-cache"
}
```

## 操作の注意事項

* 認識されるスカラーパラメーターは、ASCII 制御文字や DEL を含まない空でない文字列として、1回だけ指定する必要があります。重複するクエリ／フォームフィールドは配列にデコードされ、スカラーとして読み取る際に拒否されます。
* 各フィールドに curl --data-urlencode を使うなど、URL エンコードされたフォームデータを使用してください。トークン本文が JSON の場合、invalid\_request で拒否されます。
* どちらの認可方式でも resource オーディエンスが必須です。コードまたはリフレッシュトークンを発行した環境の MCP URL と完全に一致する必要があります。
* 認可コードの交換には、元の client\_id、完全一致する redirect\_uri、対応する S256 code\_verifier が必要です。コードの有効期間は2分で、1回限り使用できます。
* トークンエンドポイントは、Basic と Bearer を含むすべての Authorization ヘッダー、および本文の client\_secret または client\_assertion フィールドを拒否します。
* アクセストークンの有効期間は最大15分です。refresh\_token を登録している場合、接続とリフレッシュトークンファミリーは、ユーザーの承認から30日後に失効します。ローテーションによって期限は延長されません。
* refresh\_token が返されるかどうかは、登録されたグラントタイプによって決まります。認可リクエストに offline\_access を含めるかどうかには依存しません。リフレッシュトークンが返される場合、返却される scope に必ず offline\_access が追加されます。
* 更新するには、grant\_type=refresh\_token に client\_id、現在の refresh\_token、resource、任意で権限を絞った scope を添えて送信してください。保存済みリフレッシュトークンは、新しい値にアトミックに置き換えてください。
* 使用済み認可コードまたはローテーション済みリフレッシュトークンを再利用すると、そのすべてのアクセストークンを含めて接続全体が失効します。同じコードやリフレッシュトークンを同時に交換しないでください。
* 更新リクエストで権限が追加されることはありません。scope を明示した場合、要求した製品権限と ID 権限のみが保持されます。offline\_access は省略した製品権限を保持しません。
* トークンは、権限を付与したユーザー、クライアント、リソースオーディエンス、現在のチーム所有権、有効な有料アクセスに紐付けられます。権限付与の失効や所有権の変更があった場合は、再接続が必要です。
* 公開トークンエンドポイントの上限は、クライアント IP ごとに毎分 60 リクエストで、ワーカー間で共有されます。URL エンコードされた本文は 32 KiB 以内です。
* OAuth の失敗時は error と error\_description が返されます。本文の解析エラーは、それより前に連携パーサーのエラー形式で返される場合があります。
* openid と email は製品権限とは別の ID 権限であり、公開されている場合のみ受け付けられます。email には openid が必要です。初回の認可で ID スコープのみを指定すると、同意画面に表示される既定の製品権限が使われます。
* 動的登録で返された client\_id、またはクライアントメタデータドキュメントの正確な公開 HTTPS URL。
* openid が付与されると、認可コードの交換で RS256 署名付きの id\_token も返されます。署名、発行者、対象、有効期限、指定した場合は nonce を検証してください。付与された ID スコープはトークン応答の scope に含まれます。更新応答では新しい id\_token は発行されません。
* OpenID Connect が利用できなくなった場合、scope を指定せずに更新すると、製品権限は保持され、ID 権限は削除されます。利用できない ID スコープを明示的に要求すると invalid\_scope が返されます。
* アカウントが削除または無効化されている場合、トークンエンドポイントは HTTP 400 で invalid\_grant を返します。

## エラー

| HTTP ステータス | コード | 意味または対処方法 |
| - | - | - |
| 400 | `invalid_request` | 本文または認識されたパラメーターが無効、不足、重複、またはエンコード不正です。 |
| 400 | `invalid_client` | client\_id が不明、クライアント HTTP 認証が指定された、または client\_secret/client\_assertion が指定されました。 |
| 400 | `invalid_target` | リソースの audience がないか、MCP リソースと完全に一致しません。 |
| 400 | `unsupported_grant_type` | グラントが未対応、またはこのクライアントに refresh\_token が登録されていません。 |
| 400 | `invalid_grant` | コードまたはトークンが無効、期限切れ、失効済み、再使用済み、不一致、または現在のアカウント/チームで認可されなくなっています。 |
| 400 | `invalid_scope` | リフレッシュリクエストが権限を追加しようとしているか、未対応のスコープを含んでいます。 |
| 413 | `REQUEST_TOO_LARGE` | リクエストが許可された本文サイズを超えています。JSONの上限は 1 MiB、URLエンコードされたフォームの上限は 32 KiB です。 |
| 415 | `UNSUPPORTED_CONTENT_TYPE` | 連携の本文パーサーは JSON または URL エンコードされたフォームのみを受け付けます。ルートによっては、どちらか一方のエンコード方式が必須です。 |
| 429 | `temporarily_unavailable` | 公開 OAuth リクエストのレート上限に達しました。現在の制限期間が終わってから再試行してください。 |
| 500 | `server_error` | 認可を一時的に利用できません。後で再試行してください。 |


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