# x402 Bazaar Listing Monitor [Health: Active]

**Category:** 💰 Finance & Fintech  
**Repository:** https://github.com/acjlabs/x402-listing-monitor  
**GitHub Stars:** 1  
**Views:** 0  
**Installs:** 0  
**Upvotes:** 0  
**Directory Page:** https://allmcps.com/mcp/x402-bazaar-listing-monitor

## Description
Checks x402 Bazaar resource listings against the public discovery catalog and flags drops.

## Claude Desktop Quick Installation
Remote MCP endpoint (confidence: high). Install path detected from listing signals. Add as a URL/SSE server in your client:

```json
"mcpServers": {
  "x402-bazaar-listing-monitor": {
    "url": "https://x402-listing-monitor.acjlabs.com/mcp"
  }
}
```

## Documentation & README

# x402 Bazaar Listing Monitor

Scheduled watchdog for x402 sellers: polls Coinbase CDP's public Bazaar discovery catalog for the
resources you register and alerts when one drops out or comes back — instead of finding out from a
revenue dip days later.

Sellers who settle real x402 payments have no reliable way to confirm their resources stay
discoverable in CDP's Bazaar catalog. The discovery API has a recurring, publicly-reported class of
bug where a resource silently stops appearing despite confirmed settlements — sellers currently catch
this only by manually re-running `GET /discovery/merchant?payTo=<address>` on their own schedule.

This service automates that check: register your `payTo` address and the resource URLs you serve, and
a scheduled poll diffs them against the live discovery catalog. State changes are recorded with
timestamps, so you have a durable history you can cite if you need to escalate to CDP support.

## MCP server

**Endpoint:** `https://x402-listing-monitor.acjlabs.com/mcp` (streamable HTTP)

One tool — no signup, no API key:

### `check_listing_health`

Checks whether a seller's x402 Bazaar resources are currently listed under a given `payTo` address in
the public discovery catalog. Runs the same per-seller diff as the scheduled poller, on demand, for
any `payTo`/resources pair — registered here or not.

| parameter | type | notes |
| --- | --- | --- |
| `payTo` | string | `0x`-prefixed, 40 hex characters |
| `resources` | string[] | 1–200 `http(s)` URLs |

Returns each resource flagged as listed or missing, as JSON.

## HTTP API

Base URL: `https://x402-listing-monitor.acjlabs.com`

| method | path | purpose |
| --- | --- | --- |
| `GET` | `/health` | liveness check |
| `POST` | `/register` | register a seller for scheduled polling |
| `GET` | `/status` | read your own current status and recent alerts |
| `POST` | `/poll` | run a poll immediately (counts only, see below) |

### `POST /register`

```json
{
  "sellerId": "your-slug",
  "payTo": "0x0000000000000000000000000000000000000000",
  "resources": ["https://api.example.com/your-resource"],
  "alertWebhookUrl": "https://example.com/hook"
}
```

- `sellerId` — 2–64 characters: letters, digits, `-`, `_`
- `payTo` — `0x`-prefixed, 40 hex characters
- `resources` — 1–200 `http(s)` URLs, no duplicates
- `alertWebhookUrl` — optional. A public `https` URL; alerts on your plan are `POST`ed to it. IP-literal,
  loopback, `.internal`/`.local` hosts and URLs carrying credentials are rejected.
- `alertEmail` — optional, and **stored but not yet used**: email delivery is not enabled (see Status).

Both contact fields are optional and registration succeeds without either. Supply neither and nothing is
pushed to you — use `GET /status` below to check on your listings yourself.

Resources are watched by self-declaration: the service checks what you tell it to check. A `sellerId`
that already exists is rejected rather than overwritten.

### `GET /status`

```
GET /status?sellerId=your-slug&payTo=0x0000000000000000000000000000000000000000
```

Returns your own record: every resource you registered with its current status (`listed`, `missing`,
`payTo-mismatch`, or `null` if no poll has reached it yet), its consecutive-miss count and last-checked
timestamp, plus your most recent alerts and whether each was delivered.

