# x402 API Directory - pay-per-call APIs with live prices (`vital_tuxedo/x402-api-directory`) Actor

Every pay-per-call API on the x402 discovery board, one row per resource: URL, host, description, price in USD, network, payee, scheme, and an optional live probe for the HTTP 402 that says the price is still being asked. Filter by network and price.

- **URL**: https://apify.com/vital\_tuxedo/x402-api-directory.md
- **Developed by:** [Stephen Psaradellis](https://apify.com/vital_tuxedo) (community)
- **Categories:** Developer tools, AI
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 1,000 resource rows

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## x402 API Directory

A dataset of every pay-per-call API on the x402 discovery board: one row per
HTTP 402 resource with its URL, price in USD, network, payee and payment
scheme, plus an optional live probe that records whether the resource still
answers `402 Payment Required` today. Run it with the defaults for a
200-row sample, or set `maxResources` to 0 for the whole board.

x402 is the HTTP 402 payment protocol: an API answers a plain request with
`402 Payment Required` and its price, and a client that pays (USDC on Base,
usually) gets the response. Coinbase runs a public discovery board of these
resources. This Actor reads the board, normalises every row, and optionally
sends each resource one plain GET to record what it answers.

### What you get

One dataset row per x402 resource:

| field | meaning |
|---|---|
| `url`, `host`, `path` | the resource |
| `description` | the publisher's own description |
| `price_usd` | the price in USD when the asset is USDC, else `null` |
| `price_atomic`, `asset`, `asset_name` | the raw price as listed |
| `network` | e.g. `eip155:8453` (Base mainnet) |
| `pay_to` | the payee address |
| `scheme`, `schemes` | the payment scheme(s) accepted |
| `http_method`, `input_type`, `output_type` | from the board's bazaar extension, when present |
| `board_last_updated`, `board_quality` | as the board reports them: 30-day call and payer counts |
| `probe` | `{status, live_402, latency_ms, checked_at}` when probing is on |
| `read_at` | when this row was read |

The key-value store also gets a `RUN_SUMMARY` with counts: board rows read,
rows kept after filters, probed, live 402s, pushed.

### Example output

Two rows from a run on 2026-09-06, exactly as the dataset holds them:

```json
[
  {
    "url": "https://api.onesource.io/api/chain/erc20-balance",
    "host": "api.onesource.io",
    "path": "/api/chain/erc20-balance",
    "description": "ERC20 token balance for any Ethereum wallet - USDC, USDT, DAI, or any token - via balanceOf (eth_call) on OneSource live Ethereum RPC",
    "type": "http",
    "price_usd": 0.003,
    "price_atomic": "3000",
    "asset": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
    "asset_name": "USD Coin",
    "network": "eip155:8453",
    "pay_to": "0x52E29e0d2Aa49bfBfC548C0A9F2196F4aa51f3ea",
    "scheme": "exact",
    "schemes": [
      "exact",
      "batch-settlement"
    ],
    "max_timeout_secs": 3600,
    "http_method": "GET",
    "input_type": "http",
    "output_type": "json",
    "board_last_updated": "2026-09-06T18:22:29.009Z",
    "board_quality": {
      "l30DaysTotalCalls": 1153,
      "l30DaysUniquePayers": 1147,
      "lastCalledAt": "2026-09-06T18:22:28.786Z"
    },
    "x402_version": 2,
    "probe": {
      "status": 402,
      "live_402": true,
      "latency_ms": 97,
      "checked_at": "2026-09-06T19:52:35.274Z",
      "payment_required_header": true
    },
    "read_at": "2026-09-06T19:52:35.273Z"
  },
  {
    "url": "https://api.onesource.io/api/chain/ens/:input",
    "host": "api.onesource.io",
    "path": "/api/chain/ens/:input",
    "description": "ENS resolve - turn a .eth name into an address, or an address into its primary .eth name, via eth_call on OneSource live Ethereum RPC",
    "type": "http",
    "price_usd": 0.005,
    "price_atomic": "5000",
    "asset": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
    "asset_name": "USD Coin",
    "network": "eip155:8453",
    "pay_to": "0x52E29e0d2Aa49bfBfC548C0A9F2196F4aa51f3ea",
    "scheme": "exact",
    "schemes": [
      "exact",
      "batch-settlement"
    ],
    "max_timeout_secs": 3600,
    "http_method": "GET",
    "input_type": "http",
    "output_type": "json",
    "board_last_updated": "2026-09-06T18:22:32.04Z",
    "board_quality": {
      "l30DaysTotalCalls": 1134,
      "l30DaysUniquePayers": 1131,
      "lastCalledAt": "2026-09-06T18:22:31.883Z"
    },
    "x402_version": 2,
    "probe": {
      "status": 402,
      "live_402": true,
      "latency_ms": 112,
      "checked_at": "2026-09-06T19:52:35.275Z",
      "payment_required_header": true
    },
    "read_at": "2026-09-06T19:52:35.273Z"
  }
]
```

### How to run it

1. Open the Actor in Apify Console and press **Start** with the defaults: a
   200-row sample, each resource probed once, about 30 seconds.
2. Set **Max resources** to `0` for the whole board (about 15,000 rows on
   2026-09-06), or narrow it with the filters below.
3. Read the dataset in Console, export it as JSON or CSV, or fetch it from
   the API with the run's `defaultDatasetId`.

### Input

- **maxResources** - stop after this many rows pass the filters. The default
  of 200 is a quick sample; 0 is the whole board.
- **probe** - send each resource one plain GET with no payment and record the
  status. `402` means the price is live. On by default.
- **probeConcurrency**, **probeTimeoutSecs** - how the probing is paced.
- **network** - keep only one network, e.g. `eip155:8453`.
- **minPriceUsd**, **maxPriceUsd** - keep only USDC-priced rows in a range.

### Pricing

Pay per event, with no charge for platform usage. `resource-row` is $0.002
per row pushed; `probed-row` is $0.005 per row probed (only when probing is
on). What a run costs:

| run | events | price |
|---|---|---|
| 50 rows, probed | 50 + 50 | $0.35 |
| default: 200 rows, probed | 200 + 200 | $1.40 |
| 200 rows, no probe | 200 | $0.40 |
| whole board (about 15,000 rows), probed | 15,000 + 15,000 | about $105 |

Set `maxResources` or a price range to bound a run.

### Use it from code

The **API** tab on this page has ready-made snippets for Node.js, Python
and curl, including `run-sync-get-dataset-items`, which starts a run and
returns the rows in one call. The Actor also works through the Apify MCP
server.

### FAQ

**Does the Actor pay any of these APIs?** No. It never pays a resource and
never sends a payment header. The probe is one unauthenticated GET per
resource, the same request any browser would make.

**Where do the rows come from?** From Coinbase's public x402 discovery board
(`api.cdp.coinbase.com`, the x402 discovery endpoint) and, when probing is
on, from the resource's own answer to one GET. Rows are what the board and
the resource said; nothing is ranked or judged.

**Is `price_usd` ever missing?** It is `null` when the listed asset is not a
USDC contract the Actor recognises; the raw `price_atomic` and `asset` are
always kept.

**What does `probe.status` other than 402 mean?** The resource answered
something else to a plain GET: a 200 (it serves without payment), a 404 or
5xx (it is gone or broken), or `timeout`. `live_402` is true only for a 402.

### Running locally

```
npm install
npm start
```

Input is read from `storage/key_value_stores/default/INPUT.json`; the
dataset lands under `storage/datasets/default/`.

# Actor input Schema

## `maxResources` (type: `integer`):

Stop after this many resources pass the filters. 0 means the whole board (about 15,000 rows on 2026-09-06). The default of 200 is a quick sample; set 0 for the full directory.

## `probe` (type: `boolean`):

Send one plain GET (no payment) to each resource and record the status. 402 means the price is live. Costs one probed-row event per resource in addition to the resource-row event.

## `probeConcurrency` (type: `integer`):

How many resources are probed at once.

## `probeTimeoutSecs` (type: `integer`):

A resource that does not answer within this many seconds is recorded as a timeout.

## `network` (type: `string`):

Keep only resources priced on this network, e.g. eip155:8453 (Base mainnet). Empty keeps every network.

## `minPriceUsd` (type: `string`):

Keep only resources priced at or above this in USDC. Empty means no floor.

## `maxPriceUsd` (type: `string`):

Keep only resources priced at or below this in USDC. Empty means no cap.

## Actor input object example

```json
{
  "maxResources": 200,
  "probe": true,
  "probeConcurrency": 16,
  "probeTimeoutSecs": 8,
  "network": "",
  "minPriceUsd": "",
  "maxPriceUsd": ""
}
```

# Actor output Schema

## `resources` (type: `string`):

Every resource that passed the filters, one row each, with its live probe when probing was on.

## `runSummary` (type: `string`):

Counts for the run: board rows read, rows kept, rows probed, rows answering 402, rows pushed, and whether a charge limit stopped the run early.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {};

// Run the Actor and wait for it to finish
const run = await client.actor("vital_tuxedo/x402-api-directory").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {}

# Run the Actor and wait for it to finish
run = client.actor("vital_tuxedo/x402-api-directory").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{}' |
apify call vital_tuxedo/x402-api-directory --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,vital_tuxedo/x402-api-directory"
        }
    }
}

```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/Bej28poYz6htXh6Zc/builds/O0VAn8x1HYa6LbHd4/openapi.json
