Architecture

Overview

This section provides an overview of the Verification SDK's architecture, including its components and interactions.

Architecture Diagram

Explanation

  • Provider App & Beneficiary App: These applications interact with the Verification SDK to verify documents.

  • Verification SDK: Acts as the core component, exposing a REST API for verification.

  • Verification Service: Processes the verification requests and returns results.

  • Fastify Framework: Provides the underlying infrastructure for the REST API.

Sequence Diagram

Explanation

  • Request Verification: Both apps send verification requests to the SDK.

  • Process Verification: The SDK processes these requests through the Verification Service.

  • Return Result: Results are returned to the apps, with error handling and logging.

Data Flow Diagram

Explanation

  • Input: Credential JSON and configuration data are input into the Verification Service.

  • Processing: Data undergoes verification logic and validation.

  • Output: The final output is the verification result.

API Reference

The Verification SDK exposes the /verification API endpoint for credential verification. Below are the request and response details.

Request Body

  • credential (object, required): The credential JSON to verify.

  • config (object, required): Configuration object for verification.

  • method (string, required): The verification method to use:

    • "online": Verifies using a named online verifier (requires issuerName).

    • "offline": Planned feature (to be implemented).

  • issuerName (string, required if method is "online"): Name of the verifier to use. Currently supports "dhiway".

Example Request

