Publish the page metadata and agent files the facilitator reads — and your Bazaar listing fills in with your name, logo, description and agent docs automatically.
1 · Listing — your first settled payment catalogs your endpoint in the
Bazaar (that needs the bazaar extension, see the
Get started guide). 2 · Enrichment — everything on this page. The
facilitator visits your domain and reads your page metadata plus a short list of
well-known agent files, then shows your name, logo, description and agent docs on your
merchant and resource pages.
The facilitator derives your site from the domain of your most recently
active paid endpoint — or, if you declared a website in the
x402-merchant extension, from that. Files are read from the root of that
origin, never from a sub-path.
Paid endpoint: https://api.example.com/v1/analyze
↓ same origin
Metadata read: https://api.example.com/ ← <head> tags
https://api.example.com/.well-known/x402
https://api.example.com/.well-known/agent-card.json
https://api.example.com/llms.txtapi.example.com but your
branding lives on example.com, either publish the files on the API domain too, or
declare website: "https://example.com" in your x402-merchant extension
so enrichment follows it.If your receiving (payTo) address holds an
NFDomains name,
your merchant page uses it first — ahead of your x402-merchant declaration
and your site metadata. Fill in your NFD profile and you're branded across the
facilitator without touching your server at all.
Verified properties win over user-defined ones, so verify what you can.
The lookup is by the exact receiving address you advertise in payTo — an NFD on a
different wallet won't be found.
Name NFD name → x402-merchant name → og:title → <title> Logo NFD avatar → x402-merchant logo → apple-touch-icon → icon → /favicon.ico Description og:description → <meta name="description"> Links NFD website + socials (twitter, github, telegram, discord, email) Agent docs the well-known files below
So: NFD for identity, your 402 for categories, your site for the description and banner, well-known files for what agents read next. Any layer you skip simply falls through to the next.
The root page is fetched once and parsed for these tags — first match wins:
<!-- Serve this on the ROOT page of the domain that hosts your paid endpoints --> <head> <title>EXAMPLE API — premium endpoints, paid per request</title> <meta name="description" content="Premium API endpoints, paid per request in USDC on Algorand. No accounts, no API keys, no subscriptions." /> <!-- OpenGraph: what the Bazaar and social cards read first --> <meta property="og:site_name" content="EXAMPLE API" /> <meta property="og:title" content="EXAMPLE API — premium endpoints, paid per request" /> <meta property="og:description" content="Premium API endpoints, paid per request in USDC on Algorand. No accounts, no API keys, no subscriptions." /> <meta property="og:image" content="https://your-domain.com/og.png" /> <meta property="og:url" content="https://your-domain.com" /> <meta name="twitter:card" content="summary_large_image" /> <!-- Your logo: apple-touch-icon wins (square, largest), then any icon --> <link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png" /> <link rel="icon" type="image/png" sizes="32x32" href="/favicon-32.png" /> <meta name="theme-color" content="#2EE6C5" /> </head>
Relative paths are fine — they're resolved against your origin. The page must
answer 200 as text/html; only the first 128 KB is parsed and the
fetch times out after 4 seconds, so keep your <head> near the top.
Each of these is probed at your origin. Every one that exists is listed on your merchant and resource pages as a link agents can follow — publish the ones that fit you, skip the rest.
https://your-domain.com/.well-known/x402 → x402 Discovery https://your-domain.com/.well-known/agent-card.json → A2A Agent Card https://your-domain.com/.well-known/agent.json → Agent Manifest https://your-domain.com/.well-known/ai-plugin.json → AI Plugin https://your-domain.com/.well-known/mcp.json → MCP Manifest https://your-domain.com/llms.txt → llms.txt
From JSON files the facilitator takes name (or
name_for_human, or title) and description (or
description_for_human). From llms.txt it takes the first markdown
# heading as the name. Everything else in your files is yours — agents read them
in full.
/.well-known/x402A static index of your paid endpoints, for agents that want to know your prices before making a request.
// https://your-domain.com/.well-known/x402
{
"x402Version": 2,
"name": "EXAMPLE API",
"description": "Premium API endpoints, paid per request in USDC on Algorand.",
"resources": [
{
"url": "https://your-domain.com/api/analyze",
"method": "POST",
"description": "Analyze text — 0.01 USDC per call",
"network": "algorand:wGHE2Pwdvd7S12BL5FaOP20EGYesN73ktiC1qzkkit8=",
"asset": "31566704",
"amount": "10000",
"payTo": "YOUR_ALGORAND_MERCHANT_ADDRESS"
}
]
}/.well-known/agent-card.json// https://your-domain.com/.well-known/agent-card.json (A2A)
{
"name": "EXAMPLE API",
"description": "Premium API endpoints, paid per request in USDC on Algorand.",
"url": "https://your-domain.com",
"version": "1.0.0",
"capabilities": { "streaming": false },
"defaultInputModes": ["text"],
"defaultOutputModes": ["text"],
"skills": [
{
"id": "analyze",
"name": "Analyze text",
"description": "Returns a short summary. Paid per call via x402 (0.01 USDC).",
"tags": ["x402", "algorand", "nlp"]
}
]
}/.well-known/ai-plugin.json// https://your-domain.com/.well-known/ai-plugin.json
{
"schema_version": "v1",
"name_for_human": "EXAMPLE API",
"name_for_model": "my-api-co",
"description_for_human": "Premium API endpoints, paid per request in USDC on Algorand.",
"description_for_model": "Call EXAMPLE API tools; each request is paid with x402 (HTTP 402).",
"api": { "type": "openapi", "url": "https://your-domain.com/openapi.json" },
"logo_url": "https://your-domain.com/logo.png",
"contact_email": "hello@your-domain.com"
}/.well-known/mcp.json// https://your-domain.com/.well-known/mcp.json
{
"name": "EXAMPLE API MCP",
"description": "MCP server exposing EXAMPLE API's x402-paid tools.",
"version": "1.0.0",
"transport": { "type": "sse", "url": "https://your-domain.com/sse" },
"tools": [
{ "name": "analyze", "description": "Analyze text — paid per call in USDC (x402)." }
]
}/.well-known/agent.json// https://your-domain.com/.well-known/agent.json (generic manifest)
{
"name": "EXAMPLE API",
"description": "Premium API endpoints, paid per request in USDC on Algorand.",
"url": "https://your-domain.com",
"documentation": "https://your-domain.com/llms.txt",
"payments": { "protocol": "x402", "network": "algorand", "asset": "USDC" }
}Plain markdown for LLMs: what you do, what you charge, how to pay. The first
# line is your name.
# EXAMPLE API > Premium API endpoints, paid per request in USDC on Algorand. Every endpoint answers HTTP 402 > with x402 payment requirements; pay in USDC and the response is yours. > No accounts, no API keys, no subscriptions. ## Paid endpoints - [Analyze](https://your-domain.com/api/analyze): POST a document, get the analysis. 0.01 USDC. - [Report](https://your-domain.com/api/report): GET a generated report. 0.01 USDC. ## Paying - Protocol: x402 (v2), settled by https://facilitator.goplausible.xyz - Network: Algorand MainNet · Asset: USDC (31566704) - Clients: any x402 client — see https://facilitator.goplausible.xyz/guide/use ## Docs - [OpenAPI](https://your-domain.com/openapi.json)
Operating instructions for agents already using you: how to pay, what each
endpoint takes, what to assume. The facilitator doesn't index this one — publish it because
coding agents and crawlers read it straight from your domain, the same way they read
llms.txt.
# EXAMPLE API
Instructions for agents working with this service.
## Payment
Every endpoint under /api is x402-paid. On HTTP 402, read the PAYMENT-REQUIRED
header (base64 JSON), pay the advertised requirement in USDC on Algorand, then
retry the same request with the PAYMENT-SIGNATURE header.
## Endpoints
- POST /api/analyze — { "text": string } → { "result": object } — 0.01 USDC
- GET /api/report?id=... → { "report": object } — 0.01 USDC
## Notes
- Prices are advertised in the 402; never assume them.
- Settlement is handled by facilitator.goplausible.xyz — you never pay gas.index.html for
missing paths counts as "file absent". The facilitator treats an HTML body on a
.well-known or .txt path as a miss — otherwise every SPA on the
internet would look like it publishes every file. Serve the real bytes, and register these
routes before your fallback.// Express — serve the well-known files BEFORE any SPA fallback
import express from "express";
const app = express();
// 1) static well-known + agent docs (real files, real content types)
app.use("/.well-known", express.static("public/.well-known", {
setHeaders: (res) => res.setHeader("Content-Type", "application/json"),
}));
app.get("/llms.txt", (_q, r) => r.type("text/plain").sendFile("llms.txt", { root: "public" }));
app.get("/agents.md", (_q, r) => r.type("text/markdown").sendFile("agents.md", { root: "public" }));
// 2) ...your paid routes and paymentMiddleware...
// 3) SPA fallback LAST — otherwise it swallows the paths above
// app.get("*", (_q, r) => r.sendFile("index.html", { root: "public" }));# Serve the files as-is — never let an SPA catch-all answer these paths.
location = /.well-known/x402 { default_type application/json; alias /srv/site/x402.json; }
location = /.well-known/agent-card.json { default_type application/json; alias /srv/site/agent-card.json; }
location = /llms.txt { default_type text/plain; alias /srv/site/llms.txt; }
location = /agents.md { default_type text/markdown; alias /srv/site/agents.md; }Results are cached for 24 hours. To see changes immediately, open your merchant page and hit ⟳ Refresh metadata — it re-reads your site and re-probes every file. 🩺 x402 Doctor on the same page grades your 402s and explains any missing BAZAAR or HACKATHON badge.
Something not showing up, or a file format you'd like the facilitator to read? Drop it in the GoPlausible OpenBox — every submission is read.