SettleMint
Developer guidesCompliance

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.

On-chain identity registry for market participants

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:

  1. Sender verification - The sending wallet must have an OnchainID with the required claim(s)
  2. Recipient verification - The receiving wallet must have an OnchainID with the required claim(s)
  3. 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:

ParameterTypeDescription
typeIdstringMust be "identity-verification"
modulestringIdentity verification module contract address (from system query)
valuesarrayExpression 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:

FieldTypeDescription
nodeTypenumberOperation type: 0 = TOPIC, 1 = AND, 2 = OR, 3 = NOT
valuestringFor 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:

TopicTopic ID (BigInt)
knowYourCustomer26984799302505749158794800959285050858086405868089409909048783980951278841746
antiMoneyLaundering66602700950116947137359654609674923607788815289970476259958745144319039408766
qualifiedInstitutionalInvestor39526553109170329799339511574661256630735485618560740361645615581310848276505
professionalInvestor82180795564044264154236077867753775185787185513502198122023755895636360079450
accreditedInvestor15733030998618876990024220391915773205162379317494393310546829862321881862123
accreditedInvestorVerified59850607985445873266538496619638148123529590973767384129725397368921421733377
regulationS110498984792486559366779193967170177172527553783122289566437277521370918941833

Issuer-level claims:

TopicTopic ID (BigInt)
issuerProspectusFiled66024707054635888688268119510009865452443315877106845614779928773130009296293
issuerProspectusExempt108155241138976356337931447616840292633551902984574900198960811245767215772826
issuerLicensed4159646717597184831767716799371953881543937679636133282035549426319534456864
issuerReportingCompliant63974049055435959798075765549996859356159125666706735332156257908409531829710
issuerJurisdiction22945659622044541592208660721714212954694094425401272022345597464077438219436

Asset-level claims:

TopicTopic ID (BigInt)
collateral56591694316807385155654796962642700009023257328234168678289712861780104020528
uniqueIdentifier114741468009595078276449793420639789199829227967433767091939592755701866581418
assetClassification24450086974696203741514129497527543680077858637075869492686262873957363087146
basePrice57654513796690178928725925529203455242162418455779606444866766669020006213509
assetIssuer59193974906477606357781697605998854609236670153591542535032894715512537823578
assetLocation8432405482680553454773023573904831382358253771058496665012951440405906006611

General claims:

TopicTopic ID (BigInt)
contractIdentity43841672744129833047570617593608746101743408532017342577134968204499777399068
custom4204500278131556441620930517354114011833808539324421779944429921463295225973

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:

FieldDescription
typeIdMust be "identity-verification" for this module
moduleThe identity verification module address from step 1
valuesArray of expression nodes defining required claims
values[].nodeType0 for claim topics, 1 for AND, 2 for OR, 3 for NOT
values[].valueTopic 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

ParameterTypeRequiredDescription
typeIdstringYesMust be "identity-verification"
modulestringYesModule contract address (from system query)
valuesarrayYesExpression nodes array (topics, operators, and optional grouping)
values[].nodeTypenumberYes0 = TOPIC, 1 = AND, 2 = OR, 3 = NOT
values[].valuestringYesTopic ID for TOPIC nodes, "0" for operators

Wallet verification object

FieldTypeDescription
secretVerificationCodestring6-digit pincode or TOTP code
verificationTypestring"PINCODE" (default), "SECRET_CODES", or "OTP"

Best practices

Claim selection

  • Start with knowYourCustomer for basic regulatory compliance
  • Add antiMoneyLaundering for enhanced due diligence requirements
  • Use accreditedInvestor or qualifiedInstitutionalInvestor for 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

IssueSolution
401 UnauthorizedAPI key is invalid, expired, or disabled
403 USER_NOT_AUTHORIZEDEnsure your account has tokenManager role
Module not foundQuery /system/default to get the correct module address
Invalid expressionVerify expression nodes follow the correct format with valid nodeType values
Invalid topic IDVerify topic ID matches the keccak256 hash of the claim topic name

On this page