Skip to Content
Building with PassportIndividual VerificationsMajor ConceptsAttestation Protocols

Attestation Protocols

For a simpler integration, use the Individual Verifications API which provides convenient endpoints that handle attestation queries for you.

Individual Verifications issue attestations through Sign Protocol , allowing you to query and validate verification status directly on-chain. This page covers the attestation schemas, how to query them, and how to validate the data.

Sign Protocol Overview

Every Individual Verification (Government ID, Phone, Biometrics, Clean Hands) issues a Sign Protocol attestation when a user completes verification. These attestations are stored on-chain and can be queried by any application.

Key Addresses

ComponentAddress
Attester (Relayer)0xB1f50c6C34C72346b1229e5C80587D0D659556Fd

Schema IDs by Network

EnvironmentSchema IDNetworkChain ID
Productiononchain_evm_10_0x1Optimism10
Productiononchain_evm_10_0x8Base8453
Sandboxonchain_evm_11155420_0xc41Optimism Sepolia11155420

API Endpoints

EnvironmentEndpoint
Productionhttps://mainnet-rpc.sign.global/api/index/attestations
Sandboxhttps://testnet-rpc.sign.global/api/index/attestations

Attestation Schema

Individual Verification attestations contain a ZK proof that encodes the verification type, action ID, and issuer information.

Raw Schema

string circuitId, uint256[] publicValues

Fields

FieldTypeDescription
circuitIdstringIdentifies the verification type (see Circuit IDs below)
publicValuesuint256[]Array of public values from the ZK proof

Public Values Array

The publicValues array contains the following elements:

IndexFieldDescription
0nullifierHashUnique identifier preventing duplicate verifications
1signedCredentialHashHash of the signed credential
2actionIdThe action ID used for sybil resistance
3expiresAtUnix timestamp when the verification expires
4issuerAddress of the credential issuer
5recipientAddress that received the attestation

Circuit IDs

Each verification type has a unique circuit ID that identifies what kind of verification the attestation represents.

Verification TypeCircuit ID
Government ID (KYC)0x729d660e1c02e4e419745e617d643f897a538673ccf1051e093bbfa58b0a120b
Phone0xbce052cf723dca06a21bd3cf838bc518931730fb3db7859fc9cc86f0d5483495
Biometrics0x0b5121226395e3b6c76eb8ddfb0bf2f2075e7f2c6956567e84b38a223c3a3d15

Issuer Addresses

Each verification type has an associated issuer address that must be validated.

Production Issuers

Verification TypeIssuer Address
Government ID (KYC)0x03fae82f38bf01d9799d57fdda64fad4ac44e4c2c2f16c5bf8e1873d0a3e1993
Phone0x40b8810cbaed9647b54d18cc98b720e1e8876be5d8e7089d3c079fc61c30a4
Biometrics0x0d4f849df782fb9e68d525fbda10b73e59180e59cb2a21ce5d70ccc45dbfd922

Sandbox Issuers

Verification TypeIssuer Address
Government ID (KYC)0x2332221496ffef62c0075ce833b54c5c0b78419be2571e8d1715f7990fc5279a
Phone0x1c0288e0fbbab4e1dda4732a72b391e9616d88c5d1fcfb97124584f2506645c3

Querying Attestations

Query by Schema and Attester

Use the Sign Protocol API to query all attestations for a specific schema.

curl 'https://mainnet-rpc.sign.global/api/index/attestations?schemaId=onchain_evm_10_0x1&attester=0xB1f50c6C34C72346b1229e5C80587D0D659556Fd'

Query by Recipient Address

To find attestations for a specific user:

curl 'https://mainnet-rpc.sign.global/api/scan/addresses/{address}/attestations'

Response Format

{ "data": { "page": 1, "rows": [ { "attestTimestamp": "1714819085000", "attestationId": "0x65", "attester": "0xB1f50c6C34C72346b1229e5C80587D0D659556Fd", "chainId": "10", "data": "0x000000...", "recipients": ["0xEdedf460A77928f59c27f37F73D4853FD8a07984"], "revoked": false, "schema": { "name": "HolonymV3", "description": "Holonym V3" }, "validUntil": 1770922106 } ], "size": 100, "total": 195 } }

Validating Attestations

When validating an attestation, verify the circuit ID, action ID, issuer, and expiration.

TypeScript Example

import { ethers } from "ethers"; // Expected values for Government ID verification const EXPECTED_CIRCUIT_ID = "0x729d660e1c02e4e419745e617d643f897a538673ccf1051e093bbfa58b0a120b"; const EXPECTED_ISSUER = "0x03fae82f38bf01d9799d57fdda64fad4ac44e4c2c2f16c5bf8e1873d0a3e1993"; const EXPECTED_ACTION_ID = "123456789"; const ATTESTER = "0xB1f50c6C34C72346b1229e5C80587D0D659556Fd"; interface AttestationValidation { isValid: boolean; error?: string; } function validateGovIdAttestation(attestation: any): AttestationValidation { // Check attester if (attestation.attester.toLowerCase() !== ATTESTER.toLowerCase()) { return { isValid: false, error: "Invalid attester" }; } // Check not revoked if (attestation.revoked) { return { isValid: false, error: "Attestation revoked" }; } // Check expiration const now = Math.floor(Date.now() / 1000); if (attestation.validUntil && attestation.validUntil < now) { return { isValid: false, error: "Attestation expired" }; } // Decode and validate attestation data const decoded = ethers.utils.defaultAbiCoder.decode( ["string", "uint256[]"], attestation.data ); const circuitId = decoded[0]; const publicValues = decoded[1]; const actionId = publicValues[2]; const issuer = publicValues[4]; // Validate circuit ID if (circuitId !== EXPECTED_CIRCUIT_ID) { return { isValid: false, error: "Invalid circuit ID" }; } // Validate action ID if (actionId.toString() !== EXPECTED_ACTION_ID) { return { isValid: false, error: "Invalid action ID" }; } // Validate issuer if (issuer.toHexString() !== EXPECTED_ISSUER) { return { isValid: false, error: "Invalid issuer" }; } return { isValid: true }; }

Proof of Clean Hands Attestations

Proof of Clean Hands uses a different schema on Base (chain ID 8453).

Query Clean Hands Attestations

curl 'https://mainnet-rpc.sign.global/api/scan/addresses/{address}/attestations'

Validation

function hasValidCleanHandsAttestation(attestations: any[]): boolean { const now = Math.floor(Date.now() / 1000); const CLEAN_HANDS_SCHEMA = 'onchain_evm_10_0x8'; const ATTESTER = '0xB1f50c6C34C72346b1229e5C80587D0D659556Fd'; return attestations.some(att => att.fullSchemaId === CLEAN_HANDS_SCHEMA && att.attester.toLowerCase() === ATTESTER.toLowerCase() && att.isReceiver === true && att.revoked === false && att.validUntil > now ); }

Sign Protocol Explorer

You can view attestations on the Sign Protocol explorer:


Action IDs

Action IDs enable sybil resistance by enforcing “1 person = 1 action”. The default action ID is 123456789.

For more information on action IDs and custom action IDs, see Action IDs.


Additional Resources

Last updated on