Skip to main content

KYC API Overview

KYC on the partner API has three layers: the platform's KYC tokens, KYC groups that live on a KYC token, and each asset token's KYC rules. Each layer has its own endpoints and its own access rule, and setups tie them together.

The model​

KYC tokens. A KYC token is a platform-level contract, deployed on one network, that marks wallets as KYC-approved. It is a standalone on-chain entity (a UUPS implementation behind an ERC1967 proxy) with its own registry, not part of a node's setup. A network can host several KYC tokens. Each token has an owner wallet (wallet_id), one of the platform owner node's wallets on that network's chain: it signs the deploy and every group change and token rule written on the token. Only the platform owner (root) node creates KYC tokens; the catalog is readable by any client with kyc:token:view.

A setup picks one KYC token. A setup (one deployment of a node on one network) is wired to exactly one KYC token, named with kyc_token_id when the setup is created; when none is named, the network's oldest deployed KYC token is used. The setup's kyc_token_id and kyc_token_address say which token it uses. A network with no deployed KYC token cannot host a setup, because a setup's contracts are deployed with a KYC token address. An asset token is bound to one setup (the token's setup_id).

KYC groups belong to a KYC token. A group is a named set of addresses that lives on one KYC token, so its endpoints nest under that token: /v2/admin/kycs/{kyc_token_id}/groups/.... Groups are platform-level: only the platform owner node may list, read, create or delete them or change their members. A group has two identifiers: id (24-character hex), which every path and every token rule uses, and group_id, the number that identifies the group on chain.

A token's KYC rules reference addresses and groups. Each asset token has, on the KYC token of its setup:

  • a whitelist, a blacklist and a distribution group of individual addresses;
  • KYC groups attached to its whitelist or its blacklist.

They live under /v2/admin/tokens/{token_id}/kyc/.... Every write takes a setup_id: pass the token's own setup_id (from Get Token). The call runs on the KYC token that setup is wired to and is signed by that KYC token's owner wallet. Attach only groups that live on that same KYC token: the chain identifies a group by its group_id on the token, and the API does not check where the group lives.

Endpoints​

KYC tokens​

MethodPathPermissionPage
GET/v2/admin/kyc-tokenskyc:token:viewList KYC Tokens
POST/v2/admin/kyc-tokenskyc:token:createCreate KYC Token

KYC groups​

MethodPathPermissionPage
GET/v2/admin/kycs/{kyc_token_id}/groupskyc:group:viewList KYC Groups
GET/v2/admin/kycs/{kyc_token_id}/groups/{group_id}kyc:group:viewGet KYC Group by ID
POST/v2/admin/kycs/{kyc_token_id}/groupskyc:group:createCreate KYC Group
DELETE/v2/admin/kycs/{kyc_token_id}/groups/{group_id}kyc:group:deleteDelete KYC Group
GET/v2/admin/kycs/{kyc_token_id}/groups/{group_id}/memberskyc:group:viewList KYC Group Members
POST/v2/admin/kycs/{kyc_token_id}/groups/{group_id}/memberskyc:group:member:createAdd Member to KYC Group
POST/v2/admin/kycs/{kyc_token_id}/groups/{group_id}/members/bulkkyc:group:member:createAdd Multiple Members to KYC Group
DELETE/v2/admin/kycs/{kyc_token_id}/groups/{group_id}/members/{user_address}kyc:group:member:deleteRemove Member from KYC Group

Token KYC rules​

MethodPathPermissionPage
GET/v2/admin/tokens/{token_id}/kyc/addresseskyc:token:viewList Token KYC Addresses
GET/v2/admin/tokens/{token_id}/kyc/addresses/{address_id}kyc:token:viewGet Token KYC Address
GET/v2/admin/nodes/{node_id}/kyc/addresseskyc:token:viewList Node KYC Addresses
GET/v2/admin/tokens/{token_id}/kyc/whitelistkyc:whitelist:viewGet Token Whitelist
POST/v2/admin/tokens/{token_id}/kyc/whitelistkyc:whitelist:createAdd to Whitelist
POST/v2/admin/tokens/{token_id}/kyc/whitelist/bulkkyc:whitelist:createAdd Multiple to Whitelist
DELETE/v2/admin/tokens/{token_id}/kyc/whitelist/{user_address}kyc:whitelist:deleteRemove from Whitelist
GET/v2/admin/tokens/{token_id}/kyc/blacklistkyc:blacklist:viewGet Token Blacklist
POST/v2/admin/tokens/{token_id}/kyc/blacklistkyc:blacklist:createAdd to Blacklist
POST/v2/admin/tokens/{token_id}/kyc/blacklist/bulkkyc:blacklist:createAdd Multiple to Blacklist
DELETE/v2/admin/tokens/{token_id}/kyc/blacklist/{user_address}kyc:blacklist:deleteRemove from Blacklist
GET/v2/admin/tokens/{token_id}/kyc/distributionkyc:distribution:viewGet Token Distribution Group
POST/v2/admin/tokens/{token_id}/kyc/distributionkyc:distribution:createAdd to Distribution Group
POST/v2/admin/tokens/{token_id}/kyc/distribution/bulkkyc:distribution:createAdd Multiple to Distribution Group
DELETE/v2/admin/tokens/{token_id}/kyc/distribution/{user_address}kyc:distribution:deleteRemove from Distribution Group
GET/v2/admin/tokens/{token_id}/kyc/whitelist/groupskyc:token:whitelist-group:viewList Token Whitelist Groups
POST/v2/admin/tokens/{token_id}/kyc/whitelist/groups/{group_id}kyc:token:whitelist-group:createAdd Token Whitelist Group
DELETE/v2/admin/tokens/{token_id}/kyc/whitelist/groups/{group_id}kyc:token:whitelist-group:deleteRemove Token Whitelist Group
GET/v2/admin/tokens/{token_id}/kyc/blacklist/groupskyc:token:blacklist-group:viewList Token Blacklist Groups
POST/v2/admin/tokens/{token_id}/kyc/blacklist/groups/{group_id}kyc:token:blacklist-group:createAdd Token Blacklist Group
DELETE/v2/admin/tokens/{token_id}/kyc/blacklist/groups/{group_id}kyc:token:blacklist-group:deleteRemove Token Blacklist Group

