Schemas & Plugins

Extend the VC SDK with domain-specific credential types. Plugins auto-inject JSON-LD contexts, map properties, and compose with each other.

SchemaPlugin interface

SchemaPlugin interface
 interface SchemaPlugin {
  context: string                   // JSON-LD @context URI to inject
  types: string[]                   // Credential types this plugin handles
  propertyMap: Record<string, {   // Maps claim keys to JSON-LD terms
    term: string
    type?: string
  }>
} 

How plugins work

When a schema plugin is registered and a credential is issued with a matching type:

  1. The plugin's context URI is added to the credential's @context array.
  2. Claims are wrapped according to the propertyMap — mapping your keys to JSON-LD terms.
  3. The credential type array is validated against the plugin's types.

Registering plugins

Use issuer.use() to register plugins. Calls are chainable:

Plugin registration
 import { VCIssuer, generateKeyPair } from '@attestto-com/vc-sdk'
import { drivingLicenseSchema, medicalCertSchema } from '@attestto-com/cr-vc-schemas'

const keys = generateKeyPair()

const issuer = new VCIssuer({
  did: 'did:web:issuer.example.com',
  privateKey: keys.privateKey,
})
  .use(drivingLicenseSchema)
  .use(medicalCertSchema) 

Creating a custom plugin

Define your own schema for any credential type:

Custom schema plugin
 import type { SchemaPlugin } from '@attestto-com/vc-sdk'

const employmentSchema: SchemaPlugin = {
  context: 'https://schemas.example.com/employment/v1',
  types: ['EmploymentCredential'],
  propertyMap: {
    employer: { term: 'schema:employer' },
    jobTitle: { term: 'schema:jobTitle' },
    startDate: { term: 'schema:startDate', type: 'xsd:date' },
  },
} 
Using the custom plugin
 issuer.use(employmentSchema)

const vc = await issuer.issue({
  type: 'EmploymentCredential',
  subjectDid: 'did:web:employee.example.com',
  claims: {
    employer: 'Acme Corp',
    jobTitle: 'Software Engineer',
    startDate: '2026-01-15',
  },
})

// vc['@context'] includes 'https://schemas.example.com/employment/v1'
// vc.type includes 'EmploymentCredential' 

Multiple plugins coexisting

Plugins are independent. Each one only activates when the issued credential's type matches its types array. Multiple plugins can be registered simultaneously:

Multiple plugins
 issuer
  .use(drivingLicenseSchema)     // activates for 'DrivingLicense'
  .use(medicalCertSchema)         // activates for 'MedicalCertificate'
  .use(employmentSchema)          // activates for 'EmploymentCredential'

// Each issue() call triggers only the matching plugin
const license = await issuer.issue({ type: 'DrivingLicense', ... })
const medical = await issuer.issue({ type: 'MedicalCertificate', ... }) 
💡
Costa Rica schemas included. The @attestto-com/cr-vc-schemas package provides ready-made plugins for Costa Rica credential types: driving licenses, medical certificates, vehicle inspections, and more. See the full list.

Next steps