Authorization
KYT API uses a custom HTTP-scheme based on a keyed-HMAC (Hash Message Authentication Code) for authentication.
To authenticate a request, you concatenate selected elements of the request to form a canonical string. Then you sign that string using your KYT API Secret. Finally, you add the resulting HMAC signature to the request headers.
This section describes the required headers and the process of building a valid signature.
Header parameters
| Parameter | Description |
|---|---|
API-KEY-ID | Your API Key ID. |
API-TIMESTAMP | Current UTC timestamp in milliseconds. |
API-SIGNATURE | HMAC-SHA256 signature encoded in Base64. |
String-to-sign format
BitOK KYT API requires a canonical string to be created and signed for each request.
The string must follow this exact format:
<HTTP_METHOD><PATH+QUERY><TIMESTAMP>[<BODY_JSON>]
Where:
- HTTP_METHOD — Request method (
GET,POST, etc.) - PATH+QUERY — Full API path including any query parameters
- TIMESTAMP — Same value as sent in the
API-TIMESTAMPheader - BODY_JSON — Optional JSON payload (only for requests with a body)
Signature parameters
| Parameter | Description |
|---|---|
http_method | The HTTP method of the request. Example: GET, POST. |
endpoint_with_query | The request path including query parameters. |
timestamp | The timestamp value included in the API-TIMESTAMP header. |
json_payload | The JSON request body (only for methods that include a payload). |
api_secret | The secret part of your API key, used to compute the HMAC signature. |
Building an HMAC-256 signature
Below is the logic required to build a valid signature:
- Concatenate the HTTP method, request path, timestamp, and (optionally) the request body into a canonical string.
- Compute an HMAC-SHA256 digest using your API Secret.
- Base64-encode the resulting HMAC digest.
- Send the result in the
API-SIGNATUREheader.
Send Your First Request
Your BitOK KYT API endpoint is ready.
Let’s make your first authenticated request using the /v1/transfers/register-attempt/ endpoint.
1
Base URL
https://kyt-api.bitok.org
2
Authentication & Signature
Each request must include:
API-KEY-ID— your API key identifierAPI-TIMESTAMP— current UTC timestamp in millisecondsAPI-SIGNATURE— HMAC-SHA256 signature encoded in Base64
<HTTP_METHOD><PATH+QUERY><TIMESTAMP>[<BODY_JSON>]
Example request body
{
"client_id": "id0001",
"attempt_id": "0a805206bab649a68b3408032a7352e6",
"direction": "outgoing",
"network": "ETH",
"output_address": "0x56eddb7aa87536c09ccc2793473599fd21a8b17f",
"amount": 120.5
}
Generate Signature & Send Request
- cURL
- JavaScript
- Python
curl -X POST "https://kyt-api.bitok.org/v1/transfers/register-attempt/" \
-H "Content-Type: application/json" \
-H "API-KEY-ID: YOUR_API_KEY_ID" \
-H "API-TIMESTAMP: YOUR_TIMESTAMP" \
-H "API-SIGNATURE: YOUR_SIGNATURE" \
-d '{
"client_id": "id0001",
"attempt_id": "0a805206bab649a68b3408032a7352e6",
"direction": "outgoing",
"network": "ETH",
"output_address": "0x56eddb7aa87536c09ccc2793473599fd21a8b17f",
"amount": 120.5
}'
const crypto = require("crypto-js");
const fetch = require("node-fetch");
const apiKeyId = "YOUR_API_KEY_ID";
const apiSecret = "YOUR_API_SECRET";
const url = "https://kyt-api.bitok.org/v1/transfers/register-attempt/";
const method = "POST";
const body = {
client_id: "id0001",
attempt_id: "0a805206bab649a68b3408032a7352e6",
direction: "outgoing",
network: "ETH",
output_address: "0x56eddb7aa87536c09ccc2793473599fd21a8b17f",
amount: 120.5
};
const bodyJson = JSON.stringify(body);
const timestamp = Date.now().toString();
const toSign =
method + "\n" +
"/v1/transfers/register-attempt/" + "\n" +
timestamp + "\n" +
bodyJson;
const signature = crypto
.HmacSHA256(toSign, apiSecret)
.toString(crypto.enc.Base64);
fetch(url, {
method,
headers: {
"Content-Type": "application/json",
"API-KEY-ID": apiKeyId,
"API-TIMESTAMP": timestamp,
"API-SIGNATURE": signature
},
body: bodyJson
})
.then(res => res.json())
.then(console.log)
.catch(console.error);
import time
import hmac
import hashlib
import base64
import json
import requests
API_KEY_ID = "YOUR_API_KEY_ID"
API_SECRET = "YOUR_API_SECRET"
url = "https://kyt-api.bitok.org/v1/transfers/register-attempt/"
method = "POST"
body = {
"client_id": "id0001",
"attempt_id": "0a805206bab649a68b3408032a7352e6",
"direction": "outgoing",
"network": "ETH",
"output_address": "0x56eddb7aa87536c09ccc2793473599fd21a8b17f",
"amount": 120.5
}
body_json = json.dumps(body)
timestamp = str(int(time.time() * 1000))
to_sign = (
method + "\n" +
"/v1/transfers/register-attempt/" + "\n" +
timestamp + "\n" +
body_json
)
signature = base64.b64encode(
hmac.new(API_SECRET.encode(), to_sign.encode(), hashlib.sha256).digest()
).decode()
headers = {
"Content-Type": "application/json",
"API-KEY-ID": API_KEY_ID,
"API-TIMESTAMP": timestamp,
"API-SIGNATURE": signature
}
response = requests.post(url, headers=headers, data=body_json)
print("Status:", response.status_code)
print("Response:", response.json())
3
Sample Response
{
"id": "05c69c2a-5602-4efe-9ae3-816b695fad36",
"client_id": "id0001",
"attempt_id": "0a805206bab649a68b3408032a7352e6",
"registered_at": "2025-11-17T13:07:36.508069+03:00",
"risk_level": "undefined",
"risk_score": null,
"network": "ETH",
"token_id": "native",
"token_symbol": "ETH",
"tx_status": "none",
"tx_hash": null,
"occurred_at": null,
"input_address": null,
"output_address": "0x56eddb7aa87536c09ccc2793473599fd21a8b17f",
"direction": "outgoing",
"amount": 120.5,
"value_in_fiat": 291975.1499056175,
"check_state": {
"exposure": "none",
"exposure_checked_at": null,
"counterparty": "checking",
"counterparty_checked_at": null,
"sanctions": "none",
"sanctions_checked_at": null
},
"fiat_currency": "USD"
}