Skip to Content
DocsCredsEzrah Creds SDK

Ezrah Creds SDK

This document provides a comprehensive overview of how to use the Ezrah Creds SDK, a TypeScript package that simplifies the creation, issuance, and verification of Verifiable Credentials (VCs). It also includes tools for managing Decentralized Identifiers (DIDs), webhook integrations, organization settings, and analytics — all designed to integrate seamlessly with Ezrah’s identity infrastructure.

[!Note] Current SDK Version: @coincord/ezrah-creds-sdk@1.0.0-alpha.12


Installation

To start using the Ezrah Creds SDK, install it via npm or yarn. This will add the SDK to your project so you can begin issuing and verifying credentials and interacting with the Ezrah platform programmatically.

Ezrah(Coincord) Libraries are hosted on github not npm so add this to your .npmrc file, (vim ~/.npmrc)

@coincord:registry=https://npm.pkg.github.com

With this set your environment will know to check github for coincord libraries instead of npm

# npm npm install @coincord/ezrah-creds-sdk

or

# yarn yarn install @coincord/ezrah-creds-sdk

Also setup your environment configs with the following configurations.

EZRAH_CREDENTIAL_BASE_URL=api.ezrah.co EZRAH_ORGANIZATION_API_KEY=<your_api_key>

You can generate new API keys on your Ezrah Dashboard

Getting Started

This section initializes the SDK. Import the main class and instantiate it to begin accessing all available methods. This object becomes your main entry point for issuing credentials, managing webhooks, and more.

import EzrahCredential from '@coincord/ezrah-creds-sdk'; const ezrah = new EzrahCredential();

Credential Management

This section contains methods to issue Verifiable Credentials (VCs) to users. These credentials can contain any structured data and are tied to a DID. Use this to programmatically issue credentials for KYC, employment, certification, and more. These credentials can contain any structured data and are tied to a DID. Use this to programmatically issue credentials for KYC, employment, certification, and more.

Issue a pre-defined Credential

Use this method when you already have a pre-defined credential template (claim ID) and want to issue a VC to a user identified by their DID.

const credential = await ezrah.issueCredential({ claimID: 'template123', did: 'did:ezrah:abc123', claims: { name: 'John Doe', role: 'Admin', }, });

Response

{ proof: string, proof_type: string, credential: string }

Issue a Credential via SDK:

A simplified method to issue credentials using just the basic details (title, claim ID, and fields). Ideal for quick issuance flows or UI-based forms.

The claims must match the claims referenced within the template id. it doesn’t need to be a complete match of the list but a partial match.

