DEV Community

Mohammad Mudassir
Mohammad Mudassir

Posted on

Your x402 End-Point Is Invisible

Settlement gets you paid. Discovery gets you found. They're different systems.

One of the most common questions we've seen during the x402 Global Challenge is:

"My endpoint is live. Payments are working. Why isn't it showing up on the leaderboard or in the Bazaar?"

In almost every case, the payment flow is working perfectly.

The missing piece is usually discovery, and for Global Challenge participants, making sure your endpoint is tagged correctly for the challenge.

There are really two things to verify:

  1. The Bazaar discovery extension is enabled on your endpoint.
  2. Your resource is tagged with x402-global-challenge, so challenge activity is correctly identified and attributed.

It's easy to assume that once your endpoint accepts payments, the facilitator automatically knows everything about your API. It doesn't.

You shipped an x402-protected endpoint. Payments verify, payments settle, the money arrives. Then you go looking for yourself in the Leaderboard and there's nothing there.

Nothing is broken. You just never declared the discovery extension, or your endpoint isn't tagged for the challenge. Both are small configuration changes, but they're easy to miss.

The 30-second check

Before reading further, find out whether this is you:

curl -s "https://facilitator.goplausible.xyz/discovery/resources?includeTestnets=true&limit=1000" \
  | jq '.items[] | select(.resourceUrl | contains("your-domain"))'
Enter fullscreen mode Exit fullscreen mode

Empty output, but payments are settling? Keep reading. That's the exact gap this post closes.

Payment and discovery are two different systems

This is the root of the confusion, so it's worth being blunt about it:

What it does What turns it on
Payment Verifies and settles on-chain paymentMiddleware(routes, server)
Discovery (Bazaar) Catalogs your endpoint so agents and the dashboard can find it extensions: declareDiscoveryExtension({...}) on the route

A facilitator can settle thousands of payments for you and still have nothing to publish.

A settlement is simply proof that an address paid an amount on a network. It carries no description of what your endpoint does: no method, no input shape, no output example. There is nothing in it to build a catalog entry from.

The discovery extension supplies that metadata. It rides along inside your 402 Payment Required response, and the facilitator catalogs it when a client actually pays against it.

The two lines in your resource server

Line one, the import:

import { declareDiscoveryExtension } from "@x402-avm/extensions";
Enter fullscreen mode Exit fullscreen mode

Line two, one key on the route config you already have:

const routes = {
  "GET /api/quote": {
    accepts: {
      scheme: "exact",
      network: ALGORAND_MAINNET_CAIP2,
      payTo: PAY_TO_ADDRESS,
      price: "$0.01",
      extra: {
        feePayer: FEE_PAYER,
        tag: "x402-global-challenge",
      },
    },
    description: "Live ALGO/USD quote with confidence interval.",
    extensions: declareDiscoveryExtension({}),
  },
};

app.use(paymentMiddleware(routes, server));
Enter fullscreen mode Exit fullscreen mode

That's genuinely it.

declareDiscoveryExtension({}) with an empty configuration produces a valid discovery extension and is enough to get your endpoint cataloged. Everything you can pass beyond that improves the listing, but none of it is required just to appear.

Also note what you don't do:

You don't call registerExtension, and you don't touch your x402ResourceServer. The framework binding scans your routes for a bazaar key under extensions and registers the server-side extension automatically on the first paid request.

The same behavior works across @x402-avm/hono, @x402-avm/express, and @x402-avm/next.

Add the required challenge tag to the extra field of your resource configuration:

extra: {
  feePayer: FEE_PAYER,
  tag: "x402-global-challenge",
},
Enter fullscreen mode Exit fullscreen mode

This helps identify your endpoint as part of the x402 Global Challenge and ensures your activity is properly tracked and attributed.

Without this tag:

  • Your endpoint can still accept payments.
  • Discovery can still work.
  • But your activity may not be recognized as part of the Global Challenge.

Think of it as metadata for the facilitator. It tells the platform that this endpoint belongs to the challenge and should be included when tracking participant activity.

Verify it in three commands

Check the discovery API directly. It's the source of truth and updates immediately.

# 1. Your 402 response carries the discovery extension
curl -i https://your-domain/api/quote | grep -i bazaar

# 2. Your resource exists in the catalog
curl -s "https://facilitator.goplausible.xyz/discovery/resources?includeTestnets=true&limit=1000" \
  | jq '.items[] | select(.resourceUrl | contains("your-domain"))'

# 3. Your merchant exists
curl -s "https://facilitator.goplausible.xyz/discovery/merchants?includeTestnets=true&limit=500" \
  | jq '.items[] | select(.addresses.avm == "YOUR_PAYTO_ADDRESS")'
Enter fullscreen mode Exit fullscreen mode

Your merchantId in that API is the Base64 encoding of the first 24 characters of your payTo address, so you can compute it locally and search for it directly:

echo -n "YOUR_PAYTO_ADDRESS" | cut -c1-24 | tr -d '\n' | base64
Enter fullscreen mode Exit fullscreen mode

Between step one and step two you need one successful payment.

Discovery is triggered by payment activity. Your 402 Payment Required response can advertise the discovery extension all day, but the facilitator only creates the catalog entry after a client successfully pays for the endpoint.

Rather than waiting for someone else to call it, pay your own endpoint once using a test client.

Then brand it

Once discovery/resources returns your endpoint and your resource is correctly tagged with x402-global-challenge, you're officially discoverable.

Now it's worth polishing how your API appears in the Bazaar.

Add the following metadata at your domain root:

  • og:site_name
  • og:title
  • og:description
  • og:image

Use a publicly accessible logo, then trigger one more successful payment so the facilitator refreshes the metadata.

For a complete walkthrough, see my previous article:

Branding your x402 Merchant on the GoPlausible Dashboard

Happy hacking! 🚀

Top comments (0)