# Welcome!

&#x20;Hi, welcome to the realm of Hypersign!&#x20;

<figure><img src="/files/o8Y9SxpWjmpBvQY9aEkR" alt=""><figcaption></figcaption></figure>

<table data-card-size="large" data-view="cards"><thead><tr><th></th><th></th><th></th><th data-hidden data-type="files"></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td><mark style="color:blue;"><strong>Hypersign ID</strong></mark></td><td>KYC for RAW &#x26; Defi - Fastest user onboarding for the new internet</td><td></td><td></td><td><a href="/pages/2lcHasKaeeHd4mqiIUXh">/pages/2lcHasKaeeHd4mqiIUXh</a></td></tr><tr><td><mark style="color:blue;"><strong>Hypersign Identity Network</strong></mark></td><td>A permission less blockchain network for decentralised identity (DID) and verifiable data.</td><td></td><td></td><td><a href="/pages/-MOLDQIrnXPa0mq24fOP">/pages/-MOLDQIrnXPa0mq24fOP</a></td></tr><tr><td><mark style="color:blue;"><strong>Hypersign SSI</strong></mark></td><td>Managed cloud based SSI service</td><td></td><td></td><td><a href="/pages/iGhV6b9CyjFlDNGhaSLg">/pages/iGhV6b9CyjFlDNGhaSLg</a></td></tr></tbody></table>


# Introduction

Welcome to the Hypersign Developer Documentation.

**Hypersign** is a platform for building identity verification and compliance workflows into modern applications. Through a unified set of APIs, embeddable widgets, and webhook integrations, developers can integrate Know Your Customer (KYC), Know Your Business (KYB), identity verification, and decentralized identity (SSI) capabilities without building complex compliance infrastructure from scratch.

Whether you're building a fintech application, crypto exchange, marketplace, lending platform, RWA platform, or enterprise onboarding solution, Hypersign provides the components required to verify users and businesses while maintaining a privacy-first architecture.

### What you can build

With Hypersign, you can:

* Integrate KYC verification into your web or mobile application
* Verify businesses through KYB workflows
* Perform identity document verification and OCR
* Verify user liveness using biometric face authentication
* Run AML, sanctions, and PEP screening
* Collect user consent for regulatory compliance
* Receive real-time verification updates using webhooks
* Embed fully customizable KYC/KYB widgets
* Issue and verify W3C Verifiable Credentials
* Build privacy-preserving identity flows using Decentralized Identifiers (DIDs) and Self-Sovereign Identity (SSI)

### Privacy by Design

Hypersign is designed with privacy as a core principle.

Identity verification is performed without requiring businesses to build or manage their own verification infrastructure. Customer environments are logically isolated, while the platform supports decentralized identity workflows where users can retain ownership of their digital credentials. This architecture enables organizations to build compliant identity experiences while minimizing exposure to sensitive personal information.


# Integrations

How to integrate KYC in your app

### Now let's with the integration:

### Quick Tutorials

1. Go Live In Minutes - No integration needed
2. [Embede Hypersign ID Widget in your app.](/hypersign-id/tutorials/how-to-integrate-hypersign-id-widget-in-your-app)
3. Build Custom Onboarding using our ID Verification API

### Basic Integration

1. [Create new KYC Service ](/hypersign-id/integrations/id-service)on the [Developer Dashboard ](/hypersign-developer-dashboard/developer-dashboard)
2. [Setup Widget Configuration](/hypersign-id/integrations/widget-configuration) on the KYC Service Dashboard
3. [Generate SSI and KYC AccessTokens](/hypersign-ssi/api-doc/authentication) using secret keys
4. Embed KYC Widget URL in your UI
5. \[Optional] Extract user's data.

### Advance Integration

6. [Verify your domain ](/hypersign-id/integrations/environments/production)
7. [Go to production](/hypersign-id/integrations/environments/production)


# ID Service

Setup ID service for your app on developer dashboard

