How to Construct an HTTP Request
Once the signature is calculated the user can make a request to the endpoint of interest by sending:
- the HTTP method (POST, GET, etc)
- the full end point (this is the base URL and the path)
- the message header
- the message body
How information is sent varies slightly between REST V3 and V4 in terms of whether data is sent in the header or the body.
REST V3 | REST V4 | |
---|---|---|
HEADER | API Key API Signature | API Key API Signature Tonce |
BODY | Tonce Unix time | - |
Example Request Method
Here is an example of how to send the request.
requests.request(method, base_url + "/" + path, headers = headers, data = body_str)
Full REST Examples
These full examples bring all the methods together to demonstrate how to generate the API signature and send it along with the other important data.
The responses associated to these (and all end point requests) are documented in the relevant sections later in the document.
import time
import json
import base64
import hashlib
import hmac
import requests
import pprint
base_url = "https://trade-hk.oslsandbox.com"
key = "<key>"
secret = "<secret>"
def gen_sig_helper(secret, data):
secret_bytes = base64.b64decode(secret.encode("utf8"))
return base64.b64encode(hmac.new(secret_bytes, data.encode("utf8"), digestmod = hashlib.sha512).digest()).decode("utf8")
def v3_gen_sig(secret, path, body_str = None):
data = path
if body_str != None:
data = data + chr(0) + body_str
return gen_sig_helper(secret, data)
def v3_mk_request(method, path, body = {}, realrun = True):
print("=> " + method + ' ' + path)
tonce = int(time.time() * 1000 * 1000)
body["tonce"] = tonce
body_str = json.dumps(body)
headers = {
"Rest-Key": key,
"Rest-Sign": v3_gen_sig(secret, path, body_str),
"Content-Type": "application/json"
}
print("=> " + v3_gen_sig(secret, path, body_str))
print("=> " + str(tonce))
print("=> " + body_str)
if realrun:
response = requests.request(method, base_url + "/" + path, headers = headers, data = body_str)
response_json = response.json()
pprint.pprint(response_json)
response.raise_for_status()
return response_json
else:
print("=> Not sending messages to API server...")
return 0
def request_acc():
return v3_mk_request("POST", "api/3/account")
request_acc()
import time
import json
import base64
import hashlib
import hmac
import requests
import pprint
base_url = "https://trade-hk.oslsandbox.com"
key = "<key>"
secret = "<secret>"
def gen_sig_helper(secret, data):
secret_bytes = base64.b64decode(secret.encode("utf8"))
return base64.b64encode(hmac.new(secret_bytes, data.encode("utf8"), digestmod = hashlib.sha512).digest()).decode("utf8")
def v3_gen_sig(secret, path, body_str = None):
data = path
if body_str != None:
data = data + chr(0) + body_str
return gen_sig_helper(secret, data)
def v3_mk_request(method, path, body = {}, realrun = True):
print("=> " + method + ' ' + path)
tonce = int(time.time() * 1000 * 1000)
body["tonce"] = tonce
body_str = json.dumps(body)
headers = {
"Rest-Key": key,
"Rest-Sign": v3_gen_sig(secret, path, body_str),
"Content-Type": "application/json"
}
print("=> " + v3_gen_sig(secret, path, body_str))
print("=> " + str(tonce))
print("=> " + body_str)
if realrun:
response = requests.request(method, base_url + "/" + path, headers = headers, data = body_str)
response_json = response.json()
pprint.pprint(response_json)
response.raise_for_status()
return response_json
else:
print("=> Not sending messages to API server...")
return 0
def request_token():
return v3_mk_request("POST", "api/3/bcg/rest/auth/token")
request_token()
import time
import json
import base64
import hashlib
import hmac
import requests
import pprint
base_url = 'https://trade-hk.oslsandbox.com'
key = '<key>'
secret = '<secret>'
def gen_sig_helper(secret, data):
secret_bytes = base64.b64decode(secret.encode('utf8'))
return base64.b64encode(hmac.new(secret_bytes, data.encode('utf8'), digestmod = hashlib.sha512).digest()).decode('utf8')
def v4_gen_sig(secret, method, path, expires, body_str = None):
data = method + path + str(expires)
if body_str != None:
data = data + body_str
return gen_sig_helper(secret, data)
def v4_mk_request(method, path, body = None):
print('=> ' + method + ' ' + path)
tonce = int(time.time()) + 10
body_str = None
if body:
body_str = json.dumps(body)
headers = {
'api-key': key,
'api-signature': v4_gen_sig(secret, method, path, tonce, body_str),
'api-expires': str(tonce),
}
if body:
headers['Content-Type'] = 'application/json'
response = requests.request(method, base_url + path, headers = headers, data = body_str)
response_json = response.json()
pprint.pprint(response_json)
response.raise_for_status()
return response_json
def v3_gen_sig(secret, path, body_str = None):
data = path
if body_str != None:
data = data + chr(0) + body_str
return gen_sig_helper(secret, data)
def v3_mk_request(method, path, body = {}):
print('=> ' + method + ' ' + path)
tonce = int(time.time() * 1000 * 1000)
body['tonce'] = tonce
body_str = json.dumps(body)
headers = {
'Rest-Key': key,
'Rest-Sign': v3_gen_sig(secret, path, body_str),
'Content-Type': 'application/json'
}
response = requests.request(method, base_url + '/' + path, headers = headers, data = body_str)
response_json = response.json()
pprint.pprint(response_json)
response.raise_for_status()
return response_json
order_id_v4 = v4_mk_request('POST', '/api/v4/order', {
'ordType': 'Limit',
'symbol': 'BTCUSD',
'orderQty': '0.01',
'price': '39000',
'side': 'Buy'
})['orderID']
v4_mk_request('GET', '/api/v4/order?orderID=' + order_id_v4)
v4_mk_request('DELETE', '/api/v4/order', {'orderID': [order_id_v4]})
order_id_v3 = v3_mk_request('POST', 'api/3/order/new', {
'order': {
'orderType': 'LIMIT',
'tradedCurrency': 'BTC',
'settlementCurrency': 'USD',
'buyTradedCurrency': True,
'tradedCurrencyAmount': '0.01',
'limitPriceInSettlementCurrency': '39000'
}
})['orderId']
v3_mk_request('POST', 'api/3/order/info', {'orderId': order_id_v3})
v3_mk_request('POST', 'api/3/order/cancel', {'orderIds': [order_id_v3]})
const https = require('https');
const crypto = require('crypto');
const host = 'trade-hk.oslsandbox.com';
const key = '<key>';
const secret = '<secret>';
function response_as_json(resolve, reject) {
return function(res) {
let str = '';
res.on('data', function (chunk) { str += chunk; });
res.on('end', function (arg) {
console.log(JSON.parse(str));
((res.statusCode >= 200 && res.statusCode < 300) ? resolve : reject)(str ? JSON.parse(str) : '');
});
}
}
function gen_sig_helper(secret, data) {
const secret_bytes = Buffer.from(secret, 'base64');
return crypto.createHmac('sha512', secret_bytes).update(data).digest('base64');
}
function v4_gen_sig(secret, method, path, expires, body_str) {
let data = method + path + expires;
if (body_str) {
data = data + body_str;
}
return gen_sig_helper(secret, data);
}
function v4_mk_request(method, path, body) {
console.log(`=> ${method} ${path}`);
return new Promise((resolve, reject) => {
const tonce = Math.floor(Date.now() / 1000) + 10;
const body_str = JSON.stringify(body);
const headers = {
'api-key': key,
'api-signature': v4_gen_sig(secret, method, path, tonce, body_str),
'api-expires': tonce,
'Content-Type': 'application/json'
}
if (body) {
headers['Content-Length'] = Buffer.byteLength(body_str);
}
const opt = { host, method, path, headers };
const req = https.request(opt, response_as_json(resolve, reject));
if (body) {
req.write(body_str);
}
req.end();
});
}
function v3_gen_sig(secret, path, body_str) {
let data = path;
if (body_str) {
data = data + '\0' + body_str;
}
return gen_sig_helper(secret, data);
}
function v3_mk_request(method, path, body) {
console.log(`=> ${method} ${path}`);
return new Promise((resolve, reject) => {
const tonce = Math.floor(Date.now() * 1000);
body['tonce'] = tonce;
const body_str = JSON.stringify(body);
const headers = {
'Rest-Key': key,
'Rest-Sign': v3_gen_sig(secret, path, body_str),
'Content-Type': 'application/json'
}
const opt = { host, method, path: '/' + path, headers };
const req = https.request(opt, response_as_json(resolve, reject));
req.write(body_str);
req.end();
});
}
async function run() {
const order_id_v4 = (await v4_mk_request('POST', '/api/v4/order', {
'ordType': 'Limit',
'symbol': 'BTCUSD',
'orderQty': '0.01',
'price': '39000',
'side': 'Buy'
}))['orderID'];
await v4_mk_request('GET', '/api/v4/order?orderID=' + order_id_v4);
await v4_mk_request('DELETE', '/api/v4/order', {'orderID': [order_id_v4]});
const order_id_v3 = (await v3_mk_request('POST', 'api/3/order/new', {
'order': {
'orderType': 'LIMIT',
'tradedCurrency': 'BTC',
'settlementCurrency': 'USD',
'buyTradedCurrency': true,
'tradedCurrencyAmount': '0.01',
'limitPriceInSettlementCurrency': '39000'
}
}))['orderId'];
await v3_mk_request('POST', 'api/3/order/info', {'orderId': order_id_v3});
await v3_mk_request('POST', 'api/3/order/cancel', {'orderIds': [order_id_v3]});
}
run();