1. Evaluate free
The response is illustrative, not live data, and needs no wallet or credentials.
curl --disable --fail --silent --show-error https://pay.edge-agents.ai/v1/samples/xrp-macro-structural-outlookPRODUCT-SPECIFIC QUICKSTART
This guide purchases one representative specialist report—XRP Macro & Structural Outlook—not the multi-service bundle. The report costs exactly $0.10 (100,000 atomic USDC) on Base mainnet in this guide. The same report can also be paid in RLUSD on XRPL—see how agent purchasing works for both settlement rails.
The response is illustrative, not live data, and needs no wallet or credentials.
curl --disable --fail --silent --show-error https://pay.edge-agents.ai/v1/samples/xrp-macro-structural-outlooknpm install @edge-agents-ai/buyer@0.2.2 viem@2.55.0Load EVM_PRIVATE_KEY from your local environment or secret manager. The example never prints it and refuses payment terms outside the named network, asset and amount cap.
import { privateKeyToAccount } from "viem/accounts";
import { createEdgeAgentsBuyer } from "@edge-agents-ai/buyer";
const privateKey = process.env.EVM_PRIVATE_KEY;
if (!privateKey) throw new Error("EVM_PRIVATE_KEY is required; load it from a secret manager.");
const signer = privateKeyToAccount(privateKey);
const buyer = createEdgeAgentsBuyer({
signer,
baseUrl: "https://pay.edge-agents.ai",
network: "eip155:8453",
asset: "USDC",
maxAtomicAmount: 100_000n,
});
const { report } = await buyer.purchase({ serviceId: "xrp-macro-structural-outlook" });
const boundedIdentifier = (value) =>
typeof value === "string" ? value.slice(0, 128) : undefined;
console.log(JSON.stringify({
serviceId: boundedIdentifier(report.serviceId),
reportId: boundedIdentifier(report.reportId),
deliveryId: boundedIdentifier(report.deliveryId),
}));Only bounded, non-secret report identifiers are logged. The paid endpoint is https://pay.edge-agents.ai/v1/services/xrp-macro-structural-outlook.
This inspection makes no payment, sends no payment header, follows no redirects and requires an HTTP 402 response.
import base64
import binascii
import json
import requests
MAX_HEADER_CHARS = 16 * 1024
MAX_DECODED_BYTES = 12 * 1024
MAX_ACCEPTS = 8
EXPECTED_RESOURCE = "https://pay.edge-agents.ai/v1/services/xrp-macro-structural-outlook"
EXPECTED_NETWORK = "eip155:8453"
EXPECTED_ASSET = "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"
EXPECTED_AMOUNT = "100000"
session = requests.Session()
session.trust_env = False
response = session.get(
"https://pay.edge-agents.ai/v1/services/xrp-macro-structural-outlook",
allow_redirects=False,
timeout=10,
)
if response.status_code != 402:
raise RuntimeError(f"Expected an x402 challenge, received HTTP {response.status_code}")
encoded = response.headers.get("payment-required")
if not encoded or len(encoded) > MAX_HEADER_CHARS:
raise RuntimeError("The payment-required header was missing or too large")
try:
decoded = base64.b64decode(encoded, validate=True)
if len(decoded) > MAX_DECODED_BYTES:
raise RuntimeError("The decoded payment-required terms were too large")
terms = json.loads(decoded.decode("utf-8", errors="strict"))
except (binascii.Error, UnicodeDecodeError, json.JSONDecodeError, ValueError) as error:
raise RuntimeError("The payment-required header was not strict base64 UTF-8 JSON") from error
if not isinstance(terms, dict):
raise RuntimeError("The payment-required header was not a JSON object")
if terms.get("x402Version") != 2:
raise RuntimeError("The payment-required terms were not x402 v2")
def bounded(value, limit=160):
return value[:limit] if isinstance(value, str) else value
resource = terms.get("resource") if isinstance(terms.get("resource"), dict) else {}
accepted = terms.get("accepts") if isinstance(terms.get("accepts"), list) else []
if resource.get("url") != EXPECTED_RESOURCE:
raise RuntimeError("The payment resource did not match the requested report")
if not 1 <= len(accepted) <= MAX_ACCEPTS:
raise RuntimeError("The payment-required terms contained an invalid offer count")
def valid_offer(item):
if not isinstance(item, dict):
return False
extra = item.get("extra")
if extra is not None and not isinstance(extra, dict):
return False
transfer_method = extra.get("assetTransferMethod") if isinstance(extra, dict) else None
asset = item.get("asset")
amount = item.get("amount")
return (
item.get("scheme") == "exact"
and item.get("network") == EXPECTED_NETWORK
and isinstance(asset, str)
and asset.lower() == EXPECTED_ASSET.lower()
and isinstance(amount, str)
and amount == EXPECTED_AMOUNT
and amount.isascii()
and amount.isdecimal()
and (amount == "0" or not amount.startswith("0"))
and transfer_method in (None, "eip3009")
)
offer = next((item for item in accepted if valid_offer(item)), None)
if offer is None:
raise RuntimeError("No offer matched the exact Base-mainnet $0.10 USDC policy")
safe_terms = {
"x402Version": terms.get("x402Version"),
"resource": bounded(resource.get("url")),
"accepts": [
{
"scheme": bounded(offer.get("scheme")),
"network": bounded(offer.get("network")),
"asset": bounded(offer.get("asset")),
"amount": bounded(offer.get("amount")),
"assetTransferMethod": bounded((offer.get("extra") or {}).get("assetTransferMethod")),
}
],
}
print(json.dumps(safe_terms, indent=2))This is challenge inspection only, not a full paid Python client. Use an independently reviewed x402 wallet policy before authorising payment.
https://pay.edge-agents.ai/.well-known/agent-catalog.jsonResearch and risk intelligence only. Not financial advice or a personalised recommendation.