nohumans.directory

Find and vet paid x402 APIs before your agent pays: probe status, a reliability score, and whether a real USDC purchase delivered.

Hosted MCP Server

npx add-mcp 'https://api.nohumans.directory/mcp'

Installs into Claude Code, Codex, Cursor and more

Documentation

← nohumans.directory

Check before you pay

Your agent is about to send USDC to a URL. One request first tells you whether that endpoint is live, whether it has ever been paid successfully, and whether it was listed here and later removed. Every snippet below does the same thing — only the syntax changes.

GET https://nohumans.directory/v1/resolve?url=<endpoint>

What you get back

  • match: "active" — listed and currently tracked. Read status (verified / unverified / failing), score (0..1 recency-weighted probe success), paid_verification (our latest purchase that delivered) and paid_verification_latest (our latest purchase, delivered or not, with its settlement tx).
  • match: "delisted" — it was listed here and removed. Treat as a warning.
  • match: "unknown" (HTTP 404) — never listed, never checked. This is not a verdict. Absence of a record says nothing about an endpoint either way.

Free, unauthenticated, cached 30s. No account, no key.

Before paying: rules

Data alone does not stop an agent from paying; a rule does. Apply these to the record, in order. The first rule that matches decides.

  1. Our latest purchase failed: if paid_verification_latest.delivered is false, do not pay. That purchase settled real USDC and got no valid response. This holds even when status is verified and score is 1: status and score measure the payment challenge, not delivery.
  2. Known bad: if status is failing, /v1/resolve answers match: "delisted", or payto_unstable is true, do not pay.
  3. The 402 you receive disagrees with the record: a price above price_amount or above your budget, a payTo different from observed.pay_to on the same network, or a resource URL that is not the URL you called. Do not pay.
  4. A 402 after you paid: never pay the same request a second time. Stop and keep the transaction hash; if the payment settled on Base, report it (POST /v1/reports, ok: false, signed by the wallet that paid).
  5. No evidence either way: status unverified, or match: "unknown". Pay only if the user has allowed spending on untested services; otherwise ask first.
  6. These rules are not weighed against price. A small amount is not a reason to pay through any rule above.

The snippets below apply the record checks (rules 1 and 2). Rules 3 and 4 need the 402 your client receives; rule 5 needs your user’s spending policy. The same rules are in /llms.txt and SKILL.md.

After paying: report the outcome

Paid a listed endpoint on Base? Tell the next buyer whether it delivered. The report is signed by the wallet that paid and the payment is checked on chain, so only real buyers can report; each transaction counts once and each payer has one voice. Reports count toward ranking once three distinct payers have reported a listing. One call, with viem:

import { privateKeyToAccount } from "viem/accounts"; const account = privateKeyToAccount(PAYER_KEY); // the wallet that paid const txHash = "0x..."; // your payment to this endpoint, on Base const ok = true; // did it deliver what it promised? const message = "nohumans.directory report v1\nlisting_id: LISTING_ID\ntx_hash: " + txHash.toLowerCase() + "\nok: " + ok; const payer_signature = await account.signMessage({ message }); await fetch("https://api.nohumans.directory/v1/reports", { method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify({ listing_id: "LISTING_ID", ok, tx_hash: txHash, payer_signature }), });

Base payments only. If the message format ever changes, a POST without payer_signature answers 400 with the exact message_to_sign; that echo is the authority. Field reference: /llms.txt (POST /v1/reports).

MCP clients

If your framework speaks MCP, connect once and the check becomes a tool your agent can call on its own — along with search and full listing detail.

claude mcp add --transport http nohumans https://nohumans.directory/mcp

Tools: find_paid_service (search by need), get_service_details (full record by id), resolve_endpoint (pre-spend check of a URL you already hold) and what_agents_are_asking_for (what agents searched for here, for sellers deciding what to build).

Connect from your client — one server, one URL

The MCP server is https://api.nohumans.directory/mcp: Streamable HTTP, stateless, no key, no session. Pick your client; the config below is exact for each. Nothing to translate.

Add to Cursor Add to VS Code Add to VS Code Insiders

Claude (desktop or web): Settings → Connectors → Add custom connector → paste the URL. Claude Code:

claude mcp add --transport http nohumans https://api.nohumans.directory/mcp

ChatGPT: Settings → Connectors → Developer mode → add MCP server → paste the URL.

Gemini CLI:

gemini mcp add --transport http nohumans https://api.nohumans.directory/mcp

Windsurf (~/.codeium/windsurf/mcp_config.json), Cline, Roo, and any client that reads a mcpServers block:

{ "mcpServers": { "nohumans": { "type": "http", "url": "https://api.nohumans.directory/mcp" } } }

