Skip to content
3.5. Verifiable Credentials

3.5. Verifiable Credentials

This tutorial covers the Verifiable Credentials (VCs) system in the dAIEDGE Middleware, enabling decentralized identity attestations following W3C standards.

Overview

Verifiable Credentials allow you to:

  • Request attestations about your identity (claims)
  • Issue credentials as a trusted issuer
  • Verify credential authenticity cryptographically
  • Present credentials for authentication
  • Manage credential lifecycle (activate/revoke)

What are Verifiable Credentials?

VCs are tamper-proof digital attestations issued by trusted parties:

  • Issuer: Entity that creates and signs the credential
  • Holder: Entity that receives and presents the credential
  • Verifier: Entity that checks the credential’s validity

Prerequisites


User Roles

Issuer Role

The VC system uses application-level roles (not blockchain roles):

RolePurposeWho Has It
IssuerIssue VCs, view requests, activate/revoke VCsUsers granted issuer role by admin
AdminGrant/revoke issuer rolePlatform administrators
Regular UserRequest VCs, view own VCs, verify/decode VCsAll authenticated users

Role Hierarchy

Admin (platform level)
└── Can grant/revoke Issuer role

Issuer
├── View VC requests
├── Accept VC requests (issue credentials)
├── Activate VCs
└── Revoke VCs

Regular User
├── Request VCs
├── View own VCs
├── Verify credentials
└── Decode credentials

Step 1: Request a Verifiable Credential

Request a VC with specific claims about your identity.

Endpoint

POST /api/v1/vcs/requests

Request

curl -X POST https://middleware-daiedge.bisite.usal.es/api/v1/vcs/requests \
  -H "Content-Type: application/json" \
  -H "x-session-id: {SESSION_ID}" \
  -d '{
    "walletId": "0000019a9c4f8d2b1e7a6f3c9b5e8d1a",
    "password": "WalletPass123!",
    "did": "did:ethr:development:0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb7",
    "claims": [
      {
        "type": "group",
        "value": "Group1"
      }
    ]
  }'

Request Body

FieldTypeRequiredDescription
walletIdstringYesYour wallet ID
passwordstringYesWallet password
didstringYesYour DID (must be owned by your wallet)
claimsarrayYesArray of claim objects

Supported Claims

Claim TypeData TypeAllowed ValuesDescription
groupenumGroup1, Group2User membership group for access control

Claim Object Structure

{
  "type": "group",
  "value": "Group1"
}

Response (200 OK)

Note: This endpoint returns an empty body. To find your request after submitting it, use the list endpoint (Step 2) and filter by your did.

{}

Error Responses

CodeErrorCause
404WALLET_NOT_FOUNDWallet doesn’t exist
400WRONG_PASSWORDWallet password incorrect
400INVALID_DIDDID format invalid
400NOT_IDENTITY_OWNERWallet doesn’t own this DID
400INVALID_CLAIMS_FORMATClaims array structure invalid
400INVALID_CLAIM_TYPEUnsupported claim type
400INVALID_CLAIM_VALUEValue not allowed for claim type
403INVALID_WALLETWallet doesn’t belong to you

Step 2: List Your Verifiable Credentials

View all VCs issued to your identity.

Endpoint

GET /api/v1/vcs?did={did}&page={page}

Request

curl -X GET "https://middleware-daiedge.bisite.usal.es/api/v1/vcs?did=did:ethr:development:0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb7&page=1" \
  -H "x-session-id: {SESSION_ID}"

Query Parameters

ParameterTypeRequiredDescription
didstringYesYour DID
pagenumberNoPage number (default: 1)

Response (200 OK)

{
  "vcs": [
    {
      "id": "0000019a9c6a7b8c9d1e2f3a4b5c6d7e",
      "did": "did:ethr:development:0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb7",
      "credential": "eyJhbGciOiJFUzI1NksifQ...",
      "active": true
    }
  ],
  "page": 1,
  "totalPages": 1,
  "total": 1
}

Response Fields

FieldDescription
idVerifiable Credential ID
didDID the credential was issued to
credentialJWT-encoded Verifiable Credential
activeWhether the credential is currently active

Error Responses

CodeErrorCause
400INVALID_DIDDID format invalid
404USER_DID_NOT_FOUNDDID not found in system
403INVALID_USER_DIDDID doesn’t belong to you

Step 3: Verify a Verifiable Credential

Cryptographically verify that a credential is valid.

Endpoint

POST /api/v1/vcs/verify-credential

Request

curl -X POST https://middleware-daiedge.bisite.usal.es/api/v1/vcs/verify-credential \
  -H "Content-Type: application/json" \
  -H "x-session-id: {SESSION_ID}" \
  -d '{
    "vcJwt": "eyJhbGciOiJFUzI1NksifQ..."
  }'

Request Body

FieldTypeRequiredDescription
vcJwtstringYesJWT-encoded Verifiable Credential

