Canopy

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.content

The 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 outcomesfetch() surfaces the same outcomes as pay() for paid responses
  • TypeScript SDK reference — full fetch and discover signatures