HTTP API

更新时间:
复制 MD 格式

Server-side tracking parameters

  1. Go to the management console and click Collection Information.

  2. primary domain name: The endpoint for reporting data from server-side data tracking.

  3. secondary domain name: By default, this is the same as the primary domain name. Customers using a private deployment can provide a secondary domain name as a backup.

  4. ServiceSecret and ServiceID are verification parameters. Keep them confidential.

Note: This information is security-sensitive and is only visible to users with administrator permissions.

image.png

Request

Endpoint: https://<your-ingestion-domain:port>/server

The Content-Type request header must be application/json.

Request parameters

JSON parameters for event reporting

Parameter

(case-sensitive)

Type

Required

Description

Example

sign

string

Yes

A signature to verify request integrity.

f564cae6a8ad458648id9d607a124322

app_id

string

Yes

Your ServiceID, found in your server-side data tracking information.

OA8kI9Jis7YJNh5uh

appkey

string

Yes

The application key. Obtain this from the QT management console.

9moqdsuia8hvxm7k8shf82n

id

string

Yes

The event code you configured when creating the event in the QT console.

click

umid

string

Required for all event types except $$_user_profile.

The device ID.

djajdjdk1

puid

string

Required for $$_user_profile events; optional otherwise.

The user ID.

user_001

page_name

string

No

The page name.

page_index

ts

string

Yes

The millisecond timestamp indicating when the event occurred.

1659493170125

cusp

object

No

Contains custom event property data.

{"foo": "bar"}

gp

object

No

Contains global property data.

{"foo": "bar"}

sdk_type

string

Yes

The SDK type. Must be httpapi.

httpapi

server_ts

string

No. The QT server generates this automatically. If provided, this value overrides the one generated by the server.

The server-side millisecond timestamp.

1659493170125

uuid

string

No. Used to generate the log_id (supported in v2.4.17 and later).

Provide a unique uuid for each log to ensure a highly unique log_id.

1234567890

log_id

string

No. Automatically generated by the QT server.

The log ID. The server generates this from the uuid if provided; otherwise, it's generated from the timestamp.

1234567890

Event message protocol

{ 
  "sign":"27c95768438645138cfb010ded871091",  // Required. The signature.

  
  "app_id":"xxxxxxxxx",                       // Corresponds to the ServiceID in your server-side data tracking information.
  
  "appkey":"1344444",                         // Required. The application appkey.
  "id" : "get_coupons",                       // Required. The event code.
  "umid" : "edfafs",                          // The device ID. Required, except for $$_user_profile events.
  "puid" : "123456",                          // The user ID. Required for $$_user_profile events; recommended otherwise.
                                              
    
  "page_name":"home_page",                    // Optional. The page code. 
  "ts" : "1614667799165",                     // Required. The event's millisecond timestamp.
  "cusp" : {                                  // Custom event properties.
    "p1" : "1",
    "p2" : "2",
    "p3" : "3"
  },
  
  "sdk_type":"httpapi",                       // Fixed value. This field is added automatically by the collection service.
  "server_ts":"1614667799165",               // Optional. If provided, this value is used. Otherwise, the server uses the log ingestion timestamp.
  "_id":'123344'                              // Unique log ID. The collection service generates this field automatically.
}

JSON parameters for user property reporting

Parameter

(case-sensitive)

Type

Required

Description

Example

sign

string

Yes

A signature to verify request integrity.

f564cae6a8ad458648id9d607a124322

app_id

string

Yes

Your ServiceID, found in your server-side data tracking information.

OA8kI9Jis7YJNh5uh

appkey

string

Yes

The application key. Obtain this from the QT management console.

9moqdsuia8hvxm7k8shf82n

id

string

Yes

The event code for reporting user properties. Must be $$_user_profile.

$$_user_profile

umid

string

No

The device ID.

djajdjdk1

puid

string

Yes

The user ID.

user_001

ts

string

Yes

The millisecond timestamp indicating when the event occurred.

1659493170125

cusp

object

Yes

Contains the user property data to report.

{"name": "tom", "gender": "1"}

sdk_type

string

Yes

The SDK type. Must be httpapi.

httpapi

server_ts

string

No. The QT server generates this automatically. If provided, this value overrides the one generated by the server.

The server-side millisecond timestamp.

1659493170125

uuid

string

No. Used to generate the log_id (supported in v2.4.17 and later).

Provide a unique uuid for each log to ensure a highly unique log_id.

1234567890

log_id

string

No. Automatically generated by the QT server.

The log ID. The server generates this from the uuid if provided; otherwise, it's generated from the timestamp.

1234567890

User property message protocol

