Ripardocs
Dashboard

Discovery

A paid endpoint nobody can find earns nothing. There are three discovery surfaces here, and they are at very different stages of completion. It is worth being blunt about which is which.

SurfaceStatus
The agent's own manifestWorks. Served by every agent, free.
The A2A agent cardWorks. Served alongside the manifest.
The on-chain IdentityRegistryWorks, on Algorand TestNet. Read it over MCP.
Listing in the x402 BazaarNot wired up. See below.

The manifest

Every agent built with serve() publishes one at /.well-known/ripar.json, unpaid:

{
  "name": "Ripar Text Tools",
  "handle": "ripar-text-tools",
  "network": "testnet",
  "payTo": "KBDRZK3BV2YFJJAVV3S5XQYDWU4RDDI6EDXXKMG3O4AEVPEDCETDKEISKQ",
  "endpoints": [
    {
      "name": "summarize",
      "url": "https://api.ripar.io/api/summarize",
      "method": "POST",
      "price": "$0.01",
      "input": {
        "type": "object",
        "properties": { "text": { "type": "string", "minLength": 1 } },
        "required": ["text"]
      }
    }
  ],
  "x402": { "facilitator": "…", "network": "algorand:…", "asset": { "id": 10458941 } }
}

The schema is the important part. It is what lets a caller that has never seen your service construct a valid request without reading documentation — and it is the same schema the server enforces before payment, so a request built from it cannot be rejected for shape.

ripar manifest https://api.ripar.io
Why the manifest is free

A caller that has never met you reads it to learn what exists, what it costs and what shape the input takes. Charging for that would mean paying to find out whether something is worth paying for.

The agent card

The same agent, described for agent-to-agent discovery, at /.well-known/agent.json. Its extensions carry the x402 prices, the on-chain agentId, and the MCP server a peer should connect to — so one fetch tells another agent how to pay you and which tools it will find. See the Agent HTTP API.

The on-chain registry

The IdentityRegistry (Algorand TestNet app 769444119) binds an agent id to a domain and a controlling address. That binding is the only authenticated one in the system: everything else — a manifest, a card — is a claim served by a host.

ripar_search_agents
{ "query": "ripar.io", "withReputation": true }

Each result carries a cardUrl of https://<domain>/.well-known/agent.json, so resolving an id gets you to a live card. Reading the registry costs nothing and needs no key.

Registration is a claim, not proof of a domain

The registry records that an address said it controls a domain. Nothing verifies that the domain agrees. Fetch the card and check that its agentId points back before you treat the two as the same party.

The Bazaar

The x402 Bazaar is a real, live index — the GoPlausible facilitator serves it at GET https://facilitator.goplausible.xyz/discovery/resources, listing resources with their accepts blocks across Algorand, Base and Solana.

Getting listed is not a call you make. There is no registration endpoint — an earlier version of this SDK exported registerWithBazaar(), which POSTed a manifest to /bazaar/register on the facilitator, and that path returns 404. Because the helper swallowed every failure by design, an agent that called it received a plausible { ok: false } and believed itself listed forever.

The real mechanism is a route extension. serve() attaches a Bazaar discovery extension to every endpoint with listed: true, deriving the example request body from that endpoint's own input schema, so the catalogue entry cannot drift from what validation will accept. The facilitator then catalogues the resource while verifying a payment for it.

The consequence is worth stating plainly: an endpoint becomes discoverable by being paid for, not by announcing itself. That is the same rule the Reputation Registry enforces, and it is why the index is worth reading — everything in it has taken real money.

// Nothing to call. This endpoint is listed by default, so serve() declares it.
defineEndpoint({ name: "summarize", price: "$0.01", input: schema, handler })
 
// listed: false keeps an endpoint payable but out of both the manifest and the index.
defineEndpoint({ name: "internal", price: "$0.05", listed: false, handler })

Reading the index

import { listBazaar, findInBazaar } from "@ripar/sdk";
 
const all = await listBazaar({ limit: 50 });
if (all.ok) for (const r of all.resources) console.log(r.resourceUrl, r.accepts);
 
const oracles = await findInBazaar("oracle");

Neither throws — an index being down cannot take a working paid endpoint offline. A failure comes back as { ok: false, error } so you can log it and carry on.

Search is local, not server-side

The index has no search route (/discovery/search is a 404), so findInBazaar reads a page and filters it in your process. It only sees what limit fetched — an empty result means "not in the page I read", not "does not exist".

Staying unlisted

Not everything should be advertised. An endpoint marked listed: false still takes x402 payments but is left out of the manifest:

defineEndpoint({ name: "internal/reindex", price: "$0.05", listed: false, handler });

Useful for paid internal services where you want metered billing between teams without publishing the capability. It is omission, not access control — the URL is still callable by anyone who can pay and knows it exists.