Aquanow
Legacy
Legacy
  • About Aquanow
    • Introduction
  • VERSION DIFFERENCES
    • Latest vs Legacy
  • User Guide
    • Trading
      • Order Book
      • Submitting Orders
      • Order Types / Strategies
      • Trade Management
    • Automated Conversions
      • Autopilot
    • Deposits & Withdrawals
      • Deposits
      • Withdrawals
      • Balances
      • Transaction History
      • Approval Workflows
    • Account Management
      • CSV Exports
      • Address Management
      • IP Whitelisting
      • User List
  • Integration Guide
    • API Keys
      • Rate and API Key Limits
    • Authentication
    • Staging environment
    • Postman
    • Supported Assets and Tickers
    • Testnet and Faucet
  • API Endpoints | V1.0
    • Accounts API
      • User Balances
      • API Keys
    • Transaction API
      • Get Transactions
      • Create Transactions
      • Approvals API
      • Get Withdrawal Fee Estimate
    • Executions API
      • GET or Query Orders
      • Trading Strategies
    • Market Data API
      • Authorized Market Data
  • API Endpoints | V2.0
    • Transaction API
      • Get Transactions
    • Executions API
      • GET or Query Orders
      • Trading Strategies
  • Webhooks
    • Subscribing to Webhooks
    • Transaction Webhook
  • Websockets
    • Introduction
    • Authenticated Websockets
      • Market Data Websocket
      • Reporting Websocket
  • Data Objects & Statuses
    • Websocket Objects
    • Transaction Objects
      • Approval Objects
      • Fee Estimate Objects
    • Accounts Objects
    • Executions Objects
      • Duration Order Objects
    • Market Data Objects
    • Statuses
  • FAQs and Misc. Information
    • FAQs
    • Misc. Information
Powered by GitBook
On this page
  • API Authentication
  • Code Example
  • Common Authentication Errors
  1. Integration Guide

Authentication

PreviousRate and API Key LimitsNextStaging environment

Last updated 8 months ago

API Authentication

Authentication is done using an API key and a secret key. To generate this pair, view .

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.

API Keys