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
- Verifying credentials — validate signatures, check expiration, detect tampering
- Key management — Ed25519 vs ES256, generation, and storage
- Schemas & plugins — build custom schema plugins for your domain
- Costa Rica credentials — CR-specific types and schemas