# Authentication

### API Authentication

Authentication is done using an API key and a secret key. To generate this pair, view [API Keys](/aquanow/integration-guide/api-keys.md).

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

{% hint style="info" %}
Body is currently NOT a required parameter when generating a signature for all requests.\
Aquanow's signature is created using SHA-384 encryption.
{% endhint %}

### Code Example

{% tabs %}
{% tab title="Javascript" %}

```javascript
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();
```

{% endtab %}

{% tab title="Python" %}

```python
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)
```

{% endtab %}

{% tab title="Java" %}

```java
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);
    }
}
```

{% endtab %}

{% tab title="PHP (GET)" %}

```php
<?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();
}
```

{% endtab %}

{% tab title="PHP (POST)" %}

```php
<?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();
}
```

{% endtab %}
{% endtabs %}

### 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`).<br>

#### HTTP 403

HTTP 403 usually happens when a request is blocked by IP whitelist or an incorrect URL/HTTP method.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.aquanow.io/aquanow/integration-guide/authentication.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
