Skip to content

x402 — Pay-per-request micropayments

TCG API speaks x402, the HTTP 402 micropayment protocol built for AI agents. No account, no registration, no subscription — an agent that can hold USDC on Base or Solana can call every paid endpoint by attaching a signed payment to each request.

All existing X-API-Key auth keeps working unchanged. x402 is additive.

  • Discovery: /.well-known/x402.json
  • Live endpoint / price map: https://api.tcgapi.dev/v1/x402/info
  • Networks: Base mainnet and Solana mainnet — both settle in USDC (6 decimals).
  • Facilitator: Coinbase CDP — api.cdp.coinbase.com/platform/v2/x402 — serves both chains.
  • Spec: github.com/coinbase/x402
Terminal window
curl -i https://api.tcgapi.dev/v1/cards/123

Response:

HTTP/2 402
content-type: application/json
cache-control: no-store
vary: X-PAYMENT
{
"x402Version": 1,
"error": "X-PAYMENT header is required",
"accepts": [
{
"scheme": "exact",
"network": "base",
"maxAmountRequired": "5000",
"asset": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
"payTo": "0x908B2Cc89A2387F754ba3C80aedb06F3457436Aa",
"resource": "https://api.tcgapi.dev/v1/cards/123",
"description": "Single card details",
"maxTimeoutSeconds": 60,
"extra": { "name": "USD Coin", "version": "2" }
},
{
"scheme": "exact",
"network": "solana",
"maxAmountRequired": "5000",
"asset": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
"payTo": "AHk5DFmmdvPMjf6tZFrMPbHGhEBUDhUmcqmWkYANYthg",
"resource": "https://api.tcgapi.dev/v1/cards/123",
"description": "Single card details",
"maxTimeoutSeconds": 60,
"extra": { "feePayer": "BENrLoUbndxoNMUS5JXApGMtNykLjFXXixMtpDwDR9SP" }
}
]
}

Pick whichever chain your agent already holds USDC on and sign against that entry.

Base (EVM): Use the x402-fetch Node client — it picks the EVM entry from accepts[], EIP-712-signs a TransferWithAuthorization, and retries automatically.

import { wrapFetchWithPayment } from "x402-fetch";
import { privateKeyToAccount } from "viem/accounts";
const account = privateKeyToAccount(process.env.PRIVATE_KEY as `0x${string}`);
const fetchWithPayment = wrapFetchWithPayment(fetch, account);
const res = await fetchWithPayment("https://api.tcgapi.dev/v1/cards/123");
const data = await res.json();
const txHash = res.headers.get("X-Payment-Response"); // base64-encoded settlement

Solana: Use @x402/svm with a Solana keypair. The payload carries a pre-signed SPL TransferChecked instruction instead of an EIP-712 authorization; the outer envelope (scheme, network, base64 payload in X-PAYMENT) is identical.

import { ExactSvmSchemeV1 } from "@x402/svm/v1";
import { toClientSvmSigner } from "@x402/svm";
import { createKeyPairSignerFromBytes } from "@solana/kit";
import { base58 } from "@scure/base";
const keypair = await createKeyPairSignerFromBytes(base58.decode(process.env.SOLANA_PRIVATE_KEY!));
const client = new ExactSvmSchemeV1(toClientSvmSigner(keypair));
// Pick the solana entry from the 402 body, then:
const payload = await client.createPaymentPayload(1, svmRequirement);
const xPayment = Buffer.from(JSON.stringify({ ...payload, x402Version: 1 })).toString("base64");
const res = await fetch("https://api.tcgapi.dev/v1/cards/123", { headers: { "X-PAYMENT": xPayment } });

By hand: base64-encode {x402Version, scheme, network, payload} and retry with X-PAYMENT: <base64>. The payload shape differs per chain (EVM: signed authorization; SVM: { transaction: <base64 pre-signed tx> }).

HTTP/2 200
content-type: application/json
x-payment-response: <base64(SettlementResponse)>
cache-control: no-store
vary: X-PAYMENT
{ "data": { "id": 123, "name": "...", "tcgplayer_id": 456 }, "meta": {}, "payment": { "method": "x402", "tx_hash": "0x...", "amount_usdc": "5000" } }

All prices are atomic USDC (6 decimals on Base) per request.

EndpointsAtomicUSD
/v1/cards/{id}, /v1/cards/{id}/prices, /v1/cards/tcgplayer/{id}, /v1/cards/{id}/prices/cardmarket, /v1/cardmarket/coverage5000$0.005
/v1/sets, /v1/sets/{id}, /v1/sets/{id}/cards, /v1/sets/{id}/prices, /v1/sets/{id}/prices/cardmarket5000$0.005
/v1/search, /v1/prices/top-movers, /v1/cards/{id}/history5000$0.005
/v1/cards/{id}/history/detailed20000$0.020
/v1/bulk/prices, /v1/bulk/cards, /v1/bulk/history50000$0.050
/v1/export/set/{id}250000$0.250

Not x402-enabled: /v1/bulk/resolve/tcgplayer and /v1/bulk/resolve/name (subscription-only — they use per-item credit accounting that doesn’t map to a single x402 charge).

Public endpoints (/v1/games, /v1/games/{slug}, /v1/games/{slug}/sets, /v1/auth/*) never require payment.

  • No double-charge on retries. Each EIP-3009 nonce is recorded server-side. Replaying the same X-PAYMENT returns 402.
  • No CDN caching of paid responses. Both 402 and paid 200 responses set Cache-Control: no-store and Vary: X-PAYMENT.
  • Preflight is always free. OPTIONS requests return 204 and never trigger payment.
  • Rate limits don’t apply. x402 requests bypass the subscription daily-request quota (the payment is the rate limit).
  • No signup for your agents. Give an agent a USDC balance and it works.
  • Settlement is on-chain. Nothing to reconcile; the tx hash is the receipt.
  • Cheap. $0.005 is the floor for most read endpoints — cheaper than building and managing an API key for a one-off agent task.
  • Backward compatible. Your existing X-API-Key integrations don’t change.