API Documentation
Base URL: https://x402-list.com/api/v1/
All endpoints return JSON. No authentication required for read access. Rate limit: 200 req/min per IP (soft-throttled above 100). You can also browse the service directory or submit a new service via the web interface.
Quick start for agents
Everything in this directory is available as machine-readable JSON. No JavaScript, no login, no SDK required.
# List online services sorted by uptime
$ curl https://x402-list.com/api/v1/services?status=online&sort=uptime&ref=docs
# Fetch a specific service with endpoints and pricing
$ curl https://x402-list.com/api/v1/services/<slug>?ref=docs
# Get the OpenAPI 3.1 specification
$ curl https://x402-list.com/openapi.json Agent-first resources: /openapi.json · /llms.txt · /llms-full.txt
MCP server
A first-party Model Context Protocol server exposes this API to MCP clients through 5 read-only tools: search_x402_services, get_service, find_best_service, check_health, and get_facilitator_volumes.
Hosted endpoint (Streamable HTTP): https://mcp.x402-list.com/mcp. Local stdio via npm: npx -y x402-list-mcp. Example client config:
{
"mcpServers": {
"x402-list": {
"command": "npx",
"args": ["-y", "x402-list-mcp"]
}
}
} GET /api/v1/services
Returns a paginated list of all registered x402 services.
Query Parameters
| Param | Type | Description |
|---|---|---|
| network | string | Filter by network abbreviation, case-insensitive: BSE, SOL, POL, ARB, BSP, AVX (see /networks). Full names like base or solana are not matched: unrecognized values are silently ignored and return the unfiltered list |
| status | string | Filter by status: online, degraded, offline, unknown |
| category | string | Filter by category, case-insensitive (see /categories) |
| sort | string | Sort order: newest (default), uptime, cheapest, endpoints |
| q | string | Substring search across name, description, category, and base URL |
| page | integer | Page number (default: 1) |
| per_page | integer | Results per page, max 100 (default: 25) |
Example Response (?per_page=2)
{
"data": [
{
"slug": "heron",
"name": "Heron",
"description": "Measures how visible a website is to AI search engines and returns a structured improvement plan. Per-audit price quoted in USDC on Base.",
"base_url": "https://heronapp.io",
"website_url": "https://heronapp.io",
"category": "AI",
"status": "online",
"verified": false,
"endpoint_count": 1,
"min_price_usd": 0.25043,
"networks": ["BSE"],
"networks_caip2": ["eip155:8453"],
"uptime_24h": 100,
"avg_response_time_ms": 306,
"last_checked_at": "2026-07-06T10:21:00.405Z",
"created_at": "2026-07-02T20:13:25.690Z"
},
{
"slug": "netintel",
"name": "NetIntel",
"description": "Pay-per-call network and domain intelligence API: DNS, SSL/TLS, WHOIS/RDAP, email security, IP reputation, OSINT.",
"base_url": "https://netintel.dev",
"website_url": "https://netintel.dev",
"category": "AI",
"status": "online",
"verified": false,
"endpoint_count": 37,
"min_price_usd": 0,
"networks": ["BSE"],
"networks_caip2": ["eip155:8453"],
"uptime_24h": 100,
"avg_response_time_ms": 77,
"last_checked_at": "2026-07-06T10:29:02.849Z",
"created_at": "2026-07-01T13:57:51.651Z"
}
],
"meta": {
"total": 86,
"page": 1,
"per_page": 2,
"total_pages": 43
}
} GET /api/v1/services/:slug
Returns full details for a single service, including every active endpoint with its per-network pricing. Unknown slugs return a 404 error envelope (see Response Format below).
Example Response (endpoints truncated to 1 entry)
{
"data": {
"slug": "netintel",
"name": "NetIntel",
"description": "Pay-per-call network and domain intelligence API: DNS, SSL/TLS, WHOIS/RDAP, email security, IP reputation, OSINT.",
"base_url": "https://netintel.dev",
"website_url": "https://netintel.dev",
"category": "AI",
"status": "online",
"verified": false,
"consecutive_failures": 0,
"check_interval_minutes": 15,
"last_checked_at": "2026-07-06T10:29:02.852Z",
"created_at": "2026-07-01T13:57:51.651Z",
"uptime": { "24h": 100, "7d": 100, "30d": 100, "90d": 100 },
"avg_response_time_ms": 77,
"total_checks": 438,
"networks": ["BSE"],
"networks_caip2": ["eip155:8453"],
"asset": "USDC",
"endpoints": [
{
"id": "a9d34456-f44f-4383-8696-b2acbe46f6bf",
"method": "GET",
"path": "/asn-lookup/analyze",
"description": null,
"mime_type": null,
"is_active": true,
"first_seen_at": "2026-07-01T13:57:51.651Z",
"last_seen_at": "2026-07-06T10:29:02.775Z",
"min_price_usd": 0.03,
"networks": ["BSE"],
"pricing": [
{
"scheme": "exact",
"network": "eip155:8453",
"network_caip2": "eip155:8453",
"asset_address": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
"asset_address_norm": "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913",
"asset_name": "USDC",
"price": "30000",
"price_usd": "0.0300000000",
"pay_to": "0xdaDc335482AD545296Fd7b28518A251fFCbEb9Df",
"max_timeout_seconds": 300
}
]
}
]
}
} GET /api/v1/services/:slug/uptime
Returns daily uptime rollups for the service over the requested period, newest first: one entry per day with uptime percentage, average response time, and check counts.
Query Parameters
| Param | Type | Description |
|---|---|---|
| period | string | Time window: 24h, 7d, 30d, 90d (default: 30d). Any other value returns 400 |
Example Response (?period=7d, truncated to 2 entries)
{
"data": [
{
"period_start": "2026-07-06T00:00:00.000Z",
"period_end": "2026-07-07T00:00:00.000Z",
"uptime_percentage": 100,
"avg_response_time_ms": 69.76,
"total_checks": 38,
"successful_checks": 38
},
{
"period_start": "2026-07-05T00:00:00.000Z",
"period_end": "2026-07-06T00:00:00.000Z",
"uptime_percentage": 100,
"avg_response_time_ms": 71.18,
"total_checks": 90,
"successful_checks": 90
}
]
} GET /api/v1/services/:slug/volume
Returns measured on-chain settlement volume for the service over time (USD), one point per UTC day, oldest first. Volume is read directly on-chain by settler attribution over the service's payTo mapping (USDC only), never self-reported, and is a conservative undercount: only settlements the monitor observed are counted. The series is honest-empty until a settlement is observed. The status and null-vs-zero semantics are carried on the service detail's assessment.traction block.
Query Parameters
| Param | Type | Description |
|---|---|---|
| period | string | Time window: 24h, 7d, 30d, 90d, all (default: 90d). all reads the full recorded history. Any other value returns 400 |
Example Response (?period=7d, truncated to 2 entries)
{
"data": [
{
"date": "2026-07-05",
"volume_usd": 12.47,
"tx_count": 39
},
{
"date": "2026-07-06",
"volume_usd": 9.8,
"tx_count": 31
}
]
} GET /api/v1/services/:slug/buyers
Returns the measured distinct on-chain buyer count for the service over time, one point per UTC day, oldest first. Distinct buyers are counted straight from the raw settlements per day (never summed from a rollup) over the service's payTo mapping, USDC only. Like the volume series it is a conservative undercount and honest-empty until a settlement is observed.
Query Parameters
| Param | Type | Description |
|---|---|---|
| period | string | Time window: 24h, 7d, 30d, 90d, all (default: 90d). all reads the full recorded history. Any other value returns 400 |
Example Response (?period=7d, truncated to 2 entries)
{
"data": [
{
"date": "2026-07-05",
"unique_buyers": 7
},
{
"date": "2026-07-06",
"unique_buyers": 5
}
]
} GET /api/v1/services/:slug/checks
Returns individual health-check results for a service, newest first.
Query Parameters
| Param | Type | Description |
|---|---|---|
| limit | integer | Number of results, max 100 (default: 20) |
| offset | integer | Offset for pagination (default: 0) |
Example Response (?limit=2)
{
"data": [
{
"id": "aa7af11f-d67b-4b32-9539-79758b3623fa",
"checked_at": "2026-07-06T10:29:02.849Z",
"response_time_ms": 72,
"status_code": 402,
"is_up": true,
"error_message": null,
"endpoints_found": 37
},
{
"id": "00f471af-8b24-44a4-9e44-e99e28800c5b",
"checked_at": "2026-07-06T10:13:02.631Z",
"response_time_ms": 66,
"status_code": 402,
"is_up": true,
"error_message": null,
"endpoints_found": 37
}
],
"meta": {
"total": 438
}
} GET /api/v1/checks
Live feed of health checks across all services, newest first. Useful for building real-time dashboards.
Query Parameters
| Param | Type | Description |
|---|---|---|
| limit | integer | Number of results, max 100 (default: 50) |
| offset | integer | Offset for pagination (default: 0) |
Example Response (?limit=2)
{
"data": [
{
"id": "dfb29787-0fa7-49d7-ba89-6e9ae7ab3925",
"checked_at": "2026-07-06T10:29:20.071Z",
"is_up": false,
"response_time_ms": 2500,
"status_code": null,
"endpoints_found": 0,
"service_name": "Sivut Public Data APIs",
"service_slug": "sivut-public-data-apis",
"service_status": "offline"
},
{
"id": "d602008c-e915-4b27-b868-f5d6f6f0a05d",
"checked_at": "2026-07-06T10:29:02.942Z",
"is_up": true,
"response_time_ms": 953,
"status_code": 402,
"endpoints_found": 3,
"service_name": "AsterPay",
"service_slug": "asterpay",
"service_status": "online"
}
],
"meta": {
"total": 300469
}
} GET /api/v1/status
Aggregate platform health: counts by status plus a per-service status entry for every listed service (the services array is truncated to 2 entries here).
Example Response
{
"data": {
"total": 86,
"online": 68,
"degraded": 9,
"offline": 8,
"unknown": 1,
"services": [
{
"slug": "2s-io",
"name": "2s.io",
"status": "online",
"last_checked_at": "2026-07-06T10:16:01.134Z",
"consecutive_failures": 0,
"uptime_24h": 100,
"avg_response_time_ms": 185.45
},
{
"slug": "aeo-audit-api",
"name": "AEO Audit API",
"status": "online",
"last_checked_at": "2026-07-06T10:25:00.433Z",
"consecutive_failures": 0,
"uptime_24h": 100,
"avg_response_time_ms": 285.53
}
]
}
} GET /api/v1/networks
Lists all blockchain networks tracked by x402 List, with per-network service counts and average uptime. The abbreviation values are what the ?network= filter on /services accepts. Response truncated to 2 entries here.
Example Response
{
"data": [
{
"id": "836f6a83-251b-41ba-b44a-c6be54139ebb",
"caip2_id": "eip155:8453",
"caip2": "eip155:8453",
"name": "Base",
"abbreviation": "BSE",
"chain_type": "evm",
"is_mainnet": true,
"explorer_url": "https://basescan.org",
"service_count": 79,
"avg_uptime": 89.6
},
{
"id": "393fd87c-3aa5-4f2e-86c7-52a7623d9d66",
"caip2_id": "solana:5eykt4usfv8p8njdtrepy1vzqkqzkvdp",
"caip2": "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp",
"name": "Solana",
"abbreviation": "SOL",
"chain_type": "svm",
"is_mainnet": true,
"explorer_url": "https://solscan.io",
"service_count": 26,
"avg_uptime": 96
}
],
"meta": {
"avg_uptime_method": "per-service mean of the latest daily uptime rollup"
}
} GET /api/v1/stats
Platform-wide aggregate statistics: service and endpoint totals, uptime averages, pricing distribution, and a per-network breakdown (truncated to 2 entries here).
Example Response
{
"data": {
"total_services": 86,
"total_endpoints": 436,
"total_networks": 5,
"total_networks_note": "mainnet networks only; networks[] includes testnets flagged by is_mainnet",
"avg_uptime_24h": 90.5,
"avg_uptime_7d": 91,
"avg_uptime_method": "per-service mean of the latest daily uptime rollup",
"avg_response_time_ms": 405,
"checks_per_hour": 344,
"pricing": {
"avg_price_usd": 0.418,
"min_price_usd": 0,
"max_price_usd": 19.97,
"median_price_usd": 0.005
},
"networks": [
{ "abbreviation": "BSE", "is_mainnet": true, "service_count": 79, "avg_uptime": 89.6 },
{ "abbreviation": "SOL", "is_mainnet": true, "service_count": 26, "avg_uptime": 96 }
]
}
} GET /api/v1/categories
Lists the category labels currently in use, as a flat array of strings. Use these values for the ?category= filter on /services and the category field of POST /submit. The former /api/v1/tags taxonomy has been removed and now returns 410 Gone.
Example Response
{
"data": ["AI", "Blockchain", "Compute", "Content", "Data", "Finance", "Other"]
} GET /api/v1/facilitators
Paginated list of x402 facilitators with settlement volumes measured on-chain, sorted by volume in the selected timeframe. verification is on-chain (measured from blockchain transactions) or listed (chain declared by a settler address, not yet measured).
Query Parameters
| Param | Type | Description |
|---|---|---|
| timeframe | string | Window that drives the sort order: 24h, 7d, 30d, all (default: 7d) |
| include | string | Comma-separated optional embeds: timeseries (daily volume series) and/or chains (per-network, per-token breakdown) |
| days | integer | Length of the embedded timeseries window, 1 to 90 (default: 30, only with include=timeseries) |
| page | integer | Page number (default: 1) |
| per_page | integer | Results per page, max 100 (default: 25) |
Example Response (truncated to 2 entries)
{
"data": [
{
"facilitator_id": "coinbase",
"name": "Coinbase",
"website_url": "https://docs.cdp.coinbase.com/x402/welcome",
"volume_usd_24h": 2427.75,
"volume_usd_7d": 36219.99,
"volume_usd_30d": 193952.67,
"volume_usd_all": 1573230.28,
"tx_count_24h": 151811,
"tx_count_7d": 1399119,
"tx_count_30d": 8869191,
"tx_count_all": 16978418,
"last_activity_at": "2026-07-06T00:00:00.000Z",
"settler_count": 35,
"verification": "on-chain"
},
{
"facilitator_id": "mrdn",
"name": "Meridian",
"website_url": "https://docs.mrdn.finance",
"volume_usd_24h": 2331.97,
"volume_usd_7d": 32219.96,
"volume_usd_30d": 187217.82,
"volume_usd_all": 1236223.48,
"tx_count_24h": 113,
"tx_count_7d": 1709,
"tx_count_30d": 8315,
"tx_count_all": 57941,
"last_activity_at": "2026-07-06T00:00:00.000Z",
"settler_count": 1,
"verification": "on-chain"
}
],
"meta": {
"total": 28,
"page": 1,
"per_page": 25,
"total_pages": 2,
"timeframe": "7d"
}
} POST /api/v1/submit
Submit a new x402-compatible service for review and inclusion in the directory. Endpoints are probed automatically for valid HTTP 402 responses, then a human reviews the submission before it is listed. Submissions from free hosting and dev-tunnel domains (vercel.app, workers.dev, ngrok, trycloudflare, etc.) are rejected with 400: production services must be on their own domain. Each email address may submit once every 7 days (see Rate Limiting below), and submissions still pending after the 7-day review window are auto-rejected with an email notification. The same endpoint also accepts x402 facilitator submissions: see the next section.
Paid resubmission after a rejection. If the latest submission for the same email or the same service URL was rejected less than 14 days ago, resubmitting is not free: it costs a one-time $0.50 USDC (x402) payment on Base, which replaces the 7-day cooldown (pay and re-enter immediately). Once 14 days have passed since the rejection, resubmitting is free again. Without payment the endpoint answers HTTP 402 with a PAYMENT-REQUIRED header and an accepts[] body; pay with an x402-capable client and retry the same request with a PAYMENT-SIGNATURE header. On success the 201 carries a PAYMENT-RESPONSE header. First-time submissions, and resubmissions whose latest is still pending or approved, are unaffected.
Request Body (JSON, all fields required except notes)
| Field | Type | Description |
|---|---|---|
| url | string | Base URL of the x402 service |
| string | Submitter contact email | |
| service_name | string | Human-readable name of the service (max 255 chars) |
| description | string | Brief description of what the service does |
| website_url | string | Public website URL |
| category | string | Service category (use /categories for valid values) |
| endpoints | string[] | Endpoint paths to probe, max 50 (e.g. ["/v1/generate"]) |
| notes | string | Additional context (optional) |
Example Request
curl -X POST https://x402-list.com/api/v1/submit \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com",
"email": "operator@example.com",
"service_name": "Example x402 API",
"description": "AI text generation via x402 micropayments",
"website_url": "https://example.com",
"category": "AI",
"endpoints": ["/v1/generate", "/v1/classify"],
"notes": "Optional context about the service"
}' Example Response (201; probe_result is null if the probe timed out)
{
"data": {
"submission_id": "7f0d2c5e-9a41-4b3a-8c67-2f51f0f8a915",
"status": "pending",
"probe_result": {
"endpoints_found": 2,
"errors": []
}
}
} Paid Resubmission Response (402; only when the latest submission for this email or URL was rejected)
The PAYMENT-REQUIRED response header carries the same x402 object base64-encoded, without the app-level message field (which is body-only). Pay the single accepts[0] option ($0.50 USDC on Base) and retry with a PAYMENT-SIGNATURE header.
{
"x402Version": 2,
"accepts": [
{
"scheme": "exact",
"network": "eip155:8453",
"asset": "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913",
"amount": "500000",
"payTo": "0x0000000000000000000000000000000000000000",
"maxTimeoutSeconds": 300,
"extra": { "name": "USD Coin", "version": "2" }
}
],
"resource": {
"url": "https://x402-list.com/api/v1/submit",
"description": "Resubmission fee after a rejected submission",
"mimeType": "application/json",
"serviceName": "x402 List"
},
"error": "resubmission_fee_required",
"message": "A submission from this email or for this URL was rejected less than 14 days ago, so resubmitting now requires a $0.50 x402 payment on Base (USDC). Pay with an x402-capable client by sending the request again with a PAYMENT-SIGNATURE header, or wait until 14 days have passed to resubmit for free. See https://x402-list.com/api for the flow."
} POST /api/v1/submit (facilitator)
The same endpoint also accepts x402 facilitator submissions (settlement infrastructure operators, listed on /facilitators). Set "type": "facilitator" in the body to select this variant; without it the request is handled as a service submission. Facilitators are not probed over HTTP: instead, the enabled EVM chains among the declared networks are scanned for recent on-chain USDC settlement activity originated by the submitted settler addresses (30-day window, 15 seconds total budget). Solana and chains outside the measured registry are recorded as declared claims and checked during manual review. A failed or idle probe never blocks the submission: every facilitator submission is reviewed by a human before listing. Approved facilitators appear in GET /facilitators with verification: "listed" and switch to "on-chain" automatically once settlement volume is measured. Website URLs on free hosting or dev-tunnel domains are rejected with 400, and the 7-day per-email cooldown is tracked separately per submission type (see Rate Limiting below).
Request Body (JSON; required: type, email, facilitator_name, website_url, settler_addresses, networks)
| Field | Type | Description |
|---|---|---|
| type | string | Must be facilitator to select this variant |
| string | Submitter contact email | |
| facilitator_name | string | Human-readable facilitator name (max 255 chars) |
| website_url | string | Public website URL, on your own domain |
| settler_addresses | string[] | On-chain addresses that originate settlement transactions, 1 to 25: 0x EVM (40 hex chars) or base58 Solana (32-44 chars). Also accepted as one comma/newline separated string |
| networks | string[] | Declared settlement networks, 1 to 25 (e.g. base, polygon, solana). Enabled EVM chains are probed on-chain; the rest stay declared claims. Also accepted as one comma/newline separated string |
| description | string | What the facilitator does (optional) |
| facilitator_id_slug | string | Proposed identifier slug: lowercase letters, digits, single hyphens, max 100 chars (optional) |
| token_claims | string[] | Tokens the facilitator claims to settle, informational only (optional) |
| claimed_volume_usd | string | number | Self-reported all-time settlement volume in USD, informational only: cross-checked against the on-chain probe at review (optional) |
| notes | string | Additional context (optional) |
Example Request
curl -X POST https://x402-list.com/api/v1/submit \
-H "Content-Type: application/json" \
-d '{
"type": "facilitator",
"email": "operator@examplepay.com",
"facilitator_name": "ExamplePay",
"website_url": "https://examplepay.com",
"description": "x402 settlement facilitator for USDC on Base and Solana",
"settler_addresses": [
"0x7c5fa2ab8c9d01234e56f7a8b9c0d1e2f3a4b5c6",
"4Nd1mYQZ7d5xUEhFcq8xJwzB3tYkTn5eGf2u1V9pQrSt"
],
"networks": ["base", "solana"],
"facilitator_id_slug": "examplepay",
"token_claims": ["USDC"],
"claimed_volume_usd": "125000",
"notes": "Settling x402 payments since May 2026"
}' Example Response (201; probe_result covers only the enabled EVM chains and is null if the probe could not run)
{
"data": {
"submission_id": "3b8e1f42-6c9d-4e07-9a15-d824c0b7f691",
"status": "pending",
"probe_result": {
"addresses_with_activity": ["0x7c5fa2ab8c9d01234e56f7a8b9c0d1e2f3a4b5c6"],
"tx_count": 1284,
"errors": []
}
}
} POST /api/v1/services/:slug/request-update
Owners of a listed service can propose changes to their listing's declarative metadata: name, description, website URL, category, contact email, NEW endpoint paths, and base URL as an always-manual identity change. Measured data (verified status, uptime, pricing, pay_to) can never be overridden through this channel: it stays read-only for everyone. An empty or omitted field always means unchanged, so a partial body can never clear or accidentally rewrite a field. Ownership is proven per request with a domain proof: the response returns a one-time token (shown once, only its hash is stored) that must be published as its own line at {base_url origin}/.well-known/x402list.txt on the CURRENT listed domain, then confirmed with verify-ownership below within 72 hours. Every verified request is reviewed by a human before anything is applied, and nothing about a pending request is shown publicly. One request per email per service every 7 days (429 with Retry-After); a browser form is available at /services/:slug/update.
Request Body (JSON or form-encoded; required: email, plus at least one changed field)
| Field | Type | Description |
|---|---|---|
| string | Requester contact email (cooldown key together with the service) | |
| name | string | New display name (optional; empty = unchanged) |
| description | string | New description (optional; empty = unchanged) |
| website_url | string | New public website URL, own domain only (optional) |
| category | string | New category (use /categories for valid values) (optional) |
| contact_email | string | New listing contact email (optional) |
| base_url | string | New base URL. Identity change: always reviewed manually, the slug never changes (optional) |
| endpoints_add | string[] | NEW endpoint paths to add and monitor, max 50; already-listed paths are ignored. Also accepted as one comma/newline separated string (optional) |
Example Request
curl -X POST https://x402-list.com/api/v1/services/example-x402-api/request-update \
-H "Content-Type: application/json" \
-d '{
"email": "operator@example.com",
"description": "AI text generation and classification via x402 micropayments",
"endpoints_add": ["/v1/summarize"]
}' Example Response (201; the ownership_token is returned only here, only once)
{
"data": {
"request_id": "9c2f7b1e-4d3a-4f60-b2c8-51e9a0d47f36",
"status": "pending_verification",
"proposed_changes": {
"description": "AI text generation and classification via x402 micropayments",
"endpoints_add": ["/v1/summarize"]
},
"ownership_token": "x402list-verify-Ux3nT9qYw1Zb7kD4mR8sVfA2cH6jL0pEoI5gNyQtBw0",
"well_known_url": "https://example.com/.well-known/x402list.txt",
"well_known_path": "/.well-known/x402list.txt",
"token_expires_at": "2026-07-09T14:00:00.000Z",
"verify": {
"method": "POST",
"url": "/api/v1/services/example-x402-api/verify-ownership",
"body": { "request_id": "9c2f7b1e-4d3a-4f60-b2c8-51e9a0d47f36" }
},
"note": "Publish the ownership_token as a line of the well-known file on the service's CURRENT domain, then call verify. The token is shown only once and expires in 72 hours. Review is manual after verification."
}
} POST /api/v1/services/:slug/verify-ownership
Step 2 of an update request: after publishing the token in the well-known file, call this endpoint with the request_id. The server re-fetches {base_url origin}/.well-known/x402list.txt on the CURRENT listed domain (with the same SSRF discipline as the monitor: public hosts only, manual redirects, 64KB body cap, 10s timeout) and matches the token against the file's lines. On success the token is consumed (one-shot) and, when the proposed diff touches base_url or adds endpoints, the standard HTTP 402 probe runs so the reviewer sees fresh probe_result data; a failed probe never blocks the request. The request then goes to manual review and the requester is notified by email of the outcome. Errors: 400 when the file cannot be fetched or the token is not in it, 404 unknown request or wrong service, 409 already reviewed, 410 token expired (submit a new request).
Example Request
curl -X POST https://x402-list.com/api/v1/services/example-x402-api/verify-ownership \
-H "Content-Type: application/json" \
-d '{"request_id": "9c2f7b1e-4d3a-4f60-b2c8-51e9a0d47f36"}' Example Response (200; probe_result is null when the diff does not touch the probe surface)
{
"data": {
"request_id": "9c2f7b1e-4d3a-4f60-b2c8-51e9a0d47f36",
"status": "verified",
"probe_result": {
"endpoints_found": 1,
"errors": []
},
"note": "Ownership verified. The request now goes to manual review; you will be notified by email."
}
} POST /api/v1/suggestions
Paid suggestion box. Suggest a change, feature, bug, or data fix for the x402 List directory itself, and pay for the feedback channel in x402. Each suggestion costs a one-time $0.10 USDC (x402) payment on Base: the fee is the anti-spam skin-in-the-game, so there is no refund. Suggestions are internal and reviewed by a human; they are not published and carry no public roadmap. This endpoint is agent-first (JSON), and the paid flow is the standard x402 handshake: the first call returns HTTP 402 with a PAYMENT-REQUIRED header and an accepts[] body (single option, $0.10 USDC on Base); pay with an x402-capable client and retry the same request with a PAYMENT-SIGNATURE header. On success the 201 carries a PAYMENT-RESPONSE header.
Request Body (JSON; only text is required)
| Field | Type | Description |
|---|---|---|
| text | string | The suggestion (1 to 2000 characters) |
| category | string | One of feature, bug, data, other (optional, defaults to other) |
| string | Contact email to receive the review outcome (optional) |
Example Request
curl -X POST https://x402-list.com/api/v1/suggestions \
-H "Content-Type: application/json" \
-H "PAYMENT-SIGNATURE: <base64 x402 payment payload>" \
-d '{
"text": "Add a /api/v1/services bulk export endpoint for offline indexing",
"category": "feature",
"email": "agent@example.com"
}' Example Response (201; PAYMENT-RESPONSE header carries the settlement receipt)
{
"data": {
"id": "b1e7c3a4-2f6d-4c8b-9a10-5e2f7d0c1a34",
"status": "received"
}
} Payment Required Response (402; when no PAYMENT-SIGNATURE is sent)
The PAYMENT-REQUIRED response header carries the same x402 object base64-encoded, without the app-level message field (which is body-only). Pay the single accepts[0] option ($0.10 USDC on Base) and retry with a PAYMENT-SIGNATURE header. When the payment layer is not configured, this endpoint answers HTTP 503 instead.
{
"x402Version": 2,
"accepts": [
{
"scheme": "exact",
"network": "eip155:8453",
"asset": "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913",
"amount": "100000",
"payTo": "0x0000000000000000000000000000000000000000",
"maxTimeoutSeconds": 300,
"extra": { "name": "USD Coin", "version": "2" }
}
],
"resource": {
"url": "https://x402-list.com/api/v1/suggestions",
"description": "Suggestion fee for x402 List directory feedback",
"mimeType": "application/json",
"serviceName": "x402 List"
},
"error": "suggestion_fee_required",
"message": "Posting a suggestion to the x402 List directory requires a $0.10 x402 payment on Base (USDC). Pay with an x402-capable client: send the request again with a PAYMENT-SIGNATURE header. See https://x402-list.com/api for the flow."
} GET /api/v1/openapi.json
Returns the full OpenAPI 3.1 specification for this API. Use it to auto-generate client libraries or import into tools like Postman. Also served at /openapi.json.
Response Format
All successful responses are a JSON object with a data key holding the requested resource (object or array). List endpoints add a meta key with pagination info such as total, page, per_page, and total_pages.
Error responses use an error key instead. code is a number mirroring the HTTP status:
{
"error": {
"code": 404,
"message": "Service 'nonexistent-slug-xyz' not found"
}
} HTTP Status Codes
| Code | Meaning |
|---|---|
| 200 | Success |
| 201 | Created (POST /submit) |
| 400 | Bad request / invalid parameters |
| 402 | Payment required: a metered request beyond the free daily quota (see Metering), or a paid write endpoint |
| 404 | Resource not found |
| 410 | Gone: endpoint removed (e.g. /api/v1/tags, replaced by /api/v1/categories) |
| 429 | Rate limit exceeded, or POST /submit email cooldown (see below) |
| 500 | Internal server error |
Metering
Reads are free for agents and point queries. Sustained bulk pulling is metered: each IP gets 2,000 free GET requests per day (UTC day) across /api/v1/*. Beyond that quota, each additional request costs $0.01 USDC (x402) on Base, charged per request. The quota does not apply to /api/v1/openapi.json, to the write endpoints (POST /submit, POST /suggestions, and the ownership routes), or to /api/admin/*.
Every metered response carries an X-Meter-Remaining header with the free requests left today. Once the quota is exhausted the API answers metered requests with HTTP 402: pay accepts[0] ($0.01 USDC on Base) with an x402-capable client and retry the same request with a PAYMENT-SIGNATURE header; the successful response then carries a PAYMENT-RESPONSE header. The PAYMENT-REQUIRED response header carries the same x402 PaymentRequired object base64-encoded, without the app-level message field (which is body-only).
Example Response Header
X-Meter-Remaining: 1913 Example 402 (over the free daily quota)
{
"x402Version": 2,
"accepts": [
{
"scheme": "exact",
"network": "eip155:8453",
"asset": "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913",
"amount": "10000",
"payTo": "0x0000000000000000000000000000000000000000",
"maxTimeoutSeconds": 300,
"extra": { "name": "USD Coin", "version": "2" }
}
],
"resource": {
"url": "/api/v1/services",
"description": "x402 List API metered access (per request beyond the free daily quota)",
"mimeType": "application/json",
"serviceName": "x402 List"
},
"error": "metering_fee_required",
"message": "This request is beyond the free daily quota (2,000 requests/day per IP). Each additional request costs $0.01 USDC (x402) on Base. Pay with an x402-capable client and retry the same request with a PAYMENT-SIGNATURE header. See https://x402-list.com/api for the flow."
} Rate Limiting
All endpoints are rate-limited to 200 requests per minute per IP address (sliding window, resets every minute). Above 100 req/min the response includes X-RateLimit-Throttled: true as an advisory signal - requests still succeed. Above 200 req/min the API returns 429 Too Many Requests with a Retry-After header indicating seconds until the window resets.
X-RateLimit-Limit: 200
X-RateLimit-Remaining: 87
X-RateLimit-Reset: 1783339200
X-RateLimit-Throttled: true # only when count > 100 POST /submit additionally enforces a 7-day cooldown per submitter email, tracked separately per submission type: a second submission of the same type (service or facilitator) from the same email within 7 days returns 429 with Retry-After set to the seconds left until the cooldown ends (up to 7 days, not the per-minute window). A service submission does not block a facilitator submission from the same email, and vice versa. Submissions of either type still pending after the 7-day review window are auto-rejected, with an email notification, so the address can submit again.