Back to blog
Build Your Own Agent8 min read

Crypto Market Data Agent: Agentic AI Payments With CoinMarketCap x402

No API key, no monthly plan, just a wallet and a signature. Here's how we wired an agent that pays CoinMarketCap a few cents in USDC every time it asks a question, and what our first real test against an empty wallet actually looked like.

Abhishek Upadhyay
Abhishek Upadhyay
Crypto Market Data Agent: Agentic AI Payments With CoinMarketCap x402

Agentic AI Payments in Practice: A Crypto Market Data Agent That Pays Per Call

A crypto market data agent that calls CoinMarketCap's live x402 endpoint is agentic AI payments in practice. The model asks a question, and something underneath has to price the request, sign a payment, and hand CoinMarketCap real USDC before any data comes back, no subscription, no plan, no API key sitting in an .env file anywhere. That "something underneath" is the part most tutorials skip, because it's the part that actually moves money.

Key Takeaways

  • This agent pays CoinMarketCap directly, per call, in USDC on Base mainnet, using the x402 protocol. There is no key to request and no plan to pick.
  • Abstraxn's MCP layer never signs the payment. It relays CoinMarketCap's 402 challenge back exactly as received, the same pattern already used for Bitrefill and every OpenWeb Ninja tool in this stack.
  • Payments and Identity carry the weight for this agent: the payment itself, and reusing the exact access key the agent's wallet was created with, since a fresh one can't touch funds that already exist.
  • Our first instinct was wrong. We started by signing inside Abstraxn's tool host with a platform key, the same shape as an existing integration. Looking at how every other x402 upstream in this codebase already worked told us that wasn't it.
  • Clone examples/05-crypto-market-data, fund the agent's wallet with a few cents of USDC on Base, and ask it Bitcoin's price.

We built the signing step twice. The first version lived inside web3-agent-kit-service, Abstraxn's own MCP tool host, and used the same platform API key that an existing integration already used for a different payment protocol. It was a reasonable guess: there was precedent for a per-call key parameter, and it meant the example app didn't need to know anything about signing. It was also the wrong shape, and we only caught it by reading the rest of the codebase instead of trusting the analogy.

The short version: CoinMarketCap's MCP server is paywalled with x402: every tool call gets a 402 until a valid signed payment comes with it. Abstraxn's MCP layer hosts twelve cmc_* tools and relays that 402 back untouched, never signing anything itself. This example app catches the challenge, signs it with the agent's own server-wallet access key, and retries once. Clone examples/05-crypto-market-data. If Hello Wallet already runs on your machine, this is one more pnpm --filter and a few cents of USDC away.

What does a crypto market data agent actually do?

Ask it Bitcoin's price and it doesn't reach for a cached number or a free tier. It calls cmc_search_cryptos to resolve "Bitcoin" to CoinMarketCap's numeric id, then calls cmc_get_crypto_quotes with that id. Ask about holder concentration, trending narratives, or an upcoming macro event like an FOMC meeting, and it reaches for one of eleven other cmc_* tools instead. Those cover technical analysis, news, and global market context, and none of them need an id at all.

Every one of those calls is metered. CoinMarketCap's x402 endpoint doesn't check a bearer token or an API key; it checks whether the request carries a valid payment. The first attempt at any tool never does, so it comes back as a 402 with a priced challenge attached: pay this much, in this asset, on this network, to this address, and try again. That's the moment every other tutorial about "AI agents that use tools" quietly skips past. This one doesn't get to.

The wall: reasoning about a price is easy, paying for it isn't

An LLM can reason perfectly well about what CoinMarketCap's response means. It cannot hold a wallet, and it should not be trusted to decide, on its own, when a payment is worth signing. Somewhere between "the model wants this data" and "the data actually arrives," something has to hold a real key and check the price against a real limit. Then it has to produce a real signature, without the model ever seeing the credential that did it.

That gap isn't a shortcoming unique to CoinMarketCap's design. Any pay-per-call API sits behind the same wall: the request is cheap to reason about and expensive to actually authorize. x402 just makes the wall explicit instead of hiding it behind a support ticket for API access.

The Four Powers behind agentic AI payments

Every agent Abstraxn provisions gets the same four things underneath it: a verifiable identity, a wallet it controls, a way to pay, and policy that keeps it in bounds. A trading agent leans hardest on Wallet and Policy. This one leans on Payments and Identity instead, since it's authenticating to a paid data source and settling a transaction on nearly every message.

