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'
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());
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)
OAuth en het MCP-protocol
Wissel een autorisatiecode in of roteer een vernieuwingstoken
Verkrijg kort geldige MCP-toegangstokens met de S256-autorisatiecode of het huidige vernieuwingstoken van een publieke client.
POST
/
oauth
/
token
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'
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());
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)
Verkrijg kort geldige MCP-toegangstokens met de S256-autorisatiecode of het huidige vernieuwingstoken van een publieke client.
POST https://api.voicecheap.ai/oauth/token
Authenticatie
Geen HTTP-clientauthenticatie. Stuur client_id in de URL-gecodeerde body. Elke Authorization-header, client_secret of client_assertion wordt geweigerd.Aanvraagbody
Tonen grant_type: authorization_code
Tonen grant_type: authorization_code
string
vereist
De client_id uit dynamische registratie of de exacte openbare HTTPS-URL van het clientmetadatadocument.Minimale lengte: 1. Maximale lengte: 2048. Patroon:
^[^\u0000-\u001F\u007F]+$.string
vereist
Vereiste exacte resource-audience: gebruik de resource-waarde uit de metadata van de beschermde resource van deze omgeving. In productie is dit https://api.voicecheap.ai/mcp. Een andere origin, een ander pad of een afsluitende slash wordt geweigerd.Formaat: “uri”.
field
vereist
Waarde zoals gedefinieerd in het volledige invoerschema.Vereiste waarde: “authorization_code”.
string
vereist
Eenmalige code die naar de exact geregistreerde callback wordt teruggestuurd.Minimale lengte: 1. Maximale lengte: 256. Patroon:
^mcp_code_[A-Za-z0-9_-]{43}$.string
vereist
Moet exact gelijk zijn aan de callback die aan deze code en registratie is gekoppeld.Minimale lengte: 1. Maximale lengte: 2048. Patroon:
^[^\u0000-\u001F\u007F]+$.string
vereist
Oorspronkelijke PKCE-verifier die is gebruikt om de S256 code_challenge van de autorisatieaanvraag te berekenen.Minimale lengte: 43. Maximale lengte: 128. Patroon:
^[A-Za-z0-9._~-]{43,128}$.Tonen grant_type: refresh_token
Tonen grant_type: refresh_token
string
vereist
De client_id uit dynamische registratie of de exacte openbare HTTPS-URL van het clientmetadatadocument.Minimale lengte: 1. Maximale lengte: 2048. Patroon:
^[^\u0000-\u001F\u007F]+$.string
vereist
Vereiste exacte resource-audience: gebruik de resource-waarde uit de metadata van de beschermde resource van deze omgeving. In productie is dit https://api.voicecheap.ai/mcp. Een andere origin, een ander pad of een afsluitende slash wordt geweigerd.Formaat: “uri”.
field
vereist
Waarde zoals gedefinieerd in het volledige invoerschema.Vereiste waarde: “refresh_token”.
string
vereist
Het huidige, nog niet gebruikte vernieuwingstoken van een client die voor refresh_token is geregistreerd.Minimale lengte: 1. Maximale lengte: 256. Patroon:
^mcp_refresh_[A-Za-z0-9_-]{43}$.string
Door spaties gescheiden deelverzameling van de oorspronkelijke rechten, eventueel met offline_access. Niet-ondersteunde namen, lege waarden en extra rechten worden geweigerd; duplicaten worden verwijderd. Een expliciete scope behoudt alleen de genoemde product- en identiteitsrechten en kan alle productrechten verwijderen. Laat scope weg om de huidige autorisatie te behouden, behalve dat identiteitsrechten vervallen als OpenID Connect niet beschikbaar is.Minimale lengte: 1. Maximale lengte: 2048. Patroon:
^ *(?: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))* *$.Technisch schema
Technisch schema
{
"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
}
]
}
Voorbeeldaanvragen
Volg de gedocumenteerde codering en authenticatie voor deze route. De antwoordstructuur en idempotentieregels van de actie-API gelden alleen voor actieaanroepen.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'
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());
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)
Antwoord
Een ondoorzichtig Bearer-toegangstoken, de resterende geldigheidsduur in seconden, toegekende machtigingen en een vernieuwingstoken wanneer de client refresh_token heeft geregistreerd. expires_in is maximaal 900 en kan lager zijn wanneer de autorisatie bijna verloopt.HTTP 200
{
"access_token": "mcp_access_DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD",
"token_type": "Bearer",
"expires_in": 900,
"refresh_token": "mcp_refresh_EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE",
"scope": "account:read projects:read offline_access"
}
Antwoordheaders
{
"Cache-Control": "no-store",
"Pragma": "no-cache"
}
Opmerkingen bij de bewerking
- Herkende scalaire parameters moeten eenmaal worden opgegeven als niet-lege strings zonder ASCII-besturingstekens of DEL. Herhaalde query-/formuliervelden worden gedecodeerd als arrays en geweigerd wanneer ze als scalaire waarden worden gelezen.
- Gebruik URL-gecodeerde formuliergegevens, zoals curl —data-urlencode per veld. Een JSON-tokenbody wordt geweigerd met invalid_request.
- De resource-audience is vereist voor beide granttypen en moet exact overeenkomen met de MCP-URL van de omgeving die de code of het vernieuwingstoken heeft uitgegeven.
- Voor het inwisselen van een autorisatiecode zijn de oorspronkelijke client_id, exacte redirect_uri en overeenkomende S256 code_verifier vereist. Codes verlopen na 2 minuten en zijn eenmalig te gebruiken.
- Het tokeneindpunt weigert elke opgegeven Authorization-header, inclusief Basic en Bearer, evenals elk bodyveld client_secret of client_assertion.
- Toegangstokens zijn maximaal 15 minuten geldig. Wanneer refresh_token is geregistreerd, verlopen de verbinding en de vernieuwingstokenfamilie 30 dagen nadat de gebruiker toestemming heeft gegeven; rotatie verlengt die termijn niet.
- Of refresh_token wordt geretourneerd, hangt af van de geregistreerde granttypen. Het hangt niet af van het opnemen van offline_access in de autorisatieaanvraag. De geretourneerde scope voegt offline_access toe wanneer een vernieuwingstoken wordt geretourneerd.
- Stuur voor vernieuwing grant_type=refresh_token met client_id, de huidige refresh_token, resource en optioneel een beperktere scope. Vervang het opgeslagen vernieuwingstoken atomair door de nieuwe waarde.
- Hergebruik van een verbruikte autorisatiecode of geroteerd vernieuwingstoken trekt de volledige verbinding in, inclusief alle bijbehorende toegangstokens. Wissel dezelfde code of hetzelfde vernieuwingstoken niet gelijktijdig in.
- Vernieuwingsverzoeken voegen nooit rechten toe. Met een expliciete scope blijven alleen de gevraagde product- en identiteitsrechten behouden; offline_access behoudt geen weggelaten productrechten.
- Tokens zijn gebonden aan de gebruiker die toestemming verleent, de client, de resource-audience, het huidige teameigendom en actieve betaalde toegang. Bij ingetrokken toestemming of gewijzigd eigendom moet opnieuw verbinding worden gemaakt.
- De openbare tokenlimiet is 60 aanvragen per minuut per client-IP, gedeeld door alle workers. URL-gecodeerde body’s zijn beperkt tot 32 KiB.
- OAuth-fouten retourneren error en error_description. Fouten bij het parsen van de body kunnen eerder worden geretourneerd in de foutvorm van de integratieparser.
- openid en email zijn identiteitsrechten, los van productrechten, en worden alleen geaccepteerd als ze worden vermeld. email vereist openid. Bij de eerste autorisatie gebruikt een verzoek met alleen identiteitsscopes de standaardproductrechten die op het toestemmingsscherm staan.
- De client_id uit dynamische registratie of de exacte openbare HTTPS-URL van het clientmetadatadocument.
- Wanneer openid is verleend, geeft het uitwisselen van de autorisatiecode ook een met RS256 ondertekend id_token terug. Controleer de handtekening, uitgever, doelgroep, vervaltijd en nonce indien opgegeven. Verleende identiteitsscopes staan in scope van het tokenantwoord; vernieuwingsantwoorden geven geen nieuw id_token uit.
- Als OpenID Connect niet meer beschikbaar is, behoudt vernieuwen zonder scope de productrechten en verwijdert het de identiteitsrechten. Expliciet om niet-beschikbare identiteitsscopes vragen geeft invalid_scope terug.
- Als het account is verwijderd of uitgeschakeld, geeft het tokenendpoint invalid_grant met HTTP 400 terug.
Fouten
| HTTP-status | Code | Betekenis of herstel |
|---|---|---|
| 400 | invalid_request | De body of een herkende parameter is ongeldig, ontbreekt, is dubbel opgegeven of heeft de verkeerde codering. |
| 400 | invalid_client | De client_id is onbekend, er is HTTP-clientauthenticatie opgegeven, of er is een client_secret/client_assertion opgegeven. |
| 400 | invalid_target | De resourcedoelgroep ontbreekt of komt niet exact overeen met de MCP-resource. |
| 400 | unsupported_grant_type | De grant wordt niet ondersteund, of refresh_token is niet voor deze client geregistreerd. |
| 400 | invalid_grant | De code of het token is ongeldig, verlopen, ingetrokken, opnieuw gebruikt, komt niet overeen of is niet langer geautoriseerd voor het huidige account/team. |
| 400 | invalid_scope | Een vernieuwingsaanvraag probeert machtigingen toe te voegen of bevat niet-ondersteunde scopes. |
| 413 | REQUEST_TOO_LARGE | De aanvraag overschrijdt de toegestane bodygrootte. JSON is beperkt tot 1 MiB en URL-gecodeerde formulieren tot 32 KiB. |
| 415 | UNSUPPORTED_CONTENT_TYPE | De bodyparser van de integratie accepteert alleen JSON of URL-gecodeerde formulieren. De route kan specifiek een van deze coderingen vereisen. |
| 429 | temporarily_unavailable | De openbare frequentielimiet voor OAuth-aanvragen is bereikt. Wacht tot het huidige tijdvenster voorbij is voordat je het opnieuw probeert. |
| 500 | server_error | Autorisatie is tijdelijk niet beschikbaar. Probeer het later opnieuw. |
Was deze pagina nuttig?

