Bazaar — Service-Discovery
Was ist Bazaar?
Bazaar ist die Discovery-Schicht für x402. Sie beantwortet die Frage: „Was kann ich hier kaufen, und was kostet es?“ Agenten durchstöbern einen strukturierten Katalog aus Services, Preisen und Input/Output-Schemas unter /.well-known/x402.json.
So funktioniert es
Veröffentliche /.well-known/x402.json:
{
"x402Version": 2,
"name": "Your Service",
"description": "What your service does",
"network": "base",
"facilitator": "coinbase",
"payTo": "0xYourWallet",
"services": [
{
"method": "POST",
"path": "/api/generate",
"description": "Generate content",
"amount": "100000",
"discoverable": true,
"outputSchema": {
"input": {
"type": "http",
"method": "POST",
"bodyFields": {
"prompt": { "type": "string", "required": true }
}
},
"output": {
"type": "json",
"schema": { "result": { "type": "string" } }
}
}
}
]
}
Pflichtfelder
- x402Version — Spezifikationsversion (nutze
2; der Scanner akzeptiert auch1— siehe unten) - name — Anbietername
- network — Blockchain (z. B.
base, oder unter v2 die CAIP-Formeip155:8453) - facilitator — Settlement-Anbieter (z. B.
coinbase) - payTo — Wallet-Adresse, die Zahlungen empfängt
- services[] — Array kostenpflichtiger Endpoints mit
methodundpath
v1 vs. v2
x402 v2 erschien im Dezember 2025 und ist die aktuelle Spezifikation, aber v1-Server sind in freier Wildbahn noch verbreitet. AgentGrade akzeptiert beide. Alle Unterschiede auf Protokollebene:
- Header-Namen: v1 nutzte Header mit
X--Präfix (X-PAYMENTbeim erneuten Request,X-PAYMENT-RESPONSEbei Erfolg). v2 lässt dasX--Präfix weg (PAYMENT-SIGNATURE,PAYMENT-RESPONSE) — dieX--Konvention wurde bereits 2012 durch RFC 6648 für veraltet erklärt. - Wo die Challenge liegt: v1 legte die Payment-Challenge in den JSON-Body der 402-Antwort. v2 verschiebt sie in den
PAYMENT-REQUIRED-Response-Header (base64-codiertes JSON) und macht den Body frei für eine menschenlesbare Paywall-Seite. - Umbenennung des
amount-Felds: v1saccepts[]-Einträge nutztenmaxAmountRequiredfür den Preis. v2 benennt das Feld inamountum. - Form von
resource: v1 legteresource(als String-URL),descriptionundmimeTypein jedenaccepts[]-Eintrag. v2 hebt diese in ein Top-Level-resource-Objekt mit den Feldernurl,descriptionundmimeType— einmal für die gesamte 402-Antwort deklariert statt pro accepts-Eintrag dupliziert. - Chain-Identifikation: v1 nutzte Freitext-Strings wie
"base"für dasnetwork-Feld. v2 standardisiert auf CAIP-IDs wieeip155:8453, sodass dasselbe Feld auch für Nicht-EVM-Chains und Off-Chain-Schienen funktioniert. - Dynamisches
payTo: v1 deklarierte einen statischen Empfänger pro Service im Discovery-Katalog. v2 lässt den ServerpayTopro Request berechnen — nützlich für Marktplätze, die Zahlungen an einzelne Verkäufer weiterleiten. - Sessions: v1 verlangte den vollen Zahlungsablauf bei jedem Aufruf. v2 ergänzt wallet-gesteuerte Sessions (Sign In With X402) — einmal signieren, der Server stellt eine Session aus, nachfolgende Aufrufe überspringen den Handshake.
Wenn du neu baust, baue v2. Wenn du einen bestehenden v1-Server auditierst: Der Scanner bestraft dich nicht dafür, auf v1 zu sein — aber die v2-Unterschiede oben sind echte Effizienzgewinne.
Wie du einen 402 zurückgibst
Der Discovery-Katalog oben deklariert, was du verkaufst. Die 402-Antwort ist das, was die Zahlung tatsächlich auslöst, wenn ein Agent einen kostenpflichtigen Endpoint ohne Zahlung aufruft.
v2-Form (aktuelle Spezifikation)
Die Payment-Challenge steht im PAYMENT-REQUIRED-Response-Header als base64-codiertes JSON-Objekt. Den Response-Body kannst du beliebig nutzen — typischerweise für eine menschenlesbare Paywall-Seite. Der erneute Request kommt mit der signierten Zahlung im PAYMENT-SIGNATURE-Request-Header an (ebenfalls base64-codiertes JSON). Bei Erfolg kann der Server einen PAYMENT-RESPONSE-Header mit Settlement-Details setzen.
app.post('/api/generate', async (req, res) => {
if (!req.get('PAYMENT-SIGNATURE')) {
const challenge = {
x402Version: 2,
resource: {
url: 'https://yourdomain.com/api/generate',
description: 'Generate content from a prompt',
mimeType: 'application/json'
},
accepts: [{
scheme: 'exact',
network: 'base', // or CAIP form: 'eip155:8453'
amount: '100000', // smallest units; 6-decimal USDC → $0.10
asset: '0x833589fCD6EDb6E08f4c7C32D4f71b54bdA02913',
payTo: '0xYourWalletAddress',
maxTimeoutSeconds: 60
}],
extensions: { bazaar: { discoverable: true } }
};
res.status(402);
res.set('PAYMENT-REQUIRED', Buffer.from(JSON.stringify(challenge)).toString('base64'));
return res.send('<h1>$0.10 to generate content</h1>');
}
// Verify the signature with your facilitator, then run the work.
// The @coinbase/x402 SDK handles the verification call for you.
res.json({ result: '...' });
});
v1-Form (Legacy, body-basiert)
v1-Server legten die Challenge in den JSON-Body der 402-Antwort. Der erneute Request nutzte den X-PAYMENT-Header, und ein erfolgreiches Settlement kam in X-PAYMENT-RESPONSE zurück. v1 nutzt außerdem maxAmountRequired statt v2s amount.
app.post('/api/generate', async (req, res) => {
if (!req.get('X-PAYMENT')) {
return res.status(402).json({
x402Version: 1,
error: 'Payment required to access this resource',
accepts: [{
scheme: 'exact',
network: 'base',
maxAmountRequired: '100000',
asset: '0x833589fCD6EDb6E08f4c7C32D4f71b54bdA02913',
payTo: '0xYourWalletAddress',
resource: 'https://yourdomain.com/api/generate',
maxTimeoutSeconds: 60
}]
});
}
// ...verify the X-PAYMENT signature, then serve the work
});
Achtung — AgentGrades Live-402-Check ist v2-only. Unser Scanner liest den PAYMENT-REQUIRED-Response-Header, um eine funktionierende Paywall zu bestätigen. Ein v1-Server, der seine Challenge in den Body legt, besteht den Discovery-Katalog-Check (/.well-known/x402.json), punktet aber nicht beim Live-402-Check. Wenn dir das wichtig ist, baue v2.
Nutze das SDK
Signaturverifikation willst du mit ziemlicher Sicherheit nicht selbst bauen — nutze stattdessen die @coinbase/x402-Middleware. Sie kapselt beide Antwortformen und den Facilitator-Roundtrip in einer Zeile Express-/Fastify-/Hono-Setup.
extensions.bazaar im Live-402-Header
Wenn ein Agent einen kostenpflichtigen Endpoint ohne Zahlung aufruft, gibt dein Server HTTP 402 mit einem base64-codierten Payment-Required-Header zurück. Die JSON-Payload dieses Headers sollte extensions.bazaar deklarieren, damit Agenten wissen, dass dieser Endpoint Teil eines auffindbaren Katalogs ist. Die JSON-Payload vor der base64-Codierung (v2-Form):
{
"x402Version": 2,
"accepts": [
{
"scheme": "exact",
"network": "base",
"amount": "100000",
"asset": "0xUSDC...",
"payTo": "0xYourWallet",
"maxTimeoutSeconds": 60
}
],
"extensions": {
"bazaar": { "discoverable": true }
}
}
Ohne extensions.bazaar haben Agenten, die auf einen 402 treffen, kein Signal, dass der Endpoint auch unter /.well-known/x402.json katalogisiert ist — sie behandeln ihn womöglich als einzelnen kostenpflichtigen Endpoint statt als Teil eines durchsuchbaren Service.
Reifegrad der Spezifikation
Teil von x402 v2. Bazaar-Discovery ist innerhalb der x402-Spezifikation definiert.
Mehr erfahren
- x402.org — x402-Protokollspezifikation (inklusive Bazaar)