curl --request GET 'https://api.voicecheap.ai/oauth/authorize?client_id=mcp_client_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA&redirect_uri=https%3A%2F%2Fassistant.example.com%2Foauth%2Fcallback&response_type=code&response_mode=query&code_challenge=E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM&code_challenge_method=S256&resource=https%3A%2F%2Fapi.voicecheap.ai%2Fmcp&scope=account%3Aread+projects%3Aread+offline_access&state=example-client-csrf-state'
const input = {
client_id: 'mcp_client_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA',
redirect_uri: 'https://assistant.example.com/oauth/callback',
response_type: 'code',
response_mode: 'query',
code_challenge: 'E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM',
code_challenge_method: 'S256',
resource: 'https://api.voicecheap.ai/mcp',
scope: 'account:read projects:read offline_access',
state: 'example-client-csrf-state',
};
const response = await fetch(
'https://api.voicecheap.ai/oauth/authorize?client_id=mcp_client_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA&redirect_uri=https%3A%2F%2Fassistant.example.com%2Foauth%2Fcallback&response_type=code&response_mode=query&code_challenge=E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM&code_challenge_method=S256&resource=https%3A%2F%2Fapi.voicecheap.ai%2Fmcp&scope=account%3Aread+projects%3Aread+offline_access&state=example-client-csrf-state',
{
method: 'GET',
headers: {},
redirect: 'manual',
},
);
console.log(response.status, await response.text());
import os
import requests
response = requests.request(
"GET",
"https://api.voicecheap.ai/oauth/authorize?client_id=mcp_client_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA&redirect_uri=https%3A%2F%2Fassistant.example.com%2Foauth%2Fcallback&response_type=code&response_mode=query&code_challenge=E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM&code_challenge_method=S256&resource=https%3A%2F%2Fapi.voicecheap.ai%2Fmcp&scope=account%3Aread+projects%3Aread+offline_access&state=example-client-csrf-state",
headers={},
timeout=120,
allow_redirects=False,
)
print(response.status_code, response.text)
OAuth en het MCP-protocol
Start MCP-accountautorisatie
Maak een kort geldige autorisatieaanvraag aan en stuur de gebruiker door naar de VoiceCheap-pagina voor aanmelden en toestemming voor machtigingen.
GET
/
oauth
/
authorize
curl --request GET 'https://api.voicecheap.ai/oauth/authorize?client_id=mcp_client_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA&redirect_uri=https%3A%2F%2Fassistant.example.com%2Foauth%2Fcallback&response_type=code&response_mode=query&code_challenge=E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM&code_challenge_method=S256&resource=https%3A%2F%2Fapi.voicecheap.ai%2Fmcp&scope=account%3Aread+projects%3Aread+offline_access&state=example-client-csrf-state'
const input = {
client_id: 'mcp_client_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA',
redirect_uri: 'https://assistant.example.com/oauth/callback',
response_type: 'code',
response_mode: 'query',
code_challenge: 'E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM',
code_challenge_method: 'S256',
resource: 'https://api.voicecheap.ai/mcp',
scope: 'account:read projects:read offline_access',
state: 'example-client-csrf-state',
};
const response = await fetch(
'https://api.voicecheap.ai/oauth/authorize?client_id=mcp_client_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA&redirect_uri=https%3A%2F%2Fassistant.example.com%2Foauth%2Fcallback&response_type=code&response_mode=query&code_challenge=E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM&code_challenge_method=S256&resource=https%3A%2F%2Fapi.voicecheap.ai%2Fmcp&scope=account%3Aread+projects%3Aread+offline_access&state=example-client-csrf-state',
{
method: 'GET',
headers: {},
redirect: 'manual',
},
);
console.log(response.status, await response.text());
import os
import requests
response = requests.request(
"GET",
"https://api.voicecheap.ai/oauth/authorize?client_id=mcp_client_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA&redirect_uri=https%3A%2F%2Fassistant.example.com%2Foauth%2Fcallback&response_type=code&response_mode=query&code_challenge=E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM&code_challenge_method=S256&resource=https%3A%2F%2Fapi.voicecheap.ai%2Fmcp&scope=account%3Aread+projects%3Aread+offline_access&state=example-client-csrf-state",
headers={},
timeout=120,
allow_redirects=False,
)
print(response.status_code, response.text)
Maak een kort geldige autorisatieaanvraag aan en stuur de gebruiker door naar de VoiceCheap-pagina voor aanmelden en toestemming voor machtigingen.
GET https://api.voicecheap.ai/oauth/authorize
Authenticatie
Geen op deze route. De daaropvolgende toestemmingsprocedure in de browser vereist dat de gebruiker zich aanmeldt, en goedkeuring vereist toegang tot een in aanmerking komend betaald account.Queryparameters
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
Moet exact overeenkomen met een van de geregistreerde redirect_uris van deze client.Minimale lengte: 1. Maximale lengte: 2048. Patroon:
^[^\u0000-\u001F\u007F]+$.field
vereist
Waarde zoals gedefinieerd in het volledige invoerschema.Vereiste waarde: “code”.
field
Waarde zoals gedefinieerd in het volledige invoerschema.Vereiste waarde: “query”. Standaardwaarde: “query”.
string
vereist
Base64url SHA-256-hash van de oorspronkelijke code_verifier, zonder opvulling.Minimale lengte: 43. Maximale lengte: 43. Patroon:
^[A-Za-z0-9_-]{43}$.field
vereist
Waarde zoals gedefinieerd in het volledige invoerschema.Vereiste waarde: “S256”.
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”.
string
Door spaties gescheiden machtigingen uit scopes_supported, eventueel inclusief offline_access. Niet-ondersteunde namen en waarden met alleen witruimte worden geweigerd; duplicaten worden verwijderd. Als scope wordt weggelaten of geen productmachtigingen bevat, bijvoorbeeld alleen openid of alleen offline_access, worden de standaardleesscopes geselecteerd die ook voor deze client zijn geregistreerd. email vereist openid; alleen email wordt geweigerd. Aangevraagde productmachtigingen moeten voor deze client zijn geregistreerd. Identiteitsmachtigingen moeten expliciet worden aangevraagd en door de gebruiker worden goedgekeurd; zonder scope worden geen identiteitsmachtigingen aangevraagd.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))* *$.string
Optionele ondoorzichtige waarde die bij de uiteindelijke callback wordt teruggestuurd. Gebruik een nieuwe, onvoorspelbare waarde en controleer deze in de client.Minimale lengte: 1. Maximale lengte: 2048. Patroon:
^[^\u0000-\u001F\u007F]+$.string
Optionele ondoorzichtige nonce die in het ID-token wordt herhaald wanneer openid is verleend. Controleer deze in de client.Minimale lengte: 1. Maximale lengte: 2048. Patroon:
^[^\u0000-\u001F\u007F]+$.string
Tekstwaarde.Vereiste waarde: “consent”.
Technisch schema
Technisch schema
{
"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."
},
"redirect_uri": {
"type": "string",
"minLength": 1,
"maxLength": 2048,
"pattern": "^[^\\u0000-\\u001F\\u007F]+$",
"description": "Must exactly match one of this client's registered redirect_uris."
},
"response_type": {
"const": "code"
},
"response_mode": {
"const": "query",
"default": "query"
},
"code_challenge": {
"type": "string",
"minLength": 43,
"maxLength": 43,
"pattern": "^[A-Za-z0-9_-]{43}$",
"description": "Base64url SHA-256 digest of the original code_verifier, without padding."
},
"code_challenge_method": {
"const": "S256"
},
"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"
]
},
"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 permissions from scopes_supported, optionally including offline_access. Unsupported names and whitespace-only values are rejected; duplicates are removed. Omitting scope or supplying no product scopes, such as openid alone or offline_access alone, selects the default read scopes intersected with this client's registered product scopes. email requires openid; email alone is rejected. Requested product permissions must be registered for this client. Identity permissions must be explicitly requested and approved by the user; omitting scope requests no identity permissions.",
"examples": [
"account:read projects:read offline_access"
]
},
"state": {
"type": "string",
"minLength": 1,
"maxLength": 2048,
"pattern": "^[^\\u0000-\\u001F\\u007F]+$",
"description": "Optional opaque value echoed on the final callback. Use a fresh unpredictable value and verify it in the client."
},
"nonce": {
"type": "string",
"minLength": 1,
"maxLength": 2048,
"pattern": "^[^\\u0000-\\u001F\\u007F]+$",
"description": "Optional opaque nonce echoed in the ID token when openid is granted. Verify it in the client."
},
"prompt": {
"type": "string",
"const": "consent"
}
},
"required": [
"client_id",
"redirect_uri",
"response_type",
"code_challenge",
"code_challenge_method",
"resource"
],
"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 GET 'https://api.voicecheap.ai/oauth/authorize?client_id=mcp_client_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA&redirect_uri=https%3A%2F%2Fassistant.example.com%2Foauth%2Fcallback&response_type=code&response_mode=query&code_challenge=E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM&code_challenge_method=S256&resource=https%3A%2F%2Fapi.voicecheap.ai%2Fmcp&scope=account%3Aread+projects%3Aread+offline_access&state=example-client-csrf-state'
const input = {
client_id: 'mcp_client_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA',
redirect_uri: 'https://assistant.example.com/oauth/callback',
response_type: 'code',
response_mode: 'query',
code_challenge: 'E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM',
code_challenge_method: 'S256',
resource: 'https://api.voicecheap.ai/mcp',
scope: 'account:read projects:read offline_access',
state: 'example-client-csrf-state',
};
const response = await fetch(
'https://api.voicecheap.ai/oauth/authorize?client_id=mcp_client_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA&redirect_uri=https%3A%2F%2Fassistant.example.com%2Foauth%2Fcallback&response_type=code&response_mode=query&code_challenge=E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM&code_challenge_method=S256&resource=https%3A%2F%2Fapi.voicecheap.ai%2Fmcp&scope=account%3Aread+projects%3Aread+offline_access&state=example-client-csrf-state',
{
method: 'GET',
headers: {},
redirect: 'manual',
},
);
console.log(response.status, await response.text());
import os
import requests
response = requests.request(
"GET",
"https://api.voicecheap.ai/oauth/authorize?client_id=mcp_client_AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA&redirect_uri=https%3A%2F%2Fassistant.example.com%2Foauth%2Fcallback&response_type=code&response_mode=query&code_challenge=E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM&code_challenge_method=S256&resource=https%3A%2F%2Fapi.voicecheap.ai%2Fmcp&scope=account%3Aread+projects%3Aread+offline_access&state=example-client-csrf-state",
headers={},
timeout=120,
allow_redirects=False,
)
print(response.status_code, response.text)
Antwoord
HTTP-omleiding naar de toestemmingspagina van VoiceCheap. Er is geen JSON-resultaatbody. Location bevat een ondoorzichtige request-waarde; de gebruiker meldt zich vervolgens aan en kiest machtigingen.HTTP/1.1 302 Found
Cache-Control: no-store
Pragma: no-cache
Referrer-Policy: no-referrer
Location: https://app.voicecheap.ai/mcp/authorize?request=mcp_req_BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
Antwoordheaders
{
"Cache-Control": "no-store",
"Pragma": "no-cache",
"Referrer-Policy": "no-referrer",
"Location": "https://app.voicecheap.ai/mcp/authorize?request=mcp_req_BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"
}
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.
- Pas URL-codering toe op elke querywaarde. redirect_uri moet exact de schrijfwijze gebruiken die voor deze client is geregistreerd.
- Gebruik alleen S256; plain PKCE en implicit/token-antwoorden worden niet ondersteund. Bewaar de oorspronkelijke code_verifier van 43–128 tekens voor het inwisselen van het token.
- De parameter resource is verplicht en moet exact gelijk zijn aan de MCP-resource-URL van de geselecteerde omgeving.
- De standaardset productscopes is account:read usage:read projects:read transcription:read subtitles:read tts:read voices:read images:read thumbnails:read. Een aanvraag met standaardwaarden wordt beperkt tot de scopes die door de client zijn geregistreerd; als er geen productscopes overblijven, mislukt de autorisatie.
- Een scope die alleen uit offline_access bestaat, gebruikt de standaardselectie van productscopes. offline_access wordt verwijderd voordat productmachtigingen worden getoond of verleend.
- Toestemmingsaanvragen verlopen na 10 minuten en kunnen één keer worden beantwoord. De gebruiker mag alleen een niet-lege subset van de gevraagde productmachtigingen goedkeuren.
- Na goedkeuring ontvangt de callback van de client code, iss en de oorspronkelijke state, indien opgegeven. De autorisatiecode verloopt na 2 minuten en kan één keer worden ingewisseld.
- Na een weigering ontvangt de clientcallback error=access_denied, error_description, iss en de oorspronkelijke state als die was opgegeven; er wordt geen code uitgegeven.
- Ongeldige clientmetadata, afwijkende redirect-URI’s, PKCE, scopes of resource leiden direct tot OAuth-JSON-fouten; ze worden niet doorgestuurd naar een ongevalideerde callback.
- De openbare autorisatielimiet is 30 aanvragen per minuut per client-IP, gedeeld door alle workers.
- 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.
- OpenID Connect ondersteunt prompt=consent. Andere prompt-waarden en max_age worden geweigerd; stille autorisatie en een geforceerde nieuwe aanmelding worden niet ondersteund.
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 of het clientmetadatadocument kan niet worden opgehaald of gevalideerd. |
| 400 | unsupported_response_type | response_type is niet code. |
| 400 | invalid_target | resource ontbreekt of is niet exact de MCP-URL van de omgeving. |
| 400 | invalid_scope | Een aangevraagde productscope wordt niet ondersteund, is niet geregistreerd of laat geen bruikbare machtiging over. |
| 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. |
| 503 | temporarily_unavailable | De clientmetadata is tijdelijk niet beschikbaar. Probeer het later opnieuw. |
Was deze pagina nuttig?

