Open Platform (Open API) Integration Guide

Online docs (recommended): https://docs.rizzitgo.com — API reference stays in sync with this guide
Audience: external partners / third-party developers
Languages: English (this document) · 中文

This guide explains how to integrate with our /open-api/* open endpoints. The open endpoints are physically isolated from the consumer-facing /app-api and the admin /admin-api. They use OAuth2 client_credentials (client mode) for authentication, and control the set of callable endpoints per application via scope.


1. Overview and Architecture

Call sequence:

sequenceDiagram
    participant P as Partner App
    participant GW as API Gateway
    participant SYS as System Service
    participant BIZ as Business Service

    P->>GW: POST /open-api/system/oauth2/token<br/>Basic(clientId:clientSecret)
    GW->>SYS: forward token request
    SYS-->>P: access_token (userType=OPEN_API, expires_in)
    P->>GW: POST /open-api/goods/detail<br/>Bearer access_token + tenant-id
    GW->>BIZ: validate token + scope, then forward
    BIZ-->>P: business data (unified {code,data,msg})

2. Glossary

Term Description
clientId Client ID, the public identifier of the application.
clientSecret Client secret, shown only once at creation/reset. Treat it like a password and keep it secret.
scope Authorization scope; determines which endpoints can be called. Multiple values are space-separated (e.g. goods:detail:read).
tenant-id Tenant ID, the multi-tenant isolation identifier, passed as a request header.
access_token Access token, the credential for calling business endpoints; time-limited (see expires_in).
expires_in Remaining token lifetime, in seconds.
userType User type; always OPEN_API for open-platform tokens.

3. Onboarding Process

  1. Contact platform operations and submit: partner name, contact (name / email / phone), source IPs for callbacks (optional, for the IP whitelist), and the required scopes.
  2. Operations creates the application under Admin Console "Open Platform / Partner Applications" and issues:
    • clientId
    • clientSecret (shown only once; store it securely)
    • the granted scope list (e.g. goods:detail:read)
    • tenant-id
  3. The partner exchanges clientId + clientSecret for an access_token, then calls business endpoints with the token.

Pre-launch checklist:


4. Environments and Domains

Environment Gateway domain Notes
Sandbox / Test api-qa.rizzitbuy.com For integration testing; data isolated from production.
Production api.rizzitgo.com Live environment.

The production gateway domain is api.rizzitgo.com (already used in the examples), and the test/sandbox gateway domain is api-qa.rizzitbuy.com. Replace placeholders such as {tenant-id}, {clientId}, {clientSecret} with the actual values issued by operations.


5. Obtaining an Access Token

Request parameters:

Parameter Location Required Description
Authorization Header Yes Basic base64(clientId:clientSecret)
tenant-id Header Yes Tenant ID
grant_type Body Yes Fixed value client_credentials
scope Body No Space-separated; if omitted, all scopes granted to the application are used

Request example:

curl -X POST 'https://api.rizzitgo.com/open-api/system/oauth2/token' \
  -H 'Authorization: Basic {base64(clientId:clientSecret)}' \
  -H 'tenant-id: {tenant-id}' \
  -d 'grant_type=client_credentials' \
  -d 'scope=goods:detail:read'

Response fields:

Field Type Description
access_token string Access token, carried in subsequent business requests
refresh_token string Empty string in client-credentials mode (no refresh token; re-fetch after expiry)
token_type string Fixed value Bearer
expires_in number Token lifetime in seconds, e.g. 1800
scope string The actually granted scopes, space-separated

Response example:

{
  "code": 0,
  "data": {
    "access_token": "xxxxxxxx",
    "refresh_token": "",
    "token_type": "Bearer",
    "expires_in": 1800,
    "scope": "goods:detail:read"
  },
  "msg": ""
}

Note: the open platform only supports client_credentials. Passing any other grant_type (such as authorization_code / password / refresh_token) returns 400 with the message "the open platform only supports the client_credentials grant". The token's userType is fixed to OPEN_API and cannot access /admin-api or /app-api.


6. Calling Business Endpoints

Every business request must include:

Header Required Description
Authorization Yes Bearer {access_token}
tenant-id Yes The tenant ID, matching the one used to obtain the token
Content-Type Yes (when there is a body) application/json

7. API Reference

7.1 Query Goods Detail (pilot)

Request body (application/json):

Field Type Required Description
goodsId string Yes Goods ID; must not be empty and must not be 0
source integer Yes Goods source: 1=Taobao, 2=1688, 3=Weidian

Request example:

curl -X POST 'https://api.rizzitgo.com/open-api/goods/detail' \
  -H 'Authorization: Bearer {access_token}' \
  -H 'tenant-id: {tenant-id}' \
  -H 'Content-Type: application/json' \
  -d '{"goodsId":"123456","source":1}'

Response fields:

Field Type Description
goodsId string Goods ID
goodsTitle string Goods title
goodsDetailUrl string Goods detail page URL
goodsPicUrl string Goods main image
price string Price (in yuan)
priceInCents number Price (in cents)
orginalPrice string Original price (in yuan)
stockNum string Stock quantity
salesCount string Sales count
goodsImageUrlList string[] List of goods image URLs
postFee string Shipping fee (in yuan)
goodsSource integer Goods source: 1=Taobao, 2=1688, 3=Weidian

Response example:

{
  "code": 0,
  "data": {
    "goodsId": "123456",
    "goodsTitle": "Sample Goods",
    "goodsDetailUrl": "https://example.com/item/123456",
    "goodsPicUrl": "https://example.com/img/123456.jpg",
    "price": "99.00",
    "priceInCents": 9900,
    "orginalPrice": "129.00",
    "stockNum": "1000",
    "salesCount": "532",
    "goodsImageUrlList": [
      "https://example.com/img/1.jpg",
      "https://example.com/img/2.jpg"
    ],
    "postFee": "0.00",
    "goodsSource": 1
  },
  "msg": ""
}

7.2 Query Goods QC Detail

Request body (application/json):

Field Type Required Description
goodsId string Yes Goods ID; must not be empty and must not be 0
source integer Yes Goods source: 1=Taobao, 2=1688, 3=Weidian

Request example:

curl -X POST 'https://api.rizzitgo.com/open-api/goods/qc-detail' \
  -H 'Authorization: Bearer {access_token}' \
  -H 'tenant-id: {tenant-id}' \
  -H 'Content-Type: application/json' \
  -d '{"goodsId":"123456","source":1}'

Response fields:

Field Type Description
goodsId string Goods ID
qcPathList string[] QC photo URL list
length string Length (cm)
width string Width (cm)
height string Height (cm)
weight string Weight (g)
volume string Volume (cm3)
completionTime string QC completion time (yyyy-MM-dd HH:mm:ss)

Note: for internal information protection, the QC endpoints do not return inspector / photographer staff IDs or names.

Response example:

{
  "code": 0,
  "data": {
    "goodsId": "123456",
    "qcPathList": [
      "https://example.com/qc/1.jpg",
      "https://example.com/qc/2.jpg"
    ],
    "length": "30",
    "width": "20",
    "height": "10",
    "weight": "500",
    "volume": "6000",
    "completionTime": "2026-06-02 18:30:00"
  },
  "msg": ""
}

7.3 Query Goods QC Image List

Request example:

curl -X POST 'https://api.rizzitgo.com/open-api/goods/qc-images' \
  -H 'Authorization: Bearer {access_token}' \
  -H 'tenant-id: {tenant-id}' \
  -H 'Content-Type: application/json' \
  -d '{"goodsId":"123456","source":1}'

Response example: data is an array of QC image URLs.

{
  "code": 0,
  "data": [
    "https://example.com/qc/1.jpg",
    "https://example.com/qc/2.jpg"
  ],
  "msg": ""
}

7.4 Paginated QC Data Query by Time

Request body (application/json):

Field Type Required Description
pageNo integer Yes Page number, starting from 1
pageSize integer Yes Page size
goodsId string No Filter by exact goods ID
source integer No Goods source: 1=Taobao, 2=1688, 3=Weidian
createTime string[] No Record creation time range [start, end], format yyyy-MM-dd HH:mm:ss
completionTime string[] No QC completion time range [start, end], format yyyy-MM-dd HH:mm:ss

Request example:

curl -X POST 'https://api.rizzitgo.com/open-api/goods/qc-page' \
  -H 'Authorization: Bearer {access_token}' \
  -H 'tenant-id: {tenant-id}' \
  -H 'Content-Type: application/json' \
  -d '{
        "pageNo": 1,
        "pageSize": 10,
        "completionTime": ["2026-06-01 00:00:00", "2026-06-02 23:59:59"]
      }'

Response fields: data.list is an array of QC details (same fields as 7.2), data.total is the total count.

{
  "code": 0,
  "data": {
    "list": [
      {
        "goodsId": "123456",
        "qcPathList": ["https://example.com/qc/1.jpg"],
        "length": "30",
        "width": "20",
        "height": "10",
        "weight": "500",
        "volume": "6000",
        "completionTime": "2026-06-02 18:30:00"
      }
    ],
    "total": 1
  },
  "msg": ""
}

7.5 Search Goods by Image

Request body (application/json):

Field Type Required Description
imagesUrl string Yes Image URL; must be a publicly accessible image address (common image extensions such as .jpg/.png). An invalid format returns "The image URL format is invalid"
page integer Yes Current page, starting from 1
source integer Yes Goods source: 1=Taobao, 2=1688, 3=Weidian

Request example:

curl -X POST 'https://api.rizzitgo.com/open-api/goods/search-by-images' \
  -H 'Authorization: Bearer {access_token}' \
  -H 'tenant-id: {tenant-id}' \
  -H 'Content-Type: application/json' \
  -d '{"imagesUrl":"https://example.com/img/query.jpg","page":1,"source":1}'

Response fields:

Field Type Description
goodsList object[] Goods list; element fields below
page integer Current page
size integer Page size
totalPage integer Total pages
totalCount integer Total count

goodsList element fields:

Field Type Description
goodsId string Goods ID
goodsTitle string Goods title
goodsDetailUrl string Goods detail page URL
goodsPicUrl string Goods main image
goodsSource integer Goods source: 1=Taobao, 2=1688, 3=Weidian
price string Price (yuan)
priceInCents number Price (cents)
originPriceInCents number Original/strike-through price (cents)
salesCount string Sales count
hasDiscount boolean Whether a promotion applies
discountPriceInCents number Discounted price (cents)

Note: to protect internal information, the open API does not return member-scoped fields such as collection status or personalized share links.

Response example:

{
  "code": 0,
  "data": {
    "goodsList": [
      {
        "goodsId": "123456",
        "goodsTitle": "Sample Goods",
        "goodsDetailUrl": "https://example.com/item/123456",
        "goodsPicUrl": "https://example.com/img/123456.jpg",
        "goodsSource": 1,
        "price": "99.00",
        "priceInCents": 9900,
        "originPriceInCents": 9900,
        "salesCount": "532",
        "hasDiscount": true,
        "discountPriceInCents": 8900
      }
    ],
    "page": 1,
    "size": 20,
    "totalPage": 5,
    "totalCount": 100
  },
  "msg": ""
}

7.6 Parse Goods URL

Request body (application/json):

Field Type Required Description
searchUrl string Yes The goods link to parse. Supports short links, long links, and pasted text with noise (spaces and Chinese characters are stripped automatically).
rno string No Promotion code; when non-empty it is appended to the response targetGoodsDetailUrl.

Request example:

curl -X POST 'https://api.rizzitgo.com/open-api/goods/search-url-parse' \
  -H 'Authorization: Bearer {access_token}' \
  -H 'tenant-id: {tenant id}' \
  -H 'Content-Type: application/json' \
  -d '{"searchUrl":"https://detail.tmall.com/item.htm?id=768650559131","rno":"ABC123"}'

Response fields:

Field Type Description
goodsId string Platform goods ID
goodsSource integer Goods source: 1=Taobao, 2=1688, 3=Weidian, 4=Other
goodsSourceName string Goods source name (taobao/alibaba/weidian)
goodsDetailUrl string Original platform goods detail page URL
targetGoodsDetailUrl string In-site share link (includes the promotion code when rno is non-empty)
success boolean Whether parsing succeeded
searchUrl string The cleaned input link

Response example:

{
  "code": 0,
  "data": {
    "goodsId": "768650559131",
    "goodsSource": 1,
    "goodsSourceName": "taobao",
    "goodsDetailUrl": "https://detail.tmall.com/item.htm?id=768650559131",
    "targetGoodsDetailUrl": "https://www.rizzitgo.com/detailPage?goodsId=768650559131&source=1&rno=ABC123",
    "success": true,
    "searchUrl": "https://detail.tmall.com/item.htm?id=768650559131"
  },
  "msg": ""
}

7.7 Redeem Coupon by Code (issue to a member by email)

Request body (application/json):

Field Type Required Description
code string Yes Redeem code
email string Yes Email of the recipient member, must exactly match a platform member account
requestId string No External request id for idempotency; the same requestId is processed only once within 10 minutes, duplicates return "Duplicate request, please do not retry"

Request example:

curl -X POST 'https://api.rizzitgo.com/open-api/promotion/redeem-code/redeem' \
  -H 'Authorization: Bearer {access_token}' \
  -H 'tenant-id: {tenantId}' \
  -H 'Content-Type: application/json' \
  -d '{"code":"E602F4DC626E4948","email":"[email protected]","requestId":"REQ-20260604-0001"}'

Response fields:

Field Type Description
code string Redeem code
email string Recipient member email
prize string Prize description, auto-generated from the coupon discount: percentage coupon as 30% OFF, amount coupon as $10 OFF (USD, converted from cents); comma-separated when multiple; falls back to coupon title when no discount info
success boolean Whether redemption succeeded
message string Result description
coupons object[] Coupons issued in this redemption (usually 1 in random mode); element fields below

coupons element fields:

Field Type Description
templateId number Coupon template ID
title string Coupon title
couponType integer Coupon type: 1=shipping, 2=product, 3=site-wide
discountType integer Discount type: 1=amount-off, 2=percentage-off
discountPrice number Discount amount (in cents)
discountPercent number Discount percent (effective when discountType=2, e.g. 80 means 20% off)
usePriceCondition number Threshold: minimum spend to use (in cents, 0 = no threshold)
validStartTime string Valid from
validEndTime string Valid until

Response example:

{
  "code": 0,
  "data": {
    "code": "E602F4DC626E4948",
    "email": "[email protected]",
    "prize": "30% OFF",
    "success": true,
    "message": "兑换成功,共获得 1 张优惠券",
    "coupons": [
      {
        "templateId": 1001,
        "title": "满100减10",
        "couponType": 2,
        "discountType": 1,
        "discountPrice": 1000,
        "discountPercent": null,
        "usePriceCondition": 10000,
        "validStartTime": "2026-06-01 00:00:00",
        "validEndTime": "2026-06-30 23:59:59"
      }
    ]
  },
  "msg": ""
}

Business errors: empty email returns "Email is required"; no member found by email returns "Member does not exist"; non-existent/expired/voided redeem codes and per-user or per-day (incl. per-IP) redemption limits reuse the existing redeem-code error codes. Redemption limits, validity and quotas are configured in the admin; please call within the agreed quota.


8. Revoking a Token (optional)

curl -X POST 'https://api.rizzitgo.com/open-api/system/oauth2/token/revoke' \
  -H 'Authorization: Basic {base64(clientId:clientSecret)}' \
  -H 'tenant-id: {tenant-id}' \
  -d 'token={access_token}'

9. Unified Response Structure and Error Codes

All endpoints return the unified structure { code, data, msg }: code = 0 means success, anything else means failure, and msg carries the message.

Common errors:

HTTP / code Meaning Suggested handling
401 Token missing / invalid / expired Obtain a new token and retry
403 Insufficient scope / wrong user type Contact operations to grant the required scope
429 Rate limited (per clientId) Lower the call rate, retry with exponential backoff, request a higher QPS if needed
400 Invalid parameter / unsupported grant_type Check request parameters and grant type

10. Security and Limits


11. Code Samples (obtain token -> query goods detail)

cURL

# 1) obtain token
TOKEN=$(curl -s -X POST 'https://api.rizzitgo.com/open-api/system/oauth2/token' \
  -H 'Authorization: Basic {base64(clientId:clientSecret)}' \
  -H 'tenant-id: {tenant-id}' \
  -d 'grant_type=client_credentials' \
  -d 'scope=goods:detail:read' | jq -r '.data.access_token')

# 2) query goods detail
curl -X POST 'https://api.rizzitgo.com/open-api/goods/detail' \
  -H "Authorization: Bearer ${TOKEN}" \
  -H 'tenant-id: {tenant-id}' \
  -H 'Content-Type: application/json' \
  -d '{"goodsId":"123456","source":1}'

Java (JDK 11+ HttpClient)

import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.util.Base64;

public class OpenApiDemo {

    static final String GATEWAY = "https://api.rizzitgo.com";
    static final String TENANT_ID = "{tenant-id}";
    static final String CLIENT_ID = "{clientId}";
    static final String CLIENT_SECRET = "{clientSecret}";

    public static void main(String[] args) throws Exception {
        HttpClient http = HttpClient.newHttpClient();

        // 1) obtain token
        String basic = Base64.getEncoder()
                .encodeToString((CLIENT_ID + ":" + CLIENT_SECRET).getBytes());
        HttpRequest tokenReq = HttpRequest.newBuilder()
                .uri(URI.create(GATEWAY + "/open-api/system/oauth2/token"))
                .header("Authorization", "Basic " + basic)
                .header("tenant-id", TENANT_ID)
                .header("Content-Type", "application/x-www-form-urlencoded")
                .POST(HttpRequest.BodyPublishers.ofString(
                        "grant_type=client_credentials&scope=goods:detail:read"))
                .build();
        HttpResponse<String> tokenResp = http.send(tokenReq, HttpResponse.BodyHandlers.ofString());
        System.out.println(tokenResp.body());
        // In a real project, parse data.access_token with a JSON library
        String accessToken = "<parse data.access_token from tokenResp>";

        // 2) query goods detail
        HttpRequest bizReq = HttpRequest.newBuilder()
                .uri(URI.create(GATEWAY + "/open-api/goods/detail"))
                .header("Authorization", "Bearer " + accessToken)
                .header("tenant-id", TENANT_ID)
                .header("Content-Type", "application/json")
                .POST(HttpRequest.BodyPublishers.ofString(
                        "{\"goodsId\":\"123456\",\"source\":1}"))
                .build();
        HttpResponse<String> bizResp = http.send(bizReq, HttpResponse.BodyHandlers.ofString());
        System.out.println(bizResp.body());
    }
}

Python (requests)

import base64
import requests

GATEWAY = "https://api.rizzitgo.com"
TENANT_ID = "{tenant-id}"
CLIENT_ID = "{clientId}"
CLIENT_SECRET = "{clientSecret}"

# 1) obtain token
basic = base64.b64encode(f"{CLIENT_ID}:{CLIENT_SECRET}".encode()).decode()
token_resp = requests.post(
    f"{GATEWAY}/open-api/system/oauth2/token",
    headers={"Authorization": f"Basic {basic}", "tenant-id": TENANT_ID},
    data={"grant_type": "client_credentials", "scope": "goods:detail:read"},
)
access_token = token_resp.json()["data"]["access_token"]

# 2) query goods detail
biz_resp = requests.post(
    f"{GATEWAY}/open-api/goods/detail",
    headers={
        "Authorization": f"Bearer {access_token}",
        "tenant-id": TENANT_ID,
        "Content-Type": "application/json",
    },
    json={"goodsId": "123456", "source": 1},
)
print(biz_resp.json())

12. FAQ


13. Online API Documentation

The gateway's Knife4j-aggregated Swagger includes an /open-api/** group, where you can view request/response definitions of each endpoint online to ease integration.


14. Document Version

Version Date Changes
v1.0 2026-06 Initial release: OAuth2 client-credentials integration, goods-detail pilot endpoint.
v1.1 2026-06 Added goods QC endpoints: QC detail, QC image list, paginated QC query by time (scope goods:qc:read); token_type corrected to Bearer.
v1.2 2026-06 Added search-goods-by-image endpoint /open-api/goods/search-by-images (scope goods:search:read).
v1.3 2026-06 Added coupon redeem endpoint /open-api/promotion/redeem-code/redeem (scope promotion:redeem-code:redeem), issuing coupons to a member by email.
v1.4 2026-06 Added goods URL parse endpoint /open-api/goods/search-url-parse (scope goods:search:read), with optional promotion code rno.