Both `sellerId` and `payTo` are required and must match your registration; anything else returns `404`.
This is a knowledge check, not authentication — the data it returns is a diff against a public catalog.
Your `alertEmail` and `alertWebhookUrl` are never echoed back, only reported as set or not set.

### `POST /poll`

Runs the same poll the six-hourly cron runs, immediately, for every registered seller. Takes no body
and returns counts only:

```json
{ "polled": 2, "ok": 2, "failed": 0 }
```

It reports nothing about any individual seller. This endpoint is unauthenticated, so anything it
returned would be public — read your own state with `GET /status` instead.

Only one poll runs at a time. If a poll is already in progress — whether someone else triggered it or
the six-hourly cron did — this returns `409` and does no work:

```json
{ "status": "already_running" }
```

That is not an error to retry through: the poll you asked for is already happening, and retrying cannot
make its alerts arrive sooner or arrive twice — the lock is what stops two concurrent polls from sending
you the same alert. It is a guarantee against duplication, not a delivery guarantee: an alert is always
recorded before it is sent, and if the send does not land it stays recorded and undelivered rather than
being retried. Wait, then read `GET /status`, which shows each recent alert and whether it was
delivered.

Per-IP rate limits apply to `/register`, `/status`, `/poll` and MCP tool calls.

### Webhook payload

```json
{
  "service": "x402-listing-monitor",
  "sellerId": "your-slug",
  "checkedAt": "2026-08-07T00:00:00.000Z",
  "alerts": [
    {
      "type": "listing-dropped",
      "resource": "https://api.example.com/your-resource",
      "detail": "was listed, now missing from discovery",
      "message": "⚠️ Listing dropped: https://api.example.com/your-resource — was listed, now missing from discovery"
    }
  ]
}
```

`checkedAt` is the poll's timestamp, matching `created_at` on the same alerts in `GET /status`. Any 2xx
counts as delivered. Redirects are not followed — a `3xx` is treated as a failed delivery, so register
the final URL. Failed deliveries are not retried; the alert stays in your history marked undelivered.

## Polling and alerts

The scheduled poll runs **every 6 hours**. Each run diffs your registered resources against the live
discovery catalog and records state changes with timestamps — a history, not just a point-in-time
answer.

| alert type | tier |
| --- | --- |
| resource dropped out of the catalog | free |
| still missing after an indexing-lag grace period | free |
| resource recovered | free |
| registered payTo missing from the catalog entry | paid |
| catalog quality/rank drop | paid |

"Still missing" fires **once per miss streak**, from the first poll at which a resource has been absent
for three or more consecutive polls — long enough that indexing lag is ruled out. It does not repeat
every six hours while the resource stays missing; the current state is always readable from
`GET /status`.

Three consecutive misses is the earliest it can fire, not the only point at which it can. A resource
that is already past three consecutive misses **and has not yet been alerted for that streak** raises
its one alert on the next poll. If the resource recovers and later drops out again, that is a new
streak and it alerts again.

Paid tiers also tighten the polling interval.

## Status

Early release. The service is live and polling, and the recorded alert history is authoritative for
what it has observed.

- **Webhook delivery is enabled.** Register an `https` `alertWebhookUrl` and alerts on your plan are
  `POST`ed to it when a check produces one.
- **Email alerts are not enabled yet.** `alertEmail` is stored against your registration and nothing is
  sent to it.
- **No contact is required.** `GET /status` gives you the same information on demand.

## Source availability & support

This repository hosts the documentation for the hosted service. The service implementation is not
open source. Bug reports and feature requests are welcome in this repo's Issues; you can also reach us
at <contact@acjlabs.com>.

## Source availability & support

This repository hosts the documentation for the hosted service. The service implementation is not open source. Bug reports and feature requests are welcome in this repo's Issues; you can also reach us at <contact@acjlabs.com>.