const credential = await ezrah.issueCredentialSDK({ title: "Request title", template_claim_id: "a_claims_template_from_template_list", claims: { name: "John Doe", role: "Admin" }, options: { policy_control: false // default } })

Update Credential Policy

This method allows you to update the policy control state of a credential.

const result = await ezrah.policyControlCredential({ credential_urn: "urn:vc:abc123...", action: "REVOKE", // or "REVOKE, EXPIRY, SUSPEND" state: true, // or false });

Issue an Encrypted Credential

Issue via SD-JWT secure end to end encryption

SD-JWT Secure End-to-End Encryption

SD-JWT (Selective Disclosure JSON Web Token) enables users to disclose only specific claims (pieces of data) to a relying party, while keeping the rest confidential. When combined with secure end-to-end encryption, this approach ensures that sensitive information is protected both at rest and in transit.

This implementation introduces secure encryption of the disclosures using ephemeral (one-time use) keys with the X25519 key exchange protocol and AES-256 encryption.

How It Works

1. Claim Hashing and Disclosure Generation
  • Before encryption, each claim (e.g., name, birthdate, etc.) is hashed to generate its disclosure representation.
  • These hashed claims are selectively shared only when the user permits it.
2. Ephemeral Key Exchange with X25519
  • A fresh ephemeral key pair is generated for each encryption session using X25519, a Diffie-Hellman key exchange over Curve25519.
  • These keys are one-time use only, providing forward secrecy and preventing reuse-based attacks.
  • The receiver’s public key (e.g., device or backup key) is used to derive a shared secret via X25519.
3. Encryption using AES-256
  • The shared secret derived from X25519 is used as the symmetric key for encrypting the disclosure payload.
  • AES-256 in GCM or CBC mode (implementation-specific) is used for the encryption.
  • A nonce (or IV) ensures randomness for each encryption, preventing identical cipher outputs.

Note

A note on ephemeral key usage and backup process and functionalities

Ephemeral Key Usage (Key Backup and Recovery)

KeyDescriptionPurpose
device_keyEphemeral public key derived for the current deviceUsed to decrypt disclosures on the current device
back_upEphemeral key for user’s backup or recovery mechanismEnables access during recovery or multi-device sync
  • These keys are included encrypted and can be safely sent over the network.
  • Only the holder of the corresponding private keys can derive the shared secret and decrypt the disclosures.
Benefits
  • Selective Disclosure: Users share only what’s needed.
  • End-to-End Encrypted: Even intermediaries can’t read the claims.
  • Forward Secrecy: Ephemeral keys ensure past sessions remain secure.
  • Recovery Friendly: The back_up key allows for secure restoration of encrypted data.

How to Create an Encrypted SD-JWT Credential

Step 1: Define Credential Claims
const claims = { sub: 'subject_string_here', kyc_provider: 'DOJAH', passport_id: '2347BV98FB', expiry_date: new Date('10-10-2027').toISOString(), issuanceDate: new Date().toISOString(), first_name: 'Nelson', last_name: 'Obioma', issuer: { id: 'issuer string here' }, }; const disclosureFrame: Array<string> = [ 'passport_id', 'expiry_date', 'first_name', 'last_name', 'issuer', ];
Step 2: Issue Encrypted SD-JWT Credential
const endUserPublicKey = 'HexadecimalEncodedEndUserPublickKey'; const result = await ezrahCredsSDK.issueEncryptedSDJWT( claims, disclosureFrame, endUserPublicKey, { policy_control: false // default } );
// Response { _encoded: string // base64Encoded SD-JWT urn: string, // nullable credential: { // SD-JWT "header": { "typ": "dc+sd-jwt", "kid": "<key_id>", "alg": "ES256K" }, "payload": { "iss": "did:ezrah:<issuer_did>", "vct": "https://credentials.example.com/identity_credential", "kyc_provider": "DOJAH", "issuanceDate": "2025-05-15T14:23:41.174Z", "_sd": ["...hashes"], "_sd_alg": "sha-256" }, "signature": "<signature_string>" }, "encrypted_disclosures": { "ciphertext": "...", "iv": "...", "ephemeralPublicKey": "..." } } }
Result: Issued Credential
// response / result { "credential": "<jwt_string_here>" }

This is a signed and encrypted JWT that contains secure disclosures.


Decoded JWT Structure
Note

This is also the structure of the credential JSON response within the issueEncryptedSDJWT method.

{ "header": { "typ": "dc+sd-jwt", "kid": "<key_id>", "alg": "ES256K" }, "payload": { "iss": "did:ezrah:<issuer_did>", "vct": "https://credentials.example.com/identity_credential", "kyc_provider": "DOJAH", "issuanceDate": "2025-05-15T14:23:41.174Z", "_sd": ["...hashes"], "_sd_alg": "sha-256" }, "signature": "<signature_string>" }, "encrypted_disclosures": { "ciphertext": "...", "iv": "...", "ephemeralPublicKey": "..." } }

Encrypted Disclosure structure

{ encrypted_disclosures: { ciphertext: 'gCxNC18f31VAoX6Mea4fh3sdI5wDOfKUuEC9CHuVEzEcmOFY1XVPX5u21Vft2...', iv: 'JyZ08NSSqrbLHVCt', ephemeralPubKey: 'LZQFwtDa0eSLkpPKjKpyVYlDrMcFMYN7kPdCENhefw0', enc: 'AES-GCM', alg: 'X25519-AES-GCM' } }

Decrypted Disclosure Structure

Disclosures are decrypted on the client device.

"disclosures": [ { "key": "passport_id", "value": "2347BV98FB", "salt": "...", "_digest": "...", "_encoded": "..." }, { "key": "expiry_date", "value": "2027-10-09T23:00:00.000Z" }, { "key": "first_name", "value": "Nelson" }, { "key": "last_name", "value": "Obioma" }, { "key": "issuer", "value": { "id": "did:ezrah:<issuer_did>" } } ]

Behind the Scenes: Preprocessing

Before sending the request, the SDK:

  • Hashes selected claims using sha256
  • Encrypts disclosures using X25519 + AES-GCM
  • Packs claims into _sd
Example of Preprocessed Structure
{ "_hash_alg": "sha256", "packedClaims": { "sub": "subject_string_here", "kyc_provider": "DOJAH", "issuanceDate": "2025-05-15T14:23:41.207Z", "_sd": ["<hashed_disclosure_1>", "<hashed_disclosure_2>", ...] }, "disclosures": [ { "key": "passport_id", "value": "2347BV98FB", "salt": "...", "_digest": "...", "_encoded": "..." }, ... ] }

Final Credential Creation API Request
{ "subject": "did:ethr:0x1234...abcd", "issuer": "did:ethr:0xissuer1234...def0", "type": ["VerifiableCredential", "KYCVerifiedCredential"], "issuanceDate": "2025-05-15T13:12:34.468Z", "expirationDate": "2027-10-09T23:00:00.000Z" }

OAuth Verification Model.

This section allows you define authentication verification models which use the oauth protocol pattern to allow you handle third party authentication and verification using your credentials in easy to manage flows.

const authenticationModel: VerificationModel = await ezrah.createAuthVerificationModel({ title: "Title of the verification model", purpose: "purpose of the verification model", claims_match: "firstname,lastname,passport_id", // claims to match, comma seperated issuer_match: "did:ezrah:sdinsidnsdn", // if a did is entered this would be used as the issuer to match against, this always defaults to your organization did, manual_verification: true, // set to true to get webhook notifications from these verifications. client_id: "unique_client_id_here", client_secret: "client_secret_here", oob_prefix: "https://the_domain_prefix_for_oob", // this defaults to oauth.ezrah.co, callback: "https://partner_call_back_url_for_oauth_process.", custom_url_scheme: "url_scheme_for_mobile_clients", session_duration: "148000" // Session duration in seconds, e.g 2 days (148000) }) // Response type VerificationModel = { id: string, verification_title: string, purpose: string, verification_link: string, manual_verification: string, issuer_match: string claims_match: string, client_id: string | null, client_secret: string | null }

Credential Verification

This section allows you to define models for verifying specific credentials. You can specify what claims to match, whether verification is manual, and then fetch all requests associated with those models. This is useful for onboarding, compliance, and access-control use cases.

Create a Verification Model

Use this method to define the conditions under which a credential should be considered valid. This can include issuer checks, field matching, and whether the request requires human review.

const model: VerificationModel = await ezrah.createVerificationModel({ title: 'Employee Verification', purpose: 'Verify employee credentials', claims_match: { department: 'Engineering' }, issuer_match: 'issuer123', manual_verification: false, }); type VerificationModel = { id: string, verification_title: string, purpose: string, verification_link: string, manual_verification: string, issuer_match: string claims_match: string, client_id: string | null, client_secret: string | null }

Fetch Verification Models

Retrieves a list of verification models you’ve defined. Helpful for displaying available verification flows in your dashboard or admin interface.

const models = await ezrah.verifcationModels();

Get Verification Requests

Returns all credential verification requests submitted to a specific verification model. You can use this to build review dashboards or trigger workflows based on verification outcomes.

const requests = await ezrah.verifcationRequests('model123');

DID and Templates

This section handles the discovery and templating side of the system. You can resolve DIDs to get metadata and structure your credential issuance using reusable templates.

Resolve a DID

Resolves a DID (Decentralized Identifier) and returns associated metadata. Useful for displaying user info or validating an identity before issuing or verifying credentials.

const didInfo = await ezrah.resolveDID('did:ezrah:abc123'); // sample resolve did // { "did": "did:ezrah:0x7d3241B6eE2E05F09fDa3809dFA54530CE0b8fF6", "resolvedDID": { "didDocumentMetadata": { "versionId": "72276059", "updated": "2025-06-02T14:34:03Z" }, "didResolutionMetadata": { "contentType": "application/did+ld+json" }, "didDocument": { "id": "did:ezrah:0x7d3241B6eE2E05F09fDa3809dFA54530CE0b8fF6", "verificationMethod": [ { "id": "did:ezrah:0x7d3241B6eE2E05F09fDa3809dFA54530CE0b8fF6#controller", "type": "EcdsaSecp256k1RecoveryMethod2020", "controller": "did:ezrah:0x7d3241B6eE2E05F09fDa3809dFA54530CE0b8fF6", "blockchainAccountId": "eip155:137:0x7d3241B6eE2E05F09fDa3809dFA54530CE0b8fF6" }, { "id": "did:ezrah:0x7d3241B6eE2E05F09fDa3809dFA54530CE0b8fF6#delegate-1", "type": "X25519KeyAgreementKey2019", "controller": "did:ezrah:0x7d3241B6eE2E05F09fDa3809dFA54530CE0b8fF6", "publicKeyBase58": "F4LBhZCRzqxPYLamhZZXgZjwEEB3txfLo6TXbQZa2WQC" } ], "authentication": [ "did:ezrah:0x7d3241B6eE2E05F09fDa3809dFA54530CE0b8fF6#controller" ], "assertionMethod": [ "did:ezrah:0x7d3241B6eE2E05F09fDa3809dFA54530CE0b8fF6#controller" ], "service": [ { "id": "did:ezrah:0x7d3241B6eE2E05F09fDa3809dFA54530CE0b8fF6#service-1", "type": "DIDCommMessaging", "serviceEndpoint": "https://dev-eccw.ezrah.co/webhooks/did/service/did:ezrah:0x7d3241B6eE2E05F09fDa3809dFA54530CE0b8fF6" } ], "keyAgreement": [ "did:ezrah:0x7d3241B6eE2E05F09fDa3809dFA54530CE0b8fF6#delegate-1" ], "@context": [ "https://www.w3.org/ns/did/v1", "https://w3id.org/security/suites/secp256k1recovery-2020/v2", "https://w3id.org/security/v3-unstable" ] } } }

Fetch Templates

Retrieves a list of credential templates available for use in issuance. Templates help standardize the data structures you issue, making it easier to automate workflows and comply with schema requirements.

const templates = await ezrah.templates();

Credential Analytics

Use this section to track issued credentials and gather insight into how credentials are being used. You can fetch lists of credentials and get usage stats across different timelines or templates.

Get Issued Credentials

Lists all credentials issued under your organization, optionally filtered by timeline, status, or template. Useful for analytics dashboards and credential audits.

const credentials = await ezrah.issuedCredentials({ cursor: null, take: 10, timeline: '05/07/2024-05/09/2025', // Previous time-RecentTime status: 'issued', template_id: 'template123', });

Fetch Credential Analytics

Provides an overview of credential-related statistics, such as issuance counts and trends. Ideal for tracking adoption and performance of your identity programs.

const analytics = await ezrah.credentialAnalytics();

Webhook Management

This section lets you set up webhooks to listen for events like credential issuance or verification results. Great for real-time integrations with your backend or third-party systems.

Add a Credential Webhook

Registers a new webhook to be triggered when a specific request key is processed. Webhooks enable you to respond automatically to issuance or verification events.

const webhook = await ezrah.addCredentialsWebhook({ request_key: 'req123', name: 'Credential Issued Webhook', webhook_url: 'https://example.com/webhook', });

Update a Webhook

Edits an existing webhook configuration, such as changing the endpoint URL or display name.

const updatedWebhook = await ezrah.updateCredentialWebhook({ webhook_id: 'webhook123', request_key: 'req123', name: 'Updated Webhook', webhook_url: 'https://example.com/updated-webhook', });

Delete a Webhook

Deletes a webhook by its ID. Use this to clean up old integrations or disable inactive endpoints.

const result = await ezrah.deleteCredentialWebhook('webhook123');

List Webhooks

Retrieves all currently registered webhooks. Useful for building settings pages or debugging integrations.

const webhooks = await ezrah.webhooks();

Organization Management

Manage your organization settings such as general metadata and branding. These APIs help ensure your credentials are visually aligned with your brand and that team access is correctly configured.

Get Organization Info

Returns information about the current organization using the SDK. This includes your organization’s name, branding, and configuration details.

const orgDetails = await ezrah.organization();

Request Mediator

This functionality set allows you to be able to send DIDComm Requests to partner DIDs in a customizable manner, you can also include other protocol request attachments within your requests to enable partner dids initiate integrated calls for different interactions and processes.

// Send a notification message to a did const result = await ezrah.createRequestMessage({ source: "Partner X", oob_code: "eyJ3f32b298fdbdf9egf0gb3fb8-de29e9vfff22ff.....", message: "Partner X is trying to access your passport", reciever_did: "did:ezrah:0x9cdac82d.....", session_code: "session tracker for the individual request" }) // Result is boolean // result = true/false

The session_code in the request would be used passed through the protocol processes and made available at the webhooks and callback urls to detect the active session the request belongs to.

Error Handling

To ensure your integration is resilient, wrap all SDK methods in try/catch blocks. This helps you gracefully handle network issues, misconfigurations, or invalid inputs.

try { const response = await ezrah.templates(); } catch (error) { console.error('Something went wrong:', error); }

Notes

  • Fully written in TypeScript with complete type definitions.
  • Designed to work hand-in-hand with the Ezrah GraphQL Playground for advanced operations.
  • For security, always store your API keys using environment variables or a secure vault.
Last updated on