Working with clientKey

clientKey is a user-defined identifier that you assign yourself and use to link KYC sessions with your users, applications, or contracts.

With clientKey you can:

  • find all KYC sessions for a specific user;

  • associate verification results with your objects (userId, orderId, loanId, etc.);

  • filter sessions through the REST API;

  • more easily process webhooks.

Important: the value of clientKey is defined by you — the platform does not generate it automatically.


Format and limitations

  • Type: string

  • Maximum length: 36 characters

  • Format: any string, recommended to use Latin letters, digits, separators ([a-zA-Z0-9_-])

Recommended usage:

  • 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 a KYC identifier.


Two forms of clientKey: raw and encrypted

For WebSDK integration, it is important to understand that there are:

  1. Raw value (clientKeyRaw) The value you define: e.g., "user_123" or "loan-42".

  2. Encrypted value (clientKey) The value you actually pass to the widget. It is the result of encrypting clientKeyRaw using the scenario's secret key from the dashboard.

Workflow structure:

  1. On your backend:

    • generate clientKeyRaw (up to 36 characters);

    • encrypt it with the scenario secret key;

    • send the encrypted clientKey to the frontend.

  2. On the frontend:

    • pass the encrypted clientKey into KYCWidget.setupKYC(...).

  3. On the KYC service side:

    • the value is decrypted;

    • raw clientKeyRaw is stored in the session;

    • you can filter sessions and get results by it via API and webhooks.

In the API (/kyc/session/status, /kyc/sessions/filter and webhooks) you work with the raw value you defined. Encryption is needed only for secure transfer of clientKey to the browser.


Where clientKey is used

In WebSDK

Widget call:

In REST API

  • /kyc/session/status — you can pass clientKey to check the status for the specific key;

  • /kyc/sessions/filter — there is a clientKey filter to get all sessions by this key.

Here you pass the raw value (clientKeyRaw), without encryption.


Generating and encrypting clientKey on backend

The scenario secret key is stored only on your server. It must never be sent to the browser.

General idea:

  1. Take clientKeyRaw (up to 36 characters).

  2. Take scenario secret key (scenarioSecretKey) from the dashboard.

  3. Encrypt clientKeyRaw on backend (example — AES-256-CBC).

  4. Encode the result in Base64 and pass it to WebSDK as clientKey.

Node.js example (AES-256-CBC)

Use this encrypted clientKey in:

The “Check” button next to the scenario secret key in the dashboard uses the same algorithm and helps verify that encryption/decryption works correctly. For production always encrypt on your server.


How to test clientKey

  1. In the dashboard, find the scenario secret key.

  2. Click “Check” and enter a test clientKeyRaw (e.g., test_user_1).

  3. The dashboard will return the encrypted value — you can temporarily use it in integration examples.

  4. Ensure that:

    • the widget opens without errors;

    • in your KYC sessions logs, the raw clientKeyRaw is visible (e.g., through filtering via /kyc/sessions/filter).


Common questions and issues

“Where do I get clientKey and clientUser values?”

  • clientKeyany string up to 36 chars that you define: userId, application number, order ID, any useful value. This parameter is required.

  • clientUser — also any string up to 36 chars, but in new integrations you should avoid using it.

Best practice: set clientKeyRaw equal to your userId or orderId, encrypt it and pass only clientKey.


Error: “Failed to perform asymmetric decryption!”

This usually means:

  • a raw clientKeyRaw was passed to the widget instead of an encrypted value;

  • or a wrong scenario secret key was used;

  • or clientKey was corrupted or truncated (e.g., copy/paste issue).

Check that:

  1. You pass a proper Base64 encrypted value to the widget.

  2. The scenario in the dashboard matches the secret key used for encryption.

  3. You are not using the deprecated clientUser parameter.


“How to decipher clientKey for a webhook?”

You do not need clientKey to decrypt webhook data:

  • webhook payload is encrypted with the webhook secret, not the clientKey;

  • to decrypt you only need your webhook secret and the encrypted field from the POST.

clientKey inside the webhook JSON is simply the raw value you defined (clientKeyRaw).


“Why is the webhook field encrypted always different even for the same JSON?”

This is expected:

  • encryption uses random IV (initialization vector);

  • same JSON + same key = different ciphertext every time;

  • after decryption the JSON is identical.


“How is the general success/failed status determined?”

Overall KYC session status:

  • successonly if all checks pass;

  • if any check fails (OCR, fraud, databases, etc.) → overall status is failed.

External database checks (sanctions, Court Enforcement Office, etc.) also affect the overall status. Any critical red flag results in failed.


  1. On backend at the beginning of KYC process:

    • generate or choose clientKeyRaw (e.g., user_123);

    • encrypt it → encryptedClientKey;

    • save clientKeyRaw on your side together with userId/orderId.

  2. On frontend:

    • pass encryptedClientKey to KYCWidget.setupKYC(...).

  3. To obtain results:

    • receive webhook and inspect clientKey inside decrypted JSON;

    • or call /kyc/sessions/filter with clientKey = clientKeyRaw.

This ensures you always know which user or application each KYC session belongs to.

Last updated