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
- Auth model: standard OAuth2 client-credentials mode. Partners exchange the issued
clientId + clientSecretfor a short-livedaccess_token, then call business endpoints with that token. The open platform does not involve user login, authorization-code, or password grants. - Endpoint isolation: all open endpoints live under the
/open-api/**prefix and are routed separately by the gateway. Open tokens have a fixed user type ofOPEN_APIand cannot access/admin-apior/app-api, eliminating privilege escalation at the source. - Permission granularity: each endpoint is guarded by the
scopeit requires (e.g. the goods-detail endpoint requiresgoods:detail:read). An application can only call endpoints corresponding to the scopes granted to it. - Multi-tenancy: requests must carry
tenant-id, which must match the one used when the token was obtained.
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
- Contact platform operations and submit: partner name, contact (name / email / phone), source IPs for callbacks (optional, for the IP whitelist), and the required scopes.
- Operations creates the application under Admin Console "Open Platform / Partner Applications" and issues:
clientIdclientSecret(shown only once; store it securely)- the granted
scopelist (e.g.goods:detail:read) tenant-id
- The partner exchanges
clientId + clientSecretfor anaccess_token, then calls business endpoints with the token.
Pre-launch checklist:
-
clientSecretstored securely (recommended: a secrets manager; never embed in frontend/client code or logs). - All required
scopes confirmed as granted. - Caller egress IP added to the whitelist (if operations enabled the whitelist).
- Token caching implemented (reuse within
expires_in; do not fetch a token on every request). - Auto re-fetch on
401and exponential backoff retry on429implemented.
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 isapi-qa.rizzitbuy.com. Replace placeholders such as{tenant-id},{clientId},{clientSecret}with the actual values issued by operations.
5. Obtaining an Access Token
- Method & path:
POST /open-api/system/oauth2/token - Authentication: HTTP Basic. Base64-encode
clientId:clientSecretand put it in theAuthorizationheader (i.e.Authorization: Basic base64(clientId:clientSecret)). - Content-Type:
application/x-www-form-urlencoded
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 othergrant_type(such asauthorization_code/password/refresh_token) returns400with the message "the open platform only supports the client_credentials grant". The token'suserTypeis fixed toOPEN_APIand cannot access/admin-apior/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)
- Method & path:
POST /open-api/goods/detail - Required scope:
goods:detail:read
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
- Method & path:
POST /open-api/goods/qc-detail - Required scope:
goods:qc:read
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
- Method & path:
POST /open-api/goods/qc-images - Required scope:
goods:qc:read - Request body: same as 7.2 (
goodsId+source)
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
- Method & path:
POST /open-api/goods/qc-page - Required scope:
goods:qc:read
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
- Method & path:
POST /open-api/goods/search-by-images - Required scope:
goods:search:read
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
- Method & path:
POST /open-api/goods/search-url-parse - Required scope:
goods:search:read - Description: Parses short or long links from Taobao/Tmall, 1688, Weidian, and common agent sites (cssbuy, cnfans, hoobuy, etc.) to extract the platform goods ID and source. Unrecognized links return "Failed to parse product 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)
- Method & path:
POST /open-api/promotion/redeem-code/redeem - Required scope:
promotion:redeem-code:redeem - Description: Uses a pre-configured redeem code from the platform admin (which can bind N coupon templates and randomly hit one by weight) to issue a coupon to the member identified by the given email. The member must already exist (exact email match); otherwise it returns "Member does not exist". This endpoint does not auto-create members.
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)
- Method & path:
POST /open-api/system/oauth2/token/revoke - Authentication: same as obtaining a token (HTTP Basic)
- Parameter:
token={access_token}(application/x-www-form-urlencoded)
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
- IP whitelist: if operations configured
ipWhitelistfor the application (comma-separated, multiple IPs), only source IPs in the whitelist may call; empty means no restriction. - Rate limiting: a per-application QPS can be configured (
rateLimitQps,0means unlimited). Exceeding it returns429. - Secret storage:
clientSecretis shown only once; never embed it in frontend/client code, logs, or version control. If leaked, immediately contact operations to "Reset Secret" under "Partner Applications"; the old secret is invalidated instantly. - Token caching and concurrent refresh: cache the
access_tokenon the client and reuse it withinexpires_into avoid frequent token fetches. Refresh ahead of expiry with a buffer (e.g. when less than 60s remain), and lock the refresh to prevent concurrent duplicate fetches. - Retry and backoff: on
401, re-fetch the token and retry once; on429or network jitter, retry with exponential backoff (e.g. 1s, 2s, 4s) with an upper bound. - Multi-tenancy: always carry a
tenant-idconsistent with the token to avoid cross-tenant access being rejected.
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
- Frequent
401s? Usually the token expired or was not cached. Reuse the token withinexpires_inand refresh before expiry; ensure theAuthorizationheader is in theBearer {access_token}format. - Getting
403? The application has not been granted thescoperequired by that endpoint. Contact operations to grant it. - Getting
429? You hit the per-clientIdQPS limit. Lower the rate and retry with backoff; request a higher quota if needed. - Cross-tenant access rejected? Ensure the
tenant-idheader matches the one used to obtain the token. clientSecretleaked? Immediately contact operations to "Reset Secret"; the old secret is invalidated instantly. Update the secret in your configuration.
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. |