Build an issuer

You run the brand side: start an exchange and deliver a signed authenticity credential into the product's wallet — over the same VCALM exchange loop the wallet speaks.

You'll do exactly 3 things

  1. Expose an interaction URL (on a tag, QR, or link) that advertises vcapi.
  2. When the wallet POSTs to your exchange URL, respond with the authenticity credential in a verifiablePresentation.
  3. Optionally bind the credential to the current owner first, then deliver; finish the exchange.

1. Advertise the exchange

The wallet dereferences your interaction URL (iuv=1) and you return the protocols you support. Offer vcapi for VCALM:

{
  "protocols": {
    "vcapi": "https://issuer.brand.example/exchanges/bag-456"
  }
}

2. Deliver the credential

The wallet POSTs an empty body to start. You respond with the signed authenticity credential wrapped in a verifiablePresentation:

{
  "verifiablePresentation": {
    "@context": ["https://www.w3.org/ns/credentials/v2"],
    "type": ["VerifiablePresentation"],
    "verifiableCredential": [{
      "@context": [
        "https://www.w3.org/ns/credentials/v2",
        "https://w3id.org/traceability/v1"
      ],
      "type": ["VerifiableCredential", "ProductPassportCredential"],
      "issuer": "did:web:brand.example",
      "credentialSubject": {
        "id": "did:example:bag-456",
        "product": {"sku": "HB-2026-0042", "model": "Atelier Tote"},
        "origin": {"country": "FR", "facility": "Paris Atelier"},
        "manufacturedOn": "2026-03-14"
      },
      "proof": { "...": "brand signature" }
    }]
  }
}

The exchange is complete when you return no verifiablePresentationRequest.

3. (Optional) Bind to the current owner first

To tie the credential to whoever holds the product, respond to the wallet's first POST with a verifiablePresentationRequest for DID Authentication, then deliver on the next turn:

{
  "verifiablePresentationRequest": {
    "query": [{
      "type": "DIDAuthentication",
      "acceptedMethods": [{"method": "example"}]
    }],
    "challenge": "99612b24-63d9-11ea-b99f-4f66f3e4f81a",
    "domain": "issuer.brand.example"
  }
}

That's it

A conformant provenance issuer is this exchange: advertise, deliver, confirm. Signing the credential is your issuer instance's job — the coordinator just runs the exchange.

Prefer a library to raw HTTP?

Issuer-side helpers live in Digital Bazaar's Bedrock VC modules. A dogfooded standalone VCALM client is planned; until it ships, the HTTP flow above is the supported path.

Go deeper

← Back to roles