Build a verifier
- You run the buyer or retailer side: ask the product's wallet to present its
- authenticity credential, then verify the proof — over the same VCALM
- exchange loop the wallet speaks.
+ You run the buyer or retailer 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 and verifies the credential
+ for you. Your job is three calls: create
+ an exchange, share an interaction URL that points the product's wallet at it,
+ then poll until the verified result comes back.
- Under the hood: the raw VCALM exchange
-
- Want to build your own coordinator, or just see exactly what the server does
- on the wire? It's a short HTTP loop — three things:
-
+ What the coordinator does
- - Expose an interaction URL that advertises
vcapi.
- - When the wallet POSTs to start, respond with a
-
verifiablePresentationRequest describing the credential you
- need.
- - Receive the
verifiablePresentation and verify its proof,
- challenge, and domain.
+ - Create an exchange against a workflow that requests the
+ authenticity credential and names the brands you trust.
+ - Host and share an interaction URL that points the
+ product's wallet at that exchange.
+ - Poll the exchange until it completes, then read the
+ verified result.
+
+ The workflow service does the rest — it sends the presentation request,
+ receives the wallet's response, and verifies the proof, challenge, domain,
+ trusted issuer, and status before it ever returns a result to you.
+
- 1. Request the credential
+ 1. Create the exchange
- When the wallet POSTs an empty body to your exchange URL, respond with a
- QueryByExample asking for the credential type you need:
+ POST to your workflow's exchanges endpoint. The workflow already
+ encodes request a product passport and trust the real
+ brand; you pass just the per-exchange variables:
+ {% highlight "bash" %}
+POST https://workflows.example/workflows/authenticity-check/exchanges
+ {% endhighlight %}
{% highlight "json" %}
{
- "verifiablePresentationRequest": {
- "query": [{
- "type": "QueryByExample",
- "credentialQuery": [{
- "reason": "Please present this product's authenticity credential.",
- "example": {
- "@context": [
- "https://www.w3.org/ns/credentials/v2",
- "https://w3id.org/traceability/v1"
- ],
- "type": "ProductPassportCredential"
- },
- "trustedIssuer": [{
- "required": true,
- "issuer": "did:web:brand.example"
- }]
- }]
- }],
- "challenge": "3182bdea-63d9-11ea-b6de-3b7c1404d57f",
- "domain": "retailer.example"
+ "ttl": 900,
+ "variables": {
+ "reason": "Please present this product's authenticity credential."
}
}
{% endhighlight %}
- The challenge and domain are what you'll verify in
- the returned proof — they stop a captured presentation from being replayed.
- Use trustedIssuer to require the credential come from the real
- brand.
+ This call is authenticated. On success the service returns
+ 204 No Content with a Location header — your
+ exchange URL:
+
+ {% highlight "http" %}
+HTTP/1.1 204 No Content
+Location: https://workflows.example/workflows/authenticity-check/exchanges/z19xQ...
+ {% endhighlight %}
+
+ The workflow's challenge and domain stop a captured
+ presentation from being replayed; its trustedIssuer setting
+ requires the credential come from the real brand.
- 2. Receive the presentation
+ 2. Host and share the interaction URL
- The wallet POSTs the signed presentation back to the same exchange 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:
{% highlight "json" %}
{
- "verifiablePresentation": {
- "@context": ["https://www.w3.org/ns/credentials/v2"],
- "type": ["VerifiablePresentation"],
- "holder": "did:example:bag-456",
- "verifiableCredential": [{ "...": "the authenticity VC" }],
- "proof": {
- "challenge": "3182bdea-63d9-11ea-b6de-3b7c1404d57f",
- "domain": "retailer.example",
- "...": "holder signature"
+ "VerifiablePresentation": {
+ "interact": {
+ "service": [{
+ "type": "VerifiableCredentialApiExchangeService",
+ "serviceEndpoint": "https://workflows.example/workflows/authenticity-check/exchanges/z19xQ..."
+ }]
}
}
}
{% endhighlight %}
+
+ The product's wallet POSTs to that endpoint and runs the exchange with the
+ workflow service directly. You are not in that loop.
+
- 3. Verify the proof
- Before you trust the product is genuine, check all of the following:
-
- - The presentation proof is valid and the
-
challenge / domain match what you sent.
- - The credential's proof is valid and the issuer is the
- brand you trust.
- - The credential is not revoked (e.g. reported stolen or
- recalled) — check its status.
- - The credential is unexpired and the type matches your
- request.
-
+ 3. Poll for the verified result
+
+ GET the exchange URL (authenticated) until its state is
+ complete:
+
+ {% highlight "bash" %}
+GET https://workflows.example/workflows/authenticity-check/exchanges/z19xQ...
+ {% endhighlight %}
+ {% highlight "json" %}
+{
+ "exchange": {
+ "id": "z19xQ...",
+ "state": "complete",
+ "variables": {
+ "results": {
+ "authenticityCheck": {
+ "did": "did:example:bag-456",
+ "verifiablePresentation": { "...": "verified: the authenticity VC" }
+ }
+ }
+ }
+ }
+}
+ {% endhighlight %}
+
+ A complete state means the workflow service already verified the
+ presentation for you — proof, challenge, domain, trusted issuer, and
+ revocation/expiry status. The verified result lands under
+ exchange.variables.results, keyed by the workflow's step names.
+
That's it
- A conformant provenance verifier is this exchange: request, receive, verify.
- The cryptographic verification is your verifier instance's job — the
- coordinator just runs the exchange.
+ A provenance verifier, as a coordinator, is these three calls: create
+ an exchange, host and share the interaction URL, poll for the verified
+ result. The cryptographic verification and protocol interop are the
+ workflow service's job — you create exchanges and read what comes back.
On the wallet end, a standalone client-side VCALM library is still planned;
- until it ships, the raw HTTP flow is the supported path there. For the
- verifier/coordinator side shown here, use
+ 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