# APIStead MCP

Endpoint: `https://apistead.qd.je/mcp`

Transport: Streamable HTTP, JSON-RPC 2.0 over `POST`.

Authentication: none.

Payment: none for MCP discovery. Paid API calls use x402 on the API's own HTTP 402 route in USDC on Base. The full payment flow is below.

## Marketplace status

APIStead Marketplace is not accepting new listing submissions yet. All live APIs are first-party APIs built and operated by APIStead Labs.

The APIs are live and payable. The marketplace catalogue and provider submission flow are not live yet. The `submit_listing` tool returns the current closed status.

## Connect

Use the endpoint as a remote MCP server in any client that supports Streamable HTTP.

```json
{
  "mcpServers": {
    "apistead": {
      "url": "https://apistead.qd.je/mcp"
    }
  }
}
```

## Initialize

```bash
curl -sS https://apistead.qd.je/mcp \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  --data '{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "initialize",
    "params": {
      "protocolVersion": "2025-06-18",
      "capabilities": {},
      "clientInfo": { "name": "my-agent", "version": "1.0.0" }
    }
  }'
```

## List tools

```bash
curl -sS https://apistead.qd.je/mcp \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  --data '{"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}}'
```

## Tools

| Tool | Purpose |
|---|---|
| `search_apis` | Search the catalogue by capability, category, network and price |
| `list_apis` | List listings with pagination |
| `list_bundles` | List outcome-oriented recipes that combine several paid routes |
| `get_api` | Read one listing with routes, verification and reliability |
| `get_routes` | Read the route methods, paths, prices and examples |
| `get_receipt` | Read a public settlement receipt |
| `check_reliability` | Read uptime and reliability for a listing |
| `submit_listing` | Return the current listing submission status. Submissions are closed |

## Spotify v2

The Spotify v2 listing is `spotify-api-v2`. Read it over MCP with `get_api`, then read its twenty-three routes with `get_routes`:

```bash
curl -sS https://apistead.qd.je/mcp \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  --data '{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"get_api","arguments":{"id_or_slug":"spotify-api-v2"}}}'
```

```bash
curl -sS https://apistead.qd.je/mcp \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  --data '{"jsonrpc":"2.0","id":4,"method":"tools/call","params":{"name":"get_routes","arguments":{"id_or_slug":"spotify-api-v2"}}}'
```

The routes are:

```text
GET|POST /api/v2/spotify/search?q=
GET|POST /api/v2/spotify/search/podcasts?q=
GET|POST /api/v2/spotify/search/episodes?q=
GET|POST /api/v2/spotify/search/audiobooks?q=
GET|POST /api/v2/spotify/search/users?q=
GET|POST /api/v2/spotify/playlist?url=
GET|POST /api/v2/spotify/album?url=
GET|POST /api/v2/spotify/artist?url=
GET|POST /api/v2/spotify/artist/top-tracks?url=
GET|POST /api/v2/spotify/artist/discography?url=
GET|POST /api/v2/spotify/artist/playlists?url=
GET|POST /api/v2/spotify/artist/related?url=
GET|POST /api/v2/spotify/artist/discovered-on?url=
GET|POST /api/v2/spotify/artist/featuring?url=
GET|POST /api/v2/spotify/track?url=
GET|POST /api/v2/spotify/track/similar-albums?url=
GET|POST /api/v2/spotify/podcast?url=
GET|POST /api/v2/spotify/podcast/episodes?url=
GET|POST /api/v2/spotify/episode?url=
GET|POST /api/v2/spotify/audiobook?url=
GET|POST /api/v2/spotify/audiobook/chapters?url=
GET|POST /api/v2/spotify/genres?q=
GET|POST /api/v2/spotify/user?url=
```

Playlists return every ordered track; there is no song limit. The twenty-three v2 routes cost $0.03 USDC per call on Base. Search is v2-only. Supported `type` values are `all`, `track`, `album`, `artist`, `playlist`, `podcast`, `episode`, `audiobook`, `genre` and `user`. Dedicated search routes cover podcasts, episodes, audiobooks and users. Artist routes cover playlists, related artists, discovered-on playlists and featuring playlists; each reports `total`, `returned` and `complete`. Similar albums are based on a supplied track. Track, album and artist radio are not exposed. Discography returns all albums, singles and EPs by default. `preview_url` is included when Spotify publishes a 30-second preview, and artist records include `world_rank`. Each new route costs $0.03 USDC and returns normalized JSON. The v1 listing remains `spotify-api` with five routes.

## Payment

MCP is discovery only. It never returns a 402 and never takes payment. When the agent chooses a paid route, it calls that API route directly over HTTP.

### Where the 402 challenge comes from

The 402 comes from the paid API route itself, not from the MCP server and not from a marketplace.

- `/mcp` — free discovery. Never 402.
- `/api`, `/api/apis/{slug}`, `/api/apis/{slug}/md` — free documentation and listing metadata. Never 402.
- `/agent/*`, `/llms.txt`, `/llms-full.txt`, `/openapi.json` — free discovery. Never 402.
- `/api/v1/...` and `/api/v2/...` — the paid product routes. Return 402 until a valid payment is attached. Spotify v2 search and catalogue routes live under `/api/v2/spotify/...`; the v1 routes remain under `/api/v1/spotify/...`.

