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
| Method | Path | Permission | Page |
|---|---|---|---|
GET | /v2/admin/kyc-tokens | kyc:token:view | List KYC Tokens |
POST | /v2/admin/kyc-tokens | kyc:token:create | Create KYC Token |
KYC groups
| Method | Path | Permission | Page |
|---|---|---|---|
GET | /v2/admin/kycs/{kyc_token_id}/groups | kyc:group:view | List KYC Groups |
GET | /v2/admin/kycs/{kyc_token_id}/groups/{group_id} | kyc:group:view | Get KYC Group by ID |
POST | /v2/admin/kycs/{kyc_token_id}/groups | kyc:group:create | Create KYC Group |
DELETE | /v2/admin/kycs/{kyc_token_id}/groups/{group_id} | kyc:group:delete | Delete KYC Group |
GET | /v2/admin/kycs/{kyc_token_id}/groups/{group_id}/members | kyc:group:view | List KYC Group Members |
POST | /v2/admin/kycs/{kyc_token_id}/groups/{group_id}/members | kyc:group:member:create | Add Member to KYC Group |
POST | /v2/admin/kycs/{kyc_token_id}/groups/{group_id}/members/bulk | kyc:group:member:create | Add Multiple Members to KYC Group |
DELETE | /v2/admin/kycs/{kyc_token_id}/groups/{group_id}/members/{user_address} | kyc:group:member:delete | Remove Member from KYC Group |
Token KYC rules
| Method | Path | Permission | Page |
|---|---|---|---|
GET | /v2/admin/tokens/{token_id}/kyc/addresses | kyc:token:view | List Token KYC Addresses |
GET | /v2/admin/tokens/{token_id}/kyc/addresses/{address_id} | kyc:token:view | Get Token KYC Address |
GET | /v2/admin/nodes/{node_id}/kyc/addresses | kyc:token:view | List Node KYC Addresses |
GET | /v2/admin/tokens/{token_id}/kyc/whitelist | kyc:whitelist:view | Get Token Whitelist |
POST | /v2/admin/tokens/{token_id}/kyc/whitelist | kyc:whitelist:create | Add to Whitelist |
POST | /v2/admin/tokens/{token_id}/kyc/whitelist/bulk | kyc:whitelist:create | Add Multiple to Whitelist |
DELETE | /v2/admin/tokens/{token_id}/kyc/whitelist/{user_address} | kyc:whitelist:delete | Remove from Whitelist |
GET | /v2/admin/tokens/{token_id}/kyc/blacklist | kyc:blacklist:view | Get Token Blacklist |
POST | /v2/admin/tokens/{token_id}/kyc/blacklist | kyc:blacklist:create | Add to Blacklist |
POST | /v2/admin/tokens/{token_id}/kyc/blacklist/bulk | kyc:blacklist:create | Add Multiple to Blacklist |
DELETE | /v2/admin/tokens/{token_id}/kyc/blacklist/{user_address} | kyc:blacklist:delete | Remove from Blacklist |
GET | /v2/admin/tokens/{token_id}/kyc/distribution | kyc:distribution:view | Get Token Distribution Group |
POST | /v2/admin/tokens/{token_id}/kyc/distribution | kyc:distribution:create | Add to Distribution Group |
POST | /v2/admin/tokens/{token_id}/kyc/distribution/bulk | kyc:distribution:create | Add Multiple to Distribution Group |
DELETE | /v2/admin/tokens/{token_id}/kyc/distribution/{user_address} | kyc:distribution:delete | Remove from Distribution Group |
GET | /v2/admin/tokens/{token_id}/kyc/whitelist/groups | kyc:token:whitelist-group:view | List Token Whitelist Groups |
POST | /v2/admin/tokens/{token_id}/kyc/whitelist/groups/{group_id} | kyc:token:whitelist-group:create | Add Token Whitelist Group |
DELETE | /v2/admin/tokens/{token_id}/kyc/whitelist/groups/{group_id} | kyc:token:whitelist-group:delete | Remove Token Whitelist Group |
GET | /v2/admin/tokens/{token_id}/kyc/blacklist/groups | kyc:token:blacklist-group:view | List Token Blacklist Groups |
POST | /v2/admin/tokens/{token_id}/kyc/blacklist/groups/{group_id} | kyc:token:blacklist-group:create | Add Token Blacklist Group |
DELETE | /v2/admin/tokens/{token_id}/kyc/blacklist/groups/{group_id} | kyc:token:blacklist-group:delete | Remove Token Blacklist Group |
Who may call
The permission above is checked at the gateway. The endpoints then check where your node sits:
| Endpoints | Rule | Refusal |
|---|---|---|
GET /v2/admin/kyc-tokens | Any client with the permission | — |
POST /v2/admin/kyc-tokens and every /v2/admin/kycs/... endpoint | Your node must be the platform owner (root) node | 403, code 10005 |
/v2/admin/tokens/{token_id}/kyc/... | Your node must be the token's node or one of its ancestors | 403, code 10005 |
/v2/admin/nodes/{node_id}/kyc/addresses | Your node must be that node or one of its ancestors | 403, 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.
| Operation | type | internal_id |
|---|---|---|
| Create KYC group | 37 | The group's id |
| Delete KYC group | 38 | The group's id |
| Add member to KYC group | 39 | The group's id |
| Remove member from KYC group | 40 | The group's id |
| Add multiple members to KYC group | 41 | The group's id |
| Add to whitelist | 42 | The new rule's id |
| Add multiple to whitelist | 43 | The token's id |
| Remove from whitelist | 44 | The rule's id |
| Add to blacklist | 45 | The new rule's id |
| Add multiple to blacklist | 46 | The token's id |
| Remove from blacklist | 47 | The rule's id |
| Add to distribution group | 48 | The new rule's id |
| Remove from distribution group | 49 | The rule's id |
| Add multiple to distribution group | 50 | The token's id |
| Add token whitelist group | 51 | The attachment's id |
| Remove token whitelist group | 52 | The attachment's id |
| Add token blacklist group | 53 | The attachment's id |
| Remove token blacklist group | 54 | The 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
searchfilter of the token lists and of the group member list, and theaddressfilter of List Token KYC Addresses, match a whole address and ignore letter case. Theaddressfilter 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:
| Code | Domain | Message | Meaning |
|---|---|---|---|
20001001 | 20001 | kyc group not found | No such group, or it lives on another KYC token than the path names |
20001004 | 20001 | invalid kyc token id | kyc_token_id is not a valid id (Create KYC Group) |
20003001 | 20003 | kyc token address not found | The address is not on that list of the token |
20004001 | 20004 | kyc token group not found | The 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).