KYC Proofs
Add Claim
File a claim into one of the four assignable slots
POST
/
customers
/
api
/
identity
/
add-claim
curl -X POST "https://api.trusset.org/customers/api/identity/add-claim" \
-H "X-API-Key: trusset_your_key_here" \
-H "Content-Type: application/json" \
-d '{
"walletAddress": "0xabCDeF0123456789AbcdEf0123456789aBCDEF01",
"claimType": "SANCTIONS_CHECK",
"dataInput": "screened-2026-09-06-clear",
"expiryDays": 90
}'
const url = 'https://api.trusset.org/customers/api/identity/add-claim';
const headers = { 'X-API-Key': 'trusset_your_key_here', 'Content-Type': 'application/json' };
const body = {
walletAddress: '0xabCDeF0123456789AbcdEf0123456789aBCDEF01',
claimType: 'SANCTIONS_CHECK',
dataInput: 'screened-2026-09-06-clear',
expiryDays: 90
};
const { data } = await fetch(url, { method: 'POST', headers, body: JSON.stringify(body) }).then(r => r.json());
const tx = await signer.sendTransaction(data.transaction);
await tx.wait();
const confirmed = await fetch(url, {
method: 'POST',
headers,
body: JSON.stringify({ ...body, txHash: tx.hash })
}).then(r => r.json());
{
"success": true,
"data": {
"action": "SIGN_TRANSACTION",
"transaction": { "to": "0xEf244c4Bd4d71Bd9A30EDF6Edef7CCC72642291a", "data": "0x..." },
"functionName": "addClaim",
"description": "Add SANCTIONS_CHECK claim for 0xabCDeF0123456789AbcdEf0123456789aBCDEF01",
"registerKind": "TRUSSET",
"walletAddress": "0xabCDeF0123456789AbcdEf0123456789aBCDEF01",
"claimType": "SANCTIONS_CHECK",
"dataHash": "0x365036c53705a570a416a0e41030d84e9a1fd21928878bb7bddef2f372d7bd54",
"expiry": 1796472000,
"confirmWith": {
"endpoint": "POST /customers/api/identity/add-claim",
"field": "txHash"
}
},
"error": null,
"metadata": {
"requestId": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-09-06T12:00:00.000Z"
}
}
{
"success": true,
"data": {
"walletAddress": "0xabCDeF0123456789AbcdEf0123456789aBCDEF01",
"claimType": "SANCTIONS_CHECK",
"dataHash": "0x365036c53705a570a416a0e41030d84e9a1fd21928878bb7bddef2f372d7bd54",
"expiry": 1796472000,
"txHash": "0x6e2b9d41c07a35f8e1d4b20c9a7f63e5d8c1b0a4f7e2d9c6b3a0f5e8d1c4b7a2",
"gasUsed": "74388"
},
"error": null,
"metadata": {
"requestId": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-09-06T12:00:00.000Z"
}
}
{
"success": false,
"data": null,
"error": {
"code": "PROOF_REQUIRED",
"message": "This claim type must be added from a KYC proof; use /claims/from-proof"
},
"metadata": {
"requestId": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-09-06T12:00:00.000Z"
}
}
Writes a claim to the registry from a hash you supply. It covers the four slots that are not backed by a proof.
The registry keeps one claim per slot. Filing a slot replaces the claim already there, whoever wrote it. The API does not check that the wallet holds an active identity, and the register reverts
addClaim for one that does not.KYC, ACCREDITATION, RESIDENCY and CITIZENSHIP are refused here with PROOF_REQUIRED. Those four slots are reserved on this API for claims filed from a proof bundle. File them with Add Claims from Proof or Attest Proofs. The one exception is the RESIDENCY claim that Build Pending Registration files with a queued approval.The register does not enforce the reservation. A wallet holding KYC_PROVIDER_ROLE can write any slot by calling the register directly.Body Parameters
string
required
The subject.
string | integer
required
One of
AML, TAX_RESIDENCY, SANCTIONS_CHECK, PEP_CHECK, by name or index.string
The claim’s payload as a 32-byte hex hash,
0x and 64 hex characters. What it commits to is your convention. When both fields are sent, a valid dataHash wins.string
A string to derive the hash from instead. The hash is
keccak256 over the UTF-8 JSON {"claimType":"<name>","data":"<input>","wallet":"<wallet>"}, with the input trimmed and the wallet lowercased. The same input under a different slot or subject therefore gives a different hash.Supply this or dataHash.integer
Days until the claim expires, between 0 and 36500.
0 or omitted means no expiry.string
Send it to confirm. Omit it to receive the calldata.
string
ERC-3643 register only. The EIP-191 signature over the
messageHash from a SIGN_MESSAGES answer, as 65-byte hex.string
ERC-3643 register only. The instance wallet that signs the claim. It must hold a CLAIM key on the register’s trusted issuer.
Sign and confirm
On the Trusset register the calldata callsaddClaim on the register, which needs a wallet holding KYC_PROVIDER_ROLE. Before handing it out, the API checks that one of your instance’s registered wallets holds that role, and refuses with KYC_PROVIDER_ROLE_MISSING otherwise. It skips the check when the instance has no registered wallet or the role cannot be read. On the Trusset ID Register, which instances without a register of their own share, it also refuses with 403 IDENTITY_HELD_BY_ANOTHER_ISSUER when the wallet’s identity was registered by a wallet that is not one of your instance’s, and with 409 IDENTITY_NOT_REGISTERED when the wallet holds no active identity, which the register would refuse.
The confirm leg requires a mined, successful addClaim on this instance’s register that targets this wallet. It reads the slot, hash and expiry back out of the transaction and reports them, rather than comparing them with your request. On the Trusset ID Register the transaction must be signed by a verified wallet of your instance (UNAUTHORIZED_SIGNER otherwise). It records the claim once in your instance’s verification history as an ADD_CLAIM entry with the claim type, hash, expiry, transaction and signer; confirming the same txHash again writes no second entry.
On an ERC-3643 register
When the instance is bound to an ERC-3643 register, the claim is written to the subject’s ONCHAINID. It needs a signature from a CLAIM key on the register’s trusted issuer.- The first call answers
SIGN_MESSAGES. Sign themessageHashinmessagesas an EIP-191 personal message with a wallet that holds a CLAIM key onclaimIssuer. - Call again with
claimSignature. The answer isSIGN_TRANSACTIONS, with oneaddClaimstep addressed to the ONCHAINID. - Broadcast it and confirm with
txHash.
NOT_REGISTERED. Deploy one first with POST /customers/api/identity/onchainid and confirm it, so it is recorded. The claim carries no expiry, so expiryDays is not written and the confirm leg reports expiry: 0. The role check becomes an agent check on the register.
| Code | HTTP | Cause |
|---|---|---|
INVALID_CLAIM_SIGNATURE | 400 | The signature is not 65-byte hex, or does not recover for this identity, topic and data |
REGISTRY_AGENT_MISSING | 403 | None of your instance’s wallets is an agent of the register |
CLAIM_SIGNER_MISSING | 403 | None of your instance’s wallets holds a CLAIM key on the register’s trusted issuer |
CLAIM_SIGNER_NOT_TRUSTED | 403 | signerAddress, or the wallet the signature recovers to, holds no CLAIM key on the trusted issuer |
NOT_REGISTERED | 409 | The wallet has no ONCHAINID yet |
REGISTRY_NO_CLAIM_TOPICS | 409 | The register requires no claim topics, so there is nothing to file |
REGISTRY_NO_TRUSTED_ISSUER | 409 | The register names no trusted issuer for its claim topic |
CHAIN_UNAVAILABLE | 503 | The confirmed transaction could not be read |
Response Fields
object
Show child attributes
Show child attributes
string
SIGN_TRANSACTION. On an ERC-3643 register, SIGN_MESSAGES and then SIGN_TRANSACTIONS. Calldata leg only.object
The unsigned registry call. Trusset register, calldata leg only.
string
addClaim. Trusset register, calldata leg only.string
TRUSSET or TREX. Calldata leg only.array
ERC-3643 register only: the claim message to sign, with
messageHash, claimType, identity, topic and claimIssuer.array
ERC-3643 register only: the
addClaim transaction to the ONCHAINID, once the signature is in.string
The subject, checksummed.
string
The slot, by name. On the confirm leg it is read back from the mined transaction, not echoed.
string
The hash written, lowercased. On the confirm leg it is read back from the mined transaction.
integer
Unix seconds, or
0. On the confirm leg it is read back from the mined transaction.string
The confirmed transaction. Confirm leg only.
string
Gas used. Confirm leg only.
object
{ endpoint, field: "txHash" }. Calldata leg only.curl -X POST "https://api.trusset.org/customers/api/identity/add-claim" \
-H "X-API-Key: trusset_your_key_here" \
-H "Content-Type: application/json" \
-d '{
"walletAddress": "0xabCDeF0123456789AbcdEf0123456789aBCDEF01",
"claimType": "SANCTIONS_CHECK",
"dataInput": "screened-2026-09-06-clear",
"expiryDays": 90
}'
const url = 'https://api.trusset.org/customers/api/identity/add-claim';
const headers = { 'X-API-Key': 'trusset_your_key_here', 'Content-Type': 'application/json' };
const body = {
walletAddress: '0xabCDeF0123456789AbcdEf0123456789aBCDEF01',
claimType: 'SANCTIONS_CHECK',
dataInput: 'screened-2026-09-06-clear',
expiryDays: 90
};
const { data } = await fetch(url, { method: 'POST', headers, body: JSON.stringify(body) }).then(r => r.json());
const tx = await signer.sendTransaction(data.transaction);
await tx.wait();
const confirmed = await fetch(url, {
method: 'POST',
headers,
body: JSON.stringify({ ...body, txHash: tx.hash })
}).then(r => r.json());
{
"success": true,
"data": {
"action": "SIGN_TRANSACTION",
"transaction": { "to": "0xEf244c4Bd4d71Bd9A30EDF6Edef7CCC72642291a", "data": "0x..." },
"functionName": "addClaim",
"description": "Add SANCTIONS_CHECK claim for 0xabCDeF0123456789AbcdEf0123456789aBCDEF01",
"registerKind": "TRUSSET",
"walletAddress": "0xabCDeF0123456789AbcdEf0123456789aBCDEF01",
"claimType": "SANCTIONS_CHECK",
"dataHash": "0x365036c53705a570a416a0e41030d84e9a1fd21928878bb7bddef2f372d7bd54",
"expiry": 1796472000,
"confirmWith": {
"endpoint": "POST /customers/api/identity/add-claim",
"field": "txHash"
}
},
"error": null,
"metadata": {
"requestId": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-09-06T12:00:00.000Z"
}
}
{
"success": true,
"data": {
"walletAddress": "0xabCDeF0123456789AbcdEf0123456789aBCDEF01",
"claimType": "SANCTIONS_CHECK",
"dataHash": "0x365036c53705a570a416a0e41030d84e9a1fd21928878bb7bddef2f372d7bd54",
"expiry": 1796472000,
"txHash": "0x6e2b9d41c07a35f8e1d4b20c9a7f63e5d8c1b0a4f7e2d9c6b3a0f5e8d1c4b7a2",
"gasUsed": "74388"
},
"error": null,
"metadata": {
"requestId": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-09-06T12:00:00.000Z"
}
}
{
"success": false,
"data": null,
"error": {
"code": "PROOF_REQUIRED",
"message": "This claim type must be added from a KYC proof; use /claims/from-proof"
},
"metadata": {
"requestId": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-09-06T12:00:00.000Z"
}
}
Error Codes
| Code | HTTP | Cause |
|---|---|---|
INVALID_ADDRESS | 400 | walletAddress is missing or malformed |
INVALID_CLAIM_TYPE | 400 | claimType is not a slot name or an index from 0 to 7 |
PROOF_REQUIRED | 400 | One of the four reserved slots was named |
INVALID_HASH | 400 | Neither a valid dataHash nor a non-empty dataInput was supplied |
INVALID_EXPIRY | 400 | expiryDays is outside 0 to 36500 |
INVALID_TX | 400 | txHash is not a 32-byte hex hash |
TX_REVERTED | 400 | The transaction reverted |
TX_WRONG_TARGET | 400 | The transaction was not sent to this instance’s register |
TX_WRONG_FUNCTION | 400 | The transaction does not call addClaim |
TX_TARGET_MISMATCH | 400 | The confirmed transaction targets a different wallet |
KYC_PROVIDER_ROLE_MISSING | 403 | None of your instance’s wallets holds KYC_PROVIDER_ROLE on the register. Calldata leg only |
IDENTITY_HELD_BY_ANOTHER_ISSUER | 403 | Trusset ID Register: the identity was registered by a wallet that is not one of your instance’s. Calldata leg only |
IDENTITY_NOT_REGISTERED | 409 | Trusset ID Register: the wallet holds no active identity to add a claim to. Calldata leg only |
UNAUTHORIZED_SIGNER | 403 | Trusset ID Register, confirm leg: the transaction was not signed by a verified wallet of your instance |
TX_NOT_FOUND | 404 | The transaction is not mined yet |
OWN_REGISTRY_NOT_CONFIGURED | 409 | The instance is bound to its own register but has no valid register address |
REGISTRY_PROBE_FAILED | 503 | The instance’s own register, or its trusted issuer, could not be read |
ADD_CLAIM_FAILED | 400 or 500 | A chain call failed (400), or the request failed unexpectedly (500) |
⌘I
curl -X POST "https://api.trusset.org/customers/api/identity/add-claim" \
-H "X-API-Key: trusset_your_key_here" \
-H "Content-Type: application/json" \
-d '{
"walletAddress": "0xabCDeF0123456789AbcdEf0123456789aBCDEF01",
"claimType": "SANCTIONS_CHECK",
"dataInput": "screened-2026-09-06-clear",
"expiryDays": 90
}'
const url = 'https://api.trusset.org/customers/api/identity/add-claim';
const headers = { 'X-API-Key': 'trusset_your_key_here', 'Content-Type': 'application/json' };
const body = {
walletAddress: '0xabCDeF0123456789AbcdEf0123456789aBCDEF01',
claimType: 'SANCTIONS_CHECK',
dataInput: 'screened-2026-09-06-clear',
expiryDays: 90
};
const { data } = await fetch(url, { method: 'POST', headers, body: JSON.stringify(body) }).then(r => r.json());
const tx = await signer.sendTransaction(data.transaction);
await tx.wait();
const confirmed = await fetch(url, {
method: 'POST',
headers,
body: JSON.stringify({ ...body, txHash: tx.hash })
}).then(r => r.json());
{
"success": true,
"data": {
"action": "SIGN_TRANSACTION",
"transaction": { "to": "0xEf244c4Bd4d71Bd9A30EDF6Edef7CCC72642291a", "data": "0x..." },
"functionName": "addClaim",
"description": "Add SANCTIONS_CHECK claim for 0xabCDeF0123456789AbcdEf0123456789aBCDEF01",
"registerKind": "TRUSSET",
"walletAddress": "0xabCDeF0123456789AbcdEf0123456789aBCDEF01",
"claimType": "SANCTIONS_CHECK",
"dataHash": "0x365036c53705a570a416a0e41030d84e9a1fd21928878bb7bddef2f372d7bd54",
"expiry": 1796472000,
"confirmWith": {
"endpoint": "POST /customers/api/identity/add-claim",
"field": "txHash"
}
},
"error": null,
"metadata": {
"requestId": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-09-06T12:00:00.000Z"
}
}
{
"success": true,
"data": {
"walletAddress": "0xabCDeF0123456789AbcdEf0123456789aBCDEF01",
"claimType": "SANCTIONS_CHECK",
"dataHash": "0x365036c53705a570a416a0e41030d84e9a1fd21928878bb7bddef2f372d7bd54",
"expiry": 1796472000,
"txHash": "0x6e2b9d41c07a35f8e1d4b20c9a7f63e5d8c1b0a4f7e2d9c6b3a0f5e8d1c4b7a2",
"gasUsed": "74388"
},
"error": null,
"metadata": {
"requestId": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-09-06T12:00:00.000Z"
}
}
{
"success": false,
"data": null,
"error": {
"code": "PROOF_REQUIRED",
"message": "This claim type must be added from a KYC proof; use /claims/from-proof"
},
"metadata": {
"requestId": "550e8400-e29b-41d4-a716-446655440000",
"timestamp": "2026-09-06T12:00:00.000Z"
}
}
