Attest a User

Verify identity and issue on-chain attestations

View as Markdown

This guide walks you through the end-to-end attestation flow — initiating KYC verification, creating an on-chain attestation, and verifying it.

Prerequisites

  • An organization with chains enabled (Onboard an Organization)
  • A user with a linked wallet
  • An API key with attestations:read and attestations:write scopes

1. Install and authenticate

client.ts
1import { SignumClient } from "@signum-tech/sdk";
2
3const signum = new SignumClient({
4 apiKey: process.env.SIGNUM_API_KEY,
5});

2. Initiate KYC verification

Start the identity verification flow by selecting a verification level. The four levels are: basic, standard, enhanced, and institutional.

initiate-kyc.ts
1const kyc = await signum.kyc.initiate({
2 level: "standard",
3 userInfo: {
4 email: "investor@example.com",
5 firstName: "Jane",
6 lastName: "Smith",
7 country: "US",
8 },
9});
10
11// kyc contains the provider URL/token for the verification flow
12console.log(kyc);

The API returns 200 with the provider URL or token. Redirect the user to complete the verification flow with the KYC provider.

3. Check KYC status

Poll the KYC status endpoint until verification completes:

check-kyc-status.ts
1async function waitForKyc(): Promise<void> {
2 const maxAttempts = 30;
3 const intervalMs = 3000;
4
5 for (let i = 0; i < maxAttempts; i++) {
6 const status = await signum.kyc.getStatus();
7
8 if (status.status === "approved") {
9 console.log("KYC verification complete");
10 return;
11 }
12
13 if (status.status === "rejected") {
14 throw new Error("KYC verification rejected");
15 }
16
17 await new Promise((r) => setTimeout(r, intervalMs));
18 }
19
20 throw new Error("KYC verification timed out");
21}

4. Create attestation (self-service path)

Once the user is verified, create an on-chain attestation. This is the self-service path where the authenticated user attests their own wallet.

create-attestation.ts
1const result = await signum.attestations.create({
2 walletAddress: "0xabc...def",
3 chainEid: 30101,
4});
5
6console.log(result.accepted); // true
7console.log(result.attestationId); // "att_xyz789"
8console.log(result.status); // "pending"
9console.log(result.message); // Guidance on polling for completion

The API returns 202 Accepted — the attestation is queued for on-chain settlement. The kycLevel defaults to the user’s verified level. You can also pass optional fields:

FieldTypeDescription
walletAddressstringWallet address to attest (required)
chainEidnumberLayerZero Endpoint ID of the target chain (required)
kycLevelnumberKYC level 0-4 (defaults to user’s verified level)
countryCodestringISO 3166-1 alpha-2 country code
expiresAtstringAttestation expiry (ISO 8601)
sanctionsClearbooleanSanctions clearance status
isAccreditedbooleanAccredited investor flag
riskScorenumberRisk score (0-100)

5. Create attestation (org-initiated path)

Organizations can attest members on their behalf. This is useful for institutional onboarding where the org has completed KYC outside of Clossir.

org-attest.ts
1const result = await signum.orgs.members.attest(org.id, userId, {
2 kycLevel: 2,
3 countryCode: "US",
4 reason: "Bank onboarding KYC complete",
5});
6
7console.log(result.accepted); // true
8console.log(result.attestations); // Array of created attestations
9console.log(result.message);

The API returns 202 Accepted. Omitting walletAddresses attests all wallets linked to the user. Omitting chainEid attests on all chains where the user has wallets.

The self-service path (step 4) requires the user to have completed KYC at the requested level. The org-initiated path lets you attest members whose identity was verified outside of Clossir — for example, through your existing institutional KYC process.

6. Verify an attestation

Verify the cryptographic integrity of an attestation by checking its hash:

verify.ts
1const verification = await signum.attestations.verify(attestationId);
2
3console.log(verification); // Hash verification result

7. Listen for events

Three attestation event channels notify you of lifecycle changes:

ChannelFires when
signum.attestation.createdA new attestation is issued
signum.attestation.revokedAn attestation is revoked
signum.attestation.sync_completedA cross-chain sync completes (success or failure)

See Subscribe to Webhooks for how to receive these events, or browse the full payload schemas in the API Reference.

Reference

Next steps