Trango ComputeContextIQ
x402Policy CheckERC-8004USDCBasex402-fetchAI agentsagent commerce

How to Pay ContextIQ's Policy Check API With x402: A Technical Walkthrough

A hands-on x402 walkthrough: the 402 challenge, signing a USDC payment on Base with x402-fetch, and reading the ERC-8004-backed decision from ContextIQ's Policy Check API.

August 29, 2026Trango Compute Inc.

Policy Check is built to be called by code, not just clicked in a dashboard — an agent framework hits it right before authorizing a payment to some counterparty, and gets back an allow / warn / block decision it can act on automatically. That means the interesting integration path isn't the UI, it's calling /api/v1/policy-check directly and paying for it the way an autonomous agent actually would: per call, in USDC, with no account and no API key. This is a hands-on walkthrough of that flow — real requests, real response shapes, nothing hypothetical.

What You Need

A wallet with a small amount of USDC on Base (each call is $0.05) and a way to sign an x402 payment — this walkthrough uses x402-fetch, a Node package that wraps fetch and handles the entire challenge-sign-retry cycle for you. No ContextIQ account, no API key, no sign-up.

Step 1: The Anonymous Request Gets a 402, Not an Answer

Call the endpoint with no payment attached and you get back a structured HTTP 402 Payment Required, not an error:

curl -X POST https://contextiq.trango-compute.com/api/v1/policy-check \
  -H "Content-Type: application/json" \
  -d '{"endpoint": "https://api.example.com/paid-resource", "agentId": "1", "network": "ethereum"}'
{
  "x402Version": 1,
  "accepts": [
    {
      "scheme": "exact",
      "network": "base",
      "maxAmountRequired": "50000",
      "resource": "https://contextiq.trango-compute.com/api/v1/policy-check",
      "description": "Policy Check — pre-payment counterparty risk check (identity + reputation + payment challenge) — per call",
      "mimeType": "*/*",
      "payTo": "0x4eba5ea3cf0f3fc307099317e17e54390f7a4c58",
      "maxTimeoutSeconds": 300,
      "asset": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
      "extra": { "name": "USDC", "version": "2" }
    }
  ],
  "error": "Payment required"
}

Every field here is something a client needs to construct a payment, not documentation fluff: scheme: "exact" means pay this exact amount, no more, no less; maxAmountRequired is 50000 atomic units of a 6-decimal token — $0.05 USDC; asset is USDC's real contract address on Base mainnet; payTo is where it settles; maxTimeoutSeconds bounds how long the signed payment stays valid. resource is the exact URL the payment is scoped to — it won't validate against a different endpoint, by design.

Step 2: Sign and Pay With x402-fetch

You could hand-roll the EIP-3009 transferWithAuthorization signature this challenge implies, but there's no reason to. x402-fetch wraps fetch, catches the 402, signs the payment with a wallet client, and retries — the whole cycle in one call:

npm install x402-fetch viem
import { createWalletClient, http } from "viem";
import { privateKeyToAccount } from "viem/accounts";
import { wrapFetchWithPayment } from "x402-fetch";
import { base } from "viem/chains";

const account = privateKeyToAccount(process.env.WALLET_PRIVATE_KEY as `0x${string}`);
const client = createWalletClient({ account, transport: http(), chain: base });

const fetchWithPay = wrapFetchWithPayment(fetch, client);

const response = await fetchWithPay("https://contextiq.trango-compute.com/api/v1/policy-check", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({
    endpoint: "https://api.example.com/paid-resource",
    agentId: "1",
    network: "ethereum",
  }),
});

const result = await response.json();
console.log(result);

wrapFetchWithPayment takes an optional third argument capping the amount it's willing to authorize (defaults to $0.10) — worth setting explicitly in production code so a misconfigured endpoint can't silently charge more than you expect. Under the hood: it re-requests with the signed proof in an X-PAYMENT header, ContextIQ's middleware verifies it against Coinbase's CDP facilitator, and only then does the request actually reach Policy Check's logic.

