{"openapi":"3.1.0","info":{"title":"BotsRated API","version":"0.4.0","description":"Signed checks of paid AI services, before your agent pays. Facts-only, receipt-backed measurements of x402 sellers, refreshed by automatic unpaid probes. Payments in USDC on Base mainnet. No grade or index is shown until a host has 3 paid test-buys on 3 different days.","x-guidance":"Use GET /v1/preflight?url= (free) first: it tells you whether a seller is covered and what its latest unpaid probe showed, with freshness. GET /v1/check?host= returns measured facts, paid test-buys with Base tx links, freshness and the last 5 receipts; GET /v1/report/{host} returns the full receipt history; GET /v1/best?task=&sort=reliability|price|latency&max_price= returns the top 3 covered providers for a task with matching routes. Free samples of each paid response: /v1/sample/check, /v1/sample/report, /v1/sample/best. Free need search: GET /v1/find?q= (top matches with a reason; uses 1 free daily check). Live totals: GET /v1/pulse. Measured rates: GET /v1/rates. Unknown hosts and bad input get a free 4xx (error.code, error.hint, charged:false) before any payment. Read freshness.stale before relying on a number. Remote MCP servers (Official MCP Registry) are covered too: preflight/check/report accept an MCP server host (type: mcp), and /v1/best adds mcp_results matched on tool names and descriptions.","contact":{"name":"BotsRated","url":"https://botsrated.com","email":"botsrated@gmail.com"},"termsOfService":"https://botsrated.com/terms","license":{"name":"MIT (client libraries, receipt format and verifier)","url":"https://github.com/botsrated/botsrated/blob/main/LICENSE"}},"x-pricing":{"currency":"USDC","network_note":"x402 v2, exact scheme, Base USDC; charged only on a 2xx answer","routes":{"preflight":{"url":"https://botsrated.com/v1/preflight?url=<host>","price_usd":"0","note":"free and unlimited (normal per-IP rate limits apply)"},"find":{"url":"https://botsrated.com/v1/find?q=<need>","price_usd":"0","note":"search; each call uses 1 of the 25 free daily checks (shared with /v1/check); 429 free_quota_used after that"},"check":{"url":"https://botsrated.com/v1/check?host=<host>","price_usd":"0.001","amount_atomic":"1000","free_per_day":25},"report":{"url":"https://botsrated.com/v1/report/<host>","price_usd":"0.002","amount_atomic":"2000","free_per_day":3},"best":{"url":"https://botsrated.com/v1/best?task=<keywords>","price_usd":"0.01","amount_atomic":"10000","free_per_day":0}},"free_quota":{"per":"client IP address (IPv6: /48 prefix)","day":"UTC","check":25,"report":3,"overall_daily_limit":15000,"overall_daily_limit_note":"free checks (including searches) and reports served per UTC day across all clients; after that every client gets the normal x402 402 until the next UTC day","exhausted":"normal x402 402 payment requirement","opt_out_header":"X-BotsRated-Free-Quota: off","response_fields":"free_quota {route, used, limit, remaining, resets_at}; headers X-BotsRated-Free-Quota-Remaining / -Limit / -Reset","not_applied_to":"blockrun.ai (the advertised example that x402 scanners probe); use /v1/sample/* for a free example"},"volume_tiers":"none yet (planned: automatic per-wallet monthly tiers; never prepaid balances or stored credit)","no_custody":"No accounts, prepaid balances, stored credit or refunds held. Each paid call is one x402 payment for that call.","badge":"Free and earned from measurements; never sold. Paying BotsRated never buys a better result, rank or badge. Paid alert plans make us check the hosts they cover more often; those checks use the same method and are published the same way.","free_data":{"dataset":"https://botsrated.com/dataset.json","signature":"https://botsrated.com/dataset.sig.json"},"pricing_page":"https://botsrated.com/pricing"},"servers":[{"url":"https://botsrated.com"}],"paths":{"/v1/preflight":{"get":{"operationId":"preflight","summary":"Latest unpaid probe of a seller (free, unlimited; per-IP rate limits)","security":[],"parameters":[{"name":"url","in":"query","required":true,"schema":{"type":"string"},"description":"Seller hostname or URL, e.g. blockrun.ai"},{"name":"resource","in":"query","required":false,"schema":{"type":"string","maxLength":500},"description":"Optional: resource.url from the 402 you are about to pay. The answer adds resource_check.host_matches (false = the resource is on a different host than the seller we checked)."}],"responses":{"200":{"description":"Latest stored probe with freshness. Counts below 5 are left out (small_counts explains). retry_safety: see its schema.","content":{"application/json":{"schema":{"type":"object","properties":{"retry_safety":{"type":"object","description":"Resent Payment Check status and the seller's own idempotency claim. The check is not currently running (it would only ever run on sellers who opt in), so replay_tested is always false.","properties":{"payment_identifier_advertised":{"type":["boolean","null"],"description":"The seller's 402 advertises x402's optional payment-identifier extension (an idempotency key that lets a service recognise a resent request). The seller's own claim; null = not seen yet."},"payment_identifier_required":{"type":["boolean","null"],"description":"The 402 marks payment-identifier as required."},"seen_at":{"type":["string","null"],"format":"date-time"},"receipt_id":{"type":["string","null"],"description":"Signed receipt the claim was read from."},"replay_tested":{"type":"boolean","description":"Whether our Resent Payment Check has run on this service. Always false: the check is not currently running, and it would only ever run on sellers who opt in."},"note":{"type":"string"}}},"valid_402":{"type":"boolean","description":"x402 only. false when there is no valid 402 on the latest check, or when its payTo (or an MPP recipient such as Tempo) is 0x000…000, which USDC can't be paid to. latest_probe.valid_402 (signed record) only means the 402 parsed with accept options."},"terms_consistent":{"type":["boolean","null"],"description":"x402 only. From the latest signed check; false when payto_zero_address is true."},"payto_zero":{"type":"boolean","description":"Same as payto_zero_address. When every payTo seen is 0x000…000, recent_window.valid_402 and valid_402_rate count those checks as invalid (0); parseable_402 keeps the raw counts."},"payto_zero_address":{"type":"boolean","description":"Present and true when the latest 402 lists payTo (or an MPP recipient) 0x000…000."},"discovery_response":{"type":"boolean","description":"With payto_zero_address: the seller's 402 body said discovery: true (it says the full payment request needs a purchase body)."},"price_note":{"type":"string","description":"With payto_zero_address: 'quoted in a discovery response' (or 'quoted with payTo 0x000…000')."},"warning":{"type":"string","description":"Neutral note, e.g. 'This unpaid 402 lists payTo 0x000…000. USDC can't be paid to that address. The seller says the full payment request needs a purchase body.'"},"servers":{"type":"array","description":"type mcp only","items":{"type":"object","properties":{"latest_receipt_url":{"type":["string","null"],"description":"null while price_check_in_progress"},"latest_receipt_withheld":{"type":"string","enum":["price_check_in_progress"]},"paid_tools_check":{"type":"object","description":"MCP servers only. Our unpaid price check: initialize + tools/list, at most 2 unpaid tools/call to tools that state a price; nothing is paid.","properties":{"paid":{"type":["boolean","null"],"description":"true = a payment request or stated tool price was seen; null = no payment signals recorded"},"checked_at":{"type":"string"},"method":{"type":"string"},"price_check_in_progress":{"type":"boolean","description":"true while our comparison of that server's stated and requested prices is not finished. Prices, the comparison and seller text are then left out, latest_receipt_url is null and /receipt/<id> returns a stub."},"declared_vs_quoted":{"type":"string","enum":["match","declared_only","observed_only","no_payment_request","not_comparable","not_checked","explained_by_seller","price_check_in_progress"],"description":"Stated price vs the payment request. price_check_in_progress replaces the old not_shown value."},"paid_tools":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"price_usd":{"type":["number","null"]},"price_source":{"type":"string"},"payment_request":{"type":["object","null"]},"declared_vs_quoted":{"type":"string","enum":["match","declared_only","observed_only","no_payment_request","not_comparable","not_checked","explained_by_seller","price_check_in_progress"]}}}}}}}}}}}}},"headers":{"X-BotsRated-Stale":{"description":"Present (value 1) only when the live read failed and this is the last good answer (at most 15 min old). JSON bodies then also carry stale, stale_built_at, stale_age_s, stale_note.","schema":{"type":"string"}},"X-BotsRated-Stale-Age":{"description":"Age of the stale copy in seconds (only with X-BotsRated-Stale).","schema":{"type":"integer"}},"X-BotsRated-Built-At":{"description":"When the stale copy was built, ISO 8601 UTC (only with X-BotsRated-Stale).","schema":{"type":"string"}},"X-BotsRated-Retries":{"description":"Present when a live answer came after internal retries (number of retries).","schema":{"type":"integer"}}}},"400":{"description":"Missing url","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not covered","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"temporarily_unavailable: the database did not answer in time and no recent last-good copy existed. Nothing charged. Retry after the Retry-After seconds (20). Treat as no answer, not as a pass.","headers":{"Retry-After":{"schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/find":{"get":{"operationId":"find","summary":"Top matches for a need, with a factual reason (free; uses 1 free daily check)","description":"Same filters as /v1/best (valid x402 challenge in the last 48 h; MCP: successful handshake in the last 48 h), trimmed: up to 3 x402 sellers in results[] and up to 3 MCP servers in mcp_results[], each with reason and page. Counts against the 25 free checks per client IP (IPv6 /48) per UTC day, shared with /v1/check; then 429 free_quota_used (use /v1/best via x402).","security":[],"parameters":[{"name":"q","in":"query","required":true,"schema":{"type":"string","maxLength":80},"description":"What you need, 1-4 keywords, e.g. weather"}],"x-free-quota":{"per_day":25,"per":"client IP (IPv6 /48), UTC day","shared_with":"/v1/check"},"responses":{"200":{"description":"Matches","content":{"application/json":{"schema":{"type":"object","properties":{"query":{"type":"string"},"terms":{"type":"array","items":{"type":"string"}},"results":{"type":"array","items":{"type":"object","properties":{"type":{"type":"string","const":"x402"},"host":{"type":"string"},"category":{"type":"string"},"description":{"type":"string"},"reason":{"type":"string"},"latency_p50_ms":{"type":["integer","null"]},"quoted_price_usd":{"type":["number","null"]},"recent":{"type":"string"},"page":{"type":"string"}}}},"mcp_results":{"type":"array","items":{"type":"object"}},"free_quota":{"type":"object"},"upgrade":{"type":"object"},"charged":{"type":"boolean","const":false}},"required":["results","mcp_results"]}}}},"400":{"description":"Missing query, or longer than 80 characters (free, does not use a free check)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Free daily quota used","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/pulse":{"get":{"operationId":"pulse","summary":"Live totals across everything watched (free, cached 60 s)","description":"Totals only, never names a seller: paid services and MCP servers watched, valid in the last 24 h, down or failed in the last 7 days (among those that worked in that window), quoted price changed today vs yesterday (UTC), last probe time. freshness: measured from the fast check loop over the last 24 h (full_24h is false until 24 h of data exist): fast-tier host count, p50 and p95 time between checks per tier, change-to-alert-job latency, and minutes since the last check across all live hosts (null when there is no data yet).","security":[],"responses":{"200":{"description":"Totals","content":{"application/json":{"schema":{"type":"object"}}}},"429":{"description":"Too many requests from this client (per-IP limit). Retry after the Retry-After seconds.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/rates":{"get":{"operationId":"rates","summary":"Measured large-sample rates: offline, payTo change, price vs listing (free, cached up to 5 min; built_at = when computed)","description":"Over our most recent completed UTC days: offline share of test calls, payTo-change share and price-vs-listing share of valid payment requests on main routes, each with its sample size, number of services and the publication rule (a rate is null below the minimum sample). Also the median quoted price. /v1/savings-rates is an alias.","security":[],"responses":{"200":{"description":"Rates","content":{"application/json":{"schema":{"type":"object"}}},"headers":{"X-BotsRated-Stale":{"description":"Present (value 1) only when the live read failed and this is the last good answer (at most 15 min old). JSON bodies then also carry stale, stale_built_at, stale_age_s, stale_note.","schema":{"type":"string"}},"X-BotsRated-Stale-Age":{"description":"Age of the stale copy in seconds (only with X-BotsRated-Stale).","schema":{"type":"integer"}},"X-BotsRated-Built-At":{"description":"When the stale copy was built, ISO 8601 UTC (only with X-BotsRated-Stale).","schema":{"type":"string"}},"X-BotsRated-Retries":{"description":"Present when a live answer came after internal retries (number of retries).","schema":{"type":"integer"}}}},"429":{"description":"Too many requests from this client (per-IP limit). Retry after the Retry-After seconds.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"temporarily_unavailable: the database did not answer in time and no recent last-good copy existed. Nothing charged. Retry after the Retry-After seconds (20). Treat as no answer, not as a pass.","headers":{"Retry-After":{"schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/savings-rates":{"get":{"operationId":"savingsRates","summary":"Alias of /v1/rates (free)","deprecated":true,"security":[],"responses":{"200":{"description":"Rates","content":{"application/json":{"schema":{"type":"object"}}}},"429":{"description":"Too many requests from this client (per-IP limit). Retry after the Retry-After seconds.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/coverage":{"get":{"operationId":"coverage","summary":"What is covered and how fresh (free)","security":[],"responses":{"200":{"description":"Counts by source, probe schedule, last probe run","content":{"application/json":{"schema":{"type":"object"}}},"headers":{"X-BotsRated-Stale":{"description":"Present (value 1) only when the live read failed and this is the last good answer (at most 15 min old). JSON bodies then also carry stale, stale_built_at, stale_age_s, stale_note.","schema":{"type":"string"}},"X-BotsRated-Stale-Age":{"description":"Age of the stale copy in seconds (only with X-BotsRated-Stale).","schema":{"type":"integer"}},"X-BotsRated-Built-At":{"description":"When the stale copy was built, ISO 8601 UTC (only with X-BotsRated-Stale).","schema":{"type":"string"}},"X-BotsRated-Retries":{"description":"Present when a live answer came after internal retries (number of retries).","schema":{"type":"integer"}}}},"429":{"description":"Too many requests from this client (per-IP limit). Retry after the Retry-After seconds.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"temporarily_unavailable: the database did not answer in time and no recent last-good copy existed. Nothing charged. Retry after the Retry-After seconds (20). Treat as no answer, not as a pass.","headers":{"Retry-After":{"schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/sample/{route}":{"get":{"operationId":"sample","summary":"Free sample of a paid response","security":[],"parameters":[{"name":"route","in":"path","required":true,"schema":{"type":"string","enum":["check","report","best"]}}],"responses":{"200":{"description":"Same shape as the paid route, for a fixed example, with sample: true","content":{"application/json":{"schema":{"type":"object"}}}},"404":{"description":"Unknown sample","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/check":{"get":{"operationId":"check","summary":"Measured facts for a host","tags":["Ratings"],"parameters":[{"name":"host","in":"query","required":true,"schema":{"type":"string","description":"Hostname of an x402 seller (e.g. blockrun.ai) or of a remote MCP server (then type: mcp, servers[] with handshake facts)","example":"blockrun.ai"},"example":"blockrun.ai"}],"x-payment-info":{"price":{"mode":"fixed","currency":"USD","amount":"0.001"},"protocols":[{"x402":{}}],"network":"eip155:8453"},"x-sample":"https://botsrated.com/v1/sample/check","x-free-quota":{"per_day":25,"per":"client IP (IPv6 /48), UTC day","then":"x402 402"},"responses":{"200":{"description":"Measured facts for the host","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HostFacts"}}}},"400":{"description":"Missing or invalid host (free, not charged)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Payment Required (x402 v2 challenge in the PAYMENT-REQUIRED header and body)"},"404":{"description":"Host not covered (free, returned before the 402; not charged)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"facilitator_unavailable: the payment facilitator did not answer in time, so no payment terms were built. Nothing charged. Retry after the Retry-After seconds (5).","headers":{"Retry-After":{"schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"x402Payment":[]},{"subscriptionToken":[]},{}]}},"/v1/report/{host}":{"get":{"operationId":"report","summary":"Full receipt history","tags":["Ratings"],"parameters":[{"name":"host","in":"path","required":true,"schema":{"type":"string","description":"Hostname of an x402 seller (e.g. blockrun.ai) or of a remote MCP server (30 days of mcp_probe receipts)","example":"blockrun.ai"},"example":"blockrun.ai"}],"x-payment-info":{"price":{"mode":"fixed","currency":"USD","amount":"0.002"},"protocols":[{"x402":{}}],"network":"eip155:8453"},"x-sample":"https://botsrated.com/v1/sample/report","x-free-quota":{"per_day":3,"per":"client IP (IPv6 /48), UTC day","then":"x402 402"},"responses":{"200":{"description":"Measured facts for the host","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HostFacts"}}}},"400":{"description":"Missing or invalid host (free, not charged)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Payment Required (x402 v2 challenge in the PAYMENT-REQUIRED header and body)"},"404":{"description":"Host not covered (free, returned before the 402; not charged)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"facilitator_unavailable: the payment facilitator did not answer in time, so no payment terms were built. Nothing charged. Retry after the Retry-After seconds (5).","headers":{"Retry-After":{"schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"x402Payment":[]},{"subscriptionToken":[]},{}]}},"/v1/best":{"get":{"operationId":"best","summary":"Best Pick: top 3 covered providers for a task","tags":["Ratings"],"parameters":[{"name":"task","in":"query","required":true,"schema":{"type":"string","description":"Task keywords, e.g. web search","example":"web search"},"example":"web search"},{"name":"sort","in":"query","schema":{"type":"string","enum":["reliability","price","latency"],"default":"reliability"}},{"name":"max_price","in":"query","schema":{"type":"number","minimum":0},"description":"Max last-quoted price per call in USD"},{"name":"type","in":"query","schema":{"type":"string","enum":["all","x402","mcp"],"default":"all"},"description":"all: x402 sellers in results[] plus remote MCP servers in mcp_results[] (matched on tool names and descriptions); x402 or mcp: only that kind"}],"x-payment-info":{"price":{"mode":"fixed","currency":"USD","amount":"0.01"},"protocols":[{"x402":{}}],"network":"eip155:8453"},"x-sample":"https://botsrated.com/v1/sample/best","responses":{"200":{"description":"Top 3 providers with matching routes, the numbers behind the order and receipts","content":{"application/json":{"schema":{"type":"object","properties":{"beta":{"type":"boolean"},"task":{"type":"string"},"sort":{"type":"string"},"ranking":{"type":"string"},"considered":{"type":"object"},"results":{"type":"array","items":{"type":"object"}}},"required":["results"]}}}},"400":{"description":"Invalid task, sort or max_price (free, not charged)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Payment Required"},"503":{"description":"facilitator_unavailable: the payment facilitator did not answer in time, so no payment terms were built. Nothing charged. Retry after the Retry-After seconds (5).","headers":{"Retry-After":{"schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"x402Payment":[]},{"subscriptionToken":[]},{}]}},"/receipt/{id}":{"get":{"operationId":"receipt","summary":"One receipt (free)","security":[],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","pattern":"^[0-9a-f]{20}$"}}],"responses":{"200":{"description":"Receipt","content":{"application/json":{"schema":{"type":"object"}}},"headers":{"X-BotsRated-Stale":{"description":"Present (value 1) only when the live read failed and this is the last good answer (at most 15 min old). JSON bodies then also carry stale, stale_built_at, stale_age_s, stale_note.","schema":{"type":"string"}},"X-BotsRated-Stale-Age":{"description":"Age of the stale copy in seconds (only with X-BotsRated-Stale).","schema":{"type":"integer"}},"X-BotsRated-Built-At":{"description":"When the stale copy was built, ISO 8601 UTC (only with X-BotsRated-Stale).","schema":{"type":"string"}},"X-BotsRated-Retries":{"description":"Present when a live answer came after internal retries (number of retries).","schema":{"type":"integer"}}}},"404":{"description":"Unknown receipt","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"temporarily_unavailable: the database did not answer in time and no recent last-good copy existed. Nothing charged. Retry after the Retry-After seconds (20). Treat as no answer, not as a pass.","headers":{"Retry-After":{"schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/plans":{"get":{"operationId":"plans","summary":"Seller-alert and data plans, rules, webhook signature format (free)","security":[],"tags":["Plans"],"responses":{"200":{"description":"Plans","content":{"application/json":{"schema":{"type":"object"}}}},"429":{"description":"Too many requests from this client (per-IP limit). Retry after the Retry-After seconds.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/alerts/subscribe":{"post":{"operationId":"alertsSubscribeFree","summary":"Free seller alerts for 1 host (daily signed webhook digest, 30 days)","description":"Free alerts allow up to 3 active free alert subscriptions per client (IP address), and up to 1,000 across all users.","security":[],"tags":["Plans"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscribeAlerts"}}}},"responses":{"201":{"description":"Active subscription and its bearer token (shown once)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscribeResult"}}}},"400":{"description":"Invalid host or webhook (webhook must echo the verification challenge)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Host not covered","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit, or the free alert limit: up to 3 active free alert subscriptions per client (IP address), and up to 1,000 across all users","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/subscribe/alerts-10":{"post":{"operationId":"subscribe_alerts_10","summary":"Seller alerts alerts-10: $9 per 30 days (one payment = one period, no auto-renewal)","description":"Up to 10 hosts; a signed webhook a few minutes after the check that sees a change (payTo, quoted price, valid 402 lost/regained, delisted/relisted, stale). Each host on the plan is checked every few minutes. The same bearer token also reads /v1/check and /v1/report for the hosts on the plan without per-call payment (60 requests/min): for hosts we have test-bought, that includes our own paid test-buy receipts with delivered, non_empty, schema_valid and, on newer receipts, stall. Most hosts have no paid test-buy yet, and delivery outcomes are read on request; they are not alert events. Body and webhook are validated before the 402; activation only after settlement.","tags":["Plans"],"x-payment-info":{"price":{"mode":"fixed","currency":"USD","amount":"9"},"protocols":[{"x402":{}}],"network":"eip155:8453"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscribeAlerts"}}}},"responses":{"200":{"description":"Active subscription and its bearer token (shown once)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscribeResult"}}}},"400":{"description":"Invalid body or webhook (free, before the 402)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Payment Required (x402 v2)"},"404":{"description":"Unknown plan or host not covered (free)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"facilitator_unavailable: the payment facilitator did not answer in time, so no payment terms were built. Nothing charged. Retry after the Retry-After seconds (5).","headers":{"Retry-After":{"schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"x402Payment":[]}]}},"/v1/subscribe/alerts-50":{"post":{"operationId":"subscribe_alerts_50","summary":"Seller alerts alerts-50: $29 per 30 days (one payment = one period, no auto-renewal)","description":"Up to 50 hosts; same events and timing as alerts-10 (payTo, quoted price, valid 402 lost/regained, delisted/relisted, stale). The same bearer token also reads /v1/check and /v1/report for the hosts on the plan without per-call payment (60 requests/min): for hosts we have test-bought, that includes our own paid test-buy receipts with delivered, non_empty, schema_valid and, on newer receipts, stall. Most hosts have no paid test-buy yet, and delivery outcomes are read on request; they are not alert events. Body and webhook are validated before the 402; activation only after settlement.","tags":["Plans"],"x-payment-info":{"price":{"mode":"fixed","currency":"USD","amount":"29"},"protocols":[{"x402":{}}],"network":"eip155:8453"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscribeAlerts"}}}},"responses":{"200":{"description":"Active subscription and its bearer token (shown once)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscribeResult"}}}},"400":{"description":"Invalid body or webhook (free, before the 402)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Payment Required (x402 v2)"},"404":{"description":"Unknown plan or host not covered (free)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"facilitator_unavailable: the payment facilitator did not answer in time, so no payment terms were built. Nothing charged. Retry after the Retry-After seconds (5).","headers":{"Retry-After":{"schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"x402Payment":[]}]}},"/v1/subscribe/data-starter":{"post":{"operationId":"subscribe_data_starter","summary":"Data plan data-starter: $49 per 30 days (one payment = one period, no auto-renewal)","description":"Bearer token: /v1/check, /v1/report and /v1/best without per-call payment for 30 days (fair use, 60 requests/min). Body and webhook are validated before the 402; activation only after settlement.","tags":["Plans"],"x-payment-info":{"price":{"mode":"fixed","currency":"USD","amount":"49"},"protocols":[{"x402":{}}],"network":"eip155:8453"},"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"Active subscription and its bearer token (shown once)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscribeResult"}}}},"400":{"description":"Invalid body or webhook (free, before the 402)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Payment Required (x402 v2)"},"404":{"description":"Unknown plan or host not covered (free)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"facilitator_unavailable: the payment facilitator did not answer in time, so no payment terms were built. Nothing charged. Retry after the Retry-After seconds (5).","headers":{"Retry-After":{"schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"x402Payment":[]}]}},"/v1/subscribe/botpulse-indie":{"post":{"operationId":"subscribe_botpulse_indie","summary":"BotPulse botpulse-indie: $5 per 30 days (one payment = one period, no auto-renewal)","description":"BotPulse digests (MCP, x402, Base/CDP, agent framework changes) pushed to 1 signed webhook (ed25519, key botsrated-botpulse-1) right after each Monday/Thursday digest is published, plus a bearer token for the full digest history (GET /v1/botpulse/history; the free feed shows only the latest 4 digests). 30 requests/min. Body and webhook are validated before the 402; activation only after settlement.","tags":["Plans"],"x-payment-info":{"price":{"mode":"fixed","currency":"USD","amount":"5"},"protocols":[{"x402":{}}],"network":"eip155:8453"},"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"webhook_urls":{"type":"array","maxItems":1,"items":{"type":"string","format":"uri"},"description":"One signed webhook (must echo the challenge)"}}}}}},"responses":{"200":{"description":"Active subscription and its bearer token (shown once)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscribeResult"}}}},"400":{"description":"Invalid body or webhook (free, before the 402)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Payment Required (x402 v2)"},"404":{"description":"Unknown plan or host not covered (free)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"facilitator_unavailable: the payment facilitator did not answer in time, so no payment terms were built. Nothing charged. Retry after the Retry-After seconds (5).","headers":{"Retry-After":{"schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"x402Payment":[]}]}},"/v1/subscribe/botpulse-business":{"post":{"operationId":"subscribe_botpulse_business","summary":"BotPulse botpulse-business: $49 per 30 days (one payment = one period, no auto-renewal)","description":"Everything in botpulse-indie, delivered to up to 5 endpoints: signed webhooks and/or Discord channel webhooks (posted as a formatted message, so your team channel gets each digest), plus the full digest history at 300 requests/min. Telegram: point a signed webhook at your own bot or relay. Body and webhook are validated before the 402; activation only after settlement.","tags":["Plans"],"x-payment-info":{"price":{"mode":"fixed","currency":"USD","amount":"49"},"protocols":[{"x402":{}}],"network":"eip155:8453"},"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"webhook_urls":{"type":"array","maxItems":5,"items":{"type":"string","format":"uri"},"description":"Signed webhooks (must echo the challenge) and/or Discord channel webhook URLs"}}}}}},"responses":{"200":{"description":"Active subscription and its bearer token (shown once)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscribeResult"}}}},"400":{"description":"Invalid body or webhook (free, before the 402)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Payment Required (x402 v2)"},"404":{"description":"Unknown plan or host not covered (free)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"facilitator_unavailable: the payment facilitator did not answer in time, so no payment terms were built. Nothing charged. Retry after the Retry-After seconds (5).","headers":{"Retry-After":{"schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"x402Payment":[]}]}},"/v1/subscribe/data-pro":{"post":{"operationId":"subscribe_data_pro","summary":"Data plan data-pro: $199 per 30 days (one payment = one period, no auto-renewal)","description":"Bearer token: /v1/check, /v1/report and /v1/best without per-call payment for 30 days (600 requests/min). Planned: signed change feed for all hosts. Body and webhook are validated before the 402; activation only after settlement.","tags":["Plans"],"x-payment-info":{"price":{"mode":"fixed","currency":"USD","amount":"199"},"protocols":[{"x402":{}}],"network":"eip155:8453"},"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"Active subscription and its bearer token (shown once)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscribeResult"}}}},"400":{"description":"Invalid body or webhook (free, before the 402)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Payment Required (x402 v2)"},"404":{"description":"Unknown plan or host not covered (free)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"facilitator_unavailable: the payment facilitator did not answer in time, so no payment terms were built. Nothing charged. Retry after the Retry-After seconds (5).","headers":{"Retry-After":{"schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"x402Payment":[]}]}},"/v1/subscription":{"get":{"operationId":"subscription","summary":"Subscription status (bearer token)","tags":["Plans"],"security":[{"subscriptionToken":[]}],"responses":{"200":{"description":"Subscription","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"Missing or unknown token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/subscription/cancel":{"post":{"operationId":"subscriptionCancel","summary":"Cancel (stops delivery; plan payments are final, see /terms for the fault exception)","tags":["Plans"],"security":[{"subscriptionToken":[]}],"responses":{"200":{"description":"Cancelled","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"Missing or unknown token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/subscription/update":{"post":{"operationId":"subscriptionUpdate","summary":"Change hosts or webhook of an active subscription","tags":["Plans"],"security":[{"subscriptionToken":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"hosts":{"type":"array","items":{"type":"string"}},"webhook_url":{"type":"string","format":"uri"}}}}}},"responses":{"200":{"description":"Updated","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"Invalid hosts or webhook","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or inactive token","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/sellers":{"get":{"operationId":"sellersPage","summary":"Browse covered sellers and MCP servers (HTML page)","tags":["Pages"],"security":[],"parameters":[{"name":"q","in":"query","schema":{"type":"string"}},{"name":"cat","in":"query","schema":{"type":"string"}},{"name":"type","in":"query","schema":{"type":"string","enum":["x402","mcp"]}},{"name":"status","in":"query","schema":{"type":"string","enum":["live","all"]}},{"name":"price","in":"query","schema":{"type":"string","enum":["lt001","001-01","gt01"]}},{"name":"page","in":"query","schema":{"type":"integer","minimum":1,"maximum":200}}],"responses":{"200":{"description":"HTML","content":{"text/html":{"schema":{"type":"string"}}}},"429":{"description":"Too many requests from this client (per-IP limit). Retry after the Retry-After seconds.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/s/{host}":{"get":{"operationId":"sellerPage","summary":"One seller or MCP server: status, price on the main route, payTo, test purchases, receipts, alternatives (HTML page)","tags":["Pages"],"security":[],"parameters":[{"name":"host","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"HTML","content":{"text/html":{"schema":{"type":"string"}}},"headers":{"X-BotsRated-Stale":{"description":"Present (value 1) only when the live read failed and this is the last good answer (at most 15 min old). JSON bodies then also carry stale, stale_built_at, stale_age_s, stale_note.","schema":{"type":"string"}},"X-BotsRated-Stale-Age":{"description":"Age of the stale copy in seconds (only with X-BotsRated-Stale).","schema":{"type":"integer"}},"X-BotsRated-Built-At":{"description":"When the stale copy was built, ISO 8601 UTC (only with X-BotsRated-Stale).","schema":{"type":"string"}},"X-BotsRated-Retries":{"description":"Present when a live answer came after internal retries (number of retries).","schema":{"type":"integer"}}}},"404":{"description":"Not covered (HTML)"},"503":{"description":"temporarily_unavailable: the database did not answer in time and no recent last-good copy existed. Nothing charged. Retry after the Retry-After seconds (20). Treat as no answer, not as a pass.","headers":{"Retry-After":{"schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/what-we-check":{"get":{"operationId":"whatWeCheckPage","summary":"What we check for, with the large-sample rates we measured (HTML page; /savings redirects here)","tags":["Pages"],"security":[],"responses":{"200":{"description":"HTML","content":{"text/html":{"schema":{"type":"string"}}}},"429":{"description":"Too many requests from this client (per-IP limit). Retry after the Retry-After seconds.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/leaderboard":{"get":{"operationId":"leaderboardPage","summary":"300 covered x402 sellers ordered by our own recent checks (HTML page)","tags":["Pages"],"security":[],"responses":{"200":{"description":"HTML","content":{"text/html":{"schema":{"type":"string"}}}},"429":{"description":"Too many requests from this client (per-IP limit). Retry after the Retry-After seconds.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/dispute":{"post":{"operationId":"dispute","summary":"Seller dispute / right of reply (free)","security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"host":{"type":"string"},"receipt_id":{"type":"string"},"contact":{"type":"string"},"statement":{"type":"string"}},"required":["host","statement"]}}}},"responses":{"202":{"description":"Dispute received"},"400":{"description":"Invalid body","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}},"components":{"securitySchemes":{"subscriptionToken":{"type":"http","scheme":"bearer","description":"Token from a subscribe response (brs_...). An active data-plan token also unlocks /v1/check, /v1/report and /v1/best without per-call payment. An active paid alerts token (alerts-10, alerts-50) unlocks /v1/check and /v1/report only for the hosts on that subscription (other hosts: 403 host_not_on_plan; /v1/best: 403), 60 requests/min."},"x402Payment":{"type":"apiKey","in":"header","name":"PAYMENT-SIGNATURE","description":"x402 v2 payment payload (base64), built by any x402 client from this route's 402 PAYMENT-REQUIRED answer. USDC on Base. X-PAYMENT (x402 v1) is accepted too."}},"schemas":{"Error":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"hint":{"type":"string"},"charged":{"type":"boolean","const":false}},"required":["code","message"]}}},"SubscribeAlerts":{"type":"object","properties":{"host":{"type":"string"},"hosts":{"type":"array","items":{"type":"string"}},"webhook_url":{"type":"string","format":"uri","description":"https on a public DNS name; must answer 2xx with the challenge from the verification POST"}},"required":["webhook_url"]},"SubscribeResult":{"type":"object","properties":{"token":{"type":"string"},"token_note":{"type":"string"},"state":{"type":"string"},"subscription":{"type":"object","properties":{"id":{"type":"string"},"plan":{"type":"string"},"state":{"type":"string"},"hosts":{"type":"array","items":{"type":"string"}},"starts_at":{"type":["string","null"]},"expires_at":{"type":["string","null"]},"payment_tx":{"type":["string","null"]},"tx_url":{"type":["string","null"]}}}}},"HostFacts":{"type":"object","required":["beta","host","measured","freshness"],"properties":{"beta":{"type":"boolean"},"served_at":{"type":"string","format":"date-time"},"host":{"type":"string"},"route_probed":{"type":"object"},"category":{"type":"string"},"description":{"type":["string","null"],"description":"Listing text from x402-list or 402index only; null when the service was found through the Coinbase CDP Bazaar, Agentic.Market or 402index's Bazaar entries (used only to find services)."},"listing":{"type":"object","description":"Listing terms from x402-list or 402index only. No directory usage counts (30-day calls or payers) are published; they were removed 2026-10-24.","properties":{"price_usd":{"type":["number","null"]},"amount_atomic":{"type":["string","null"]},"asset":{"type":["string","null"]},"network":{"type":["string","null"]},"payTo":{"type":["string","null"]},"source":{"type":["string","null"],"description":"x402-list, 402index or 402index-<feed>; null when the listing terms are not shown"},"listed_in":{"type":"array","items":{"type":"string"},"description":"Directories where we found the service (discovery only)"},"other_routes_listed":{"type":"integer"},"terms_shown":{"type":"boolean","description":"false when the listing came from a directory we use only to find services"},"note":{"type":"string"}}},"attribution":{"type":"string","description":"Present when a field comes from x402-list: \"Data: x402-list.com (CC BY 4.0), modified\""},"measured":{"type":"object"},"paid_tests":{"type":"object"},"index":{"type":["number","null"]},"index_label":{"type":"string"},"freshness":{"type":"object","properties":{"last_probe_at":{"type":["string","null"]},"age_seconds":{"type":["integer","null"]},"stale":{"type":"boolean"},"stale_after_seconds":{"type":"integer"}}},"receipts":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"ts":{"type":"string"},"status":{"type":["integer","null"]},"valid_402":{"type":"boolean"},"receipt_url":{"type":"string"},"tx_url":{"type":["string","null"]},"signature":{"type":"string"}}}},"paid_receipts":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"ts":{"type":"string"},"tx_hash":{"type":"string"},"tx_url":{"type":"string"},"charged_as_quoted":{"type":"boolean"},"delivered":{"type":"boolean"},"non_empty":{"type":"boolean"},"schema_valid":{"type":["boolean","null"]},"stall":{"type":"boolean","description":"true when our paid retry hit our client timeout (45 s) before the response finished; absent on receipts recorded before 2026-10-27 UTC"}}}}}}}}}