TypeScript/JavaScript SDK for programmatically interacting with the 5N ID service. This SDK provides a clean, type-safe wrapper around the 5N ID API for managing credentials, verification links, and identity verification.
npm install @fivenorth/id-sdk
# or
bun add @fivenorth/id-sdk
# or
yarn add @fivenorth/id-sdkimport { idSdk } from '@fivenorth/id-sdk';
// Connect with your client credentials (defaults to mainnet)
const connection = await idSdk.connect({
clientId: 'your-client-id',
clientSecret: 'your-client-secret',
});
// Get credentials for a specific user
const credentials = await connection.getCredentialsByPartyId('party::123');
console.log(credentials);The SDK uses OAuth2 client credentials flow for authentication. You'll need your Client ID and Client Secret from your institution settings.
import { idSdk } from '@fivenorth/id-sdk';
// Connect to mainnet (default)
const connection = await idSdk.connect({
clientId: 'your-client-id',
clientSecret: 'your-client-secret',
});
// Connect to devnet
const devConnection = await idSdk.connect({
clientId: 'your-client-id',
clientSecret: 'your-client-secret',
network: 'devnet',
});The SDK supports two networks:
mainnet(default) - Production environmentdevnet- Development environment
URLs are automatically resolved based on the network. You can override them if needed, but it's recommended to use the network parameter.
Request credentials from a user by creating a credentials access request (proposal):
await connection.createCredentialsRequest({
partyId: 'party::123',
providers: ['GOOGLE', 'LINKEDIN', 'GITHUB'],
});Retrieve all approved credentials that your institution has access to, with pagination:
// Get first page (default: offset=0, limit=10)
const allCredentials = await connection.getCredentials();
// With pagination
const page2 = await connection.getCredentials({
offset: 10,
limit: 20,
});
console.log(allCredentials.items); // Array of credentials
console.log(allCredentials.pagination); // { offset, limit, total }Get credentials disclosed by a specific user to your institution:
const userCredentials = await connection.getCredentialsByPartyId('party::123');
userCredentials.forEach(credential => {
console.log(credential.provider); // 'GOOGLE', 'LINKEDIN', etc.
console.log(credential.kycStatus); // 'APPROVED', 'REJECTED', etc.
console.log(credential.partyId); // User's party ID
console.log(credential.email); // Registered account email (top-level, same as list filters)
console.log(credential.freshness); // 'FRESH', 'MODERATE', 'STALE', 'REVOKED'
});Generate a short-lived verification link for a specific credential:
const verification = await connection.generateVerificationLink({
contractId: '008cb3c4e71260967ef...',
});
console.log(verification.verificationUrl); // URL to share
console.log(verification.token); // Token for status checkingGenerate multiple verification links at once (max 100 per batch):
const batchResult = await connection.generateVerificationLinksBatch({
requests: [
{ contractId: '00020bf30f6b3714bff...' },
{ contractId: '008cb3c4e71260967ef...' },
],
});
batchResult.results.forEach(result => {
if (result.result) {
console.log(`Success: ${result.result.verificationUrl}`);
} else if (result.error) {
console.error(`Error: ${result.error.message}`);
}
});Check the verification status for a token (public endpoint, no authentication required):
const status = await connection.checkVerificationStatus('verification-token');
console.log(status.status); // 'strong', 'moderate', 'weak', etc.
console.log(status.color); // 'green', 'amber', 'red'
console.log(status.isActive); // boolean
console.log(status.credentialData); // Original credential metadataThe resolve functionality provides three lookup methods to find credentials:
Find credentials when you have an identifier that matches credential metadata (email, username, or domain—for example a DNS domain on a DNS credential) or the user’s ID service account username (the user.username field on the API; usually the email address used to register). The match is case-insensitive. This returns all associated credentials the institution can access and the user's party ID:
// Resolve by email (metadata or ID service account username)
const result = await connection.resolve('user@example.com');
// Resolve by provider username in metadata, or ID service account username
const result2 = await connection.resolve('johndoe');
console.log(result.credentials); // Array of resolved credentials
result.credentials.forEach(cred => {
console.log(cred.partyId); // User's party ID
console.log(cred.email); // Registered account email (top-level)
console.log(cred.kycProvider); // Provider (GOOGLE, LINKEDIN, etc.)
console.log(cred.contractId); // Contract ID on the ledger
});Find all credentials when you have a user's party ID. This returns all credentials for that user:
const partyId = 'party::04a5835d6cc470817989e9acc1f20c0a::12200d35764b9b490251e499af00626b54516c4f3f1c021c2eb72bf7c72f38662cb0';
const result = await connection.reverseResolve(partyId);
console.log(result.credentials); // All credentials for this party
result.credentials.forEach(cred => {
console.log(cred.email); // Registered account email (top-level)
console.log(cred.username); // Username from metadata
console.log(cred.kycProvider); // Provider
});Find credentials when you have a purchased alias/FQDN:
const result = await connection.resolveByAlias('alice.5n.xyz');
console.log(result.credentials);The SDK can automatically determine which lookup method to use:
// Forward lookup (metadata email/username/domain or ID service account username)
const result1 = await connection.resolveCredentials({
q: 'user@example.com'
});
// Reverse lookup (automatically uses party ID)
const result2 = await connection.resolveCredentials({
partyId: 'party::123'
});
// Alias lookup (automatically uses alias/FQDN)
const result3 = await connection.resolveCredentials({
a: 'alice.5n.xyz'
});Use getHumanScores for a page of scores (optional partyIds / emails filters) or getHumanScoreByPartyId for one party. Each list item and the single-party response use the same object shape as GET /api/v1/users/me/human-scores (wallet) and public profile humanScore: top-level partyId, email (registered account, same convention as credential DTOs), and nested humanScore:
const item = await connection.getHumanScoreByPartyId('party::identifier');
console.log(item.email); // Registered account email
console.log(item.humanScore.totalScore);
console.log(item.humanScore.confidenceLevel); // 'low', 'medium-low', 'medium', 'medium-high', 'high'
console.log(item.humanScore.breakdown);
console.log(item.humanScore.badges);
console.log(item.humanScore.details);The nested humanScore includes:
- totalScore: Overall score from 0-100
- confidenceLevel: Confidence level based on the score
- breakdown: Score breakdown by category (accountAgeScore, socialMetricsScore, emailConsistencyScore, providerCountScore, …)
- badges: Array of earned badges with levels (bronze, silver, gold, platinum)
- details: Detailed metrics including account ages, social metrics, email consistency, provider count, and raw user info
The main SDK class. The class name is IDSdk and it's exported as an instance idSdk.
connect(config: IDSdkConfig): Promise<Connection>- Create and authenticate a new connectiongetVersion(): string- Get the SDK version
The connection instance returned from idSdk.connect(). All API operations are performed through this connection.
createCredentialsRequest(request: CreateCredentialsRequest): Promise<void>- Create a credentials access requestgetCredentials(options?: GetCredentialsOptions): Promise<CredentialsListResponse>- Get all institution credentials with paginationgetCredentialsByPartyId(partyId: string): Promise<Credential[]>- Get credentials for a specific party IDgenerateVerificationLink(request: GenerateVerificationLinkRequest): Promise<GenerateVerificationLinkResponse>- Generate a verification linkgenerateVerificationLinksBatch(request: BatchGenerateVerificationLinkRequest): Promise<BatchGenerateVerificationLinkResponse>- Generate multiple verification linkscheckVerificationStatus(token: string): Promise<VerificationStatusResponse>- Check verification status (public endpoint)resolve(query: string): Promise<ResolveCredentialsResponse>- Forward lookup: resolve byq(credential metadata email/username/domain or ID service account username)reverseResolve(partyId: string): Promise<ResolveCredentialsResponse>- Reverse lookup: Resolve credentials by party IDresolveByAlias(alias: string): Promise<ResolveCredentialsResponse>- Alias lookup: Resolve credentials by alias/FQDNresolveCredentials(options: ResolveCredentialsOptions): Promise<ResolveCredentialsResponse>- Automatically resolve using forward, reverse, or alias lookupgetHumanScores(options?: GetHumanScoresOptions): Promise<HumanScoresListResponse>- Get human scores (pagination / filters)getHumanScoreByPartyId(partyId: string): Promise<HumanScoreItem>- Get human score for one party (partyId,email, nestedhumanScore)
type Network = 'devnet' | 'mainnet' | 'dev' | 'main';type CredentialProvider = 'GOOGLE' | 'LINKEDIN' | 'GITHUB' | 'DISCORD' | 'TWITTER';interface Credential {
partyId: string;
email: string; // registered account email (same source as list `emails` filter)
contractId: string;
provider: CredentialProvider;
kycStatus: KYCStatus;
expirationDate: string;
issuedAt: string;
freshness: FreshnessStatus;
metadata: CredentialMetadata;
}interface VerificationStatusResponse {
status: VerificationStatus;
color: VerificationColor;
contractId: string | null;
issuedAt: string | null;
expiredAt: string | null;
isActive: boolean;
isArchived: boolean;
isSuperseded: boolean;
isRevoked: boolean;
message: string | null;
kycProvider: string | null;
credentialData: CredentialMetadata | null;
}interface ResolveCredentialsResponse {
credentials: ResolvedCredential[];
}
interface ResolvedCredential {
partyId: string;
userId: number;
email: string; // registered account email
username?: string;
firstName?: string;
lastName?: string;
kycProvider: 'GOOGLE' | 'LINKEDIN' | 'GITHUB' | 'DISCORD' | 'TWITTER';
contractId: string;
metadata?: Record<string, any>;
}Nested under HumanScoreItem.humanScore from getHumanScoreByPartyId / each element of getHumanScores().items:
interface HumanScoreResult {
totalScore: number;
confidenceLevel: ConfidenceLevel;
breakdown: {
accountAgeScore: number;
socialMetricsScore: number;
emailConsistencyScore: number;
providerCountScore: number;
};
badges: HumanScoreBadge[];
details: {
accountAges: Array<{ provider: CredentialProvider; ageInDays: number }>;
socialMetrics: SocialAccountMetrics[];
emailConsistency: {
uniqueEmails: string[];
consistencyScore: number;
};
providerCount: number;
allUserInfo: Record<string, any>[];
allTokenClaims: Record<string, any>[];
};
}interface HumanScoreItem {
partyId: string;
email: string; // registered account email (top-level, same as credentials)
humanScore: HumanScoreResult;
}interface HumanScoreBadge {
id: string;
name: string;
description: string;
level: BadgeLevel;
category: string;
icon?: string;
}
type BadgeLevel = 'bronze' | 'silver' | 'gold' | 'platinum';
type ConfidenceLevel = 'low' | 'medium-low' | 'medium' | 'medium-high' | 'high';The SDK provides specific error types for better error handling:
import { idSdk, UnauthorizedError, APIError } from '@fivenorth/id-sdk';
try {
const connection = await idSdk.connect({
clientId: '...',
clientSecret: '...',
});
const creds = await connection.getCredentials();
} catch (error) {
if (error instanceof UnauthorizedError) {
console.error('Authentication failed:', error.message);
} else if (error instanceof APIError) {
console.error('API error:', error.statusCode, error.message);
} else {
console.error('Unexpected error:', error);
}
}UnauthorizedError- Thrown when authentication fails (invalid credentials or expired token)APIError- Thrown when API requests fail (includes statusCode and response)TokenExpiredError- Thrown when access token expires (automatically handled by retry logic)
The SDK automatically handles OAuth2 token management:
- Tokens are automatically obtained on first use
- Tokens are cached and reused until near expiration
- Tokens are automatically refreshed when expired
- Failed requests due to expired tokens are automatically retried once
The SDK uses API version v1 by default. The version is embedded in the base URL and can be configured when creating a connection (though this is typically not necessary).
bun install
bun run buildIf you want to generate types from the OpenAPI specification:
bun run generate-typesThis will generate types from the OpenAPI specification into src/generated-types.ts.
See LICENSE file for details.
For questions or issues, please contact support@fivenorth.io or visit the 5N ID API Integration documentation.