Authentication
API Authentication
Authentication is done using an API key and a secret key. To generate this pair, view API Keys.
As an example, we will use the /users/v1/userbalance
endpoint to show how to authenticate. This can be used for all endpoints that requires authentication.
These are encoded as HTTP headers named:
x-nonce
x-api-key
x-signature
Body is currently NOT a required parameter when generating a signature for all requests. Aquanow's signature is created using SHA-384 encryption.
Code Example
require("isomorphic-fetch");
const crypto = require("crypto");
async function sendRequest() {
const apiKey = "YOUR_API_KEY";
const apiSecret = "YOUR_API_SECRET";
const apiPath = "/users/v1/userbalance";
const nonce = Date.now().toString();
const httpMethod = "GET";
const signatureContent = JSON.stringify({
httpMethod,
path: apiPath,
nonce
});
const sig = crypto
.createHmac("sha384", apiSecret)
.update(signatureContent)
.digest("hex");
try {
const res = await fetch(`https://api.aquanow.io${apiPath}?`, {
method: httpMethod,
headers: {
"x-nonce": nonce,
"x-api-key": apiKey,
"x-signature": sig
}
});
if (res.status !== 200) {
throw new Error(`${(await res.json()).message} status ${res.status}`);
}
const result = await res.json();
console.log("Result: ", result);
} catch (error) {
console.log("error", error);
}
}
sendRequest();
import datetime, json, hmac, hashlib, requests, base64
def get_sig(httpMethod, apiPath, apiSecret, nonce):
results = {}
signatureDict = {
"httpMethod": httpMethod,
"path": apiPath,
"nonce": str(nonce)
}
signatureContent = json.dumps(signatureDict, separators=(',',':'))
print(signatureContent)
return hmac.new(bytes(apiSecret, 'utf-8'), bytes(str(signatureContent), 'utf-8'), hashlib.sha384).hexdigest()
def get_orders(apiKey, apiSecret):
apiPath = "/trades/v1/order"
httpMethod = "GET"
nonce = int(datetime.datetime.now().timestamp() * 1000)
url = "https://api.aquanow.io/trades/v1/order"
payload = {}
headers = {
"x-nonce": str(nonce),
"x-api-key": apiKey,
"x-signature": get_sig(httpMethod, apiPath, apiSecret, nonce),
}
print(headers)
response = requests.request("GET", url, headers=headers, data=payload)
print(response.text.encode('utf8'))
get_orders(apiKey,secretKey)
package com.beaverbitcoin.api.service;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.binary.Hex;
import org.apache.http.HttpHeaders;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import com.amazonaws.HttpMethod;
import com.beaverbitcoin.api.interfaces.IDateService;
import lombok.extern.slf4j.Slf4j;
@Service
@Slf4j
public class AquanowWebService implements IAquanowWebService {
private static final String ENCRYPTION_ALGORITHM = "SHA-384";
private static final String HMAC_ENCRYPTION_ALGORITHM = "HmacSHA384";
private static final String TRADE_API_PATH = "/trades/v1/market";
private static final String BUY_SIDE = "buy";
@Autowired
private IDateService dateService;
@Value("${AQUANOW_SECRET}")
protected String aquanowSecret;
@Value("${AQUANOW_KEY_ID}")
protected String aquanowKeyId;
@Value("${AQUANOW_HOST}")
protected String aquanowHost;
@Override
public boolean createTransaction(Long deliverQuantity) {
HttpClient httpClient = HttpClients.createDefault();
JSONObject body = new JSONObject();
body.put("deliverQuantity", deliverQuantity);
body.put("ticker", "BTC-CAD");
body.put("tradeSide", BUY_SIDE);
HttpPost httpPost = getHttpPost(TRADE_API_PATH, body);
try {
HttpResponse response = httpClient.execute(httpPost);
String responseBody = EntityUtils.toString(response.getEntity());
System.out.print("response body: " + responseBody);
} catch (IOException e) {
log.error("Error calling aquanow", e);
return false;
}
return true;
}
protected String getSignature(String httpMethod, String apiPath, String nonce) {
String toBeHashed = "{\"httpMethod\":\"" + httpMethod + "\",\"path\":\"" + apiPath + "\",\"nonce\":\""
+ nonce + "\"}";
SecretKeySpec secretKeySpec = new SecretKeySpec(aquanowSecret.getBytes(), ENCRYPTION_ALGORITHM);
try {
Mac mac = Mac.getInstance(HMAC_ENCRYPTION_ALGORITHM);
mac.init(secretKeySpec);
return String.valueOf(Hex.encodeHex(mac.doFinal(toBeHashed.getBytes())));
} catch (Exception e) {
log.error("Problem generating aquanow signature", e);
throw new UnsupportedOperationException("Problem generating aquanow signature", e);
}
}
private HttpPost getHttpPost(String path, JSONObject body) {
String nonce = getFormattedDate();
String signature = getSignature(HttpMethod.POST.name(), path, nonce);
log.debug("Aquanow url: {}", aquanowHost + path);
HttpPost httpPost = new HttpPost(aquanowHost + path);
setAquanowHeaders(httpPost, signature, nonce);
try {
httpPost.setEntity(new StringEntity(body.toString()));
log.debug("Json body: {}", body.toString());
} catch (UnsupportedEncodingException e) {
log.error("Couldn't set up post body for HttpEntity", e);
throw new UnsupportedOperationException("Couldn't set up post body for HttpEntity", e);
}
return httpPost;
}
protected String getFormattedDate() {
return "" + dateService.getCurrentTimestamp();
}
private void setAquanowHeaders(HttpRequestBase httpRequest, String signature, String nonce) {
httpRequest.setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE);
httpRequest.setHeader("x-nonce", nonce);
httpRequest.setHeader("x-signature", signature);
httpRequest.setHeader("x-api-key", aquanowKeyId);
httpRequest.setHeader(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE);
}
}
<?php require_once 'vendor/autoload.php';
use GuzzleHttp\Client;
$method = 'GET';
$endpoint = '/users/v1/userbalance';
$nonce = round(microtime(true) * 1000);
$apiKey = 'YOUR_API_KEY';
$apiSecret = 'YOUR_API_SECRET';
$content = [
'httpMethod' => $method,
'path' => $endpoint,
'nonce' => (string) $nonce,
];
$json = json_encode($content, JSON_UNESCAPED_SLASHES);
$signature = hash_hmac('sha384', $json, $apiSecret);
$client = new Client([
'base_uri' => 'https://api.aquanow.io',
'headers' => [
'x-nonce' => $nonce,
'x-api-key' => $apiKey,
'x-signature' => $signature,
],
]);
try {
$response = $client->request('GET', '/users/v1/userbalance', [
'query' => [
'symbol' => "BTC",
],
]);
echo $response->getBody();
} catch (RequestException $error) {
echo $error
->getResponse()
->getBody()
->getContents();
} catch (\Exception $error) {
echo $error->getResponse()->getBody();
}
<?php require_once 'vendor/autoload.php';
use GuzzleHttp\Client;
$method = 'POST';
$endpoint = '/payment/v1/requestPaymentAddress';
$nonce = round(microtime(true) * 1000);
$apiKey = 'YOUR_API_KEY';
$apiSecret = 'YOUR_API_SECRET';
$content = [
'httpMethod' => $method,
'path' => $endpoint,
'nonce' => (string) $nonce,
];
$json = json_encode($content, JSON_UNESCAPED_SLASHES);
$signature = hash_hmac('sha384', $json, $apiSecret);
$client = new Client([
'base_uri' => 'https://api.aquanow.io',
'headers' => [
'x-nonce' => $nonce,
'x-api-key' => $apiKey,
'x-signature' => $signature,
'Accept' => 'application/json',
],
]);
try {
$response = $client->request($method, '/payment/v1/requestPaymentAddress', [
'body' => json_encode(
[
'cryptoType' => "BTC",
'fiat' => "USD",
'fiatReceivable' => '100',
'subaccount' => "yourSubAcount"
]
)
]);
echo $response->getBody();
} catch (RequestException $error) {
echo $error
->getResponse()
->getBody()
->getContents();
} catch (\Exception $error) {
echo $error->getResponse()->getBody();
}
Common Authentication Errors
HTTP 401
HTTP 401 usually happens when invalid auth credentials are in the request auth headers. Other possible reasons include:
nonce
in calculating auth credentials are outdated.There's parameters included when generating the signature (e.g.,
/users/v1/userbalance?BTC
would throw an error while/users/v1/userbalance
would be successful).Full link is included when generating the signature (e.g.,
https://api.aquanow.io/users/v1/userbalance
).
HTTP 403
HTTP 403 usually happens when a request is blocked by IP whitelist or an incorrect URL/HTTP method.
Last updated