Skip to main content
POST
Puts a wallet on the identity register your instance writes to. Once you confirm the mined transaction, the customer record is created or updated as verified. Nothing is broadcast for you: every call returns what to sign.
investorType must name a preset or one of your verification profiles. Any other value, INSTITUTIONAL, NONE or a number included, is refused with 400 INVALID_INVESTOR_TYPE on both legs, and the message lists the values your instance accepts.
What you sign depends on the register. Every calldata response names it in registerKind.

Body Parameters

string
required
The wallet to register. Checksummed or lowercase. A mixed-case address with a wrong checksum is refused.
string
required
ISO 3166-1 code as alpha-2 (DE), alpha-3 (DEU) or numeric (276). Stored in alpha-3 form. An ERC-3643 register also receives it, as the numeric code.Refused with COUNTRY_BLOCKED when it is on the blocked list of the verification profile named after investorType.
string
default:"RETAIL"
RETAIL, PROFESSIONAL or ELIGIBLE_COUNTERPARTY in any letter case, or the key of one of your custom verification profiles, also in any letter case. A custom key registers with that profile’s on-chain investor type. Omitted, null or an empty string reads as RETAIL. A disabled profile is refused with INVALID_INVESTOR_TYPE on the build call unless the wallet’s customer record is already under it, so a customer of a disabled profile can still be verified again. The confirm call records what was signed. Anything else, a number included, is refused with INVALID_INVESTOR_TYPE.A Trusset register stores the type on chain as 1, 2 or 3. An ERC-3643 register has no investor type, so there it is kept on the customer record only. The record keeps the profile key as the profile spells it, so professional is stored as PROFESSIONAL.
integer
Days until the identity is soft-expired. 0 or omitted sets none. Trusset register only: an ERC-3643 register does not store it.
integer
Days until the identity is hard-expired and stops counting as verified. 0 or omitted sets none. Trusset register only.The API does not check either expiry. A Trusset register reverts the transaction when the soft expiry is not earlier than the hard expiry, or when either lies in the past.
string
The KYC hash to register, as 32-byte hex (0x and 64 hex characters). Stored lowercased. For a KYC proof bundle this is its Merkle root. On an ERC-3643 register it becomes the data of the KYC claim.
object
Data to derive the hash from when kycHash is omitted: the keccak256 of its JSON serialisation. With neither, the hash covers the wallet, the country and the current time, so it changes on every call.
array
ERC-3643 only. The signatures from the SIGN_CLAIMS phase, as [{ walletAddress, signature }]. An entry may add claimType, such as KYC.
string
ERC-3643 only. A single claim signature for walletAddress, instead of claimSignatures.
object
ERC-3643 only. An ONCHAINID you deployed with your own tooling, keyed by wallet: { "<wallet>": "<onchainid>" }. It is used when the register holds no identity for the wallet and the contract answers as an ONCHAINID. Otherwise it is ignored.
string
ERC-3643 only. The wallet that will sign the claim. Refused with CLAIM_SIGNER_NOT_TRUSTED when it holds no claim key on the register’s trusted issuer. Defaults to the first of your instance’s wallets, primary first, that holds one.It also becomes the management key of any ONCHAINID the plan deploys. Name a wallet registered to your instance, because Confirm ONCHAINID refuses any other management key.
string
The hash of the mined transaction. Send it with the same body to confirm. On an ERC-3643 register, send the hash of steps[confirmStepIndex]. Omit it to receive the calldata or the next phase.

Response Fields

object
With neither kycHash nor kycData, each call derives a new hash from the current time. Send the kycHash from the first response on every later call. On an ERC-3643 register this is required: the claim signature covers the hash, and a new hash makes it fail with CLAIM_SIGNER_NOT_TRUSTED.

Verify on a Trusset register