Inorder to use Hypersign ID verification, you need to setup your account on [Entity Developer Dashboard](https://entity.dashboard.hypersign.id/) and setup your KYC service.

### Pre-requisite

Before you setup your KYC service, you need to setup your SSI service:

{% content-ref url="/pages/LyWgA1OhK43Vbe2Gj7wL" %}
[Setup SSI Service](/hypersign-ssi/setup-ssi-service)
{% endcontent-ref %}

and create a issuer DID:&#x20;

{% content-ref url="/pages/3tapyAFHhE3YWdZf7vyT" %}
[Create Your First DID](/hypersign-ssi/setup-ssi-service/create-your-first-did)
{% endcontent-ref %}

You will need Issuer DID to setup KYC service and Issuer DID can only be created once you have SSI service.&#x20;

### KYC Service Setup

Once you have setup your SSI service and created your issuer DID, now you are ready to setup your KYC service on the [Entity Developer Dashboard](https://entity.dashboard.hypersign.id/).&#x20;

Login  to Entity Developer Dashboard and click on **'+Create'** to create a new serivce just like you did for SSI service.&#x20;

<figure><img src="/files/3Lhpw12S02QyMplhODwy" alt=""><figcaption><p>Create KYC Service</p></figcaption></figure>

> *If you have not created SSI service before, you will see the above screen other wise you will see list of services you have on the home screen*

Enter relevant details about your service and choose **"KYC API Service"** in the "**Select Service**" dropdown.&#x20;

<figure><img src="/files/KPWCIOVizoog0w9FZraK" alt=""><figcaption></figcaption></figure>

Also make sure you associate SSI service and link issuer DID which you had created in the previous steps. Once all details are filled in the form, click the **"Save"** button to create your KYC service.

<figure><img src="/files/j2Ca12T0kZjV0CNhX00B" alt=""><figcaption></figcaption></figure>

An API secret key is generated for this service. You can save copy and save this Secret key for later purpose. Additionally you can always generate a new secret key, if you happen to loose it.&#x20;

Your KYC Service has been successfully created. You may also take note of your KYC service **Tenant URL** which we will use latter.  You may also notice that the service by default runs in "[**dev**" mode](/hypersign-id/integrations/environments/development).&#x20;

<figure><img src="/files/CzwpOOFeyj7kcbsRsl0T" alt=""><figcaption></figcaption></figure>

Now that your KYC service is created, you are ready to setup KYC widget configuration. Let's proceed to Widget configuration page.&#x20;

{% content-ref url="/pages/xBCcYcpL4pIdVZ2xEhiP" %}
[Widget Configuration](/hypersign-id/integrations/widget-configuration)
{% endcontent-ref %}


# Widget Configuration

[Hypersign KYC widget](/hypersign-id/id-widget) is web based application to capture user's data. It is used to capture, user facial detail, ID document, user consent etc. In order to use KYC Widget in your frontend, you first need to configure it in the [Entity Developer Dashboard](https://entity.dashboard.hypersign.id/). Widget configuration enable you to do custom configurations of KYC widget for your users.&#x20;

Logon to [Entity Developer Dashboard](https://entity.dashboard.hypersign.id/). and proceed to "**Know Your Customer**" tab of your services and click on your KYC service tile.

<figure><img src="/files/1XFX2XtLkaInwtdwohC9" alt=""><figcaption></figcaption></figure>

Your KYC service dashboard opens up.  Now navigate to "**Widget Configuration**" page by clicking on "**Widget**" menu item in the side nav bar.

<figure><img src="/files/NEWZzUsu4ulMobtdqyxp" alt=""><figcaption></figcaption></figure>

### Facial Recognition

The first configuration is Facial recogination which is already enabled. So no need to do anything here.

<figure><img src="/files/S4NRBB863d0MdTZ5O4iw" alt=""><figcaption></figcaption></figure>

This feature, if enabled, will ask user to open their camera and record a video on KYC widget to prove he/she is a human. Once the data is collected and verified, KYC server issues a "**Personhood Credential**" to the user which acts as a proof that "*he/she is indeed a real human and not bot*".

{% hint style="info" %}
Check list of all supported credentials and proofs types here.
{% endhint %}

### ID Document Verification

<figure><img src="/files/uFyz53eXyOxHHJBUjsYL" alt=""><figcaption></figcaption></figure>

Now enable ID document verification setting and select document type as "**Passport**". The feature, if enabled, the KYC widget will ask users to provide ID document. The ID document is captured, data extracted and sent to the KYC service. KYC service does the following things with the data:

1. **Document Verification:** Checks if document was tampered or not in correct format. In some cases, it also verifies if digital signature attached with the document is correct or not.&#x20;
2. **OCR:** Extracts relevant data from the ID document.
3. **Facial Authentication:** Matches user's image in the ID document with the user's photo taken during the facial recognition step
4. **Uniqueness Check:** Checks if the user unique in the system - restricting same user not using same ID document with multiple accounts.&#x20;

Upon successful verifications of all, the KYC service issues him/her "**Passport Credential**", which is technically a [verifiable credential](/hypersign-ssi/api-doc/verifiable-credential), to the user.&#x20;

{% hint style="info" %}
Check list of all supported credentials and proofs types here.
{% endhint %}

### User Consent

<figure><img src="/files/HGKt2PeXjtY7rtRnkqvt" alt=""><figcaption></figcaption></figure>

Configure user consent page by providing a valid reason for "why you are collecting user's data". Read more about user consent here:

{% content-ref url="/pages/mGozwY9Oig4vO9Yfn8N9" %}
[Capture User Consent](/hypersign-id/id-widget/data-capture/capture-user-consent)
{% endcontent-ref %}

### Zero Knowledge Proof (zk-proof)

<figure><img src="/files/6bfmlR3udHQeJOhpi28H" alt=""><figcaption></figcaption></figure>

Enable zk-proof configuration if do not want to collect user's personal data but the proof of facts. We have following proofs available.

1. [**Proof Of KYC (PoK)**](/hypersign-id/concepts/zk-proof-types/proof-of-kyc-pok):  Proves that user has finished his/her KYC. &#x20;
2. [**Proof Of Personhood (PoP)**](/hypersign-id/concepts/zk-proof-types/proof-of-personhood-pop): Proves that user is not a bot
3. [**Proof Of Age (PoA)**](/hypersign-id/concepts/zk-proof-types/proof-of-age-poa): Proves user is above the specified age (age need to be specified in text box)

Configure one of more proofs and click on **Update Configuration** button to save your settings.&#x20;

### On-Chain KYC

<figure><img src="/files/LXWjmDeeP0SdEWJhpzZ0" alt=""><figcaption></figcaption></figure>

You might want to provide service to  users based on verification in your Dapp. For that your smart contracts wants to verify user's Identity before allowing to access other features of the smart contract. Since users cannot send his personal data to a contract because of obvious privacy issues with public blockchains, user first generates zk-proofs of their ID claims and only sends proofs to contracts, preserving privacy while enabling secure verification.  Make sure to [create On-Chain KYC configuration](/hypersign-id/on-chain-kyc/contracts-deployment) in one of the supported blockchain before enabling this setting.

{% content-ref url="/pages/aMwfTbxRiWGbdejezekK" %}
[Contracts Deployment](/hypersign-id/on-chain-kyc/contracts-deployment)
{% endcontent-ref %}

{% hint style="info" %}
Make sure to enable zk-proof configuration before enabling On-Chain KYC configuration.
{% endhint %}

### Trusted Issuer

<figure><img src="/files/To9XrPSETNEreEmaKPQp" alt=""><figcaption></figcaption></figure>

Select one or more trusted issuers, with the default being 'self' - your own KYC service. This pertains to [**Reusable KYC**](/hypersign-id/concepts/reusable-kyc). If configured, users who already possess KYC credentials issued by these trusted issuers in their [data vault](/hypersign-id/id-widget/data-capture/data-vault-setup) will not need to repeat the KYC steps in the widget. They can simply authorise the sharing of their existing credentials with your app, streamlining user onboarding for your application and providing a smoother experience for your users.&#x20;

***

Now that your widget configuration is finished, you are ready to integrate Hypersign KYC in your application.&#x20;

{% content-ref url="/pages/0VTORrl9sON5pkNQW9GW" %}
[Integrations](/hypersign-id/id-widget/integrations)
{% endcontent-ref %}


# Environments


# Development

You may have noticed that by default, our KYC service was created in "**dev**" - Development mode.&#x20;

<figure><img src="/files/sZ0ckYIUQK9kgT4fvGET" alt=""><figcaption></figcaption></figure>

In "**dev**" mode following verifications are not performed by AI models integrated in the KYC service:&#x20;

1. Facial Authentication is not performed&#x20;
2. Uniqueness check is also not performed&#x20;
3. Document verification is also not performed&#x20;
4. No revocability of the credential (credential status is not registered on blockchain)
5. Email is not sent to users

Only data is captured and extracted from ID document. We suggest you to complete [full integration](/hypersign-id/id-widget/integrations), test a couple of times and then go for production.&#x20;

{% content-ref url="/pages/T5mSUuhTeEZH0atsNrtU" %}
[Production](/hypersign-id/integrations/environments/production)
{% endcontent-ref %}


# Production

Going in production requires you to verify your domain:

<figure><img src="/files/hL1ffvCzZMwh7qb9tmbi" alt=""><figcaption></figcaption></figure>

To verify your domain, click on "**Domain**" icon on your KYC service tile, "**Verify Your Domain**" popup will appear on the screen.&#x20;

<figure><img src="/files/XKE7MpTWbdw70vRehjoP" alt=""><figcaption></figcaption></figure>

Provide a valid domain name for your doman and add the provided TXT record in your DNS and finally click on "**Verify**" button.&#x20;

<figure><img src="/files/kxXdyuRnu03wzhsB2Ogb" alt=""><figcaption></figcaption></figure>

Once your domain is verified, you will see "**Green tick**" mark next to your service name on the tile. Thats it, now you are ready for production.&#x20;

And now in "**prod**" mode you get all sorts of verifications which were not present in the **"dev"** mode.&#x20;

* You get [Facial Authentication](/hypersign-id/concepts/facial-authentication).
* You get [Uniqueness check ](/hypersign-id/concepts/uniqueness-check)
* You get Document verification.&#x20;
* Credential status gets registered on the blockchain - [Credential Revocability](/hypersign-id/concepts/credential-revocability)!
* Emails are sent to user about their verification status.


# Webhook

Admin can setup webhook from their app's KYC dashboard. Login to Entity Developer Dashboard and navigate to the KYC app for you want to configure the Webhook.&#x20;

<figure><img src="/files/iuhzRZI4AYrV9q7VsWAA" alt=""><figcaption></figcaption></figure>

{% hint style="info" %}
Webhook URL must be of HTTP method POST
{% endhint %}

Webhook works on "Fire & Forget" way. As soon as the KYC server verifies the KYC it simply executes the webhook with the following request body:

```javascript
{
   idToken: "",
   sessionId: ""
}
```


# ID Widget

{% hint style="info" %}
Widget Base URL : <https://verify.hypersign.id>
{% endhint %}

<table data-view="cards"><thead><tr><th></th><th></th><th></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td>KYC Widget Integration</td><td></td><td></td><td><a href="/pages/0VTORrl9sON5pkNQW9GW">/pages/0VTORrl9sON5pkNQW9GW</a></td></tr><tr><td>User Data Capture</td><td></td><td></td><td><a href="/pages/kMEVwB0IpiuvMd4VfZKT">/pages/kMEVwB0IpiuvMd4VfZKT</a></td></tr><tr><td>Verified User Data </td><td></td><td></td><td><a href="/pages/PA1sGZz4XIbYsYpc7VYH">/pages/PA1sGZz4XIbYsYpc7VYH</a></td></tr></tbody></table>


# Integrations

### [Backend Integration](/hypersign-id/id-widget/integrations/backend-integration)

1. Integrate Service Authentication API and generate `accessTokens` in your backend.
2. Integrate Session API of KYC service and generate `sessionId` in your backend.

### [**Frontend Integration**](/hypersign-id/id-widget/integrations/frontend-integration)

1. Prepare widget URL and embed the URL in your frontend.&#x20;
2. Listen events from widget for verification result.&#x20;

{% hint style="info" %}
You can also request user data from KYC service using `idToken` you receive.
{% endhint %}


# Backend Integration

### Pre-requisites

Setup SSI service and get secret key:

{% content-ref url="/pages/LyWgA1OhK43Vbe2Gj7wL" %}
[Setup SSI Service](/hypersign-ssi/setup-ssi-service)
{% endcontent-ref %}

Setup KYC service and get secret key:

{% content-ref url="/pages/RGjD8PghNASXptSCNHZ7" %}
[ID Service](/hypersign-id/integrations/id-service)
{% endcontent-ref %}

{% hint style="warning" %}
Please keep secrets in your backend securely. If you doubt, your secrets are compromised, please [regenerate a new secret key](/hypersign-developer-dashboard/developer-dashboard/managing-api-keys).
{% endhint %}

{% content-ref url="/pages/u8XWTiyGTIJULYI41CYW" %}
[Generate AccessTokens](/hypersign-id/id-widget/integrations/backend-integration/generate-accesstokens)
{% endcontent-ref %}


# Generate AccessTokens

You must have SSI service secret key and KYC service secret key with you before proceeding to this step.&#x20;

In order to use APIs of your services, you need `accessToken` generated using your API secret keys. Generate accessToken by calling **Service Authentication API** using API secret keys. You might want to **implement an API** in your backend which will call **Service Authentication API** to generate accessTokens for SSI and KYC services, so that your API secrets are not exposed in your frontend or anywhere else.

Let's call these accessToken as `kycAccessToken` and `ssiAccessToken` for KYC service and SSI service respectively.

{% content-ref url="/pages/1ECe3zbGhbIj5m8Yls2F" %}
[Service Authentication API](/hypersign-ssi/api-doc/authentication)
{% endcontent-ref %}

Once you have both `kycAccessToken` as well as `ssiAccessToken`you may now proceed to frontend integration of the KYC widget.

{% content-ref url="/pages/cMqE7034c0k5zu83OOav" %}
[Frontend Integration](/hypersign-id/id-widget/integrations/frontend-integration)
{% endcontent-ref %}


# Generate KYC Session Id

### Pre-Requisite

{% content-ref url="/pages/u8XWTiyGTIJULYI41CYW" %}
[Generate AccessTokens](/hypersign-id/id-widget/integrations/backend-integration/generate-accesstokens)
{% endcontent-ref %}

### KYC Session Id

To generate a new KYC Session Id, first, get your KYC Service **Tenant URL** from your KYC service tile.

<figure><img src="/files/RlBTR8gGxtX1NJmwunv7" alt=""><figcaption></figcaption></figure>

and call <mark style="color:green;">**POST**</mark> `/api/v1/e-kyc/verification/session` API to generate a new KYC session for your user. Make sure to pass `kycAccessToken` in the header.&#x20;


# Frontend Integration

### Pre-requisites

Generate your access tokens before proceeding:

{% content-ref url="/pages/u8XWTiyGTIJULYI41CYW" %}
[Generate AccessTokens](/hypersign-id/id-widget/integrations/backend-integration/generate-accesstokens)
{% endcontent-ref %}

Optionally, generate KYC `sessionId` as well.&#x20;

{% content-ref url="/pages/dqe0KT4UsPFvWfC1fCqr" %}
[Generate KYC Session Id](/hypersign-id/id-widget/integrations/backend-integration/generate-kyc-session-id)
{% endcontent-ref %}

### Widget Integration

You'll need to generate a **Widget URL** and insert it into a DOM element. Additionally, you can monitor events triggered by the widget on your webpage to showcase either success or failure. Once the user completes the KYC process successfully, you'll receive an `idToken`, which can be utilised to request the user's data/credentials from the KYC server.

### Forming Widget URL

The Widget URL has  three query params:

1. **`kycAccessToken`**: KYC Access Token
2. **`ssiAccessToken`**: SSI Access Token
3. **`sessionId`**: KYC Session Id

The final Widget URL format would look something like this:

> ```
> https://verify.hypersign.id
> ?kycAccessToken=${kycAccessToken}&ssiAccessToken=${ssiAccessToken}&sessionId=${sessionId}
> ```

### Invoking the widget

You can invoke the Hypersign KYC widget through popup from your page

```javascript
const widgetUrl = `https://verify.hypersign.id
?kycAccessToken=${kycAccessToken}&ssiAccessToken=${ssiAccessToken}&sessionId=${sessionId}`

window.open(widgetUrl, 'Popup Window', 'width=850,height=900');
```

### Listening to events

You can listen to events thrown by the widget to get the result of verification.&#x20;

```javascript
window.addEventListener('message', function (event) {
    if (event.origin === 'https://verify.hypersign.id') {
        console.log('Received message from popup:', event.data);
        // make sure to parse the data before use
        const data = JSON.parse(event.data)
        
        // we send these 3 vaules: 
        // status = success / fail, 
        // message = a simple message (if any)
        const { status, message} = data;
        if (status === 'success') {
            console.log('Successfully finished the KYC')
        }
        else if (status === 'fail') {
            console.log('Failed to finish KYC')
        }
    }
});
```

You can only obtain status of verification through events. But in order to **get user data,** developers need to configure the **webhook** on their KYC dashboard.&#x20;

{% content-ref url="/pages/7FKd4OGFmtwj3wLKU2HT" %}
[Webhook](/hypersign-id/integrations/webhook)
{% endcontent-ref %}


# Data Capture


# Data Vault Setup

<figure><img src="/files/8cLhBwbMT9UOHH6wyWq1" alt=""><figcaption></figcaption></figure>


# Capture Facial Recognition

<figure><img src="/files/RVzVnJY9GL1iMl6ZlaRU" alt=""><figcaption></figcaption></figure>


# Capture ID Document

<figure><img src="/files/0PYT5GWJFX51xrsJ793Z" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/47wJT8MUaFUM95CfFIWw" alt=""><figcaption></figcaption></figure>


# Capture zk-proof and KYC token

<figure><img src="/files/3ZN3h4VC4hHlB96kcC8Z" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/DYdjti3GFT5J09aWcq1J" alt=""><figcaption></figcaption></figure>


# Capture User Consent

<figure><img src="/files/qHRnMEEXBfK1IARGy1kT" alt=""><figcaption></figcaption></figure>


# User Data


# idToken

<mark style="color:green;">`GET`</mark> {kyc\_server\_base\_url}/api/v1/e-kyc/verification/user-consent

**Headers**

| Name          | Value                       |
| ------------- | --------------------------- |
| Content-Type  | `application/json`          |
| Authorization | `Bearer <`kycAccessToken`>` |

**Response**

{% tabs %}
{% tab title="200" %}

```json
{
  "@context": [
  ],
  "type": ["VerifiablePresentation"],
  "VerifiableCredntial": [
      {
        ... 
      }
  ]
}
```

{% endtab %}
{% endtabs %}

```html
https://ent-4c71874.api.cavach.hypersign.id/api/v1/e-kyc/verification/user-consent?idToken=${idToken}
```


# Hypersign ID Wallet


# On-Chain KYC

Verify user's Identity in a privacy preserving way and grant access to your dApps

### Introduction

The on-chain KYC feature enables you to verify users' identities in a privacy-preserving manner, granting access to your dApps without compromising sensitive information. For example, if you need to verify a user’s identity before allowing access to your smart contract, this can be done in three key steps:

#### On-chain KYC Configuration

1. dApps [deploy the on-chain KYC contracts](/hypersign-id/on-chain-kyc/contracts-deployment) via the Entity Studio dashboard on their preferred (supported) blockchains.
2. dApps [activate the on-chain KYC settings and configure zero-knowledge (zk) proof ](/hypersign-id/integrations/widget-configuration)options within the widget configuration.

#### Token Minting

1. Users generate the required [zk proofs](/hypersign-id/concepts/zero-knowledge-proof-zkp) from their identity credentials.
2. Users mint Soulbound Tokens (SBTs) tied to their zk proofs.

#### Token Verification

1. The dApp’s smart contract queries and verifies the user's SBT directly on-chain, confirming identity before granting access.

This process provides decentralised, privacy-respecting identity verification for secure dApp access.

{% content-ref url="/pages/Ran74Cx714lUWZJqqH6O" %}
[Supported Blockchains](/hypersign-id/on-chain-kyc/supported-blockchains)
{% endcontent-ref %}

### Architecture

The architecture of on-chain KYC contracts is straightforward, consisting primarily of three smart contracts and a set of libraries. Initially, the Hypersign Admin deploys the **Hypersign KYC Factory** contract on the blockchain. This KYC Factory contract manages a registry of issuers and maintains the contract addresses of their respective KYC Issuer contracts.

For any dApp that wishes to implement an on-chain KYC system, they simply call the **Hypersign KYC Factory** contract to initiate the deployment of their dedicated **Hypersign KYC Issuer** contract. The contract serves two primary purposes: (a) Deploying the **Hypersign KYC Token** contract, and (b) Verifying zero-knowledge (zk) proofs to mint the **Hypersign KYC Token** for users. Once a dApp deploys its own **Hypersign KYC Issuer** contract, it needs to call the **Hypersign KYC Token** contract to instantiate its respective KYC token contract. Users then mint their on-chain ID—a  Soulbound Token (SBT)—through the **Hypersign KYC Issuer** contract, establishing their verified identity on-chain.

<div data-full-width="false"><figure><img src="/files/iGtyck43PzfzmO5Cr11U" alt=""><figcaption></figcaption></figure></div>

Finally, The **Hypersign KYC Token** contract is responsible for managing all on-chain identities for users. dApps that need to confirm a user’s completion of the KYC process can call this contract to verify their status.

{% hint style="info" %}
As a dApp, you do not need to worry about Hypersign KYC Factory Contract. You only need to deploy the KYC Issuer and KYC Token contract through Entity Studio Dashboard in just few button clicks.&#x20;
{% endhint %}

Let's go ahead and deploy these two contract through Entity studio dashboard:&#x20;

{% content-ref url="/pages/aMwfTbxRiWGbdejezekK" %}
[Contracts Deployment](/hypersign-id/on-chain-kyc/contracts-deployment)
{% endcontent-ref %}


# Contracts Deployment

Please read [introduction](/hypersign-id/on-chain-kyc#introduction) before proceeding with the contract deployments on this page. &#x20;

Head over to Entity Studio dashboard, choose your KYC service and click on **OnChain KYC**  under setting tab in left nav bar.&#x20;

<figure><img src="/files/KGVw7rbmb46GO1NhgSPn" alt=""><figcaption></figcaption></figure>

Click on **Deploy OnChain KYC** button to start the process of contract deployments.&#x20;

### Deploy Hypersign KYC Issuer Contract

Step 1 is to deploy your KYC Issuer contract through the right slider window. Select blockchain of your choice then select a DID which you want to associate with this contract.  Finally, connect your wallet and click on "**Deploy KYC Contract**" button.&#x20;

{% hint style="info" %}
If you do not have any DID yet, kindly refer to [this](/hypersign-ssi/setup-ssi-service/create-your-first-did) documentation.
{% endhint %}

{% content-ref url="/pages/Ran74Cx714lUWZJqqH6O" %}
[Supported Blockchains](/hypersign-id/on-chain-kyc/supported-blockchains)
{% endcontent-ref %}

<figure><img src="/files/J9sdM5l8xAIFdFyPpf0O" alt=""><figcaption></figcaption></figure>

You need to authorise the transaction to instantiate your KYC issuer contract through wallet. If everything works, you will see your KYC contract address in the slider.&#x20;

<figure><img src="/files/RfVFV42QDPl0rTcnYhRg" alt=""><figcaption></figcaption></figure>

Click on "**Next**" button to deploy your KYC token contract in the next step.

### Deploy Hypersign KYC Token Contract (SBT)

Same as before, authorize the transaction through your wallet to deploy your brand new KYC token contract.&#x20;

<figure><img src="/files/tmF7Sf2HWU2cmy3VnIo2" alt=""><figcaption></figcaption></figure>

Once the transaction is successfull, you will see KYC token contract address in the slider.&#x20;

<figure><img src="/files/aXHlcT9Zl9f19nndUs8h" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/OcwOcf2qEWAZdizPKQCi" alt=""><figcaption></figcaption></figure>

And your configuration is completed. Please note the configuration ID (2nd column) in the configuration record, we would need to set this configuration ID in the widget configuration.&#x20;

<figure><img src="/files/7N7WY954DbjaKthr6SrZ" alt=""><figcaption></figcaption></figure>

Now that we have deployed our contracts, let's go ahead and enable this [on chain kyc configuration](/hypersign-id/integrations/widget-configuration#on-chain-kyc) in the widget setting page:&#x20;

{% content-ref url="/pages/xBCcYcpL4pIdVZ2xEhiP" %}
[Widget Configuration](/hypersign-id/integrations/widget-configuration)
{% endcontent-ref %}


# Use Cases

### Airdrops

### DAO Voting

### Regulated Transactions


# Supported Blockchains

<https://github.com/hypersign-protocol/hypersign-kyc-chains-metadata>&#x20;


# KYC Token Metadata


# Dashboard


# User Sessions

<figure><img src="/files/zpzEpr2YKbUnIb9aQKLz" alt=""><figcaption></figcaption></figure>


# User Session Details

<figure><img src="/files/iZmIxNFhFPpFMprNU6YA" alt=""><figcaption></figcaption></figure>


# Usage

```typescript
```

<figure><img src="/files/E00UrMMCHEXn3YLeT2MG" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/sF7pLktFQ5nJ3j1DwjuO" alt=""><figcaption></figcaption></figure>


# Credit


# Concepts


# Facial Recognition


# ID Verification (via OCR)


# Reusable KYC

Configure **Reusable KYC** through "**Trusted Issuer**" setup configuration on **Widget configuration** page on the Entity Developer Dashboard.&#x20;

It has the following benefits:&#x20;

1. Reduces user onboarding time from minutes to seconds.&#x20;
2. Smoothens user onboarding process.
3. Reduce vectors for data leakages.
4. Increases security and privacy.&#x20;


# Encrypted Data Vault (EDV)


# Facial Authentication


# Issuer Marketplace

{% content-ref url="/pages/uVsoGbj4SQ5nJAA2yW7K" %}
[Reusable KYC](/hypersign-id/concepts/reusable-kyc)
{% endcontent-ref %}


# Security


# Privacy


# Credentials Types

<figure><img src="/files/1tdhXWKMPAJA5fKxOvaL" alt=""><figcaption></figcaption></figure>


# Personhood Credential


# Passport / Govt. ID Credential


# zk Proof  Types

<figure><img src="/files/9JEdGP29fbZ9xU7zfKor" alt=""><figcaption></figcaption></figure>


# Proof Of Personhood (PoP)

Hypersign’s PoP leverages video KYC and [Zero-Knowledge Proofs (ZKPs)](/hypersign-id/concepts/zero-knowledge-proof-zkp) to verify if a specific account (or wallet address) belongs to a real human.

<figure><img src="/files/RYvxUdyxXjrg4Wkg8oK8" alt=""><figcaption></figcaption></figure>

### How It Works?

1\. **Video Capture and Verification**

The process begins with a user submitting their video KYC through Hypersign's KYC Widget. Once the video is collected, it undergoes a series of AI-driven checks:

* **Liveness Detection**: The AI model uses liveness detection to confirm that the person is physically present in real-time, as opposed to a static image, video replay, or deepfake. This involves subtle movement analysis, such as blinking, head movements, and sometimes following prompts like changing gaze direction or smiling.
* **Anti-Spoofing Measures**: The AI model detects spoofing attempts, such as using photos, videos, or masks. Techniques like depth analysis and light reflection analysis differentiate between a real face and 2D images or video screens.

2\. **Credential Issuance**

Once all checks pass, the KYC issuer provides a Personhood Credential. This credential confirms that the user has passed all necessary verifications and includes a digital signature from the issuer. The user then stores the Proof of Personhood credential securely in their data vault.

3\. **Zero-Knowledge Proof (ZKP) Generation**

After receiving the credential, the user generates a [zero-knowledge proof (zk proof)](/hypersign-id/concepts/zero-knowledge-proof-zkp) of it. This proof, also known as the Proof of Personhood (PoP), is created by submitting the credential to a custom-built [zk circuit](/hypersign-id/concepts/zero-knowledge-proof-zkp/circuits), where a groth16-based zk proof is generated. This proof maintains privacy while verifying personhood.

4\. **Proof of Personhood Token Generation**

Finally, the user submits the Proof of Personhood (PoP) to the issuer's smart contract, requesting a Hypersign KYC Token, which is a Soulbound Token signifying Proof of Personhood. The smart contract verifies the zk proof and mints a token directly to the user’s wallet, establishing a blockchain-backed verification of personhood.


# Proof Of KYC (PoK)

<figure><img src="/files/ztyom0LqqKkA3kI8rLBu" alt=""><figcaption></figcaption></figure>


# Proof Of Age (PoA)

<figure><img src="/files/grrPY6ByR8SN8HzTAZcL" alt=""><figcaption></figcaption></figure>


# Uniqueness Check


# Credential Revocability


# Machine Readable Zone (MRZ)


# Liveliness Check

Liveliness Check


# Zero Knowledge Proof (zkp)

###


# Introduction

Zero-knowledge proofs involve two parties: a prover and a verifier.

* The **prover** makes an assertion that his or her proof is valid
* which the **verifier** must approve, without the prover leaking any “knowledge” other than the assertion itself.

> **How can the verifier validate an assertion without any knowledge of the content and minimal interaction with the prover?**

*This is where zero-knowledge proofs become useful !*

* Imagine frequent scenarios when one reveals private information to verify something about one’s identity
* When one applies for a credit card, he or she must give up his social security number
* When one checks in for a flight at the airport, he or she must reveal all the private information present on the passport, such as birthdate or passport number
* Even on a day-to-day basis, when a user logs on to a web or mobile application, the user must enter a password to the account and send this sensitive information to the server, trust that the application securely handles this information, and that the password is not intercepted over the network.

### 3 Essential Properties of ZKP

1. **Completeness**: Suppose a prover knows a secret number 𝑥  that solves a particular equation. Completeness guarantees that, if 𝑥  is indeed the solution, the verifier will be convinced of this without directly learning 𝑥 .
2. **Soundness**: Imagine a prover doesn’t actually know the secret number 𝑥  but tries to fool the verifier into believing they do. Soundness ensures that any false or misleading proof will be detected by the verifier.
3. **Zero knowledge**: Continuing with our secret number 𝑥 , zero-knowledge means the verifier can be convinced that the prover knows 𝑥  without learning anything about 𝑥 itself or how to solve the equation.


# zk-SNARK

### Zero Knowledge Succinct Non-interactive Argument of Knowledge (zk-SNARK)

Zk-SNARKs are specifically [zero-knowledge proofs](/hypersign-id/concepts/zero-knowledge-proof-zkp/introduction) that are:

* **Succinct:** meaning they can be verified in the matter of milliseconds with a proof length of a few hundred byte&#x73;*.*
* **Non-interactive:** refers to fact that the prover can send a single message to the verifier, without having many back-and-forth interactions.&#x20;

> Apart from these 3 requirements for zkp, **completeness**, **soundness**, and **zero-knowledge**, zk-SNARK adds few more for efficiency for the proving system.

A notable advantage of zkSNARK's is their relatively *small proof sizes* and *constant-time verification*.

### Groth16

[Groth16](https://eprint.iacr.org/2016/260.pdf) is a proving scheme, which is widely-used, efficient ZK-SNARK protocol developed by Jens Groth in 2016 that *minimizes* proof size and verification time. It is a *circuit-specific* preprocessing general-purpose zk-SNARK construction. It has become a de-facto standard used in several blockchain projects due to the constant size of its proof, and its appealing verifier time.

{% hint style="info" %}
Although, Groth16 required circuit-specific [trusted setup](#trusted-setup), we decided not to go with Plonk because proof generation time in Plonk was very high (sometime in minutes) for our custom circuit.  Moreover, proofs are shorter in Groth16 hence better performance and less Gas consumption (?).
{% endhint %}

### BN128 elliptic curve

[Groth16](#groth16) need to be instantiated with an elliptic curve. To work with Groth16 curves must be:

1. Be secure, for proof soundness
2. Be pairing-friendly, for proof verification
3. Have a highly 2-adic subgroup order, for efficient proof generation.

We had four objectives while choosing the curve,&#x20;

* a) Proofs generation should be fast (should generate proofs in seconds and not in minutes)
* b) Proofs should be decently secure (we are "okay" with 128bit security)
* c) Proofs should be compatible (proofs generated should be compatible with Ethereum as well as Cosmwasm contracts)
* d) Proofs must be cost effective (should consume less gas)

We decided to go with `BN128` since its fast and is natively supported in Ethereum 1.0, which provides precompiled contracts for efficient pairing operations on this curve. As far as Cosmwasm is concerned, we had to use [3rd party libraries](https://github.com/hypersign-protocol/hypersign-kyc-contracts/blob/main/packages/hypersign-zk-verifier/Cargo.toml) to give support for `BN128` based proofs since Cosmwasm do not natively support this curve (yet).

{% hint style="info" %}
The `BN254` curve belongs to the BN family and is colloquially called `BN128` in reference to the nominal security of the curve, or `BN254` in reference to the bit-length of the relevant prime field. So not to be confused, they both are same.&#x20;
{% endhint %}

### Trusted Setup

Setting up the ZK-SNARK protocol requires the creation of a **Universal Common Reference String (CRS).** Also described as *public parameters*, the CRS enables secure communication between provers and verifiers.  This CRS must be generated in advance by a trusted party. But the security of a system based on zkSNARKs largely boils down to how the CRS was generated. Doing so without compromising the ideals of privacy-preserving blockchain-based systems: (security and decentralization) is very important. The generation of public parameters for zkSNARKs is called the **“setup ceremony”** because of its importance and the need for *multiple independent parties* to contribute to the process.&#x20;

The preferred technique for setup ceremonies has been multi-party computation (MPC). Setup ceremony MPC schemes are interactive protocols involving multiple parties who ***contribute randomness*** to iteratively construct the CRS. A typical ceremony consists of `N` number of players, the coordinator, and the verifier. The MPC protocols are always of a round-robin nature, where a player `Pi` receives a single message from player `Pi-1.`Payer `Pi` adds their input to *accumulated randomness* before passing it onto Player `Pi+1`. In the end, the final result is the CRS.

<figure><img src="/files/oMCJedEdAiSQdQzezupm" alt=""><figcaption><p>BGM17 MPC Protocol, Ref: <a href="https://zkproof.org/2021/06/30/setup-ceremonies/">https://zkproof.org/2021/06/30/setup-ceremonies/</a></p></figcaption></figure>

The CRS is generated in two phases:&#x20;

* The first phase (phase-1) referred to as “**Powers of Tau**”, produces generic setup parameters that can be used for all circuits of the scheme, up to a given size. This ceremony is *perpetual* — that is, there is no limit to the number of participants required, and any zk-SNARK project can pick any point of the ceremony to begin their circuit-specific second phase (phase-2).
* The second phase (phase-2) converts the output of the "Powers of Tau" phase (phase-1) into an NP-relation-specific (circuit-specific) CRS.

<mark style="color:orange;">How does PoT (phase-1) ceremony works?</mark>&#x20;

* Each participant will receive a *challenge* file.
* They must generate a *response* file in a secure and honest manner.&#x20;

> As long as one participant discards the toxic waste after this process, the entire ceremony can be trusted.

{% hint style="info" %}
We did not run our own PoT phase-1 ceremony, instead we used Ptau files (of power `19` or `512` max constraints) for BN128 curve with 54 contributions from iden3 [here](https://github.com/iden3/snarkjs?tab=readme-ov-file#7-prepare-phase-2).
{% endhint %}

<mark style="color:orange;">You might be wondering what exactly is this max-constraints?</mark>

* The Power of  Tau setup generates a series of powers of a secret value, `τ`, up to a specific limit, say `τ^N` . This maximum power `N` directly determines the maximum number of constraints that can be supported in circuits using these parameters.
* If the setup phase generates up to `τ^N`, it means that the final setup parameters can support up to **N constraints** in the ZK-SNARK circuit.
* iden3 ceremonies have gone as high as `τ^2^28`, which allows for up to **268 million constraints**.
* Higher values of `𝑁` increase the computational load of the setup ceremony but offer more flexibility for complex circuits in the future.

<mark style="color:orange;">and why did we choose 512 as our max constraints?</mark>&#x20;

Choosing the power `N` depends on circuits and its completxity. For example, for our custom KYC circuits we needed minimum power `19` to put in perspective zk-rollups may need millions of constraints hence they need to use higher power value.


# Circuits

### Arithmetic circuits <a href="#arithmetic-circuits" id="arithmetic-circuits"></a>

Circuit is like a program , which can be written in a programming language like Circom. However, internally a circuit is a **constraint system**; that is, a list of constraints which have a algebric forms;

{% hint style="info" %}
**Constraints:**

In order to use zk-SNARK protocols, we need to describe the relation between signals as a system of **equations** that relate variables with gates. The equations that describe the circuit is called **constraints.**&#x20;

Constraints **must be quadratic, linear or constant equations.** In general, circuits will have several constraints (typically, one per multiplicative gate). The set of constraints describing the circuit is called **rank-1 constraint system** (R1CS).&#x20;
{% endhint %}

* Since circuits are bit difficult for developers, we have programming languages (called DSL) for writing circuit logic. **Domain specific language (DSL)** : Circom, ZoKrates, Leo, Zinc, Cairo etc
* Once you written your program, it goes for compilation which converts the DSL into **SNARK friendly format** ([R1CS](https://tlu.tarilabs.com/cryptography/rank-1), AIR, plonk-CG etc)
* Once we convert into SNARK friendly format (constraint system), we generate public parameters (Sp, Sv) which is feeded into SNARK prover function to generate zk-proof.&#x20;

<figure><img src="/files/OFzQbqxf6emvEy8GayS6" alt=""><figcaption></figcaption></figure>

### Circom

`circom` allows programmers to define the [constraints](https://docs.circom.io/circom-language/constraint-generation) that define the arithmetic circuit. All constraints must be of the form `A*B + C = 0`, where `A`, `B` and `C` are linear combinations of signals. The arithmetic circuits built using `circom` operate on signals (inputs and outputs).

Zero-knowledge permits proving **circuit satisfiability**. What this means is, that you can prove that you know a set of signals that satisfy the circuit, or in other words, that you know a solution to the R1CS. This set of signals is called the **witness.**


# SSI and ZKP

> The idea of using zero knowledge proofs to prove claims about aspects of an individual’s identity is a major use case for zk-SNARKs.

Questions like:

* “Are you over 21”?
* “Do you live in the US?”
* “Are you employed?”
* “Are you a real human being?”

Could be answered!

### The catch?

> *<mark style="color:orange;">**Identity usecase like KYC, simply verifying the ZK proof isn’t enough!**</mark>*

Suppose a verifier wants to confirm that a person is over 21 using zero-knowledge technology. In theory, anyone could generate a valid ZK proof of being over 21 with a credential (containing a date of birth field) issued by any random issuer—even if the circuit verifies the issuer’s digital signature.

> <mark style="color:yellow;">How can the verifier be 100% certain that the proof was actually generated using a date of birth field that comes from a verifiable credential issued specifically by the trusted issuer?</mark>

To answer this question, we need to design our [circuit](/hypersign-id/concepts/zero-knowledge-proof-zkp/circuits) in such a way that it does the following this:&#x20;

1. Verifies if the issuer digital signature in the credential was correct?
2. Verifies if the credential was not revoked wrt current date?&#x20;
3. Verifies if user/holder's digital signature is correct?&#x20;
4. Verifies if user is above 21 (from the DOB field)?

Finally, exposes:&#x20;

* a) result of 4 (true/false),&#x20;
* b) issuer public key (or decentralised identity), &#x20;
* c) holder public key (or decentralised identity)&#x20;

as the public signal. Now send the *public signal* and *zk proof* both to the verifier.&#x20;

The verifier first checks that the exposed issuer’s public key (or DID) matches the trusted issuer’s identity, ensuring that the proof was indeed generated from a credential issued by a trusted source. Only then does it proceed to verify the ZK proof.

<figure><img src="/files/DYt1hOnA5PSmNwotEor5" alt=""><figcaption></figcaption></figure>


# Tutorials


# How to Integrate Hypersign ID Widget In your App?

How to integrate Hypersign ID Widget

This document is a comprehensive integration guide for developers embedding the pre-built **Hypersign KYC ID Widget** into their web applications. By utilizing the pre-built widget, you can deploy a secure, compliant, and conversion-optimized identity verification flow with minimal development effort, while leaving the heavy lifting of biometric processing and decentralized identity (DID) registration to Hypersign's backend.

### 1. Integration Architecture

* **Backend Application:** Securely manages your administrative `API_SECRET` keys, handles short-lived orchestration tokens, maps user profiles to Decentralized Identifiers (DIDs), and manages session instantiation.
* **Hypersign ID Widget:** A pre-built, optimized UI overlay hosted by Hypersign that seamlessly manages user-facing permissions, camera captures, automated OCR extraction, liveness detection, and zero-knowledge signature generation.
* **Frontend Application:** Initializes the client-side session handshake, embeds the Hypersign ID Widget popup container, and listens for real-time interface messaging events (such as session termination or validation errors) to seamlessly update your app's user interface.

```

+--------------------------------------------------+          +------------------+          +--------------------------------+
|                  Client Browser                  |          |  Your Backend    |          | Hypersign  Verification Service|
+--------------------------------------------------+          +------------------+          +--------------------------------+
|  Host Application   |    Hypersign ID Widget     |          |                  |          |                                |
+---------------------+----------------------------+          +------------------+          +--------------------------------+
           |                        |                           |                                       |
           | -- [1. Fetch Session & Session JWTs] ------------->|                                       |
           |                        |                           | -- [2. Authenticate & Create DID] --->|
           |                        |                           | <-- [3. Return App/User Tokens] ------|
           | <– [4. Mount Widget with Secure Tokens] -----------|                                       |
           |                        |                                                                   |
           |                        | ---- [5. Orchestrate Captures, Biometrics & ZK Proofs] ---------->|
           |                        |                                                                   |
           |                        |                           |<-- [6. Fire Webhook (Done)] ----------|
```

### 2. Base Configuration

#### Service URLs

Initialize the base endpoints for the Hypersign and credential routing services:

* `KYC_BASE_URL`: [https://api.cavach.hypersign.id](https://api.cavach.hypersign.id/);
* `SSI_BASE_URL`: [https://api.entity.hypersign.id](https://api.entity.hypersign.id/);
* `DEVELOPER_DASHBOARD_SERVICE_BASE_URL`: [https://api.entity.dashboard.hypersign.id](https://api.entity.dashboard.hypersign.id/);

#### Prerequisite Setup

1. **Dashboard Access:** Login to [Hypersign Dashboard](https://entity.dashboard.hypersign.id/) and [go through onboarding flow](/hypersign-developer-dashboard/onboarding) to setup your ID verification tenant.
2. **Environment Secrets:** Securely generate and download your `SSI_API_SECRET` and `KYC_API_SECRET` keys from the App Settings view. Store these in your backend `.env` configuration file.
3. **Issuer Information:** Copy your application's unique decentralised identifier configuration from the SSI sub-portal:
   1. Sample DID and Verification Method IDs&#x20;
      1. &#x20;`X_ISSUER_DID` :  `did:hid:z6MkmEFC8N1AUsinEBNSszXoepHb45p38ZwidV58r1HPqCkU`
      2. `X_ISSUER_VERMETHOD_ID` :`did:hid:z6MkmEFC8N1AUsinEBNSszXoepHb45p38ZwidV58r1HPqCkU#key-1`&#x20;
      3. Please make sure that `X_ISSUER_VERMETHOD_ID` is of type `Ed25519VerificationKey2020`&#x20;

You can keep these variables in your `.env`&#x20;

```
KYC_BASE_URL=
SSI_BASE_URL=
DEVELOPER_DASHBOARD_SERVICE_BASE_URL=
X_ISSUER_DID=
X_ISSUER_VERMETHOD_ID=
SSI_API_SECRET=
KYC_API_SECRET=
```

### 3. Backend Implementation (Node.js)

The backend acts as an authenticated proxy layer. Under no circumstances should administrative API secrets be exposed to client-side code.

#### STEP 1: Prepare Administrative Access Tokens

Administrative Bearer tokens for KYC and SSI services must be cached locally and refreshed automatically only upon token expiration.

```javascript
// In-memory token cache store sample
const tokenStoreCache = {};

async function fetchAdminAccessToken(apiSecret, serviceType) {
    const cachedToken = tokenStoreCache[serviceType];

    // Check if valid token exists and hasn't expired
    if (cachedToken && cachedToken.expiryTime > Date.now()) {
        return cachedToken.access_token;
    }

    const url = `${DEVELOPER_DASHBOARD_SERVICE_BASE_URL}/api/v1/app/oauth?grant_type=${serviceType}`;

    const response = await fetch(url, {
        method: 'POST',
        headers: {
            'X-Api-Secret-Key': apiSecret,
            'Accept': 'application/json'
        }
    });

    const result = await response.json();
    if (!response.ok) throw new Error(`Auth failed: ${result.message}`);
    
    const { access_token, expiresIn } = result;
    
    // Buffer expiration by 10 seconds to account for network latency
    const expiryTime = Date.now() + (expiresIn * 1000) - 10000;
  
    tokenStoreCache[serviceType] = {
        access_token,
        expiryTime
    };

    return access_token;
}
```

#### STEP 2: Register or Fetch User DID

Every user identity journey requires a unique Decentralized Identifier (DID) to cryptographically sign verification payloads.

> ⚠️ Ensure that your data workflow enforces a strict **1:1 mapping** between a single user profile (e.g., unique internal user ID/email) and their generated DID entity.

```javascript
const users = {}; // Represents your persistent user Database table

async function registerUserDid(ssiAdminToken, email) {
    // 1. Search persistent persistence layer for pre-existing DID mappings
    const user = users[email];
    if (user && user.did) {
        return {
            email,
            did: user.did,
            verificationMethodId: user.verificationMethodId
        };
    }

    // 2. Fall back to generating a new identity reference structure on-chain
    const res = await fetch(`${SSI_BASE_URL}/api/v1/did/create`, {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json',
            'Authorization': `Bearer ${ssiAdminToken}`
        },
        body: JSON.stringify({ namespace: '' })
    });
    
    const result = await res.json();
    if (!res.ok) throw new Error(`DID Creation Failed: ${result.message}`);
    
    // Extract target Ed25519 signature scheme details
    const method = result.metaData.didDocument.verificationMethod.find(
        m => m.type === 'Ed25519VerificationKey2020'
    );

    // 3. Persist state changes inside application storage boundaries
    users[email] = { did: result.did, verificationMethodId: method.id };
    
    return {
        email,
        did: result.did,
        verificationMethodId: method.id
    };
}

```

#### STEP 3: Initialize the KYC Verification Session

Instantiate a remote verification journey record state block.

> ⏳ **Session Lifespan**: KYC state tracks a maximum validity window of **24 hours**.

```javascript
const userKycSessions = {}; // Local session reference matrix mapping tracking table

async function initializeVerificationSession(kycAdminToken, email) {
    const response = await fetch(`${KYC_BASE_URL}/api/v2/session`, {
        method: 'POST',
        headers: {
            'x-kyc-access-token': kycAdminToken,
            'Content-Type': 'application/json'
        }
    });

    const result = await response.json();
    if (!response.ok) throw new Error(`Session Init Failed: ${result.message}`);
    
    const sessionId = result.data.sessionId;

    // Persist session locally with pending validation flag
    userKycSessions[email] = {
        email,
        sessionId,
        isVerified: false
    };
  
    return sessionId;
}

```

#### STEP 4: Generate User-Specific Bearer Token

Issue highly restricted, temporary user token for the frontend widget that can only be used to complete the current user's specific KYC session.

```javascript
async function generateKycUserSessionToken(claims, kycAdminToken, ssiAdminToken, sessionId) {
    // A. Issue a DID-signed administrative JWT wrapper declaring user identity claims
    const ssiRes = await fetch(`${SSI_BASE_URL}/api/v1/did/auth/issue-jwt`, {
        method: "POST",
        headers: { 
            "Authorization": `Bearer ${ssiAdminToken}`, 
            "Content-Type": "application/json" 
        },
        body: JSON.stringify({
            issuer: { verificationMethodId: X_ISSUER_VERMETHOD_ID, did: X_ISSUER_DID },
            audience: KYC_BASE_URL,
            claims: claims, 
            ttlSeconds: 3600
        })
    });
    
    const ssiResult = await ssiRes.json();
    if (!ssiRes.ok) throw new Error(`SSI JWT Issuance Failed: ${ssiResult.message}`);
    const { accessToken: didJwt } = ssiResult;

    // B. Exchange the DID-signed assertion JWT wrapper for a scoped User Access token
    const kycRes = await fetch(`${KYC_BASE_URL}/api/v2/auth/exchange`, {
        method: "POST",
        headers: {
            "x-ssi-access-token": ssiAdminToken,
            "x-kyc-access-token": kycAdminToken,
            "Authorization": `Bearer ${didJwt}`,
            "Content-Type": "application/json"
        },
        body: JSON.stringify({ provider: "client_auth", sessionId })
    });
    
    const finalResult = await kycRes.json();
    if (!kycRes.ok) throw new Error(`KYC Token Exchange Failed: ${finalResult.message}`);
    
    return finalResult.data.kycServiceUserAccessToken;
}

```

> User's claims field **MUST** contain did and email fields

#### STEP 5: Composite Orchestration Route

Expose a single unified endpoint to provision the client onboarding setup details:

```javascript
app.post('/api/v1/onboarding/setup', async (req, res) => {
    try {
        const { email } = req.body;
        if (!email) {
            return res.status(400).json({ error: "Missing identity parameter 'email'" });
        }

        // 1. Resolve administrative application boundary tokens
        const kycAdminToken = await fetchAdminAccessToken(process.env.KYC_API_SECRET, 'access_service_kyc');
        const ssiAdminToken = await fetchAdminAccessToken(process.env.SSI_API_SECRET, 'access_service_ssi');

        // 2. Provision identity context structures
        const userClaims = await registerUserDid(ssiAdminToken, email);

        // 3. Instantiate transactional session reference
        const sessionId = await initializeVerificationSession(kycAdminToken, email);

        // 4. Derive isolated frontend action assertion token context 
        const userBearerToken = await generateKycUserSessionToken(
            userClaims, // user's `claims` field MUST contain `did` and `email` fields
            kycAdminToken,
            ssiAdminToken,
            sessionId
        );

        // 5. Package and emit execution parameters safely to client space
        res.status(200).json({
            kycAdminToken,
            ssiAdminToken,
            userBearerToken,
            sessionId,
        });

    } catch (error) {
        console.error(`[Onboarding Flow Error]:`, error);
        res.status(500).json({ error: "Internal initialization process failure" });
    }
});

```

### 4. Frontend Implementation

#### Step 1: Client Workspace Handshake

Query your secure application backend domain endpoints to collect the runtime authorization variables.

```javascript
let state = null;

async function initKycUI(userEmail) {
    const response = await fetch(`/api/v1/onboarding/setup`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ email: userEmail }),
    });
    
    const data = await response.json();
    if (!response.ok) throw new Error(data.error || "Failed to initialize setup credentials");

    // Initialize state mapping matrix safely inside local runtime space
    state = {
        tokens: { 
            kycAdmin: data.kycAdminToken, 
            ssiAdmin: data.ssiAdminToken, 
            userBearer: data.userBearerToken 
        },
        session: { id: data.sessionId },
    };
}

```

#### Step 2: Render & Orchestrate Verification Window

Build the Widget URL with the required security tokens and embede in your frontend

```javascript
const WIDGET_BASE_URL = "https://verify.hypersign.id";
let widgetCloseTimer = null;

function buildWidgetUrl() {
    const url = new URL(WIDGET_BASE_URL);
    url.searchParams.set("kycAccessToken", state.tokens.kycAdmin);
    url.searchParams.set("ssiAccessToken", state.tokens.ssiAdmin);
    url.searchParams.set("sessionId", state.session.id);
    url.searchParams.set("kycUserAccessToken", state.tokens.userBearer);
    return url.toString();
}

```

> Widget URL Format: `https://verify.hypersign.id?kycAccessToken=<kycAccessToken>&ssiAccessToken=<ssiAccessToken>&sessionId=<sessionId>&kycUserAccessToken=<kycUserAccessToken>`

#### Step 3: Invoking the widget

You can invoke the Hypersign KYC widget through popup from your page

```javascript
function openVerificationFlow() {
    const targetUrl = buildWidgetUrl();
    const widgetWindow = window.open(targetUrl, 'hypersignKycWidget', 'width=440,height=900,resizable=yes');

    if (!widgetWindow) {
        throw new Error("Navigation Container Blocked. Please check browser pop-up permissions.");
    }

    // Monitor for abrupt window exit actions
    widgetCloseTimer = window.setInterval(() => {
        if (!widgetWindow || widgetWindow.closed) {
            window.clearInterval(widgetCloseTimer);
            handleWidgetTermination();
        }
    }, 1000);
}

function handleWidgetTermination() {
    console.log("Verification modal interaction window was altered or closed by user.");
}
```

#### Step 4: Listening to Widget Events

The Hypersign KYC Widget communicates with your application using the browser's `window.postMessage()` API.

Once a verification session completes (either successfully or with an error), the widget emits an event that your application can listen for. This allows you to update your UI, redirect users, or handle verification failures.

> **Note:** A successful widget event (`VERIFICATION_SUCCESS`) indicates that the user has successfully completed the verification flow in the widget. Final verification results should always be confirmed using your configured webhook or by fetching the verification session via the API.

```javascript
window.addEventListener("message", (event) => {
  try {
    const payload =
      typeof event.data === "string"
        ? JSON.parse(event.data)
        : event.data;

    const { status, code, message } = payload;
    if (status === "success" && code === "VERIFICATION_SUCCESS") {
      window.clearInterval(widgetCloseTimer);
      console.log("Verification completed:", message);
      // Update your UI while waiting for the webhook
      // e.g. show "Verification in progress"
    }

    if (status === "error") {
      window.clearInterval(widgetCloseTimer);
      handleKycErrorStates(code);
    }
  } catch (err) {
    console.error("Failed to parse widget event.", err);
  }
});
```

### Event Payload

Every event emitted by the widget follows the same structure.

| Field     | Type     | Description                                            |
| --------- | -------- | ------------------------------------------------------ |
| `status`  | `string` | Indicates whether the event is a `success` or `error`. |
| `code`    | `string` | Machine-readable event or error code.                  |
| `message` | `string` | Human-readable description of the event.               |

**Success Event**

```
{  "status": "success",  "code": "VERIFICATION_SUCCESS",  "message": "Successfully verified the user."}
```

**Error Event**

```
{  "status": "error",  "code": "SESSION_EXPIRED",  "message": "Session expired."}
```

#### Error Codes

The widget may emit the following error codes.

| Code                             | Description                                                                                           |
| -------------------------------- | ----------------------------------------------------------------------------------------------------- |
| `SESSION_EXPIRED`                | The verification session has expired. Create a new session and restart the verification flow.         |
| `ACCESS_TOKEN_EXPIRED`           | The widget access token has expired. Generate a new token before launching the widget again.          |
| `LIVELINESS_VERIFICATION_FAILED` | Face liveness verification failed. The user should retry the biometric verification.                  |
| `DOCUMENT_VERIFICATION_FAILED`   | The uploaded identity document could not be verified.                                                 |
| `ZK_PROOF_GENERATION_FAILED`     | An unexpected error occurred while generating the cryptographic proof. Please retry the verification. |

### 5. Webhook Integration

#### Step 1: Expose Webhook Route

To consume async confirmation messages emitted by the Hypersign verification services engine, map a public endpoint inside your backend router.

```
+--------------------------------+              +-------------------------+
| Hypersign Verification Service |              |  Your Application Host  |
+--------------------------------+              +-------------------------+
            |                                        |
            | --- [POST /api/v1/webhook/kyc] ------->|  (Extract idToken)
            |                                        |
            | <--- [GET /user-consent?idToken=...] --|  (Fetch Verification Data)
            |                                        |
            | ---- [Returns JSON Credential] ------->|  (Update Database state)

```

Configure your route location setup (e.g., `https://yourdomain.com/api/v1/webhook/kyc`) in the **Hypersign ID Dashboard** under Webhook Configurations.

#### Step 2: Handle Webhook Events & Verify User Consent

Webhooks work via a **Fire-and-Forget** architectural notification strategy. When an evaluation lifecycle phase registers adjustments, the server pushes identity signatures containing data reference points directly to your destination handler:

**Expected Webhook Payload Structure**

```json
{
   "idToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
   "sessionId": "8814e6d0-1f5f-458b-8b58-fe413de19774"
}
```

#### **Step 3: Implement Webhook Listener and Token Verification**

Upon receiving the payload, make a back-channel request using your `kycAccessToken` to download the fully verified data packet structures.

```javascript
app.post('/api/v1/webhook/kyc', async (req, res) => {
    try {
        const { idToken, sessionId } = req.body;
        
        // Return 200 immediately to prevent timing timeouts on Hypersign framework
        res.status(200).json({ received: true });

        // Retrieve background administrative tokens to perform the lookups
        const kycAdminToken = await fetchAdminAccessToken(process.env.KYC_API_SECRET, 'access_service_kyc');

        // Request full document parsing using the verification identity token payload
        const complianceVerificationUrl = `${KYC_BASE_URL}/api/v1/e-kyc/verification/user-consent?idToken=${idToken}`;
        
        const dataFetchResponse = await fetch(complianceVerificationUrl, {
            method: 'GET',
            headers: {
                'x-kyc-access-token': kycAdminToken
            }
        });

        const consentDataResponse = await dataFetchResponse.json();
        
        if (consentDataResponse && consentDataResponse.success) {
            const targetEmail = Object.keys(userKycSessions).find(email => userKycSessions[email].sessionId === sessionId);
                
            if (targetEmail) {
                // Update user profile status inside database state persistence
                userKycSessions[targetEmail].isVerified = true;
                userKycSessions[targetEmail].credentialId = userCredentialPayload.id;
                
                console.log(`Identity verified successfully for profile account path: ${targetEmail}`);
            }
        }
    } catch (webhookProcessingError) {
        console.error(`[Webhook Process Processing Error Event]:`, webhookProcessingError);
    }
});

```

Example consentDataResponse for `Proof Of Age` consent

```json
{
    "success": true,
    "message": "success",
    "data": {
        "sessionId": "1b5b9cea-45bb-4a26-b76b-61e4d4a4c744",
        "presentation": {
            "@context": [
                "https://www.w3.org/2018/credentials/v1"
            ],
            "type": [
                "VerifiablePresentation"
            ],
            "verifiableCredential": [
                {
                    "@context": [
                        "https://www.w3.org/2018/credentials/v1",
                        "https://raw.githubusercontent.com/hypersign-protocol/hypersign-contexts/main/BJJSignature2021.jsonld",
                        "https://schema.org"
                    ],
                    "id": "vc:hid:z6MkuZKDPydmCgv2K1ekV3m2weQ2G88SpibLE5HvN1Gm75uZ",
                    "type": [
                        "VerifiableCredential",
                        "zkProofOfAge"
                    ],
                    "issuer": "did:hid:z3YsrhDHXqceBf2LUs4nJZF4JXdGJwQv8gwqrYqTNM5DJ",
                    "issuanceDate": "2026-06-29T13:36:00Z",
                    "expirationDate": "2027-12-10T18:30:00Z",
                    "credentialSubject": {
                        "proof": {
                            "pi_a": "AUAAv/8bgOw32obJEwc0ECU..9wsgA",
                            "pi_b": "AYAAf/8RFt9mNF7JJv0..VD2LPsy5acCoFsPXheyUqLf8LFaXIWWLApXGhVG8K+8wbWbUqT6QA==",
                            "pi_c": "AUAAv/8TiZa9PEPIPwXeHB...hwZBTrua7MEkY7Yv",
                            "protocol": "groth16",
                            "curve": "bn128"
                        },
                        "publicSignals": [
                            "BcEBAQAwCAKwS...NG6he3tV+Hw==",
                            "MwQA",
                            "MzIAAA==",
                            "BcEBAQAwCAKwSn..K7vM7d0csbuqgHw==",
                            "FcOBDcAwDAKwl4A..uTbiMrInt9ODR8gM=",
                            "HcXBEQAwCAKwlV...Owo2PriSIaQ7WGz2gn4="
                        ],
                        "criteria": {
                            "type": "Requirement",
                            "attribute": "age",
                            "operator": ">",
                            "value": 20,
                            "unit": "years"
                        },
                        "criteriaVerified": true,
                        "id": "did:hid:z6MkjBaYmFA1qQPVrL22SUJipXUGeydJwtRC4fVWGUJFBE6m"
                    },
                    "credentialStatus": {
                        "id": "https://api.atman.hypersign.id/hypersign-protocol/hidnode/ssi/credential/vc:hid:z6MkuZKDPydmCgv2K1ekV3m2weQ2G88SpibLE5HvN1Gm75uZ",
                        "type": "HypersignCredentialStatus2023"
                    },
                    "proof": {
                        "type": "BJJSignature2021",
                        "created": "2026-06-29T13:37:42Z",
                        "verificationMethod": "did:hid:z3YsrhDHXqceBf2LUs4nJZF4JXdGJwQv8gwqrYqTNM5DJ#key-1",
                        "proofPurpose": "assertionMethod",
                        "proofValue": "z5ofZ6iAgYn896u65...5QkBiKjMofm5"
                    }
                }
            ],
            "id": "vp:hid:z6MkngSE9cDhPbgBLS2XC8yw3EKSxxrn14WvsEmxQb5ES4Qe",
            "holder": "did:hid:z6MkjBaYmFA1qQPVrL22SUJipXUGeydJwtRC4fVWGUJFBE6m"
        }
    }
}
```

### Troubleshooting

#### Popup window is blocked

**Problem**

The verification widget does not open.

**Solution**

Most browsers block popups that are not triggered by a user action. Launch the widget only in response to a button click or another direct user interaction.

***

#### Session Expired

**Error Code**

`SESSION_EXPIRED`

**Cause**

The verification session has expired (sessions are valid for 24 hours).

**Solution**

Create a new verification session by calling the Session API and launch the widget again.

***

#### Access Token Expired

**Error Code**

`ACCESS_TOKEN_EXPIRED`

**Cause**

The KYC or SSI administrative access token has expired.

**Solution**

Generate a new administrative access token using your API Secret and retry the request.

***

#### Document Verification Failed

**Error Code**

`DOCUMENT_VERIFICATION_FAILED`

**Cause**

The uploaded document could not be verified.

**Possible Reasons**

* Blurry image
* Unsupported document
* Partial document capture
* Damaged document

**Solution**

Ask the user to upload a clearer image or capture the document again.

***

#### ZK Proof Generation Failed

**Error Code**

`ZK_PROOF_GENERATION_FAILED`

**Cause**

The widget failed while generating the zero-knowledge proof.

**Solution**

Retry the verification. If the issue persists, contact Hypersign Support.

***

#### Webhook Not Received

**Possible Causes**

* Incorrect webhook URL
* Endpoint is not publicly accessible
* Server returned a non-2xx response
* Firewall blocked the request

**Solution**

* Verify the webhook URL configured in the Hypersign Dashboard.
* Ensure the endpoint is publicly accessible.
* Verify your server responds with HTTP 200.

***

#### User Closed the Widget

If the user closes the popup before completing verification, simply allow them to launch the widget again.

The current verification session remains valid until it expires.


# How to add your team member?

Logon to the Entity Developer Dashboard.

Follow the instructions here:&#x20;

{% content-ref url="/pages/dQhwtMnM1Z0cL4gkGzlu" %}
[Members & Roles](/hypersign-developer-dashboard/members-and-roles)
{% endcontent-ref %}


# How does Hypersign OnChain KYC Works?

### Before we start the integration, it would be great to understand the user experience through this demo: <br>

{% embed url="<https://www.youtube.com/watch?v=aJ1Iy3xOdyU>" %}

### Basic Architecture and Flow

<figure><img src="/files/GXvZt4RlESprSwR0ZEWi" alt=""><figcaption></figcaption></figure>

1. The user navigates to the dApp’s UI.
2. The dApp prompts the user to connect their wallet.
3. The user connects and provides their wallet address.
4. The dApp checks the Trusted Issuer’s Token contract ([Hypersign KYC Token Contract](/hypersign-id/on-chain-kyc/contracts-deployment#deploy-hypersign-kyc-token-contract-sbt)) to verify if the user has already minted a ProofOfKYC Soulbound Token.
5. If not, the user initiates the on-chain KYC process through the Hypersign KYC widget:
   1. The user completes a liveness check by providing video KYC and receives a [PersonhoodCredential](/hypersign-id/concepts/credentials-types/personhood-credential) from the KYC server, which is stored in their data vault.
   2. The user then proceeds with ID verification, receives a [KYCCredential](/hypersign-id/concepts/credentials-types/passport-govt.-id-credential) from the KYC server, and stores it in their data vault.&#x20;
6. Next, the user begins with the on-chain ID minting.
   1. User generates requested [zero knowledge proofs ](/hypersign-id/concepts/zero-knowledge-proof-zkp)([supported proofs](/hypersign-id/concepts/zk-proof-types)) from their respective credentials
   2. User then submit[ zk proofs](/hypersign-id/concepts/zero-knowledge-proof-zkp) to the issuer contracts and requests for respective KYC tokens (which is basically SBTs)&#x20;
   3. The Issuer contract verifies the zk proof and mints KYC token in user’s wallet address.&#x20;
7. The user provides consent for data access to the dApp.
8. Upon receiving the user’s consent, the dApp calls the its smart contract to perform on-chain ID verification.
9. The smart contract queries the trusted Issuer’s [KYC token](/hypersign-id/on-chain-kyc/kyc-token-metadata) contract to check if the wallet address has required KYC tokens. If found, the user is considered verified on-chain.

{% hint style="info" %}
ZK proofs and [OnChain ID](/hypersign-id/on-chain-kyc) are optional; if you prefer not to use [OnChain ID](/hypersign-id/on-chain-kyc), you can still verify a user's ID off-chain.
{% endhint %}

{% hint style="info" %}
ZK proofs can be used independently in off-chain mode without requiring OnChain ID (token minting). It is not mandatory to use ZK proofs exclusively with OnChain ID. However, the reverse is not possible; OnChain ID requires ZK proofs.
{% endhint %}


# How to Build a Custom KYC Flow with the Hypersign ID APIs?

This document is for developers building a custom UI to integrate with **Hypersign ID and SSI APIs**. By using these APIs directly instead of the pre-built widget, you maintain total control over your UI/UX while leveraging decentralized identity (DID) infrastructure.

***

### 1. Integration Architecture

The integration follows a **Security-First Handshake** model:

* **Backend:** Securely manages the `API_SECRET`, fetches administrative tokens, and registers User DIDs.
* **Frontend:** Handles the camera interface, performs OCR extraction, executes Face Match, and signs the final Consent via a Verifiable Presentation.

***

### 2. Base Configuration

#### Service URLs

```js
const KYC_BASE_URL = "https://api.cavach.hypersign.id";
const SSI_BASE_URL = "https://api.entity.hypersign.id";
const DEVELOPER_DASHBOARD_SERVICE_BASE_URL = "https://api.entity.dashboard.hypersign.id"
```

#### Prerequisite Setup

1. **Dashboard Access:** Create your developer account inside the [Hypersign Dashboard](https://entity.dashboard.hypersign.id/).
2. **Environment Secrets:** Securely generate and download your `SSI_API_SECRET` and `KYC_API_SECRET` keys from the App Settings view. Store these in your backend `.env` configuration file.
3. **Issuer Information:** Copy your application's unique decentralized identifier configuration from the SSI sub-portal:

```javascript
const X_ISSUER_DID = "did:hid:z6MkmEFC8N1AUsinEBNSszXoepHb45p38ZwidV58r1HPqCkU";
const X_ISSUER_VERMETHOD_ID = "did:hid:z6MkmEFC8N1AUsinEBNSszXoepHb45p38ZwidV58r1HPqCkU#key-1"; 
```

> Note: Please make sure that `X_ISSUER_VERMETHOD_ID` is of type `Ed25519VerificationKey2020`

You can keep these variables in your `.env`

```
KYC_BASE_URL=
SSI_BASE_URL=
DEVELOPER_DASHBOARD_SERVICE_BASE_URL=
X_ISSUER_DID=
X_ISSUER_VERMETHOD_ID=
SSI_API_SECRET=
KYC_API_SECRET=
```

***

### 3. Backend Implementation (Node.js)

The backend acts as a secure proxy to ensure administrative keys are never exposed to the browser.

#### STEP 1: Prepare Administrative Access Tokens

Administrative tokens for KYC and SSI services should be cached locally and refreshed only upon expiry.

```js
async function fetchAdminAccessToken(apiSecret, serviceType) {
  const url = `${DEVELOPER_DASHBOARD_SERVICE_BASE_URL}/api/v1/app/oauth?grant_type=${serviceType}`;

  const response = await fetch(url, {
    method: 'POST',
    headers: {
        'X-Api-Secret-Key': apiSecret,
        'Accept': 'application/json'
    }
  });

  const result = await response.json();
  if (!response.ok) throw new Error(`Auth failed: ${result.message}`);
  return result.access_token;
}
```

#### STEP 2: Initialize the KYC Verification Session

Create a unique session for the user's verification journey.

```js
async function initializeVerificationSession
(kycAdminToken){
  const response = await fetch(`${KYC_BASE_URL}/api/v2/session`, {
    method: 'POST',
    headers: {
        'x-kyc-access-token': kycAdminToken,
        'Content-Type': 'application/json'
    }
  });

  const result = await response.json();
  return result.data.sessionId;
}
```

#### STEP 3: Register User DID

Every user requires a DID to sign their final verification results.

```js
async function registerUserDid(ssiAdminToken) {
    const res = await fetch(`${SSI_BASE_URL}/api/v1/did/create`, {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json',
            'Authorization': `Bearer ${ssiAdminToken}`
        },
        body: JSON.stringify({ namespace: '' })
    });
    const result = await res.json();
    
    // Find the Ed25519 key method required for signatures
    const method = result.metaData.didDocument.verificationMethod
                   .find(m => m.type === 'Ed25519VerificationKey2020');

    return {
        did: result.did,
        verificationMethodId: method.id
    };
}
```

#### STEP 4: Generate User-Specific Bearer Token

This token authorizes the frontend to perform biometric actions for this specific session only.

```js
async function generateKycUserSessionToken(claims, kycAdminToken, ssiAdminToken, sessionId) {
    // A. Issue a DID-signed JWT
    const ssiRes = await fetch(`${SSI_BASE_URL}/api/v1/did/auth/issue-jwt`, {
        method: "POST",
        headers: { "Authorization": `Bearer ${ssiAdminToken}`, "Content-Type": "application/json" },
        body: JSON.stringify({
            issuer: { verificationMethodId: X_ISSUER_VERMETHOD_ID, did: X_ISSUER_DID },
            audience: KYC_BASE_URL,
            claims: claims,
            ttlSeconds: 3600
        })
    });
    const { accessToken: didJwt } = await ssiRes.json();

    // B. Exchange JWT for the KYC User Access Token
    const kycRes = await fetch(`${KYC_BASE_URL}/api/v2/auth/exchange`, {
        method: "POST",
        headers: {
            "x-ssi-access-token": ssiAdminToken,
            "x-kyc-access-token": kycAdminToken,
            "Authorization": `Bearer ${didJwt}`,
            "Content-Type": "application/json"
        },
        body: JSON.stringify({ provider: "client_auth", sessionId })
    });
    const finalResult = await kycRes.json();
    return finalResult.data.kycServiceUserAccessToken;
}
```

#### STEP 5: Implement an API to return relevant tokens in frontend

```js


app.get('/get-required-tokens-and-session-for-a-user', async (req, res) => {
    try {
        // 1. Prepare Administrative Access Tokens (using file-based cache)
        const kycAdminToken = await fetchAdminAccessToken(KYC_API_SECRET, 'access_service_kyc') // Generate KYC Access Token
        const ssiAdminToken = fetchAdminAccessToken(SSI_API_SECRET, 'access_service_ssi') // Generate SSI Access Token

        // 2. Initialize the KYC Verification Session
        const sessionId = await initializeVerificationSession(kycAdminToken);

        // 3. Register a new User DID
        const userDidMetadata = await registerUserDid(ssiAdminToken);

        // 4. Prepare User Claims for the DID JWT
        const userData = {
            name: "John",
            email: "john@gmail.com", // Mandatory
            userDid: userDidMetadata.did, // Mandatory
        };

        // 5. Generate the final User-specific Bearer Token
        const userBearerToken = await generateKycUserSessionToken(
            userData,
            kycAdminToken,
            ssiAdminToken,
            sessionId
        );

        // 6. Return comprehensive credentials to the client
        res.json({
            kycAdminToken,
            ssiAdminToken,
            userBearerToken,
            issuerDid: X_ISSUER_DID,
            issuerVerificationMethodId: X_ISSUER_VERMETHOD_ID,
            sessionId,
            userDid: userDidMetadata.did,
            userVerificationMethodId: userDidMetadata.verificationMethodId
        });

    } catch (error) {
        console.error(`[Onboarding Flow Error]: ${error.message}`);
        res.status(400).json({ error: error.message });
    }
});
```

***

### 4. Frontend Implementation

#### Step 1: Initialize Session

Call your backend endpoint to receive all necessary session and admin tokens.

```js
async function initKycUI() {
    const response = await fetch(`/get-required-tokens-and-session-for-a-user`);
    const data = await response.json();

    // Map backend response to local state
    const state = {
        tokens: { 
            kycAdmin: data.kycAdminToken, 
            ssiAdmin: data.ssiAdminToken, 
            userBearer: data.userBearerToken 
        },
        session: { id: data.sessionId },
        user: { did: data.userDid, methodId: data.userVerificationMethodId },
        issuer: { did: data.issuerDid, methodId: data.issuerVerificationMethodId }
    };
}
```

#### Step 2: Document OCR Extraction

After capturing the ID document via the camera, send the Base64 image for extraction.

```js
async function processDocumentExtraction(base64Image) {
    const response = await fetch(`${KYC_BASE_URL}/api/v2/documents/extract`, {
        method: 'POST',
        headers: {
            'x-kyc-access-token': state.tokens.kycAdmin,
            'x-ssi-access-token': state.tokens.ssiAdmin,
            'Authorization': `Bearer ${state.tokens.userBearer}`,
            'Content-Type': 'application/json'
        },
        body: JSON.stringify({
            documentFront: base64Image,
            sessionId: state.session.id,
            documentType: "PASSPORT" // enum value
        })
    });

    const result = await response.json();
    state.session.extractionToken = result.data.extractionToken;
}
```

**documentType** (enum)

Allowed values:

* `PASSPORT`
* `GOVT_ID`

#### Step 3: Identity Verification (Face Match)

Matches the selfie against the extracted document data.

```js
async function performIdentityMatch(base64Selfie) {
    const response = await fetch(`${KYC_BASE_URL}/api/v2/biometrics/verify`, {
        method: 'POST',
        headers: {
            'x-kyc-access-token': state.tokens.kycAdmin,
            'x-ssi-access-token': state.tokens.ssiAdmin,
            'x-issuer-did': state.issuer.did,
            'x-issuer-did-ver-method': state.issuer.methodId,
            'Authorization': `Bearer ${state.tokens.userBearer}`,
            'Content-Type': 'application/json'
        },
        body: JSON.stringify({
            documentToken: state.session.extractionToken,
            sessionId: state.session.id,
            selfieImage: base64Selfie,
            holderDid: state.user.did,
        })
    });

    const result = await response.json();
    if (result.success) {
        await submitUserConsent(result.data.credentials);
    }
}
```

#### Step 4: Final Consent & SSI Presentation

Finalize the process by creating a Verifiable Presentation and submitting it to the KYC service.

```js
async function submitUserConsent(credentials) {
    // 1. Create Presentation via SSI API
    const vpRes = await fetch(`${SSI_BASE_URL}/api/v1/presentation`, {
        method: 'POST',
        headers: { 
            'Authorization': `Bearer ${state.tokens.ssiAdmin}`,
            'Content-Type': 'application/json'
        },
        body: JSON.stringify({
            credentialDocuments: credentials,
            holderDid: state.user.did,
            challenge: state.session.id,
            domain: window.location.origin,
            verificationMethodId: state.user.methodId
        })
    });
    const vpData = await vpRes.json();

    // 2. Submit Final Consent to KYC Service
    await fetch(`${KYC_BASE_URL}/api/v2/consents`, {
        method: 'POST',
        headers: { 
            'x-kyc-access-token': state.tokens.kycAdmin,
            'Authorization': `Bearer ${state.tokens.userBearer}`,
            'Content-Type': 'application/json'
        },
        body: JSON.stringify({
            sessionId: state.session.id,
            presentation: vpData.presentation
        })
    });
}
```

***


# How to Verify Users Without Any Integration?

## Hosted Verification Page

Launch a branded identity verification page in minutes—no SDKs, APIs, or application integration required.

The Hosted Verification Page allows you to create a secure, shareable verification link that users can open in any browser to complete their KYC verification. It's the fastest way to start verifying users without building or maintaining your own application.

This integration is ideal for organizations that:

* Don't have a web or mobile application
* Need to onboard users quickly with minimal setup
* Run crypto communities or DAOs
* Perform manual or operations-led onboarding
* Want to validate a proof of concept before investing in a deeper integration

Once a user completes verification, you can monitor their verification status and results directly from the Hypersign Dashboard.

Login to [Hypersign Dashboard ](https://entity.dashboard.hypersign.id/)and setup your account by going through[ onboarding flow.](/hypersign-developer-dashboard/onboarding) Once your account is setup, navigate to "**ID Verifier Configuration**" page under the solution section:&#x20;

<figure><img src="/files/IJZAgO15nnRKdwcGuiOn" alt=""><figcaption></figcaption></figure>

### How it works?

The Hosted Verification Page can be configured entirely from the Hypersign Dashboard.

1. Configure your hosted verification page.
2. Customize the page with your branding.
3. Generate a secure verification link.
4. Share the link with your users.
5. Track verification progress and results from the dashboard.

### Share the Verification Link

Once the details are filled in **ID verifier configuration** page, a Hypersign immediately updates your hosted verification page and generates a shareable verification link.&#x20;

<figure><img src="/files/oYj9EJ4hBIutuMj3ZLmT" alt=""><figcaption></figcaption></figure>

Copy the generated URL and send it to your users through any channel, including:

* Email
* WhatsApp
* Telegram
* Discord
* SMS
* Customer support tickets

Users simply open the link in their browser and complete the verification process—no application installation or account creation is required.

<figure><img src="/files/oQBt1iv0r3rRMni9RlX1" alt=""><figcaption></figcaption></figure>


# How to Integrate Aadhaar Verification APIs?

Hypersign's **Compliant Aadhaar Verification APIs** enable organizations to securely verify an individual's Aadhaar identity while supporting modern privacy and compliance requirements.

The platform provides multiple verification methods that can be used independently or combined to achieve the desired level of identity assurance:

* **Aadhaar OTP Verification** – Verify an individual's Aadhaar using the OTP sent to their Aadhaar-linked mobile number.
* **Aadhaar Secure QR Verification** – Verify the authenticity of an Aadhaar card by validating the UIDAI-issued digital signature embedded in the Secure QR Code and extract the verified Aadhaar details.
* **Aadhaar Face Match** – Perform biometric verification by comparing a live selfie with the Aadhaar photograph to confirm that the person presenting the Aadhaar is its legitimate holder.
* **Selective Disclosure** – Request only the Aadhaar attributes required for your business purpose, reducing unnecessary personal data processing while receiving cryptographically verifiable proof of the disclosed information.

These APIs can be combined to support different onboarding and verification journeys based on your application's security, compliance, and user experience requirements.

Whether you are building a banking application, digital onboarding platform, employee verification system, or customer KYC workflow, Hypersign enables you to implement Aadhaar verification with **Privacy by Design**, **data minimization**, and **cryptographic verifiability** from day one.

***

## Supported Verification Flows

<figure><img src="/files/CcmyggmUffnUvDNl2PAV" alt=""><figcaption></figcaption></figure>

## Base URL

```
https://api.cavach.hypersign.id
```

## Authentication

All Aadhaar Verification APIs require an **Access Token** for authentication.

Authentication is a two-step process:

1. Generate a **KYC API Secret** from the Hypersign Dashboard.
2. Exchange the API Secret for a short-lived **Access Token**.

The generated Access Token must be included in the `Authorization` header of every API request. Please also read [#detailed-steps-to-generate-access-token](#detailed-steps-to-generate-access-token "mention")section.

## Generate Aadhaar OTP

Generates an OTP on the mobile number linked with the Aadhaar number.

### POST /api/v1/aadhaar/otp/generate

#### Request Body

```
{
  "aadhaar_number": "111122223333",
  "reason": "For KYC"
}
```

| Field            | Type   | Required | Description                                                                                                    |
| ---------------- | ------ | -------- | -------------------------------------------------------------------------------------------------------------- |
| `aadhaar_number` | string | Yes      | 12-digit Aadhaar number of the user. **For development/sandbox mode, use `111122223333`.**                     |
| `reason`         | string | Yes      | Purpose for generating the OTP (for example: `"For KYC"`). This may be used for audit and compliance purposes. |

#### Successful Response

```
{
  "success": "true",
  "message": "success",
  "data": {
    "ref_id": "3f4d8a6d-8f4c-4d7d-bbb7-7d7d73d83b44",
    "message": "OTP generated successfully."
  }
}
```

| Field          | Type   | Description                                                                                                                                   |
| -------------- | ------ | --------------------------------------------------------------------------------------------------------------------------------------------- |
| `success`      | string | Indicates whether the request was processed successfully.                                                                                     |
| `message`      | string | Overall status of the API response.                                                                                                           |
| `data.ref_id`  | string | Reference ID for this OTP generation request. This value **must be passed** to the **OTP Verify API** along with the OTP entered by the user. |
| `data.message` | string | Additional message describing the result of the operation.                                                                                    |

#### Error Response

```
{
    "success": false,
    "error": {
        "code": "...",
        "message": "..."
    }
}
```

## Verify Aadhaar OTP

Verifies the OTP entered by the user and returns the verified Aadhaar details obtained from UIDAI.

> **When to use:**\
> Invoke this API after successfully generating an OTP using the **Generate Aadhaar OTP API**.

### POST /api/v1/aadhaar/otp/verify

#### Request Body

```
{
  "ref_id": "3f4d8a6d-8f4c-4d7d-bbb7-7d7d73d83b44",
  "otp": "111111"
}
```

| Field    | Type   | Required | Description                                                                                               |
| -------- | ------ | -------- | --------------------------------------------------------------------------------------------------------- |
| `ref_id` | string | Yes      | Reference ID returned by the **Generate Aadhaar OTP API**.                                                |
| `otp`    | string | Yes      | 6-digit OTP received on the Aadhaar-linked mobile number. **For sandbox/development mode, use `111111`.** |

#### Successful Response

Example

```json
{
  "success": "true",
  "message": "success",
  "data": {
    "verified": true,
    "aadhaarData": {
      "referenceId": "01*********7022057***79",
      "name": "XYZ",
      "dob": "30-09-1996",
      "gender": "M",
      ...
      ...
      ...,
      "villageTownCity": "Bihar",
      "jpegImage": "<Base64 Encoded Image>"
    }
  }
}
```

| Field              | Type    | Description                                                                          |
| ------------------ | ------- | ------------------------------------------------------------------------------------ |
| `success`          | string  | Indicates whether the request was processed successfully.                            |
| `message`          | string  | Overall status of the API response.                                                  |
| `data.verified`    | boolean | Indicates whether the Aadhaar data and digital signature were successfully verified. |
| `data.aadhaarData` | object  | Verified Aadhaar details returned after successful verification.                     |

The response contains verified Aadhaar information returned by UIDAI. The `photo` field can be directly used with the Face Match API.

## Verify Aadhaar Secure QR

Verifies the authenticity of an Aadhaar Secure QR Code by validating its digital signature and extracting the Aadhaar details embedded within it.

Unlike a standard QR code scanner, this API performs **cryptographic signature verification** to ensure that the QR code was issued by UIDAI and has not been tampered with.

> **When to use:**\
> Use this API when the user presents a physical or digital Aadhaar card containing a Secure QR Code. This API provides an offline Aadhaar verification mechanism without requiring OTP authentication.

### POST /api/v1/aadhaar/qr/verify

#### Request Body

```json
{
  "qrString": "<Aadhaar QR String>"
}
```

| Field      | Type   | Required | Description                                                                                                                                                           |
| ---------- | ------ | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `qrString` | string | Yes      | The Aadhaar Secure QR Code content extracted by the client application after scanning the Aadhaar card. The complete QR string should be passed without modification. |

#### What Happens Internally?

Hypersign

* verifies UIDAI digital signature
* validates QR authenticity
* extracts Aadhaar information
* extracts Aadhaar photograph
* returns verified data

#### Successful Response

```
{
  "success": "true",
  "message": "success",
  "data": {
    "verified": true,
    "aadhaarData": {
      "referenceId": "01*********7022057***79",
      "name": "XYZ",
      "dob": "30-09-1996",
      "gender": "M",
      ..
      ...
      ...
      "mobileHash": "xxxxxx1234",
      "villageTownCity": "Bihar",
      "jpegImage": "<Base64 Encoded Image>"
    }
  }
}
```

The extracted `photo` can be used with the Face Match API.

| Field              | Type    | Description                                                                                 |
| ------------------ | ------- | ------------------------------------------------------------------------------------------- |
| `success`          | string  | Indicates whether the request was processed successfully.                                   |
| `message`          | string  | Overall status of the API response.                                                         |
| `data.verified`    | boolean | Indicates whether the Aadhaar Secure QR Code's digital signature was successfully verified. |
| `data.aadhaarData` | object  | Verified Aadhaar details extracted from the Secure QR Code.                                 |

> **Note:** The fields within `aadhaarData` are identical to those returned by the **Verify Aadhaar OTP API**. Refer to the **Aadhaar Data** section in the previous API for a complete description of each field.

## Aadhaar Face Match

Compares a live selfie captured by the user with the photograph obtained from the Aadhaar verification process and returns a biometric similarity score.

The Aadhaar photograph can be obtained from either:

* **Verify Aadhaar OTP API** (`POST /api/v1/aadhaar/otp/verify`)
* **Verify Aadhaar Secure QR API** (`POST /api/v1/aadhaar/qr/verify`)

> **When to use:**\
> Use this API when biometric verification is required in addition to Aadhaar verification. This API helps confirm that the person presenting the Aadhaar document is the legitimate Aadhaar holder.

### POST /api/v1/aadhaar/face/match

#### Request Body

```
{
  "face1": "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQ...",
  "face2": "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQ..."
}
```

| Field   | Type   | Required | Description                                                                                                                                                                                                                   |
| ------- | ------ | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `face1` | string | Yes      | Base64-encoded Aadhaar photograph returned by either the **Verify Aadhaar OTP API** or the **Verify Aadhaar Secure QR API**. The image must include the appropriate Data URI prefix (for example, `data:image/jpeg;base64,`). |
| `face2` | string | Yes      | Base64-encoded live selfie captured by the client application. The image must include the appropriate Data URI prefix (for example, `data:image/jpeg;base64,`).                                                               |

#### Successful Response

```json
{
  "success": "true",
  "message": "success",
  "data": {
    "userImageScore": 88.23,
    "verified": true
  }
}
```

| Field                 | Type    | Description                                                                                                          |
| --------------------- | ------- | -------------------------------------------------------------------------------------------------------------------- |
| `success`             | string  | Indicates whether the request was processed successfully.                                                            |
| `message`             | string  | Overall status of the API response.                                                                                  |
| `data.userImageScore` | number  | Similarity score between the Aadhaar photograph and the live selfie. Higher values indicate a stronger facial match. |
| `data.verified`       | boolean | Indicates whether the similarity score meets the configured verification threshold.                                  |

## Aadhaar Data Returned Through API

| Field             | Type   | Description                                                                                                                              |
| ----------------- | ------ | ---------------------------------------------------------------------------------------------------------------------------------------- |
| `referenceId`     | string | Masked Aadhaar reference identifier.                                                                                                     |
| `name`            | string | Full name of the Aadhaar holder.                                                                                                         |
| `dob`             | string | Date of birth.                                                                                                                           |
| `gender`          | string | Gender (`M`, `F`, or `O`).                                                                                                               |
| `careOf`          | string | Parent, spouse, or guardian name.                                                                                                        |
| `house`           | string | House or building name/number.                                                                                                           |
| `street`          | string | Street or road name.                                                                                                                     |
| `landmark`        | string | Nearby landmark.                                                                                                                         |
| `villageTownCity` | string | Village, town, or city.                                                                                                                  |
| `postOffice`      | string | Post office name.                                                                                                                        |
| `subDistrict`     | string | Sub-district or Taluk.                                                                                                                   |
| `district`        | string | District name.                                                                                                                           |
| `state`           | string | State or Union Territory.                                                                                                                |
| `pincode`         | string | Postal PIN code.                                                                                                                         |
| `mobileHash`      | string | Masked representation of the Aadhaar-linked mobile number.                                                                               |
| `jpegImage`       | string | Base64-encoded photograph of the Aadhaar holder. This image can be passed directly to the **Face Match API** for biometric verification. |

## Complete Integration Examples

### OTP + Face Match

{% code expandable="true" %}

```mermaid
sequenceDiagram
    autonumber

    participant User
    participant Client as Client Application
    participant Hypersign as Hypersign API
    participant UIDAI
    participant Face as Face Match Engine

    User->>Client: Enter Aadhaar Number

    Client->>Hypersign: POST /api/v1/aadhaar/otp/generate
    Note right of Client: aadhaar_number, reason

    Hypersign->>UIDAI: Generate OTP
    UIDAI-->>Hypersign: OTP Generated
    UIDAI-->>User: Send OTP to Registered Mobile

    Hypersign-->>Client: success, ref_id

    User->>Client: Enter OTP

    Client->>Hypersign: POST /api/v1/aadhaar/otp/verify
    Note right of Client: ref_id, otp

    Hypersign->>UIDAI: Verify OTP
    UIDAI-->>Hypersign: Aadhaar Verified + Aadhaar Data

    Hypersign-->>Client: Aadhaar Details + jpegImage

    User->>Client: Capture Live Selfie

    Client->>Hypersign: POST /api/v1/aadhaar/face/match
    Note right of Client: face1 = Aadhaar Photo\nface2 = Live Selfie

    Hypersign->>Face: Compare Faces
    Face-->>Hypersign: Similarity Score + Verification Result

    Hypersign-->>Client: verified, userImageScore

    Client-->>User: Identity Verification Complete

```

{% endcode %}

### QR + Face Match

{% code overflow="wrap" expandable="true" %}

```mermaid
sequenceDiagram
    autonumber

    participant User
    participant Client as Client Application
    participant Hypersign as Hypersign API
    participant Face as Face Match Engine

    User->>Client: Scan Aadhaar Secure QR Code

    Client->>Client: Extract QR String

    Client->>Hypersign: POST /api/v1/aadhaar/qr/verify
    Note right of Client: qrString

    Hypersign->>Hypersign: Verify UIDAI Digital Signature
    Hypersign->>Hypersign: Extract Aadhaar Data & Photograph

    Hypersign-->>Client: Aadhaar Details + jpegImage

    User->>Client: Capture Live Selfie

    Client->>Hypersign: POST /api/v1/aadhaar/face/match
    Note right of Client: face1 = Aadhaar Photo\nface2 = Live Selfie

    Hypersign->>Face: Compare Faces
    Face-->>Hypersign: Similarity Score + Verification Result

    Hypersign-->>Client: verified, userImageScore

    Client-->>User: Identity Verification Complete
```

{% endcode %}

### OTP Only

{% code overflow="wrap" expandable="true" %}

```mermaid


sequenceDiagram
    autonumber

    participant User
    participant Client as Client Application
    participant Hypersign as Hypersign API
    participant UIDAI

    User->>Client: Enter Aadhaar Number

    Client->>Hypersign: POST /api/v1/aadhaar/otp/generate
    Note right of Client: aadhaar_number, reason

    Hypersign->>UIDAI: Generate OTP
    UIDAI-->>Hypersign: OTP Generated
    UIDAI-->>User: Send OTP to Registered Mobile

    Hypersign-->>Client: success, ref_id

    User->>Client: Enter OTP

    Client->>Hypersign: POST /api/v1/aadhaar/otp/verify
    Note right of Client: ref_id, otp

    Hypersign->>UIDAI: Verify OTP
    UIDAI-->>Hypersign: Aadhaar Verified + Aadhaar Data

    Hypersign-->>Client: Aadhaar Verification Result

    Client-->>User: Verification Complete

```

{% endcode %}

## Choosing the Right Verification Flow

The choice of verification flow depends on the level of identity assurance your application requires.

| Capability                                |        Aadhaar Verification + Face Match (OTP + Face Match / QR + Face Match)       |               Aadhaar Verification Only (OTP)              |
| ----------------------------------------- | :---------------------------------------------------------------------------------: | :--------------------------------------------------------: |
| Verifies Aadhaar Information              |                                          ✅                                          |                              ✅                             |
| Verifies the Person is the Aadhaar Holder |                                          ✅                                          |                              ❌                             |
| Biometric Face Verification               |                                          ✅                                          |                              ❌                             |
| Helps Prevent Identity Fraud              |                                          ✅                                          |                              ❌                             |
| Higher Identity Assurance                 |                                          ✅                                          |                         ⚠️ Limited                         |
| Recommended For                           | Banking, Financial Services, Insurance, High-value Transactions, Digital Onboarding | Low-risk onboarding, Basic KYC, Mobile Number Verification |

> **Why add Face Match?**
>
> OTP verification confirms that the user has access to the mobile number linked to the Aadhaar. However, it does **not** confirm that the person entering the OTP is the actual Aadhaar holder.
>
> Face Match adds a biometric verification step by comparing the Aadhaar photograph with a live selfie, providing a much higher level of confidence that the individual being onboarded is the legitimate Aadhaar holder.

### Recommended Verification Flow by Use Case

| Use Case                                | Recommended Flow                  |
| --------------------------------------- | --------------------------------- |
| Banking & Financial Services            | Aadhaar Verification + Face Match |
| NBFC Loan Onboarding                    | Aadhaar Verification + Face Match |
| Insurance KYC                           | Aadhaar Verification + Face Match |
| Securities & Investment Account Opening | Aadhaar Verification + Face Match |
| Digital Customer Onboarding             | Aadhaar Verification + Face Match |
| High-value Transactions                 | Aadhaar Verification + Face Match |
| Employee Verification                   | Aadhaar Verification + Face Match |
| Telecom SIM Verification                | Aadhaar Verification Only\*       |
| Low-risk Customer Onboarding            | Aadhaar Verification Only         |
| Basic Identity Verification             | Aadhaar Verification Only         |
| Mobile Number Verification              | Aadhaar Verification Only         |

> **Note:** *If stronger identity assurance or fraud prevention is required, Face Match can be added to the Aadhaar verification flow.*

## Privacy by Design with Selective Disclosure

### Why Request Only the Data You Need?

Many applications do not require the complete Aadhaar record to perform their business function.

For example:

* An age-gated service may only need the user's **date of birth**.
* A customer onboarding flow may only require the **name** and **reference ID**.
* A logistics application may only need the **name** and **address**.
* An employee verification portal may only require the **name** and **photograph**.

Requesting the complete Aadhaar dataset when only a few attributes are required increases the amount of personal data processed by your application.

Modern privacy regulations, including India's **Digital Personal Data Protection (DPDP) Act**, encourage organizations to collect and process only the personal data necessary for a specific purpose. Reducing the amount of personal data handled by your application lowers privacy risk, simplifies compliance, and limits unnecessary exposure of sensitive information.

Hypersign helps you implement this **Privacy by Design** approach from day one through **Selective Disclosure**.<br>

#### **What is Selective Disclosure?**

Selective Disclosure is a privacy-preserving mechanism that allows a verifier to request **only the Aadhaar > attributes required for a specific business purpose**, instead of receiving the complete Aadhaar record. Instead > of disclosing all available Aadhaar information, the API returns only the fields requested by your application. For example, if your application only requires:

* Name
* Date of Birth
* Reference ID the response will contain only those attributes.

#### **How does Selective Disclosure helps your organizations?**

* Reduce personal data processing
* Follow the principle of data minimization
* Lower compliance and privacy risks
* Build privacy-first applications

### Using Selective Disclosure

Selective Disclosure is supported by both Aadhaar verification APIs:

* `POST /api/v1/aadhaar/otp/verify`
* `POST /api/v1/aadhaar/qr/verify`

To request only specific Aadhaar attributes, include an additional `QueryRequest` object in the request body.

#### Request Format

```json
{
  "... existing request fields ...",

  "QueryRequest": {
    "query": [
      {
        "type": "QueryByFrame",
        "credentialQuery": {
          "frame": {
            "@context": [
              "https://www.w3.org/2018/credentials/v1",
              "https://w3id.org/citizenship/v1",
              "https://w3id.org/security/bbs/v1"
            ],
            "type": [
              "VerifiableCredential",
              "AadhaarCardCredential"
            ],
            "issuer": {},
            "issuanceDate": {},
            "credentialSubject": {
              "@explicit": true,
              "type": [
                "AadhaarCard",
                "Person"
              ],
              "referenceId": {},
              "name": {},
              "dob": {}
            }
          }
        }
      }
    ],
    "domain": "verifier.example.com", // verifier domain name
    "challenge": "99612b24-63a9-11ea-b99f-4f66f3e4f81a" // challenge can be generated and stored on your server
  }
}
```

The requested Aadhaar attributes are specified inside the `credentialSubject` object. To request an attribute, include its field name with an empty object (`{}`).

For example:

```json
"credentialSubject": {
  "@explicit": true,
  "type": [
    "AadhaarCard",
    "Person"
  ],
  "name": {},
  "dob": {},
  "referenceId": {}
}
```

The API will return only:

* `name`
* `dob`
* `referenceId`

\
You can choose fields from [#aadhaar-data-returned-through-api](#aadhaar-data-returned-through-api "mention")

#### Response Format

When **Selective Disclosure** is used, the response format differs from the standard Aadhaar verification response.

Instead of returning the complete `aadhaarData` object, the API returns a **W3C Verifiable Presentation (VP)** containing only the attributes requested in the `QueryRequest`.

**Example Response**

```json
{
  "success": true,
  "message": "success",
  "data": {
    "verified": true,
    "presentation": {
      "...": "Verifiable Presentation"
    }
  }
}
```

The `presentation` contains:

* A **Verifiable Presentation**
* One or more **Verifiable Credentials**
* Only the Aadhaar attributes requested in the `credentialSubject` frame
* Cryptographic proofs proving the authenticity and integrity of the disclosed information

The returned `presentation` follows the **W3C Verifiable Credentials** specification and contains:

| Property               | Description                                                                                                                                |
| ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
| `holder`               | DID of the Aadhaar holder presenting the credential.                                                                                       |
| `verifiableCredential` | Contains the selectively disclosed Aadhaar attributes.                                                                                     |
| `credentialSubject`    | Contains only the requested Aadhaar fields.                                                                                                |
| `proof`                | Cryptographic proof demonstrating that the disclosed attributes originate from a valid Aadhaar credential and have not been tampered with. |

Sample Response where the verifier only requested name and dob:

{% code overflow="wrap" expandable="true" %}

```json
{
  "success": true,
  "message": "success",
  "data": {
    "verified": true,
    "presentation": {
      "@context": [
        "https://www.w3.org/2018/credentials/v1",
        "https://w3id.org/citizenship/v1",
        "https://w3id.org/security/bbs/v1"
      ],
      "type": "VerifiablePresentation",
      "holder": "did:hid:z6MkwK7q57hdxE1hp3KR93W3Gd68x4Fc6G4Wp3SVSYqZqahS",
      "verifiableCredential": [
        {
          "@context": [
            "https://www.w3.org/2018/credentials/v1",
            "https://w3id.org/citizenship/v1",
            "https://w3id.org/security/bbs/v1"
          ],
          "id": "vc:hid:testnet:zkFzFSjfY1zNei6UD6SSRcDyPskh6DDJ6xrEsbuojt2fehBu48",
          "type": [
            "AadhaarCardCredential",
            "VerifiableCredential"
          ],
          "credentialSubject": {
            "id": "did:hid:z6MkwK7q57hdxE1hp3KR93W3Gd68x4Fc6G4Wp3SVSYqZqahS",
            "type": [
              "Person",
              "AadhaarCard"
            ],
            "dob": "09-06-1998",
            "name": "Amrita Kumari",
          },
          "issuanceDate": "2026-07-07T01:29:40.250Z",
          "issuer": "did:hid:z6MkmYYZ8iquQVoCVtjZYC4YT4Q3rS8ad8S69Fho6SBKRXZD",
          "proof": {
            "type": "BbsBlsSignatureProof2020",
            "created": "2026-07-07T01:29:40Z",
            "nonce": "LmztbVCHaHYgol73+4NXwoAPjUoham6LG6OyA2/o2HmvyiCMoObtKmYZdILMGWKDZPc=",
            "proofPurpose": "assertionMethod",
            "proofValue": "ABkB8DMvl5xbPGF+UqtA......aCj7hlMrAc5bR0kb2xxEFccH",
            "verificationMethod": "did:hid:z6MkmYYZ8iquQVoCVtjZYC4YT4Q3rS8ad8S69Fho6SBKRXZD#key-3"
          }
        }
      ],
      "proof": {
        "type": "BbsBlsSignature2020",
        "created": "2026-07-07T01:29:40Z",
        "challenge": "99612b24-63a9-11ea-b99f-4f66f3e4f81a",
        "domain": "verifier.example.com",
        "proofPurpose": "authentication",
        "proofValue": "laTiLAE11kDzYMFBU3ZVnv...BkG7KYma9urLMBCo4x5JoTWPaG1p7URXapIpy1ng+avITVXJin9XQoxPxyNA==",
        "verificationMethod": "did:hid:z6MkwK7q57hdxE1hp3KR93W3Gd68x4Fc6G4Wp3SVSYqZqahS#key-3"
      }
    }
  }
}
```

{% endcode %}

## Detailed Steps To Generate Access Token

### Step 1: Generate a KYC API Secret

Log in to the [**Hypersign Dashboard**](https://entity.dashboard.hypersign.id/) and navigate to: **Developer Hub → API Keys**

Generate a new **KYC API Secret** and securely store it in your application's environment variables.

Example:

```
KYC_API_SECRET=xxxxxxxxxxxxxxxxxxxxxxxx
```

> **Important:** Never expose your `KYC_API_SECRET` in client-side applications (Web, Android, or iOS). It should only be used from your trusted backend or server environment.

### Step 2: Generate an Access Token

Exchange the `KYC_API_SECRET` for an Access Token by calling the following endpoint.

#### Request

```
POST https://api.entity.dashboard.hypersign.id/api/v1/app/oauth?grant_type=access_service_kyc
```

#### Request Headers

| Header           | Value              |
| ---------------- | ------------------ |
| X-Api-Secret-Key | `<KYC_API_SECRET>` |
| Accept           | application/json   |

#### Successful Response

```
{
  "access_token": "<ACCESS_TOKEN>",
  "expiresIn": 3600
}
```

The returned Access Token is valid until the time specified by the `expiresIn` field.

**Do not generate a new Access Token before every API call.**

Instead:

* Cache the Access Token locally.
* Reuse the cached token for subsequent API requests.
* Automatically generate a new Access Token only after the current token expires.

### Step 3: Authenticate API Requests

Include the generated Access Token in the `Authorization` header of every Aadhaar Verification API request.

#### Required Headers

| Header        | Value                   |
| ------------- | ----------------------- |
| Authorization | `Bearer <ACCESS_TOKEN>` |
| Content-Type  | `application/json`      |

All APIs require authentication. Include the following headers with every request.

***

## Need Help?

For complete request/response schemas, SDKs, and API playground, refer to the Hypersign OpenAPI documentation.<br>

<br>

#### &#x20;  <br>


# Introduction

A full stack identity infrastructure for building ID products

[<mark style="color:blue;">**Entity Studio**</mark> is a full stack identity infrastructure that enables rapid development of digital identity products. It is built on the **Hypersign Identity Blockchain Network** and adheres to the **W3C** DID and Verifiable Credential specifications. The platform incorporates a low-code approach and offers APIs and SDKs to empower developers to swiftly deploy applications in production.](#user-content-fn-1)[^1]

The Entity Studio also provides an interactive playground, called **Entity Studio SSI Playground**,  to learn and test the Self Sovereign Identity (SSI) concepts.&#x20;

<table data-card-size="large" data-view="cards"><thead><tr><th></th><th></th><th></th><th data-hidden data-type="checkbox"></th><th data-hidden data-type="checkbox"></th><th data-hidden data-card-target data-type="content-ref"></th><th data-hidden data-card-cover data-type="files"></th></tr></thead><tbody><tr><td><mark style="color:blue;"><strong>SSI Playground</strong></mark></td><td><em><mark style="color:orange;">Experience Self Sovereign Identity (SSI) concepts firsthand by using our Entity Studio playground.</mark></em></td><td></td><td>false</td><td>false</td><td><a href="/pages/Op3fPJupvzC8QZv8eWzB">/pages/Op3fPJupvzC8QZv8eWzB</a></td><td></td></tr><tr><td><mark style="color:blue;"><strong>SSI API Documentation</strong></mark></td><td><em><mark style="color:orange;">Dive into our API documentation to create innovative identity products on our infrastructure.</mark></em></td><td></td><td>false</td><td>false</td><td><a href="/pages/nZNZQpf7ruzWgipWJJT0">/pages/nZNZQpf7ruzWgipWJJT0</a></td><td></td></tr><tr><td><mark style="color:blue;"><strong>Developer Dashboard</strong></mark></td><td><em><mark style="color:orange;">Manage your application and API keys and start building your identity product on our infrastructure</mark></em></td><td></td><td>false</td><td>false</td><td><a href="/pages/erV1OXXBOAKu0cuI67FJ">/pages/erV1OXXBOAKu0cuI67FJ</a></td><td></td></tr><tr><td><mark style="color:blue;"><strong>API Playground</strong></mark></td><td><em><mark style="color:orange;">Register your app on Entity Developer Dashboard and get a head start with our SSI APIs</mark></em></td><td></td><td>false</td><td>false</td><td><a href="/pages/vpsmvBEFgVPdF5k7N3xL">/pages/vpsmvBEFgVPdF5k7N3xL</a></td><td></td></tr></tbody></table>

[^1]:


# Setup SSI Service

<figure><img src="/files/OpDKqe4sTjM0lU8TjLMR" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/HTHxojJ79UoUNvTsrhpq" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/TAQO8yC2Cr0TaPlt1GPe" alt=""><figcaption></figcaption></figure>

{% content-ref url="/pages/jdfemrkZDYAHNXextTQg" %}
[Managing API keys](/hypersign-developer-dashboard/developer-dashboard/managing-api-keys)
{% endcontent-ref %}

{% content-ref url="/pages/1ECe3zbGhbIj5m8Yls2F" %}
[Service Authentication API](/hypersign-ssi/api-doc/authentication)
{% endcontent-ref %}

{% content-ref url="/pages/RGjD8PghNASXptSCNHZ7" %}
[ID Service](/hypersign-id/integrations/id-service)
{% endcontent-ref %}


# Create Your First DID

<figure><img src="/files/qJktRrOdekAUicHUInJA" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/wiGWOVL0VVHyhU36DEYj" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/4sGqfXQZnglm0WhI0GmY" alt=""><figcaption></figcaption></figure>

{% content-ref url="/pages/RGjD8PghNASXptSCNHZ7" %}
[ID Service](/hypersign-id/integrations/id-service)
{% endcontent-ref %}


# Credits

<figure><img src="/files/dHq8FD5tJL7CM7v3lvjz" alt=""><figcaption></figcaption></figure>


# API Reference

Dive into our API documentation to create innovative identity products on the Entity Studio infrastructure.

Register your application on [Entity Studio Developer Dashboard](/hypersign-developer-dashboard/developer-dashboard) and generate your API secret Key before proceeding.&#x20;

## Authentication

<table data-card-size="large" data-view="cards"><thead><tr><th></th><th></th><th></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td><mark style="color:blue;"><strong>Authentication</strong></mark></td><td><em><mark style="color:yellow;">Generate Access Token using API secret key to start accessing SSI APIs</mark></em></td><td></td><td><a href="/pages/1ECe3zbGhbIj5m8Yls2F">/pages/1ECe3zbGhbIj5m8Yls2F</a></td></tr></tbody></table>

### Self Sovereign Identity (SSI) APIs

<table data-card-size="large" data-view="cards"><thead><tr><th></th><th></th><th></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td><mark style="color:blue;"><strong>Decentralized Identifiers</strong></mark> </td><td><em><mark style="color:yellow;">APIs to manage DIDs for your apps</mark></em></td><td></td><td><a href="/pages/rL1N5Dz61lOVLHlErwQp">/pages/rL1N5Dz61lOVLHlErwQp</a></td></tr><tr><td><mark style="color:blue;"><strong>Schema</strong></mark></td><td><em><mark style="color:yellow;">APIs to manage schemas for credentials for your apps</mark></em></td><td></td><td><a href="/pages/1BLTurweWYbKSoPmmRed">/pages/1BLTurweWYbKSoPmmRed</a></td></tr><tr><td><mark style="color:blue;"><strong>Verifiable Credentials</strong></mark></td><td><em><mark style="color:yellow;">APIs to manage verifiable credentials for your apps</mark></em></td><td></td><td><a href="/pages/bnREvNkvknp5WZRI2uKP">/pages/bnREvNkvknp5WZRI2uKP</a></td></tr><tr><td><mark style="color:blue;"><strong>Verifiable Presentation</strong></mark></td><td><em><mark style="color:yellow;">API to manage presentation template and verification</mark></em></td><td></td><td><a href="/pages/bnREvNkvknp5WZRI2uKP">/pages/bnREvNkvknp5WZRI2uKP</a></td></tr></tbody></table>


# Service Authentication API

Generate access token using API secret Key

Register your service on [Entity Studio Developer Dashboard](/hypersign-developer-dashboard/developer-dashboard) and generate your API secret Key before proceeding.&#x20;

Once the API secret key is generated, you can use the API below to generate a new access token. Just pass your API secret Key in `X-Api-Secret-Key` header to generate access token. The `access_token` is required to access all SSI APIs. Read the next section for more details.&#x20;

{% hint style="info" %}
Entity Studio SSI API base URL: <https://api.entity.dashboard.hypersign.id/>
{% endhint %}

{% openapi src="/files/vgw0vjv4rN8E1Tf2vbDp" path="/api/v1/app/oauth" method="post" %}
[api-json.json](https://1497651738-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MOLDOibYYcG4PCSEDDL%2Fuploads%2FjYVydJufhHpdtxi9oslY%2Fapi-json.json?alt=media\&token=695305b2-cc3b-400b-9c46-54606891a2d7)
{% endopenapi %}

Once you generated the `accessToken`, you can pass this token as *<mark style="background-color:yellow;">bearer authorization token</mark>* in the header for all APIs.&#x20;

{% content-ref url="/pages/u8XWTiyGTIJULYI41CYW" %}
[Generate AccessTokens](/hypersign-id/id-widget/integrations/backend-integration/generate-accesstokens)
{% endcontent-ref %}


# DID

Manage DID operation using DID APIs

Please [generate access token](/hypersign-ssi/api-doc/authentication) before proceeding.  Once you generated the `access_token`, you can pass this token as *<mark style="background-color:yellow;">bearer authorization token</mark>* in the header for all APIs.&#x20;

{% hint style="info" %}
**Note:** Some of these APIs are on-chain APIs which means they need network fee to successfully execute, so make sure that your application wallet address has $hid tokens. Read [network fee](/hypersign-developer-dashboard/developer-dashboard/network-fee) section for more details.
{% endhint %}

{% hint style="info" %}
Entity Studio SSI API base URL: <https://api.entity.hypersign.id>
{% endhint %}

There are 3 steps involved in DID creation:&#x20;

* **Generate a DID Document**: Generate the data structure of the DID document.
* **Sign a DID Document (optional)**: Sign the DID Document using verification method.&#x20;
* **Register a DID Document (optional)** : Registers the signed DID Document on the blockchain network.&#x20;

{% hint style="info" %}
**Note**: You can choose not to register a DID on blockchain, in that case, the DID is concidered as private DID. We support `Ed25519VerificationKey2020` for private DIDs. Kindly read difference between [private and public DID](/core-concepts/decentralized-identifier-did/private-and-public-did) in this section.&#x20;
{% endhint %}

### Create a DID

Generates the a new DID  and DID Document.&#x20;

{% openapi src="/files/vgw0vjv4rN8E1Tf2vbDp" path="/api/v1/did/create" method="post" %}
[api-json.json](https://1497651738-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MOLDOibYYcG4PCSEDDL%2Fuploads%2FjYVydJufhHpdtxi9oslY%2Fapi-json.json?alt=media\&token=695305b2-cc3b-400b-9c46-54606891a2d7)
{% endopenapi %}

### Request Body Parameters

* **Namespace:** DID name space. Possible value is `testnet` &#x20;

#### Optional Parameters

* **MethodSpecificId**: Custom Id string which you want to attach with the DID. Please read [did:hid method spec](https://docs.hypersign.id/concepts/decentralized-identifier-did/did-registry#syntax-of-did-hid-method) for details about possible format.
* **Options.keyTypes**: We support `Ed25519VerificationKey2020`, `EcdsaSecp256k1RecoveryMethod2020` verification method key types. So only these two are possible values. Read the full [specification here](/core-concepts/specifications/supported-signature-algorithms).
* **Options.publicKey**: Please pass  the `options.publickey` property only for `Ed25519VerificationKey2020` verification method key type. For `EcdsaSecp256k1RecoveryMethod2020` , this property can be kept blank.  Its value would be publickey (in multi base format)
* **Options.walletAddress:** Please pass `options.walletAddress` for keyType `EcdsaSecp256k1RecoveryMethod2020`
* **Options.chainId:** ChainId in HEX format. For example for Etheruem main net, the chain id would be  `0x1`. This property is only required for keytype `EcdsaSecp256k1RecoveryMethod2020`&#x20;

{% hint style="info" %}
**Note**: If no optional parameters are provided then, did will be created of verification key method type `Ed25519VerificationKey2020`
{% endhint %}

{% hint style="info" %}
**Note:** If you want to create DID for blockchain wallet addresses like EVM wallets, Cosmos wallets, you should use keyType as . Read  `EcdsaSecp256k1RecoveryMethod2020`
{% endhint %}

### Register a DID

Registers a Signed DID Document in [DID registry](/core-concepts/decentralized-identifier-did/did-registry). The Gas fee ([network fee](/hypersign-developer-dashboard/developer-dashboard/network-fee)) for this DID registration will be done by applications' walletAddress.&#x20;

{% openapi src="/files/vgw0vjv4rN8E1Tf2vbDp" path="/api/v1/did/register" method="post" %}
[api-json.json](https://1497651738-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MOLDOibYYcG4PCSEDDL%2Fuploads%2FjYVydJufhHpdtxi9oslY%2Fapi-json.json?alt=media\&token=695305b2-cc3b-400b-9c46-54606891a2d7)
{% endopenapi %}

#### Request Parameters

* **didDocument :**  DID documented generated using `/api1/v1/did/create` API
* **verificationMethodId** :  Verification Method id of referred verification method in the didDocument

**Optional Parameters**

* **clientSpec :** Wallet specifications which are used to sign the didDocument string. Use `eth-personalSign` for Metamask and `cosmos-ADR036` for Keplr wallet. Learn more about client specifications [here](/core-concepts/specifications/client-specification).
* **signature:** If didDocument is signed using client wallets (Metamask or Keply) then pass the signature hex string.&#x20;

Note: Read how to use Metamask to create Hypersign DID.&#x20;

### Resolve a DID

Given a DID Id (example: `did:hid:testnet:0x123123123123`), this API will resolve the corresponding DID Document from the [DID registry](/core-concepts/decentralized-identifier-did/did-registry) (or Hypersign Blockchain).&#x20;

{% openapi src="/files/vgw0vjv4rN8E1Tf2vbDp" path="/api/v1/did/resolve/{did}" method="get" %}
[api-json.json](https://1497651738-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MOLDOibYYcG4PCSEDDL%2Fuploads%2FjYVydJufhHpdtxi9oslY%2Fapi-json.json?alt=media\&token=695305b2-cc3b-400b-9c46-54606891a2d7)
{% endopenapi %}

### Fetch all DIDs for your apps

{% openapi src="/files/vgw0vjv4rN8E1Tf2vbDp" path="/api/v1/did" method="get" %}
[api-json.json](https://1497651738-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MOLDOibYYcG4PCSEDDL%2Fuploads%2FjYVydJufhHpdtxi9oslY%2Fapi-json.json?alt=media\&token=695305b2-cc3b-400b-9c46-54606891a2d7)
{% endopenapi %}

### Update a DID

Update a DIDDocument

{% openapi src="/files/vgw0vjv4rN8E1Tf2vbDp" path="/api/v1/did" method="patch" %}
[api-json.json](https://1497651738-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MOLDOibYYcG4PCSEDDL%2Fuploads%2FjYVydJufhHpdtxi9oslY%2Fapi-json.json?alt=media\&token=695305b2-cc3b-400b-9c46-54606891a2d7)
{% endopenapi %}

#### Request Parameters

* **didDocument :**  DID documented to be updated
* **verificationMethodId** :  Verification Method id of referred verification method in the didDocument
* **deactivate** : `true` is you want to deactivate this DID, `false` otherwise.&#x20;

**Optional Parameters**

* **clientSpec :** Wallet specifications which are used to sign the didDocument string. Use `eth-personalSign` for Metamask and `cosmos-ADR036` for Keplr wallet. Learn more about client specifications [here](/core-concepts/specifications/client-specification).
* **signature:** If didDocument is signed using client wallets (Metamask or Keply) then pass the signature hex string.&#x20;

###


# Schema

> Entity Studio SSI API base URL: <https://api.entity.hypersign.id>

{% openapi src="/files/vgw0vjv4rN8E1Tf2vbDp" path="/api/v1/schema" method="post" %}
[api-json.json](https://1497651738-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MOLDOibYYcG4PCSEDDL%2Fuploads%2FjYVydJufhHpdtxi9oslY%2Fapi-json.json?alt=media\&token=695305b2-cc3b-400b-9c46-54606891a2d7)
{% endopenapi %}

{% openapi src="/files/vgw0vjv4rN8E1Tf2vbDp" path="/api/v1/schema" method="get" %}
[api-json.json](https://1497651738-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MOLDOibYYcG4PCSEDDL%2Fuploads%2FjYVydJufhHpdtxi9oslY%2Fapi-json.json?alt=media\&token=695305b2-cc3b-400b-9c46-54606891a2d7)
{% endopenapi %}

{% openapi src="/files/vgw0vjv4rN8E1Tf2vbDp" path="/api/v1/schema/{schemaId}" method="get" %}
[api-json.json](https://1497651738-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MOLDOibYYcG4PCSEDDL%2Fuploads%2FjYVydJufhHpdtxi9oslY%2Fapi-json.json?alt=media\&token=695305b2-cc3b-400b-9c46-54606891a2d7)
{% endopenapi %}


# Verifiable Credential

Please [generate access token](/hypersign-ssi/api-doc/authentication) before proceeding.  Once you generated the `access_token`, you can pass this token as  *<mark style="background-color:yellow;">bearer authorization token</mark>*  in the header for all APIs.&#x20;

### Issue a verifiable credential

An issuer may issue a [verifiable credential](/core-concepts/verifiable-credential-vc) to a subject using this API. The credential document is signed by issuer's identity key and its status is registered on the blockchain.&#x20;

{% hint style="info" %}
Entity Studio SSI API base URL: <https://api.entity.hypersign.id>
{% endhint %}

{% openapi src="/files/tqG2a4N1nThnaYfUMlnm" path="/api/v1/credential/issue" method="post" %}
[api-json.json](https://1497651738-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MOLDOibYYcG4PCSEDDL%2Fuploads%2F7SWcw0078CGMGkrodrYh%2Fapi-json.json?alt=media\&token=10361f3f-4c5b-44d6-b6af-39fbac2cc67e)
{% endopenapi %}

{% hint style="info" %}
NOTE: A developer may choose to store the verifiable credential in application's data vault securely or they may not to. Pass `true` for request body property `persist` to store the credential document, `false` otherwise.
{% endhint %}

### Verify an issued verifiable credential document

A signed verifiable credential must has signature of the issuer. Any one may verify an issued credential document. The verification result state the following facts:

> * *This document was issued by intended issuer*
> * *This document have not been tampered*
> * *This document have not been revoked*

{% openapi src="/files/vgw0vjv4rN8E1Tf2vbDp" path="/api/v1/credential/verify" method="post" %}
[api-json.json](https://1497651738-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MOLDOibYYcG4PCSEDDL%2Fuploads%2FjYVydJufhHpdtxi9oslY%2Fapi-json.json?alt=media\&token=695305b2-cc3b-400b-9c46-54606891a2d7)
{% endopenapi %}

{% hint style="info" %}
NOTE: Verifying a credential document is different than verifying a [verifiable presentatio](/hypersign-ssi/api-doc/verifiable-presentation)n. Verification result of later, also states that "*Only intended subject holds this document and not one else*".&#x20;
{% endhint %}

### Fetch a verifiable credential and/or its status by Id

{% openapi src="/files/vgw0vjv4rN8E1Tf2vbDp" path="/api/v1/credential/{credentialId}" method="get" %}
[api-json.json](https://1497651738-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MOLDOibYYcG4PCSEDDL%2Fuploads%2FjYVydJufhHpdtxi9oslY%2Fapi-json.json?alt=media\&token=695305b2-cc3b-400b-9c46-54606891a2d7)
{% endopenapi %}

{% hint style="info" %}
Pass `false` value to parameter `retrieveCredential` to only retrieve status of  the credential
{% endhint %}

### Fetch list of verifiable credentials

{% openapi src="/files/vgw0vjv4rN8E1Tf2vbDp" path="/api/v1/credential" method="get" %}
[api-json.json](https://1497651738-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MOLDOibYYcG4PCSEDDL%2Fuploads%2FjYVydJufhHpdtxi9oslY%2Fapi-json.json?alt=media\&token=695305b2-cc3b-400b-9c46-54606891a2d7)
{% endopenapi %}

### Update credential status of a verifiable credential

{% openapi src="/files/vgw0vjv4rN8E1Tf2vbDp" path="/api/v1/credential/status/{credentialId}" method="patch" %}
[api-json.json](https://1497651738-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MOLDOibYYcG4PCSEDDL%2Fuploads%2FjYVydJufhHpdtxi9oslY%2Fapi-json.json?alt=media\&token=695305b2-cc3b-400b-9c46-54606891a2d7)
{% endopenapi %}


# Verifiable Presentation

{% hint style="info" %}
Entity Studio SSI API base URL: <https://api.entity.hypersign.id>
{% endhint %}

{% content-ref url="/pages/cavqaCQ4VXDwaTNTp6fk" %}
[Presentation Template](/hypersign-ssi/api-doc/verifiable-presentation/presentation-template)
{% endcontent-ref %}

{% content-ref url="/pages/O2fNOR1YOvENfNICweVw" %}
[Presentation](/hypersign-ssi/api-doc/verifiable-presentation/presentation)
{% endcontent-ref %}


# Presentation Template

{% hint style="info" %}
Entity Studio SSI API base URL: <https://api.entity.hypersign.id>
{% endhint %}

{% openapi src="/files/vgw0vjv4rN8E1Tf2vbDp" path="/api/v1/presentation/template" method="post" %}
[api-json.json](https://1497651738-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MOLDOibYYcG4PCSEDDL%2Fuploads%2FjYVydJufhHpdtxi9oslY%2Fapi-json.json?alt=media\&token=695305b2-cc3b-400b-9c46-54606891a2d7)
{% endopenapi %}

{% openapi src="/files/vgw0vjv4rN8E1Tf2vbDp" path="/api/v1/presentation/template" method="get" %}
[api-json.json](https://1497651738-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MOLDOibYYcG4PCSEDDL%2Fuploads%2FjYVydJufhHpdtxi9oslY%2Fapi-json.json?alt=media\&token=695305b2-cc3b-400b-9c46-54606891a2d7)
{% endopenapi %}

{% openapi src="/files/vgw0vjv4rN8E1Tf2vbDp" path="/api/v1/presentation/template/{templateId}" method="get" %}
[api-json.json](https://1497651738-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MOLDOibYYcG4PCSEDDL%2Fuploads%2FjYVydJufhHpdtxi9oslY%2Fapi-json.json?alt=media\&token=695305b2-cc3b-400b-9c46-54606891a2d7)
{% endopenapi %}

{% openapi src="/files/vgw0vjv4rN8E1Tf2vbDp" path="/api/v1/presentation/template/{templateId}" method="patch" %}
[api-json.json](https://1497651738-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MOLDOibYYcG4PCSEDDL%2Fuploads%2FjYVydJufhHpdtxi9oslY%2Fapi-json.json?alt=media\&token=695305b2-cc3b-400b-9c46-54606891a2d7)
{% endopenapi %}

{% openapi src="/files/vgw0vjv4rN8E1Tf2vbDp" path="/api/v1/presentation/template/{templateId}" method="delete" %}
[api-json.json](https://1497651738-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MOLDOibYYcG4PCSEDDL%2Fuploads%2FjYVydJufhHpdtxi9oslY%2Fapi-json.json?alt=media\&token=695305b2-cc3b-400b-9c46-54606891a2d7)
{% endopenapi %}


# Presentation

{% hint style="info" %}
Entity Studio SSI API base URL: <https://api.entity.hypersign.id>
{% endhint %}

{% openapi src="/files/vgw0vjv4rN8E1Tf2vbDp" path="/api/v1/presentation" method="post" %}
[api-json.json](https://1497651738-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MOLDOibYYcG4PCSEDDL%2Fuploads%2FjYVydJufhHpdtxi9oslY%2Fapi-json.json?alt=media\&token=695305b2-cc3b-400b-9c46-54606891a2d7)
{% endopenapi %}

{% openapi src="/files/vgw0vjv4rN8E1Tf2vbDp" path="/api/v1/presentation/request" method="post" %}
[api-json.json](https://1497651738-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MOLDOibYYcG4PCSEDDL%2Fuploads%2FjYVydJufhHpdtxi9oslY%2Fapi-json.json?alt=media\&token=695305b2-cc3b-400b-9c46-54606891a2d7)
{% endopenapi %}

{% openapi src="/files/vgw0vjv4rN8E1Tf2vbDp" path="/api/v1/presentation/verify" method="post" %}
[api-json.json](https://1497651738-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MOLDOibYYcG4PCSEDDL%2Fuploads%2FjYVydJufhHpdtxi9oslY%2Fapi-json.json?alt=media\&token=695305b2-cc3b-400b-9c46-54606891a2d7)
{% endopenapi %}


# API Playground

Register your app on Entity Developer Dashboard and get a head start with our SSI APIs

Login to [Entity Studio dashboard](https://entity.hypersign.id/) and click on **API Playground** button to navigate to the Swagger playground to try API.

<figure><img src="/files/x3uqQl5Qah4ayDDT54WT" alt=""><figcaption><p>Entity Studio Dashboard</p></figcaption></figure>

<figure><img src="/files/3qmyPrpFFRwwO3Q6i962" alt=""><figcaption><p>API Playground</p></figcaption></figure>


# SSI Playground

Experience Self Sovereign Identity (SSI) concepts firsthand by using our Entity Studio playground.

Login to [Entity Studio dashboard](https://entity.hypersign.id/) and click on **SSI Playground** button to navigate to the playground dashboard.

<figure><img src="/files/J5mN2cWbTSNOdYBQtQcg" alt=""><figcaption><p>Entity Studio Dashboard</p></figcaption></figure>

<figure><img src="/files/8BiztbPsS7CeeqgAsCM1" alt=""><figcaption><p>SSI playground dashboard</p></figcaption></figure>

Watch this demo vedio to undertand and use SSI playground with one simple usecase.&#x20;

{% embed url="<https://www.youtube.com/watch?v=27E4KpIhF90>" %}
Watch demo of Entity Studio Playground
{% endembed %}


# Service

Manage your service and API keys and start building your identity product on our infrastructure

<table data-card-size="large" data-view="cards"><thead><tr><th></th><th></th><th></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td>SSI Service</td><td></td><td></td><td><a href="/pages/LyWgA1OhK43Vbe2Gj7wL">/pages/LyWgA1OhK43Vbe2Gj7wL</a></td></tr><tr><td>KYC Service</td><td></td><td></td><td><a href="/pages/RGjD8PghNASXptSCNHZ7">/pages/RGjD8PghNASXptSCNHZ7</a></td></tr></tbody></table>


# Managing API keys

### API Secret Key

<figure><img src="/files/ZoQDqQtmKY0B7lQdhfMv" alt=""><figcaption><p>API secret Key</p></figcaption></figure>

Upon successful registration, an API secret key will be generated for your app. You may use this API secret key to generate access token to access all SSI APIs. Read more about it in [authentication](/hypersign-ssi/api-doc/authentication) section.&#x20;

{% hint style="warning" %} <mark style="color:red;">Make sure to copy and save API secret key securely. If lost, this key can not be recovered. However, you can regenerate a new one.</mark>
{% endhint %}

<figure><img src="/files/78TOEPB9SiucA1hbXS7C" alt=""><figcaption><p>Regenerate a new API secret by clicking on this icon</p></figcaption></figure>


# Network Fee

Every application is associate with a wallet address (account address on Hypersign Blockchain) and the private key for that wallet address is managed by Entity Studio API server for the application via an encrypted data vault (read security section for more details).&#x20;

Since many SSI APIs are on-chain activities, `$hid` token is required to pay for transaction fee for those on-chain activities.&#x20;

### Application Wallet

Go to the developer dashboard and click on **Edit** icon of your application's card.  Right slider will be opened where you can see details of your wallet.&#x20;

<figure><img src="/files/1IauTmJ9wlLU7xsV0Bia" alt=""><figcaption><p>Wallet created for the application</p></figcaption></figure>

{% hint style="info" %}
Initially balance of this wallet is 0, all on-chain API requests will fail.  You can request hid testnet tokens from our Faucet
{% endhint %}

{% content-ref url="/pages/03fynfth83yAYlIte9c4" %}
[Faucet (testnet)](/hypersign-identity-network/faucet)
{% endcontent-ref %}


# Members & Roles

How to add your teammates and give customise permissions via role managment

1. [Admin invites a member to his/her account.](/hypersign-developer-dashboard/members-and-roles/members)
2. [Member accepts the invitation](/hypersign-developer-dashboard/members-and-roles/invitations) from his/her dashboard.
3. [Admin creates a role](/hypersign-developer-dashboard/members-and-roles/roles-and-permissions) with permissions.&#x20;
4. [Admin assigns the role](/hypersign-developer-dashboard/members-and-roles/members/assign-role-to-member) to a member.&#x20;
5. [Members can switch to admin](/hypersign-developer-dashboard/members-and-roles/invitations/member-access-admins-dashboard) dashboard to access data.


# Members

Add a new member / teammate to your profile

Login to your dashboard and click on **"Setting"** icon under the profile menu on the nav bar.  Proceed to **"Member & Roles"** tab and then proceed to the **"All Members"** page.

<figure><img src="/files/y7BzIWxbjLYkoj0e2y0Z" alt=""><figcaption></figcaption></figure>

Click on **"Invite Member"** button to add a new members to your account. In the popup enter email Id of the member you want to invite.

<figure><img src="/files/liAk8OklMIjYDhZLNHbp" alt=""><figcaption></figcaption></figure>

{% hint style="info" %}
Invitee must have account on the Entity Developer Dashboard. If not, kindly ask them to create one.
{% endhint %}

Finally click on **"Invite"** button to invite a new member.

<figure><img src="/files/AwiKfUfaaRMgtlZv0awX" alt=""><figcaption></figcaption></figure>

An invitation code is generated. You can copy and send the code to the member. Alternatively, member do also get the invitation on their dashboard.&#x20;

The invitation is currently in  **"Pending"** state.&#x20;

<figure><img src="/files/UnVHpcR8FbdGLLBgpO5x" alt=""><figcaption></figcaption></figure>

Next, lets see how an invitee may accept the invitation.

{% content-ref url="/pages/xonfpoZV3kGfO5p2kOqL" %}
[Invitations](/hypersign-developer-dashboard/members-and-roles/invitations)
{% endcontent-ref %}


# Assign Role To Member

Before proceeding make sure the following:&#x20;

1. A [member was invited](/hypersign-developer-dashboard/members-and-roles/members) to your account
2. [Member accepted](/hypersign-developer-dashboard/members-and-roles/invitations) your invitation on their dashboard
3. You have [created role](/hypersign-developer-dashboard/members-and-roles/roles-and-permissions) with several permission.

### Let's assign a role to invited member!

Head to "**All Members**" page under "**Member & Roles**" tab in the "**Setting**"page and click on "**Hamburger**" icon on any member.  You will list of role you had created earlier under "**Assign Role**" section.&#x20;

<figure><img src="/files/lKEihhQAzmfdtbN4b4bD" alt=""><figcaption></figcaption></figure>

Click on the name of the role (in yellow box) to assign a role this member.&#x20;

<figure><img src="/files/fmSbofjQKMHTEDbQLh49" alt=""><figcaption></figcaption></figure>

A role is assigned to this member. Now the member can assess your (admin's) dashboard right from their account.&#x20;

{% content-ref url="/pages/bfm8wnfYZZwCXMIAJe2M" %}
[Member Access Admin's Dashboard](/hypersign-developer-dashboard/members-and-roles/invitations/member-access-admins-dashboard)
{% endcontent-ref %}


# Invitations

A member can accept an invitation

A member can login to their dashboard and navigate to "**Invitations**" page under "**Member & Roles**" tab on the "**Setting**" page.

<figure><img src="/files/nB33HA5Z9ToFc02sJd6C" alt=""><figcaption></figcaption></figure>

Click on the hamburger icon on the any Admins invitations you want to accept and then click on "**Accept Invitation**" from the menu to accept the invitation.

<figure><img src="/files/rPPwl79emirXcusFQmko" alt=""><figcaption></figcaption></figure>

Once the member accept the invitation, the invitation goes into "**Accepted**" state.

<figure><img src="/files/ZVILI90MnY8VlbHl42VV" alt=""><figcaption></figcaption></figure>

Admin is now ready to assign a role to this member.&#x20;

{% content-ref url="/pages/kU5W9q1TVKyIgzg5WOZq" %}
[Roles & Permissions](/hypersign-developer-dashboard/members-and-roles/roles-and-permissions)
{% endcontent-ref %}


# Member Access Admin's Dashboard

Once a [role is assigned](/hypersign-developer-dashboard/members-and-roles/members/assign-role-to-member) to a member by the admin, a member can "**Switch**" to the admin's account right from their dashboard. Click on "**Switch Account**" on any admin you want to switch account to, present under **Invitation** page of **Members & Roles** tab in **Setting** page.

<figure><img src="/files/V2rABveri2UiBxdon7OQ" alt=""><figcaption></figcaption></figure>

{% hint style="info" %}
By default, a member is logged in to his account which he can switch to admin's account if given permissions.
{% endhint %}

Member is now accessing the admin's dashboard.&#x20;

<figure><img src="/files/uykD93sxhvW7uP3wEeGN" alt=""><figcaption></figcaption></figure>


# Roles & Permissions

Create a new role with permission

Navigate to "**Roles & Permission**" page under "**Members & Role**" tab on the "**Setting**" page. Click on "**Create Custom Role**" button to create a new role.&#x20;

<figure><img src="/files/R6aodkPFfK77NB5IxRc7" alt=""><figcaption></figcaption></figure>

Enter relevant details about the role and click on "**Save**" button to save the role.&#x20;

<figure><img src="/files/OljMWp5ODtc8D3p5pLdC" alt=""><figcaption></figcaption></figure>

{% hint style="warning" %}
Check "All' in all service for simplicity. But this will give "All" access of your dashboard to members including delete access.&#x20;
{% endhint %}

Check out permission list to understand about these permissions:&#x20;

{% content-ref url="/pages/khV9TDAV2v5RRpbNW67B" %}
[Permissions List](/hypersign-developer-dashboard/members-and-roles/roles-and-permissions/permissions-list)
{% endcontent-ref %}

You can see your role with name "**Admin**" is created with 3 permissions.&#x20;

<figure><img src="/files/PmS5zsccrgMrZxdhZPcU" alt=""><figcaption></figcaption></figure>

Now is the time to assign this role to a member we previously invited in our account.&#x20;

{% content-ref url="/pages/AxhLwZehZgQTvTGcjq4F" %}
[Assign Role To Member](/hypersign-developer-dashboard/members-and-roles/members/assign-role-to-member)
{% endcontent-ref %}


# Permissions List

<figure><img src="/files/8Lfkav8hlFY3QpsqrY2J" alt=""><figcaption></figcaption></figure>


# Security


# Login

<figure><img src="/files/p0UA58WFKjzXBrOviao2" alt=""><figcaption></figcaption></figure>


# Multi factor Authentication (MFA)


# Onboarding

Navigate to [https://entity.dashboard.hypersign.id](https://entity.dashboard.hypersign.id/#/studio/login)

<figure><img src="/files/f35hZR8CrJHiWl8UdiGG" alt=""><figcaption></figcaption></figure>

Choose your business type&#x20;

<figure><img src="/files/kaFlEd6p15SXrUc4r8OC" alt=""><figcaption></figcaption></figure>

Proceed to enter details and upload logo about your company

<figure><img src="/files/CNWiXE8CDiXNHLr6TpLW" alt=""><figcaption></figcaption></figure>

Select your preffered services

<figure><img src="/files/Fb3jLT6IJpoOs4lGMtjO" alt=""><figcaption></figcaption></figure>

Choose estimated usage&#x20;

<figure><img src="/files/RnHHm6U8Z50Ii2tKmMMX" alt=""><figcaption></figcaption></figure>

Now choose one of more industry your business might belongs to

<figure><img src="/files/VkSkfF8iUV9SBblviR4m" alt=""><figcaption></figcaption></figure>

Review your provided information and request credits to setup your verification pods

<figure><img src="/files/kEsJq3XWELdDmH6vaNpF" alt=""><figcaption></figcaption></figure>

Your credit request will be submitted and you will have to wait upto 24hr to get all your service activated. Once your service is active you will get email notification, alternatively you can login to dashboard to check the  status.&#x20;

<figure><img src="/files/aaTB9bVfLWbEuva0iV0l" alt=""><figcaption></figcaption></figure>


# Introduction

A Proof Of Stake (PoS) based permissionless blockchain network for digital identity

The Hypersign Identity Network is a permissionless blockchain network to manage digital identity and access rights. It aims to empower humans to gain control of their data and access on the internet by providing scalable, interoperable and secure [verifiable data registry (VDR)](https://www.w3.org/TR/did-core/#dfn-verifiable-data-registry) to implement use cases on Self Sovereign Identity (SSI) principles.

The Hypersign Identity Network is built using [Cosmos-SDK](https://tendermint.com/sdk/) and is fully compatible with [W3C DID specifications](https://www.w3.org/TR/did-core/).

## Public Endpoints

| Type | Link                               |
| ---- | ---------------------------------- |
| RPC  | <https://rpc.prajna.hypersign.id/> |
| API  | <https://api.prajna.hypersign.id/> |

## Blockchain Explorers

[Testnet Explorer - Prajna](https://explorer.hypersign.id/hypersign-prajna-testnet)


# Validators & Delegators


# Installation of Node

Instructions to install hid-node binary

### Building from Source

* Clone the Github repository.

```bash
git clone https://github.com/hypersign-protocol/hid-node.git
```

* Checkout the tag that the network is currently running on and build the node.

```bash
cd hid-node
git checkout v0.2.0
make install
```

* Run the following to ensure that node binary is installed.

```bash
hid-noded version
```

### Download the binary

* Export the environment variables according to your Operating System and Architecture, and install the binary

<pre class="language-bash"><code class="lang-bash">export OS=&#x3C;operating-system>
<strong>export ARCH=&#x3C;system-architecture>
</strong><strong>export TAG=0.2.0
</strong>
<strong># Download the binary
</strong>wget https://github.com/hypersign-protocol/hid-node/releases/download/v${TAG}/hid-noded-${TAG}-${OS}-${ARCH}.tar.gz
</code></pre>

Refer the following table to obtain the environment variables for your system configuration.

| Operating System |   OS   |  ARCH |
| :--------------: | :----: | :---: |
|   Linux 64-bit   |  linux | amd64 |
|    Linux ARMv7   |  linux | arm64 |
|       MacOS      | darwin | amd64 |


# Running a Testnet Validator Node

### Hardware Requirements

* **Minimal**
  * 16 GB RAM
  * 300 GB SSD Storage
  * 1.4 GHz x2 CPU
* **Recommended**
  * 32 GB RAM
  * 600 GB SSD Storage
  * 2.0 GHx x4 CPU

### Prerequisites

* Golang 1.21 required. ([Installation Ref](https://go.dev/doc/install))
* git [Installation Ref](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git)
* make [Installation Ref](https://linuxhint.com/install-make-ubuntu/)

### Installation

{% content-ref url="/pages/MSavVmvFkvAe8iX2yARq" %}
[Installation of Node](/hypersign-identity-network/validator/installation-of-node)
{% endcontent-ref %}

### Generate Wallet

* Run the following to generate a wallet. Save the mnemonic displayed on the output, which can be used for scenarios where you would like to import your wallet address.

```
hid-noded keys add <key-name>
```

* If you already have a [BIP39](https://github.com/bitcoin/bips/tree/master/bip-0039) mnemonic, you can import your wallet by running the following. Enter the mnemonic string in the prompt and the wallet will be imported.

```
hid-noded keys add <key-name> --recover
```

### Configure the Full Node

* Initialise the node with a moniker name.

```
hid-noded init <moniker-name> --chain-id prajna-1
```

Configuration files of the node are stored in the default location: `$HOME/.hid-node`. If you want to specify a different location, append the flag `--home <hid-node-home-directory>` to the above command. In this case, for every transaction based commands, you have to explicitly pass this flag.

* Replace `genesis.json` present in `<hid-node-home-directory>/config` with the Testnet genesis [here](https://github.com/hypersign-protocol/networks/blob/master/testnet/prajna/final_genesis.json).
* Copy the final peers from [here](https://github.com/hypersign-protocol/networks/blob/master/testnet/prajna/final_peers.txt). Open `<hid-node-home-directory>/config/config.toml` and the add the peers in the field `persistent_peers`.

### Run Full Node

`hid-noded` binary can be run in either of the following ways:

* In Terminal

```
hid-noded start
```

* As a system service
  * Change directory: `cd /etc/systemd/system`
  * Add the [hid-noded system service file](https://github.com/hypersign-protocol/hid-node/blob/main/contrib/hidnoded-standalone.service) to `/etc/systemd/system` directory.
  * Reload service files: `sudo systemctl daemon-reload`
  * To make sure your service starts on every reboot (Optional): `sudo systemctl enable hidnoded-standalone.service`
  * To start the service: `sudo systemctl start hidnoded-standalone.service`
  * To check the status of service: `sudo systemctl status hidnoded-standalone.service`
  * To restart the service: `sudo systemctl restart hidnoded-standalone.service`

### Important Points

If you haven't run any CometBFT based chains before, please note the following points before moving to the upcoming sections below:-

* RPC and gRPC ports can be modified in `<blockchain-config-dir>/config/config.toml`
* API port can be modified in `<blockchain-config-dir>/config/app.toml`
* There are primarily two types of commands:
  * Transaction based. It starts with `hid-noded tx ...`
  * Query based. It starts with `hid-noded q ...`
* Transaction based commands may/always require the following flags:
  * `--chain-id prajna-1`
  * `--fees 4000uhid`: The value of fees is arbitrary, but it should be sufficiently high enough for the transaction to go through. `4000uhid` is an appropriate value for almost every transaction
  * `--node <rpc-ip-or-dns:rpc-port>`: The node expects RPC to run on default port 26657. If your RPC port is different from default, you need to explicitly pass this flag. In case of default port, it can be skipped.
* Query based commands may require the following flag:
  * `--node <rpc-ip-or-dns:rpc-port>`: The node expects RPC to run on default port 26657. If your RPC port is different from default, you need to explicitly pass this flag. In case of default port, it can be skipped.
* Learn more about Cosmos SDK's modules and their respective commands from [here](https://docs.cosmos.network/v0.47/build/modules)

### Promotion of Full Node to Validator Node

* Perform these steps only when your node is completely **synced** with the testnet.
* Acquire some **$HID** tokens. Use the faucet channel of Hypersign Protocol's Discord Server from [here](https://discord.com/channels/777575858075861033/1186968387860049920)
* Perform the following validator creation transaction.

```
hid-noded tx staking create-validator \
--from <key-name> \
--amount 1000000uhid \
--pubkey "$(hid-noded comet show-validator)" \
--chain-id prajna-1 \
--moniker="<validator-name>" \
--commission-max-change-rate=0.01 \
--commission-max-rate=1.0 \
--commission-rate=0.07 \
--min-self-delegation="1000000" \
--details="<enter details about your validator node or validation service>" \
--security-contact="<contain details>" \
--website="<your website>"
--fees="<Transaction fees in uhid. Example: 4000uhid>"
```

### Redeeming Staked Rewards

Having significant stake in the blockchain comes with reward in the form of tokens. The redemption of rewards needs to be done manually. Run the following to redeem rewards:

```
hid-noded tx distribution withdraw-rewards <validator-addr> --from <validator-wallet-address> --chain-id jagrat --fees <Transaction fees in uhid. Example: 4000uhid>
```

* `<validator-addr>` - Validator's Operator address. (Prefix is `hidvaloper`)
* `<validator-wallet-address>` - Validator's wallet address from which they have stake tokens. (Prefix `hid`)

If you also want to withdraw validator commission, append the `--commission` flag to the above command.

To check the outstanding validator rewards.

```
hid-noded q distribution validator-outstanding-rewards <validator-addr>
```

* `<validator-addr>` - Validator's Operator address. (Prefix is `hidvaloper`)

### Unjailing a validator node

In CometBFT-based blockchain, if a node is not active for a certain period of time or if the current self stake falls below the minimum self stake, it is temporarily moved out of the validator set. This situation is called Jailing of a validator. The validator remains in the jailed period for about 10 minutes.

The validator can only be unjailed manually through a transaction after the jailed period is over and if the current self stake is above the required self stake at the time the time of performing the following unjail transaction:

```
hid-noded tx slashing unjail --from <validator-associated-wallet-address> --chain-id jagrat --fees <amount-in-uhid>
```


# Governance


# Proposals

**Hypersign Identity Network** provides the facility of Governance, which provides opportunities to suggest changes in the blockchain. These suggestions to improve any aspect of the blockchain are expressed in the form of a **proposal**. A minimum deposit is needed (in $HID) to submit a proposal, and hence any user holding significant $HID can submit one of the following proposals:

* Simple Text Proposals
* Software Upgrade
* Blockchain Parameter Change
* Community Grants

Proposals status are of following types:

* **StatusDepositPeriod**
  * Time until necessary minimum deposit is made for a proposal
* **StatusVotingPeriod**
  * Time frame during which votes are accepted.
* **StatusPassed**
  * Proposal is passed and successfully executed
* **StatusRejected**
  * Proposal is rejected

A successful proposal requires a minimum participation from all stakeholders, known as Quoram. The value is **33.4%** of total voting power

Few helpful commands:

* Query the list of proposals

```
hid-noded q gov proposals
```

* Query a single proposal with proposal id

```
hid-noded q gov proposal <Proposal ID>
```

## Voting

Voting is essential is deciding whether a blockchain proposal will be accepted or rejected. Only Validators and their delegators have the ability to vote on proposals. There are four types of vote:

* **Yes**
  * Agreement on the proposal
* **No**
  * Disagreement on the proposal
* **Abstain**
  * Refrains from voting on the proposal
* **No With Vote**
  * Strongly Disagrees on the proposal with intention of discarding the proposal
  * If **33.4%** or more votes `No With Veto`, the proposal is discarded and the deposit is burned, unlike in above scenarios where the deposit is refunded to the proposer.
  * This ensures that any spam proposal submission will result in proposer losing their deposit.

Run the following command to submit your vote for a proposal:

```
hid-noded tx gov vote <Proposal ID> <Vote=(yes|no|abstain|no_with_veto)> \
--from <wallet-address-associated-with-validator> \
--chain-id <Chain ID>
```

Example: Voting `yes` to a proposal of proposal id 3.

```
hid-noded tx gov vote 3 yes --from <wallet-address-associated-with-validator> --chain-id jagrat
```




---

[Next Page](/llms-full.txt/1)

