Skip to main content
x402 support is currently in beta. Endpoints, pricing, and supported networks may change. Join the Mobula Telegram to report issues or share feedback.
Mobula’s x402 endpoints deliver real-time crypto data without an API key. Each request costs $0.001 USDC, paid directly on-chain at the moment you call the API. There is no account, no subscription, and no rate limit tied to credentials — your wallet balance is the only thing you need. This model works particularly well for AI agents, automated scripts, and any application that makes infrequent or unpredictable API calls.

Endpoints

EndpointData returnedPrice per call
GET /x402/market/detailsDEX pool price, liquidity, volume, and trade metrics$0.001 USDC
GET /x402/token/detailsToken price, market cap, holder stats, and security flags$0.001 USDC
GET /x402/cefi/funding-ratePerpetual funding rates across Binance, Bybit, OKX, Deribit, Hyperliquid, Gate, and Lighter$0.001 USDC

How Payment Works

On the first request (no payment), the server returns 402 Payment Required with a payment-required header describing what to pay, on which network, and to which address. Your client signs the USDC transfer and retries with an x-payment header. The server verifies and settles on-chain, then returns the data. The entire handshake happens within your existing HTTP client — no wallet UI, no browser extension.

TypeScript — Base Mainnet (EVM)

x402 endpoints require a cryptographically signed USDC transfer in the request header — a standard fetch call cannot produce this on its own. The three packages below handle it:
PackageRole
@x402/coreDecodes the payment-required header and orchestrates the handshake
@x402/evmSigns the EIP-3009 transferWithAuthorization payload using your EVM wallet
viemConverts your private key into a compatible signer
npm install @x402/core @x402/evm viem
The following helper wraps the 402 handshake. Set it up once and call it like a regular fetch.
import { x402Client, x402HTTPClient } from '@x402/core/client';
import { registerExactEvmScheme } from '@x402/evm/exact/client/register';
import { privateKeyToAccount } from 'viem/accounts';

// Initialise once at application startup
const account = privateKeyToAccount(process.env.EVM_PRIVATE_KEY as `0x${string}`);
const coreClient = new x402Client();
registerExactEvmScheme(coreClient, { signer: account });
const httpClient = new x402HTTPClient(coreClient);

async function mobulaFetch(url: string): Promise<unknown> {
  const probe = await fetch(url);
  if (probe.status !== 402) return probe.json();

  const raw = probe.headers.get('payment-required')!;
  const decoded = JSON.parse(Buffer.from(raw, 'base64').toString());

  const requirement = httpClient.getPaymentRequiredResponse(
    (header) => probe.headers.get(header),
    decoded,
  );
  const payload  = await httpClient.createPaymentPayload(requirement);
  const headers  = httpClient.encodePaymentSignatureHeader(payload);

  const res = await fetch(url, { headers });
  if (!res.ok) throw new Error(`Payment rejected — HTTP ${res.status}`);
  return res.json();
}

// Example calls
const poolData  = await mobulaFetch('https://api.mobula.io/x402/market/details?address=0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640&blockchain=Ethereum');
const tokenData = await mobulaFetch('https://api.mobula.io/x402/token/details?address=0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2&blockchain=Ethereum');
const rates     = await mobulaFetch('https://api.mobula.io/x402/cefi/funding-rate?symbol=BTC');
Requirements
  • EVM private key (0x…) — MetaMask: Account Details → Export Private Key
  • USDC on Base mainnet at 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913
  • ETH on Base for gas (a few cents covers hundreds of calls)

TypeScript — Solana Mainnet

The same mobulaFetch pattern works for Solana. The only difference is the signer — @x402/svm produces an SPL token transfer instead of an EIP-3009 payload.
npm install @x402/core @x402/svm @solana/kit bs58
import { x402Client, x402HTTPClient } from '@x402/core/client';
import { registerExactSvmScheme } from '@x402/svm/exact/client';
import { createKeyPairSignerFromBytes } from '@solana/kit';
import bs58 from 'bs58';

const signer = await createKeyPairSignerFromBytes(
  bs58.decode(process.env.SOLANA_PRIVATE_KEY!)
);
const coreClient = new x402Client();
registerExactSvmScheme(coreClient, { signer });
const httpClient = new x402HTTPClient(coreClient);

// mobulaFetch — identical body to the EVM version above
async function mobulaFetch(url: string): Promise<unknown> {
  const probe = await fetch(url);
  if (probe.status !== 402) return probe.json();

  const raw = probe.headers.get('payment-required')!;
  const decoded = JSON.parse(Buffer.from(raw, 'base64').toString());

  const requirement = httpClient.getPaymentRequiredResponse(
    (header) => probe.headers.get(header),
    decoded,
  );
  const payload = await httpClient.createPaymentPayload(requirement);
  const headers = httpClient.encodePaymentSignatureHeader(payload);

  const res = await fetch(url, { headers });
  if (!res.ok) throw new Error(`Payment rejected — HTTP ${res.status}`);
  return res.json();
}
Requirements
  • Solana private key in base58 format — Phantom or Backpack: Settings → Security → Export Private Key
  • USDC on Solana mainnet at EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v
  • SOL for transaction fees

Exposing as Agent Tools

Register mobulaFetch once at agent startup, then wrap each endpoint in a named function. The x402 Bazaar extension embedded in the 402 response includes a machine-readable JSON schema of the response, so an agent can inspect what it will receive before committing to payment.
// tools/mobula.ts
export function getMarketDetails(poolAddress: string, blockchain: string) {
  return mobulaFetch(
    `https://api.mobula.io/x402/market/details?address=${poolAddress}&blockchain=${blockchain}`
  );
}

export function getTokenDetails(tokenAddress: string, blockchain: string) {
  return mobulaFetch(
    `https://api.mobula.io/x402/token/details?address=${tokenAddress}&blockchain=${blockchain}`
  );
}

export function getCeFiFundingRates(symbol: string, exchange?: string) {
  const params = new URLSearchParams({ symbol });
  if (exchange) params.set('exchange', exchange);
  return mobulaFetch(`https://api.mobula.io/x402/cefi/funding-rate?${params}`);
}
Each invocation settles $0.001 USDC on-chain atomically with the data retrieval. There are no separate billing cycles or credential refresh flows to manage.

Verifying the Flow End-to-End

Two ready-made scripts in the repository exercise the complete 402 → sign → settle cycle against the live API. Run either one to confirm your wallet and USDC balance are configured correctly before integrating into your application. Solana mainnet
SOLANA_PRIVATE_KEY="<base58_key>" \
ENDPOINT="/x402/market/details?address=0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640&blockchain=Ethereum" \
API_URL="https://api.mobula.io" \
bun run apps/api/src/x402/test-payment-solana.ts
Base mainnet (EVM)
TEST_PRIVATE_KEY="0x<evm_key>" \
ENDPOINT="/x402/market/details?address=0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640&blockchain=Ethereum" \
API_URL="https://api.mobula.io" \
bun run apps/api/src/x402/test-payment.ts
Each script logs every step of the handshake and writes the full response JSON to /tmp/x402-response.json.

Using a Standard API Key Instead

All three endpoints are also available via the standard REST API with API key authentication. See Market Details, Token Details, and CeFi Funding Rate. Get a free API key at admin.mobula.io.