Build an issuer

You run the brand side. As a coordinator you speak VCALM — just the coordinator side of it. You don't run VCALM delivery, the on-the-wire exchange with the product's wallet; a workflow service does that. Your whole job is three calls: create an exchange, share an interaction URL that points the product's wallet at it, then poll the exchange until the credential has been issued.

What the coordinator does

  1. Create an exchange by POSTing the workflow's variables to its exchanges endpoint.
  2. Host and share an interaction URL that points the product's wallet at that exchange.
  3. Poll the exchange until it completes, then read the result.

The workflow service does everything in between — protocol negotiation, optional owner binding, signing, talking to whatever wallet shows up — and hands you back just the result.

1. Create the exchange

POST to your workflow's exchanges endpoint. The body carries a ttl and the variables the workflow expects — here, which product the credential is for:

POST https://workflows.example/workflows/provenance-issuance/exchanges
{
  "ttl": 900,
  "variables": {
    "subject": "did:example:bag-456",
    "sku": "HB-2026-0042"
  }
}

This call is authenticated (your service uses a capability or OAuth2 token). On success the service returns 204 No Content with a Location header — that's your exchange URL:

HTTP/1.1 204 No Content
Location: https://workflows.example/workflows/provenance-issuance/exchanges/z19xQ...

2. Host and share the interaction URL

The exchange URL is the vcapi interaction endpoint. Hosting and sharing it is the coordinator's responsibility — put it on a tag, QR code, or link, typically wrapped in a presentation request the wallet understands:

{
  "VerifiablePresentation": {
    "interact": {
      "service": [{
        "type": "VerifiableCredentialApiExchangeService",
        "serviceEndpoint": "https://workflows.example/workflows/provenance-issuance/exchanges/z19xQ..."
      }]
    }
  }
}

The product's wallet POSTs to that endpoint and runs the exchange with the workflow service directly. Owner binding and credential delivery happen there — you are not in that loop.

3. Poll for the result

While the wallet works, GET the exchange URL (authenticated) until its state is complete:

GET https://workflows.example/workflows/provenance-issuance/exchanges/z19xQ...
{
  "exchange": {
    "id": "z19xQ...",
    "state": "complete",
    "variables": {
      "results": {
        "ownerBinding": {
          "did": "did:example:bag-456",
          "verifiablePresentation": { "...": "the wallet's authenticated VP" }
        }
      }
    }
  }
}

Verified per-step results land under exchange.variables.results, keyed by the workflow's step names. A complete state means the authenticity credential was issued into the product's wallet.

That's it

A provenance issuer, as a coordinator, is these three calls: create an exchange, host and share the interaction URL, poll for the result. Signing the credential and speaking every wallet's protocol is the workflow service's job — you just create exchanges and read what comes back.

On the wallet end, a standalone client-side VCALM library is still planned; until it ships, wallets run the exchange over the raw HTTP flow. The coordinator side shown here works today against any VCALM workflow service, such as one running @bedrock/vc-delivery.

Go deeper

← Back to roles