DEV Community

Forge Alone
Forge Alone

Posted on Edited on Originally published at unlisted.sh AI-assisted

x402 endpoint not showing in the Bazaar? 15 causes and fixes

Originally published at unlisted.sh/guide. I built Unlisted, the paid checker mentioned at the end, but everything here works by hand for free. Updated October 5, 2026: now 15 causes, up from 10, with several confirmed by Coinbase contributors.

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. I hit several of these causes on my own API, so here's every one I know of, each with the symptom and the fix.

Coinbase's own Get discovered (Bazaar) guide is the official checklist. The causes below add what sellers have run into, each linked to where it was reported or confirmed.

How a route gets listed

The Bazaar doesn't crawl the web for x402 endpoints. A route gets listed when a payment to it settles through CDP's facilitator, its 402 challenge carries a valid extensions.bazaar declaration, and the settle request carries both paymentPayload.extensions.bazaar and paymentPayload.resource. CDP then probes the route with the example input from your declaration and expects a 402.

So you need a well-formed challenge on a public https URL, CDP as the facilitator, and at least one settled payment that carries the metadata.

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
Enter fullscreen mode Exit fullscreen mode

If your route is there, it's listed. If not, read on.

Your own server can also read CDP's answer. On verify and settle, CDP's facilitator returns an EXTENSION-RESPONSES header: base64 JSON whose bazaar.status is success (cataloged), processing (accepted, being cataloged) or rejected (with a rejectedReason). No bazaar key means discovery wasn't submitted at all. processing doesn't confirm that indexing will succeed.

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, 4 and 5
Your app runs behind Render, Railway, Fly, Heroku, nginx or a load balancer 6
A plain request to your route, without its parameters, gets a 400, 409 or 422 13
Your decoded challenge has extensions inside an accepts entry 4
Some x402 clients say there are no payment options 8
CDP's facilitator answered rejected 3 (read rejectedReason)
Valid challenge, settled through CDP, status "processing", still not listed 13 and 10, then the open reports near the end
Was listed, now gone 15
Several of your URLs show up as one entry 14
Listed, but agentic.market shows enriched: false Not curated (near the end)
Listed, but with the wrong method or no input schema 9
Listed, but showing an old price or description 12

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. It doesn't have to be a mainnet payment: a Coinbase contributor confirmed in cdp-sdk #835 that a testnet settlement through CDP works too, as long as extensions.bazaar.info.input and paymentPayload.resource are set.

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. A Coinbase contributor confirmed this in cdp-sdk #827. If your server uses another facilitator, CDP never sees those payments. That includes the x402.org facilitator, which keeps its own separate catalog. 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.

Make the example match the schema. Coinbase's docs say rejections are usually strict JSON Schema validation: your declared input must validate against schema.properties.input.

