Skip to main content
Quick Start

Token authentication

Authentication methods for AOQ, WebRTC, and WebSocket protocols

Describes the token authentication mechanism for Realtime API, including how to obtain an API key and how to authenticate when connecting via WebSocket, WebRTC, and AOQ.

Overview

Realtime API uses API keys for authentication. Regardless of the protocol you use -- WebSocket, WebRTC, or AOQ -- authentication is performed by passing a Bearer token in the Authorization HTTP header. Authentication occurs at the connection phase. Once the connection is established, subsequent audio/video and data transmission requires no re-authentication. Authentication differences across protocols:
ProtocolWhenMethodNotes
WebSocketDuring WebSocket handshakeHTTP Header Authorization: Bearer $DASHSCOPE_API_KEYClient or server carries the API key directly when connecting
WebRTCDuring SDP exchange HTTP requestHTTP Header Authorization: Bearer $DASHSCOPE_API_KEYClient or server carries the API key when initiating the SDP exchange
AOQWhen AppServer requests the gatewayHTTP Header Authorization: Bearer $DASHSCOPE_API_KEYAPI key is used only on the server side; the client uses the token returned by the gateway

Get an API key

Step 1: Activate the service

  1. Go to the QwenCloud console and log in with your account.
  2. If this is your first time using the service, follow the on-screen instructions to activate it.

Step 2: Create an API key

  1. In the left navigation pane of the console, select API Key Management.
  2. Click Create API Key and select the workspace to associate.
  3. After the API key is created, copy and save it immediately.
Security note: Your API key is the sole credential for accessing the service. Do not hard-code it in client-side code or commit it to a repository. Manage it through environment variables or a backend service.

Connection authentication details

AOQ protocol authentication

AOQ uses a server-side proxy authentication model: the API key is used only on the AppServer side. The client connects using a temporary token returned by the gateway, which prevents the API key from being exposed on the client.
Token authentication

Gateway request curl example

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

Request fields

FieldValueDescription
endpointSelect based on your deploymentSpecify the endpoint domain
Content-Typeapplication/json--
AuthorizationBearer $DASHSCOPE_API_KEYRequired
x-dashscope-rtc-transportmoqSpecifies AOQ protocol
clientIpOptional. Client's real public IPWhen not provided, the IP of the request to the QwenCloud gateway is used as the client IP. When provided, the clientIp is used as the client IP. The Realtime API uses the client IP to provide optimal Relay access point information

Response example

{
  "sid": "1d06b55683db49bba67a407902f62d02:1782706970:69aecdc5...",
  "aoqTokenForClient": "ecc1a46015d5496ca4ff7a48281eb739",
  "clientRelayEndpoints": [{"endpoint": "121.199.XX.XX", "port": 8443}],
  "clientRelayCertFingerprint": "sha256/99843495...",
  "sidExpiresInSecs": 7200,
  "extraInfo": {"workspaceIdHash": "2021b6f98cea4cff"}
}

Response fields

FieldDescription
sidSession ID
aoqTokenForClientClient connection token; pass this to the SDK's token field
clientRelayEndpointsArray of Relay endpoints (endpoint + port)
clientRelayCertFingerprintTLS certificate fingerprint for the Relay
sidExpiresInSecsSession expiry time in seconds
extraInfo.workspaceIdHashWorkspace ID hash

AOQ Client SDK connection example

  • iOS (Swift)
  • Android (Java)
  • HarmonyOS (ArkTS)
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.map { item in
  let ep = AoqRelayEndpoint()
  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)
clientIp is an optional field in the request body. When not provided, the IP of the request to the QwenCloud gateway is used as the client IP. When provided, the clientIp is used as the client IP. It is recommended that the AppServer obtains the client's real IP on the server side and fills it in to get optimal Relay access points.

WebRTC protocol authentication

WebRTC authentication is completed through an HTTP POST request during the SDP exchange. The client sends an Offer SDP to the server, and the server returns an Answer SDP.
FieldValueDescription
MethodPOST--
URLhttps://{endpoint}/api/v1/webrtc/realtime?model={model_name}Replace endpoint and model_name
Content-Typeapplication/sdpRequest body is an SDP string
AuthorizationBearer $DASHSCOPE_API_KEYRequired
ResponseHTTP 200 with Answer SDPReturns 4xx on failure
WebRTC is currently available on an allowlist basis. Contact your account manager to obtain an endpoint.
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 });

WebSocket protocol authentication

WebSocket authentication is straightforward: the client passes the API key in an HTTP header when establishing the WebSocket connection.
FieldValueDescription
URLwss://dashscope-intl.aliyuncs.com/api-ws/v1/realtime?model={model_name}--
AuthorizationBearer $DASHSCOPE_API_KEYRequired
import websocket, os
API_KEY = os.getenv("DASHSCOPE_API_KEY")
URL = "wss://dashscope-intl.aliyuncs.com/api-ws/v1/realtime?model=qwen3.5-omni-plus-realtime"
ws = websocket.WebSocketApp(URL, header=["Authorization: Bearer " + API_KEY])
ws.run_forever()
You can also connect using the DashScope SDK.