OpenAI Agents SDK (Python):

from agents.mcp import MCPServerStreamableHttp nohumans = MCPServerStreamableHttp(name="nohumans", params={"url": "https://api.nohumans.directory/mcp"})

LangChain / LangGraph (langchain-mcp-adapters):

client = MultiServerMCPClient({"nohumans": {"url": "https://api.nohumans.directory/mcp", "transport": "streamable_http"}})

Not on MCP? Function-calling stacks read /openapi.json; A2A agents read the signed agent card; marketplaces (AgentCash, Poncho, x402scan) already carry the same routes. If your client isn’t here and needs a different line, hello@nohumans.directory — it will be added, not translated.

TypeScript — @x402/fetch (v2)

const check = await fetch(`https://nohumans.directory/v1/resolve?url=${encodeURIComponent(url)}`); const v = check.ok ? await check.json() : { match: "unknown" }; const d = v.detail ?? {}; if (v.match === "delisted" || d.status === "failing" || d.payto_unstable || d.paid_verification_latest?.delivered === false) // our latest purchase took the money and did not deliver throw new Error("skip: " + (d.paid_verification_latest?.failure_reason ?? d.status ?? v.match)); const res = await fetchWithPayment(url); // your existing paid call

TypeScript — x402-fetch / x402-axios (v1)

The v1 client packages are deprecated upstream but still widely installed. One extra reason to check first: a v1 client reads payment terms from the 402 body, so a v2 endpoint that answers with a payment-required header will look broken to it. We record which version each endpoint actually used.

const v = await (await fetch(`https://nohumans.directory/v1/resolve?url=${encodeURIComponent(url)}`)).json().catch(() => ({ match: "unknown" })); if (v.detail?.x402_version === 2) console.warn("v2 endpoint — a v1-only client may not see its terms"); if (v.match === "delisted" || v.detail?.status === "failing" || v.detail?.paid_verification_latest?.delivered === false) return; const res = await fetchWithPay(url); // x402-fetch

Python

import requests, urllib.parse r = requests.get("https://nohumans.directory/v1/resolve", params={"url": target}) v = r.json() if r.ok else {"match": "unknown"} d = v.get("detail") or {} if (v["match"] == "delisted" or d.get("status") == "failing" or d.get("payto_unstable") or (d.get("paid_verification_latest") or {}).get("delivered") is False): raise RuntimeError(f"skip {target}: {v['match']}")

Any language / curl

curl -sG https://nohumans.directory/v1/resolve --data-urlencode "url=$ENDPOINT" | jq '.match, .detail.status, .detail.score, .detail.paid_verification_latest.delivered'

Paid verdict — one call, $0.005 USDC on Base

Everything above is free and stays free. For a listing you are about to spend real money on, GET /v1/listings/:id/verdict folds the whole record into one word — pay, caution or avoid — with the reasons, by the rule at /methodology#verdict. It is an x402 v2 route: the unpaid call answers 402 with its terms in both the payment-required header and the body, so any v2 client pays it exactly the way it pays the endpoint you are vetting.

import { x402Client, wrapFetchWithPayment } from "@x402/fetch"; import { registerExactEvmScheme } from "@x402/evm/exact/client"; const client = registerExactEvmScheme(new x402Client(), { signer }); // viem account const payFetch = wrapFetchWithPayment(fetch, client); const v = await (await payFetch(`https://nohumans.directory/v1/listings/${id}/verdict`)).json(); if (v.verdict === "avoid") throw new Error(v.reasons.join("; "));

A real answer, 2026-09-05, for a listing with status verified: {"verdict":"caution","reasons":["no successful paid delivery on record from our scout"]} — clean 402 history, stable payTo, price as declared, but we have not yet bought from it ourselves, and the verdict says exactly that. caution on a verified listing is the rule working, not a contradiction; the free record it summarises is the same /v1/listings/:id above. On Coinbase's hosted wallet, awal x402 pay <url> buys the same verdict. Settlement runs through the CDP facilitator; the transaction hash comes back in the payment-response header.

What this does not tell you

Everything here is endpoint behaviour: correct 402s, a live free sample, a stable payment address, real payment volume, and — where we have paid it ourselves — that a real purchase returned valid data at a point in time. None of it verifies who operates the software behind a URL today, and none of it guarantees the content you buy is accurate. A compromised domain that keeps its payment address and returns well-formed responses passes every check here. That is a structural limit of behavioural verification, not a gap we intend to close quietly.

Full field reference: /llms.txt. Questions or a framework we should cover: hello@nohumans.directory

state of the network · methodology · stats · sellers · integrate · data · terms · privacy