Reputation: 1232
I am pulling my hair out trying to query the CoinSpot API.
The endpoint for the Read Only API is: https://www.coinspot.com.au/api/ro
The documentation states:
All requests to the API will need to include the following security data.
Headers: key - Your API key generated from the settings page sign - The POST data is to be signed using your secret key according to HMAC-SHA512 method. Post Params: nonce - Any integer value which must always be greater than the previous requests nonce value.
I try to query the 'List My Balances' endpoint via: https://www.coinspot.com.au/api/ro/my/balances
However, the code I have formulated below always returns an error: "invalid/missing nonce".
I have tried so many different variations and approaches but it is always the same error.
require(httr)
key <- "68z...39k"
secret <- "71A...48i"
result <- POST("https://www.coinspot.com.au/api/ro/my/balances",
body = list('nonce'=as.integer(as.POSIXct(Sys.time()))), add_headers("key"=key,"sign"=openssl::sha512("https://www.coinspot.com.au/api/ro/my/balances",key = secret)))
content(result)
Any help much appreciated.
Upvotes: 5
Views: 1210
Reputation: 81
Here is my code in python working in python version 3.6.2
import os
coinSpotApiKey = os.environ['coinSpotReadAPIKey']
coinSpotSecretKey = os.environ['coinspotSecretKey']
import requests
import hmac
import hashlib
import time
# Your API key and secret
api_key = coinSpotApiKey
secret_key = coinSpotSecretKey
# API endpoint
url = 'https://www.coinspot.com.au/api/v2/ro/my/balances'
def myBalance():
# Create a nonce (must be unique and incrementing)
nonce = int(time.time() * 1000)
# Prepare the data payload
data = f'{{"nonce":"{nonce}"}}'
# Convert the data to JSON and encode as bytes
post_data = data.encode('utf-8')
# Create the HMAC signature
signature = hmac.new(
secret_key.encode('utf-8'),
post_data,
hashlib.sha512
).hexdigest()
# Set up headers
headers = {
'key': api_key,
'sign': signature,
'Content-Type': 'application/json',
}
# Make the POST request
response = requests.post(url, headers=headers, data=f'{{"nonce":"{nonce}"}}')
return(response)
Upvotes: 0
Reputation: 64
Heres my code in c# using Restsharp and Newtonsoft
//put the nonce at the beginning
JObject joBody = JObject.Parse(@"{'nonce': '" + DateTimeOffset.UtcNow.ToUnixTimeSeconds().ToString() + "'}");
joBody.Merge(originalBody);
var client = new RestClient(_coinspotSettings.BaseURL);
RestRequest request = new RestRequest(endpoint, Method.POST);
request.AddJsonBody(JsonConvert.SerializeObject(joBody));
request.AddHeader("key", coinspotAccount.APIKey);
request.AddHeader("sign", SignData(coinspotAccount, Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(joBody))).ToLower());
request.AddHeader("Content-Type", "application/json");
private string SignData(CoinspotAccount coinspotAccount, byte[] JSONData)
{
var HMAC = new HMACSHA512(Encoding.UTF8.GetBytes(coinspotAccount.APISecret));
byte[] EncodedBytes = HMAC.ComputeHash(JSONData);
StringBuilder stringBuilder = new StringBuilder();
for (int i = 0; i <= EncodedBytes.Length - 1; i++)
stringBuilder.Append(EncodedBytes[i].ToString("X2"));
return stringBuilder.ToString();
}
Upvotes: 0
Reputation: 21
Ive struggled with this too- the coinspot API guide isn't very clear.
I figured out you are meant to encode the postdata in correct json format using sha512 and add that to the sign header. See example below querying account balances on v2 of the api.
require(httr)
api_key = "68z...39k"
api_secret = "71A...48i"
base_url = "https://www.coinspot.com.au/api/v2/ro"
request = "/my/balances"
nonce = as.character(as.integer(Sys.time()))
postdata = paste0('{"nonce":"',nonce,'"}') # important to get the quotes correct
api_sign = digest::hmac(api_secret, postdata, algo="sha512",raw=F)
result = POST(paste0(base_url, request),
body = list("nonce"=nonce),
add_headers(c("key"=api_key,
"sign"=api_sign)),
encode="json"
)
cat(rawToChar(result$content))
You would change what is in postdata
based on what you are doing with the API- this is a simple example to build on. If you want to see what postdata
should look like prior to encryption in sign, use cat(rawToChar(result$request$options$postfields))
after making a request.
Upvotes: 2
Reputation: 141
For me, I was missing the JSON string encoded postdata in the body, including the nonce. As soon as I added that, it started working.
Upvotes: 1