Not in the x402 Bazaar? Nine silent causes, in order
Nine causes of a missing Bazaar listing that leave no error anywhere, cheapest to check first, each with a command that proves it and a control that can fail.

Usually because one small thing is wrong on your side and the party that could tell you, a buyer agent or the indexer, simply walks away without writing to you. You also cannot ask for a place in the catalog: nothing is submitted and nothing is registered. An x402 Bazaar listing appears after a payment has been settled through the Coinbase facilitator, so every cause below either prevents that payment or prevents the Bazaar listing from surviving it.
The nine causes are ordered by how cheap they are to test, not by how likely they are. Work down the list and keep going after the first hit, because these defects stack and fixing one often uncovers the next. Every check ends with a control, a case where you know what the answer must be, because a check that has never been seen to fail proves nothing.
1. The requirements are not in the header
In version 2 of the protocol, the price requirements travel in the response's PAYMENT-REQUIRED header. The standard buyer client reads that header and ignores the body, so a perfectly good JSON body without the header is a shop with the door painted on. The header must also appear on refusals, not only on the first unpaid answer.
curl -s -D - -o /dev/null https://YOUR-HOST/your/paid/path | grep -i payment-required
Control: run the same command against a seller you know works. If both print nothing, your command is wrong, not the two servers.
2. The header and the body disagree
The header carries the same JSON as the body, encoded as standard base64 of the UTF-8 bytes. Two slips are common: the URL-safe alphabet, which is what your JWT helper produces, and btoa applied to text that contains a non-ASCII character. Decode the header with the function that ships in the buyer library, not a parser you wrote, and compare the result with the body byte for byte. Serialise the object once and send that one string in both places.
3. The token domain is missing from the first requirement
Inside accepts[0] the extra object holds the name and version of the token's signing domain. The schema treats it as optional. A buyer cannot produce a signature without it, so it leaves quietly. The catalog's public validate endpoint still says accepted, because it checks the format of the document, not whether anyone could sign it. We measured exactly that on a second service of ours before we wrote this down.
Fix: add extra with the name and version that belong to your token on your network. The values differ between the main network and the test network, and copying one onto the other produces a signature that the token contract rejects.
4. The catalog block is empty or in the wrong place
The bazaar entry belongs in an extensions object placed directly on the body root, a sibling of accepts and resource; putting it inside the first requirement hides it. An empty object parses fine and fails validation: the public specification asks for info with an input description, and a schema that info is checked against. The output example is optional in the spec, so do not treat its absence as the cause. Check the raw body, not the decoded object: the decoding code in the buyer library can discard fields it has no schema for. The bazaar extension spec lists the exact fields.
5. Your price is above the buyer's default cap
Out of the box, the standard buyer client declines any one payment worth more than a dollar; only its owner can lift that ceiling. That decline is made on the buyer's side, so your logs stay empty. If any price you publish is higher, state it in the places agents consult ahead of buying: your docs page, your agent guidance text, your tool descriptions.
6. The settlement went through the wrong facilitator or network
Cataloging is triggered by a payment that Coinbase's facilitator settled on a main network. A payment on a test network, or one settled by the public x402.org facilitator, is valid and will never list you. If you only ever tested on the test network, this is your answer, and you have never been a candidate.
7. Your own decoder chokes on the incoming payment
The buyer echoes your resource block, description included, inside the payment header. If your server decodes that header with a bare atob, it reads the bytes as Latin-1, and a dash, an ellipsis or a Cyrillic letter in the description turns into control characters. The whole payload is then rejected by the facilitator, with a message that starts paymentPayload is invalid, which reads like a broken buyer. It was exactly this that failed our first sale on the main network, on 30 September 2026; the repaired server settled the next attempt.
When decoding the header, treat its bytes as UTF-8. While you are there, log the facilitator's errorMessage and correlationId on a rejection: when the facilitator answers with HTTP 400 the usual reason fields are absent, and code that reads only those records an unhelpful "unknown reason".
8. Your own zone blocks the clients
A web application firewall in front of your server can answer non-browser clients with a block page before any payment logic runs. Cloudflare's Browser Integrity Check does this with HTTP 403 and error code 1010 for script clients, sitewide. The catalog crawler may be among the clients turned away. Request the same path twice, once like a browser and once like a plain script, and compare the status codes.
9. The listing lapsed
Listings are kept per resource, and a resource that has had no settled payment for about 30 days drops out. A settlement on your cheap resource leaves the clock of an expensive one running. If you were listed and vanished, look at the date of the last settlement for that exact resource before touching a correct response.
Proving that the fix worked
Read the requirements the way a buyer does, with the buyer library's HTTP client, and then read the same body again with the header withheld. The second read must fail. If it succeeds, the library quietly used the body instead, so the first success told you nothing. Then make one genuine payment using that library, not with a hand-written script, through the Coinbase facilitator on the main network; our own first purchase did that, and its transaction is 0x146f02c8c8bb883b35929d88f0d115b5150b9e6ec9b5fe063d24d452db394315 in block 51993034, paid to 0x8e37022edcf0f21cf3c9f93fee9d4d32519f36f4.
Finally search the discovery API by your domain. Control: a domain you invented must give an empty answer, and remember that some discovery endpoints return their list under resources and others under items, so a parser that checks only one of them wrongly concludes nothing is there.
If you would rather hand a pasted response to a checklist than read this list, there is a skill for that; the list above stands without it.
When this does not apply
This list is for version 2 sellers that want the Coinbase catalog. It does not cover other catalogs, which have their own crawlers and their own rules, and it does not help if your endpoint is simply not paid or not reachable. Several things in it are our own measurements on one network and one facilitator at a given time: the catalog's behaviour can change, and nothing here guarantees a listing. The lapse rule in cause nine comes from our notes on how the catalog behaved, and the public documentation page we read does not state it, so treat it as observed rather than promised. We also did not test causes that one other seller reported only once, such as a resource that stays unlisted after its opening settlement shipped a malformed catalog block. We ran the defects on a single stack, so a cause we list as silent may be noisy on yours.
Read this post as Markdown: /blog/x402-not-in-bazaar.md · Atom feed.