{ 
  "sign":"27c95768438645138cfb010ded871091",  // Required. The signature.
  "app_id":"xxxxxxxxx",                       // Required. Your ServiceID, found in the server-side data tracking information.
  
  
  "appkey":"1344444",                         // Required. The application appkey.
  "id" : "$$_user_profile",                   // Required. Identifies the request as a user property update.
  "umid" : "edfafs",                          // Optional. The device ID.
  "puid" : "123456",                          // Required. The user ID.
  "ts" : "1614667799165",                     // Required. The event's millisecond timestamp.
  "cusp" : {                                  // Required. The user properties to set.
    "gender" : "1",                           // Example: Gender
    "birthday" : "1988-12-24"                 // Example: Date of birth
  },
  
  
  "sdk_type" : "httpapi",                     // Fixed value. This field is added automatically by the collection service.
  "server_ts":"1614667799165",             // Optional. If provided, this value is used. Otherwise, the server uses the log ingestion timestamp.
  "_id":'123344'                           // Unique log ID. The collection service generates this field automatically.
}

sign generation

  1. Create a map object containing all key-value pairs from the request, excluding the sign field.

  2. Serialize the map to a compact JSON string, with keys sorted in natural ASCII order. Ensure there are no spaces between fields. For Java, you can use JSONObject.toJSONString(mapObject, SerializerFeature.MapSortField).

  3. Retrieve your ServiceSecret.

  4. Concatenate the sorted JSON string with your ServiceSecret and compute the MD5 hash of the result: sign = MD5(sorted_json_string + ServiceSecret).

  5. Add the sign value to the map, then serialize it to create the final request payload.

Signature verification flow

image

Responses

The response Content-Type is application/json.

The response body is a JSON string containing two fields: code and message.

Code

Message

Description

Httpapi_300_200

Request successful

The request was successful.

Httpapi_300_101

Invalid signature

Signature verification failed. See the section on generating the sign value.

Httpapi_300_102

Invalid JSON format

The request payload is not in a valid JSON format.

Httpapi_300_103

A required field is missing

A required parameter is missing. Check the request parameter tables.

Httpapi_300_104

A required field for user properties is missing

A required parameter for user properties is missing. Check the request parameter tables.

Httpapi_300_105

Invalid event ID

The provided event ID is incorrect.

Httpapi_300_106

Incorrect appkey or ServiceSecret

The appkey or ServiceSecret is incorrect.

Java demo

