Authentication
To interact with the Bring Trade API, every request must be authenticated using your API Key and Secret Key. This ensures that your API calls are secure and authorized.
Bring Trade uses HMAC-SHA256 to sign requests, ensuring the integrity and authenticity of the transmitted data. The following example demonstrates how to authenticate API requests using Java, including placing an order, querying an order, and canceling an order.
Each request must include:
- API Key: This is passed in the headers as X-MBX-APIKEY.
- Signature: Generated using the HMAC-SHA256 algorithm and your API secret, it is sent in the signature header.
- Nonce: A unique timestamp, sent in the nonce header, to ensure the request is valid at the time it’s made.
The sample Java code demonstrates the following:
- Placing an Order: How to create a POST request for placing a trade on Bring Trade.
- Querying an Order: Using a GET request to check the status of an existing order.
- Canceling an Order: Submitting a DELETE request to cancel an active order.
You’ll find the HMAC-SHA256 encryption method is used for signing the payload, ensuring that your requests are secure and that they can’t be tampered with during transmission. Make sure to replace placeholders like "your API key", "your secret key", and "your orderId" with your actual credentials and values when implementing.
For detailed examples of how to authenticate and execute each API call, refer to the Java code provided above.
📖 Third Party Libraries
// JDK11 or later
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.26</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>3.1.3</version>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.15</version>
</dependency>
<dependency>
<groupId>org.java-websocket</groupId>
<artifactId>Java-WebSocket</artifactId>
<version>1.5.7</version>
</dependency>
</dependencies>
🎬 Code Demo
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.experimental.UtilityClass;
import lombok.extern.slf4j.Slf4j;
import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.time.Duration;
import java.time.Instant;
import java.util.*;
@Slf4j
@UtilityClass
public class BringTradeDemo {
private static final String HOST = "https://api.bring.trade";
private static final HttpClient client = HttpClient.newHttpClient();
private static final String API_KEY = "your api key";
private static final String SECRET_KEY = "your secret key";
private static final ObjectMapper objectMapper = new ObjectMapper();
public static void main(String[] args) {
// Place order, POST example
placeOrder();
// Query order, GET example
queryOrder();
// Cancel order, DELETE example
cancelOrder();
}
private static void placeOrder() {
try {
String url = HOST + "/api/v1/trade/order";
SortedMap<String, Object> paramMap = new TreeMap<>();
paramMap.put("symbol", "BT_PERP_BTC_USD");
paramMap.put("side", "BUY");
paramMap.put("orderType", "LIMIT");
paramMap.put("orderQty", "0.1");
paramMap.put("limitPrice", "110");
String nonce = gmtNow();
String sign = getSign(paramMap, SECRET_KEY, nonce);
String jsonBody = objectMapper.writeValueAsString(paramMap);
HttpRequest request = HttpRequest.newBuilder()
.timeout(Duration.ofSeconds(5))
.header("Content-Type", "application/json")
.header("nonce", nonce)
.header("signature", sign)
.header("X-MBX-APIKEY", API_KEY)
.POST(HttpRequest.BodyPublishers.ofString(jsonBody))
.uri(URI.create(url))
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
log.info("response body{}", response.body());
// do something
} catch (Exception exception) {
log.error("placeOrder error:{}", exception.getMessage());
}
}
private static void queryOrder() {
try {
// replace with your orderId
String orderId = "your orderId";
SortedMap<String, Object> paramMap = new TreeMap<>();
paramMap.put("orderId", orderId);
String nonce = gmtNow();
String sign = getSign(paramMap, SECRET_KEY, nonce);
String payload = getPayload(paramMap);
String url = HOST + "/api/v1/trade/order";
if (!payload.isEmpty()) {
url += "?" + payload;
}
HttpRequest request = HttpRequest.newBuilder()
.timeout(Duration.ofSeconds(5))
.header("Content-Type", "application/json")
.header("nonce", nonce)
.header("signature", sign)
.header("X-MBX-APIKEY", API_KEY)
.GET()
.uri(URI.create(url))
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
log.info("response body {}", response.body());
// do something
} catch (Exception exception) {
log.error("queryOrder error:{}", exception.getMessage());
}
}
private static void cancelOrder() {
try {
String url = HOST + "/api/v1/trade/order";
// replace with your orderId
String orderId = "your orderId";
SortedMap<String, Object> paramMap = new TreeMap<>();
paramMap.put("orderId", orderId);
String nonce = gmtNow();
String sign = getSign(paramMap, SECRET_KEY, nonce);
String jsonBody = objectMapper.writeValueAsString(paramMap);
HttpRequest request = HttpRequest.newBuilder()
.timeout(Duration.ofSeconds(5))
.header("Content-Type", "application/json")
.header("nonce", nonce)
.header("signature", sign)
.header("X-MBX-APIKEY", API_KEY)
.method("DELETE", HttpRequest.BodyPublishers.ofString(jsonBody))
.uri(URI.create(url))
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
log.info("response body {}", response.body());
// do something
} catch (Exception exception) {
log.error("cancelOrder error:{}", exception.getMessage());
}
}
private static String gmtNow() {
return String.valueOf(Instant.now().getEpochSecond());
}
private static String getSign(Map<String, Object> param, String secretKey, String nonce) {
String payload = getPayload(param);
payload += "&" + nonce;
try {
return hmacSHA1EncryptString(payload, secretKey);
} catch (Exception e) {
throw new RuntimeException("Error generating sign", e);
}
}
private static String getPayload(Map<String, Object> paramMap) {
if (Objects.isNull(paramMap) || paramMap.size() <= 0) {
return "";
}
StringBuilder buffer = new StringBuilder();
for (Map.Entry<String, Object> entry : paramMap.entrySet()) {
Object value = entry.getValue();
if (value != null) {
buffer.append(entry.getKey()).append("=").append(value.toString()).append("&");
}
}
return buffer.substring(0, buffer.length() - 1);
}
private static String hmacSHA1EncryptString(String encryptText, String
encryptKey) throws Exception {
return toHexString(hmacSHA1Encrypt(encryptText, encryptKey));
}
private static byte[] hmacSHA1Encrypt(String encryptText, String encryptKey)
throws Exception {
String MAC_NAME = "HmacSHA256";
String ENCODING = "UTF-8";
byte[] data = encryptKey.getBytes(ENCODING);
SecretKey secretKey = new SecretKeySpec(data, MAC_NAME);
Mac mac = Mac.getInstance(MAC_NAME);
mac.init(secretKey);
byte[] text = encryptText.getBytes(ENCODING);
return mac.doFinal(text);
}
private static String toHexString(byte[] bytes) {
Formatter formatter = new Formatter();
for (byte b : bytes) {
formatter.format("%02x", b);
}
return formatter.toString();
}
}
// Postman Script Demo
const API_KEY = 'YOUR API KEY';
const SECRET_KEY = 'YOUR SECRET KEY';
// Helper functions
function gmtNow() {
return Math.floor(new Date().getTime() / 1000).toString();
}
function getPayload(params) {
return Object.keys(params)
.sort()
.map(key => `${key}=${params[key]}`)
.join('&');
}
function hmacSHA256(text, secret) {
const crypto = require('crypto-js');
return crypto.HmacSHA256(text, secret).toString(crypto.enc.Hex);
}
function getSign(params, secretKey, nonce) {
let payload = getPayload(params) + `&${nonce}`;
return hmacSHA256(payload, secretKey);
}
// Request parameters (Replace these with dynamic values if needed)
const params = {
};
// Generate nonce and signature
let nonce = gmtNow();
let signature = getSign(params, SECRET_KEY, nonce);
// Set headers and body dynamically in the Postman request
pm.request.headers.add({ key: "X-MBX-APIKEY", value: API_KEY })
pm.request.headers.add({ key: "nonce", value: nonce })
pm.request.headers.add({ key: "signature", value: signature })
// GET
// pm.request.addQueryParams(getPayload(params))
// POST
// pm.request.body.raw = JSON.stringify(params)
// Log for debugging
console.log('Signature:', signature);
console.log('Nonce:', nonce);
console.log("Params", params)