x402 endpoint not showing in the Bazaar? 10 causes and fixes
Your x402 endpoint returns a 402, takes payment, and works. But it isn't in the CDP Bazaar, so agents searching the catalog never find it. Below is every cause we know of, with the symptom and the fix for each. You can work through it by hand for free.
extensions.bazaar declaration. After that, CDP re-crawls it from time to time. So you need three things: a well-formed challenge, CDP as the facilitator, and at least one settled payment.- No payment has settled through CDP yet
- Payments settle through a different facilitator
- extensions.bazaar is missing or malformed
- The description is too long
- resource.url says http:// behind a proxy
- The resource field is missing
- The 402 body is empty or accepts is malformed
- A POST route is described as GET
- The route uses a bare wildcard
- You changed price or metadata and the listing didn't update
None of them fit? See accepted as “processing”, never indexed.
Quick triage
| What you see | Most likely cause |
|---|---|
| Nobody has paid the route yet | 1 |
| Real payments have landed, still not listed | 2, then 3 and 4 |
| Your app runs behind Render, Railway, Fly, Heroku, nginx or a load balancer | 5 |
| Some x402 clients say there are no payment options | 7 |
| Valid challenge, settled through CDP, status “processing”, still not listed | Known open problem |
| Listed, but with the wrong method or no input schema | 8 |
| Listed, but showing an old price or description | 10 |
Free first step: ask the Bazaar directly
CDP's discovery API is public. Open this in your browser with your receiving wallet address:
https://api.cdp.coinbase.com/platform/v2/x402/discovery/merchant?payTo=0xYOUR_PAY_TO_ADDRESS
If your route shows up there, it's listed. If the list is empty or your route is missing, read on.
1. No payment has settled through CDP yet
Symptom
Your challenge looks right, but the route has never been paid. This is the most common cause for a brand-new endpoint.
Fix
Make one real, paid call to the route that settles through CDP's facilitator. A cent is enough. Then give the Bazaar time to crawl it.
?mode=paid) makes that payment for you, on Base mainnet in USDC, for routes priced up to $0.05. Its result is in settlement_echo. The report's bazaar_index_status check covers this.2. Payments settle through a different facilitator
Symptom
You've had real, settled payments, but the route still isn't listed.
Fix
The CDP Bazaar only learns about routes from settlements that go through CDP's facilitator. If your server is set up with another facilitator, CDP never sees those payments. Point the route at CDP's facilitator (it needs a CDP API key), then make one more paid call.
3. extensions.bazaar is missing or malformed
Symptom
Payments settle, but there's nothing for the Bazaar to index. Decode your 402 challenge, and either extensions.bazaar isn't there or it's incomplete.
Fix
Declare discovery metadata on the route. In the Python SDK that's declare_discovery_extension(...) passed as the route's extensions, plus registering bazaar_resource_server_extension on the resource server. At minimum, extensions.bazaar.info.input.type must be "http" or "mcp". If you include info.output, it needs a type too.
Also check the paying side. A client that drops the extension when it sends the payment leaves CDP with nothing to index (see x402 #3557).
bazaar_extension check covers this.4. The description is too long
Symptom
Everything else is right, payments may even fail, and nothing tells you why. A long route description can break things without any error (see x402 #2993).
Fix
Keep the route's description under about 500 characters. One or two sentences is plenty: what it returns and what it costs.
description_length check covers this.5. resource.url says http:// behind a proxy
Symptom
Your public URL is https://, but the decoded challenge advertises http://. Your host terminates TLS and forwards plain HTTP to your app, so the app builds the URL from what it sees. CDP's validation only accepts https:// resource URLs.
Fix
Tell your server to trust the forwarded scheme. For uvicorn:
uvicorn main:app --proxy-headers --forwarded-allow-ips='*'
# or set the env var
FORWARDED_ALLOW_IPS=*
For other stacks, read X-Forwarded-Proto (Express: app.set("trust proxy", true)), or hardcode your public https base URL.
scheme_mismatch check covers this.6. The resource field is missing
Symptom
The challenge has payment options but no resource, so the Bazaar doesn't know which URL it's cataloging.
Fix
Include resource.url: the full public https URL of the paid route. Current x402 SDKs fill it in for you. Hand-rolled 402 responses often leave it out.
resource_present check covers this.7. The 402 body is empty or accepts is malformed
Symptom
x402 v2 puts the challenge in a base64 PAYMENT-REQUIRED header, and some servers send {} as the body. Clients and crawlers that read the body find no payment options.
Fix
Keep the header, and also return the same decoded JSON as the 402 body. Make sure accepts is a non-empty array of objects, each with scheme, network, asset, amount and payTo.
parse_error.8. A POST route is described as GET
Symptom
Your route takes a JSON body, but the listing (or the validation) treats it as GET, so it sends no body and gets an error instead of a 402.
Fix
Declare the body in the discovery metadata. In the Python SDK, pass body_type="json" plus an example input and input_schema to declare_discovery_extension. Make sure the route key says POST too.
"method": "POST" and a sample "body". Unlisted probes, pays and asks CDP using the route's real method.9. The route uses a bare wildcard
Symptom
The route is declared as /prices/*, so the listing can't tell agents what goes in the path.
Fix
Use a named parameter in the paywall's route pattern, such as GET /prices/:symbol, so the discovery metadata names the path parameter.
routeTemplate, the Check flags a bare * segment. The report's route_template check covers this.10. You changed price or metadata and the listing didn't update
Symptom
The route is listed, but with an old price, description or schema (see cdp-sdk #813).
Fix
The Bazaar refreshes a route when it re-crawls it, so a change can take a while to show up. Make a new paid call after the change, then check the crawl time again before assuming it's stuck.
bazaar_index_status result includes when CDP last crawled it, plus 30-day calls and unique payers.If none of these fit: accepted as “processing”, never indexed
Symptom
Your challenge is valid, a payment settled through CDP's facilitator, and the facilitator answered with bazaar.status: "processing". CDP's own validation says the route would be accepted. Days later it still isn't in the catalog.
What's known
Several sellers have reported this, and as of October 1, 2026 none of the reports has an answer from a maintainer: x402 #3266, x402 #3281, cdp-sdk #830 and cdp-sdk #835. It looks like a problem on CDP's side, and there is no confirmed fix. “Processing” is also returned for routes that do get indexed, so that status alone tells you nothing either way.
What to try
Rule out causes 1 to 10 first, since several of them produce the same symptom. Then make one fresh settlement through CDP after your last change, because a settlement made while something was still wrong may not be picked up again. If it's still missing after a few days, add your route and settlement details to one of the open issues above. More reports make it easier for CDP to find the pattern.
bazaar_index_status check tells you whether you're in this state: not indexed, but CDP would accept the route. Paid mode can make a fresh settlement for you. Unlisted can't make CDP index a route, and it won't claim to.Check all of it in one call
Unlisted runs every check above against your endpoint and asks CDP for its live index status. No signup and no API key: you pay per call in USDC on Base through x402, and you're only charged if the check completes.
POST https://unlisted.sh/diagnose
Content-Type: application/json
{"url": "https://your-api.example.com/paid-route"}
| Mode | Price | What it does |
|---|---|---|
| Check | $0.02 | Your 402 challenge, the Bazaar declaration, and CDP's live index status |
Check + real payment (?mode=paid) | $0.10 | All of the above, plus one real test payment to your route. Once per domain per 24 hours. |
Replace the sample URL with your own endpoint. The report opens with bazaar.indexed (true, false, or null if CDP couldn't be reached), then one result per check with a fix for each failure.