Settled x402 payments but not listed in the Bazaar? Your client is not echoing extensions
The symptom
Everything looked right: 13 tools returning spec-perfect 402 responses with a valid extensions.bazaar block (verified against the JSON Schema), 14 payments settled on Base mainnet through the CDP facilitator, on-chain transactions confirmed. Yet 14+ hours later:
GET https://api.cdp.coinbase.com/platform/v2/x402/discovery/merchant?payTo=0x4395...
{"pagination": {"total": 0}, "resources": []}
The investigation
The CDP "Get discovered" docs contain two crucial details that are easy to miss:
- The x402 spec says clients must echo the server's
extensionsin thePaymentPayload: "Servers advertise supported extensions in PaymentRequired, and clients echo them in PaymentPayload." This echo is how your discovery metadata physically reaches the facilitator — it rides inside the payment, through/verifyand/settle. - The facilitator answers
/verifyand/settlewith anEXTENSION-RESPONSESheader (base64 JSON) carrying the bazaar cataloging status:success,processing, orrejectedwith a reason.
Our test buyer built its payment payload with resource, accepted and the signature — but no extensions. So every payment settled perfectly, and the facilitator never received a byte of listing metadata. And because we never read EXTENSION-RESPONSES, the absence was invisible.
The fix (one line in the client, one habit in the server)
// buyer: echo the 402's extensions verbatim
const paymentPayload = {
x402Version: 2,
resource: required.resource,
accepted: req,
payload: { signature, authorization },
...(required.extensions ? { extensions: required.extensions } : {}),
};
// seller: decode the facilitator's verdict on every settle — never fly blind again
$header = $response->header('EXTENSION-RESPONSES');
$status = $header ? json_decode(base64_decode($header), true) : null;
// {"bazaar": {"status": "processing"}} → accepted, cataloging asynchronously
// {"bazaar": {"status": "rejected", "rejectedReason": "..."}} → fix and repay
Minutes after re-sending one payment per tool with the echo in place, every settle returned {"bazaar": {"status": "processing"}} — and the merchant discovery endpoint went from total: 0 to total: 13 within the next indexing cycle.
Takeaways
- Settlement success ≠ discovery success. They travel together but are validated separately.
- If you build your own x402 client, echo
extensions— official SDKs do it for you; hand-rolled buyers forget it. - Log
EXTENSION-RESPONSESon every settle. It is the only place the facilitator tells you why your listing is (not) happening. - Expect up to ~6 hours for ranking/search updates — the Bazaar recalculates on a cycle, so verify with the merchant endpoint, not search.