A directory of paid endpoints.
List a machine-payable endpoint without an account, or find one to call. Buyers settle straight to the merchant’s wallet.
A registry of machine-payable endpoints. A merchant lists an endpoint and a price in USDG; an agent finds it in the directory, calls it through the marketplace, answers the 402, and the money lands in the merchant’s own wallet.
x402’s exact scheme settles one transfer to one recipient, so “the builder gets paid” and “Aeron takes a cut” cannot both happen in one transfer without a splitter contract. This service picks the builder: payTo on every 402 is the address on the listing, never Aeron’s. The take-rate is recorded per sale as an accrued receivable and billed out of band.
Endpoints
| Endpoint | |
|---|---|
GET /v1/services | The directory. Filter with ?category= and ?q=. |
GET /v1/services/{slug} | One listing. |
POST /v1/services | Register a listing. Wallet signature, no account. |
PATCH /v1/services/{slug} | Change price, endpoint, or status. Owner only. |
POST /s/{slug} | Call a service, paid via x402. The 402 states the offer twice: a v2 PAYMENT-REQUIRED header and a v1 body. Pay with PAYMENT-SIGNATURE or X-PAYMENT; the receipt comes back as PAYMENT-RESPONSE and X-PAYMENT-RESPONSE. |
GET /openapi.json | Every active listing as an OpenAPI 3.1 operation with x-payment-info, for agents that shop by schema (agentcash, x402scan). |
GET /llms.txt | The same catalogue as prose. |
POST /mcp | The same catalogue as MCP tools, over Streamable HTTP. Read-only, no key. |
GET /v1/directory | Endpoints indexed from the wider x402 network. ?category= ?q= ?host= ?limit= ?offset= |
GET /v1/directory/merchants | The same, rolled up by merchant. |
GET /ledger/stats | Public sales ledger. |
GET /healthz | Status and facilitator mode. |
The catalogue as an MCP server
POST /mcp speaks MCP over Streamable HTTP with four read-only tools: search_endpoints, get_endpoint, list_merchants and list_services. It is how an agent shops the rail without reading an OpenAPI document.
claude mcp add --transport http aeron-market https://market.aeron.sh/mcp
{
"mcpServers": {
"aeron-market": { "type": "streamable-http", "url": "https://market.aeron.sh/mcp" }
}
}Listed in the Cursor directory, which installs it in one click. In Claude’s own apps, add the URL under Settings → Connectors.
A hosted connector needs a server at a URL, and aeron-wallet is already an MCP server — but it holds a private key, so hosting it would make Aeron custodial. The directory is the opposite shape: public data, no key, no money, no account. It can sit at a public URL precisely because there is nothing there to steal. Discovery here, payment on your own machine.
The server is stateless and issues no session id. GET /mcp answers 405: nothing here subscribes to anything, so an event stream would hold a socket open to say nothing.
Listing without an account
There are no accounts. A merchant proves control of an address by signing a statement that names exactly what it authorises:
Aeron Marketplace Sign to prove this wallet controls the listing. This authorises no payment. action: register slug: acme-ocr address: 0x… issued: 2026-08-30T09:00:00.000Z body: <sha256 of the request body>
Sent as x-aeron-address, x-aeron-signature, x-aeron-issued. Change the action, the slug, or a byte of the body after signing and the signature stops matching, so one signature cannot be reused for a different call. Signatures expire after five minutes and are spendable exactly once.
What a listing may point at
Every listing becomes a URL this Worker fetches on a buyer’s behalf, so an unchecked endpoint is an SSRF hole. Plaintext http, embedded credentials, loopback, private and link-local ranges, cloud metadata, and internal-only suffixes are rejected — at registration and again at call time, so a listing edited after the rules tightened is not reachable.
It matches on the hostname as written, so it cannot stop a public name that resolves to a private address. It is a filter on obvious abuse, not a guarantee.
Requests to merchants are rebuilt rather than forwarded: the buyer’s payment header, cookies, and credentials never cross over. Only the body and two identifying headers do — x-aeron-buyer and x-aeron-payment-ref — and the marketplace signs its forwarded calls so a merchant can tell a paid call from a stranger’s.
Order of operations
Nothing settles until the merchant has answered 2xx.
verify -> call merchant -> was anything delivered? -> settle -> respond
|
no -> merchant's own answer, nothing chargedSettling first was simpler, and it was wrong: it billed the buyer for the merchant’s outages and for its refusals — and a refusal is the common case, not the rare one. A well-built merchant rejects bad input cheaply and early, the way rwa.aeron.sh answers 422 to any question asking for advice before it fetches anything. Billing that is billing for a sentence saying no.
Only a 2xx is delivery. A merchant’s 4xx is its refusal of your input; its 5xx is its own outage. Both come back untouched with no X-PAYMENT-RESPONSE, and that absence is what tells a wallet nothing moved.
| Status | Charged | Meaning |
|---|---|---|
ok | yes | Settled, and the buyer got the merchant’s answer. |
settle_unknown | maybe | /settle never resolved; delivered anyway, reconcile against the chain. |
not_delivered | no | Merchant unreachable or answered outside 2xx. Zeroed. |
delivered_unsettled | no | Merchant delivered, settlement failed, answer discarded. Zeroed. |
failed_after_settle | yes | Historical only: rows written under the old order. |
Zeroed rows are excluded from every total in /ledger/stats, so they cannot read as revenue or inflate the sale count.
Updated 20 September 2026. Everything on this page is read from the running services; report a drift at github.com/aeronlabs.