Smart identity verification
Configure the identity verification compliance module to require verified OnchainID claims for all asset transfers. Build logical expressions combining multiple claim requirements.
This guide explains how to configure the identity verification compliance module when creating an asset via API. This module ensures both sender and recipient wallets have verified OnchainID claims before any transfer can occur.

For the web interface approach, see the compliance overview.
Prerequisites
- Platform URL (e.g.,
https://your-platform.example.com) - API key from a user with the Token Manager role (see Getting Started for API key setup)
- Token factory for your desired asset type must be deployed
- Wallet verification method enabled on your account (pincode or 2FA)
How identity verification works
When you enable the identity verification compliance module on an asset, the blockchain validates every transfer by checking:
- Sender verification - The sending wallet must have an OnchainID with the required claim(s)
- Recipient verification - The receiving wallet must have an OnchainID with the required claim(s)
- Trusted issuer - The claim must be issued by an issuer in the asset's trusted issuer registry
If any check fails, the transfer is rejected on-chain.
Minting is also validated
When minting new units, the recipient wallet must also pass identity verification. Only wallets with valid claims can receive newly minted assets.
Configuration parameters
When configuring the identity verification module during asset creation, you set these parameters:
| Parameter | Type | Description |
|---|---|---|
typeId | string | Must be "identity-verification" |
module | string | Identity verification module contract address (from system query) |
values | array | Expression nodes defining the required claim logic |
Expression nodes
The values array contains expression nodes that define which claims are required. Each node has two fields:
| Field | Type | Description |
|---|---|---|
nodeType | number | Operation type: 0 = TOPIC, 1 = AND, 2 = OR, 3 = NOT |
value | string | For TOPIC nodes: the claim topic ID (BigInt). For operators: "0" |
Understanding expressions
Expressions use infix notation in the API - topics and operators are listed in reading order. For example, "KYC
AND AML" is expressed as: [KYC_TOPIC, AML_TOPIC, AND_OPERATOR]. The system converts this to postfix notation for
on-chain evaluation.
Configuring identity verification during asset creation
Get identity verification module address
Query the system to get the registered identity verification compliance module address:
curl -X GET "https://your-platform.example.com/api/system/default" \
-H "X-Api-Key: YOUR_API_KEY"Response:
{
"complianceModuleRegistry": {
"complianceModules": [
{
"typeId": "identity-verification",
"module": "0x7a2088a1bFc9d81c55368AE168C2C02570cB814F",
"name": "SMART Identity Verification Module"
}
// ... other modules
]
}
}Save the module address for the typeId: "identity-verification" entry.
Choose claim topic IDs
Select the claim topics you want to require. Each topic has a unique ID computed as keccak256(topicName):
Investor-level claims:
| Topic | Topic ID (BigInt) |
|---|---|
knowYourCustomer | 26984799302505749158794800959285050858086405868089409909048783980951278841746 |
antiMoneyLaundering | 66602700950116947137359654609674923607788815289970476259958745144319039408766 |
qualifiedInstitutionalInvestor | 39526553109170329799339511574661256630735485618560740361645615581310848276505 |
professionalInvestor | 82180795564044264154236077867753775185787185513502198122023755895636360079450 |
accreditedInvestor | 15733030998618876990024220391915773205162379317494393310546829862321881862123 |
accreditedInvestorVerified | 59850607985445873266538496619638148123529590973767384129725397368921421733377 |
regulationS | 110498984792486559366779193967170177172527553783122289566437277521370918941833 |
Issuer-level claims:
| Topic | Topic ID (BigInt) |
|---|---|
issuerProspectusFiled | 66024707054635888688268119510009865452443315877106845614779928773130009296293 |
issuerProspectusExempt | 108155241138976356337931447616840292633551902984574900198960811245767215772826 |
issuerLicensed | 4159646717597184831767716799371953881543937679636133282035549426319534456864 |
issuerReportingCompliant | 63974049055435959798075765549996859356159125666706735332156257908409531829710 |
issuerJurisdiction | 22945659622044541592208660721714212954694094425401272022345597464077438219436 |
Asset-level claims:
| Topic | Topic ID (BigInt) |
|---|---|
collateral | 56591694316807385155654796962642700009023257328234168678289712861780104020528 |
uniqueIdentifier | 114741468009595078276449793420639789199829227967433767091939592755701866581418 |
assetClassification | 24450086974696203741514129497527543680077858637075869492686262873957363087146 |
basePrice | 57654513796690178928725925529203455242162418455779606444866766669020006213509 |
assetIssuer | 59193974906477606357781697605998854609236670153591542535032894715512537823578 |
assetLocation | 8432405482680553454773023573904831382358253771058496665012951440405906006611 |
General claims:
| Topic | Topic ID (BigInt) |
|---|---|
contractIdentity | 43841672744129833047570617593608746101743408532017342577134968204499777399068 |
custom | 4204500278131556441620930517354114011833808539324421779944429921463295225973 |
Create asset with identity verification module
Include the identity verification module in the initialModulePairs array when creating your asset.
Example: Require KYC verification
curl -X POST "https://your-platform.example.com/api/token/create" \
-H "X-Api-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"type": "equity",
"name": "KYC Protected Equity",
"symbol": "KYCE",
"decimals": 18,
"countryCode": 840,
"priceCurrency": "USD",
"basePrice": "100",
"initialModulePairs": [
{
"typeId": "identity-verification",
"module": "0x7a2088a1bFc9d81c55368AE168C2C02570cB814F",
"values": [
{
"nodeType": 0,
"value": "26984799302505749158794800959285050858086405868089409909048783980951278841746"
}
]
}
],
"walletVerification": {
"secretVerificationCode": "YOUR_PINCODE",
"verificationType": "PINCODE"
}
}'Response:
{
"id": "0x1234567890AbCdEf1234567890AbCdEf12345678",
"type": "equity",
"createdAt": "2025-01-15T10:30:00.000Z",
"name": "KYC Protected Equity",
"symbol": "KYCE",
"decimals": 18,
"basePrice": "[\"100\",0]",
"basePriceCurrencyCode": "USD",
"totalSupply": "[\"0\",0]",
"pausable": {
"paused": true
}
}The response includes the full asset object with additional fields like identity, accessControl, complianceModuleConfigs, userPermissions, and stats. Note that the asset starts paused by default.
Key fields in initialModulePairs:
| Field | Description |
|---|---|
typeId | Must be "identity-verification" for this module |
module | The identity verification module address from step 1 |
values | Array of expression nodes defining required claims |
values[].nodeType | 0 for claim topics, 1 for AND, 2 for OR, 3 for NOT |
values[].value | Topic ID (BigInt string) for topics, "0" for operators |
Verify configuration
Query the asset to confirm the identity verification module is configured:
curl -X GET "https://your-platform.example.com/api/token/0x1234567890AbCdEf1234567890AbCdEf12345678" \
-H "X-Api-Key: YOUR_API_KEY"Response (relevant fields):
{
"id": "0x1234567890AbCdEf1234567890AbCdEf12345678",
"type": "equity",
"name": "KYC Protected Equity",
"symbol": "KYCE",
"complianceModuleConfigs": [
{
"complianceModule": {
"typeId": "identity-verification",
"module": "0x7a2088a1bFc9d81c55368AE168C2C02570cB814F"
}
}
]
}Confirm that complianceModuleConfigs contains an entry with typeId: "identity-verification".
Expression examples
Single requirement (KYC only)
Require only the knowYourCustomer claim:
{
"values": [
{
"nodeType": 0,
"value": "26984799302505749158794800959285050858086405868089409909048783980951278841746"
}
]
}Combined requirements (KYC AND AML)
Require both knowYourCustomer AND antiMoneyLaundering claims:
{
"values": [
{
"nodeType": 0,
"value": "26984799302505749158794800959285050858086405868089409909048783980951278841746"
},
{
"nodeType": 0,
"value": "66602700950116947137359654609674923607788815289970476259958745144319039408766"
},
{ "nodeType": 1, "value": "0" }
]
}Alternative requirements (KYC OR accreditedInvestor)
Require either knowYourCustomer OR accreditedInvestor claim:
{
"values": [
{
"nodeType": 0,
"value": "26984799302505749158794800959285050858086405868089409909048783980951278841746"
},
{
"nodeType": 0,
"value": "15733030998618876990024220391915773205162379317494393310546829862321881862123"
},
{ "nodeType": 2, "value": "0" }
]
}Complex expression with grouping
Require (KYC AND AML) OR qualifiedInstitutionalInvestor:
{
"values": [
"(",
{
"nodeType": 0,
"value": "26984799302505749158794800959285050858086405868089409909048783980951278841746"
},
{
"nodeType": 0,
"value": "66602700950116947137359654609674923607788815289970476259958745144319039408766"
},
{ "nodeType": 1, "value": "0" },
")",
{
"nodeType": 0,
"value": "39526553109170329799339511574661256630735485618560740361645615581310848276505"
},
{ "nodeType": 2, "value": "0" }
]
}Operator precedence
When building expressions without parentheses, operators follow this precedence (highest to lowest): NOT (3) → AND (2)
→ OR (1). Use parentheses "(" and ")" as array elements to explicitly group operations.
Request parameters
Identity verification module configuration
| Parameter | Type | Required | Description |
|---|---|---|---|
typeId | string | Yes | Must be "identity-verification" |
module | string | Yes | Module contract address (from system query) |
values | array | Yes | Expression nodes array (topics, operators, and optional grouping) |
values[].nodeType | number | Yes | 0 = TOPIC, 1 = AND, 2 = OR, 3 = NOT |
values[].value | string | Yes | Topic ID for TOPIC nodes, "0" for operators |
Wallet verification object
| Field | Type | Description |
|---|---|---|
secretVerificationCode | string | 6-digit pincode or TOTP code |
verificationType | string | "PINCODE" (default), "SECRET_CODES", or "OTP" |
Best practices
Claim selection
- Start with
knowYourCustomerfor basic regulatory compliance - Add
antiMoneyLaunderingfor enhanced due diligence requirements - Use
accreditedInvestororqualifiedInstitutionalInvestorfor securities with investor restrictions - Combine claims with AND for stricter requirements, OR for flexibility
Expression design
- Keep expressions simple when possible - a single topic is often sufficient
- Test complex expressions thoroughly before deploying to production
- Document your expression logic for compliance audits
- Consider using OR with accreditation claims to support different investor types
Trusted issuers
- Ensure claim issuers are registered in the trusted issuer registry
- Verify issuer credentials before adding them to the registry
- Regularly audit trusted issuer permissions
Troubleshooting
| Issue | Solution |
|---|---|
401 Unauthorized | API key is invalid, expired, or disabled |
403 USER_NOT_AUTHORIZED | Ensure your account has tokenManager role |
Module not found | Query /system/default to get the correct module address |
Invalid expression | Verify expression nodes follow the correct format with valid nodeType values |
Invalid topic ID | Verify topic ID matches the keccak256 hash of the claim topic name |
Related guides
- Verify KYC - Issue KYC verifications to users
- Configure Trusted Issuers - Set up issuer permissions