Call once without txHash and send transaction from a wallet that holds KYC_PROVIDER_ROLE on the register. Then send the same body again with txHash added. The endpoint picks updateIdentity when the wallet already holds an identity that is not revoked, expired ones included. It picks verifyIdentity when the wallet has none or was revoked. If the register cannot be read, it falls back to verifyIdentity, which reverts for a wallet that already holds an unrevoked identity. When the wallet already holds an active identity, the calldata calls updateIdentity instead. On the Trusset ID Register, which instances without a register of their own share, that update is refused with 403 IDENTITY_HELD_BY_ANOTHER_ISSUER when the identity was registered by a wallet that is not one of your instance’s and has not expired. Before handing out calldata, the API checks that one of your instance’s wallets holds KYC_PROVIDER_ROLE. It refuses with KYC_PROVIDER_ROLE_MISSING only when it can read every wallet and none holds the role. With no wallet registered, or when the read fails, it lets the call through. The verdict is cached for 60 seconds, so a refusal can outlast a new role grant by up to a minute.

Verify on an ERC-3643 register

Each call answers the next phase. Call again with what the previous phase produced until phase is REGISTER, carrying the same kycHash throughout.
1

Deploy an ONCHAINID (DEPLOY_IDENTITY)

Returned when the wallet has no ONCHAINID. Send each step’s transaction as a contract creation, then confirm each deployment with Confirm ONCHAINID so it is recorded. Confirming a deployment here returns TX_WRONG_TARGET, whatever confirmWith says.You can deploy ahead of time with Deploy ONCHAINID, or pass an ONCHAINID you deployed yourself in identities.
2

Sign the claim (SIGN_CLAIMS)

Sign each messageHash as an EIP-191 personal message over its 32 bytes. Use a wallet that holds a CLAIM key on claimIssuer, such as one in claimSigners. Call again with claimSignatures: [{ walletAddress, signature }].
3

Register (REGISTER)

Send steps in order. The claim step adds the claim to the wallet’s ONCHAINID. The verify step registers a new wallet, and a country step corrects the country of a wallet already on the register. Confirm with the hash of steps[confirmStepIndex].
The API refuses up front with REGISTRY_AGENT_MISSING when none of your instance’s wallets is an agent, and with CLAIM_SIGNER_MISSING when none holds a claim key. It does not check that the agent and signerAddress are the same wallet. An ERC-3643 register stores no investor type and no expiry. investorType reaches the customer record only, and the two expiry fields are not stored anywhere. The ERC-3643 example sends everything from one wallet that is both an agent of the register and a claim signer. Passing its address as signerAddress makes it the management key of any ONCHAINID it deploys, so it can also send the claim step.

Confirm

The confirm leg reads the mined transaction and refuses it before writing anything when:
  • it is not mined, reverted, or is not a register or ONCHAINID write this endpoint confirms (TX_WRONG_TARGET, TX_WRONG_FUNCTION)
  • it targets a different wallet, or an ONCHAINID that is not this wallet’s (TX_TARGET_MISMATCH)
  • on the Trusset ID Register, it was not signed by one of your instance’s verified wallets (UNAUTHORIZED_SIGNER). On your own register the signer is logged, not checked
  • on a Trusset register, the mined investor type differs from this request’s (TX_INVESTOR_TYPE_MISMATCH)
  • on an ERC-3643 register, the register does not yet report the wallet as verified (NOT_VERIFIED_ON_REGISTER)
Then it writes the customer record with country, the profile key investorType resolved to, status: "verified", verifiedAt and the kycHash read from the chain, and records the write in your instance’s verification history as a VERIFY_DIRECT entry with the operation (verify or update), the mined investor type, the transaction and its signer. A reclassification through this endpoint therefore shows in the history like one made in the issuer app. When the profile investorType names has an eligibility register, the wallet’s admission to it is queued for your wallet to sign. See Eligibility registers.
Confirming also settles any pending verification for the same wallet. Its row is marked confirmed with this transaction, so the queue does not ask for the signature again.

Error Codes