Who may call​

The permission above is checked at the gateway. The endpoints then check where your node sits:

EndpointsRuleRefusal
GET /v2/admin/kyc-tokensAny client with the permission—
POST /v2/admin/kyc-tokens and every /v2/admin/kycs/... endpointYour node must be the platform owner (root) node403, code 10005
/v2/admin/tokens/{token_id}/kyc/...Your node must be the token's node or one of its ancestors403, code 10005
/v2/admin/nodes/{node_id}/kyc/addressesYour node must be that node or one of its ancestors403, code 10005

Asynchronous writes​

Every write is an on-chain operation that settles after the response.

Creating a KYC token answers 201 with the token in status deploying. The deploy runs in two on-chain steps (implementation, then proxy). Poll List KYC Tokens, which lists deployed tokens only, until the token appears with its address.

Every other write answers with:

{
"requires_approval": false,
"completed": true
}

completed: true means the request was accepted and the on-chain call queued, not that the chain has confirmed it. requires_approval is always false: KYC writes have no approval step.

The call is recorded as a node transaction on the platform owner (root) node, whichever node owns the token, with the type and internal_id below. Its status is 1 started, 2 in progress, 3 done, 4 error (the reason is in error) or 5 waiting for the receipt. A client whose node is the platform root can follow it with List Node Transactions for the root node, filtered by types and internal_id. Other nodes cannot read the root node's transactions; they see only the effect in the list reads.

Operationtypeinternal_id
Create KYC group37The group's id
Delete KYC group38The group's id
Add member to KYC group39The group's id
Remove member from KYC group40The group's id
Add multiple members to KYC group41The group's id
Add to whitelist42The new rule's id
Add multiple to whitelist43The token's id
Remove from whitelist44The rule's id
Add to blacklist45The new rule's id
Add multiple to blacklist46The token's id
Remove from blacklist47The rule's id
Add to distribution group48The new rule's id
Remove from distribution group49The rule's id
Add multiple to distribution group50The token's id
Add token whitelist group51The attachment's id
Remove token whitelist group52The attachment's id
Add token blacklist group53The attachment's id
Remove token blacklist group54The attachment's id

A rule's id comes from the token's list reads; an attachment's id from List Token Whitelist Groups or List Token Blacklist Groups.

The list reads show the platform's record, not the chain:

  • An add (group, member, address, group attachment) writes its row at once. The row shows up in the lists before the chain confirms, and it stays there if the transaction ends in error. A row in a list is not proof that the rule is on chain; the transaction is.
  • A remove or delete takes the row out of the lists only once its transaction is confirmed.

Addresses​

  • Addresses are stored exactly as sent. The API does not check their format and does not normalise their letter case.
  • A remove matches the stored address exactly, letter case included. Copy the address from the list read.
  • The search filter of the token lists and of the group member list, and the address filter of List Token KYC Addresses, match a whole address and ignore letter case. The address filter of List Node KYC Addresses matches part of an address.
  • Adding an address or a group that is already on the list fails with 500 / 10000. A bulk add containing one such address adds nothing.

Errors​

See Errors for the error format and the common codes. The KYC codes are:

CodeDomainMessageMeaning
2000100120001kyc group not foundNo such group, or it lives on another KYC token than the path names
2000100420001invalid kyc token idkyc_token_id is not a valid id (Create KYC Group)
2000300120003kyc token address not foundThe address is not on that list of the token
2000400120004kyc token group not foundThe group is not attached to that list of the token

These codes carry no specific HTTP status and are answered with 400. Node access refusals are 403 with code 10005 (domain 2).