Payments. This is the whole point of the example. x402 is live, and CoinMarketCap's endpoint speaks it natively: decode the 402, build a signed payment authorization, attach it, retry. Nothing here is simulated. The agent's own USDC balance is what makes or breaks the call.

Identity. Signing only works if it's done as the wallet that already exists, not a new one. The agent's server-wallet access key gets reused on every payment, the same key that was issued when the wallet was first created. Authenticate without it and the signer mints a fresh, unrelated key that has no claim on the funds already sitting in the real wallet. Reusing it correctly is what lets a payment actually clear.

Wallet. The wallet itself is the same one every agent in this series gets through Abstraxn WaaS, the same get_wallet_address Hello Wallet smoke-tests. This example doesn't add a second wallet; it just spends from the one that was already there.

Policy. One control is live here: a per-transaction limit, X402_MAX_PAYMENT_USD, checked against the challenge before any signature happens. Ask CoinMarketCap for something priced above that cap and the agent refuses to sign it, full stop. Nothing broader runs in this example, and nothing broader is claimed.

How does CoinMarketCap's 402 challenge actually get paid?

Abstraxn's tool host never touches the signature. cmc_get_crypto_quotes and its eleven siblings call CoinMarketCap directly and hand back whatever comes: a real result, or a decoded 402 challenge, unmodified either way. That's the same shape Bitrefill's gift card tool and every OpenWeb Ninja tool already use in this stack for their own upstream paywalls. It's also exactly what made the first, platform-key version of this feature the wrong call: it solved a problem that didn't exist here, and it put a signing responsibility in a place it never belonged.

LayerRole
LLMDecides which cmc_* tool answers the question, reads back the result
Abstraxn MCPHosts the twelve cmc_* tools, relays CoinMarketCap's 402 back untouched, signs nothing
This app's signerCatches the 402, signs with the agent's own access key, retries once
CoinMarketCap x402 endpointVerifies the signed payment, settles it, returns the real data
Agent's Base walletPays every call directly, in USDC, no subscription anywhere
Browser chat → /api/chat → cmc_get_crypto_quotes, unsigned      ← CoinMarketCap returns 402 + challenge
                         → sign with the agent's own access key ← this app, not Abstraxn's tool host
                         → cmc_get_crypto_quotes, signed retry  ← CoinMarketCap verifies, returns data

Our first real end-to-end run against a genuinely funded wallet came back clean: challenge decoded, payment signed without a single error, retry accepted. The run before that, against a brand-new agent we'd never sent USDC to, failed too, but at the right place: CoinMarketCap's facilitator rejected the signed payment for insufficient funds. That's not a signing bug. That's the balance check doing exactly its job, on a wallet that had genuinely never been funded.

The code: the catch, the signer, the tool set

The part worth reading first is the retry logic, since it's the only new decision this example makes. Everything else, the chat loop, the wallet bootstrap, the MCP wiring, is the same scaffold every example in this series shares.

// packages/mcp/src/index.ts
const first = await mcp.rpc("tools/call", { name, arguments: args }, {
  executionContext: "delegated",
});
if (first.error?.code === -32402) {
  const paymentPayload = await signX402Payment(session, first.error.data.paymentRequirements);
  const retry = await mcp.rpc("tools/call", { name, arguments: args, paymentPayload }, {
    executionContext: "delegated",
  });
  return retry.result;
}

Signing itself lives in its own package, next to the rest of this app's wallet code, not inside Abstraxn's tool host:

// packages/wallet/src/x402-signer.ts
export async function signX402Payment(session, paymentRequired) {
  // reuse session.accessKey, refuse anything outside Base USDC or over X402_MAX_PAYMENT_USD,
  // sign through the agent's own server wallet, return the completed payment payload
}

And the tool set is one named entry in the same shared MCP config every example reads from:

// packages/mcp/src/index.ts
cmcMarketData: [
  "cmc_search_cryptos",
  "cmc_get_crypto_quotes",
  "cmc_get_crypto_info",
  "cmc_get_crypto_news",
  "cmc_get_technical_analysis",
  "cmc_get_holder_metrics",
  "cmc_search_crypto_info",
  "cmc_get_trending_narratives",
  "cmc_get_derivatives_metrics",
  "cmc_get_global_metrics",
  "cmc_get_macro_events",
  "cmc_get_marketcap_technical_analysis",
  "get_wallet_address",
]

