Issuing Credentials

Create W3C Verifiable Credentials with the VCIssuer class. Configure your DID, sign with Ed25519 or ES256, and extend with schema plugins.

Install

Terminal
 npm install @attestto-com/vc-sdk 

IssuerConfig

Pass an IssuerConfig object when constructing the issuer:

IssuerConfig interface
 interface IssuerConfig {
  did: string              // Issuer DID (e.g. 'did:web:example.com')
  privateKey: Uint8Array   // Private key bytes
  algorithm?: 'Ed25519' | 'ES256'  // Default: 'Ed25519'
  keyId?: string          // Verification method ID (default: did + '#key-1')
} 
Basic issuer setup
 import { VCIssuer, generateKeyPair } from '@attestto-com/vc-sdk'

const keys = generateKeyPair()

const issuer = new VCIssuer({
  did: 'did:web:my-org.example.com',
  privateKey: keys.privateKey,
  algorithm: 'Ed25519',
  keyId: 'did:web:my-org.example.com#signing-key-2026',
}) 

IssueOptions

The issue() method accepts these options:

IssueOptions interface
 interface IssueOptions {
  type: string | string[]     // Credential type(s) — added to ['VerifiableCredential']
  subjectDid: string          // The subject's DID
  claims: Record<string, unknown>  // Claims about the subject
  context?: string | string[] // Additional JSON-LD @context URIs
  expirationDate?: string    // ISO 8601 expiration timestamp
  credentialStatus?: {      // Optional revocation endpoint
    id: string
    type: string
  }
  id?: string                 // Credential ID (auto-generated UUID if omitted)
} 

Issuing a credential

issue-credential.ts
 const vc = await issuer.issue({
  type: 'ProfessionalLicense',
  subjectDid: 'did:web:holder.example.com',
  claims: {
    profession: 'Civil Engineer',
    licenseNumber: 'CE-2026-1234',
    jurisdiction: 'Costa Rica',
  },
  expirationDate: '2028-12-31T23:59:59Z',
  credentialStatus: {
    id: 'https://status.example.com/credentials/1',
    type: 'StatusList2021Entry',
  },
})

console.log(vc.id)     // 'urn:uuid:...' (auto-generated)
console.log(vc.type)   // ['VerifiableCredential', 'ProfessionalLicense']
console.log(vc.proof)  // { type: 'Ed25519Signature2020', ... } 

Multiple types

Pass an array to type to apply multiple credential types:

TypeScript
 const vc = await issuer.issue({
  type: ['ProfessionalLicense', 'GovernmentIssuedCredential'],
  subjectDid: 'did:web:holder.example.com',
  claims: { profession: 'Architect' },
})
// vc.type = ['VerifiableCredential', 'ProfessionalLicense', 'GovernmentIssuedCredential'] 

Schema plugins

Register schema plugins with issuer.use() to auto-inject JSON-LD contexts and validate claims against known types. Calls are chainable.

Using schema plugins
 import { drivingLicenseSchema } from '@attestto-com/cr-vc-schemas'

issuer.use(drivingLicenseSchema)

// Now issuing a 'DrivingLicense' type auto-injects the CR context
const vc = await issuer.issue({
  type: 'DrivingLicense',
  subjectDid: 'did:web:holder.example.com',
  claims: { licenseClass: 'B1', fullName: 'Jane Doe' },
}) 
💡
Auto-generated IDs. When you omit the id option, the SDK generates a urn:uuid:... identifier automatically. Pass your own if you need deterministic credential IDs.

Next steps