All Products
Search
Document Center

Marketplace:Marketplace Token Tracking Guide

Last Updated:Jul 14, 2026

Alibaba Cloud Marketplace — Token Consumption Tracking Guide for Partners

This guide walks you through the implementation of token consumption tracking (metering) for products listed on the Alibaba Cloud Marketplace that invoke Alibaba Cloud Model Studio (Bailian) APIs. Proper tracking ensures your product qualifies as a MaaS (Model-as-a-Service) product, which unlocks platform-level sales support, promotional resources, and accurate revenue attribution.

Why this matters: Products without proper tracking cannot be classified as MaaS products, which results in reduced sales effort and fewer platform resources allocated to your listing.

1. Overview

When your product calls Bailian APIs (e.g., Qwen models), you need to attach a special HTTP header x-dashscope-euid to every API request. This header identifies the end customer so that token consumption is correctly attributed to their account and to your product.

The implementation has three moving parts:

  1. Receive customer identity via an SPI callback (or License API) when a customer purchases your product on the Marketplace.

  2. Store the mapping between the customer and their productCode + aliUid in your system.

  3. Attach the tracking header to every Bailian API call, dynamically populated from your stored mapping.

Estimated implementation effort: 1–2 developer days.

2. The x-dashscope-euid Header

Every request to the Bailian API must include the following header:

x-dashscope-euid: <JSON string>

The JSON payload contains exactly five fields. All five are required.

Field

Type

Fixed?

Value

bizType

String

Fixed

B2B

moduleType

String

Fixed

Third-partyproducts

moduleCode

String

Dynamic

market_${productCode} — productCode comes from the SPI callback

accountType

String

Fixed

Aliyun

accountId

String

Dynamic

The customer's Alibaba Cloud account ID (aliUid) from the SPI callback

Example (marketplace customer — "narrow scope"):

{
  "bizType": "B2B",
  "moduleType": "Third-partyproducts",
  "moduleCode": "market_abc123",
  "accountType": "Aliyun",
  "accountId": "1234567890"
}

Example (non-marketplace customer — "broad scope" fallback):

{
  "bizType": "B2B",
  "moduleType": "Third-partyproducts",
  "moduleCode": "market_cmapi00069878",
  "accountType": "Aliyun",
  "accountId": ""
}

The "broad scope" fallback is used when a user calling your service is not found in your mapping table (i.e., they did not purchase through the Marketplace). In this case, moduleCode uses a hardcoded productCode (visible in your ISV console after publishing), and accountId is an empty string.

Case Sensitivity Rules

Component

Case-Sensitive?

Notes

Header key name

No

x-dashscope-euid and X-DashScope-EUID are both accepted

JSON field names (keys)

Yes

Must use exact camelCase: bizType, moduleType, etc.

JSON field values

No

B2B and b2b are both recognized

3. Obtaining Dynamic Values via SPI Callbacks

The values for productCode and accountId (aliUid) come from the Marketplace at the time a customer purchases your product. The mechanism differs by product type.

3A. SaaS Products — SPI Delivery

When publishing your SaaS product, enable "Production API Notification" and configure your SPI callback URL. Select at least the createInstance event.

After a customer completes payment, the Marketplace sends an HTTP GET request to your callback URL:

GET https://your-domain.com/spi/callback?action=createInstance&aliUid=123456&orderBizId=xxx&productCode=abc123&...

Key parameters you need to capture and store:

Parameter

Description

productCode

Your product code — used in moduleCode

aliUid

Customer's Alibaba Cloud account ID

orderBizId

Unique business instance ID for idempotency

Store the mapping orderBizId → (productCode, aliUid) in your database and associate it with the customer's account in your system.

Important: Your SPI endpoint must be idempotent (deduplicate on orderBizId) and respond within 3 seconds. The Marketplace retries up to 120 times on failure.

3B. SaaS Products — License Code Delivery

For license-code products, dynamic values are obtained via the DescribeLicense API instead of SPI callbacks.

When a customer activates their license, call:

DescribeLicense(LicenseCode = "<customer's license code>")

Extract the following from the response:

  • License.ProductCode → used in moduleCode

  • License.ExtendInfo.AliUid → used in accountId

Store these values and bind them to the customer's account for subsequent Bailian API calls.

3C. API Products — orderPay SPI

For API products, configure the Payment Success (orderPay) SPI callback in your ISV console. After a customer pays, the Marketplace pushes:

Parameter

Description

action

Fixed value: orderPay

aliUid

Customer's Alibaba Cloud account ID

orderBizId

Business instance ID = CaCloudMarketInstanceId

productCode

Your product code

You must respond with {"success":true} and ensure idempotency based on requestId.

Critical mapping: orderBizId from the SPI callback is the same value as CaCloudMarketInstanceId that the API Gateway passes through to your backend. Configure your API Gateway to forward CaCloudMarketInstanceId as a backend header, then look up your mapping table to retrieve the corresponding productCode and aliUid.

4. Runtime Logic

At runtime, when a customer triggers a Bailian API call through your product:

Customer invokes your service
        ↓
Look up the customer in your mapping table
        ↓
   ┌────┴────┐
   │ Found?  │
   └────┬────┘
    Yes ↓          No ↓
        ↓              ↓
  Narrow scope     Broad scope (fallback)
  moduleCode =     moduleCode = market_<hardcoded productCode>
    market_<stored productCode>
  accountId =      accountId = ""
    <stored aliUid>
        ↓              ↓
        └──────┬───────┘
               ↓
  Assemble x-dashscope-euid header
               ↓
  Call Bailian API with the header

5. Code Examples

Python (requests library)

import requests
import json

url = "https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions"

headers = {
    "Authorization": "Bearer sk-xxx",
    "Content-Type": "application/json",
    "x-dashscope-euid": json.dumps({
        "bizType": "B2B",
        "moduleType": "Third-partyproducts",
        "moduleCode": "market_abc123",
        "accountType": "Aliyun",
        "accountId": "1234567890"
    })
}

payload = {
    "model": "qwen-plus",
    "messages": [
        {"role": "system", "content": "You are a helpful assistant."},
        {"role": "user", "content": "Hello"}
    ]
}

response = requests.post(url, headers=headers, json=payload)
print(response.json())

Python (OpenAI SDK)

from openai import OpenAI

client = OpenAI(
    api_key="sk-xxx",
    base_url="https://dashscope.aliyuncs.com/compatible-mode/v1",
    default_headers={
        "x-dashscope-euid": '{"bizType":"B2B","moduleType":"Third-partyproducts","moduleCode":"market_abc123","accountType":"Aliyun","accountId":"1234567890"}'
    }
)

response = client.chat.completions.create(
    model="qwen-plus",
    messages=[
        {"role": "system", "content": "You are a helpful assistant."},
        {"role": "user", "content": "Hello"}
    ]
)
print(response.choices[0].message.content)

Java (OkHttp)

import okhttp3.*;

public class BailianTrackingExample {

    public static void main(String[ ] args) throws Exception {

        OkHttpClient client = new OkHttpClient();

        String euidJson = "{\"bizType\":\"B2B\",\"moduleType\":\"Third-partyproducts\","
            + "\"moduleCode\":\"market_abc123\",\"accountType\":\"Aliyun\","
            + "\"accountId\":\"1234567890\"}";

        String body = "{\"model\":\"qwen-plus\",\"messages\":["
            + "{\"role\":\"user\",\"content\":\"Hello\"}]}";

        Request request = new Request.Builder()
            .url("https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions")
            .post(RequestBody.create(body, MediaType.parse("application/json")))
            .addHeader("Authorization", "Bearer sk-xxx")
            .addHeader("Content-Type", "application/json")
            .addHeader("x-dashscope-euid", euidJson)
            .build();

        Response response = client.newCall(request).execute();
        System.out.println(response.body().string());
    }
}

Node.js (fetch)

const response = await fetch(
  "https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions",
  {
    method: "POST",
    headers: {
      "Authorization": "Bearer sk-xxx",
      "Content-Type": "application/json",
      "x-dashscope-euid": JSON.stringify({
        bizType: "B2B",
        moduleType: "Third-partyproducts",
        moduleCode: "market_abc123",
        accountType: "Aliyun",
        accountId: "1234567890"
      })
    },
    body: JSON.stringify({
      model: "qwen-plus",
      messages: [
        { role: "user", content: "Hello" }
      ]
    })
  }
);
const data = await response.json();
console.log(data);

Go

package main

import (
    "bytes"
    "encoding/json"
    "fmt"
    "net/http"
)

