Specification
Environments
We understand that the development and testing process is a critical part of building and integrating with our smart energy management platform.
To facilitate this, we offer two distinct environments: sandbox and production. These environments serve specific purposes, each designed to help you build, test, integrate faster and more effectively with the HanChuESS Connect.
Sandbox
idaas-sandbox.hanchuess.com
Ideal playground for developers and partners who want to experiment with theHanChuESS Connect without touching real user data.
Production
idaas.hanchuess.com
The real deal. In this environment, you have access to actual data from customers assets. It is the place to go when you are ready to launch your application
EndPoints
Authenticate
https://{DOMAIN}/portal/{METHOD}
OpenAPI
https://{DOMAIN}/api/{METHOD}
{METHOD} is a sub-class url in each api reference.
Protocol
Https supported only, Use OAuth2.0 authentication mechanism.
Restriction
The open API is designed in
RESTfulstyle.Request data format supports
UTF-8,JSONformat to return.Authenticate allow partner obtain token before invoke, modes supported in the following:
authorization_code
client_credentials
About our limits
Limits are designed to prevent API abuse, while minimizing impact on common customer usage patterns.
You may hit rate limits over shorter time intervals. For instance, a rate of 60 requests per minute (RPM) may be enforced as 1 request per second. Short bursts of requests at a high volume can surpass the rate limit and result in rate limiterrors.
We use the token bucket algorithm to do rate limiting. This means that your capacity is continuously replenished up to your maximum limit, rather than beingreset at fixed intervals.
All limits described here represent maximum allowed usage, not guaranteed minimums. These limits are intended to reduce unintentional overspend and ensurefair distribution of resources among users.
Request Header
Content-Type
Request type.
Authorization
User Access token.
Accept-Language
I18N support, default en-US, optional zh-CN.
X-Signature
Use HMAC256 to signature.
X-Timestamp
Current timestamp in milliseconds.
X-Nonce
Used once, random characters by UUIDv4.
X-Api-Version
Specified api version if needed.
Response Header
X-Request-Id
Troubleshooting when needed.
X-RateLimit-Remaining
Remaining tokens in bucket.
X-RateLimit-Replenish-Rate
Replenish token per request.
X-RateLimit-Burst-Capacity
Token bucket burst capacity.
X-RateLimit-Requested-Tokens
Token consumption in request.
Return Format
msg
string
Prompt or error message.
data
object
Response data in json format.
Signature
Restriction
Partners ought to generate different nonce per request, and server could tolerate max time within 60 seconds, otherwise, illegal request would receive 403 response from HanchuESS Connect.
Rule
Format
{HTTP_METHOD}:{API_METHOD}:{TIMESTAMP}:{NONCE}
{HTTP_METHOD} - POST/GET/DELETE/PATCH/PUT
{API_METHOD} - sub-class url in each api reference
{TIMESTAMP}: current timestamp in millieseconds
{NONCE}: random six characters in UUIDv4
Code Example
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class HmacDigest {
private static final Logger log = LoggerFactory.getLogger(HmacDigest.class);
public static String digestByHmac(String signStr, String secret, String algorithm) {
if (signStr == null || secret == null || algorithm == null) {
log.warn("Input parameters cannot be null");
return null;
}
try {
// 1. Key transformer
SecretKeySpec secretKey = new SecretKeySpec(
secret.getBytes(StandardCharsets.UTF_8),
algorithm
);
// 2. Initialization
Mac mac = Mac.getInstance(algorithm);
mac.init(secretKey);
// 3. Digest caculation
byte[] rawHmac = mac.doFinal(signStr.getBytes(StandardCharsets.UTF_8));
// 4. Base64 encode
return Base64.getEncoder().encodeToString(rawHmac);
} catch (IllegalArgumentException e) {
log.error("Invalid argument: {}", e.getMessage());
} catch (java.security.NoSuchAlgorithmException e) {
log.error("Unsupported algorithm: {}", algorithm);
} catch (java.security.InvalidKeyException e) {
log.error("Invalid key for algorithm: {}", algorithm);
} catch (Exception e) {
log.error("Unexpected error: {}", e.getMessage());
}
return null;
}
}const crypto = require('crypto');
function digestByHmac(signStr, secret, algorithm) {
try {
// Normalize algorithm name (remove 'HMAC' prefix if present)
const normalizedAlg = algorithm.replace(/^hmac/i, '').toLowerCase();
const hmac = crypto.createHmac(normalizedAlg, secret);
hmac.update(signStr);
return hmac.digest('base64');
} catch (ex) {
console.error(`ex: ${ex.message}`);
return null;
}
}package main
import (
"crypto/hmac"
"crypto/sha1"
"crypto/sha256"
"crypto/sha512"
"encoding/base64"
"errors"
"log"
"strings"
)
func digestByHmac(signStr, secret, algorithm string) string {
var hashFunc func() hash.Hash
switch strings.ToLower(algorithm) {
case "hmacsha1", "sha1":
hashFunc = sha1.New
case "hmacsha256", "sha256":
hashFunc = sha256.New
case "hmacsha512", "sha512":
hashFunc = sha512.New
default:
log.Printf("Unsupported algorithm: %s", algorithm)
return ""
}
mac := hmac.New(hashFunc, []byte(secret))
mac.Write([]byte(signStr))
digest := mac.Sum(nil)
return base64.StdEncoding.EncodeToString(digest)
}import hmac
import hashlib
import base64
def digest_by_hmac(sign_str: str, secret: str, algorithm: str) -> str:
try:
hash_algorithm = algorithm.lower().replace('-', '')
digest = hmac.new(
secret.encode('utf-8'),
sign_str.encode('utf-8'),
getattr(hashlib, hash_algorithm)
).digest()
return base64.b64encode(digest).decode('utf-8')
except Exception as ex:
print(f"ex: {str(ex)}")
return NoneLast updated