<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Forge Alone</title>
    <description>The latest articles on DEV Community by Forge Alone (@forgealone).</description>
    <link>https://dev.to/forgealone</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4156008%2F2b0bb48b-8fc9-4f15-b1f6-097e72215805.png</url>
      <title>DEV Community: Forge Alone</title>
      <link>https://dev.to/forgealone</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/forgealone"/>
    <language>en</language>
    <item>
      <title>x402 endpoint not showing in the Bazaar? 10 causes and fixes</title>
      <dc:creator>Forge Alone</dc:creator>
      <pubDate>Fri, 02 Oct 2026 00:34:25 +0000</pubDate>
      <link>https://dev.to/forgealone/x402-endpoint-not-showing-in-the-bazaar-10-causes-and-fixes-15h9</link>
      <guid>https://dev.to/forgealone/x402-endpoint-not-showing-in-the-bazaar-10-causes-and-fixes-15h9</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://unlisted.sh/guide" rel="noopener noreferrer"&gt;unlisted.sh/guide&lt;/a&gt;. I built &lt;a href="https://unlisted.sh" rel="noopener noreferrer"&gt;Unlisted&lt;/a&gt;, the paid checker mentioned at the end, but everything here works by hand for free.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;h2&gt;
  
  
  How a route gets listed
&lt;/h2&gt;

&lt;p&gt;The Bazaar doesn't crawl the web for x402 endpoints. A route gets listed when a payment to it &lt;strong&gt;settles through CDP's facilitator&lt;/strong&gt; and the 402 challenge carries a valid &lt;code&gt;extensions.bazaar&lt;/code&gt; 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.&lt;/p&gt;

&lt;h2&gt;
  
  
  Free first step: ask the Bazaar directly
&lt;/h2&gt;

&lt;p&gt;CDP's discovery API is public. Open this in your browser with your receiving wallet address:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://api.cdp.coinbase.com/platform/v2/x402/discovery/merchant?payTo=0xYOUR_PAY_TO_ADDRESS
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If your route is there, it's listed. If not, read on.&lt;/p&gt;

&lt;h2&gt;
  
  
  Quick triage
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;What you see&lt;/th&gt;
&lt;th&gt;Most likely cause&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Nobody has paid the route yet&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Real payments have landed, still not listed&lt;/td&gt;
&lt;td&gt;2, then 3 and 4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Your app runs behind Render, Railway, Fly, Heroku, nginx or a load balancer&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Some x402 clients say there are no payment options&lt;/td&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Listed, but with the wrong method or no input schema&lt;/td&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Listed, but showing an old price or description&lt;/td&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  1. No payment has settled through CDP yet
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Symptom:&lt;/strong&gt; your challenge looks right, but the route has never been paid. This is the most common cause for a brand-new endpoint.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; 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.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Payments settle through a different facilitator
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Symptom:&lt;/strong&gt; you've had real, settled payments, but the route still isn't listed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; the CDP Bazaar only learns about routes from settlements that go through CDP's facilitator. If your server uses 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.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. &lt;code&gt;extensions.bazaar&lt;/code&gt; is missing or malformed
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Symptom:&lt;/strong&gt; payments settle, but there's nothing for the Bazaar to index. Decode your 402 challenge, and either &lt;code&gt;extensions.bazaar&lt;/code&gt; isn't there or it's incomplete.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; declare discovery metadata on the route. In the Python SDK that's &lt;code&gt;declare_discovery_extension(...)&lt;/code&gt; passed as the route's &lt;code&gt;extensions&lt;/code&gt;, plus registering &lt;code&gt;bazaar_resource_server_extension&lt;/code&gt; on the resource server. At minimum, &lt;code&gt;extensions.bazaar.info.input.type&lt;/code&gt; must be &lt;code&gt;"http"&lt;/code&gt; or &lt;code&gt;"mcp"&lt;/code&gt;. If you include &lt;code&gt;info.output&lt;/code&gt;, it needs a &lt;code&gt;type&lt;/code&gt; too.&lt;/p&gt;