PayLoad Example
{
    "credential": {
        "@context": [
            "https://www.w3.org/2018/credentials/v1",
            "https://cord.network/2023/cred/v1"
        ],
        "type": [
            "VerifiableCredential"
        ],
        "issuer": "did:cord:3y6YxHpmG3nysaT4GK7r1zeGAkvKAo15nMfEjAo7D254ZTh4",
        "issuanceDate": "2025-09-22T11:44:27.321Z",
        "credentialSubject": {
            "academicyear": "2025",
            "currentclass": 10,
            "firstname": "Jhon",
            "issuedby": "Mr Doy",
            "issueddate": "Mon, 01 Sep 2025 00:00:00 GMT",
            "issuerauthority": "Head of Institute",
            "lastname": "Doe",
            "originalvc": {
                "encoding": "7bit",
                "hash": "be9ab72fdf0ec136646ac57fc6327619553b26d8bb49c4214eb524f86e879985",
                "mimetype": "image/jpeg",
                "originalname": "images.jfif",
                "size": 12121,
                "url": "https://markstudio-test.s3.ap-south-1.amazonaws.com/apidata/record-content/e6fb4558-02d7-4664-92aa-09ffd6b1c92a-images.jfif"
            },
            "percentage": 70,
            "previousclass": 9,
            "result": "Pass",
            "schoolid": "SAMPLE123",
            "schoolname": "Sample school",
            "studentuniqueid": "SAMPLE123",
            "validupto": "Tue, 30 Sep 2025 00:00:00 GMT",
            "id": "did:cord:3y6YxHpmG3nysaT4GK7r1zeGAkvKAo15nMfEjAo7D254ZTh4",
            "@context": {
                "vocab": "schema:cord:s33fTLsBqUy8MwWPiy3MPYnj73K1Kdh1kHST5AQCfjUfFadaa#"
            }
        },
        "validFrom": "2025-09-22T11:44:27.321Z",
        "validUntil": "2026-09-22T11:44:27.321Z",
        "metadata": {},
        "credentialSchema": {
            "$id": "schema:cord:s33fTLsBqUy8MwWPiy3MPYnj73K1Kdh1kHST5AQCfjUfFadaa",
            "title": "Marksheet:70fd28a2-c80c-4777-8665-ed0fd43e5268",
            "description": "Schema for Marksheet",
            "properties": {
                "studentuniqueid": {
                    "type": "string"
                },
                "firstname": {
                    "type": "string"
                },
                "middlename": {
                    "type": "string"
                },
                "lastname": {
                    "type": "string"
                },
                "schoolid": {
                    "type": "string"
                },
                "schoolname": {
                    "type": "string"
                },
                "currentclass": {
                    "type": "number"
                },
                "previousclass": {
                    "type": "number"
                },
                "examdate": {
                    "type": "string"
                },
                "cgpa": {
                    "type": "number"
                },
                "cgpamax": {
                    "type": "number"
                },
                "grade": {
                    "type": "string"
                },
                "marksmax": {
                    "type": "number"
                },
                "markstotal": {
                    "type": "number"
                },
                "percentage": {
                    "type": "number"
                },
                "result": {
                    "type": "string"
                },
                "academicyear": {
                    "type": "string"
                },
                "issuedby": {
                    "type": "string"
                },
                "issuerauthority": {
                    "type": "string"
                },
                "issueddate": {
                    "type": "string"
                },
                "validupto": {
                    "type": "string"
                },
                "originalvc": {
                    "type": "object"
                },
                "originalvc1": {
                    "type": "object"
                },
                "issuingauthorityaddress": {
                    "type": "string"
                },
                "issuingauthoritydistrict": {
                    "type": "string"
                },
                "issuingauthoritypin": {
                    "type": "number"
                },
                "issuingauthoritystate": {
                    "type": "string"
                },
                "issuingauthoritycountry": {
                    "type": "string"
                }
            },
            "required": [
                "academicyear",
                "currentclass",
                "firstname",
                "issuedby",
                "issueddate",
                "issuerauthority",
                "lastname",
                "originalvc",
                "percentage",
                "previousclass",
                "result",
                "schoolid",
                "schoolname",
                "studentuniqueid",
                "validupto"
            ],
            "type": "object",
            "additionalProperties": false,
            "$schema": "http://cord.network/draft-01/schema#"
        },
        "credentialHash": "0x0d82b612cc7acb9368cd826f132d92d801f1dc4634b5fd1fae1a5c20c313e795",
        "id": "stmt:cord:s3eK5ECZAQ5EgwZABn5Mo3iopKYxpnJZw2zrqNigcHLAdnYnC",
        "proof": [
            {
                "type": "Ed25519Signature2020",
                "created": "Mon Sep 22 2025 11:44:27 GMT+0000 (Coordinated Universal Time)",
                "proofPurpose": "sr25519",
                "verificationMethod": "did:cord:3y6YxHpmG3nysaT4GK7r1zeGAkvKAo15nMfEjAo7D254ZTh4#0x4f3a986d94477a22b88cd86b82c5391550ad7c24cfeca27a1e1ef26b87c2c324",
                "proofValue": "z4epvxWZS8y9sKA6g9E4YXWuPG8CW2fDoq5pTPWrFihGG7UqX4di5SJbD53PrsL45UJbwA5hkz8vGnyzEwM3o4uW7"
            },
            {
                "type": "CordProof2024",
                "elementUri": "stmt:cord:s3eK5ECZAQ5EgwZABn5Mo3iopKYxpnJZw2zrqNigcHLAdnYnC:0d82b612cc7acb9368cd826f132d92d801f1dc4634b5fd1fae1a5c20c313e795",
                "spaceUri": "space:cord:c36BVtThSzuW4cuS5B2ddxu4Zvn6tFmvoX3hs4APXm3Me4x2m",
                "schemaUri": "schema:cord:s33fTLsBqUy8MwWPiy3MPYnj73K1Kdh1kHST5AQCfjUfFadaa",
                "creatorUri": "did:cord:3y6YxHpmG3nysaT4GK7r1zeGAkvKAo15nMfEjAo7D254ZTh4",
                "digest": "0x0d82b612cc7acb9368cd826f132d92d801f1dc4634b5fd1fae1a5c20c313e795",
                "identifier": "stmt:cord:s3eK5ECZAQ5EgwZABn5Mo3iopKYxpnJZw2zrqNigcHLAdnYnC",
                "genesisHash": "0x743115aca5f58453993db0b163772f35d086eafefe3b9bc30e304b76453e428a"
            },
            {
                "type": "CordSDRProof2024",
                "defaultDigest": "0x0b4d5200f4d0c5a4b063dc8da07898ea1bceef042f5227dbe1fd1cdc559c6866",
                "hashes": [
                    "0x0adf094297e8af4d48a5f11a65a27afe7b5d2929079194c23afd0a382cca5fe7",
                    "0x0c9d8ae851bf8f86fc5174e00217a1e9ac28b2e38d0e78a00d10618509f85669",
                    "0x23055fa546603c82ea8f36b60fccf060079951eb6cdf5fc76416720e2be67e0e",
                    "0x38c75f18e731e75dc5d76321eccd78983e3af30a24b2f507dd5bcf2dd5ade747",
                    "0x39cf72d862538734ec3a69fe9cbb0230579cb420b13fe1e3746ccb6888413483",
                    "0x5511237dd33b7e87a36700a16306b0184d71d1875fa70820cd9ab448d8f2ec5a",
                    "0x57d5cf088c2f2cff2ce9c4feab085095b9d181c06a71aa37d5efdeac2b53d298",
                    "0x6e77dd5c93b02c6ce50c79b1d16c5b29054d14107a04cccf974759227ef2db6d",
                    "0x6f29630576f9c205dbd6560a72ac3dab491a5611a272b277f590f09b6326a1cf",
                    "0x74f2ab88ea732babc1490c2c2346d76ec2b760f6abdbabc4ff6d993982d19519",
                    "0x7b3a4d72f7930aa6fa48c2ea3a639320a4193f6aafca965b53691ab3dfcbdf94",
                    "0x8dc8bf02506ecb94808982d6be53004a1546313ca7043136f24f4cdcdf495c43",
                    "0x8dde2b726ca16adb35e15c3c77b8f8612cb4130d797eac9e48a1075b7dc9926c",
                    "0x95e4ced20abcc6108afc05661cc6f5e4bde0b881dedb77552deba77c3979c399",
                    "0xa21ed0ccc11e63e9bb8bfc67b40013c1fceaaf537a4941285d71c84621a3fc13",
                    "0xb759d562edf0963a882bdaa2dab24c962d3a7c83c8ef535259545fcd86426963",
                    "0xb7adcce87f69f554cd6a48b929cac7fd79fd8dd22a30c218fbfca9fe7542727f",
                    "0xc9ab157a6da308bcc7cfe5c4c79f564b05ee59bcba145555e2bb7d1f93b02cf1",
                    "0xca32dcc070c7f16717216e17d15fb31d1976c6a9d4cc83cf9c228dbfa9df17be",
                    "0xdff27263f2639e8522484bee4833c5af4a53acf40bfeb5cbc65863ef51bd5581",
                    "0xe83d94e540823664f218d86d52acc76a489432169aff48427464107ece739257",
                    "0xf406179a4ec03524e48f8e29258b430402c455afb24faa1c1294c4ceb27fc4df"
                ],
                "nonceMap": {
                    "0x909e3509fded97c0dd7f09356b0e9fc6a26c708f9ae2bebe0359b26a08f7c25d": "08ade62f-0263-4fa4-9989-3cbef05f736d",
                    "0x2fc931e6127a88dad7c833b77c9217075b877c1720c931be11cb1e68a04c871a": "1618f147-0205-4ee7-bfc8-7d4ac6979ad4",
                    "0xf3c0f3e0faeea60738b25aa21c2fa817ea99c8c4eb96e9bb5975ee597c00f38b": "096fc016-b659-415e-ad8b-ddf285ccc703",
                    "0x27ecda15080e3415b8878c3e7013c60e73680d954094cd971223df4663a66c8f": "36ec60bc-8cda-4b7a-a6b8-96b62dbe41e3",
                    "0xea7d16de695fc7ab62445892ffc79f1ff4781ea8f694b03b437e2bf42fbf647b": "ca3e49f6-f51c-456c-af13-25eb8b71da3a",
                    "0x9f742dea10a7a5813d40c26a9cb7045aa441f1c623c298a1d00de3539c7d8d9d": "84986c75-dfc6-454d-9f3f-34cef39a923b",
                    "0x01995f13bc3693e98df91a5061dc9cd1ab915f0a05e15da6657fdb61770f00e3": "09846a83-2a02-4036-9a47-f034342df8cb",
                    "0x9674e7bbad206c1460aa31c2b4677d79f55ab4cfc43787ce154fb1678747c80f": "a41481f0-6f8e-43de-b5cf-97cc6c85c665",
                    "0x52c23e0115285b1ecffbe5f0a264ff0b49c68890966af4e1609c94ebd276728a": "e8722501-8845-4605-8639-b4035410e6f6",
                    "0x93bc8238cf386906051a3a00e95e0788ea74f1913b7ff2489555a2ad3dd5c5a7": "994927f2-11b8-4961-b29a-ce0d718d7a49",
                    "0xba23286b4a8d29fda27de5a97b90027950ede935d4db6ed6e8fb1ff0b8697fe0": "a0d43548-4897-4f94-b83e-15256f5d8aa9",
                    "0xff0fb5bd828433f39e285cad5b10cad0c9e40ff75affc5dd62b6beb2818de790": "70d18a89-b428-43a4-84ec-4d0db217159e",
                    "0x155997db4840bda1bdef9150be015e227784133537b98586ed79d56c4a10589d": "d0d8230b-6a1d-4a83-852b-dcb83cef4fd0",
                    "0x252385a801e24a119f58333ce43b4ce4c197844d7269b522ace4caa762593ced": "358a483f-4132-4140-88b1-773f86c8bb7e",
                    "0x92a06439732444f829504c82864a95021b14872d7fd6c2285180ce8818f54f6e": "cfd289bc-1922-4569-a3b8-9a3e1f641b35",
                    "0x9482e317bbd7f53eda01abe49b26a0b538ba8dfad734003c86ef99aa4d39c1ca": "b491f085-c336-4b9c-9ca4-51dbf5355000",
                    "0x3d2d5134d35024a721588de9d34805d7400911bd4444f1784d16139e0b6a1e0f": "cdd5b7d2-967c-4c08-a70f-3100249bd9f6",
                    "0xe6099df6393c6b7f3bd824bb8fd00d3fd64b4ab00d3cc2f8d86febac13b36f9e": "108acb12-e4f1-43af-98a3-0d5d9bdf4887",
                    "0x5949189c35396e6c41ccb87e2a04ed98420f543ef61be5dac5a7d0c4c3a826cc": "91d1c10a-fac0-472f-a0f7-13e36c2844a3",
                    "0x5043e4caf86a7af5054ceddd4f42e331eb90a9fd9f42ddca250d40b8b61fcb24": "2f73471e-224c-45b6-b631-8a5e2fd044b0",
                    "0x1e09d7cf2d80bce16840752e75a80830f58bed53e5b79be781310b4fef563e71": "542b3c82-c09a-4454-9b21-0ffe081ef9eb",
                    "0x8047c2585ea9f1e6d03d0b12a4a7273ef844c7a405075a369a0844f93f8a61fc": "c6f01903-584a-400a-a7eb-4bccb940e7b1"
                },
                "genesisHash": "0x743115aca5f58453993db0b163772f35d086eafefe3b9bc30e304b76453e428a"
            }
        ]
    },
    "config": {
        "method": "online",
        "issuerName": "dhiway"
    }
}

