Saiba como a Realtime API autentica conexões com tokens, incluindo como obter uma chave de API e autenticar-se pelos protocolos WebSocket, WebRTC e AOQ.
A Realtime API usa chaves de API para autenticação. Independentemente do protocolo (AOQ, WebRTC ou WebSocket), você deve passar um bearer token no cabeçalho de requisição HTTP Authorization.
A autenticação ocorre apenas durante a configuração da conexão. Após o estabelecimento da conexão, a transmissão de dados não exige nova autenticação.
A tabela a seguir compara os métodos de autenticação dos três protocolos:
Protocolo | Momento da autenticação | Método de autenticação | Observações |
|---|---|---|---|
AOQ | Quando o AppServer da aplicação requisita o gateway | Cabeçalho HTTP | A chave de API é usada exclusivamente no lado do servidor. O cliente utiliza o token retornado pelo gateway |
WebRTC | Durante a requisição HTTP de troca de SDP | Cabeçalho HTTP | O cliente ou servidor inicia a troca de SDP com a chave de API |
WebSocket | Durante o handshake do WebSocket | Cabeçalho HTTP | O cliente ou servidor se conecta diretamente usando a chave de API |
Obter uma chave de API
Etapa 1: Ativar o Model Studio
- Acesse o console do Alibaba Cloud Model Studio e faça login com sua conta Alibaba Cloud.
- Se esta for sua primeira vez utilizando o service, siga as instruções na tela para ativá-lo.
Etapa 2: Criar uma API Key
- No painel de navegação à esquerda do console, selecione API Key.
- Clique em Create API Key e escolha o workspace a ser associado à chave.
- Após criar a chave, copie-a e armazene-a imediatamente.
ImportanteNota de segurança: A chave de API é sua única credencial para acessar o service. Não a codifique diretamente no código do cliente nem a envie para repositórios de código. Gerencie-a por meio de variáveis de ambiente ou distribua-a a partir de um service de backend.
Detalhes da autenticação de conexão
Autenticação do protocolo AOQ
O protocolo AOQ adota um modelo de autenticação por proxy no lado do servidor: a chave de API é utilizada apenas no AppServer da aplicação. O cliente se conecta usando um token temporário retornado pelo gateway, evitando que a chave de API fique exposta no cliente.
curl -X POST \
"https://{endpoint}/api/v1/webrtc/realtime?model=qwen3.5-omni-plus-realtime" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer ${DASHSCOPE_API_KEY}" \
-H "x-dashscope-rtc-transport: moq" \
-d "{\"clientIp\": \"${CLIENT_REAL_IP}\"}"
curl -X POST \
"https://{endpoint}/api/v1/webrtc/inference?model=fun-asr-realtime" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer ${DASHSCOPE_API_KEY}" \
-H "x-dashscope-rtc-transport: moq" \
-d "{\"clientIp\": \"${CLIENT_REAL_IP}\"}"
Campos da requisição
Item | Valor | Descrição |
|---|---|---|
endpoint | Selecione um domínio de acesso conforme seu cenário de negócios | Especifica o domínio de acesso. Para mais detalhes, consulte Regions and Access Domains |
Content-Type |
| Define o tipo de mensagem |
Authorization |
| Sua chave de API |
x-dashscope-rtc-transport |
| Indica o uso do protocolo AOQ |
clientIp | Endereço IP público real do cliente | Opcional. Se omitido, será usado o endereço IP que fez a requisição ao gateway do Model Studio. Caso especificado, o valor de clientIp terá prioridade. A Realtime API seleciona o melhor ponto de acesso Relay com base no endereço IP do cliente |
Exemplo de resposta
{
"sid": "1d06b55683db49bba67a407902f62d02:1782706970:69aecdc5...",
"aoqTokenForClient": "ecc1a46015d5496ca4ff7a48281eb739",
"clientRelayEndpoints": [{"endpoint": "121.199.XX.XX", "port": 8443, "route_index": 0}],
"clientRelayCertFingerprint": "sha256/99843495...",
"sidExpiresInSecs": 7200,
"extraInfo": {"workspaceIdHash": "2021b6f98cea4cff"}
}
Campos da resposta
Campo | Descrição |
|---|---|
sid | ID de sessão único |
aoqTokenForClient | Token de conexão do cliente. Passe-o para o campo token do SDK |
clientRelayEndpoints | Array de pontos de acesso Relay (endpoint + porta) |
clientRelayCertFingerprint | Impressão digital do certificado TLS do Relay |
sidExpiresInSecs | Tempo de expiração da sessão, em segundos |
extraInfo.workspaceIdHash | Hash do ID do workspace |
Exemplo de conexão com o SDK cliente AOQ
ObservaçãoO campo clientIp é opcional no corpo da requisição. Se não for especificado, o endereço IP que requisita o gateway do Model Studio será usado como IP do cliente. Quando informado, o valor de clientIp tem precedência. Configure seu AppServer para obter o endereço IP real do cliente e transmiti-lo, garantindo a seleção do melhor ponto de acesso Relay.
let resp = try JSONDecoder().decode(AllocateResponse.self, from: responseData)
let config = AoqConnectConfig()
config.token = resp.aoqTokenForClient
config.sid = resp.sid
config.certFingerprint = resp.clientRelayCertFingerprint
config.relayEndpoints = resp.clientRelayEndpoints.enumerated().map { index, item in
let ep = AoqRelayEndpoint()
// Fall back to the array index when route_index is missing
ep.routeIndex = item.routeIndex ?? index
ep.endpoint = item.endpoint
ep.port = item.port
return ep
}
config.workspaceIdHash = resp.extraInfo?.workspaceIdHash ?? ""
let audioTrack = AoqTrackParam()
audioTrack.trackType = .audio
let dataTrack = AoqTrackParam()
dataTrack.trackType = .data
config.publishTracks = [audioTrack, dataTrack]
config.subscribeTracks = [audioTrack, dataTrack]
engine.connect(config)
JSONObject obj = new JSONObject(responseText);
AoqClientEngine.AoqConnectConfig cfg = new AoqClientEngine.AoqConnectConfig();
cfg.token = obj.optString("aoqTokenForClient", "");
cfg.sid = obj.optString("sid", "");
cfg.certFingerprint = obj.optString("clientRelayCertFingerprint", "");
JSONArray arr = obj.optJSONArray("clientRelayEndpoints");
if (arr != null) {
for (int i = 0; i < arr.length(); i++) {
JSONObject o = arr.optJSONObject(i);
AoqClientEngine.AoqRelayEndpoint ep = new AoqClientEngine.AoqRelayEndpoint();
// Fall back to the array index when route_index is missing
ep.routeIndex = o.has("route_index") ? o.optInt("route_index", i) : i;
ep.endpoint = o.optString("endpoint", "");
ep.port = o.optInt("port", 0);
cfg.relayEndpoints.add(ep);
}
}
JSONObject ext = obj.optJSONObject("extraInfo");
cfg.workspaceIdHash = ext != null ? ext.optString("workspaceIdHash", "") : "";
AoqClientEngine.AoqTrackParam audio = new AoqClientEngine.AoqTrackParam();
audio.trackType = AoqClientEngine.AoqTrackType.AoqTrackTypeAudio;
AoqClientEngine.AoqTrackParam data = new AoqClientEngine.AoqTrackParam();
data.trackType = AoqClientEngine.AoqTrackType.AoqTrackTypeData;
cfg.publishTracks.add(audio);
cfg.publishTracks.add(data);
cfg.subscribeTracks.add(audio);
cfg.subscribeTracks.add(data);
engine.connect(cfg);
const obj = JSON.parse(responseText) as Record<string, Object | undefined>;
const cfg: AoqConnectConfig = {
token: String(obj['aoqTokenForClient'] ?? ''),
sid: String(obj['sid'] ?? ''),
certFingerprint: String(obj['clientRelayCertFingerprint'] ?? ''),
// Fall back to the array index when route_index is missing
relayEndpoints: (obj['clientRelayEndpoints'] as Array<any>).map((item, index) => ({
routeIndex: Number(item['route_index'] ?? index),
endpoint: String(item['endpoint'] ?? ''),
port: Number(item['port'] ?? 0)
})),
workspaceIdHash: String((obj['extraInfo'] as any)?.['workspaceIdHash'] ?? ''),
publishTracks: [
{ trackType: AoqTrackType.AoqTrackTypeAudio },
{ trackType: AoqTrackType.AoqTrackTypeData }
],
subscribeTracks: [
{ trackType: AoqTrackType.AoqTrackTypeAudio },
{ trackType: AoqTrackType.AoqTrackTypeData }
]
};
engine.connect(cfg);
Autenticação do protocolo WebRTC
O WebRTC realiza a troca de SDP por meio de uma requisição HTTP POST, momento em que ocorre a autenticação. O cliente envia o Offer SDP ao servidor, que responde com o Answer SDP.
Item | Valor | Descrição |
|---|---|---|
Método da requisição | POST | - |
URL da requisição |
| Substitua endpoint e model_name. A URL de conexão varia conforme o modelo. Para mais detalhes, consulte WebRTC connection |
Content-Type |
| O corpo da requisição é uma string SDP |
Authorization |
| Sua chave de API |
Resposta | HTTP 200 contendo o Answer SDP | Retorna um código de status 4xx em caso de falha |
const pc = new RTCPeerConnection();
const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
stream.getAudioTracks().forEach(t => pc.addTrack(t, stream));
pc.createDataChannel('oai-events');
const offer = await pc.createOffer();
await pc.setLocalDescription(offer);
// Send after ICE gathering is complete
const resp = await fetch(API_URL, {
method: 'POST',
headers: {
'Content-Type': 'application/sdp',
'Authorization': `Bearer ${API_KEY}`,
},
body: pc.localDescription.sdp,
});
const answerSdp = await resp.text();
await pc.setRemoteDescription({ type: 'answer', sdp: answerSdp });
Autenticação do protocolo WebSocket
A autenticação via WebSocket é a mais simples: basta enviar a chave de API em um cabeçalho HTTP ao estabelecer a conexão.
Item | Valor | Descrição |
|---|---|---|
URL de conexão |
| A URL de conexão varia conforme o modelo. Para mais detalhes, consulte WebSocket connection |
Authorization |
| Sua chave de API |
import websocket, os
API_KEY = os.getenv("DASHSCOPE_API_KEY")
URL = "wss://dashscope.aliyuncs.com/api-ws/v1/realtime?model=qwen3.5-omni-plus-realtime"
ws = websocket.WebSocketApp(URL, header=["Authorization: Bearer " + API_KEY])
ws.run_forever()