> ## Documentation Index
> Fetch the complete documentation index at: https://docs.verak.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Verifiable Credentials

> How to locate, fetch, and independently verify Verak-issued W3C Verifiable Credentials from a member's AT Protocol PDS.

# Verifiable Credentials

Verak issues W3C Verifiable Credentials to verified members. A VC is a signed structured achievement record — distinct from a label, which is a binary trust signal. Labels tell you *whether* someone is verified; VCs tell you *what* was verified, when, by whom, and with what proof.

This page documents the VC stack, where credentials live, and how to verify them independently using standard libraries with no Verak code.

***

## VC Stack

| Layer                 | Standard                                                  |
| --------------------- | --------------------------------------------------------- |
| Credential data model | W3C VC Data Model 2.0                                     |
| Achievement type      | Open Badges 3.0 (`OpenBadgeCredential`)                   |
| Proof suite           | `Ed25519Signature2020`                                    |
| Issuer identity       | `did:web:labeler.verak.app`                               |
| Subject identity      | Member's `did:plc`                                        |
| Storage               | Member's AT Protocol PDS (`is.verak.passport.credential`) |

Verak does not store issued VCs on its own infrastructure. After issuance, the signed credential is delivered to the member's PDS. Verak retains a public viewer record (at `/credentials/{id}`) for human-readable display, but the canonical credential lives with the member.

***

## Issuer Resolution

The issuer is identified by `did:web:labeler.verak.app`. To resolve the issuer's DID document:

```bash theme={null}
curl "https://labeler.verak.app/.well-known/did.json"
```

The DID document is served with CORS headers (`Access-Control-Allow-Origin: *`), which means browser-based VC wallets can resolve it directly without a proxy.

The document contains a `verificationMethod` entry for the issuer's Ed25519 signing key:

```json theme={null}
{
  "@context": ["https://www.w3.org/ns/did/v1"],
  "id": "did:web:labeler.verak.app",
  "verificationMethod": [
    {
      "id": "did:web:labeler.verak.app#key-1",
      "type": "Ed25519VerificationKey2020",
      "controller": "did:web:labeler.verak.app",
      "publicKeyMultibase": "z6Mk..."
    }
  ],
  "assertionMethod": ["did:web:labeler.verak.app#key-1"]
}
```

The `publicKeyMultibase` value is the base58btc-encoded public key used to verify all Verak-issued credentials.

***

## Subject Convention

All Verak VCs use the member's `did:plc` as the credential subject identifier:

```json theme={null}
{
  "credentialSubject": {
    "id": "did:plc:member-did-here",
    "type": "AchievementSubject",
    "achievement": { ... }
  }
}
```

This means you can verify that a credential was issued to a specific AT Protocol identity without knowing the member's handle, email, or any other personal identifier.

***

## Locating Credentials on a Member's PDS

Credential references are stored as `is.verak.passport.credential` records on the member's PDS. Each record is a reference — it contains the credential metadata and a URI pointing to the full signed VC.

**Step 1 — Resolve the member's PDS endpoint**

```bash theme={null}
curl "https://plc.directory/did:plc:MEMBER-DID"
```

Locate the entry in the `service` array where `type` is `AtpPersonalDataServer`. The `serviceEndpoint` value is the PDS host.

**Step 2 — List credential records**

```bash theme={null}
curl "{pds-host}/xrpc/com.atproto.repo.listRecords
  ?repo=did:plc:MEMBER-DID
  &collection=is.verak.passport.credential
  &limit=50"
```

Public records (those with `isPublic: true`) are returned without authentication. The full list, including private records, is only accessible to the account owner via an authenticated session.

**Step 3 — Fetch the signed VC**

Each record contains a `credentialUri` field pointing to the full JSON-LD credential. For Verak-issued VCs, this resolves to:

```bash theme={null}
curl "https://verak.app/api/credentials/{id}"
```

The response is the raw JSON-LD signed VC with `Content-Type: application/ld+json`.

***

## Worked Example: End-to-End Verification

The following example fetches a credential reference from a member's PDS, resolves the full VC, and verifies the Ed25519 proof using the `@digitalbazaar/vc` family of libraries. No Verak code is required.