Each paid route is wrapped by the x402 server middleware. An unpaid request returns:

```http
HTTP/2 402
content-type: application/json
payment-required: <base64-encoded JSON>
```

The JSON body is the same challenge:

```json
{
  "x402Version": 2,
  "error": "Payment required",
  "resource": {
    "url": "https://apistead.qd.je/api/v1/spotify/artist?id=5INjqkS1o8h1imAzPqGZBb",
    "description": "Spotify artist metadata and top tracks from an artist link.",
    "mimeType": "application/json"
  },
  "accepts": [
    {
      "scheme": "exact",
      "network": "eip155:8453",
      "amount": "20000",
      "asset": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
      "payTo": "0x2E9804240E493DD8daeBa4F341a5086b92cde235",
      "maxTimeoutSeconds": 300,
      "extra": { "name": "USD Coin", "version": "2" }
    }
  ]
}
```

What each field means:

| Field | Meaning |
|---|---|
| `network` | `eip155:8453` is Base mainnet. Local and staging use `eip155:84532` (Base Sepolia). |
| `asset` | USDC contract on Base: `0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913`. |
| `amount` | Atomic USDC with 6 decimals. `20000` = 0.02 USDC. |
| `payTo` | The provider wallet that receives the call payment. |
| `scheme` | `exact` means an exact-amount USDC transfer authorization. |
| `maxTimeoutSeconds` | How long the challenge remains valid. |
| `extra.name` | Must be `USD Coin` for Base USDC. |

The challenge is the authoritative price for that exact request. The `price_usdc` in a listing record is informational. If they differ, trust the live 402.

### Read the challenge by hand

```bash
curl -i "https://apistead.qd.je/api/v1/spotify/artist?id=5INjqkS1o8h1imAzPqGZBb"
```

Decode the `PAYMENT-REQUIRED` header:

```bash
curl -sS -D - -o /dev/null \
  "https://apistead.qd.je/api/v1/spotify/artist?id=5INjqkS1o8h1imAzPqGZBb" \
  | tr -d '\r' \
  | awk -F': ' 'tolower($1)=="payment-required"{print $2}' \
  | base64 -d | jq
```

### Pay and retry

1. Call the route without payment.
2. Read `PAYMENT-REQUIRED` or the JSON body.
3. Check `accepts[]`: scheme, network, asset, amount, `payTo` and timeout.
4. Confirm the amount is within the agent's spending cap and the network is Base mainnet.
5. Sign the USDC payment authorization with the agent wallet.
6. Retry the same URL with `PAYMENT-SIGNATURE: <base64 payload>`.
7. APIStead verifies and settles through the facilitator. Production uses PayAI.
8. On success, the route runs the data fetch and returns the product with `PAYMENT-RESPONSE`.
9. Keep the `PAYMENT-RESPONSE` receipt. Do not retry blindly after a 402.

The agent must never send a private key or seed phrase to APIStead. The signature is produced locally by the wallet or x402 client.

### What the headers contain

- `PAYMENT-REQUIRED` — base64-encoded 402 challenge JSON.
- `PAYMENT-SIGNATURE` — base64-encoded signed payment payload. The client builds it; APIStead never sees the private key.
- `PAYMENT-RESPONSE` — base64-encoded settlement result, including success, transaction hash, network and payer.

APIStead paid JSON responses also include:

```json
{
  "payment": {
    "protocol": "x402",
    "protocol_version": 2,
    "network": "eip155:8453",
    "network_name": "Base",
    "asset": "USDC",
    "price_usdc": 0.02,
    "pay_to": "0x2E9804240E493DD8daeBa4F341a5086b92cde235",
    "authoritative_source": "402_challenge"
  },
  "verification": {
    "status": "verified",
    "route_verified": true,
    "last_verified_at": "2026-11-11T19:36:52.251Z",
    "receipt_url": "https://basescan.org/tx/0x5deeb402be7675ca1b20abd9a059da238f994ee6865897912fde3ef42b666732"
  }
}
```

### Minimal client

Use an x402 client library so it handles the 402, signature and retry.

```ts
import { wrapFetchWithPaymentFromConfig } from "@x402/fetch";
import { ExactEvmScheme } from "@x402/evm";
import { privateKeyToAccount } from "viem/accounts";

const account = privateKeyToAccount(process.env.EVM_PRIVATE_KEY as `0x${string}`);
const paidFetch = wrapFetchWithPaymentFromConfig(fetch, {
  schemes: [{ network: "eip155:8453", client: new ExactEvmScheme(account) }],
});

const response = await paidFetch(
  "https://apistead.qd.je/api/v1/spotify/artist?id=5INjqkS1o8h1imAzPqGZBb",
);

console.log(await response.json());
```

Python clients can use `x402-httpx`. Per-route Python, JavaScript and cURL examples are in `/api/apis/{slug}/md`.

## Other surfaces

- API reference: `https://apistead.qd.je/api`
- OpenAPI: `https://apistead.qd.je/openapi.json`
- Agent skill: `https://apistead.qd.je/skill`
- Full catalogue: `https://apistead.qd.je/llms-full.txt`
- x402 manifest: `https://apistead.qd.je/.well-known/x402`
- x402 resource manifest: `https://apistead.qd.je/.well-known/x402.json`
