Prerequisites
Introduction
- All endpoints return either a JSON object or array
- The base URL is: https://oracle.binance.com
Request API
All endpoints require the following additional parameters, which are placed in the header
- x-api-key: optional, contact us to generate the apiKey and secretKey for you
- x-api-timestamp:the millisecond timestamp of when the request was created and sent(UTC+0)
- x-api-signature: signature(optional), for specific signature rules, see signature
Data signature
tip
Please note that the signature is optional here. You can still access our API without signature. However, you will be limited to a lower rate. If you foresee your application having a higher rate to the Off-chain API, please contact us for a dedicated apiKey and apiSecret.
- Endpoints use
HMAC SHA256
signatures. TheHMAC SHA256
signature is a keyed HMAC SHA256 operation. Use yoursecretKey
as the key andtotalParams
as the value for the HMAC operation - The
signature
is not case sensitive - The parameters of the query string and request body are sorted in ascending order by key, with & links in the middle, and finally the x-api-timestamp in the header is spliced
Example
- x-api-key:754ead833a9ff0e3884ee5dd689ddba2dd1dc66af1342b754291568e01fb6a5f
- secretKey:846dca24075f067de980a4bfbae1c02599c4c34b748ce17b40ebc94e0818a9ba
request body
{
"sign":true,
"symbols":"BTC/USD,ETH/USD"
}
x-api-timestamp:1669845709998
After sorting and splicing
sign=true&symbols=BTC/USD,ETH/USD&x-api-timestamp=1669845961970
HMAC SHA256 signature:
echo -n "sign=true&symbols=BTC/USD,ETH/USD&x-api-timestamp=1669845961970" | openssl dgst -sha256 -hmac "846dca24075f067de980a4bfbae1c02599c4c34b748ce17b40ebc94e0818a9ba"
(stdin)= 0eb116708c7913cb35338fc93924775048a2cab1ddcd0aea2cd7ff90bf401bc9
Code sample
- go
- java
- python
- javascript
import (
"crypto/hmac"
"crypto/sha256"
"encoding/hex"
"fmt"
"strconv"
"strings"
"time"
)
func main() {
apiSecret := "" // the apiSecret secret
apiKey := "" // the apiKey
timestamp := strconv.FormatInt(time.Now().UnixMilli(), 10) // the timestamp
fmt.Println(timestamp)
query := make(map[string]string) //the query parameters, it can be empty
body := make(map[string]string) // the request body,can be empty
body["sign"] = "false"
body["symbols"] = "ETH/USD"
msgForSig := GenerateMsgForSig(timestamp, query, body)
sig := ComputeSig(msgForSig, apiSecret)
}
func GenerateMsgForSig(timestamp string, query map[string]string, body map[string]string) string {
var sortedKeys []string
if len(query) > 0 || len(body) > 0 {
sortedKeys = make([]string, len(query)+len(body))
if len(query) > 0 {
for k := range query {
sortedKeys = append(sortedKeys, k)
}
}
if len(body) > 0 {
for k := range body {
sortedKeys = append(sortedKeys, k)
}
}
}
var strBuild strings.Builder
if len(sortedKeys) > 0 {
for _, k := range sortedKeys {
if len(query) > 0 {
if v, ok := query[k]; ok {
strBuild.WriteString(fmt.Sprintf("&%s=%s", k, v))
}
}
if len(body) > 0 {
if v, ok := body[k]; ok {
strBuild.WriteString(fmt.Sprintf("&%s=%s", k, v))
}
}
}
}
strBuild.WriteString(fmt.Sprintf("&%s=%s", "x-api-timestamp", timestamp))
return strings.Replace(strBuild.String(), "&", "", 1)
}
func ComputeSig(msgForSig, appSecret string) string {
message := []byte(msgForSig)
key := []byte(appSecret)
h := hmac.New(sha256.New, key)
h.Write(message)
return hex.EncodeToString(h.Sum(nil))
}
import org.apache.commons.collections4.MapUtils;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.Map;
public class SignUtil {
private static final String JOINER = "&";
private static final String EQUAL = "=";
public static String getSignature(String timestamp, Map<String, Object> queryParams, Map<String, Object> body) throws NoSuchAlgorithmException, InvalidKeyException {
Mac sha256HMAC = null;
String apiSecret = "";
try {
sha256HMAC = Mac.getInstance("HmacSHA256");
SecretKeySpec secretKey = new SecretKeySpec(apiSecret.getBytes(StandardCharsets.UTF_8), "HmacSHA256");
sha256HMAC.init(secretKey);
return HexUtil.encodeHexString(sha256HMAC.doFinal(GenerateMsgForSig(timestamp, queryParams, body)));
} catch (Exception e) {
throw e;
}
}
private static byte[] GenerateMsgForSig(String timestamp, Map<String, Object> queryParams, Map<String, Object> body) {
StringBuilder sb = new StringBuilder();
Map<String, Object> treeMap = new HashMap<>();
if (MapUtils.isNotEmpty(queryParams)) {
treeMap.putAll(queryParams);
}
if (MapUtils.isNotEmpty(body)) {
treeMap.putAll(body);
}
for (Map.Entry<String, Object> entry : treeMap.entrySet()) {
sb.append(JOINER).append(entry.getKey()).append(EQUAL).append(entry.getValue().toString());
}
sb.append(JOINER).append("x-api-timestamp").append(EQUAL).append(timestamp);
return sb.toString().replaceFirst(JOINER, "").getBytes(StandardCharsets.UTF_8);
}
}
public final class HexUtil {
private static final char[] HEX = new char[]{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
public static String encodeHexString(byte[] bytes) {
int nBytes = bytes.length;
char[] result = new char[2 * nBytes];
int j = 0;
byte[] var4 = bytes;
int var5 = bytes.length;
for (int var6 = 0; var6 < var5; ++var6) {
byte aByte = var4[var6];
result[j++] = HEX[(240 & aByte) >>> 4];
result[j++] = HEX[15 & aByte];
}
return new String(result);
}
}
import time
import hmac
import hashlib
def generateMsgForSig(timestamp, queryParams, body):
newDict = {}
if queryParams:
newDict = dict(newDict, **queryParams)
if body:
newDict = dict(newDict, **body)
sort = sorted(newDict.items(), key=lambda x: x[0])
sigMsg = ""
if sort:
for item in sort:
sigMsg = sigMsg + "&" + item[0] + "=" + item[1]
sigMsg = sigMsg + "&x-api-timestamp=" + timestamp
return sigMsg.replace("&", "", 1)
apiSecret = ''
timeStamp = str(int(time.time() * 1000))
body = {
"sign": "false",
"symbols": "ETH/USD"
}
sigMsg = generateMsgForSig(timeStamp, {}, body)
signature = hmac.new(bytes(apiSecret), msg=bytes(sigMsg), digestmod=hashlib.sha256).hexdigest()
const HmacSHA256 = require('crypto-js/hmac-sha256')
const EncodeHex = require('crypto-js/enc-hex')
function GenerateMsgForSig(timestamp, queryParams, body) {
var newObj = {}
if (Object.keys(queryParams).length > 0) {
newObj = Object.assign(newObj, queryParams)
}
if (Object.keys(body).length > 0) {
newObj = Object.assign(newObj, body)
}
var map = new Map(Object.entries(newObj))
//sort
var sortedObj = Array.from(map)
sortedObj.sort(function (a, b) {
return a[0].localeCompare(b[0])
})
var sigMsg = ''
for (var [k, v] of sortedObj) {
sigMsg += '&' + k + '=' + v
}
sigMsg += '&x-api-timestamp=' + timestamp
return sigMsg.replace('&', '')
}
const apiSecret = ''
queryParams = {}
body = {
sign: false,
symbols: 'ETH/USD',
}
var timeStamp = new Date().valueOf().toString()
var sigMsg = GenerateMsgForSig(timeStamp, queryParams, body)
var hash = HmacSHA256(sigMsg, apiSecret)
var hashInHex = EncodeHex.stringify(hash)
Error Codes and Messages
Any endpoint can return an ERROR The error payload is as follows:
{
"msg": "symbol not support",
"errorCode": "200001"
}
Specific error codes and messages are defined in the following table
Code | Description |
---|---|
000001 | Too many requests |
000002 | Unauthorized,invalid apiKey |
000003 | Bad request |
100001 | System error |
100002 | System load is too high, please try again later |
200001 | symbol not support |
200002 | Illegal parameter |
200003 | Signature error |