Response (200 OK)

{
  "verified": true,
  "credential": {
    "verified": true,
    "payload": {
      "iat": 1763540833,
      "vc": {
        "@context": [
          "https://www.w3.org/2018/credentials/v1"
        ],
        "type": [
          "VerifiableCredential"
        ],
        "credentialSubject": {
          "did": "did:ethr:development:0x7018205409a98fb9580b53e268d58c96d58ba640",
          "group": "Group1"
        }
      },
      "sub": "did:ethr:development:0x7018205409a98fb9580b53e268d58c96d58ba640",
      "jti": "0000019a9b39952bad9a53740f7ce5ed",
      "iss": "did:ethr:development:0x9AEd54E5cBD5e7d1aE523c104B9C23019B567B05"
    },
    "didResolutionResult": {
      "didDocumentMetadata": {},
      "didResolutionMetadata": {
        "contentType": "application/did+ld+json"
      },
      "didDocument": {
        "id": "did:ethr:development:0x9AEd54E5cBD5e7d1aE523c104B9C23019B567B05",
        "verificationMethod": [
          {
            "id": "did:ethr:development:0x9AEd54E5cBD5e7d1aE523c104B9C23019B567B05#controller",
            "type": "EcdsaSecp256k1RecoveryMethod2020",
            "controller": "did:ethr:development:0x9AEd54E5cBD5e7d1aE523c104B9C23019B567B05",
            "blockchainAccountId": "eip155:1337:0x9AEd54E5cBD5e7d1aE523c104B9C23019B567B05"
          }
        ],
        "authentication": [
          "did:ethr:development:0x9AEd54E5cBD5e7d1aE523c104B9C23019B567B05#controller"
        ],
        "assertionMethod": [
          "did:ethr:development:0x9AEd54E5cBD5e7d1aE523c104B9C23019B567B05#controller"
        ],
        "@context": [
          "https://www.w3.org/ns/did/v1",
          "https://w3id.org/security/suites/secp256k1recovery-2020/v2",
          "https://w3id.org/security/v3-unstable"
        ]
      }
    },
    "issuer": "did:ethr:development:0x9AEd54E5cBD5e7d1aE523c104B9C23019B567B05",
    "signer": {
      "id": "did:ethr:development:0x9AEd54E5cBD5e7d1aE523c104B9C23019B567B05#controller",
      "type": "EcdsaSecp256k1RecoveryMethod2020",
      "controller": "did:ethr:development:0x9AEd54E5cBD5e7d1aE523c104B9C23019B567B05",
      "blockchainAccountId": "eip155:1337:0x9AEd54E5cBD5e7d1aE523c104B9C23019B567B05"
    },
    "jwt": "eyJhbGciOiJFUzI1NkstUiIsInR5cCI6IkpXVCJ9...",
    "policies": {},
    "verifiableCredential": {
      "credentialSubject": {
        "did": "did:ethr:development:0x7018205409a98fb9580b53e268d58c96d58ba640",
        "group": "Group1",
        "id": "did:ethr:development:0x7018205409a98fb9580b53e268d58c96d58ba640"
      },
      "issuer": {
        "id": "did:ethr:development:0x9AEd54E5cBD5e7d1aE523c104B9C23019B567B05"
      },
      "id": "0000019a9b39952bad9a53740f7ce5ed",
      "type": [
        "VerifiableCredential"
      ],
      "@context": [
        "https://www.w3.org/2018/credentials/v1"
      ],
      "issuanceDate": "2025-11-19T08:27:13.000Z",
      "proof": {
        "type": "JwtProof2020",
        "jwt": "eyJhbGciOiJFUzI1NkstUiIsInR5cCI6IkpXVCJ9..."
      }
    }
  }
}

Error Responses

CodeErrorCause
400INVALID_VCJWTVC JWT is empty or invalid

Step 4: Decode a Verifiable Credential

Decode the JWT without cryptographic verification.

Endpoint

POST /api/v1/vcs/decode-credential

Request

curl -X POST https://middleware-daiedge.bisite.usal.es/api/v1/vcs/decode-credential \
  -H "Content-Type: application/json" \
  -H "x-session-id: {SESSION_ID}" \
  -d '{
    "vcJwt": "eyJhbGciOiJFUzI1NksifQ..."
  }'

Response (200 OK)

{
  "iat": 1763540833,
  "vc": {
    "@context": [
      "https://www.w3.org/2018/credentials/v1"
    ],
    "type": [
      "VerifiableCredential"
    ],
    "credentialSubject": {
      "did": "did:ethr:development:0x7018205409a98fb9580b53e268d58c96d58ba640",
      "group": "Group1"
    }
  },
  "sub": "did:ethr:development:0x7018205409a98fb9580b53e268d58c96d58ba640",
  "jti": "0000019a9b39952bad9a53740f7ce5ed",
  "iss": "did:ethr:development:0x9AEd54E5cBD5e7d1aE523c104B9C23019B567B05"
}