package com.aliyun.app.quickaplus.mock.once_mock;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.aliyun.app.quickaplus.mock.util.MD5Util;
import okhttp3.*;
import java.io.IOException;
/**
* Server-side API demo.
*
* @author chengtao
*/
public class ServiceApiDemo {
    /**
    * Primary domain name.
    */
    private static final String API_URL = "*****";
    /**
    * Corresponds to the ServiceID in your server-side data tracking information.
    */
    private static final String SERVICE_ID = "*******";
    /**
    * Corresponds to the ServiceSecret in your server-side data tracking information.
    */
    private static final String SERVICE_SECRET = "*******";
    /**
    * HTTP client for sending logs.
    */
    private static final OkHttpClient client = new OkHttpClient();
/**
* Main function.
*
* @param args Arguments.
*/
    public static void main(String[] args) {
        String srcJsonString = getMockData();
        JSONObject json = JSON.parseObject(srcJsonString);
        // Add the service ID to the payload.
        json.put("app_id",SERVICE_ID);
        // Add the timestamp to the payload.
        json.put("ts", String.valueOf(System.currentTimeMillis()));
        // Calculate the signature.
        String sign = MD5Util.md5(JSONObject.toJSONString(json,
        SerializerFeature.MapSortField) + SERVICE_SECRET);
        json.put("sign", sign);
        String desJsonString = JSON.toJSONString(json,
        SerializerFeature.DisableCircularReferenceDetect);
        Request request = new Request.Builder()
        .url(API_URL + "/server")
        .post(RequestBody.create(desJsonString,
        MediaType.parse("application/json")))
        .build();
        try {
            Response response = client.newCall(request).execute();
            if (!response.isSuccessful()) {
                System.out.printf("[DEMO] Failed to send log: %s%n", response);
            } else {
                System.out.printf("[DEMO] Send successful: %s%n",
                response.body().string());
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
/**
* Gets mock data.
*
* @return A JSON string of mock data.
*/
    private static String getMockData() {
        return "{\n" +
        " \"appkey\": \"1344444\",\n" +
        " \"id\": \"get_coupons\",\n" +
        " \"umid\": \"uuid()\",\n" +
        " \"puid\": \"puid1\",\n" +
        " \"page_name\": \"home_page\",\n" +
        " \"cusp\": {\n" +
        " \"p1\": \"1\",\n" +
        " \"p2\": \"2\",\n" +
        " \"p3\": \"3\"\n" +
        " },\n" +
        " \"gp\": {\n" +
        " \"p1\": \"1\",\n" +
        " \"p2\": \"2\",\n" +
        " \"p3\": \"3\"\n" +
        " },\n" +
        " \"sdk_type\": \"httpapi\"\n" +
        "}";
    }
}

Python demo

# Correctly formatted string for signing (compact, sorted keys)
{"appkey":"4b6G49PAkLUb4212","cusp":{"p1":"1","p2":"2","p3":"3"},"gp":{"p1":"1","p2":"2","p3":"3"},"id":"get_coupons","page_name":"home_page","puid":"puid1","sdk_type":"httpapi","umid":"uuid()"}tEkNnx8VDuR0mwEl3hXd7aozYh8Q2qS4
# Incorrectly formatted string for signing (contains spaces)
{"appkey": "your_app_key", "cusp": {"p1": "1", "p2": "2", "p3": "3"}, "gp": {"p1": "1", "p2": "2", "p3": "3"}, "id": "get_coupons", "page_name": "home_page", "puid": "puid1", "sdk_type": "httpapi", "umid": "uuid()"}tEkNnx8VDuR0mwEl3hXd7aozYh8Q2qS
import json
import hashlib
import http.client
import ssl
import time

# Replace with your service ID
service_id = "your_service_id"
# Replace with your service secret
service_secret = "your_service_secret"
# Replace with your data ingestion service endpoint
qlc_end_point = "https://your_endpoint.com"

def get_millisecond_timestamp():
    # Get a 13-digit millisecond timestamp
    return str(int(round(time.time() * 1000)))

ts1 = get_millisecond_timestamp()
print(ts1)

# Mock payload
data = {
   # For debugging only. Must be an empty string or removed in production. 
   # Must match the DebugKey entered in "Tracking Verification > Server-side Verification".
    "dk":"",
   # Replace with your appkey
    "appkey":"your_appkey",
    "app_id": service_id,
    "id": "get_coupons",
    "umid": "uuid1",
    "puid": "puid2",
    "page_name": "home_page",
    "ts": ts1,
    "cusp": {
        "card_type": "experience",
        "scene": "purchase",
        "card_level": "trial",
        "carrier": "YourApp",
        "card_no": "d7tyk",
        "user_id": "zsfMzsvHyA==",
        "card_name": "7-day-trial",
        "resource_id": "eedf17067cf64be299a844bbc8101426"
    },
    "gp": {
        "p1": "1",
        "p2": "2",
        "p3": "3"
    },
    "sdk_type": "httpapi"
}

def sort_dict_keys(d):
    # Recursively sort dictionary keys
    return {k: sort_dict_keys(v) if isinstance(v, dict) else v for k, v in sorted(d.items())}

# Sort keys in alphabetical (lexicographical) order
sorted_data = sort_dict_keys(data)

# Create the string to sign: a compact JSON string (no spaces) + service_secret
string_to_sign = json.dumps(sorted_data, ensure_ascii=False, separators=(',', ':')) + service_secret
print("String to sign:", string_to_sign)

# Add the MD5 signature to the original data payload
data['sign'] = hashlib.md5(string_to_sign.encode('utf-8')).hexdigest()

# The final payload to send is the full JSON object
final_payload = json.dumps(data)

protocol, domain = qlc_end_point.split('://')
conn = None
if protocol == 'http':
    conn = http.client.HTTPConnection(domain)
elif protocol == 'https':
    conn = http.client.HTTPSConnection(domain)

if conn:
    conn.request("POST", "/server", body=final_payload, headers={"Content-Type": "application/json"})
    response = conn.getresponse()
    print("Response:", response.read().decode())
    conn.close()

MD5Util class code

package com.aliyun.app.quickaplus.mock.util;

import java.security.MessageDigest;

/**
 * MD5 hashing utility class.
 *
 * @author zheng.zhang
 */
public class MD5Util {

    public static String md5(String s) {
        char hexDigits[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
        try {
            byte[] btInput = s.getBytes();
            // Get a MessageDigest object that implements the MD5 algorithm.
            MessageDigest mdInst = MessageDigest.getInstance("MD5");
            // Update the digest using the specified byte array.
            mdInst.update(btInput);
            // Get the hash's bytes.
            byte[] md = mdInst.digest();
            // Convert the byte array into a hexadecimal string.
            int j = md.length;
            char str[] = new char[j * 2];
            int k = 0;
            for (int i = 0; i < j; i++) {
                byte byte0 = md[i];
                str[k++] = hexDigits[byte0 >>> 4 & 0xf];
                str[k++] = hexDigits[byte0 & 0xf];
            }
            return new String(str);
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * Unit test.
     */
    public static void main(String[] args) {
        StringBuilder dtskey = new StringBuilder("abc12390");
        dtskey.append('\0').append("~!@#$%^&*()_+");
        System.out.println(MD5Util.md5(dtskey.toString()));
        System.out.println(MD5Util.md5("20121221"));
        System.out.println(MD5Util.md5("Encrypt"));
    }
}