跳到主要内容

Binance Web3 API Specification V0.0.6 (2024-01-09)

Web3 API description

  • Binance's Partners need to follow the API specification in this doc to provide Binance with a set of endpoints in order to integrate with Binance.

General API Information

  • All endpoints return a common JSON object with "code", "message" and "data", no matter it's a success or not.
  • Here "data" is either a customized JSON object or a simple type (int, string...). it may vary from endpoint to endpoint.
  {
"code": "XXXXXX",
"message": "success",
"data": {
"abc": "efg",
...
}
}
  • General codes in responses:

    code | Description ---- | ---- 000000 |success 000001 | too many requests 000002 | system busy 000003 | invalid signature 000004 | invalid recvWindow 000005 | invalid timestamp. timestamp for this request is outside of the recvWindow. Or timestamp for this request was 1000ms ahead of the server's time. 000006 | invalid argument

  • All time and timestamp related fields are in millisecond.

  • HTTP 5XX return codes are used for internal errors. The issue is on partner's side. Binance will NOT treat this as a failure operation; the execution status is UNKNOWN.

  • For GET endpoints, parameters must be sent as a query string.

  • For POST, PUT , and DELETE endpoints, the parameters must be sent in the request body with content type application/x-www-form-urlencoded.

  • Parameters may be sent in any order.

  • Requests out of receiving window must NOT be executed. Partner's server should verify:

    1. recvWindow <= 10000 (ms)
    2. partner's server time - 3000 < timestamp < partner's server time + recvWindow.
  • Every partner need to define a url prefix so that Binance can invoke the partner's endpoint using prefix + endpoint_url.

  • Each request and response should be logged in both Binance and partner's sides for further investigation.

Signature

  • In order to ensure the data security, all SIGNED endpoints should be signed by Binance and be verified by partners. We would use RSA encrption/signature to do the signature.
  • Binance will generate a private public key pair for each partner and send each partner their public key via email.
  • When Binance invokes a partner's SIGNED endpoint, Binance will send "timestamp", "recvWindow" in the url (GET) or request body (POST, PUT and DELETE) and "signature" in header (GET, POST, PUT and DELETE).
  • Partners should verify the signature of all paratemeters in the url , including timestamp and recvWindow, is correct by the public key. Example:
// privateKey & publicKey here are just examples. Will use different key pair in the Testing & Production environment.
String privateKey = "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAJtaheRtvB9xmctbjdWyHVgy7Vblrit4ge9" +
"wxioWNYmXiG4Dskpl0L87emYSrF1IZk+R6sOg3vTJ8VQ8nAocX5lzfQJZIdOA36K9HVbgTDJB3jxvtZ91To1U27anSn0HZ29zK2x0hn4" +
"UqMPCNemXDbX//3NfvEuvasX5h4/WanbRAgMBAAECgYBhrrGxyC4Zt1x0ucSdMbmx05PYp+K0ArnwzIBNxlkzgsyOIFTi4tI27DcyJ1up6/"+
"Qo5B8xkt2eHbxYsyOKV/zjjNo7afmQ/woBPgCxuErNJsdo2g0nH0k8A4Pw0FcLQL4sQocyfYsFMNhP56SY5fkgRAdAYPJ5v5RG47dLVoMGY" +
"QJBANF69BOAa/V+wubh5d5+l04zDkt/xMq7AoeHbeABpEOAEVwEfYqrH2H/BreUod8LixC6CR1KZZ9s+nnSGd9kz+sCQQC92nGk32kU09Oc" +
"XtQzRn1Fi2AHvsSShQ8rwf40Buxl0IZK6sQkkSb2Eg1bA+E5KfAbzfX2YziAH/KcsdaxZ2EzAkEAwlK3tpuMCplDviBSOBrgyzcLjLgC2zm" +
"t+AGGyKVdNwzHjb/QoeFqZGLKXWRw4NL5d1PMfrJ0IPdcR8PCInyHbwJAT2CqzT1fiQa73hBD9qBNNit83iAjvgMGAcydRRFz+2nBDEe19Hf" +
"/6zhG/zvTCfx/2JA3e2mmsOMqo9szIX9QwwJAVfTewPB76mTwrTDbvBXAAXRU1WKpmrDiKHCViRO8Z6iP/KwwQxqpGiZTXr6zN8onidVjRzW" +
"JHGcWq3cCGO0v9w==";

String publicKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCbWoXkbbwfcZnLW43Vsh1YMu1W5a4reIHvcMYqFjWJl4huA7JK" +
"ZdC/O3pmEqxdSGZPkerDoN70yfFUPJwKHF+Zc30CWSHTgN+ivR1W4EwyQd48b7WfdU6NVNu2p0p9B2dvcytsdIZ+FKjDwjXplw21//9zX7x" +
"Lr2rF+YeP1mp20QIDAQAB";

/** Binance Side (Sign)*/

// sign
String parameters = "a=b&c=[\"1\",\"2\",\"3\"]&recvWindow=5000&timestamp=1499827319559";
String signature = RSAUtil.sign(parameters, RSAUtil.getPrivateKey(privateKey));
log.debug("signature: {}", signature)
// LOG [debug] signature: VI6k2ILEFuB2ltAIYHrEeFjlxq4ZMHdoPTMLxFyHrg1ylnMpFJo2J/YStRKRdEh0Pv+beVWje0Nz+rZ6z3RzPFFwFkgEGK4XT3PGnpYnZXWvvCBHhQg0OmypNftzktUxcekbazWvF4BSTxoFlIDYBdAt5L69lUnwY7GZ9pOXGoU=

// put signature in the header

/** Partener Side (Verification)*/
// get parameter string from requestBody (POST, PUT, and DELETE) or parameters (GET):

String parameters = "a=b&c=[\"1\",\"2\",\"3\"]&recvWindow=5000&timestamp=1499827319559";

// get from header "signature"
String signature = "VI6k2ILEFuB2ltAIYHrEeFjlxq4ZMHdoPTMLxFyHrg1ylnMpFJo2J/YStRKRdEh0Pv+beVWje" +
"0Nz+rZ6z3RzPFFwFkgEGK4XT3PGnpYnZXWvvCBHhQg0OmypNftzktUxcekbazWvF4BSTxoFlIDYBdAt5L69lUnwY7GZ9pOXGoU=";

// verify
boolean isSignatureValid = RSAUtil.verify(parameters, RSAUtil.getPublicKey(publicKey), signature);

RSAUtil

import java.security.KeyFactory;
import java.security.PublicKey;
import java.security.Signature;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.X509EncodedKeySpec;

public class RSAUtil {

public static boolean verify(String parameterStr, PublicKey publicKey, String sign) throws Exception {
byte[] keyBytes = publicKey.getEncoded();
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PublicKey key = keyFactory.generatePublic(keySpec);
Signature signature = Signature.getInstance("SHA256withRSA");
signature.initVerify(key);
signature.update(parameterStr.getBytes());
return signature.verify(Base64.decodeBase64(sign.getBytes()));
}

public static PublicKey getPublicKey(String publicKey) throws Exception {
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
byte[] decodedKey = Base64.decodeBase64(publicKey.getBytes());
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(decodedKey);
return keyFactory.generatePublic(keySpec);
}

public static PrivateKey getPrivateKey(String privateKey) throws Exception {
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
byte[] decodedKey = Base64.decodeBase64(privateKey.getBytes());
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(decodedKey);
return keyFactory.generatePrivate(keySpec);
}

}

API Specification

Server Time (UNSIGNED)

GET /v1/time
to check the partner's server time

Parameters: None

Response Body:

NameTypeMandatoryDescription
codeStringYES"000000"
messageStringYES"success"
dataLongYEStimestamp

Response examples:

{
"code": "000000",
"message": "success",
"data": 1499827319559
}

{
"code": "000002",
"message": "system busy",
"data": null
}

Task Completion (SIGNED)

GET /v1/task/completion

Parameters:

NameTypeMandatoryDescription
walletAddressStringYESa user's unifed id
taskString json arrayYEStask names. "deposit", "withdraw". if it's not empty, just return specific task completion status. otherwise, return all tasks completion statuses.
recvWindowLongYESreceived window
timestampLongYESclient timestamp of the request

Headers:

NameTypeMandatoryDescription
signatureStringYESsignature of the request

Response Body:

NameTypeMandatoryDescription
codeStringYES
messageStringYES
dataJSON ObjectYEStimestamp

data:

NameTypeMandatoryDescription
walletAddressStringYESa user's unifed id
taskString json arrayYEStask names. "deposit", "withdrawal"
recvWindowLongYESreceived window
timestampLongYESclient timestamp of the request

examples:

GET {prefix} + /v1/task/completion?walletAddress=0xabcdefg&task=["deposit", "withdrawal"]&recvWindow=3000&timestamp=1499827319559

Response:
{
"code": "000000",
"message": "success",
"data": {
"withdrawal": true, // complete
"deposit": false, // incomplete
}
}

{
"code": "000003",
"message": "invalid signature",
"data": null
}
{
"code": "000006",
"message": "invalid argument",
"data": null
}