Query Chat History

Last Updated on : 2025-08-05 03:12:17download

This topic describes how to query the chat history.

API description

Query the chat history of an AI agent based on the device ID, bound role type, and role ID.

API endpoint

GET: /v1.0/cloud/agent/ai/enterprise/chat/devices/{device_id}/history

Request parameters

Parameter name Type Location Required Description
device_id String path true The ID of the specified device.
gmt_end Long query true The timestamp when the chat message ends. Chat messages earlier than this time point will be returned.
page_size Integer query true The number of items returned per page. Maximum value: 20.

Response parameters

Parameter name Type Description
success Boolean Indicates whether the operation is successful.
error_code String The error code.
error_msg String The error message.
result Object The returned result.

Description of result

Parameter name Type Description
data String The chat information. It is encrypted and needs to be decrypted.
pv String The protocol version.
sign String The data signature for anti-counterfeiting verification.
t Long The system time when the API returns a result.

Sample request

GET: /v1.0/cloud/agent/ai/enterprise/chat/devices/6c50600a0e15d1fb78h***/history?page_size=20&gmt_end=1753079987512

Sample response

{
    "error_msg": null,
    "result": {
        "data": "XpAnrVY93e***",
        "pv": "1.0",
        "sign": "e92b1036a7546f912058e07546ba66585ca2***",
        "t": 1753770653706
    },
    "success": true,
    "error_code": null
}

Error codes

For more information, see Global Error Codes.

Decrypted return values

Description of data in result

Parameter name Type Description
gmt_create Long The timestamp when the chat is created.
answer List The list of answers.
question List The list of questions.
request_id String The ID of the chat history.
role_info Object The role information. If a role is deleted, this parameter will not be returned.

Description of answer/question objects

Parameter name Type Description
context String The message content.
type String The message type.

Description of the role_info object

Parameter name Type Description
role_id String The ID of the specified role.
role_name String The name of the specified role.
bind_role_type Integer The type of role to bind. Valid values:
  • 0: Custom role.
  • 1: Agent role template.
  • 2: Default role for single-role scenarios.

Sample of decrypted data

{
	"data": [{
		"answer": [{
			"context": "You told me *** before",
			"type": "text"
		}],
		"gmt_create": 1753758926504,
		"question": [{
			"context": "My ***",
			"type": "text"
		}],
		"request_id": "ccbda733-e3d2-4ee3-bb19-d201-***",
		"role_info": {
			"bind_role_type": 1,
			"role_id": "20001",
			"role_name": "Test Role"
		}
	}]
}

Chat history decryption mechanism

Functional description

To ensure data security, the chat history returned by the API is encrypted using AES-GCM authenticated encryption mode. You must decrypt the data field in the response body to retrieve the original data.

Technical specifications

Property Description
Encryption standard AES-GCM (Galois/Counter Mode).
Key source The Access Secret configured in the specified cloud development project.
Security Data integrity verification, authenticity authentication, and resistance to chosen-ciphertext attacks.

Sample code for Java

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.GeneralSecurityException;
import java.security.InvalidKeyException;
import java.util.Base64;

public class CryptoUtils {

    private static final String AES_ALGO = "AES";
    private static final String AES_GCM = "AES/GCM/NoPadding";
    private static final int GCM_NONCE_LENGTH = 12;
    private static final int GCM_TAG_LENGTH = 16;  // The authentication tag length

    /**
     * Implement AES-GCM decryption
     *
     * @param data: The Base64-encoded ciphertext string
     * @param key: The project key, also known as Access Secret
     * @return: The decrypted original string
     * @throws IllegalArgumentException: Thrown if the input parameters are invalid
     */
    public static String decryptDataGCM(String data, String key)
            throws GeneralSecurityException {
        // Parameter verification
        if (key == null || key.isEmpty()) {
            throw new IllegalArgumentException("Key cannot be null");
        }
        Key secretKey = new SecretKeySpec(key.getBytes(), AES_ALGO);
        Cipher cipher = Cipher.getInstance(AES_GCM);
        byte[] message = Base64.decodeBase64(data);
        if (message.length < GCM_NONCE_LENGTH + GCM_TAG_LENGTH) {
            throw new IllegalArgumentException();
        }
        GCMParameterSpec params = new GCMParameterSpec(GCM_TAG_LENGTH * 8, message, 0, GCM_NONCE_LENGTH);
        cipher.init(Cipher.DECRYPT_MODE, secretKey, params);
        byte[] decryptData = cipher.doFinal(message, GCM_NONCE_LENGTH, message.length - GCM_NONCE_LENGTH);
        return new String(decryptData);
    }
}

Signature generation specifications

To ensure data integrity and the authenticity of the request source, please follow the following steps to verify the signature.

Signature generation specifications

  1. Get the data returned by the API. Extract the following important fields from the API response:

    • sign: The digital signature returned by the API.
    • t: The Unix timestamp.
    • pv: The protocol version number.
    • data: The encrypted payload.
  2. Regenerate the signature locally. Calculate the signature using the same signature algorithm and key (Access Secret) as used by the API.

    String localSign = SignUtils.createCloudSign(data, pv, t, accessSecret);
    
  3. Verify the signature. Strictly compare the locally generated signature with the sign value returned by the API.

    if (!localSign.equals(apiSign)) {
      // Handle verification failure
    }
    
    Validation result Description Action
    Consistent The data is complete and the source is trustworthy. Data can be used safely.
    Inconsistent Data was tampered with during transmission, or the key does not match. 1. Discard current data.
    2. Check key validity.
    3. Trigger security alert mechanism.

Sample code for Java

/**
     * Generate a digital signature (SHA-256)
     *
     * @param data: The encrypted data, which must match the request content
     * @param pv: The protocol version, such as '1.0'
     * @param time: The timestamp, taken from the t parameter returned by the API
     * @param secretKey: The project key, also known as Access Secret
     * @return: The hexadecimal-encoded signature value
     */
    public static String createCloudSign(String data,
                                         String pv,
                                         long time,
                                         String secretKey)
                throws NoSuchAlgorithmException {
        // Parameter verification
        if (secretKey == null || secretKey.isEmpty()) {
            throw new IllegalArgumentException("secretKey cannot be null");
        }
        if (data == null || pv == null) {
            throw new IllegalArgumentException("data and pv parameters cannot be null");
        }

        // Create an ordered set of parameters (By default, TreeMap is sorted in ascending order by key)
        TreeMap<String, String> params = new TreeMap<>();
        params.put("t", String.valueOf(time));
        params.put("data", data);
        params.put("pv", pv);

        // Construct a signature string
        StringBuilder sb = new StringBuilder(128);
        for (Map.Entry<String, String> entry : params.entrySet()) {
            String value = entry.getValue();
            if (value != null && !value.trim().isEmpty()) {
                sb.append(entry.getKey())
                  .append('=')
                  .append(value)
                  .append("||");
            }
        }
        sb.append(secretKey);

        // SHA-256 hash calculation
        MessageDigest digest = MessageDigest.getInstance("SHA-256");
        byte[] hash = digest.digest(sb.toString().getBytes(StandardCharsets.UTF_8));

        // Convert to hexadecimal
        StringBuilder hexString = new StringBuilder(64);
        for (byte b: hash) {
            hexString.append(String.format("%02x", b));
        }
	return hexString.toString();
}