# nohumans.directory > A machine-readable registry of paid (x402-enabled) APIs and datasets, > verified by paying: nohumans sends real USDC to listed endpoints and > confirms delivery against the seller's own declared terms, alongside > continuous probe verification and longitudinal reputation. Query it to > find services worth paying for before your agent spends money. Live > verification totals: https://api.nohumans.directory/v1/stats (paid_verification block); full > census with methodology and corrections: https://api.nohumans.directory/state/paid-verification. Base URL: https://api.nohumans.directory ## Endpoints ### GET /v1/discover Search listings. Query params: - q : free-text term matched against name and description. Describe the actual need as specifically as possible — the real data, freshness, format, or constraint that prompted the search, not just a topic word. This text is what makes ranking relevant and is the only place that level of detail is captured; category and price are coarse filters on top of it, not a substitute. Free-text q is embedding-backed semantic search, not keyword matching: describing the need in natural language finds relevant listings even when they share no words with it. - category : category filter, e.g. data.fx, compute.translation. Exact-match against GET /v1/categories, but an unmatched value now falls back to being treated as a q text term rather than returning zero results — see category_expanded below. Still worth using a real category when you know one; it's a stronger signal than relying on fallback. - max_price : max per-call price (numeric) - min_score : min reputation score, 0..1 (recency-weighted probe success) - limit : max results (default 10, cap 50) Returns JSON: { count, results: [{ id, name, description, endpoint_url, category, price_amount, price_currency, chains, status, has_sample, x402_version, last_probed_at, onchain_unique_payers_30d, score, p50_latency_ms, p95_latency_ms, p99_latency_ms, probe_count, paid_verified, distinct_payers, report_count, report_score, status_changed_at }], category_expanded? } paid_verified (bool): a real USDC payment by our scout settled AND the response validated — see paid_verification on GET /v1/listings/:id for the on-chain tx. distinct_payers / report_count / report_score: on-chain-verified payer reports (weighted into ranking only at 3+ distinct payers). evidence_tier: one of payer_reported, paid_verified, probe_verified, probe_only, unproven — what kind of evidence stands behind this listing, strongest first; evidence_note says it in a sentence. verdict_age_seconds: how old the newest evidence is (cadence is uneven by design — settled listings are checked less often, so age alone is not staleness). status_changed_at: when the listing last changed status — a recently re-verified listing is a different bet than one stable for months. status is one of: verified, unverified, failing. 'verified' means 3+ probes, no current failure streak, and a recency-weighted score above 0.8. The score starts at the first counted probe's result and moves 10% toward each later one, so a new listing whose first probe passes needs three clean probes, and one whose score starts at zero (after a payment-address reset, a recovery from failing, or a failed first probe) needs about sixteen. 'failing' means 5+ consecutive failures; those listings still appear but rank last. Prefer verified listings with score >= 0.8. has_sample (bool): true means the listing declared a sample_query an agent can call, often free or cheap, to see real output before paying full price. For a new or thinly-reputed listing you can't yet judge from score alone, has_sample is the fastest way to evaluate it cheaply — prefer it when reputation signals are thin or tied. What has_sample actually guarantees, and what it doesn't: every probe cycle, not just at submission, a declared sample_query must return HTTP 2xx and body that parses as valid JSON, or the whole probe fails for that cycle — a listing can't hold 'verified' with a sample that's gone empty, broken, or started erroring. That's a real, continuously-rechecked floor, not a one-time check. It is still not proof the content is correct or useful — only that something live and structurally valid is being returned right now. A seller can pass this while returning accurate placeholder-shaped JSON. Payer reports (see /v1/reports) are the only signal that speaks to whether the paid response was actually correct, and they only carry weight once a listing has 3+ distinct reporters — most listings don't yet. Treat 'verified' as protocol-conformance and (when has_sample is true) sample-liveness, not as a content-accuracy guarantee. Paid verification (paid_verified on discover results, paid_verification on listing detail): a stronger, narrower signal than 'verified'. It means the nohumans scout paid this endpoint real USDC on Base, received a response, and validated it — valid JSON, no error payload, and conformance to the listing's declared response_schema where one exists. The settlement transaction hash is included in paid_verification.tx_hash as independently checkable on-chain proof, and schema_validated is three-state: true (matched declared schema), false (violated it), null (no schema declared — only JSON-validity was checked). This is a point-in-time check at verified_at, not continuous: it proves the endpoint delivered real data for real money at least once, not that it still does. First-party listings no longer exist here: all listings operated by the nohumans team were retired 2026-08-25 (changes-feed reason first_party_retired) — the directory lists nothing its operator sells. Rows with origin: first_party remain visible only as delisted history. When choosing between otherwise-similar listings, prefer paid_verified ones: it is the only signal here backed by an actual completed purchase. The scout speaks both x402 v1 (body accepts array) and v2 (payment-required header), so verification does not depend on which protocol generation a seller implements. Embeddable badge: GET /badge/:id/paid.svg. Payment-destination change protection: a listing's declared pay_to address is tracked on every probe. If it changes — an operator legitimately rotating wallets, or a compromised server redirecting funds to an attacker — reputation is fully reset (score, probe_count, consecutive failures all zeroed) and status drops back to 'unverified' immediately, regardless of what that same probe's liveness result was. A high score earned by one payment destination is never carried over to a new one; the listing has to re-earn 'verified' from scratch, the same bar a brand-new submission clears. This does not, and cannot, verify that a wallet rotation was actually legitimate — nohumans has no seller identity system and doesn't plan one. What it guarantees is narrower and still real: an address nobody has ever paid through here before never inherits trust it didn't earn. onchain_unique_payers_30d (integer, or null if never checked): distinct wallets that sent USDC to this listing's payTo address on Base in the last 30 days, read directly from public chain data — not something the probe loop measures, since a probe never pays. Read it as a CEILING on customer count, never a measurement of it: every incoming USDC transfer counts, so an operator funding its own wallet, or paying itself, inflates it. This is still genuinely different evidence from score: score proves an endpoint answers correctly, this proves USDC is arriving at its payment address. Neither implies the other, and they're deliberately never combined into one number. This still says nothing about whether what was purchased was any good — see payer reports for that, the one signal that speaks to outcome, not just payment. Full detail (onchain_tx_count_30d, onchain_volume_usd_30d, onchain_checked_at) is on GET /v1/listings/:id. onchain_checked_at is the last SUCCESSFUL read; onchain_last_attempt_at is the last try. When onchain_provider_error is 1, the figures are held from onchain_checked_at rather than fresh, and onchain_provider_status carries the HTTP status the provider gave. Figures with a null onchain_checked_at were read before 2026-08-28T10:30Z (the exact time was not retained); all-null figures mean no successful read has ever happened for that address. onchain_count_capped true means the read hit its 150-item ceiling: tx_count_30d is a floor and unique_payers/volume are truncated with it (see the 2026-08-29 correction) — this applies only to rows with onchain_source null. Since 2026-08-29 rows carry onchain_source 'index': figures come from our own index of USDC Transfer events on Base to each listing's payTo (eth_getLogs, every 5 minutes, no paging ceiling, window = today plus the 30 prior UTC days). Base USDC only: a seller settling on another chain reads as quiet here. onchain_payto_shared_listings is how many active listings declare the same payTo — the figures are a property of the address, not of any one route, so do not sum them across listings. response_mime (discover results) is the content-type the endpoint's own 402 challenge declares for a paid response (e.g. application/json). Most listings are null: the field is optional in x402 and almost nobody sets it — of 1,480 listings re-observed since it shipped, 65 declare one (4.4%), 63 of those application/json. Null means not declared, not unchecked. If your agent needs a specific format, this tells you only when the seller said so; otherwise a sample query or a paid call is the only way to know. payment_protocols (discover results and detail, since 2026-09-26) lists the payment protocols the endpoint's own 402 offered on our unpaid probes: x402, mpp (the "Payment" HTTP authentication scheme, WWW-Authenticate: Payment), or both. mpp_methods names the MPP methods as the endpoint names them (tempo, evm, stripe, ...); the record adds mpp_offers (method, intent, amount, currency, recipient, chain_id, realm) and mpp_note. Paid verification and on-chain figures cover x402 on Base only, whatever else a listing accepts. observed_network (discover results and detail) is the chain the endpoint's own 402 challenge named on the last probe; chains is what the seller typed at submission. When they differ, the observed one is what your payment must match — as of 2026-08-30, 8 active listings differ, including three that declare Base and ask for Base Sepolia testnet. onchain_daily (index rows only) is the per-UTC-day series behind the 30d figures: [{day, tx, payers, usd}], today plus 30 prior days — read it, a 30d sum hides cliffs. onchain_shape is a sample of the 25 most recent payments to the address classified by transaction calldata: {sample_n, eip3009, plain, other, sampled_at}. eip3009 = transferWithAuthorization/receiveWithAuthorization, the x402 exact scheme's on-chain signature; plain = an ordinary ERC-20 transfer() from the payer's own wallet; other = anything else (facilitator batch, smart-wallet execute, bridge — not classified). USDC arriving at an address is not x402 revenue; this is how to tell. Sample-based: when plain exceeds eip3009, treat the 30d dollar figures as gross inflow, not x402. Whole-network view: /state/the-ledger. The boundary this doesn't cross: endpoint identity vs. operator identity. Everything above verifies behavior at a URL — correct 402s, a live sample, a stable payment destination. None of it verifies who is actually running the software answering that URL today. If a domain's infrastructure is compromised and the new operator leaves pay_to untouched and returns well-formed, plausible-looking responses, every check here can pass — because the attacker controls what gets returned, including through sample_query. This is a structural limit of behavior-based verification, true of any probe-based system, not a gap specific to one check. Closing it would require verifying who controls a domain over time, a different and much larger problem than a directory, and not one nohumans is building toward. Treat 'verified' as "this URL currently behaves like a correctly-configured x402 endpoint," never as "the entity operating it today is who first registered it." x402_version (1, 2, or null): which protocol version the endpoint's own 402 challenge actually used, last time it was probed — null if never probed yet. Some x402 clients (including the widely-used x402-fetch v1 reference client) only read payment terms from the response body and see nothing from a v2 'header' challenge — check this before assuming a v2 listing is unreachable. header_bytes (integer or null, on GET /v1/listings/:id and /v1/resolve): size of the endpoint's whole response header block on the last probe. Node's built-in fetch (undici) rejects a response whose headers exceed roughly 16 KB, throwing UND_ERR_HEADERS_OVERFLOW with no status code — the call just fails. curl, Go, browsers and Cloudflare Workers read far more and are unaffected. A high value is not a defect: as of 2026-08 the largest observed is about 14 KB and every such listing is reachable. Relevant only if you are calling from a Node stack. See the observed object on GET /v1/listings/:id for the full detail (challenge_transport, scheme, network). last_probed_at (unix seconds, or null if never probed): when this listing was last actually checked, regardless of pass or fail — distinct from score, which is a rolling average and can't tell you how current it is on its own. Note this can look counterintuitive: probing is tiered by need, so a long-stable verified listing is deliberately checked less often than a new or recovering one, and can show an older last_probed_at than a newer listing precisely because it's needed less frequent re-checking, not because it's being watched less carefully. status_changed_at (unix seconds): when the CURRENT status actually started — not the last time anything about the listing was edited. A listing edited yesterday but verified for three weeks still shows three weeks here; status_changed_at only moves on a real transition (probe-driven, admin, or auto-delist), never on a plain PATCH. Use this to tell "just recovered, worth a closer look" from "stable for weeks" apart, even when two listings currently show the identical status and score. GET /v1/listings/:id/history — the full transition log for one listing: every real status change with its reason (probe_pass_streak, probe_fail_streak, probe_recovered, admin_delist, admin_restore, auto_delist_30d), newest first, capped at 50. status_changed_at above is the cheap summary for the common case; this is the actual audit trail for when it matters. category_expanded (bool, only present when true): the category filter you sent didn't exactly match anything, so it was retried as a q text term instead of returning zero results. Results are still relevant, just not via an exact category match — if you know the real category name, GET /v1/categories and use it next time for a stronger signal. p50_latency_ms, p95_latency_ms and p99_latency_ms are computed from the actual last-7-days distribution, refreshed periodically rather than on every probe, and are null until a listing has 5+ probes in that window. Until 2026-09-24 p50 was a running average; a listing keeps that older value until its first refresh after that date. Includes timeouts/failures in the sample deliberately: a probe that hit the timeout ceiling is exactly the tail-risk signal these exist to surface. If you have a latency budget, check p99, not p50 — a listing can look fine at the median and still blow your budget 1% of the time. ### GET /v1/listings/:id Full record for one listing, including request_schema and response_schema (JSON Schema) when provided, plus reputation detail (last_ok_at, consecutive_failures). ### GET /v1/listings/:id/history The full transition log for one listing: every real status change (probe-driven, admin, or auto-delist) with its reason, newest first, capped at 50. { listing_id, changes: [{ from_status, to_status, reason, changed_at }] }. status_changed_at on the listing/discover-result itself is the cheap summary for the common case; this is the full audit trail. Also includes an observed object: what the endpoint's own 402 challenge actually said, last time it was probed. Kept separate from the seller's declared fields above rather than merged into them, since the two can disagree and an agent should be able to see that. null if the listing hasn't been probed yet. checked_at unix timestamp of the last successful read x402_version 1 or 2 accepts_index which option (0-based, challenge order) these terms come from: the cheapest. null on rows recorded before 2026-09-29 that offered more than one extra the option's extra object as the challenge sent it (since 2026-09-29; null before, or when over 2,000 characters, then extra_too_large: true) challenge_transport 'body' | 'header'. v1 clients (including the x402-fetch reference client) only read the body and see nothing from a 'header' challenge — check this before assuming a listing is unreachable. network, asset, pay_to, amount_atomic, amount_usd payment terms as actually advertised right now eip712_domain { name, version } read from the challenge, or null. Must match the token contract's on-chain name(), or every payment fails with invalid_exact_evm_token_name_mismatch. price_stable_since unix timestamp; moves only when amount_atomic actually changes, so it reads as "stable since", not "last probed". price_matches_listing bool, or null if unknown. True if the seller's declared price_amount is within 2% of amount_usd. payto_stable_since unix timestamp; same semantics as price_stable_since, for pay_to. A pay_to change on a previously-stable listing can be a legitimate rotation or a takeover — this directory reports the change, it does not judge it. ### GET /v1/listings Enumerate the catalog — not ranked search, use /v1/discover for that. Stable order (created_at, then id), so paging is safe while statuses change underneath. Params: limit (default 50, max 200), offset, status (verified|unverified|failing|delisted|all; defaults to the three active states). Returns { total, count, limit, offset, next_offset, results } — next_offset is null on the last page. Mirroring the whole catalog is a supported use; the data is CC-BY-4.0. ### POST /v1/listings Submission fee: Submitting is free for the first 5 listings per registered domain (api.example.com and www.example.com both count as example.com; on shared hosts such as vercel.app or workers.dev, each app's or account's own subdomain counts as its domain). Each further new listing costs $0.25 USDC on Base (since 2026-09-28; $0.50 before), paid over x402 on the same POST: over the allowance, an unpaid POST answers 402 with the terms, and the paid retry returns 201. The submission is validated before any charge, so a rejected submission is never charged. Edits, claims, an endpoint that is already listed, and re-listing an endpoint that was listed before are free. Listings already in the directory count toward the five and never pay. The fee buys the entry, never a status, a score or a place in the order. Since 2026-09-25. The 201 body carries submission_allowance { registrable_domain, free_per_domain, used_before, fee }. Submit a listing. JSON body, required fields: name, description, endpoint_url (https only, publicly resolvable), category, price_amount. Optional: price_currency, chains, request_schema, response_schema, sample_query, submitter_email, facilitator_url. facilitator_url is self-declared, not verified: the 402 challenge never states which facilitator a seller's server actually settles through, so there is nothing to probe. Treat it as a claim, same trust level as submitter_email — useful for debugging a failed payment, not a reliability signal. Categories are dot-namespaced. Reuse an existing one where it fits (GET /v1/categories for the live list) rather than inventing a variant spelling — an unmatched category still works via text-search fallback at query time (see category_expanded under GET /v1/discover above), but an exact match is a stronger signal and costs nothing extra to get right at submission time. sample_query must be a plain GET URL — a URL string only, no method prefix (not "POST https://..."), no request body, no JSON object. If your free preview requires a POST or a request body, omit sample_query for now. sample_query must be a genuinely free preview route that returns 200 + JSON with NO payment required — NOT the paid endpoint_url again. If there is no free preview, omit sample_query entirely; the prober will verify the paid endpoint's 402 handshake directly, which is sufficient and is how most listings here are verified. Setting sample_query equal to endpoint_url is rejected at submission (it always answers 402, never the 200 a preview check expects, and would fail every probe permanently). New listings start unverified and are prioritized in the probe queue — unverified and failing listings are checked more often than long-stable verified ones: a new submission is probed on every probe run (every 2 minutes) until its tenth counted probe, not just its first check. Earning 'verified' needs 3+ probes, no failure streak, and a score above 0.8. The score starts at the first counted probe's result and moves 10% toward each later one, so a new listing whose first probe passes needs three clean probes (typically minutes), and one whose score starts at zero needs about sixteen — not a fixed guarantee. The paid endpoint must answer unpaid requests with HTTP 402 (standard x402 behavior). endpoint_url must be a single, concrete, publicly resolvable URL — not a route pattern. If your real endpoint takes a parameter (e.g. a country or symbol), pick ONE representative value for the listing (https://api.example.com/v1/price/EUR-USD, not .../v1/price/:pair) UNLESS your x402 payment check runs before route/parameter matching, so a literal ":pair" in the URL still triggers a clean 402 — verify this yourself first with a plain unpaid curl to the literal pattern URL before submitting it that way. When in doubt, use one concrete value; it always works. Worked example — WITH a free preview: POST https://api.nohumans.directory/v1/listings Content-Type: application/json { "name": "EUR/TRY spot rates", "description": "Real-time FX rates, 500ms freshness", "endpoint_url": "https://fx.example.com/v1/rate?pair=EUR-TRY", "category": "data.fx", "price_amount": 0.0005, "price_currency": "USDC", "chains": ["base"], "sample_query": "https://fx.example.com/v1/rate/preview?pair=EUR-TRY", "submitter_email": "ops@example.com" } Note sample_query is a DIFFERENT, genuinely free route — never the same URL as endpoint_url. Worked example — WITHOUT a free preview (the common case; omit sample_query entirely rather than guessing or reusing endpoint_url): { "name": "EUR/TRY spot rates", "description": "Real-time FX rates, 500ms freshness", "endpoint_url": "https://fx.example.com/v1/rate?pair=EUR-TRY", "category": "data.fx", "price_amount": 0.0005, "price_currency": "USDC", "chains": ["base"] } Response (201): { "id": "abc123def456", "claim_token": "<64-hex>", "status": "unverified", "note": "..." } SAVE claim_token — it is your private edit key, shown only once. After submitting: GET /v1/listings/{id} anytime to check verification progress (status, score, probe_count, consecutive_failures). Verification needs 3+ consecutive passing probes AND a recency-weighted score above 0.8 (the score starts at the first counted probe's result and moves 10% toward each later one: three clean probes from a passing first probe, about sixteen from zero) if the endpoint answers unpaid requests with a clean 402. Common rejection (400), so you know what NOT to send: { "endpoint_url": "https://api.example.com/x", "sample_query": "https://api.example.com/x", ... } → { "error": "sample_query must not equal endpoint_url — omit sample_query entirely if there is no free preview" } ### PATCH /v1/listings/:id Edit a listing without resetting its verification history. Auth: send the claim_token from submission in the 'x-claim-token' header. Editable: name, description, category, price_amount, price_currency, chains, request_schema, response_schema, sample_query, submitter_email. endpoint_url is immutable (delist + resubmit to change it). ### DELETE /v1/listings/:id Self-serve delist. Same auth as PATCH (x-claim-token header). Soft delete: the listing leaves discovery immediately; probe and verification history are retained. Status change is recorded as 'self_delisted'. ### GET /v1/listings/:id/claim, POST /v1/listings/:id/claim/challenge, POST /v1/listings/:id/claim For any listing not yet claimed, whether hand-indexed or self-submitted, and for recovering a lost edit key. GET is read-only: it explains the flow and issues nothing (since 2026-08-30 — it used to mint a token, and crawlers following the link were rotating sellers' keys; see the 2026-08-29 corrections). POST .../claim/challenge returns a one-time challenge token, valid 24h; prove control of the endpoint by serving it at /.well-known/nohumans-claim or as an 'x-nohumans-claim' response header, then POST .../claim with {"email": "..."} to take ownership and receive a private edit key, shown once. A challenge is never a credential: requesting one changes nothing about an existing edit key. Submitting a listing already returns a claim_token once; this flow is how you recover if that value was lost. This proves control of the domain right now, not identity of whoever originally built the service — if a domain lapses or changes hands, whoever controls it today can claim the listing and inherit whatever reputation history it already has. Same boundary as everywhere else here: verification is behavioral, not identity-based. ### POST /v1/reports Report whether a listing delivered as expected, PROVEN by an on-chain payment AND a signature from the wallet that made it — not an honor-system claim. Body: { listing_id, ok, tx_hash, payer_signature, detail? }. tx_hash must be a real payment to the listing's endpoint on Base: the receipt is checked server-side for an ERC-20 Transfer on an accepted asset to the listing's live payTo. The Transfer log's sender is the payer (in x402's EIP-3009 flow the transaction sender is the facilitator, never the payer). payer_signature is an EIP-191 personal_sign over the canonical report message, and must recover to that payer — tx hashes are public, so without the signature anyone could report on payments they never made. Canonical message v1 (newline-separated, no trailing newline): nohumans.directory report v1 listing_id: tx_hash: <0x...lowercase> ok: POST without a valid signature and the 400 echoes the exact message_to_sign for your request — the API teaches the format. Further gates: the payment must be at least 90% of the listing's observed live price (dust can't mint a "distinct payer"); the tx must be no older than 30 days and must postdate the listing; one report per transaction; one voice per payer (your latest verified report supersedes earlier ones — N payments are not N votes). Reports affect ranking only once 3+ distinct payers have reported (25% weight alongside the 75% probe-based score) — below that floor a single report can't move a listing, however loud. This is the answer-quality signal probing alone can't provide: liveness and 402-conformance are checkable from outside, "did I get what I paid for" isn't, without someone who actually paid saying so. Full rationale, coverage limits, and what we do NOT verify: https://api.nohumans.directory/methodology ### GET /state, /state/paid-verification, /state/the-400-you-paid-for, /state/week-2026-10-07, /state/week-2026-09-30, /state/week-2026-09-23, /state/week-2026-09-16, /state/week-2026-09-02, /state/week-2026-09-09 State of the network: dated, citable reports measured by this directory's own instruments. First report (2026-08-25): a $5.40, 1,333-purchase paid-delivery census of 550 x402 endpoints — 332 of 481 payment-requiring endpoints delivered; 69 advertise a price and never charge; 52 settled payment on-chain then rejected the request; zero declare a checkable response schema. Wave 5 addendum (2026-08-26): 359 endpoints never previously purchased from, $0.41, 140 delivered — the all-purchases delivery rate fell 69.0% to 61.5% because this slice is the cheap, previously unmeasured tail, not because the network changed; 99 of the 359 settle payment and then reject the request with a 400. Correction (2026-08-27): the census's "zero declare a schema" figure measured our submission form — an unpaid census of all 1,675 active listings found 82% carry machine-readable metadata in-band (extensions.bazaar in the 402 challenge itself); 463 declare a field-level response schema; and 97 of wave 5's 99 paid-then-400s had declared the very parameters our buyer omitted (figures amended same day after fixing a 4KB header-truncation bug in our own collector; both corpora retained). A same-day chain audit further found most "settled payment then rejected" verdicts never settled: the scout's non-200 path recorded an attached authorization, not moved money — wave 5's 99 such calls cost $0.0045 (3 settled), and 241 of the census's 405 4xx attempts are chain-proven unsettled. Second report (2026-08-28): The 400 you didn't pay for — the corrected anatomy of the paid-then-rejected failure class (97/99 declared their contract in-band; 96/99 never settled), with the 99-endpoint pinned list served as JSON. Each report has a machine-readable JSON twin (waves array included) and is CC-BY-4.0. ### GET /v1/stats Public stats: { listings_total, hosts_total, verified, probes_24h, probe_pass_rate_24h, avg_probe_gap_min }. A listing is one priced ROUTE, not a host: several routes commonly share an origin, so listings_total runs about 3x hosts_total. If you are comparing this index against a host-level census, compare hosts_total. listings_total counts active listings only (delisted excluded), and only those probed at least once — submission is public and creates a row instantly as 'unverified', so a flood of just-submitted junk can't inflate this number before the probe loop has actually looked at any of it. A genuine new submission still counts within its first probe cycle, typically minutes. ### GET /l/:id Human-readable listing page: probe history, reliability stats, badge embed. ### GET /badge/:id.svg Embeddable status shield for a listing (verified / unverified / failing). Sellers: embed it in your README linking to your /l/:id page. ### GET /v1/demand What agents search this directory for. The search terms themselves, verbatim, with counts of searches and distinct client IPs — no top-N cap, every term that any client asked, however many. 30-day window, ending a week behind live while the paid tier is on sale (a day when it is not; delay_hours and window_ends_at in the response say which). Rules, all stated at /privacy (dates and amendments there, not repeated here): a term containing a URL, hostname, wallet address or email address is never published (it names a party rather than describing a need); any term can be withheld by hand, on request or on our own reading that it names a party rather than describing a need, and the count of such removals is published; sellers searching their own listings are excluded and counted separately. What the rules removed is reported in 'withheld' rather than silently dropped. The window begins at the policy date and is complete once thirty days plus the delay have passed — 'covered_days' and 'coverage_note' say how much of it is real yet. It reports what was ASKED, not what is missing: whether existing listings serve a term adequately is the reader's judgement. Paging: ?limit=&offset= returns one page of top_needs with terms_total and next_offset; without them the whole feed is returned (first page only once it outgrows 5 MB, with the same paging fields). Paid tier: GET /v1/demand/clusters, the current window with queries grouped by meaning rather than exact wording, rebuilt every 15 minutes (generated_at). $0.25 USDC on Base over x402, on sale since 2026-09-13. Same protections as the free tier; the clustering and the currency are what the money buys. ### GET /integrate Copy-paste pre-spend snippets: the /v1/resolve check written for @x402/fetch (v2), x402-fetch and x402-axios (v1), Python, curl, and MCP clients. Three lines in each case. Human-readable page, but agents may find it useful too. ### GET /v1/listings/:id/verdict (paid: $0.005 USDC on Base, x402 v2) One of 5 paid routes (/v1/listings/:id/verdict, /v1/listings/:id/purchases, /v1/listings/:id/verify-now, /v1/demand/clusters, /v1/demand/report); everything else on this directory is free, except submitting more than 5 listings per registered domain (see POST /v1/listings). The unpaid call answers 402 with the terms in both the payment-required header and the body; pay with any x402 v2 client. Returns { verdict: pay|caution|avoid, reasons[], probe, payto, onchain_30d, paid_verification, price } — the free record folded into one answer by the rule at /methodology#verdict. 'caution' on a verified listing is normal (e.g. we have not bought from it yet). Not needed for cheap or familiar listings: /v1/listings/:id has the same facts. Since 2026-09-29 it also carries 'verification': the evidence object in the x402 working group's draft verifier schema (verdict true|false|inconclusive about the payment terms, reason code, evidence level, observed_at/checked_at, digest, accepts_index, and, when issued, a signed attestation). Our pay|caution|avoid is the recommendation that cites it. Mapping: /methodology#wg-verification. ### GET /v1/attestations/:id The signed record behind a verdict's verification.attestation.record_url: a compact JWS (EdDSA, key at /.well-known/jwks.json) over the verification object, the resource and verifier domains, and valid_until. Free. ### GET /v1/listings/:id/purchases (paid: $0.01 USDC on Base, x402 v2) The series the verdict is a rule over: every real purchase we have made of the listing, oldest first — outcome, live quote vs listed price, settlement tx, JSON/schema validity, freshness, normalised body hash — and the consecutive-pair deltas: delivery held/regressed/recovered, price held/moved (with quote_delta_usdc), body same/changed/no_hash. Nobody can recompute this from public data; the purchases are ours. Rule: /methodology#purchases. ### POST /v1/listings/:id/verify-now?plan=single|pack (paid, x402 v2, seller-only) Paid verification, sold only to the listing's owner. Two plans, both for listings quoting <= $0.50/call: single = one real purchase within 24 hours, $2 USDC on Base; pack = three real purchases inside 30 days, first within 24 hours, timing ours, $5. Above $0.50/call: not offered (400), write to hello@nohumans.directory. GET or POST without payment answers the 402 so the price can be read by anyone; the PAID request must carry the seller's claim token in x-claim-token (401 otherwise) — we do not sell purchases against a listing to anyone but its owner. Each purchase is graded exactly as a wave and published on the record whatever it finds: settlement tx, delivery outcome, failure reason, and the paid-depth rung (paid_verified -> 2x -> held -> Nwk, or failed_rebuy if the endpoint stops delivering). What money buys: WHEN. What it never buys: the outcome, the rung, status, score, verdict, or rank. A failure caused by our own client does not count and is re-run. One open plan per listing at a time (429 with progress). Fulfilment is manual in this phase; runs happen on weekdays. Rule: /methodology#verify-now. ### GET /v1/resolve?url= Look up a specific endpoint URL you already hold (from another catalog, a prompt, anywhere) and get this directory's verdict before paying. Returns match 'active' with the full listing record (same shape as /v1/listings/:id), match 'delisted' if it was listed here and later removed (treat as a warning), or 404 with match 'unknown' if never listed — absence is not a verdict, it has simply never been checked here. Include the query string exactly as held; parameterized listings bake params into the URL. Trailing slashes and http/https differences are tolerated. ### POST /mcp MCP server (Streamable HTTP transport, stateless). Tools: - find_paid_service(query?, category?, max_price?, min_score?, limit?) → ranked discovery, same data as /v1/discover - get_service_details(id) → full listing record, same data as /v1/listings/:id - resolve_endpoint(url) → URL -> verdict, same data as /v1/resolve; use when you hold a URL but no listing id - what_agents_are_asking_for() → the aggregate demand feed, same data as /v1/demand: what agents searched for here, for a seller deciding what to build or list If your framework speaks MCP, prefer this over raw HTTP. ### GET /stats Paid-verification statistics: how many endpoints we have purchased from, how many delivered, and the full outcome breakdown by failure reason — including the failures caused by our own client. Published with the SQL and the denominator so the pass rate can be recomputed rather than trusted. Every figure also available as JSON at /v1/stats. ### GET /sellers For API operators: how listing, probing, and paid verification work from the seller side — failure taxonomy, badges, claiming, contact. ### GET /.well-known/agent-card.json A2A AgentCard for this directory (also at /.well-known/agent.json for legacy clients). JWS-signed (Ed25519); verify against /.well-known/jwks.json. States plainly that this is a registry, not an agent: it performs no tasks and executes no payments. Skills mirror the three MCP tools. ### GET /.well-known/x402 This directory's own x402 discovery manifest (service description, MCP access, REST index). We serve the same convention we index; the .json spelling is also served as an alias. ## Notes - All verification probes originate from this service's infrastructure. - Ranking is verified-first, then reputation score, then price. Ranking is never sold. - Contact: hello@nohumans.directory ### Scout address Paid verifications settle on-chain from 0x54E163e9B8eDDa194D83F46AdD921bfA5fc5f4E0 (nohumans-scout). A small USDC payment from that address is a verification event: point-in-time, occasional waves as resources allow, never purchasable, no action needed to receive it. ## Index Every surface of this service, absolute URLs: - https://api.nohumans.directory/v1/discover - https://api.nohumans.directory/v1/listings/:id - https://api.nohumans.directory/v1/resolve?url= - https://api.nohumans.directory/v1/attestations/:id - https://api.nohumans.directory/integrate - https://api.nohumans.directory/methodology - https://api.nohumans.directory/stats - https://api.nohumans.directory/.well-known/ai-catalog.json - https://api.nohumans.directory/terms - https://api.nohumans.directory/privacy - https://api.nohumans.directory/v1/listings (POST submit, PATCH edit) - https://api.nohumans.directory/v1/listings/:id/claim - https://api.nohumans.directory/v1/reports - https://api.nohumans.directory/v1/stats - https://api.nohumans.directory/v1/export - https://api.nohumans.directory/v1/changes - https://api.nohumans.directory/v1/categories - https://api.nohumans.directory/v1/demand - https://api.nohumans.directory/mcp - https://api.nohumans.directory/l/:id - https://api.nohumans.directory/badge/:id.svg - https://api.nohumans.directory/badge/:id/paid.svg - https://api.nohumans.directory/sellers - https://api.nohumans.directory/.well-known/x402 - https://api.nohumans.directory/state - https://api.nohumans.directory/openapi.json (OpenAPI 3.1; also at /.well-known/openapi.json) - https://api.nohumans.directory/state/paid-verification (+ .json twin) - https://api.nohumans.directory/state/the-ledger (+ .json twin) — 30d USDC payments on Base to every listed seller, x402-signed vs other - https://api.nohumans.directory/state/the-400-you-paid-for (+ .json twin; /wave5-endpoints.json pinned list) - https://api.nohumans.directory/state.json — every report: path, title, published date, JSON twin - https://api.nohumans.directory/methodology.json — the rules as data: probe tiers, status thresholds, pass-rate neutral classes, verdict thresholds, paid routes - https://api.nohumans.directory/state/week-2026-10-07 (+ .json twin) — weekly report #6: correction #26 (the outcome label paid_but_status_NNN was defined as payment accepted with USDC moved; of 651 records audited on chain, 127 had settled, 515 had not and 9 could not be checked), a payment-forwarding bug of ours fixed 2026-09-28, and a probe pass rate not yet explained. - https://api.nohumans.directory/state/week-2026-09-30 (+ .json twin) — weekly report #5: corrections #23-#25 (the paid demand feed read about half its stated 30-day window; both outside buyers refunded on chain), two bugs in our own buyer fixed and 26 records corrected by appended signed records, a regroup at 0.78 that briefly duplicated needs and a wrongly stated cause corrected, named lookups and scripted rotation listed apart from demand, the x402 WG draft verifier object and signed attestations on the paid verdict - https://api.nohumans.directory/state/week-2026-09-23 (+ .json twin) — weekly report #4: wave 11 (185 paid; 90 of 90 bought-before endpoints delivered again; 36 of 45 changed listings never reached payment; all 5 non-deliveries charged before validating input), 61 wrongly-failed records corrected by appended signed records, correction #22, a five-hour timeout window on 09-22 (~215 listings briefly failing; cause, updated 09-23: US East Coast networks, not our software), paging fix on /v1/listings, Paddock 178 of 182 decisive and 97 of 97 on second purchases - https://api.nohumans.directory/state/week-2026-09-16 (+ .json twin) — weekly report #3: wave 10 (168 re-bought, 11 of 20 changed-but-healthy listings still delivered), correction #19 (429 counted as failure for 17 days, 620 verdicts were our own request rate), every paid-verification outcome defined at /methodology#outcomes, sentinel payTo blocks verified, 30-day demand funnel - https://api.nohumans.directory/state/week-2026-09-09 (+ .json twin) — weekly report #2: 3,325 routes imported on evidence, corrections #15-#17, 1,020 paid-verified, 89.6% agreement with a chain-side pre-spend verdict on 376 paid calls (the 39 disagreements taxonomised), 30 spellings for the manifest network key, auto-relist 'one of twenty' - https://api.nohumans.directory/state/week-2026-09-02 (+ .json twin) — weekly report: 512 false 'failing' verdicts we caused, wave 6 (233 refused, first refund-on-failure), 31 POST-only listings misread as dead, corrections #10-#14 - https://api.nohumans.directory/.well-known/agent-card.json - https://api.nohumans.directory/.well-known/jwks.json - https://api.nohumans.directory/.well-known/mcp.json - https://api.nohumans.directory/agents.txt - https://api.nohumans.directory/llms.txt ## Licence Directory data (listings, statuses, scores, probe outcomes, paid-verification results) is CC BY 4.0: https://creativecommons.org/licenses/by/4.0/ Reuse freely; attribute "nohumans.directory" with a link to https://api.nohumans.directory. Bulk copies: https://api.nohumans.directory/v1/export (NDJSON) and https://api.nohumans.directory/v1/changes. A verdict describes behaviour observed at a point in time — if you republish one, say when it was observed.