x402 — Auto-pay paywalled APIs
x402 is an HTTP protocol extension for machine-to-machine payments. When a server requires payment for a resource, it returns a 402 Payment Required response with payment details. The client pays, then retries the original request. Your code never sees the 402 — it receives the content directly.
Canopy's fetch() is a drop-in replacement for the global fetch (TypeScript) or for httpx requests (Python) that handles the exchange transparently. Non-402 responses pass through unchanged, so you can use canopy.fetch() everywhere without breaking normal HTTP calls.
Calling a paywalled API
import { Canopy } from "@canopy-ai/sdk";
const canopy = new Canopy({
apiKey: process.env.CANOPY_API_KEY!,
agentId: process.env.CANOPY_AGENT_ID!,
});
// The 402 handshake is invisible — you get the final 200 response
const res = await canopy.fetch("https://paid-api.example.com/generate-image");
const data = await res.arrayBuffer();res = canopy.fetch("https://paid-api.example.com/generate-image")
data = res.contentThe same agent policy that governs pay() applies here. If a paywall asks for an amount above the agent's approval threshold, fetch() returns a pending_approval outcome that the SDK will surface.
Discovering services to pay
Instead of hardcoding endpoint URLs, query Canopy's registry of x402 services:
const services = await canopy.discover({ category: "data", query: "orderbook" });
const feed = services.find((s) => s.policyAllowed && s.url);
if (feed) {
const res = await canopy.fetch(feed.url);
const data = await res.json();
}services = canopy.discover(category="data", query="orderbook")
feed = next((s for s in services if s["policy_allowed"] and s["url"]), None)
if feed:
res = canopy.fetch(feed["url"])
data = res.json()Each result includes policyAllowed: true | false so the agent (and the LLM behind it) can reason about which services are available before spending.
Where to go next
- MPP — Tempo-rail counterpart for sub-cent calls; same
fetch()handles both - Payment outcomes —
fetch()surfaces the same outcomes aspay()for paid responses - TypeScript SDK reference — full
fetchanddiscoversignatures