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

# Scambia un codice di autorizzazione o ruota un refresh token

> Ottieni token di accesso MCP di breve durata usando il codice di autorizzazione S256 di un client pubblico o il suo token di aggiornamento corrente.

Ottieni token di accesso MCP di breve durata usando il codice di autorizzazione S256 di un client pubblico o il suo token di aggiornamento corrente.

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

## Autenticazione

Nessuna autenticazione HTTP del client. Invia client\_id nel corpo con codifica URL. Qualsiasi header Authorization, client\_secret o client\_assertion viene rifiutato.

## Corpo della richiesta

<Expandable title="grant_type: authorization_code">
  <ParamField body="client_id" type="string" required>
    Il client\_id restituito dalla registrazione dinamica o l’URL HTTPS pubblico esatto del documento di metadati del client.

    Lunghezza minima: 1. Lunghezza massima: 2048. Pattern: `^[^\u0000-\u001F\u007F]+$`.
  </ParamField>

  <ParamField body="resource" type="string" required>
    Audience esatta della risorsa richiesta: usa il valore resource dei metadati della risorsa protetta di questo ambiente. In produzione è [https://api.voicecheap.ai/mcp](https://api.voicecheap.ai/mcp). Un'origine, un percorso o una barra finale differenti vengono rifiutati.

    Formato: "uri".
  </ParamField>

  <ParamField body="grant_type" type="field" required>
    Valore definito dallo schema di input completo.

    Valore obbligatorio: "authorization\_code".
  </ParamField>

  <ParamField body="code" type="string" required>
    Codice monouso restituito al callback esatto registrato.

    Lunghezza minima: 1. Lunghezza massima: 256. Pattern: `^mcp_code_[A-Za-z0-9_-]{43}$`.
  </ParamField>

  <ParamField body="redirect_uri" type="string" required>
    Deve essere esattamente uguale al callback associato a questo codice e a questa registrazione.

    Lunghezza minima: 1. Lunghezza massima: 2048. Pattern: `^[^\u0000-\u001F\u007F]+$`.
  </ParamField>

  <ParamField body="code_verifier" type="string" required>
    Verificatore PKCE originale usato per calcolare il code\_challenge S256 della richiesta di autorizzazione.

    Lunghezza minima: 43. Lunghezza massima: 128. Pattern: `^[A-Za-z0-9._~-]{43,128}$`.
  </ParamField>
</Expandable>

<Expandable title="grant_type: refresh_token">
  <ParamField body="client_id" type="string" required>
    Il client\_id restituito dalla registrazione dinamica o l’URL HTTPS pubblico esatto del documento di metadati del client.

    Lunghezza minima: 1. Lunghezza massima: 2048. Pattern: `^[^\u0000-\u001F\u007F]+$`.
  </ParamField>

  <ParamField body="resource" type="string" required>
    Audience esatta della risorsa richiesta: usa il valore resource dei metadati della risorsa protetta di questo ambiente. In produzione è [https://api.voicecheap.ai/mcp](https://api.voicecheap.ai/mcp). Un'origine, un percorso o una barra finale differenti vengono rifiutati.

    Formato: "uri".
  </ParamField>

  <ParamField body="grant_type" type="field" required>
    Valore definito dallo schema di input completo.

    Valore obbligatorio: "refresh\_token".
  </ParamField>

  <ParamField body="refresh_token" type="string" required>
    Il refresh token corrente non ancora utilizzato di un client registrato per refresh\_token.

    Lunghezza minima: 1. Lunghezza massima: 256. Pattern: `^mcp_refresh_[A-Za-z0-9_-]{43}$`.
  </ParamField>

  <ParamField body="scope" type="string">
    Sottoinsieme delle autorizzazioni originali separato da spazi, che può includere offline\_access. Nomi non supportati, valori vuoti e autorizzazioni aggiunte vengono rifiutati; i duplicati vengono rimossi. Uno scope esplicito conserva solo le autorizzazioni di prodotto e identità elencate e può rimuovere tutte quelle di prodotto. Ometti scope per conservare l’autorizzazione attuale, tranne le autorizzazioni di identità, che vengono rimosse se OpenID Connect non è disponibile.

    Lunghezza minima: 1. Lunghezza massima: 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))* *$`.
  </ParamField>
</Expandable>

<Accordion title="Schema tecnico">
  ```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>

## Esempi di richiesta

Segui la codifica e l'autenticazione documentate per questa route. L'involucro e le regole di idempotenza dell'API delle azioni si applicano solo alle invocazioni di azioni.

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

## Risposta

Un token di accesso Bearer opaco, la durata residua in secondi, gli scope concessi e un refresh token quando il client ha registrato refresh\_token. expires\_in è al massimo 900 e può essere inferiore in prossimità della scadenza dell'autorizzazione.

```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"
}
```

## Intestazioni della risposta

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

## Note sull'operazione

