
All requests to the Verigram API must be authenticated. For this, the request must contain the following headers:
X-Verigram-Api-Version: API version, current version 2.0
X-Verigram-Api-Key: your API key
You can generate API keys in the Client Console.
There are two kinds of keys:
Test: limited by time and number of requests. Can be used with the mock service (mockery).
Production: not limited by time, the number of requests is limited by the terms of the contract, and cannot be used with the mock service (mockery).
Unlike the test key, the production API key consists of two parts:
API key - the key is passed in the header
API secret - the secret is not passed in the header, but is used to sign the request.
When you call the API with a test key, HMAC signatures are not required.
The request is signed using the HMAC-SHA256 algorithm in Hex format. HMAC is a cryptographic method that allows you to verify the integrity and authenticity of data when transmitted over open channels.
The secret key (API Secret) can be found in the Client Console.

The signature is created from two elements: your API Secret (as the key) and the string to sign (Message).
Forming the string to sign
Join the current time (timestamp in seconds) and the request path (URI), starting with the slash /.
Format: {Timestamp}{Request path with parameters}
Example 1: URL: https://abc.com/path/to/resource, timestamp: 1652360077, string to sign: 1652360077/path/to/resource
Example 2: URL: https://abc.com/path?key1=value1&key2=value2, timestamp: 1676003122, string to sign: 1676003122/path?key1=value1&key2=value2
Hashing
Calculate the hash of the resulting string using the HMAC-SHA256 algorithm, using your API Secret, and convert the result to a Hex string (lowercase).
ā± Validity period: the generated signature is valid for exactly 1 minute. Make sure your server has time synchronization (NTP) configured.
Pass the resulting signature and the current time (timestamp) in the request headers:
X-Verigram-Hmac-SHA256 - the resulting Hex string
X-Verigram-Ts - exactly the same timestamp as in the string you signed
Also don't forget the two standard headers: X-Verigram-Api-Version, X-Verigram-Api-Key.
If verification fails, the server will return a 401 Unauthorized error:
Invalid timestamp: the signature has expired (check the clock on the server).
Invalid API key: incorrect X-Verigram-Api-Key.
Invalid signature: the request data does not match the string from which the signature was made.
import hmac
import hashlib
import requests
from datetime import datetime
# 1. Authorization data
API_KEY = "your-api-key"
API_SECRET = "your-api-secret"
API_HOST = "https://services.kz-ala-1.verigram.kz"
# 2. Forming request parameters
path = "/flow"
ts = str(int(datetime.now().timestamp()))
# 3. Assemble the string and create the signature (Hex string)
signable_str = f"{ts}{path}"
signature = hmac.new(
API_SECRET.encode("utf-8"),
msg=signable_str.encode("utf-8"),
digestmod=hashlib.sha256
).hexdigest()
# 4. Configure headers
headers = {
"X-Verigram-Api-Version": "2.0.0",
"X-Verigram-Api-Key": API_KEY,
"X-Verigram-Hmac-SHA256": signature,
"X-Verigram-Ts": ts
}
# 5. Send the POST request
response = requests.post(f"{API_HOST}{path}", headers=headers)
print(response.status_code, response.json())import crypto from 'crypto';
// 1. Authorization data
const API_KEY = "your-api-key";
const API_SECRET = "your-api-secret";
const API_HOST = "https://services.kz-ala-1.verigram.kz";
async function makeAuthenticatedRequest() {
try {
// 2. Request parameters
const path = "/flow";
const timestamp = Math.floor(Date.now() / 1000).toString(); // Time in seconds
// 3. Assemble the string and create the signature (Hex)
const signableStr = `${timestamp}${path}`;
const signature = crypto
.createHmac('sha256', API_SECRET)
.update(signableStr)
.digest('hex'); // Automatically produces a lowercase Hex string
// 4. Configure headers
const headers = {
'Content-Type': 'application/json',
'X-Verigram-Api-Version': '2.0.0',
'X-Verigram-Api-Key': API_KEY,
'X-Verigram-Hmac-SHA256': signature,
'X-Verigram-Ts': timestamp
};
// 5. Send the POST request
const response = await fetch(`${API_HOST}${path}`, {
method: 'POST',
headers: headers
});
const result = await response.json();
console.log(`Status Code: ${response.status}`);
console.log('Response:', result);
} catch (error) {
console.error('An error occurred while sending the request:', error);
}
}
makeAuthenticatedRequest();date -u --rfc-3339=ns; nc time.aws.com 13If the difference is noticeable, set up a time synchronization service, chrony or ntpd, specifying time.aws.com as the server.
The API secret is as significant as a password: whoever owns it can sign requests on behalf of your account. Store it as strictly as you store passwords and private keys, and never insert it into the code of mobile and web clients, in public repositories, or in logs.
Storage recommendations:
Keep the API Secret in environment variables or in a secrets manager (for example, HashiCorp Vault)
Sign requests only on the backend. The secret must not end up in code that runs in the browser or in a mobile application.
Do not send the secret via email, messengers, or support tickets in plain form.
Even if all these measures are followed, the secret can unfortunately leak. Therefore, rotate the API key and secret not only upon a confirmed leak, but also on a regular basis, according to a pre-set schedule.
Rotation can be carried out using the following algorithm:
In the Client Console, click the "Generate Production Access Keys" button.
Replace the old key and secret in your system with the new pair, and make sure everything works.
Revoke the old key pair (the "Revoke" button)