Starts KYC verification process on a registered user handle. This call triggers to KYC application to be sent.

After having created a user and a handle with /register, you can start the KYC verification process on the user with this endpoint. The verification results for a handle are asynchronously returned at the /check_kyc endpoint, and further details on handling failures can be found in the documentation there.


The request body at this endpoint is the header_msg JSON object.

You also need to pass a kyc_level key into the request body. In most cases you will need to use the kyc_level: KYC-STANDARD, or for Stearns you will likely use KYC-SARDINE-STRICT. See KYC/KYB Levels documentation for more details.


Updating end user data with a passed status

All end user data must go through re-verification of KYC in the event an end user needs to update their data after passing KYC.

  • It is your responsibility to build the logic to call the /request_kyc and /check_kyc endpoints to run the updated end user data through re-verification.

NOTE: If the end user needs to update their name you will need contact support after the end user has uploaded official documents with proof of name change, such as:

  • A marriage license or divorce decree (this must have your new legal name printed by the state, and it must show that a name change occurred)
  • A court order for the name change

Authorization / Authentication

header.user_handle should have the registered handle to be verified.

Apps using Access Token Authorization

Use a valid access token in an Authorization: Bearer request header.

See Authenticating with an Access Token for more details.

Apps using ECDSA Authentication

Both authsignature and usersignature headers are required for this request. The usersignature header should be generated with a keypair registered to the user (either registered from the /register endpoint or the /register_wallet endpoint).

See the section on ECDSA Authentication for more detail about ECDSA signature generation.

End users who failed KYC twice

Sila will restrict to re-requesting KYC after 2 failures. This will stop our customers to send updates & resubmissions for KYC data on failed KYC using /update endpoints. Previously, there was no limit to sending /request_kyc requests after failing KYC. This gives unlimited access to our end-users to send updated information and check KYC updates; We have put up this restriction so that bad actors not to send continually update end-user data and re-attempt KYC.

Note - We recently renamed the field auth_handle to app_handle. For backward compatibility, auth_handle is still valid but has been removed from our documentation.

