> ## Documentation Index
> Fetch the complete documentation index at: https://docs.velafi.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Generate a Token

> Sign a request with your API key and secret to get the business token that authenticates other VelaFi API calls in the X-BH-TOKEN header.

Use this endpoint to get a business token. Your server signs the request with its API secret and sends its API key in the `X-BH-APIKEY` header. The response contains a `token`, which you send in the `X-BH-TOKEN` header on authenticated requests, and an `expireTime`.

> [!NOTE]
>
> Before this call can succeed, VelaFi must enable API access on your account and the API key must have an IP whitelist. The request must come from an IP address on that whitelist. See [Authentication](https://docs.velafi.com/api-reference/authentication.md).

## Endpoint

```text theme={null}
GET https://api.velafi.com/v2/token/generate
```

> [!NOTE]
>
> Use `https://api-test.velafi.com/v2/token/generate` with your sandbox credentials for sandbox testing.

## Request Headers

**X-BH-APIKEY** `string` *required*

Your API key.

## Query Parameters

**timestamp** `integer` *required*

The current Unix time in milliseconds, for example `1740568725231`.

**signature** `string` *required*

HMAC-SHA256 of the string `timestamp=<timestamp>`, keyed with your API secret and encoded as lowercase hex.

> [!WARNING]
>
> Send only `timestamp` and `signature` as query parameters. The server verifies the signature against your query string without the `signature` parameter. With only these two parameters, the signed string is exactly `timestamp=<timestamp>`.

## How to Sign

**1. Build the message**

Take the current Unix time in milliseconds and build the string `timestamp=<ms>`, for example `timestamp=1740568725231`.

**2. Compute the HMAC**

Compute HMAC-SHA256 of the message, using your API secret as the key.

**3. Hex-encode the result**

Encode the 32-byte result as a 64-character lowercase hex string. This is the `signature`.

## Response Fields

**code** `integer`

`200` on success. Errors return a negative code; see [Errors](#errors).

**msg** `string`

`SUCCESS` on success, otherwise an error message.

**data** `object`

**data fields**

**token** `string`

The business token. Send it in the `X-BH-TOKEN` header on authenticated requests.

**expireTime** `string`

When the token expires, as a Unix timestamp in milliseconds. Request a new token before this time.

## Examples

```bash cURL theme={null}
API_KEY="your_api_key"
API_SECRET="your_api_secret"
TIMESTAMP=$(( $(date +%s) * 1000 ))
SIGNATURE=$(printf 'timestamp=%s' "$TIMESTAMP" | openssl dgst -sha256 -hmac "$API_SECRET" | sed 's/^.*= //')

curl --request GET \
  --url "https://api-test.velafi.com/v2/token/generate?timestamp=${TIMESTAMP}&signature=${SIGNATURE}" \
  --header "X-BH-APIKEY: ${API_KEY}"
```

```python Python theme={null}
import hashlib
import hmac
import time

import requests

BASE_URL = "https://api-test.velafi.com"
API_KEY = "your_api_key"
API_SECRET = "your_api_secret"


def generate_token():
    timestamp = str(int(time.time() * 1000))
    signature = hmac.new(
        API_SECRET.encode("utf-8"),
        f"timestamp={timestamp}".encode("utf-8"),
        hashlib.sha256,
    ).hexdigest()

    response = requests.get(
        f"{BASE_URL}/v2/token/generate",
        params={"timestamp": timestamp, "signature": signature},
        headers={"X-BH-APIKEY": API_KEY},
        timeout=10,
    )
    body = response.json()
    if body.get("code") != 200:
        raise RuntimeError(f"Token request failed: {body}")
    return body["data"]["token"], int(body["data"]["expireTime"])


token, expire_time_ms = generate_token()
print(token, expire_time_ms)
```

```javascript Node.js theme={null}
const crypto = require("crypto");

const BASE_URL = "https://api-test.velafi.com";
const API_KEY = "your_api_key";
const API_SECRET = "your_api_secret";

async function generateToken() {
  const timestamp = Date.now().toString();
  const signature = crypto
    .createHmac("sha256", API_SECRET)
    .update(`timestamp=${timestamp}`)
    .digest("hex");

  const url = `${BASE_URL}/v2/token/generate?timestamp=${timestamp}&signature=${signature}`;
  const response = await fetch(url, { headers: { "X-BH-APIKEY": API_KEY } });
  const body = await response.json();
  if (body.code !== 200) {
    throw new Error(`Token request failed: ${JSON.stringify(body)}`);
  }
  return { token: body.data.token, expireTime: Number(body.data.expireTime) };
}

generateToken().then(({ token, expireTime }) => console.log(token, expireTime));
```

```java Java theme={null}
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;

public class GenerateToken {
    private static final String BASE_URL = "https://api-test.velafi.com";
    private static final String API_KEY = "your_api_key";
    private static final String API_SECRET = "your_api_secret";

    public static void main(String[] args) throws Exception {
        String timestamp = String.valueOf(System.currentTimeMillis());
        String signature = hmacSha256Hex(API_SECRET, "timestamp=" + timestamp);

        HttpRequest request = HttpRequest.newBuilder()
                .uri(URI.create(BASE_URL + "/v2/token/generate?timestamp=" + timestamp + "&signature=" + signature))
                .header("X-BH-APIKEY", API_KEY)
                .GET()
                .build();

        HttpResponse<String> response = HttpClient.newHttpClient()
                .send(request, HttpResponse.BodyHandlers.ofString());
        // On success: {"code":200,"msg":"SUCCESS","data":{"token":"...","expireTime":"..."}}
        System.out.println(response.body());
    }

    static String hmacSha256Hex(String secret, String message) throws Exception {
        Mac mac = Mac.getInstance("HmacSHA256");
        mac.init(new SecretKeySpec(secret.getBytes(StandardCharsets.UTF_8), "HmacSHA256"));
        byte[] raw = mac.doFinal(message.getBytes(StandardCharsets.UTF_8));
        StringBuilder hex = new StringBuilder();
        for (byte b : raw) {
            hex.append(String.format("%02x", b));
        }
        return hex.toString();
    }
}
```

```json Response theme={null}
{
  "code": 200,
  "msg": "SUCCESS",
  "data": {
    "token": "00000000-0000-0000-0000-000000000006",
    "expireTime": "1740568725231"
  }
}
```

## Errors

Errors return HTTP status `400` with a negative `code`:

| Code | Message | Cause |
| - | - | - |
| `-1002` | You are not authorized to execute this request | The `X-BH-APIKEY` header is missing or malformed. |
| `-1004` | `Missing required parameter '<name>'` | The `signature` query parameter is missing, or `timestamp` is missing while other query parameters are sent. The message names the missing parameter. |
| `-1103` | An unknown parameter was sent. | The request has no query parameters, or `signature` is the only one. |
| `-1022` | Signature for this request is not valid. | The signature does not match, or the API key does not exist. |
| `-1023` | Please set IP whitelist before using API | The API key has no IP whitelist. |
| `-2015` | Invalid API-key, IP, or permissions for action. | The API key or your account is disabled, or the request IP address is not on the key's whitelist. |
| `-5033` | You are not yet an API user. Please contact the OTC customer service manager if you have any needs. | API access is not enabled on your account. |

## Using the Token

Send the token in the `X-BH-TOKEN` header:

```bash theme={null}
curl --request GET \
  --url https://api-test.velafi.com/v2/user/account \
  --header "X-BH-TOKEN: your_token"
```

Request a new token before `expireTime`. A call with an expired or unknown token fails with code `-1022`.


## Related topics

- [Authentication](https://docs.velafi.com/api-reference/authentication.md)
- [Error Codes](https://docs.velafi.com/docs/error-codes.md)
- [List Crypto→Fiat Pairs](https://docs.velafi.com/api-reference/basic-configuration/get-crypto-fiat-pairs.md)
- [List Crypto→Fiat Payment Methods](https://docs.velafi.com/api-reference/basic-configuration/get-crypto-fiat-payment-methods.md)
- [List Fiat→Crypto Pairs](https://docs.velafi.com/api-reference/basic-configuration/get-fiat-crypto-pairs.md)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.