lib/agent.ts still defines what the agent decides and when, in plain English, nothing else:

// examples/05-crypto-market-data/lib/agent.ts
export const agentConfig: AgentConfig = {
  name: "Crypto Market Data Agent",
  tools: "cmcMarketData",
  system: `Every cmc_* tool call is paid automatically the moment you call it, so only
call a tool when its data is actually needed, and never call the same tool twice for
the same question. Most tools need a numeric id, not a ticker; resolve one with
cmc_search_cryptos first if you don't already have it.`,
};

Run it

git clone https://github.com/Abstraxn-Labs/abstraxn-agent-examples
cd abstraxn-agent-examples
pnpm install
cp .env.example .env
pnpm run build:packages
pnpm --filter @abstraxn-examples/crypto-market-data dev

Environment variables

VariableWhereNotes
ABSTRAXN_API_KEYabstraxn-agent-examples/.envDashboard → Agentic Stack → Overview
ABSTRAXN_USER_IDENTITYabstraxn-agent-examples/.envAny stable identity string, e.g. an email
LLM_PROVIDER / LLM_API_KEY / LLM_MODELabstraxn-agent-examples/.envOne provider block, see docs/LLM-PROVIDERS.md
CHAIN_RPC_BASEabstraxn-agent-examples/.env, optionalDefaults to a public Base mainnet RPC
X402_MAX_PAYMENT_USDabstraxn-agent-examples/.env, optionalHard cap per payment, defaults to $0.05

Open http://localhost:3005 and try:

What's Bitcoin's price and 24-hour trend?

Watch for the sequence in your terminal: a 402 logged, a signed payment logged, then either a completed result or a plain insufficient-funds rejection.

Before you go live

CoinMarketCap's x402 endpoint has no sandbox and no test mode. It's live mainnet, full stop. Before any cmc_* call can succeed, send the agent's own wallet, the address get_wallet_address returns, a small amount of real USDC on Base. A first call from a freshly created, unfunded agent is expected to fail with an insufficient-funds rejection. Treat that as confirmation the payment path is real, not a bug to chase down. Keep X402_MAX_PAYMENT_USD low while you're testing, and only raise it once you've watched one full ask, sign, and pay cycle complete and match what you expected.

Further reading: MCP integration · Building an agent that pays its own API bills

Next in the series

If Hello Wallet already works for you, this example is the next short step: same scaffold, same wallet bootstrap, one new package handling the signature. Firecrawl research is the closest sibling, another agent that leans on Payments and Identity rather than Wallet and Policy, just against a scrape instead of a quote. Trading agent and fraud and policy agent go the other direction, leaning on Wallet and Policy instead.

FAQ

Does this agent need a CoinMarketCap API key?

No. CoinMarketCap's x402 endpoint takes no key and no plan at all. Every call is priced individually and settled in USDC on Base mainnet, so the only thing the agent needs is its own wallet with a small USDC balance.

What happens if the agent's wallet has no USDC?

The signed payment goes out, CoinMarketCap's facilitator checks it against the wallet, and it comes back rejected for insufficient funds. That is a normal, expected result on a freshly created agent, not a bug. It is actually proof the payment path works: the challenge was real, the signature was accepted, and only the balance check stopped it.

Who signs the x402 payment, Abstraxn or this example app?

This app does. Abstraxn's MCP layer only relays CoinMarketCap's 402 challenge back untouched, the same way it already does for Bitrefill and the OpenWeb Ninja tools. Signing happens here, using the agent's own server-wallet access key, so no platform-level signing key is involved anywhere in the flow.

Which MCP tools does this agent use, and what do they cost?

Twelve cmc_* tools covering quotes, technical analysis, holder metrics, news, trending narratives, and global or macro market context. Each call costs around a cent in USDC on Base. A hard cap, X402_MAX_PAYMENT_USD, refuses to sign anything priced above it.

About the Author

Abhishek Upadhyay

Abhishek Upadhyay

Software Engineer

Abhishek Upadhyay is a Software Engineer at Abstraxn. He builds MCP tool integrations, wires payment protocols into agent workflows, and contributes to the open-source Build your Agent with Abstraxn series.