clientKey is a custom identifier that you set yourself and use to associate KYC sessions with your users, applications, or contracts.
Through clientKey you can:
- find all KYC sessions for a specific user;
- match verification results with your objects (userId, orderId, loanId, etc.);
- filter sessions via REST API;
- it’s more convenient to process webhooks.
Important: the value of clientKey is chosen by you; the platform does not generate it automatically.
Format and limitations
- Type:
string - Maximum length: 36 characters
- Format: any string, it is convenient to limit yourself to Latin letters, numbers, and separators (
[a-zA-Z0-9_-])
Recommended to use:
clientKey = userId— if one KYC check per user;clientKey = "${userId}:${applicationId}"— if KYC is linked to an application, order, contract;clientKey = UUID— if it is more convenient to work only with the KYC identifier.
Two forms of clientKey: “raw” and encrypted
To integrate with WebSDK, you need to understand that there are:
- Original value (
clientKeyRaw) What you came up with: for example,"user_123"or"loan-42". - Encrypted value (
clientKey) This is what you actually pass to the widget. It is the result of encryptingclientKeyRawwith the “script secret key” in the Personal Account.
How it works:
- On the backend:
- form
clientKeyRaw(up to 36 characters); - encrypt it with the script’s secret key;
- send the encrypted
clientKeyto the front.
- On the frontend:
- pass the encrypted
clientKeytoKYCWidget.setupKYC(...).
- On the **KYC service** side:
- value is deciphered;
- the original
clientKeyRawis saved in the session; - it can be used to filter sessions and retrieve results via API and webhooks.
In the API (
/kyc/session/status,/kyc/sessions/filter, and webhooks), you work with the original value that you set yourself. Encryption is only needed for the secure transmission ofclientKeyto the browser.
Where clientKey is Used
In WebSDK
Widget call:
window.KYCWidget.setupKYC({
schemaId: "SCHEMA_ID", // Schema validation ID
clientKey: "ENCRYPTED_CLIENT_KEY", // encrypted clientKeyRaw
theme: "light",
closeCb: () => console.log("CLOSE"),
successCb: (payload) => {
console.log("SUCCESS", payload);
// here you already know the original clientKeyRaw, as you set it yourself on the backend
},
}); In the REST API
/kyc/session/status— you can passclientKeyto clarify the status for a specific key;/kyc/sessions/filter— there is aclientKeyfilter to get all sessions by key.
Here you pass the original value (clientKeyRaw), without encryption.
Generation and Encryption of clientKey on the Backend
The Scenario Secret Key is stored only on your server-side. It must not be transmitted to the browser.
General idea:
- Take
clientKeyRaw(up to 36 characters). - Take the script secret key from the personal account (
scenarioSecretKey). - On the backend, encrypt
clientKeyRawusing an algorithm (e.g., AES-256-CBC). - Pass the resulting Base64 string to WebSDK as
clientKey.
Example in Node.js (AES-256-CBC)
const crypto = require("crypto");
// 1. Source identifier (what you want to see in APIs and webhooks)
const clientKeyRaw = "user_123"; // up to 36 characters
// 2. Script secret key from the Personal Account (DO NOT pass to the browser!)
const password = "SCENARIO_SECRET_KEY";
// 3. Obtain a 32-byte key from the password
const key = crypto.createHash("sha256").update(password).digest('hex').substr(0, 32);
// 4. Generate a random IV (16 bytes)
const iv = crypto.randomBytes(16);
// 5. Encrypt clientKeyRaw
const cipher = crypto.createCipheriv("aes-256-cbc", key, iv);
const encrypted = Buffer.concat([cipher.update(clientKeyRaw, "utf8"), cipher.final()]);
// 6. We glue together IV + ciphertext and encode it in Base64 — this is the clientKey for the widget
const encryptedBase64 = Buffer.concat([iv, encrypted]).toString("base64");
console.log("clientKeyRaw:", clientKeyRaw);
console.log("clientKey (encrypted):", encryptedBase64); This is the encrypted clientKey that you substitute into:
window.KYCWidget.setupKYC({
schemaId: "SCHEMA_ID",
clientKey: encryptedBase64,
// ...
}); The “Check” button next to the script secret key in the Personal Account uses the same encryption algorithm and helps to quickly verify that
clientKeyis encrypted/decrypted correctly. For production, always encrypt on your backend.
How to test clientKey
- In the personal account, find the secret script key.
- Click the “Check” button and enter the test
clientKeyRaw(e.g.,test_user_1). - The LC will return an encrypted value — it can be temporarily substituted into the integration examples (instead of
"ENCRYPTED_CLIENT_KEY"). - Make sure that:
- widget opens without errors;
- your KYC session logs show the original
clientKeyRaw(e.g., in filtering byclientKeyvia/kyc/sessions/filter).
Frequently Asked Questions and Errors
“Where do I get the values for clientKey and clientUser?”
clientKey— any string up to 36 characters, which you define yourself:userId, application number, order, any convenient value. The parameter is required.clientUser— also any string up to 36 characters, but it is better not to use it in new integrations.
Best practice: set
clientKeyRaw= youruserIdororderId, encrypt it, and only passclientKey.
Console Error: “Failed to perform asymmetric decryption!”
Most often it means that:
- an unencrypted
clientKeyRawwas passed to the widget; - or a different secret key was used, other than the script key;
- or the
clientKeyvalue was corrupted/truncated (e.g., during copying).
Check:
- That you are passing a Base64 string obtained after encryption to the widget (see the example above).
- That the script in the LC and the secret key you use for encryption match.
- The extra parameter
clientUseris not used (it can be removed).
“And how do I find the clientKey to decrypt the webhook?”
The webhook body does not require clientKey for decryption:
- the webhook is encrypted with the session key/webhook secret, not the
clientKey; - to decrypt, you only need the password/key that you specified in the webhook settings, and the encrypted field
encryptedfrom the POST request.
clientKey in the webhook is simply one of the JSON fields within the already decrypted body, and its value will be exactly what you set in clientKeyRaw.
“Why does each test webhook come with a different encrypted string, even though the JSON is the same?”
This is normal:
- a **random IV (initialization vector)** is used for encryption;
- even with the same JSON and encryption key, the ciphertext is different each time;
- after decryption the body will be the same JSON.
“How is the general status success/failed related to checks and databases?”
Overall KYC session status:
success— only if all checks passed successfully;- if somewhere there is a
failed(OCR, fraud, databases, etc.) — the overall status will befailed.
Checks against external databases (sanctions, bailiffs, etc.) also affect the overall success: if a “red flag” is considered critical, it will result in failed at the session level as well.
Recommended workflow with clientKey
- On the backend at the start of the KYC process:
- generate or select a
clientKeyRaw(e.g.,user_123); - encrypt it with the secret script key →
encryptedClientKey; - you save
clientKeyRawwith yourself along withuserId/orderId.
- On the frontend:
- pass
encryptedClientKeytoKYCWidget.setupKYC(...).
- To get the result:
- either accept the webhook and look for the
clientKeyfield within the body; - or call
/kyc/sessions/filterwithclientKey = clientKeyRawto find all sessions for this key.
This way, you can always unambiguously determine which user or application any KYC session belongs to.