Error Responses

CodeErrorCause
400INVALID_VCJWTVC JWT is empty or invalid

Issuer Operations (Issuer Role Required)

The following operations require the Issuer role.

Step 5: List VC Requests (Issuer Only)

View all pending credential requests.

Endpoint

GET /api/v1/vcs/requests?page={page}

Request

curl -X GET "https://middleware-daiedge.bisite.usal.es/api/v1/vcs/requests?page=1" \
  -H "x-session-id: {SESSION_ID}"

Response (200 OK)

{
  "requests": [
    {
      "id": "0000019a9c7f3e2d1c8b4a7e6f9c3d2a",
      "did": "did:ethr:development:0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb7",
      "info": "{\"did\":\"did:ethr:development:0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb7\",\"group\":\"Group1\"}",
      "created": 1697000000000,
      "accepted": false
    }
  ],
  "page": 1,
  "totalPages": 1,
  "total": 1
}

Response Fields

FieldDescription
idRequest ID
didRequester’s DID
infoJSON string with requested claims
createdRequest timestamp
acceptedWhether the request has been accepted

Error Responses

CodeErrorCause
403NOT_ISSUERYou don’t have issuer role

Step 6: Accept VC Request (Issuer Only)

Issue a credential by accepting a request.

Endpoint

POST /api/v1/vcs/requests/{id}/accept

Request

curl -X POST https://middleware-daiedge.bisite.usal.es/api/v1/vcs/requests/{REQUEST_ID}/accept \
  -H "Content-Type: application/json" \
  -H "x-session-id: {SESSION_ID}" \
  -d '{
    "walletId": "0000019a9c8e4d3f2a1b7c6e5f9d8a3b",
    "password": "IssuerPass123!"
  }'

Request Body

FieldTypeRequiredDescription
walletIdstringYesIssuer’s wallet ID
passwordstringYesWallet password

Response (200 OK)

{}

The VC is created and associated with the requester’s DID.

Error Responses

CodeErrorCause
404VC_REQUEST_NOT_FOUNDRequest doesn’t exist
400REQUEST_ALREADY_ACCEPTEDRequest was already accepted
400WRONG_PASSWORDWallet password incorrect
403NOT_ISSUERYou don’t have issuer role
403INVALID_WALLETWallet doesn’t belong to you

Step 7: Activate/Revoke VCs (Issuer Only)

Activate a VC

POST /api/v1/vcs/active/{VC_ID}
curl -X POST https://middleware-daiedge.bisite.usal.es/api/v1/vcs/active/{VC_ID} \
  -H "x-session-id: {SESSION_ID}"

Revoke a VC

POST /api/v1/vcs/revoke/{VC_ID}
curl -X POST https://middleware-daiedge.bisite.usal.es/api/v1/vcs/revoke/{VC_ID} \
  -H "x-session-id: {SESSION_ID}"

Response (200 OK)

{}

Error Responses

CodeErrorCause
404VC_NOT_FOUNDVC doesn’t exist
403NOT_ISSUERYou don’t have issuer role

Admin Operations (Admin Role Required)

The following operations require the Admin role.

Step 8: Grant/Revoke Issuer Role (Admin Only)

Grant Issuer Role

POST /api/v1/vcs/grant-issuer-role
curl -X POST https://middleware-daiedge.bisite.usal.es/api/v1/vcs/grant-issuer-role \
  -H "Content-Type: application/json" \
  -H "x-session-id: {SESSION_ID}" \
  -d '{
    "uid": "0000019a9ca2e3f4a5b6c7d8e9f1a2b3"
  }'

Revoke Issuer Role

POST /api/v1/vcs/revoke-issuer-role
curl -X POST https://middleware-daiedge.bisite.usal.es/api/v1/vcs/revoke-issuer-role \
  -H "Content-Type: application/json" \
  -H "x-session-id: {SESSION_ID}" \
  -d '{
    "uid": "0000019a9ca1d2e3f4a5b6c7d8e9f1a2"
  }'

Request Body

FieldTypeRequiredDescription
uidstringYesTarget user’s UID

Response (200 OK)

{}

Error Responses

CodeErrorCause
404USER_NOT_FOUNDUser doesn’t exist
403NOT_ADMINYou don’t have admin role

VC Lifecycle

1. User Requests VC
   → Submits claims for attestation

2. Issuer Reviews Request
   → Views pending requests
   → Validates claims

3. Issuer Accepts Request
   → Signs and issues credential
   → VC becomes active

4. User Receives VC
   → JWT stored in system
   → Can present to verifiers

5. Verifier Checks VC
   → Cryptographic verification
   → Checks issuer trust
   → Validates claims

6. Lifecycle Management
   → Issuer can revoke VC
   → Issuer can re-activate VC

Next Steps

Related Topics