```js theme={null}
import { Ed25519VerificationKey2020 } from '@digitalbazaar/ed25519-verification-key-2020'
import { Ed25519Signature2020 } from '@digitalbazaar/ed25519-signature-2020'
import * as vc from '@digitalbazaar/vc'
import jsonld from 'jsonld'

// 1. Resolve the issuer's DID document and extract the signing key
const didDoc = await fetch('https://labeler.verak.app/.well-known/did.json')
  .then(r => r.json())

const verificationMethod = didDoc.verificationMethod.find(
  vm => vm.type === 'Ed25519VerificationKey2020'
)

const issuerKey = await Ed25519VerificationKey2020.from(verificationMethod)

// 2. Build a document loader that resolves the issuer DID locally
//    (avoids a network round trip during verification)
const documentLoader = jsonld.documentLoaders.node()
const customLoader = async (url) => {
  if (url === 'did:web:labeler.verak.app' || url.startsWith('did:web:labeler.verak.app#')) {
    return { contextUrl: null, document: didDoc, documentUrl: url }
  }
  return documentLoader(url)
}

// 3. Fetch the signed credential
const credential = await fetch('https://verak.app/api/credentials/CREDENTIAL-ID')
  .then(r => r.json())

// 4. Verify
const suite = new Ed25519Signature2020({ key: issuerKey })

const result = await vc.verifyCredential({
  credential,
  suite,
  documentLoader: customLoader,
})

if (result.verified) {
  const subject = credential.credentialSubject.id  // did:plc:...
  const achievement = credential.credentialSubject.achievement.name
  console.log(`${achievement} verified for ${subject}`)
} else {
  console.error('Verification failed:', result.error)
}
```

**What a successful result means**

* The credential was issued by `did:web:labeler.verak.app`
* The `credentialSubject.id` is the member's AT Protocol DID
* The proof has not been tampered with since issuance
* The credential has not expired (check `expirationDate` if present)

**What it does not mean**

Proof verification confirms cryptographic integrity. It does not confirm that the underlying evidence reviewed by Verak editors is still current. For live trust state — including revocation — query the labeler directly.

***

## Credential Structure Reference

A Verak-issued VC has this shape:

```json theme={null}
{
  "@context": [
    "https://www.w3.org/2018/credentials/v1",
    "https://purl.imsglobal.org/spec/ob/v3p0/context-3.0.3.json",
    "https://w3id.org/security/suites/ed25519-2020/v1"
  ],
  "id": "https://verak.app/api/credentials/CREDENTIAL-ID",
  "type": ["VerifiableCredential", "OpenBadgeCredential"],
  "issuer": {
    "id": "did:web:labeler.verak.app",
    "type": "Profile",
    "name": "Verak"
  },
  "issuanceDate": "2026-06-01T00:00:00.000Z",
  "credentialSubject": {
    "id": "did:plc:member-did-here",
    "type": "AchievementSubject",
    "achievement": {
      "id": "https://verak.app/achievements/verified-professional",
      "type": ["Achievement"],
      "name": "Verified Professional",
      "description": "Identity and professional standing independently reviewed and verified by Verak editors.",
      "criteria": {
        "narrative": "Issued after a Verak editor reviews submitted evidence signals and confirms professional identity."
      }
    }
  },
  "proof": {
    "type": "Ed25519Signature2020",
    "created": "2026-06-01T00:00:00.000Z",
    "verificationMethod": "did:web:labeler.verak.app#key-1",
    "proofPurpose": "assertionMethod",
    "proofValue": "z..."
  }
}
```

***

## Dependencies

The worked example above requires:

```bash theme={null}
npm install @digitalbazaar/vc \
            @digitalbazaar/ed25519-verification-key-2020 \
            @digitalbazaar/ed25519-signature-2020 \
            jsonld
```

These are maintained by the Digital Bazaar team and implement the W3C VC Data Model and Ed25519 proof suite specifications. No Verak packages are required.

<Note>
  These libraries use the Node.js runtime. The `jsonld` package uses a document loader that requires network access at verify time for any `@context` URLs it hasn't already resolved. The custom document loader in the example above short-circuits the issuer DID resolution to avoid the network round trip. You may want to cache the W3C and IMS contexts locally for production use.
</Note>
