Examples
These examples show the “challenge → sign → retry” pattern. For a deeper explanation, see Payment Flow (x402).
cURL (see the headers)
curl -i "https://sentiment-api.kytona.com/v2/snapshot/crypto?format=compact_trading&fields=ts,mood,rec"TypeScript (v2, Base/EVM)
import { decodePaymentRequiredHeader } from "@x402/core/http";
import { ExactEvmScheme } from "@x402/evm";
export async function fetchPaid<T>(url: string) {
const challenge = await fetch(url);
if (challenge.status !== 402) throw new Error(`Expected 402, got ${challenge.status}`);
let requirements: any = null;
try {
requirements = await challenge.json();
} catch {}
if (!requirements?.accepts?.length) {
const header = challenge.headers.get("PAYMENT-REQUIRED");
if (!header) throw new Error("Missing PAYMENT-REQUIRED header");
requirements = decodePaymentRequiredHeader(header);
}
const scheme = new ExactEvmScheme({
privateKey: process.env.EVM_PRIVATE_KEY!,
network: "eip155:8453",
});
const sig = await scheme.sign(requirements);
const paid = await fetch(url, { headers: { "PAYMENT-SIGNATURE": sig.encodedSignature } });
if (!paid.ok) throw new Error(`Paid request failed: ${paid.status} ${await paid.text()}`);
return (await paid.json()) as T;
}
const url =
"https://sentiment-api.kytona.com/v2/snapshot/crypto?format=compact_trading&fields=ts,mood,rec";
const data = await fetchPaid<{ mood: number; rec: string }>(url);
console.log(data);Python (conceptual)
The exact import paths depend on the Python x402 client you’re using. The core pattern is identical:
GETthe endpointOn
402, parse requirementsSign locally
Retry with
PAYMENT-SIGNATURE
Last updated