&lt;p&gt;Also check the paying side. A client that drops the extension when it sends the payment leaves CDP with nothing to index (&lt;a href="https://github.com/x402-foundation/x402/issues/3557" rel="noopener noreferrer"&gt;x402 #3557&lt;/a&gt;).&lt;/p&gt;

&lt;h2&gt;
  
  
  4. The description is too long
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Symptom:&lt;/strong&gt; everything else is right, payments may even fail, and nothing tells you why. A long route description can break things without any error (&lt;a href="https://github.com/x402-foundation/x402/issues/2993" rel="noopener noreferrer"&gt;x402 #2993&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; keep the route's &lt;code&gt;description&lt;/code&gt; under about 500 characters. One or two sentences is plenty: what it returns and what it costs.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. &lt;code&gt;resource.url&lt;/code&gt; says &lt;code&gt;http://&lt;/code&gt; behind a proxy
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Symptom:&lt;/strong&gt; your public URL is &lt;code&gt;https://&lt;/code&gt;, but the decoded challenge advertises &lt;code&gt;http://&lt;/code&gt;. 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 &lt;code&gt;https://&lt;/code&gt; resource URLs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; tell your server to trust the forwarded scheme. For uvicorn:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;uvicorn main:app &lt;span class="nt"&gt;--proxy-headers&lt;/span&gt; &lt;span class="nt"&gt;--forwarded-allow-ips&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'*'&lt;/span&gt;
&lt;span class="c"&gt;# or set the env var&lt;/span&gt;
&lt;span class="nv"&gt;FORWARDED_ALLOW_IPS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;*&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For other stacks, read &lt;code&gt;X-Forwarded-Proto&lt;/code&gt; (Express: &lt;code&gt;app.set("trust proxy", true)&lt;/code&gt;), or hardcode your public https base URL.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. The &lt;code&gt;resource&lt;/code&gt; field is missing
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Symptom:&lt;/strong&gt; the challenge has payment options but no &lt;code&gt;resource&lt;/code&gt;, so the Bazaar doesn't know which URL it's cataloging.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; include &lt;code&gt;resource.url&lt;/code&gt;: 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.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. The 402 body is empty or &lt;code&gt;accepts&lt;/code&gt; is malformed
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Symptom:&lt;/strong&gt; x402 v2 puts the challenge in a base64 &lt;code&gt;PAYMENT-REQUIRED&lt;/code&gt; header, and some servers send &lt;code&gt;{}&lt;/code&gt; as the body. Clients and crawlers that read the body find no payment options.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; keep the header, and also return the same decoded JSON as the 402 body. Make sure &lt;code&gt;accepts&lt;/code&gt; is a non-empty array of objects, each with &lt;code&gt;scheme&lt;/code&gt;, &lt;code&gt;network&lt;/code&gt;, &lt;code&gt;asset&lt;/code&gt;, &lt;code&gt;amount&lt;/code&gt; and &lt;code&gt;payTo&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  8. A POST route is described as GET
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Symptom:&lt;/strong&gt; 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.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; declare the body in the discovery metadata. In the Python SDK, pass &lt;code&gt;body_type="json"&lt;/code&gt; plus an example &lt;code&gt;input&lt;/code&gt; and &lt;code&gt;input_schema&lt;/code&gt; to &lt;code&gt;declare_discovery_extension&lt;/code&gt;. Make sure the route key says &lt;code&gt;POST&lt;/code&gt; too.&lt;/p&gt;

&lt;h2&gt;
  
  
  9. The route uses a bare wildcard
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Symptom:&lt;/strong&gt; the route is declared as &lt;code&gt;/prices/*&lt;/code&gt;, so the listing can't tell agents what goes in the path.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; use a named parameter in the paywall's route pattern, such as &lt;code&gt;GET /prices/:symbol&lt;/code&gt;, so the discovery metadata names the path parameter.&lt;/p&gt;

&lt;h2&gt;
  
  
  10. You changed price or metadata and the listing didn't update
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Symptom:&lt;/strong&gt; the route is listed, but with an old price, description or schema (&lt;a href="https://github.com/coinbase/cdp-sdk/issues/813" rel="noopener noreferrer"&gt;cdp-sdk #813&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; 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.&lt;/p&gt;

&lt;h2&gt;
  
  
  If none of these fit: accepted as "processing", never indexed
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Symptom:&lt;/strong&gt; your challenge is valid, a payment settled through CDP's facilitator, and the facilitator answered with &lt;code&gt;bazaar.status: "processing"&lt;/code&gt;. CDP's own validation says the route would be accepted. Days later it still isn't in the catalog.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What's known:&lt;/strong&gt; several sellers have reported this, and as of October 1, 2026 none of the reports has an answer from a maintainer: &lt;a href="https://github.com/x402-foundation/x402/issues/3266" rel="noopener noreferrer"&gt;x402 #3266&lt;/a&gt;, &lt;a href="https://github.com/x402-foundation/x402/issues/3281" rel="noopener noreferrer"&gt;x402 #3281&lt;/a&gt;, &lt;a href="https://github.com/coinbase/cdp-sdk/issues/830" rel="noopener noreferrer"&gt;cdp-sdk #830&lt;/a&gt; and &lt;a href="https://github.com/coinbase/cdp-sdk/issues/835" rel="noopener noreferrer"&gt;cdp-sdk #835&lt;/a&gt;. 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.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What to try:&lt;/strong&gt; 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. If it's still missing after a few days, add your route and settlement details to one of the open issues above.&lt;/p&gt;

&lt;h2&gt;
  
  
  Checking it in one call
&lt;/h2&gt;

&lt;p&gt;If you'd rather not decode challenges by hand, &lt;a href="https://unlisted.sh" rel="noopener noreferrer"&gt;Unlisted&lt;/a&gt; runs all of 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, and it only charges if the check completes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Check, $0.02:&lt;/strong&gt; your 402 challenge, the Bazaar declaration, and CDP's live index status.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Check + real payment, $0.10:&lt;/strong&gt; all of that, plus one real test payment to your route, which covers cause 1 for you.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;POST https://unlisted.sh/diagnose
Content-Type: application/json

{"url": "https://your-api.example.com/paid-route"}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The full guide, kept up to date, is at &lt;a href="https://unlisted.sh/guide" rel="noopener noreferrer"&gt;unlisted.sh/guide&lt;/a&gt;. If you've hit a cause that isn't listed here, tell me in the comments and I'll add it.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Unlisted isn't affiliated with Coinbase.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>web3</category>
      <category>api</category>
      <category>ai</category>
      <category>x402</category>
    </item>
  </channel>
</rss>