Example Response (Success)

{
  "success": true,
  "message": "Credential verified successfully."
}

Example Response (Failure)

{
  "success": false,
  "message": "Credential verification failed.",
  "errors": [
    {
      "error": "Some information in the credential couldn't be verified. Please ensure the credential is complete and hasn't been modified.",
      "raw": "Error verifyDisclosedAttributes"
    }
  ]
}

Error Response (Bad Request)

{
  "error": "Missing or empty required parameter: credential"
}

Core Components

The SDK uses a modular, extensible architecture for credential verification, centered around the src/services directory:

How to Add a New Verifier

  1. Create a New Verifier Class:

    • Implement the verify(credential) method with your logic.

    • Place your file in the appropriate folder (online-verifiers or offline-verifier).

  2. Naming Convention:

    • Name your class as <ProviderName>Verifier (e.g., AcmeVerifier).

    • The filename should match the class name (e.g., AcmeVerifier.js).

  3. Update Configuration:

    • To use your verifier, set method and issuerName in the request config:

      {
        "credential": { /* ... */ },
        "config": {
          "method": "online",
          "issuerName": "acme"
        }
      }
    • The factory will automatically load your verifier if the naming matches.

  4. (Optional) Add Error Translation:

    • For online verifiers, you can add custom error translation logic as shown in DhiwayVerifier.js.

Example: Adding a New Online Verifier

  1. Create src/services/verifiers/online-verifiers/AcmeVerifier.js:

    const VerifierInterface = require('../VerifierInterface');
    class AcmeVerifier extends VerifierInterface {
      async verify(credential) {
        // Your verification logic here
        return { success: true, message: 'Verified by Acme.' };
      }
    }
    module.exports = AcmeVerifier;
  2. Use it in your API request:

    {
      "credential": { /* ... */ },
      "config": {
        "method": "online",
        "issuerName": "acme"
      }
    }

Tip: No changes to the factory or service are needed if you follow the naming and folder conventions.

For more details, see the code in src/services.

Note: This SDK is designed to enable interoperable, extensible, and standards-based credential verification. To support new providers or offline verification, simply add a new class implementing the required logic and register it with the verification service.

Last updated