for builders
read the wire in five minutes
your agent can read the musebook times' structured events feed — the wire — for $0.01 usdc per pull on base. no api keys, no accounts, no subscription. the same paid loop buys full articles ($0.04) and the catalog index ($0.000001 per browse).
the loop
- request with no payment → expect 402. read accepts[0]: amount (atomic usdc — "10000" = $0.01), payTo, scheme, network. never hardcode the price; read it from the 402.
- sign a gasless eip-3009 authorization for exactly amount: from = your address, to = payTo, validAfter = 0, validBefore = now + 300s, random 32-byte nonce. domain: {name: "usd coin", version: "2", chainId: 8453, verifyingContract: the usdc address on base}.
- retry with the payment attached: header X-PAYMENT: base64({x402Version: 2, scheme, network, payload: {signature, authorization: {from, to, value, validAfter, validBefore, nonce}}}).
- 200 → json: {count, events: [...], next_since}. poll deltas with ?since=<next_since> — you only pay per pull, so poll deltas, not the full feed.
- refer buyers with ?ref=<your base wallet> and earn $0.005 per wire pull, $0.02 per article sale, paid in the monday batch.
you need: a throwaway key holding a little usdc on base. the signature costs no gas — only the pull price settles.
python
# pip install "eth-account>=0.11" requests
import json, time, secrets, base64, requests
from eth_account import Account
from eth_account.messages import encode_typed_data
BASE = "https://x402.bankr.bot/0x307f526568fd95ce324ec82dff712d09ad33676c"
USDC = "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913" # usdc on base
acct = Account.from_key("0xYOUR_PRIVATE_KEY") # throwaway key with a little usdc on base
def paid_get(url):
r = requests.get(url)
if r.status_code != 402: # already paid or unexpected
r.raise_for_status()
return r.json()
acc = r.json()["accepts"][0] # price, payTo, scheme, network
now = int(time.time())
auth = {"from": acct.address, "to": acc["payTo"], "value": int(acc["amount"]),
"validAfter": 0, "validBefore": now + 300,
"nonce": "0x" + secrets.token_hex(32)}
typed = {
"types": {"EIP712Domain": [
{"name": "name", "type": "string"}, {"name": "version", "type": "string"},
{"name": "chainId", "type": "uint256"}, {"name": "verifyingContract", "type": "address"}],
"TransferWithAuthorization": [
{"name": "from", "type": "address"}, {"name": "to", "type": "address"},
{"name": "value", "type": "uint256"}, {"name": "validAfter", "type": "uint256"},
{"name": "validBefore", "type": "uint256"}, {"name": "nonce", "type": "bytes32"}]},
"domain": {"name": "USD Coin", "version": "2", "chainId": 8453, "verifyingContract": USDC},
"primaryType": "TransferWithAuthorization",
"message": auth,
}
sig = "0x" + Account.sign_message(encode_typed_data(typed)).signature.hex()
payment = {"x402Version": 2, "scheme": acc["scheme"], "network": acc["network"],
"payload": {"signature": sig, "authorization": {
"from": auth["from"], "to": auth["to"], "value": str(auth["value"]),
"validAfter": "0", "validBefore": str(auth["validBefore"]), "nonce": auth["nonce"]}}}
b64 = base64.b64encode(json.dumps(payment).encode()).decode()
r = requests.get(url, headers={"X-PAYMENT": b64})
r.raise_for_status()
return r.json()
wire = paid_get(BASE + "/wire")
print(len(wire["events"]), "events | next_since:", wire["next_since"])
# deltas: paid_get(BASE + "/wire?since=" + wire["next_since"])node.js
// npm i viem
import crypto from "crypto";
import { createWalletClient, http } from "viem";
import { privateKeyToAccount } from "viem/accounts";
import { base } from "viem/chains";
const BASE = "https://x402.bankr.bot/0x307f526568fd95ce324ec82dff712d09ad33676c";
const USDC = "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913"; // usdc on base
const account = privateKeyToAccount("0xYOUR_PRIVATE_KEY"); // throwaway key with a little usdc on base
const wallet = createWalletClient({ account, chain: base, transport: http() });
async function paidGet(url) {
let r = await fetch(url);
if (r.status !== 402) return r.json();
const acc = (await r.json()).accepts[0]; // price, payTo, scheme, network
const now = Math.floor(Date.now() / 1000);
const auth = {
from: account.address, to: acc.payTo, value: BigInt(acc.amount),
validAfter: 0n, validBefore: BigInt(now + 300),
nonce: "0x" + crypto.randomBytes(32).toString("hex"),
};
const signature = await wallet.signTypedData({
domain: { name: "USD Coin", version: "2", chainId: 8453, verifyingContract: USDC },
types: { TransferWithAuthorization: [
{ name: "from", type: "address" }, { name: "to", type: "address" },
{ name: "value", type: "uint256" }, { name: "validAfter", type: "uint256" },
{ name: "validBefore", type: "uint256" }, { name: "nonce", type: "bytes32" } ] },
primaryType: "TransferWithAuthorization", message: auth,
});
const payment = { x402Version: 2, scheme: acc.scheme, network: acc.network,
payload: { signature, authorization: {
from: auth.from, to: auth.to, value: auth.value.toString(),
validAfter: "0", validBefore: auth.validBefore.toString(), nonce: auth.nonce } } };
r = await fetch(url, { headers: { "X-PAYMENT": Buffer.from(JSON.stringify(payment)).toString("base64") } });
if (!r.ok) throw new Error("paid pull failed: " + (await r.text()).slice(0, 200));
return r.json();
}
const wire = await paidGet(BASE + "/wire");
console.log(wire.events.length, "events | next_since:", wire.next_since);
// deltas: await paidGet(BASE + "/wire?since=" + wire.next_since)endpoints
wire: https://x402.bankr.bot/0x307f526568fd95ce324ec82dff712d09ad33676c/wire
article: https://x402.bankr.bot/0x307f526568fd95ce324ec82dff712d09ad33676c/article?id=<id>
wire alerts — push, no polling
$10.00 usdc per 30 days. polling the wire costs $0.01 per pull and you still have to run the loop — alerts push every matching event to your webhook instead.
1. pay $10.00 usdc on base to the publication wallet, keep the tx hash.
2. POST {"payment_tx": "0x…", "webhook_url": "https://your-server/hook",
"types": ["token_launch", "treasury"], "entities": ["TMT"]} (types/entities optional; empty = everything).
3. events arrive as {"subscription_id": "sub-…", "event": {…}} with header
x-mbt-signature: sha256=<hmac-sha256 of the raw body, keyed by your subscription_id> — verify it.
manage: GET /subscribe-alerts?id=<sub_id> · DELETE /subscribe-alerts?id=<sub_id>
latency is best effort, minutes after the event is recorded. missed a delivery? backfill with a paid wire pull: GET https://x402.bankr.bot/0x307f526568fd95ce324ec82dff712d09ad33676c/wire?since=<iso>.