Also check the paying side. The settle request has to carry paymentPayload.extensions.bazaar, so a client that drops the extension when it sends the payment leaves CDP with nothing to index (x402 #3557).

4. extensions sits inside accepts instead of next to it

Symptom: your 402 has a complete Bazaar declaration, but it's inside a payment option, at accepts[0].extensions.bazaar, instead of at the top level of the 402 body. Payments settle and nothing is indexed. It's an easy mistake in hand-rolled 402 responses, and in code ported from x402 v1, where discovery metadata sat inside each payment option as outputSchema.

Fix: move extensions to the top level of the 402 body, next to accepts, and to the same place in the decoded PAYMENT-REQUIRED header. The x402 v2 specification defines extensions on the 402 response itself, and an accepts entry has no such field. Clients copy the top-level extensions into the payment they send, and the x402 SDK drops an extensions key it finds inside an accepts entry, so CDP never gets your declaration. Then make a new settlement.

5. The description is too long

Symptom: everything else is right, but payments fail. Coinbase's docs say CDP's facilitator rejects verify and settle requests whose description is over 500 characters, and sellers have reported the failure being hard to trace (x402 #2993).

Fix: keep the route's description to 500 characters or fewer. One or two sentences is plenty: what the endpoint does and when an agent should call it.

6. 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=*
Enter fullscreen mode Exit fullscreen mode

For other stacks, read X-Forwarded-Proto (Express: app.set("trust proxy", true)), or hardcode your public https base URL.

7. 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.

8. 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 an empty JSON object 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.

9. 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.

10. External $ref/$id in a schema, or paymentPayload.resource not sent

Symptom: payments settle through CDP and CDP's validation says the route would be accepted, but it never appears in the catalog. Sellers in x402 #3045 traced this to two things on their side.

Fix, part one: inline your schemas. If the input schema or output.schema in your Bazaar declaration has a $ref or $id pointing to an external URL, inline the referenced definitions and drop the external $id. A Coinbase contributor confirmed this cause in cdp-sdk #835, where indexing failed with "schema must not contain external $ref/$id references". CDP's /v2/x402/validate can pass a route that still has this problem.

Fix, part two: send paymentPayload.resource when you settle. Coinbase's docs say the settlement that triggers indexing must set both paymentPayload.extensions.bazaar and paymentPayload.resource, and settlement succeeds without them, so nothing warns you. Current SDKs fill it in. Hand-rolled settle code often doesn't. One seller also had to settle with an x402 v2 payload, where resource is an object rather than a URL string.

After either fix, make a new settlement.

11. 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. With the CDP SDK's TypeScript createX402Server, the route key also needs a specific HTTP method: Coinbase's docs say a wildcard method doesn't give the SDK enough to generate discovery metadata.

12. You changed price or metadata and the listing didn't update

Symptom: the route is listed, but with an old price, description or schema (cdp-sdk #813).

Fix: make a new paid call after the change. A Coinbase contributor said in cdp-sdk #835 that indexing can't be retriggered on an existing settlement. Then check the crawl time again before assuming it's stuck. Ranking is separate: Coinbase's docs say it's recomputed every six hours.

13. A bare request or CDP's probe gets a 400 instead of a 402

Symptom: a plain request to your route, without its parameters or body, gets a 400, 409 or 422 instead of a 402. Crawlers, discovery tools and agents checking a route before they pay send exactly that kind of request, so they never see your price.

The same thing can stop indexing. After a settlement, the Bazaar probes your route with the example input from extensions.bazaar.info.input, or an empty body if you didn't declare one. If your input validation runs before the x402 middleware, the probe gets a 400, 409 or 422 instead of a 402, and indexing stops there. A Coinbase contributor traced a stuck route to exactly this in cdp-sdk #830: the probe got a 409.

Fix: let the x402 middleware answer before your input validation runs, so an unpaid request gets a 402 whatever its input. If validation has to come first, at least make sure the example input in your declaration passes it and comes back as a 402. Then make a new settlement.

14. Several URLs collapse into one entry

Symptom: you serve many resources, such as /data/0xabc.../report and /data/0x123.../report, but the Bazaar lists them as a single entry.

Fix: Coinbase's docs say the Bazaar turns any path segment that is entirely a UUID, an EVM address or transaction hash, or a Solana address or transaction hash into a generic route parameter. To keep resources listed separately, add a prefix or suffix so the segment isn't a bare identifier, such as /user-<uuid> instead of /<uuid>.

15. The route dropped out after 30 days without a settlement

Symptom: your route was listed, and now it's gone from the catalog and search results.

Fix: Coinbase's docs say resources that go 30 days without a settlement are removed, and endpoints that stop returning a 402 are eventually removed too. A listed route needs ongoing paid traffic through CDP's facilitator. Keep sending paymentPayload.extensions.bazaar and paymentPayload.resource on every settlement.

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: processing means the metadata was accepted and is being cataloged asynchronously. Routes that do get indexed see it too, so it tells you nothing either way. Two of the reports were answered by a Coinbase contributor and both turned out to be fixable on the seller's side: cdp-sdk #830 (cause 13) and cdp-sdk #835 (cause 10). As of October 4, 2026, x402 #3266 and x402 #3281 are still open with no maintainer answer.

What to try: rule out causes 1 to 15 first, especially 13 and 10. Then make one fresh settlement through CDP after your last change. If it's still missing after a few days, add your route and settlement details to one of the open issues. More reports make it easier for CDP to find the pattern.

Indexed, but not curated (enriched: false)

Symptom: your route is in the CDP Bazaar, but agentic.market's record for your service shows enriched: false, and you're not in the featured slice. This is a different problem from not being indexed (cdp-sdk #838).

What it means: a Coinbase contributor explained in #838 that enriched is only turned on for the hand-picked editorial set of curated endpoints. Meeting the published criteria makes an endpoint eligible to be selected, not entitled to it.

Coinbase's curation requirements are: live x402 payments on mainnet, at least 99% availability over 30 days, passing the platform health probe, agent-ready metadata (a complete input schema, a description that tells an agent when to use the endpoint, per-call pricing, supported networks and documented error responses), and passing validation. The docs don't describe an application process.

Checking it in one call

If you'd rather not decode challenges by hand, Unlisted runs these checks against your endpoint and asks CDP for its live index status, including whether CDP would accept the route if it isn't listed yet. It's pay-per-call over x402 (USDC on Base), with no signup:

  • Check, $0.02: your 402 challenge, the Bazaar declaration, CDP's probe rebuilt from your declaration, and CDP's live index status.
  • Check + real payment, $0.10: all of that, plus one real test payment to your route, which covers cause 1 for you. For routes priced up to $0.05, once per domain per 24 hours. If no test payment can be made, you aren't charged.
POST https://unlisted.sh/diagnose
Content-Type: application/json

{"url": "https://your-api.example.com/paid-route"}
Enter fullscreen mode Exit fullscreen mode

Unlisted can't make CDP index a route, and it won't claim to.

The full guide, kept up to date, is at unlisted.sh/guide. If you've hit a cause that isn't listed here, tell me in the comments and I'll add it.

Unlisted isn't affiliated with Coinbase.

Top comments (2)

Collapse
 
tigeropswin profile image
tigerops-win •

The most useful tip here is the one at the top — checking the public discovery API directly with your payTo address before doing anything else. When I was debugging a missing listing, I spent a while re-reading my 402 challenge before realizing cause #1 was the actual problem: nothing had ever settled through CDP's facilitator, so there was nothing to index. Rule zero for anyone debugging this: query the discovery API first, then work the checklist backwards from the symptom.

Collapse
 
forgealone profile image
Forge Alone •

Thanks, and agreed: that lookup takes ten seconds and it tells you which half of the list you're in. Cause 1 caught me too. My challenge was fine the whole time and I kept re-reading it anyway.

I updated the post today. It's now 15 causes, and two of the "stuck on processing" reports got answers from a Coinbase contributor: one was CDP's probe getting a 409 instead of a 402 (cause 13), the other an external $id in the schema (cause 10). Both were fixable on the seller's side.