GuidesProvenance verification

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 a 400, 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.status is active, inactive, or unknown. Only a verified domain of an active partner yields active. An unknown or unverified domain returns the same shape with status: "unknown", an empty name, and canonicalUrl: null — it reveals nothing about the registry.
  • lot.status is confirmed, no_match, or unavailable, and never exceeds the partner result: without an active partner match, a lot query is unavailable, not a decided no_match.
  • expiresAt is roughly five minutes out. Do not cache a positive beyond it.
  • A 503 means 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.