One naming note if you go looking at package docs: x402-fetch (unscoped, the one used above) implements x402 wire version 1 — the version ContextIQ's /api/v1/* routes speak — and is now marked legacy/security-patches-only upstream. The actively developed replacement is the scoped @x402/fetch package, which speaks wire version 2. More on why that distinction matters below.

Step 3: Read the Decision

A successful call returns exactly the JSON shape documented in the worked examples post — a categorical decision, a transparent 0–100 score with every point traced to a named check, and the full identity/payment data the score was computed from:

{
  "decision": "allow",
  "score": 70,
  "maxScore": 100,
  "reasons": [
    { "check": "erc8004_identity_found", "points": 15, "maxPoints": 15, "detail": "Agent #1 is registered on Ethereum" },
    { "check": "x402_challenge_valid", "points": 25, "maxPoints": 25, "detail": "Payment challenge is well-formed with a usable option" }
  ],
  "identity": { "agentId": "1", "network": "ethereum", "status": "found" },
  "payment": { "target": "https://api.example.com/paid-resource", "status": "valid" },
  "scannedAt": "2026-08-27T12:00:00.000Z"
}

The decision field is what you gate on; score and reasons are there so "why" isn't a black box a downstream reviewer has to trust blindly. An agent framework can act purely on decision, or apply its own threshold to score — both are meant to be usable independently.

Alternative: A Pro API Key Instead of x402

If you're calling this from a server you control and don't want to manage a hot wallet for micropayments, the same endpoint accepts a Pro API key instead:

curl -X POST https://contextiq.trango-compute.com/api/v1/policy-check \
  -H "Authorization: Bearer sk_live_..." \
  -H "Content-Type: application/json" \
  -d '{"endpoint": "https://api.example.com/paid-resource", "agentId": "1", "network": "ethereum"}'

Same response, same logic, flat monthly Pro pricing instead of per-call USDC. Both auth paths are handled by the same route — the server checks for an Authorization header first, and only falls through to the x402 challenge if one isn't present. Keys are generated from the Developers page, which — along with every endpoint's docs — is viewable without an account; only key creation itself requires signing in.

The x402 v2 Pilot — What's Different, and What's Not Ready Yet

There's a second route, /api/v2/policy-check, with identical decision logic but a different wire protocol: x402 version 2. It's worth understanding as a distinct case, not just "the newer one":

  • The payment challenge moves out of the JSON body entirely and into a base64-encoded PAYMENT-REQUIRED response header — the spec calls the body itself "a server implementation concern."
  • Network ids switch to CAIP-2 format (eip155:8453 instead of base), and the challenge carries a Bazaar discovery extension describing the endpoint's input/output shape.
  • The client sends its signed proof back via a PAYMENT-SIGNATURE header, not X-PAYMENTx402-fetch (the legacy v1 package used above) won't work against it; you'd need @x402/fetch instead.

The v2 challenge shape is confirmed correct — it passes Coinbase's own public Bazaar validator with every check green, which is the whole reason the route exists: v1 challenges get rejected by that validator outright, before it checks anything else. But two things keep it a pilot rather than a recommendation: actual settlement over v2 hasn't been exercised against a real payment yet, and passing the validator hasn't (yet) translated into the route actually appearing in Coinbase's Bazaar catalog — a gap documented independently by other sellers, not something specific to this implementation. Use /api/v1/policy-check for anything that needs to work today.

Try It

Every example above is a real, currently-live call — the challenge shape, the pricing, the response fields are all exactly what you'll get hitting /api/v1/policy-check right now. Policy Check is a Pro feature callable from the dashboard for exploring by hand, or via the API for wiring into an agent framework's payment-authorization step. Full docs for this and every other ContextIQ endpoint are on the Developers page — no login required to read them.

Try ContextIQ free

Free tools for AI engineers.

Follow Trango Compute on LinkedIn

We post updates on new tools, context engineering patterns, and LLM cost research.

Follow on LinkedIn