# Authentication

{% hint style="danger" %}
This API version is deprecated and will no longer be supported after December 1, 2025. Refer to [API v3](https://docs.b2binpay.com/api-guide/authentication) for updated descriptions.
{% endhint %}

## Obtain token

### Request

<mark style="color:blue;">`POST`</mark> `[base]/token`

<table><thead><tr><th width="135">Name</th><th width="106">Type</th><th width="100">Required</th><th>Description</th></tr></thead><tbody><tr><td><code>login</code></td><td>string</td><td>Yes</td><td>Your API key.</td></tr><tr><td><code>password</code></td><td>string</td><td>Yes</td><td>Your API secret.</td></tr></tbody></table>

#### Request example

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

```sh
curl --request POST \
--url [base]/token/ \
--header 'Content-Type: application/vnd.api+json' \
--data '{
  "data": {
    "type": "auth-token",
    "attributes": {
      "login": "<Your API key>",
      "password": "<Your secret>"
    }
  }
}'
```

{% endtab %}

{% tab title="Python" %}

```python
import requests

url = '[base]/token/'

headers = {
  'content-type': 'application/vnd.api+json',
}

data = {
  'data': {
    'type': 'auth-token',
    'attributes': {
      'login': '<Your API key>',
      'password': '<Your API secret>',
    }
  }
}

requests.post(url, headers=headers, json=data)
```

{% endtab %}

{% tab title="PHP" %}

```php
<?php

use GuzzleHttp\Client;
use GuzzleHttp\Exception\RequestException;

$client = new GuzzleHttp\Client();
try {
  $res = $client->post('[base]/token/', [
    'json' => [
      'data' => [
        'type' => 'auth-token',
        'attributes' => [
          'login' => '<Your API key>',
          'password' => '<Your API secret>',
        ],
      ],
    ],
    'headers' => [
      'Content-Type' => 'application/vnd.api+json',
    ],
  ]);
echo $res->getBody();
} catch (RequestException $e) {}
```

{% endtab %}
{% endtabs %}

### Response

<table><thead><tr><th width="231">Name</th><th width="106">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>access</code></td><td>string</td><td>Your access token. It has an expiry time of about a minute and after expiration should be refreshed.</td></tr><tr><td><code>refresh</code></td><td>string</td><td>The long-living token that is used for obtaining new access tokens (refer to <a href="#refresh-token">Refresh token</a>).</td></tr><tr><td><code>access_expired_at</code></td><td>string</td><td>The date and time of access token expiration.</td></tr><tr><td><code>refresh_expired_at</code></td><td>string</td><td>The date and time of refresh token expiration.</td></tr><tr><td><code>is_2fa_confirmed</code></td><td>boolean</td><td><p>If <code>true</code>, 2FA is enabled.</p><p><em>2FA is unavailable for API users.</em></p></td></tr><tr><td><code>time</code></td><td>string</td><td>The date and time of request receiving.</td></tr><tr><td><code>sign</code></td><td>string</td><td><p>The HMAC signature for a response payload authentication.</p><p>To verify that the refresh token was sent by B2BINPAY, generate an HMAC signature using the <code>sha256</code> as algorithm: <code>sha256</code> hash of the concatenation of your login and password as a key, and the concatenation of <code>meta.time</code> and <code>refresh</code> fields as a message.</p><p>Refer to <a href="#auth-verification">Auth verification</a> below for a sign verification example.</p></td></tr></tbody></table>

#### Response example

{% code overflow="wrap" %}

```json
{
  "data": {
    "type": "auth-token",
    "id": "0",
    "attributes": {
      "refresh": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...",
      "access": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...",
      "access_expired_at": "2020-12-29T05:42:11.925654Z",
      "refresh_expired_at": "2020-12-29T11:27:11.925654Z",
      "is_2fa_confirmed": false
    }
  },
  "meta": {
    "time": "2020-12-29T05:27:11.925654Z",
    "sign": "bcd6519ce27fed2ce9efe49cd09b387f050c0122c96..."
  }
}
```

{% endcode %}

#### Response codes

<table><thead><tr><th width="134">HTTP code</th><th width="274">Application code</th><th width="170">Description</th><th>Suggested action</th></tr></thead><tbody><tr><td><mark style="color:green;"><code>200</code></mark></td><td>—</td><td>OK</td><td>—</td></tr><tr><td><mark style="color:red;"><code>400</code></mark></td><td>2006: No active account found with the given credentials</td><td>Incorrect credentials</td><td>Send correct credentials.</td></tr><tr><td><mark style="color:red;"><code>429</code></mark></td><td>throttled: Request was throttled</td><td>Too many requests</td><td>Try again later.</td></tr><tr><td><mark style="color:red;"><code>500</code></mark></td><td>—</td><td>Internal server error</td><td>Try again later.</td></tr><tr><td><mark style="color:red;"><code>502</code></mark></td><td>—</td><td>Bad gateway</td><td>Try again later.</td></tr><tr><td><mark style="color:red;"><code>503</code></mark></td><td>—</td><td>Service unavailable</td><td>Try again later.</td></tr><tr><td><mark style="color:red;"><code>504</code></mark></td><td>—</td><td>Gateway timeout</td><td>Try again later.</td></tr><tr><td><mark style="color:red;"><code>5xx</code></mark></td><td>—</td><td>Other server errors</td><td>Try again later.</td></tr></tbody></table>

***

## Refresh token

{% hint style="danger" %}
Once you receive a new key pair using your refresh token, the previous refresh token can no longer be used. A refresh token that is found to be invalid while not being expired must be rendered suspicious.
{% endhint %}

### Request

<mark style="color:blue;">`POST`</mark> `[base]/token/refresh/`

<table><thead><tr><th width="135">Name</th><th width="106">Type</th><th width="100">Required</th><th>Description</th></tr></thead><tbody><tr><td><code>refresh</code></td><td>string</td><td>Yes</td><td>Your refresh token from the <a href="#obtain-token">Obtain token</a> response.</td></tr></tbody></table>

#### Request example

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

```bash
curl --request POST \
--url [base]/token/refresh/ \
--header 'Content-Type: application/vnd.api+json' \
--data '{
  "data": {
    "type": "auth-token",
    "attributes": {
      "refresh": "<Your refresh token>"
    }
  }
}'
```

{% endtab %}

{% tab title="Python" %}

```python
import requests

url = '[base]/token/refresh/'

headers = {
  'content-type': 'application/vnd.api+json',
}

data = {
  'data': {
    'type': 'auth-token',
    'attributes': {
      'refresh': '<Your refresh token>',
    },
  },
}

requests.post(url, headers=headers, json=data)
```

{% endtab %}

{% tab title="PHP" %}
{% code overflow="wrap" %}

```php
<?php

use GuzzleHttp\Client;
use GuzzleHttp\Exception\RequestException;

$client = new GuzzleHttp\Client();
try {
  $res = $client->post('[base]/token/refresh/', [
    'json' => [
      'data' => [
        'type' => 'auth-token',
        'attributes' => [
          'refresh' => 'Your refresh token',
        ],
      ],
    ],
    'headers' => [
      'Content-Type' => 'application/vnd.api+json',
    ],
  ]);
echo $res->getBody();
} catch (RequestException $e) {}
```

{% endcode %}
{% endtab %}
{% endtabs %}

### Response

The response body is the same as for [Obtain token](#obtain-token) request, but without `meta` fields.

#### Response body example

```json
{
  "type": "auth-token",
  "id": "0",
  "attributes": {
    "refresh": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...",
    "access": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...",
    "access_expired_at": "2020-12-29T05:42:11.925654Z",
    "refresh_expired_at": "2020-12-29T11:27:11.925654Z",
    "is_2fa_confirmed": false
  }
}
```

#### Response codes

<table><thead><tr><th width="134">HTTP code</th><th width="274">Application code</th><th width="169">Description</th><th>Suggested action</th></tr></thead><tbody><tr><td><mark style="color:green;"><code>200</code></mark></td><td>—</td><td>OK</td><td>—</td></tr><tr><td><mark style="color:red;"><code>401</code></mark></td><td>2007: No active account found with the given credentials</td><td>Incorrect credentials</td><td>Send correct credentials.</td></tr><tr><td><mark style="color:red;"><code>500</code></mark></td><td>—</td><td>Internal server error</td><td>Try again later.</td></tr><tr><td><mark style="color:red;"><code>502</code></mark></td><td>—</td><td>Bad gateway</td><td>Try again later.</td></tr><tr><td><mark style="color:red;"><code>503</code></mark></td><td>—</td><td>Service unavailable</td><td>Try again later.</td></tr><tr><td><mark style="color:red;"><code>504</code></mark></td><td>—</td><td>Gateway timeout</td><td>Try again later.</td></tr><tr><td><mark style="color:red;"><code>5xx</code></mark></td><td>—</td><td>Other server errors</td><td>Try again later.</td></tr></tbody></table>

***

## Auth verification

Refer to the example below for a sign verification instance.

<details>

<summary>Auth verification example</summary>

{% code overflow="wrap" %}

```javascript
// "crypto-js": "4.0.0" is installed as a dependency
const SHA256 = require("crypto-js/sha256");
const hmacSHA256 = require('crypto-js/hmac-sha256');

// set API user login and password
const login = 'Your API key';
const password = 'Your API secret';

// parse /api/token/ response payload
const authResponse = JSON.parse("{\n" +
    "  \"data\": {\n" +
    "    \"type\": \"auth-token\",\n" +
    "    \"id\": \"0\",\n" +
    "    \"attributes\": {\n" +
    "      \"refresh\": \"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUz\",\n" +
    "      \"access\": \"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI\",\n" +
    "      \"access_expired_at\": \"2020-08-24T13:50:12.192479+03:00\",\n" +
    "      \"refresh_expired_at\": \"2020-08-24T19:33:33.192479+03:00\",\n" +
    "      \"is_2fa_confirmed\": false\n" +
    "    }\n" +
    "  },\n" +
    "  \"meta\": {\n" +
    "    \"time\": \"2020-08-24T10:33:33.192479Z\",\n" +
    "    \"sign\": \"e70adec551e26b560049e42aa0993ae42cac4e03fbbb300320d8be\"\n" +
    "  }\n" +
    "}");
    
// prepare data for hash check
const message = authResponse['meta']['time'] + authResponse['data']['attributes']['refresh'];
const responseSign = authResponse['meta']['sign'];
const secret = SHA256(login + password);
const calculatedSign = hmacSHA256(message, secret).toString();

// print result
if (responseSign === calculatedSign) {
  console.log('Verified');
} else {
  console.log('Invalid sign');
}
```

{% endcode %}

</details>
