Every API here is available over the APIs.io API and to AI agents over MCP.
openapi: 3.2.0
info:
title: Sato Hub public X402 API
version: 1.1.0
summary: Read access to the onchain agent library, its change feed, and the Agent Passport registry.
description: 'Public reads need no key and no account; the projects and listings routes take a bearer key. A Sato API key is optional on every metered endpoint and only raises limits. What is free, what is paid (the plans are Sato Check Team and Platform & Data), every limit and the fee schedule are listed on the pricing page, and the same sheet is machine-readable at /api/pricing.json.
Pricing: https://satohub.ai/pricing
License: Catalog data CC-BY-4.0 — attribution: data by satohub.ai. Scores/liveness are informational signals, not safety or quality guarantees.
Scores and liveness are informational signals computed from public evidence. They are not safety ratings, audits, or claims about returns. `verification_status` distinguishes self-reported from independently checked; self-reported is never presented as verified.
Every shape this API returns is also published as a versioned JSON Schema (draft 2020-12) at https://satohub.ai/schemas — catalogue at https://satohub.ai/schemas/index.json. They are referenced from components.schemas below, and v1 is additive-only: a breaking change becomes v2 at a new URL. Validate with additional properties allowed.
The same data is available to agents over MCP (Streamable HTTP, JSON-RPC) at https://satohub.ai/api/mcp — documented at https://satohub.ai/mcp. That endpoint is not described here because it is not REST.
INTERPRETED ANSWERS. A route template sent literally (`{slug}`), an empty query or body, a parameter under another name (`?package=` for `?target=`) or another spelling of a chain (`8453`, `eth`, `bsc`) is answered with the closest honest thing instead of a bare 4xx, and always LABELLED: the body carries an `interpretation` object (`interpreted_as`, `requested`, `rule`, `note`; the same four keys are repeated at the top level when they cannot collide with the record''s own fields), and the response carries the header `X-Sato-Interpreted: ` (plus `Content-Location` when there is a canonical URL). An interpreted answer is never an exact match. Nothing that moves money is ever interpreted beyond a chain spelling: no amount, token, taker, recipient, deployer or slippage is defaulted, a missing chain is never assumed, a chain is never guessed from an address, and a generic network word (`mainnet`, `testnet`) is never read as a chain (the answer lists the candidates). Writes are never interpreted, and a receipt is never served for a template.'
contact:
name: Sato Hub
url: https://satohub.ai
x-guidance: 'Free: search and read the onchain-agent catalog (/api/export/index.json, /api/changes, /api/resolve) and use the MCP server at /api/mcp. Paid over x402 (USDC on Base, no account or key): GET /api/x402/history/{slug} for one listing''s daily Sato Score record, GET /api/x402/agent-economy for the weekly agent-economy series. Each paid read is priced per unit delivered (daily points or rows returned): the 402 states the exact amount, the unit, the quantity and the formula, which is also on /pricing. The Sato Score measures how open, active and verifiable a project is; it is not a safety or returns grade.'
x-status:
page: https://satohub.ai/status/sato-hub
json: https://satohub.ai/api/status.json
feed: https://satohub.ai/status/feed.xml
note: Success ratios and latencies of Sato Hub's own hourly checks. Not a service-level agreement.
license:
name: CC-BY-4.0
url: https://creativecommons.org/licenses/by/4.0/
servers:
- url: https://satohub.ai
security: []
tags:
- name: X402
paths:
/api/export/x402-verified.json:
get:
tags:
- X402
operationId: getX402Verified
summary: x402 endpoints probed for a real HTTP 402, per URL
description: 'The rows /numbers/x402-endpoints-that-answer and /x402/verified are built from: every URL probed daily for listings tagged x402, each with declared_as (payment_resource = named as paid in the project''s own /.well-known/x402; mcp_endpoint; listing_page = homepage, docs, repo or article), the observed outcome, HTTP status, where the payment payload was read, and the declared network. No payment is sent; null means unknown, never 0. The payload carries its own rules array.'
parameters: []
responses:
'200':
description: Per-URL states plus the funnel by kind.
content:
application/json:
schema:
type: object
properties:
checked_at:
type:
- string
- 'null'
window_days:
type: integer
rules:
type: array
items:
type: string
funnel:
type: object
endpoints:
type: array
items:
type: object
/api/x402/history/{slug}:
get:
tags:
- X402
operationId: getPaidScoreHistory
summary: Daily Sato Score history for one listing (x402, paid)
description: 'Daily Sato Score history for one Sato Hub listing: score, tier components, GitHub stars, status and verification state per day, with the dates the score moved (genuine changes vs our own method revisions marked). Captured daily since 2026-06-12; not reconstructable. The current catalog and the daily score line stay free. Priced per daily point returned: $0.005 for up to 90 days, +$0.001 per day beyond. Price: $0.005 for up to 90 daily points, plus $0.001 per daily point beyond 90: price = $0.005 if d <= 90, else $0.005 + $0.001 x (d - 90), where d is the number of daily points the response returns. Rounded up to the USDC base unit. Unknown, deprecated or unscored slugs are answered 404 (with candidate slugs and their URLs) before any payment is requested, so nobody pays for nothing. Calling the template itself ({slug}, :slug) answers 402 with this route''s real challenge and an explanation, and a payment sent to it is never settled. A near-miss slug that plainly means a listing is read as it, labelled `resolved_from` / `interpreted_as`, and the challenge names the canonical URL. Example: https://satohub.ai/api/x402/history/coinbase-agentkit'
x-example-url: https://satohub.ai/api/x402/history/coinbase-agentkit
x-payment-info:
price:
mode: dynamic
currency: USD
min: '0.005'
max: '0.315'
protocols:
- x402: {}
parameters:
- name: slug
in: path
required: true
schema:
type: string
example: coinbase-agentkit
description: A listing slug from the free catalog at /api/export/index.json.
- name: days
in: query
required: false
schema:
type: integer
minimum: 1
maximum: 400
example: 90
description: The most daily points to return. You pay for the points the response contains, not the number asked for.
responses:
'200':
description: The per-day record for the listing. When the slug was a near-miss, the body carries `resolved_from`, `interpreted_as` and `note`.
content:
application/json:
schema:
type: object
'402':
description: 'Payment Required — an x402 v2 PAYMENT-REQUIRED challenge (USDC) whose `amount` is the exact price of THIS request, with `unit`, `unit_price`, `quantity` and `formula` in the body. Also answered, with `error: payment_invalid` and the facilitator''s reason, when a presented payment is rejected, and with `error: price_changed` and a fresh quote when the data changed after you were quoted (never charged). It lists one `accepts` entry per network (eip155:8453, solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp), each the same price in USDC; pay on any one.'
'404':
description: '`not_found` / `ambiguous_slug` — the body lists up to 5 candidate slugs with their exact URLs, where to find slugs and an example; or an unscored listing, or no history yet. A 404 never asks for payment and is never charged.'
'422':
description: '`template_not_callable` — a payment was sent to the route template. It was not settled and nothing was charged.'
'502':
description: '`facilitator_error` — the payment facilitator could not be reached or failed; nothing was charged, retry later.'
/api/x402/agent-economy:
get:
tags:
- X402
operationId: getPaidAgentEconomySeries
summary: Weekly agent-economy series (x402, paid)
description: 'The weekly agent-economy series behind Sato Hub''s free current-week counts: one row per venue, chain, stage and week, measured from public chain reads. Rows are never summed across venues, chains or stages; null means unknown, never zero. The current week stays free at /api/export/adoption.json. Priced per row returned: $0.0001 per row, minimum $0.005. Price: $0.0001 per row returned, minimum $0.005: price = max($0.005, $0.0001 x r), where r is the number of rows the response returns. Rounded up to the USDC base unit.'
x-payment-info:
price:
mode: dynamic
currency: USD
min: '0.005'
max: '5.000'
protocols:
- x402: {}
parameters:
- name: weeks
in: query
required: false
schema:
type: integer
minimum: 1
example: 12
description: How many weekly points to return (bounded server-side). More weeks, more rows, a higher price.
- name: venue
in: query
required: false
schema:
type: string
description: Only this venue. Fewer rows, a lower price.
- name: chain
in: query
required: false
schema:
type: string
description: Only this chain.
- name: stage
in: query
required: false
schema:
type: string
description: Only this lifecycle stage.
responses:
'200':
description: The weekly series.
content:
application/json:
schema:
type: object
'402':
description: 'Payment Required — an x402 v2 PAYMENT-REQUIRED challenge (USDC) whose `amount` is the exact price of THIS request, with `unit`, `unit_price`, `quantity` and `formula` in the body. Also answered, with `error: payment_invalid` and the facilitator''s reason, when a presented payment is rejected, and with `error: price_changed` and a fresh quote when the data changed after you were quoted (never charged). It lists one `accepts` entry per network (eip155:8453, solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp), each the same price in USDC; pay on any one.'
'404':
description: '`no_rows` / `no_history` — nothing matches the filters (never charged).'
'413':
description: '`too_many_rows` — the filters match more than 50000 rows; narrow them (never charged).'
'502':
description: '`facilitator_error` — the payment facilitator could not be reached or failed; nothing was charged, retry later.'
components:
securitySchemes:
bearerAuth:
type: http
scheme: bearer
description: 'Two different credentials ride this header, and they are told apart by their shape.
• A SATO API KEY, `sk_sato_…` — optional on every metered endpoint. It is NEVER required: each of those endpoints answers an anonymous caller at the free limits, and a key only raises the caps and attributes the calls to an account. A key may also be sent as `X-Sato-Key`. An unknown or revoked key is served as if no key were present, never refused. Limits and plans: /pricing.
• A PRIVY ACCESS TOKEN for a signed-in account — required by the claim endpoints and the key-management endpoints. A token that is not a Sato key is treated as one of these.'
satoKey:
type: apiKey
in: header
name: X-Sato-Key
description: 'The same optional Sato API key, on its own header. Equivalent to `Authorization: Bearer sk_sato_…`.'
externalDocs:
description: The published Sato Hub formats, as JSON Schema.
url: https://satohub.ai/schemas