Waveshare API Documentation
This document is intended for third-party integrators (distributors, ERP systems, quoting platforms, etc.) and describes how to call the Waveshare API.
1. Environments
| Environment | Domain |
| Test | http://120.25.215.223 |
| Production | https://www.waveshare.com |
1.1 Authentication Credentials
| Environment | app_key | app_secret |
| Test |
waveshare_demo |
waveshare_demo_app_secret |
| Production |
Please contact Waveshare official to apply for production credentials. |
Note: In all request/response examples and code samples throughout this document, {{APP_KEY}} and {{APP_SECRET}} are placeholders. Please replace them with the actual credentials listed in the table above before sending requests.
All API requests use the POST method. The request body is in JSON format with Content-Type: application/json.
2. Price Change List (priceloglist)
Retrieves a paginated list of products whose prices have changed within a specified time range.
Endpoint
| Environment | URL |
| Test | POST http://120.25.215.223/restapi/price/changelog |
| Production | POST https://www.waveshare.com/restapi/price/changelog |
2.1 Request Parameters
| Parameter | Required | Type | Description |
app_key | Yes | string | Client identity assigned by Waveshare, e.g. {{APP_KEY}} |
timestamp | Yes | int | Unix epoch timestamp (UTC) at request time; server verifies deviation ≤ 300 seconds |
sign | Yes | string | Request signature, see Section 4 for details |
start_date | No | string | Start date, format YYYY-MM-DD; default is 7 days ago |
end_date | No | string | End date, format YYYY-MM-DD; default is today |
page | No | int | Page number, starting from 1; default is 1 |
page_size | No | int | Number of records per page; default is 20, maximum is 100 |
sku | No | string | Filter by exact SKU (optional) |
2.2 Response Parameters
Success Response (code = 0)
| Field | Type | Description |
code | int | Return code; 0 indicates success |
msg | string | Return message |
server_time | int | Current server Unix timestamp |
data.page | int | Current page number |
data.page_size | int | Records per page |
data.total | int | Total number of matching records |
data.list[].sku | string | Product SKU |
data.list[].part_number | string | Product part number |
data.list[].retail_price | float | Retail price (USD) |
data.list[].distributor_price | float|null | Distributor price (USD). Returns a float under normal conditions; returns null when the discount is cancelled — refer to the desc field |
data.list[].desc | string|null | Description field. Returns discount_cancelled when distributor_price is null due to discount cancellation; otherwise returns null |
data.list[].currency | string | Currency unit, fixed as USD |
data.list[].changed_at | string | Price change date, format YYYY-MM-DD |
Note: The API only returns fields visible to distributors on the Price Changelog page. Sensitive information such as cost prices and internal notes is excluded.
Error Response
| Field | Type | Description |
code | int | Error code |
msg | string | Error description |
server_time | int | Current server Unix timestamp |
Error Code Table
| code | Meaning |
| 0 | Success |
| 40001 | Missing required parameter |
| 40101 | app_key does not exist or is disabled |
| 40102 | Timestamp expired or clock skew exceeds 300 seconds |
| 40104 | Signature error |
| 42901 | Rate limit exceeded (per app_key) |
| 50000 | Internal server error |
2.3 Request Example
POST /restapi/price/changelog
Content-Type: application/json
{"app_key":"{{APP_KEY}}","timestamp":1748083920,"start_date":"2026-03-10","end_date":"2026-03-21","page":1,"page_size":20,"sign":"7A1B2C3D4E5F6A7B8C9D0E1F2A3B4C5D6E7F8A9B0C1D2E3F4A5B6C7D8E9F0"}
2.4 Response Example
{
"code": 0,
"msg": "ok",
"server_time": 1748083920,
"data": {
"page": 1,
"page_size": 20,
"total": 57,
"list": [
{
"sku": "14865",
"part_number": "SIM7000E NB-IoT HAT",
"retail_price": 45.00,
"distributor_price": 37.13,
"desc": null,
"currency": "USD",
"changed_at": "2026-05-21"
},
{
"sku": "10451",
"part_number": "RP2040-Zero",
"retail_price": 5.99,
"distributor_price": null,
"desc": "discount_cancelled",
"currency": "USD",
"changed_at": "2026-05-21"
}
]
}
}
2.5 Error Response Example
{
"code": 40104,
"msg": "sign error",
"server_time": 1748083920,
"data": null
}
3. Single SKU Price History (pricehistory)
Retrieves the historical price change records for a specific product.
Endpoint
| Environment | URL |
| Test | POST http://120.25.215.223/restapi/price/history |
| Production | POST https://www.waveshare.com/restapi/price/history |
3.1 Request Parameters
| Parameter | Required | Type | Description |
app_key | Yes | string | Client identity assigned by Waveshare |
timestamp | Yes | int | Unix epoch timestamp (UTC) at request time |
sign | Yes | string | Request signature, see Section 4 for details |
sku | Yes | string | Product SKU |
3.2 Response Parameters
Success Response (code = 0)
| Field | Type | Description |
code | int | Return code; 0 indicates success |
msg | string | Return message |
server_time | int | Current server Unix timestamp |
data.sku | string | Product SKU |
data.history[].retail_price | float | Retail price (USD) |
data.history[].distributor_price | float|null | Distributor price (USD). Returns a float under normal conditions; returns null when the discount is cancelled — refer to the desc field |
data.history[].desc | string|null | Description field. Returns discount_cancelled when distributor_price is null due to discount cancellation; otherwise returns null |
data.history[].currency | string | Currency unit, fixed as USD |
data.history[].changed_at | string | Price change date, format YYYY-MM-DD |
3.3 Request Example
POST /restapi/price/history
Content-Type: application/json
{"app_key":"{{APP_KEY}}","timestamp":1748083920,"sku":"10451","sign":"7A1B2C3D4E5F6A7B8C9D0E1F2A3B4C5D6E7F8A9B0C1D2E3F4A5B6C7D8E9F0"}
3.4 Response Example
{
"code": 0,
"msg": "ok",
"server_time": 1748083920,
"data": {
"sku": "10451",
"history": [
{
"retail_price": 5.99,
"distributor_price": 4.79,
"desc": null,
"currency": "USD",
"changed_at": "2026-05-21"
},
{
"retail_price": 6.99,
"distributor_price": null,
"desc": "discount_cancelled",
"currency": "USD",
"changed_at": "2026-05-14"
}
]
}
}
4. Authentication (HMAC-SHA256 Signature)
All API requests must include three authentication parameters: app_key, timestamp, and sign.
4.1 Signature Algorithm
- Prepare parameters: Collect all request parameters except
sign itself.
- Filter empty values: Remove parameters whose values are empty strings or
null.
- Sort lexicographically: Sort parameters by their keys in ascending ASCII order.
- Build the string to sign: Concatenate the sorted parameters as
key=value pairs separated by &. Keys and values must be URL-encoded per RFC 3986. Important: The signature is computed from the key-value pairs of the parameters, not from the JSON body string itself. Therefore, the signature algorithm remains unchanged regardless of the request body format.
- Compute the signature: Sign the concatenated string using the HMAC-SHA256 algorithm with the
app_secret as the key.
- Output: Convert the resulting signature to an uppercase hexadecimal string and use it as the
sign parameter value.
4.2 PHP Example
<?php
function ws_request($path, array $biz, $appKey, $appSecret)
{
// 1. Merge business and authentication parameters
$params = array_merge($biz, [
'app_key' => $appKey,
'timestamp' => time(),
]);
// 2. Filter empty values
foreach ($params as $k => $v) {
if ($v === '' || $v === null) unset($params[$k]);
}
// 3. Sort by key (ASCII ascending)
ksort($params);
// 4. URL-encode and concatenate key-value pairs
$pairs = [];
foreach ($params as $k => $v) {
$pairs[] = rawurlencode($k) . '=' . rawurlencode((string)$v);
}
$stringToSign = implode('&', $pairs);
// 5. Compute HMAC-SHA256 signature and convert to uppercase hex
$params['sign'] = strtoupper(hash_hmac('sha256', $stringToSign, $appSecret));
// 6. Send POST request (JSON body)
$url = 'http://120.25.215.223' . $path; // Test environment; for production, use https://www.waveshare.com
$body = json_encode($params);
$ctx = stream_context_create([
'http' => [
'method' => 'POST',
'header' => "Content-Type: application/json\r\n"
. 'Content-Length: ' . strlen($body) . "\r\n",
'content' => $body,
'timeout' => 10,
'ignore_errors' => true,
],
]);
return json_decode(file_get_contents($url, false, $ctx), true);
}
// ===== Call priceloglist endpoint =====
$resp1 = ws_request('/restapi/price/changelog', [
'start_date' => '2026-03-10',
'end_date' => '2026-03-21',
'page' => 1,
'page_size' => 20,
], '{{APP_KEY}}', '{{APP_SECRET}}');
print_r($resp1);
// ===== Call pricehistory endpoint =====
$resp2 = ws_request('/restapi/price/history', [
'sku' => '10451',
], '{{APP_KEY}}', '{{APP_SECRET}}');
print_r($resp2);
4.3 Python Example
import hashlib
import hmac
import time
import urllib.parse
import requests
def ws_request(path, biz, app_key, app_secret):
# 1. Merge business and authentication parameters
params = {**biz, 'app_key': app_key, 'timestamp': int(time.time())}
# 2. Filter empty values
params = {k: v for k, v in params.items() if v != '' and v is not None}
# 3. Sort by key and URL-encode key-value pairs
sorted_items = sorted(params.items())
qs = urllib.parse.urlencode(sorted_items)
# 4. Compute HMAC-SHA256 signature and convert to uppercase hex
sign = hmac.new(app_secret.encode(), qs.encode(), hashlib.sha256).hexdigest().upper()
params['sign'] = sign
# 5. Send POST request (JSON body)
url = 'http://120.25.215.223' + path # Test environment; for production, use https://www.waveshare.com
return requests.post(url, json=params, timeout=10).json()
# ===== Call priceloglist endpoint =====
resp1 = ws_request(
'/restapi/price/changelog',
{'start_date': '2026-03-10', 'end_date': '2026-03-21', 'page': 1, 'page_size': 20},
'{{APP_KEY}}', '{{APP_SECRET}}',
)
print(resp1)
# ===== Call pricehistory endpoint =====
resp2 = ws_request(
'/restapi/price/history',
{'sku': '10451'},
'{{APP_KEY}}', '{{APP_SECRET}}',
)
print(resp2)
4.4 cURL Example (Manual Signature)
#!/bin/bash
# Note: This example requires you to construct the sign manually.
# In practice, use the SDK or a script to compute it automatically.
APP_KEY="{{APP_KEY}}"
APP_SECRET="{{APP_SECRET}}"
TIMESTAMP=$(date +%s)
# Construct the string to sign (concatenate app_key, timestamp, start_date, end_date, page, page_size)
# Note: The sign below is a placeholder; replace it with the actual computed signature.
# Call priceloglist endpoint (JSON body)
curl -s -X POST "http://120.25.215.223/restapi/price/changelog" \
-H "Content-Type: application/json" \
-d '{"app_key":"{{APP_KEY}}","timestamp":'${TIMESTAMP}',"start_date":"2026-03-10","end_date":"2026-03-21","page":1,"page_size":20,"sign":"<computed_signature>"}'
5. Notes
- Clock Synchronization: Ensure that your server time is within 300 seconds of UTC; otherwise, requests will be rejected.
- Rate Limiting: Each
app_key has an independent rate limit (default 60 requests/minute). Exceeding this limit will return a 42901 error.
- Data Range: The span between
start_date and end_date should not exceed 90 days to avoid excessively large responses.
- HTTPS Required: The production environment supports HTTPS only; HTTP requests will be rejected.
- Credential Security: Keep your
app_secret safe. Do not disclose it to any third party.