Verify a partner and lot from a storefront
The provenance seal lets a shopper confirm that a store is a currently-authorized partner of a supplier — and, optionally, that a specific lot was really supplied to that partner with approved documentation. The trust lives in the data, not the badge image: a copied badge on some other domain resolves to nothing. This guide shows how to read the verification, embed the seal, and (as a merchant) claim your own domain.
The verification endpoint is public, unauthenticated, and CORS-open on purpose.
The response carries no credentials, and its trust binding is in the payload —
partner.domain must equal the embedding page’s hostname, so a response served
to any other site is refused by the widget.
Read the public verification
The single read that backs the seal:
GET https://api.ruo.pro/provenance/v1/{supplier}/partner-verification?domain={hostname}[&lot={lot-id}]{supplier}— the supplier’s registry (a tenant ref).domain— the hostname being checked (required). It is normalized the way registry rows are stored; an invalid hostname is a400, never a registry miss.lot— an optional lot id to confirm against the partner’s supply records.
curl "https://api.ruo.pro/provenance/v1/acme-labs/partner-verification?domain=shop.example.com&lot=LOT-2291"A verified partner with a confirmed lot returns:
{
"partner": {
"status": "active",
"name": "Example Retail Co.",
"domain": "shop.example.com",
"scope": "Finished-goods reseller, North America"
},
"expiresAt": "2026-09-14T18:35:00.000Z",
"canonicalUrl": "https://api.ruo.pro/provenance/v1/acme-labs/verify/example-retail",
"lot": {
"status": "confirmed",
"id": "LOT-2291",
"material": "Reference compound A",
"suppliedTo": "Example Retail Co.",
"documentationUrl": "https://.../coa/LOT-2291.pdf"
}
}Read the fields fail-closed:
partner.statusisactive,inactive, orunknown. Only a verified domain of an active partner yieldsactive. An unknown or unverified domain returns the same shape withstatus: "unknown", an emptyname, andcanonicalUrl: null— it reveals nothing about the registry.lot.statusisconfirmed,no_match, orunavailable, and never exceeds the partner result: without an active partner match, a lot query isunavailable, not a decidedno_match.expiresAtis roughly five minutes out. Do not cache a positive beyond it.- A
503means the read failed — treat it as an error, never as a decided negative.
Surface the verified state
Embed the seal script
The simplest path. The widget derives its API and canonical origin from its own
src, calls partner-verification with the page’s own hostname, validates the
response hard (domain echo, status enums, a future expiresAt, and
suppliedTo === partner.name on confirmed lots), and only renders the verified
state when all of it holds.
<script src="https://api.ruo.pro/provenance/v1/acme-labs/widget.js" defer></script>Or build a “verify this site” checker
From the other direction — on your own site, or anywhere trust matters — take a
user-entered URL, send new URL(input).hostname as domain=, render
partner.status, and link canonicalUrl. No key is needed; do not cache
positives beyond expiresAt.
The badge itself is inert. The independent artifact a copied badge cannot fake is the canonical record, a plain HTML page with the partner’s current status, scope, and verified domains:
GET https://api.ruo.pro/provenance/v1/{supplier}/verify/{partnerRef}Claim your own domain (merchant)
If you are the retailer, add your storefront hostname to your partnership so the
seal resolves on it. These routes use your fdk_ credential (scope
write:own_store) under /provenance/v1/my.
# See your partnerships, domains, supply records, and the embed snippet
curl https://api.ruo.pro/provenance/v1/my/partnerships \
-H "Authorization: Bearer fdk_your_key_here"
# Claim a hostname
curl -X POST https://api.ruo.pro/provenance/v1/my/partnerships/acme-labs/domains \
-H "Authorization: Bearer fdk_your_key_here" \
-H "content-type: application/json" \
-d '{ "hostname": "shop.example.com" }'A hostname that is already a verified storefront domain of your store verifies
instantly. Anything else gets a TXT challenge to publish at
_provenance-challenge.<hostname>; the claim response returns the record name
and value. Run the check once the record is live:
curl -X POST https://api.ruo.pro/provenance/v1/my/partnerships/acme-labs/domains/shop.example.com/verify \
-H "Authorization: Bearer fdk_your_key_here"A verified domain is never verified-forever. A background sweep re-checks verified domains every few hours: a DCV domain must still publish its token, and a platform domain must still be a verified storefront domain of your store. Three sustained misses lapse the row and the seal stops resolving positive for that host.
What is automatic vs. what you configure
- Automatic: continuous re-verification, fail-closed responses, and the widget’s own hard validation of every field.
- You configure (merchant): claiming and verifying your storefront domains.
- Operator-side: creating partners, supply records, and lot documentation in the registry.
Related
- Provenance and the verification seal — the trust model, the field contract, and the discrepancy-report flow.