This document describes the interfaces and provides sample code for authenticating speech evaluation, essay grading, and AI teacher services.
For security and ease of maintenance, you must integrate this step on the server-side. This prevents key leakage and associated security vulnerabilities.
RAM users require the AliyunAIContentFullAccess permission to invoke this service.
Speech Evaluation Authorization and Request Flow

The evaluation device initiates an authorization request
The evaluation device sends a
POSTrequest to your server to request pre-evaluation authorization.
Your server authenticates the user and requests authorization
After your server receives the request from the evaluation device, it authenticates the user.
After the user is authenticated, your server sends an authorization request to the speech evaluation authorization service.
Obtain the authorization ID
After the request is processed, the speech evaluation authorization service returns an authorization ID (
warrant_id) to your server. This authorization ID can be used multiple times during its validity period.
Pass the authorization ID to the evaluation device
After your server receives the authorization ID, it returns the ID to the evaluation device.
Assemble and send the evaluation request
The evaluation device assembles a data packet in JSON format as specified by the evaluation request interface.
The evaluation device then uses the authorization ID and other required information to send an evaluation request to the evaluation server.
Receive the evaluation results
The evaluation server processes the request and returns the evaluation results to the evaluation device in JSON format.
Service Presentation
Finally, the evaluation device uses the evaluation results to update the business logic or user interface, which completes the process.
Authentication Interface Requests
Request Addresses
https://api.cloud.ssapi.cn/auth/authorize
https://gate-01.api.cloud.ssapi.cn/auth/authorize
https://gate-02.api.cloud.ssapi.cn/auth/authorize
https://gate-03.api.cloud.ssapi.cn/auth/authorizeRequest Method
Send the request using a form POST.
Request Parameters
Parameter Name | Type | Is it mandatory? | Default Value | Description |
appid | string | Y | None | Obtain this from the console after placing an order on the Alibaba Cloud official website. For non-official website orders, contact your service representative. |
timestamp | string | Y | None | The timestamp (10-digit UNIX timestamp in seconds) when you initiate the authorization request. |
user_id | string | Y | string | The unique identifier for your product's user system. This can be a user ID or device ID. Ensure it remains unique. Note that this user ID must match the user ID passed during evaluation; otherwise, evaluation may not function correctly. |
user_client_ip | ip string | Y | None | The public network IP address of the client device. |
request_sign | string | Y | None | The signature for the authorization interface parameters. MD5 encrypt the parameters in the following order;
For a code example, see Signature logic example for requesting authorization. |
warrant_available | integer | N | 7200 | The time-to-live (TTL) for the authorization ID, in seconds. |
appid and app_secret: You can obtain these credentials from the console after you purchase the service on the Alibaba Cloud website. If you purchased the service through other channels, contact your service representative.
For more information about how to obtain these credentials, see Quick Integration for Speech Evaluation.
The app_secret is a critical credential. You must store it in a secure runtime environment and not include it in authorization requests.
Response Parameters
Parameter Name | Type | Is this required? | Default Value | Description |
code | integer | Y | 0 | Status code: 0: Success |
msg | string | Y | success | Status description: success: Success |
data.warrant_id | string | Y | string | The authorization ID returned by the platform. |
data.expire_at | timestamp | Y | time()+7200 | The authorization ID expiration time, default 2 hours. |
Error Codes
Error Code | Location | Error Description |
430001 | Platform | When requesting the platform, no parameters were passed. |
430002 | Platform | When requesting the platform, the timestamp parameter was not passed. |
430003 | Platform | When requesting the platform, the request_sign parameter was not passed. |
430004 | Platform | When requesting the platform, the appid parameter was not passed. |
430005 | Platform | When requesting the platform, the appid is invalid. |
430006 | Platform | When requesting the platform, the user_id parameter was not passed. |
430007 | Platform | When requesting the platform, the user_client_ip parameter was not passed. |
430008 | Platform | When requesting the platform, the request_sign failed authentication; the signature is incorrect. If requesting the staging environment, modify it according to the returned information. |
430009 | Platform | The platform authentication server crashed. |
Examples
Request Authorization
curl
curl -X POST \
https://api.cloud.ssapi.cn/auth/authorize \
-F "appid=your_appid" \
-F "timestamp=$(date +%s)" \
-F "user_id=your_user_id" \
-F "user_client_ip=your_client_ip" \
-F "request_sign=your_request_sign" \
-F "warrant_available=7200"Replace the parameters in the example with your actual values. The `$(date +%s)` command retrieves the real-time timestamp.
Authorization Response
{
"code": 0,
"message": "success",
"data": {
"warrant_id": "5aec3959f4130352bf067fd21f019",
"expire_at": 1525430617,
"timestamp": "1525423417"
}
}Signature Logic Example for Requesting Authorization
PHP
$data = ['appid' => $app_id, 'timestamp' => $timestamp, 'user_id' => $user_id, 'user_client_ip' => $user_client_ip, 'app_secret' => $app_secret];
ksort($data);
$data_kv = [ ];
foreach ($data as $k => $v) {
array_push($data_kv, $k.'='.$v);
}
$sign_string = implode('&', $data_kv);
$new_sign = md5($sign_string);JAVA
import java.security.MessageDigest;
import java.util.*;
// Java version of signature generation code
Map<String, Object> data = new HashMap<>();
data.put("appid", app_id);
data.put("timestamp", timestamp);
data.put("user_id", user_id);
data.put("user_client_ip", user_client_ip);
data.put("app_secret", app_secret);
List<Map.Entry<String, Object>> list = new ArrayList<>(data.entrySet());
Collections.sort(list, Map.Entry.comparingByKey());
StringBuilder signString = new StringBuilder();
for (Map.Entry<String, Object> entry : list) {
signString.append(entry.getKey()).append("=").append(entry.getValue().toString()).append("&");
}
String sign = signString.toString().substring(0, signString.length() - 1); // Remove the last extra "&"
try {
MessageDigest md = MessageDigest.getInstance("MD5");
byte[ ] digest = md.digest(sign.getBytes());
StringBuilder hexString = new StringBuilder();
for (byte b : digest) {
hexString.append(String.format("%02x", b));
}
String newSign = hexString.toString(); // MD5 signature
} catch (Exception e) {
e.printStackTrace();
}Python
from hashlib import md5
def generate_signature(app_id, timestamp, user_id, user_client_ip, app_secret):
"""
Generate the signature string based on the given parameters.
"""
params = {'appid': app_id, 'timestamp': str(timestamp),'user_id': user_id, 'user_client_ip': user_client_ip,'app_secret': app_secret}
sorted_params = dict(sorted(params.items()))
query_string = '&'.join([f"{k}={v}" for k, v in sorted_params.items()])
signature = md5(query_string.encode()).hexdigest()
return signature
# Example
app_id = 'a111'
timestamp = 1603885321
user_id = 'w9egtDf3PMAOaxZVGSlQUip12no6WCvu'
user_client_ip = '111.111.XXX.XXX'
app_secret = 'wHkC1SMmDLrVO86vcydG2ax4oPYuqiIh'
print(generate_signature(app_id, timestamp, user_id, user_client_ip, app_secret))```Complete Example
This section provides a complete example that shows the logic for reading keys from environment variables, address polling, signing requests, and obtaining authorization.
Go Language
package main
import (
"bytes"
"crypto/md5"
"encoding/hex"
"encoding/json"
"fmt"
"io"
"mime/multipart"
"net/http"
"os"
"sort"
"time"
)
func main() {
appId := os.Getenv("APP_ID")
appSecret := os.Getenv("APP_SECRET")
timestamp := fmt.Sprintf("%d", time.Now().Unix())
userClientIp := "172.26.1.61" // Replace with the actual public network IP address of the client.
userID := "dummyUserId" // Replace with the actual user ID.
signature := generateSignature(appId, timestamp, userID, userClientIp, appSecret)
fmt.Printf("signature=%s\n\n", signature)
urls := [ ]string{
// Staging environment
"http://ginger-trial.api.cloud.ssapi.cn:8080/auth/authorize",
// Production environment
//"https://api.cloud.ssapi.cn/auth/authorize",
//"https://gate-01.api.cloud.ssapi.cn/auth/authorize",
//"https://gate-02.api.cloud.ssapi.cn/auth/authorize",
//"https://gate-03.api.cloud.ssapi.cn/auth/authorize",
}
for _, url := range urls {
respBody, err := requestAuthorization(url, appId, timestamp, userID, userClientIp, signature)
if err == nil {
fmt.Println("Authorization Done")
// Construct a JSON string containing the authorization ID.
var result struct {
Code int `json:"code"`
Msg string `json:"msg"`
Data struct {
WarrantId string `json:"warrant_id"`
ExpireAt int64 `json:"expire_at"`
} `json:"data"`
}
// Parse JSON data
if err := json.NewDecoder(bytes.NewBuffer([ ]byte(respBody))).Decode(&result); err == nil {
// Print parsed data
fmt.Printf("Status Code: %d\n", result.Code)
fmt.Printf("Status Description: %s\n", result.Msg)
fmt.Printf("Authorization ID: %s\n", result.Data.WarrantId)
fmt.Printf("Authorization ID Expiration Time: %d\n", result.Data.ExpireAt)
} else {
// Handle parsing errors
fmt.Printf("JSON parsing failed: %v\n", err)
// Output resp.Body content as a string
fmt.Printf("Response Body Content:%s;;;\n", respBody)
}
break
}
time.Sleep(time.Second * 2) // Polling interval
}
}
func generateSignature(appId, timestamp, userId, userClientIp, appSecret string) string {
data := map[string]string{
"appid": appId,
"timestamp": timestamp,
"user_id": userId,
"user_client_ip": userClientIp,
"app_secret": appSecret,
}
var keys [ ]string
for key := range data {
keys = append(keys, key)
}
sort.Strings(keys)
var buf bytes.Buffer
for _, key := range keys {
buf.WriteString(key + "=" + data[key] + "&")
}
buf.Truncate(buf.Len() - 1) // Remove the last extra "&"
hash := md5.New()
hash.Write([ ]byte(buf.String()))
return hex.EncodeToString(hash.Sum(nil))
}
func requestAuthorization(url, appId, timestamp, userID, clientIp, signature string) (string, error) {
body := &bytes.Buffer{}
writer := multipart.NewWriter(body)
_ = writer.WriteField("appid", appId)
_ = writer.WriteField("timestamp", timestamp)
_ = writer.WriteField("user_id", userID)
_ = writer.WriteField("user_client_ip", clientIp)
_ = writer.WriteField("request_sign", signature)
_ = writer.WriteField("warrant_available", "7200")
err := writer.Close()
if err != nil {
return "", err
}
req, _ := http.NewRequest("POST", url, body)
req.Header.Set("Content-Type", writer.FormDataContentType())
client := &http.Client{}
resp, err := client.Do(req)
if err != nil || resp.StatusCode != http.StatusOK {
return "", err
}
bodyBytes, _ := io.ReadAll(resp.Body)
fmt.Printf("Response Body Content:%s;;;\n", string(bodyBytes))
return string(bodyBytes), err
}
Python Language
import os
import time
import requests
from hashlib import md5
# Get sensitive information from environment variables
app_id = os.getenv('APP_ID')
app_secret = os.getenv('APP_SECRET')
# Other required parameters
timestamp = int(time.time())
user_id = 'your_user_id'
user_client_ip = '192.168.0.1'
# Signature generation function
def generate_signature(app_id, timestamp, user_id, user_client_ip, app_secret):
params = {
'appid': app_id,
'timestamp': str(timestamp),
'user_id': user_id,
'user_client_ip': user_client_ip,
'app_secret': app_secret
}
sorted_params = dict(sorted(params.items()))
query_string = '&'.join(f'{k}={v}' for k, v in sorted_params.items())
return md5(query_string.encode()).hexdigest()
signature = generate_signature(app_id, timestamp, user_id, user_client_ip, app_secret)
# Request URL list
urls = [
#
'http://trial.cloud.ssapi.cn:8080/auth/authorize',
# Production environment
# 'https://api.cloud.ssapi.cn/auth/authorize',
# 'https://gate-01.api.cloud.ssapi.cn/auth/authorize',
# 'https://gate-02.api.cloud.ssapi.cn/auth/authorize',
# 'https://gate-03.api.cloud.ssapi.cn/auth/authorize'
]
# Send request and process response
for url in urls:
response = requests.post(
url=url,
data={
'appid': app_id,
'timestamp': str(timestamp),
'user_id': user_id,
'user_client_ip': user_client_ip,
'request_sign': signature,
'warrant_available': '7200'
},
headers={'Content-Type': 'application/x-www-form-urlencoded'}
)
if response.status_code == 200:
print("Original result: " + str(response.content))
result = response.json()
if result['code'] == 0:
print(f"warrant_id: {result['data']['warrant_id']}")
print(f"Expiration time: {result['data']['expire_at']}")
break
Java Language
First, import the following Maven dependency:
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.78</version>
</dependency>package com.alibaba.edu.efec.demo;
import com.alibaba.fastjson.JSONObject;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.util.*;
public class TestGetWarrant {
public static void main(String[ ] args) throws IOException {
// Get sensitive information from environment variables
String app_id = System.getenv("APP_ID");
String app_secret = System.getenv("APP_SECRET");
// Other required parameters
long timestamp = System.currentTimeMillis() / 1000L;
String user_id = "your_user_id";
String user_client_ip = "192.168.0.1";
// Signature generation function
String signature = generateSignature(app_id, timestamp, user_id, user_client_ip, app_secret);
// Request URL list
List<String> urls = Arrays.asList(
"http://trial.cloud.ssapi.cn:8080/auth/authorize"
// Production environment
// "https://api.cloud.ssapi.cn/auth/authorize",
// "https://gate-01.api.cloud.ssapi.cn/auth/authorize",
// "https://gate-02.api.cloud.ssapi.cn/auth/authorize",
// "https://gate-03.api.cloud.ssapi.cn/auth/authorize"
);
// Send request and process response
for (String urlStr : urls) {
try {
HttpURLConnection connection = (HttpURLConnection) new URL(urlStr).openConnection();
connection.setRequestMethod("POST");
connection.setDoOutput(true);
connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
Map<String, Object> params = new HashMap<>();
params.put("appid", app_id);
params.put("timestamp", timestamp);
params.put("user_id", user_id);
params.put("user_client_ip", user_client_ip);
params.put("request_sign", signature);
params.put("warrant_available", "7200");
StringBuilder postData = new StringBuilder();
for (Map.Entry<String, Object> param : params.entrySet()) {
if (postData.length() != 0) postData.append('&');
postData.append(param.getKey());
postData.append('=');
postData.append(URLEncoder.encode(String.valueOf(param.getValue()), StandardCharsets.UTF_8.toString()));
}
byte[ ] postDataBytes = postData.toString().getBytes(StandardCharsets.UTF_8);
connection.getOutputStream().write(postDataBytes);
int status = connection.getResponseCode();
if (status == 200) {
Scanner scanner = new Scanner(connection.getInputStream(), String.valueOf(StandardCharsets.UTF_8));
StringBuilder body = new StringBuilder();
while (scanner.hasNextLine()) {
String line = scanner.nextLine();
System.out.println(line);
body.append(line);
}
scanner.close();
// Parse JSON response
JSONObject json = JSONObject.parseObject(body.toString());
if (json.getInteger("code") == 0) {
System.out.println("warrant_id: " + json.getJSONObject("data").getString("warrant_id"));
System.out.println("Expiration time: " + json.getJSONObject("data").getString("expire_at"));
break;
}
} else {
throw new RuntimeException("Failed : HTTP error code : " + status);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
private static String generateSignature(String app_id, long timestamp, String user_id, String user_client_ip, String app_secret) {
Map<String, String> params = new TreeMap<>();
params.put("appid", app_id);
params.put("timestamp", Long.toString(timestamp));
params.put("user_id", user_id);
params.put("user_client_ip", user_client_ip);
params.put("app_secret", app_secret);
StringBuilder queryString = new StringBuilder();
for (Map.Entry<String, String> entry : params.entrySet()) {
if (queryString.length() > 0) {
queryString.append("&");
}
queryString.append(entry.getKey()).append("=").append(entry.getValue());
}
MessageDigest digest;
try {
digest = MessageDigest.getInstance("MD5");
byte[ ] hash = digest.digest(queryString.toString().getBytes(StandardCharsets.UTF_8));
StringBuilder hexString = new StringBuilder();
for (byte b : hash) {
String hex = Integer.toHexString(0xff & b);
if (hex.length() == 1) hexString.append('0');
hexString.append(hex);
}
return hexString.toString();
} catch (Exception ex) {
throw new RuntimeException(ex);
}
}
}
Error Codes
errorId | Description | Cause | Application layer recommendations |
40092 | The audio duration exceeds the limit. | The server limits the recording duration for each request. | Ensure that the recording duration is within the specified range. |
41008 | Audio format not supported. | The audio format is not supported. | Ensure that you use a supported audio format. |
41010 | Invalid audio information. | The channel in the audio information is missing or not supported. Only a value of 1 is supported. | The audio channel parameter does not exist or is not supported. |
41016 | SDK information is empty. | The sdk field is missing from connect.param. | Check whether the connect package is complete. |
41017 | The sdk object is missing the version field. | The version field is missing from connect.param.sdk. | Check whether the connect package is complete. |
41018 | The sdk object is missing the source field. | The source field is missing from connect.param.sdk. | Check whether the connect package is complete. |
41019 | The sdk object is missing the protocol field. | The protocol field is missing from connect.param.sdk. | Check whether the connect package is complete. |
41030 | Authentication failed. | The warrantId is missing or incorrect. | Check whether the warrantId was passed. Ensure that the userId used to obtain the warrantId matches the one used for the evaluation. |
41035 | Coretype not supported. | An unauthorized coretype was used. | Contact your sales representative to confirm that the coretype is enabled. |
41036 | The client concurrency limit is exceeded. | The number of concurrent evaluations has reached the purchased limit. | Contact your sales representative to confirm whether your purchased concurrency quota is sufficient. |
42003 | The client sent requests out of order. | The SDK was not invoked in the correct sequence. | Check whether the SDK is used correctly. |
430005 | Invalid appid. | An incorrect appid was used. | Confirm that the appid is valid and matches the environment. For example, test accounts require the staging environment. |
51000 | Kernel initialization failed. | The kernel returned an error when text parameters were passed to it. | Confirm that the parameters are passed in the correct format. If the issue persists, contact technical support. |
53000 | Kernel process crashed. | The kernel process crashed. This may be caused by an issue in the kernel code or by incorrect parameters passed from the SDK. | If you have confirmed that the parameter format is correct, contact technical support. |
70001 | The SDK version needs to be upgraded. | This SDK version is prohibited or has limited support. | You can contact Technical Support for assistance with the SDK. |