# x402 discovery

> List your paid endpoints in Cryptonly's public x402 discovery (Bazaar) feed, from the dashboard or from your code, so AI agents and x402 directories can find them.

The discovery feed is Cryptonly's public list of paid endpoints. AI agents and x402 directories read it to find APIs they can pay for. Listing is optional and free.

## List an endpoint priced in the dashboard

Turn on **List publicly** when you add or edit an endpoint. The **Status** column of the **Endpoints** tab shows which endpoints are listed.

<LinkButton href="https://merchant.cryptonly.net/x402?tab=endpoints" icon="external" target="_blank" rel="noopener noreferrer">Open endpoints</LinkButton>

Install `@x402/extensions` next to your `@cryptonly/x402-*` package too. It then adds the endpoint's input and output to its `402` response, so agents know how to call it.

The **Advanced** fields describe the endpoint for agents:

| Field | What it tells agents |
| --- | --- |
| Payment timeout | How long a signed payment stays valid. Sent as `maxTimeoutSeconds`. |
| Response type | The content type of the response, such as `application/json`. |
| Input JSON Schema | How to call the endpoint: query parameters for GET, HEAD and DELETE, the body for POST, PUT and PATCH. |
| Output JSON Schema | What the endpoint returns. |

## List an endpoint priced in code

Add the Bazaar extension to the route, on top of the setup from [Prices in your code](https://docs.cryptonly.net/guides/x402/prices-in-code.md):

<IconTabs>
<IconTab label="Express" icon="typescript">

```ts

server.registerExtension(bazaarResourceServerExtension);

app.use(
  paymentMiddleware(
    {
      'GET /v1/quote/:symbol': {
        accepts: [
          { scheme: 'exact', price: '$0.005', network: 'eip155:8453', payTo: process.env.PAY_TO! },
        ],
        description: 'Token price quote',
        extensions: declareDiscoveryExtension({
          output: { example: { symbol: 'SOL', usd: 150.25 } },
        }),
      },
    },
    server,
  ),
);
```

</IconTab>
<IconTab label="NestJS" icon="typescript">

```ts

@X402({
  accepts: { scheme: 'exact', price: '$0.005', network: 'eip155:8453', payTo: process.env.PAY_TO! },
  description: 'Token price quote',
  extensions: declareDiscoveryExtension({
    output: { example: { symbol: 'SOL', usd: 150.25 } },
  }),
})
@Get('quote/:symbol')
quote(@Param('symbol') symbol: string) {
  return { symbol, usd: 150.25 };
}
```

`@X402()` registers the Bazaar extension itself when `@x402/extensions` is installed.

</IconTab>
<IconTab label="Python" icon="python">

```python
# pip install "x402[extensions]"
from x402.extensions.bazaar import OutputConfig, bazaar_resource_server_extension, declare_discovery_extension

server.register_extension(bazaar_resource_server_extension)

routes = {
    "GET /v1/quote/:symbol": RouteConfig(
        accepts=PaymentOption(scheme="exact", price="$0.005", network="eip155:8453", pay_to=os.environ["PAY_TO"]),
        description="Token price quote",
        extensions=declare_discovery_extension(output=OutputConfig(example={"symbol": "SOL", "usd": 150.25})),
    ),
}
```

</IconTab>
</IconTabs>

The route is listed after its first payment. A route with path parameters is listed once, as `/v1/quote/:symbol`.

## Staying listed

- Every 10 minutes, Cryptonly makes an unpaid request to each listed endpoint. It must answer `402` and ask to be paid to one of your addresses.
- An endpoint that fails 3 checks in a row, or passes none for 24 hours, is removed from the feed. It comes back once it passes again.
- To remove an endpoint yourself, turn off **List publicly**, or stop declaring discovery in code.
- You can list up to 50 endpoints per account.
- Endpoints of verified businesses are marked with `extensions.cryptonly.verifiedMerchant: true`.

## Read the feed

The feed is public JSON in the x402 Bazaar format, at `GET https://api.cryptonly.net/x402/discovery/resources`:

```bash
curl "https://api.cryptonly.net/x402/discovery/resources?limit=20"
```

<LinkButton href="https://api.cryptonly.net/x402/discovery/resources?limit=20" variant="secondary" icon="external" target="_blank" rel="noopener noreferrer">Open the feed</LinkButton>

The sandbox feed is at `https://sandbox-api.cryptonly.net/x402/discovery/resources`. The feed needs no API key.

Or use the Bazaar client of the x402 SDK:

<IconTabs>
<IconTab label="TypeScript" icon="typescript">

```ts

const client = withBazaar(
  new HTTPFacilitatorClient({ url: 'https://api.cryptonly.net/x402' }),
);
const { items } = await client.extensions.bazaar.listResources();
```

</IconTab>
<IconTab label="Python" icon="python">

```python
# pip install "x402[extensions]"
from x402.extensions.bazaar import with_bazaar
from x402.http import FacilitatorConfig, HTTPFacilitatorClientSync

client = with_bazaar(HTTPFacilitatorClientSync(FacilitatorConfig(url="https://api.cryptonly.net/x402")))
items = client.extensions.bazaar.list_resources().items
```

</IconTab>
</IconTabs>