* I parametri scalari riconosciuti devono essere forniti una sola volta come stringhe non vuote, senza caratteri di controllo ASCII o DEL. I campi ripetuti nella query o nel modulo vengono decodificati come array e rifiutati quando vengono letti come scalari.
* Usa dati di modulo con codifica URL, ad esempio curl --data-urlencode per ciascun campo. Un corpo del token in JSON viene rifiutato con invalid\_request.
* Il destinatario resource è obbligatorio per entrambi i tipi di grant e deve corrispondere esattamente all'URL MCP dell'ambiente che ha emesso il codice o il token di aggiornamento.
* Lo scambio del codice di autorizzazione richiede il client\_id originale, l'esatto redirect\_uri e il code\_verifier S256 corrispondente. I codici scadono dopo 2 minuti e sono monouso.
* L'endpoint dei token rifiuta qualsiasi header Authorization fornito, inclusi Basic e Bearer, oltre a qualsiasi campo client\_secret o client\_assertion nel corpo.
* I token di accesso durano al massimo 15 minuti. Con refresh\_token registrato, la connessione e la famiglia di refresh token scadono 30 giorni dopo l'approvazione dell'utente; la rotazione non prolunga tale scadenza.
* La restituzione di refresh\_token dipende dai tipi di concessione registrati. Non dipende dall'inclusione di offline\_access nella richiesta di autorizzazione. Lo scope restituito aggiunge offline\_access ogni volta che viene restituito un token di aggiornamento.
* Per rinnovare, invia grant\_type=refresh\_token con client\_id, il refresh\_token corrente, resource e, facoltativamente, uno scope più ristretto. Sostituisci in modo atomico il refresh token archiviato con il nuovo valore.
* Il riutilizzo di un codice di autorizzazione già consumato o di un token di aggiornamento ruotato revoca l'intera connessione, inclusi tutti i relativi token di accesso. Non riscattare contemporaneamente lo stesso codice o token di aggiornamento.
* Le richieste di rinnovo non aggiungono mai autorizzazioni. Con uno scope esplicito vengono conservate solo le autorizzazioni di prodotto e identità richieste; offline\_access non conserva le autorizzazioni di prodotto omesse.
* I token sono vincolati all'utente che concede l'autorizzazione, al client, all'audience della risorsa, alla proprietà corrente del team e all'accesso a pagamento attivo. Un'autorizzazione revocata o un cambio di proprietà richiedono una nuova connessione.
* Il limite pubblico per i token è di 60 richieste al minuto per IP del client, condiviso tra i worker. I corpi con codifica URL sono limitati a 32 KiB.
* Gli errori OAuth restituiscono error e error\_description. Gli errori del parser del corpo possono essere restituiti prima, nel formato di errore del parser dell'integrazione.
* openid ed email sono autorizzazioni di identità, separate da quelle del prodotto, accettate solo se dichiarate. email richiede openid. Durante l’autorizzazione iniziale, una richiesta con soli ambiti di identità usa le autorizzazioni di prodotto predefinite mostrate nella schermata di consenso.
* Il client\_id restituito dalla registrazione dinamica o l’URL HTTPS pubblico esatto del documento di metadati del client.
* Quando openid è concesso, lo scambio del codice di autorizzazione restituisce anche un id\_token firmato con RS256. Verifica firma, emittente, destinatario, scadenza e nonce, se fornito. Gli ambiti di identità concessi compaiono in scope della risposta; il rinnovo non emette un nuovo id\_token.
* Se OpenID Connect diventa indisponibile, il rinnovo senza scope conserva le autorizzazioni di prodotto e rimuove quelle di identità. Richiedere esplicitamente ambiti di identità indisponibili restituisce invalid\_scope.
* Se l’account è stato eliminato o disattivato, l’endpoint dei token restituisce invalid\_grant con HTTP 400.

## Errori

| Stato HTTP | Codice | Significato o risoluzione |
| - | - | - |
| 400 | `invalid_request` | Il corpo o un parametro riconosciuto non è valido, è mancante, è duplicato oppure ha una codifica errata. |
| 400 | `invalid_client` | Il client\_id è sconosciuto, è stata fornita l'autenticazione HTTP del client oppure è stato fornito un client\_secret/client\_assertion. |
| 400 | `invalid_target` | L'audience della risorsa è assente oppure non corrisponde esattamente alla risorsa MCP. |
| 400 | `unsupported_grant_type` | La concessione non è supportata oppure refresh\_token non è stato registrato per questo client. |
| 400 | `invalid_grant` | Il codice o il token non è valido, è scaduto, è stato revocato, è stato riutilizzato, non corrisponde oppure non è più autorizzato per l'account o il team attuale. |
| 400 | `invalid_scope` | Una richiesta di aggiornamento tenta di aggiungere autorizzazioni o contiene ambiti non supportati. |
| 413 | `REQUEST_TOO_LARGE` | La richiesta supera la dimensione consentita per il corpo. JSON è limitato a 1 MiB e i moduli con codifica URL a 32 KiB. |
| 415 | `UNSUPPORTED_CONTENT_TYPE` | Il parser del corpo dell'integrazione accetta solo JSON o moduli con codifica URL. La route può richiedere specificamente una di queste codifiche. |
| 429 | `temporarily_unavailable` | È stato raggiunto il limite di frequenza delle richieste OAuth pubbliche. Attendi il termine della finestra corrente prima di riprovare. |
| 500 | `server_error` | L'autorizzazione è temporaneamente non disponibile. Riprova più tardi. |


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