POST /v2/attestations/brand/:shopSlug/request and GET /v2/attestations/brand/:shopSlug/request-status are the merchant-facing CTA + polling endpoints behind the trust-fabric dashboard widget’s Request brand attestation modal. Together they queue an operator-reviewed request and let the storefront flip its UI between the four lifecycle states without leaving the dashboard.
Both endpoints are public — no JWT, no IP-allowlist. The
:shopSlug is the URL-safe brand slug (same value the on-chain BrandAttestation.brandSlug carries — NOT the human-display name).Lifecycle
A request walks four states. The on-chain Schema A mint is gated behind operator review — clicking the CTA does NOT directly mint:
The status endpoint also reports a synthetic
NONE state when no request row exists for the slug (used by the widget to render the initial CTA).
POST — submit a request
(shopSlug, status: PENDING). Re-submitting while a PENDING row exists returns the same requestId instead of creating a duplicate — the widget always renders a success toast and never has to handle a “duplicate” 4xx.
Request
Curl example
Response (200)
decidedBy, decisionReason, merchantId, internal notes) never cross the public surface. status is hard-cast to PENDING on this endpoint: an APPROVED / MINTED / REJECTED row can never be returned by the idempotency check (only PENDING matches the dedupe index).
Error responses
GET — poll the status
NONE → PENDING → APPROVED → MINTED (or → REJECTED) without leaving the merchant dashboard. Resolution rule: any PENDING row wins (there is at most one by index); otherwise the newest terminal row (createdAt desc) is returned.
Curl example
Response (200, history exists)
status === "MINTED" the attestationUid resolves on EAS Base via the standard easscan link scheme — e.g. https://base.easscan.org/attestation/view/0x9c4f7a3e… — so the widget can link the merchant directly to the on-chain record without a second round-trip.
Response (200, no history)
The status endpoint always returns 200 — even when no request exists. The synthetic
NONE discriminator lets the widget render the initial Request brand attestation CTA without 404-handling. Storefronts should treat request === null as the “Not requested” UI state.Field reference
Operator-private fields (
decidedBy, decisionReason, mintError, mintAttempts, merchantId, free-text notes) are SCRUBBED from the public projection — they only surface on the SUPER_ADMIN admin route.
TypeScript flow example
A merchant dashboard widget driving the four-state UI:Related
- Trust Fabric overview — where Schema A brand attestations fit in the 4-axis architecture
- Lender Registry Lookup — the sibling registry pattern this module mirrors
- Methodology Registry Lookup — Schema B verifier flow
- Merchants overview — how the trust-fabric widget surfaces on the merchant dashboard