POST /0.2/request_kyc HTTP/1.1
Content-Type: application/json
Authorization: Bearer [GENERATED JWT TOKEN HERE] //OAuth2 only

  "header": {
    "created": 1234567890, 
    "app_handle": "handle.silamoney.eth", //required
    "user_handle":"user.silamoney.eth", //required
    "version": "0.2", 
    "crypto": "ETH", 
    "reference": "<your unique id>"
  "message": "header_msg",
  "kyc_level": "KYC-STANDARD" //required for Stearns, leave out for all KYB


HTTP/1.1 200 OK

  "reference":"<your unique id>",
  "message":"user submitted for KYC review.",
  "success": true,
  "response_time_ms": "171",
  "verification_uuid": "482d405f-2dc4-4cbc-9f37-13e0dfa8be5a"
// Normal flow - NOTE**, use 'KYC-STANDARD'.  This will result in a `DOCUMENTS REQUIRED` 
// verification status in /check_kyc may pass KYC by uploading a document.
const res = await Sila.requestKYC(userHandle, walletPrivateKey, 'KYC-STANDARD');

// Custom flow
const res = await Sila.requestKYC(userHandle, walletPrivateKey, 'flow_name');

// Success Response Object
console.log(res.statusCode); // 200
console.log(res.data.reference); // Random reference number
console.log(res.data.status); // SUCCESS
console.log(res.data.message); // User submitted for KYC review
### Normal flow - NOTE**, use 'KYC-STANDARD'.  This will result in a `DOCUMENTS REQUIRED` 
### verification status in /check_kyc may pass KYC by uploading a document.

payload = {
    "user_handle": "user.silamoney.eth",    #Required
    "kyc_level": "KYC-STANDARD"

User.requestKyc(silaApp,payload,user_private_key, use_kyc_level=True)

### Custom KYC Request
payload = {
    "user_handle": "user.silamoney.eth",    #Required
    "kyc_level": "CUSTOM_KYC_FLOW_NAME" // pre-approval required

User.requestKyc(silaApp,payload,user_private_key, use_kyc_level=True)

### Success Response Object
    status_code: 200,
    reference: 'ref',
    success: True,
    verification_uuid: '482d405f-2dc4-4cbc-9f37-13e0dfa8be5a',
    status: 'SUCCESS',
    message: 'user submitted for kyc',

### Failure Response Object
    status: 'FAILURE',
    message: 'error',

### ***This sdk never transmits private keys over the network,it is advised to use a secure way for managing user private keys***
// Normal flow - NOTE**, use 'KYC-STANDARD'.  This will result in a `DOCUMENTS REQUIRED` 
// verification status in /check_kyc may pass KYC by uploading a document.

ApiResponse response = api.requestKYC("user handle","KYC-STANDARD","user private key");

//Custom kyc flow
ApiResponse response = api.requestKYC("user handle","custom kyc flow name","user private key");

RequestKycResponse parsedResponse = (RequestKycResponse) response.getData();

// Normal flow - NOTE**, use 'KYC-STANDARD'.  This will result in a `DOCUMENTS REQUIRED` 
// verification status in /check_kyc may pass KYC by uploading a document.

$userHandle = 'user.silamoney.eth';
$userPrivateKey = 'some private key'; // Hex format
$kycLevel = 'KYC-STANDARD';
$response = $client->requestKYC($userHandle, $userPrivateKey, $kycLevel);

// Custom flow
$userHandle = 'user.silamoney.eth';
$userPrivateKey = 'some private key'; // Hex format
$response = $client->requestKYC($userHandle, $userPrivateKey, $kycLevel);

// Success 200
echo $response->getStatusCode(); // 200
echo $response->getData()->reference; // Random reference number
echo $response->getData()->status; // SUCCESS
echo $response->getData()->message; // User submitted for KYC review.
echo $response->getData()->success;
echo $response->getData()->verification_uuid;
ApiResponse<object> response = api.RequestKYC(userHandle, walletPrivateKey, "KYC-STANDARD");

// Custom flow
ApiResponse<object> response = api.RequestKYC(userHandle, walletPrivateKey, "flow_name");

// Success Response Object

Console.WriteLine(response.StatusCode); // 200
Console.WriteLine(((RequestKycResponse)response.Data).Reference); // Random reference number
Console.WriteLine(((RequestKycResponse)response.Data).Status); // SUCCESS
Console.WriteLine(((RequestKycResponse)response.Data).Message); // user submitted for KYC review.
Console.WriteLine(((RequestKycResponse)response.Data).VerificationUuid); // verification uuid.


Mocking KYC Failures in Sandbox - The Unhappy Path

Please refer to the /request_kyc endpoint requirements doc for testing information.


KYB Levels

Unlike with KYC, with KYB the KYC_LEVEL does not need to be specified explicitly by your API request. Instead, KYB levels are applied to the business entity based on the business type.

Request Details

headerJSON objectRequired. Requires these keys in JSON format: created, app_handle, user_handle. See the /check_handle endpoint for the complete list of fields in this object.
kyc_levelStringRequired for Stearns. The kyc_level field is used to request a specific verification flow for an entity. If left empty, KYC-STANDARD will be used.

KYC-STANDARD and KYC-SARDINE-STRICT will provide a DOCUMENTS REQUIRED status in /check_kyc for entities that don't automatically pass, but that could pass KYC by uploading a document.

See our section on KYC/KYB Levels for more details on KYC levels.


Status Codesuccess AttributeDescription
200trueThe verification process for the user registered under header.user_handle has been successfully started.
400falseBad request format - check validation_details for more information.
401falseauthsignature or usersignature header was absent or incorrect.
403falsekyc_level not configured/approved for auth_handle in current environment.
403falseEntity identity has returns for previous entity.