func main() {
    euid := map[string]string{
        "bizType":     "B2B",
        "moduleType":  "Third-partyproducts",
        "moduleCode":  "market_abc123",
        "accountType": "Aliyun",
        "accountId":   "1234567890",
    }
    euidBytes, _ := json.Marshal(euid)

    body := map[string]interface{}{
        "model": "qwen-plus",

        "messages": [ ]map[string]string{

            {"role": "user", "content": "Hello"},
        },
    }
    bodyBytes, _ := json.Marshal(body)

    req, _ := http.NewRequest("POST",
        "https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions",
        bytes.NewBuffer(bodyBytes))
    req.Header.Set("Authorization", "Bearer sk-xxx")
    req.Header.Set("Content-Type", "application/json")
    req.Header.Set("x-dashscope-euid", string(euidBytes))

    resp, err := http.DefaultClient.Do(req)
    if err != nil {
        panic(err)
    }
    defer resp.Body.Close()

    var result map[string]interface{}
    json.NewDecoder(resp.Body).Decode(&result)
    fmt.Println(result)
}

Dynamic Header Construction (Java / Spring)

For production use, you should dynamically assemble the header based on the current customer:

import org.springframework.http.*;
import org.springframework.web.client.RestTemplate;

public class BailianService {
    private final RestTemplate restTemplate = new RestTemplate();

    public String callModel(String productCode, String aliUid) {
        HttpHeaders headers = new HttpHeaders();
        headers.set("Authorization", "Bearer sk-xxx");
        headers.set("Content-Type", "application/json");

        String euid = String.format(
            "{\"bizType\":\"B2B\",\"moduleType\":\"Third-partyproducts\","
            + "\"moduleCode\":\"market_%s\",\"accountType\":\"Aliyun\","
            + "\"accountId\":\"%s\"}",
            productCode, aliUid
        );
        headers.set("x-dashscope-euid", euid);

        String body = "{\"model\":\"qwen-plus\",\"messages\":["
            + "{\"role\":\"user\",\"content\":\"Hello\"}]}";

        HttpEntity<String> entity = new HttpEntity<>(body, headers);
        ResponseEntity<String> response = restTemplate.postForEntity(
            "https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions",
            entity, String.class
        );
        return response.getBody();
    }
}

6. Common Mistakes and Troubleshooting

#

Symptom

Cause

Fix

1

Token consumption not attributed

x-dashscope-euid header is missing from the API call

Ensure the header is attached to every Bailian API request

2

Tracking is invalid

JSON field names use wrong casing (e.g., biztype instead of bizType)

Use exact camelCase for all JSON keys

3

Tracking is invalid

One or more of the 5 required fields are missing

Always include all 5 fields: bizType, moduleType, moduleCode, accountType, accountId

4

Tracking is invalid

moduleCode format is wrong

Must be market_${productCode} — do not forget the market_ prefix

5

Tokens attributed to wrong customer

accountId does not match the actual calling customer

Ensure your mapping table correctly binds each customer to their aliUid

7. Best Practices

  • Centralize header construction. Build a single utility method that assembles the x-dashscope-euid header, so the logic is not duplicated across your codebase.

  • Use a JSON serialization library. Avoid hand-constructing JSON strings. Use your language's standard JSON library to ensure correct formatting.

  • Maintain a customer mapping table. Store customer → (productCode, aliUid) in your database, populated from SPI callbacks or the DescribeLicense API.

  • Add logging during development. Print the x-dashscope-euid value in debug logs so you can verify correctness before going live.

  • Test before production. Validate your tracking implementation in a staging environment, then ask your PDM or PSA to confirm the data is correctly reported on the backend.

8. Verification

After completing your implementation, contact your Alibaba Cloud PDM (Product Development Manager) or PSA (Partner Solution Architect) to:

  1. Confirm that tracking data is being received on the platform side.

  2. Verify that token consumption is correctly attributed to the right product and customer accounts.

  3. Validate both the narrow-scope (marketplace customers) and broad-scope (non-marketplace fallback) paths.

9. Prerequisites and Constraints

  • Your product must call Bailian APIs using first-party models (e.g., Qwen, HappyHorse). Tracking only works for first-party model invocations via Bailian.

  • If your product currently uses models from other platforms or self-deployed models, you will need to migrate model calls to Bailian before tracking can be implemented.

  • Any programming language or SDK can be used, as long as you can attach custom HTTP headers to outbound requests.

10. Reference Links

Marketplace — SPI Delivery (SaaS Products)

Marketplace — License Code Delivery (SaaS Products)

Marketplace — General

Model Studio (Bailian)