Enter any URL. Watch the server return HTTP 402 with machine-readable payment requirements — no wallet needed to observe the protocol.
// npm install @x402/fetch @x402/evm viem
import { wrapFetchWithPayment } from "@x402/fetch";
import { x402Client } from "@x402/core/client";
import { ExactEvmScheme } from "@x402/evm/exact/client";
import { privateKeyToAccount } from "viem/accounts";
const signer = privateKeyToAccount(process.env.EVM_PRIVATE_KEY);
const client = new x402Client();
client.register("eip155:*", new ExactEvmScheme(signer));
// wrapFetchWithPayment auto-handles: probe 402 -> sign -> retry
const fetchWithPayment = wrapFetchWithPayment(fetch, client);
const res = await fetchWithPayment(
"https://api.scrvo.com/api/crawl",
{
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
url: "https://example.com",
formats: ["markdown"],
}),
}
);
const { pollUrl } = await res.json();
// Poll until completed
// Note: first 30-60s may return 404 (D1 consistency lag - expected)
let result;
do {
await new Promise(r => setTimeout(r, 3000));
result = await fetch("https://api.scrvo.com" + pollUrl).then(r => r.json());
} while (result.status === "running");
console.log(result.records[0].markdown); # pip install "x402[httpx]" eth_account
import asyncio, os
from eth_account import Account
from x402 import x402Client
from x402.http.clients import x402HttpxClient
from x402.mechanisms.evm import EthAccountSigner
from x402.mechanisms.evm.exact.register import register_exact_evm_client
SERVER = "https://api.scrvo.com"
async def main():
client = x402Client()
account = Account.from_key(os.getenv("EVM_PRIVATE_KEY"))
register_exact_evm_client(client, EthAccountSigner(account))
# x402HttpxClient auto-handles: probe 402 -> sign -> retry
async with x402HttpxClient(client) as http:
res = await http.post(
SERVER + "/api/crawl",
json={"url": "https://example.com", "formats": ["markdown"]}
)
data = res.json()
# Poll until completed (30-60s D1 lag on first poll is normal)
while True:
await asyncio.sleep(3)
poll = await http.get(SERVER + data["pollUrl"])
result = poll.json()
if result["status"] != "running":
break
print(result["records"][0]["markdown"])
asyncio.run(main()) # Step 1: Probe the paywall (no payment) — see the 402 body
curl -s -X POST \
https://api.scrvo.com/api/crawl \
-H "Content-Type: application/json" \
-d '{"url":"https://example.com","formats":["markdown"]}' | jq .
# Step 2: Sign the EIP-712 payload (use cast, ethers, or @x402/evm)
# Then base64-encode and submit:
curl -s -X POST \
https://api.scrvo.com/api/crawl \
-H "Content-Type: application/json" \
-H "X-PAYMENT: <base64-signed-payload>" \
-d '{"url":"https://example.com","formats":["markdown"]}' | jq .
# Response 202: { "jobId": "...", "pollUrl": "/api/crawl/..." }
# Step 3: Poll until completed
# Note: first 30-60s may return 404 — D1 eventual consistency, keep polling
curl -s https://api.scrvo.com/api/crawl/<jobId> | jq .
# Step 4: Cancel a job
curl -s -X DELETE https://api.scrvo.com/api/crawl/<jobId> | jq .