Buyer verification
Verification is the free side of the system: a paying agent or platform checks a seller's attestation with no charge, no registration and no personal data. The check completes locally.
The verification path
- Fetch the verdict for the seller's endpoint identifier over the free
path. The verdict is a small signed document: operator status, guarantee-deposit state, verification date, and the renewal cadence promise.
- Check freshness against the cadence the credential itself promises —
the buyer never needs a clock authority beyond its own.
- Verify the signature locally. The verdict payload verifies with a
published public key (Ed25519) against the canonical byte form of the payload. No call to any ZadQ system is required at decision time.
verdict ──► freshness check ──► local signature check ──► badge state
│ │ │
└── absent ────┴──── stale ──────────┴── invalid ──► "unknown"
Badge states
The badge shows one of three words. The verdict object carries the outcome (human_backed, revoked, stale, no_signal, with reason on any non-positive one); the copy-in badge snippet reduces it to three states.
| Badge | Verdict outcome | Snippet state | Meaning |
|---|---|---|---|
| verified | human_backed | human-backed | Valid, fresh attestation; an accountable, verified operator stands behind the endpoint and the issuer's guarantee deposit is at or above the published minimum |
| not verified | revoked | revoked | The attestation has been withdrawn, or has lapsed past its renewal deadline |
| unknown | stale, no_signal, or no verdict at all | unknown | No usable verdict — stale, withheld, unreachable or unverifiable — the neutral fallback |
Graceful degradation
unknown is a first-class state, not an error. Every integration keeps working when no verdict is available: the badge shows unknown and the payment flow proceeds exactly as it would without the attestation layer. Buyer-side policy — whether to pay unknown sellers — always belongs to the buyer, never to the verification layer.
What verification never requires
- No account, key or credential on the buyer side.
- No fee on the verification path.
- No personal data in either direction.
- No live dependency: a cached verdict inside its freshness window verifies
offline.
Get notified when a verdict changes
Reading the free path on your own schedule is always enough. An explorer, marketplace or buyer platform that prefers to hear about each refresh registers a receiver and gets the verdict.updated event pushed to it.
curl -sS -X POST "https://api.zadq.net/v0/webhooks" \
-H "Content-Type: application/json" \
-d '{"url": "https://receiver.example/verdicts"}'
- Free and unauthenticated. The payload is the public verdict, so the
registration asks for no account, no key and no personal data.
- The secret is shown once. The
201response carries the subscription
id, the url, createdAt and a hex signing secret. Store the secret at once; it is not returned again.
- https only, except loopback receivers for local development.
- Removal:
DELETE /v0/webhooks/{webhookId}ends the subscription.
On each verdict refresh the service POSTs the verdict to every registered receiver: the body is the Verdict object (the same document the free path returns) plus "event": "verdict.updated".
| Header | Value |
|---|---|
X-Signature | sha256=<hex>: HMAC-SHA256 over the raw request body, keyed with the subscription secret |
X-Signature-Key | The key id: the first 8 bytes of the secret's SHA-256, hex |
X-Webhook-Version | The schema version, currently 1 |
Verifying the signature
- Read the raw body bytes before parsing them.
- Decode the hex secret to bytes and compute HMAC-SHA256 over the raw body.
- Compare the result with the hex after
sha256=inX-Signature, in
constant time. Use X-Signature-Key to pick the right secret when you hold more than one.
- Accept the event only when they match; then verify the verdict's own
Ed25519 signature exactly as on the free path. The webhook signature says the event came from your subscription; the verdict signature says what the verdict is.
Owner and explorer receivers
This route is the explorer's: anyone may register, and it carries public verdicts only. A seller registers its own receivers separately, from its account in the dashboard (POST /v0/sellers/{id}/webhooks); the same signing, key id, version header and retries apply, and those receivers also hear the seller's own state, attestation status and guarantee events. The API reference lists both.
Delivery and degradation
Each delivery has a 5-second timeout and up to 3 attempts. A receiver that fails is logged and never delays a verdict. The free path stays the universal fallback: a missed or late event leaves your integration working, because the current verdict is always readable from GET /v0/verifications, and with no verdict at all the badge shows unknown.
Next: the SDK reference lists the vendorable modules implementing this path.