# Authentication and API Keys

### Get your API keys

Follow simple steps to generate API keys for using private endpoints:

* [Sign In](https://earnbit.com/login) to the EarnBIT exchange and navigate to the [API Management](https://earnbit.com/user/api) section in your profile. (Note: You also need to enable two-step authentication if you haven't already)
* To create API keys, click **Add API Key**. A package of keys will be generated, including an API Public Key, an API Secret Key, and a WebSocket Token. You can create up to 5 packages of API keys.
* Before using your API keys, they must be activated. To activate them, use the "Activate API" switch in the created package.

{% hint style="info" %}

* Authentication with API keys is required for using [private HTTP API endpoints](/earnbit/developers/exchange-api-documentation/private-endpoints-or-http.md)&#x20;
* WebSocket Token is required for usage of  [private WebSocket methods](/earnbit/developers/exchange-api-documentation/private-methods-or-websoket.md).
* You can use authentication for retrieving additional data from [public HTTP API endpoints](/earnbit/developers/exchange-api-documentation/public-endpoints-or-http.md)
  {% endhint %}

### Requirements

* Base URL: `https://api.earnbit.com`
* Auth requests should be using `POST` method and should include:
  * **Body data** with JSON that contains the following params:
    * "request" - a request endpoint path without the domain name. Example: "/api/v1/account/balance"
      * "nonce" - a 13-character number that must always be greater than the nonce of the previous completed request. For example: "1704070810000". We suggest generating a nonce as the UNIX timestamp in milliseconds. This ensures you always get an incrementing number, but be careful not to send two API calls simultaneously, as their nonces will be identical, causing one of the requests to be rejected.
      * params of request (depending on choosen request)
  * **Headers** - With every request you need to provide next headers:
    * 'Content-type': 'application/json'
      * 'X-TXC-APIKEY': api\_key (it's your public EarnBIT API key)
      * 'X-TXC-PAYLOAD': payload (it's payload is base64-encoded body data)
      * 'X-TXC-SIGNATURE': signature (it's signature is hex(HMAC\_SHA512(payload), key=api\_secret))

### Connection Examples

To assist you in getting started with our API, we've provided sample code in multiple programming languages.

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

```php
use GuzzleHttp\Client;

public function callApi()
{
    $apiKey = 'xxxxxxxxx';
    $apiSecret = 'xxxxxxxxxxxx';
    $request = '/api/v1/account/balances';
    $baseUrl = 'https://api.earnbit.com';

    $data = [
        'request' => $request,
        'nonce' => (string)\Carbon\Carbon::now()->getTimestampMs(),
    ];

    $completeUrl = $baseUrl . $request;
    $dataJsonStr = json_encode($data, JSON_UNESCAPED_SLASHES);
    $payload = base64_encode($dataJsonStr);
    $signature = hash_hmac('sha512', $payload, $apiSecret);

    $client = new Client();
    try {
        $res = $client->post($completeUrl, [
            'headers' => [
                'Content-type' => 'application/json',
                'X-TXC-APIKEY' => $apiKey,
                'X-TXC-PAYLOAD' => $payload,
                'X-TXC-SIGNATURE' => $signature
            ],
            'body' => json_encode($data, JSON_UNESCAPED_SLASHES)
        ]);
    } catch (\Exception $e) {
        return response()->json(['error' => $e->getMessage()]);
    }

    return response()->json(['result' => json_decode($res->getBody()->getContents())]);
}
```

{% endtab %}

{% tab title="Java" %}
**Example 1 - Java native http client**

{% code title="example.java" %}

```java
import com.google.gson.Gson;
import org.apache.commons.codec.digest.HmacAlgorithms;
import org.apache.commons.codec.digest.HmacUtils;
import org.junit.jupiter.api.Test;

import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.util.Base64;

class TestExample {

    Gson GSON = new Gson();
    String apiBasePath = "https://api.earnbit.com";
    String apiKey = "xxxxxxxxx";
    String apiSecret = "xxxxxxxxx";

    @Test
    void getBalance() throws Exception {
        String methodPath = "/api/v1/account/balance";
        String dataJson = GSON.toJson(new BalancesRequest(
                methodPath, "USDT", System.currentTimeMillis()
        ));
        String payload = Base64.getEncoder().encodeToString(dataJson.getBytes());
        String signature = new HmacUtils(HmacAlgorithms.HMAC_SHA_512, apiSecret).hmacHex(payload);

        try (var client = HttpClient.newHttpClient()) {
            var response = client.send(
                    HttpRequest.newBuilder()
                            .uri(URI.create(apiBasePath + methodPath))
                            .headers("Content-Type", "application/json",
                                    "X-TXC-APIKEY", apiKey,
                                    "X-TXC-PAYLOAD", payload,
                                    "X-TXC-SIGNATURE", signature)
                            .POST(HttpRequest.BodyPublishers.ofString(dataJson))
                            .build(),
                    HttpResponse.BodyHandlers.ofString()
            );
            ApiResponse apiResponse = GSON.fromJson(response.body(), ApiResponse.class);
            System.out.println(apiResponse.result());
        }
    }
}

record BalancesRequest(String request, String currency, Long nonce) {
}

record ApiResponse(Boolean success,
                   String message,
                   Integer code,
                   BalancesResponse result) {
}

record BalancesResponse(String available, String freeze) {
}
```

{% endcode %}

{% code title="build.gradle" %}

```java
dependencies {
    implementation('commons-codec:commons-codec:1.17.0')
    implementation('com.squareup.okhttp3:okhttp:4.12.0')
    implementation('com.squareup.retrofit2:converter-gson:2.11.0')
    testImplementation platform('org.junit:junit-bom:5.10.0')
    testImplementation 'org.junit.jupiter:junit-jupiter'
}
```

{% endcode %}

**Example 2 - Retrofit2 okhttp client**

{% code title="ExampleRetrofit.java" %}

```java
import com.google.gson.Gson;
import okhttp3.OkHttpClient;
import org.apache.commons.codec.digest.HmacAlgorithms;
import org.apache.commons.codec.digest.HmacUtils;
import org.junit.jupiter.api.Test;
import retrofit2.Call;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
import retrofit2.http.Body;
import retrofit2.http.Header;
import retrofit2.http.Headers;
import retrofit2.http.POST;

import java.util.Base64;

interface ApiClient {
    @Headers("Content-Type: application/json")
    @POST("/api/v1/account/balance")
    Call<ApiResponse<BalancesResponse>> balance(
            @Body BalancesRequest balancesRequest,
            @Header("X-TXC-APIKEY") String apiKey,
            @Header("X-TXC-PAYLOAD") String payload,
            @Header("X-TXC-SIGNATURE") String signature
    );
}

class TestExampleRetrofit {

    String apiBasePath = "https://api.earnbit.com";
    String apiKey = "xxxxxxxxx";
    String apiSecret = "xxxxxxxxx";

    ApiClient apiClient = new Retrofit.Builder()
            .baseUrl(apiBasePath)
            .addConverterFactory(GsonConverterFactory.create())
            .client(new OkHttpClient.Builder().build())
            .build()
            .create(ApiClient.class);

    @Test
    void getBalance() throws Exception {
        String methodPath = "/api/v1/account/balance";
        BalancesRequest request = new BalancesRequest(
                methodPath, "USDT", System.currentTimeMillis()
        );
        String dataJson = new Gson().toJson(request);
        String payload = Base64.getEncoder().encodeToString(dataJson.getBytes());
        String signature = new HmacUtils(HmacAlgorithms.HMAC_SHA_512, apiSecret).hmacHex(payload);

        ApiResponse<BalancesResponse> apiResponse = apiClient.balance(request, apiKey, payload, signature)
                .execute().body();
        System.out.println(apiResponse.result());
    }
}

record BalancesRequest(String request, String currency, Long nonce) {
}

record ApiResponse<T>(Boolean success, String message, Integer code, T result) {
}

record BalancesResponse(String available, String freeze) {
}
```

{% endcode %}

{% code title="build.gradle" %}

```java
dependencies {
    implementation('commons-codec:commons-codec:1.17.0')
    implementation('com.squareup.okhttp3:okhttp:4.12.0')
    implementation('com.squareup.retrofit2:retrofit:2.11.0')
    implementation('com.squareup.retrofit2:converter-gson:2.11.0')
    testImplementation platform('org.junit:junit-bom:5.10.0')
    testImplementation 'org.junit.jupiter:junit-jupiter'
}
```

{% endcode %}
{% endtab %}

{% tab title="Node.js" %}

```javascript
import { HttpService, Injectable } from '@nestjs/common';
import * as crypto from 'crypto';
import { AxiosResponse } from 'axios';

export interface GetBalanceRequest {
  request: string;
  currency: string;
  nonce: string;
}

export interface GetBalances {
  success: boolean;
  message: string;
  result: {
    available: string;
    freeze: string;
  };
  code: number;
}

@Injectable()
export class PaymentService {
  constructor(private http: HttpService) {
    this.createInvoice().then(console.log);
  }
  createInvoice(): Promise<AxiosResponse<GetBalances>> {
    const now = Date.now();
    const input = {
      request: '/api/v1/account/balance',
      currency: 'ETH',
      nonce: `${now}`,
    } satisfies GetBalanceRequest;

    const secret = 'xxxxxxxx';
    const apiKey = 'xxxxxxxx';
    const baseUrl = 'https://api.earnbit.com';
    const payload = JSON.stringify(input, null, 0);
    console.log(payload);
    const jsonPayload = Buffer.from(payload).toString('base64');
    const encrypted = crypto
      .createHmac('sha512', secret)
      .update(jsonPayload)
      .digest('hex');

    console.log({
      'Content-type': 'application/json',
      'X-TXC-APIKEY': apiKey,
      'X-TXC-PAYLOAD': jsonPayload,
      'X-TXC-SIGNATURE': encrypted,
    });
    return this.http
      .post<GetBalances>(`/api/v1/account/balance`, payload, {
        headers: {
          'Content-type': 'application/json',
          'X-TXC-APIKEY': apiKey,
          'X-TXC-PAYLOAD': jsonPayload,
          'X-TXC-SIGNATURE': encrypted,
        },
        baseURL: baseUrl,
      })
      .toPromise();
  }
}
```

{% endtab %}

{% tab title="Python" %}

```python
import json
import time
import base64
import hmac
import hashlib
import requests

# Constants
REQUEST_URL = "https://api.earnbit.com"
API_PATH = "/api/v1/account/balance"
API_KEY = "xxxxxxxxx"
API_SECRET = "xxxxxxxxx"

def calc_signature(payload: str) -> str:
    """
    Calculate the HMAC-SHA512 signature.

    Args:
        payload (str): Base64-encoded data.

    Returns:
        str: Hex-encoded HMAC-SHA512 signature.
    """
    signature = hmac.new(
        API_SECRET.encode(),
        payload.encode(),
        hashlib.sha512
    ).hexdigest()
    return signature

def call_api():
    # Prepare the request data
    data = {
        "request": API_PATH,
        "currency": "ETH",
        "nonce": str(int(time.time() * 1000))  # Current timestamp in milliseconds
    }

    # Convert data to JSON string
    data_json_str = json.dumps(data, separators=(',', ':'))

    # Create payload and signature
    payload = base64.b64encode(data_json_str.encode()).decode()
    signature = calc_signature(payload)

    # Prepare the headers
    headers = {
        "Content-Type": "application/json",
        "X-TXC-APIKEY": API_KEY,
        "X-TXC-PAYLOAD": payload,
        "X-TXC-SIGNATURE": signature
    }

    # Make the POST request
    response = requests.post(
        url=f"{REQUEST_URL}{API_PATH}",
        headers=headers,
        data=data_json_str
    )

    # Log the response
    print(response.status_code)
    print(response.text)

if __name__ == "__main__":
    call_api()
```

{% endtab %}

{% tab title="Go" %}

```go
package main

import (
	"crypto/hmac"
	"crypto/sha512"
	"encoding/base64"
	"encoding/hex"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"strings"
	"time"
)

const (
	requestURL = "https://api.earnbit.com"
	apiPath    = "/api/v1/account/balance"
	apiKey     = "xxxxxxxxx"
	apiSecret  = "xxxxxxxxx"
)

func calcSignature(payload string) string {
	h := hmac.New(sha512.New, []byte(apiSecret))
	h.Write([]byte(payload))
	return hex.EncodeToString(h.Sum(nil))
}

func callAPI() {
	data := map[string]string{
		"request": apiPath,
		"currency": "USDT",
		"nonce":    fmt.Sprintf("%d", time.Now().UnixNano()/int64(time.Millisecond)),
	}

	dataJSON, _ := json.Marshal(data)
	dataJSONString := string(dataJSON)

	payload := base64.StdEncoding.EncodeToString([]byte(dataJSONString))
	signature := calcSignature(payload)

	client := &http.Client{}
	req, _ := http.NewRequest("POST", requestURL+apiPath, strings.NewReader(dataJSONString))
	req.Header.Set("Content-Type", "application/json")
	req.Header.Set("X-TXC-APIKEY", apiKey)
	req.Header.Set("X-TXC-PAYLOAD", payload)
	req.Header.Set("X-TXC-SIGNATURE", signature)

	resp, err := client.Do(req)
	if err != nil {
		fmt.Println("Error:", err)
		return
	}
	defer resp.Body.Close()

	body, _ := ioutil.ReadAll(resp.Body)
	
	fmt.Println(string(body))
}

func main() {
	callAPI()
}
```

{% endtab %}
{% endtabs %}

<details>

<summary><strong>Errors</strong></summary>

**Response example:**

```json
{
    "code": 400,
    "success": false,
    "message": "authentication failure",
    "result": []
}
```

**This error occurs in the following cases:**

* The request was signed incorrectly.
* Some of the provided parameters are incorrect.
* Provided [nonce](#requirements) is incorrect or less than on the previous completed request
* The base URL or path is incorrect.
* The API keys are not [activated](#get-your-api-keys).

</details>


---

# 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://earnbit.gitbook.io/earnbit/developers/exchange-api-documentation/private-endpoints-or-http/authentication-and-api-keys.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.
