API Documentation

The x402engine exposes 38 production APIs behind x402 micropayments. Every endpoint returns 402 Payment Required until a valid stablecoin payment is attached to the request.

Base URL https://x402-gateway-production.up.railway.app
Protocol x402 v2
Payment USDC on Base, USDC on Solana, or USDm on MegaETH
Free endpoints /health, /.well-known/x402.json, /api/discover, /api/services

Quick Start

Install the x402 client packages and viem:

bash
npm install @x402/fetch @x402/evm viem

Make your first paid call with TypeScript:

TypeScript
import { wrapFetchWithPayment, x402Client } from "@x402/fetch";
import { registerExactEvmScheme } from "@x402/evm/exact/client";
import { privateKeyToAccount } from "viem/accounts";

// Create account from private key
const account = privateKeyToAccount(process.env.PRIVATE_KEY as `0x${string}`);

// Initialize x402 client and register EVM payment scheme
const client = new x402Client();
registerExactEvmScheme(client, {
  signer: account,
  networks: ["eip155:8453"], // Base mainnet
});

// Wrap native fetch — handles 402 negotiation automatically
const paidFetch = wrapFetchWithPayment(fetch, client, {
  paymentRequirementsSelector: (accepts) => accepts.find(a => a.network === "eip155:8453"),
});

// Call any endpoint — payment is transparent
const BASE = "https://x402-gateway-production.up.railway.app";

// GET endpoint
const price = await paidFetch(`${BASE}/api/crypto/price?ids=bitcoin`);
console.log(await price.json());
// { bitcoin: { usd: 97234, usd_24h_change: 2.31 } }

// POST endpoint
const balances = await paidFetch(`${BASE}/api/wallet/balances`, {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ chain: "base", address: "0x..." }),
});
console.log(await balances.json());

How does payment work?

  1. paidFetch calls the endpoint normally
  2. Engine returns 402 with payment requirements in headers
  3. The wrapper reads the requirements, signs a USDC/USDm permit or transfer
  4. It retries the request with the payment in X-PAYMENT header
  5. Engine verifies the payment, calls the upstream API, and returns data

💡 Test All Endpoints

Want to test all 38 endpoints at once? Download our comprehensive test suite:

curl -O https://x402-gateway-production.up.railway.app/test-all-endpoints.mjs
TEST_PRIVATE_KEY=0x... node test-all-endpoints.mjs

Includes proper parameters and examples for every endpoint category.

Payment Flow

If you're building a custom client (not using @x402/fetch), here's the raw HTTP flow:

Step 1: Initial request

GET /api/crypto/price?ids=bitcoin HTTP/1.1
Host: x402-gateway-production.up.railway.app

Step 2: 402 response

The engine returns payment requirements as base64 JSON in the PAYMENT-REQUIRED header:

HTTP/1.1 402 Payment Required
PAYMENT-REQUIRED: eyJ4NDAyVmVyc2lvbiI6MiwiYWNjZXB0cyI6Wy4uLl19
Content-Type: application/json

{
  "error": "X-PAYMENT header is required",
  "accepts": [
    {
      "scheme": "exact",
      "network": "eip155:8453",
      "maxAmountRequired": "1000",
      "resource": "https://x402-gateway-.../api/crypto/price?ids=bitcoin",
      "payTo": "0x7dd5Be069f2d2eAd75eC7C3423B116fF043c2629",
      "extra": { ... }
    }
  ],
  "x402Version": 2
}

Step 3: Retry with payment

Sign a payment using the details from accepts and send it in the X-PAYMENT header:

GET /api/crypto/price?ids=bitcoin HTTP/1.1
Host: x402-gateway-production.up.railway.app
X-PAYMENT: <base64-encoded signed payment payload>

Step 4: Response with settlement

HTTP/1.1 200 OK
PAYMENT-RESPONSE: <base64 settlement receipt>
Content-Type: application/json

{ "bitcoin": { "usd": 97234.12, "usd_24h_change": 2.31 } }

Supported Networks

Network CAIP-2 Token Decimals Speed Verification
Base eip155:8453 USDC 6 ~2s Coinbase CDP facilitator
MegaETH eip155:4326 USDm 18 ~10ms Direct on-chain
Solana solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp USDC 6 ~400ms Coinbase CDP facilitator
Amount conversion: $0.001 = 1000 USDC (6 decimals) = 1000000000000000 USDm (18 decimals)

Base Payment Notes

Recommended rail. Base uses Permit2 gasless signatures — the @x402/fetch + @x402/evm SDK handles everything automatically. No on-chain transfer needed from the payer, no nonce management, no gas fees.

Concurrency: Safe to send multiple Base payments in parallel — Permit2 signatures are off-chain and don't conflict.

Common errors:

  • insufficient_funds — wallet doesn't have enough USDC on Base. Each endpoint costs $0.001–$0.10 depending on the API.
  • Permit2 allowance — if using Permit2 for the first time, the SDK may need a one-time USDC approval to the Permit2 contract.

⚠️ MegaETH Payment — Beta

MegaETH payments use a different flow than Base and Solana. The rail and on-chain verifier are live, but reliability is still being hardened — expect intermittent transfer reverts under concurrent load.

  • Base / Solana: Permit2 gasless signatures, handled automatically by @x402/fetch
  • MegaETH: Requires an actual on-chain USDm transfer, then include the txHash in the payment payload

MegaETH Payment Implementation

The gateway verifies MegaETH payments by fetching the transaction receipt and checking for a USDm Transfer event to the expected recipient. The flow:

  1. Fetch the 402 response to get accepts for eip155:4326
  2. Send a USDm ERC-20 transfer(payTo, amount) on MegaETH
  3. Wait for the transaction receipt (MegaETH confirms in ~10ms)
  4. Retry the request with the txHash in the x402 payment payload

Example (viem):

import { createWalletClient, createPublicClient, http, getAddress, parseGwei } from 'viem';

// MegaETH chain config
const megaeth = {
  id: 4326,
  name: 'MegaETH',
  nativeCurrency: { name: 'Ether', symbol: 'ETH', decimals: 18 },
  rpcUrls: { default: { http: ['https://mainnet.megaeth.com/rpc'] } },
};

// USDm token: 0xFAfDdbb3FC76884949..., 18 decimals
// $0.005 = 5000000000000000 (5e15)

const txHash = await walletClient.writeContract({
  address: usdmAddress,              // from accepts.asset
  abi: erc20TransferAbi,
  functionName: 'transfer',
  args: [accepts.payTo, BigInt(accepts.amount)],
  maxFeePerGas: parseGwei('0.001'),  // MegaETH base fee is stable
  maxPriorityFeePerGas: 0n,
  gas: 200_000n,
  chain: megaeth,
  account,
});

// IMPORTANT: wait for receipt before using the txHash
const receipt = await publicClient.waitForTransactionReceipt({
  hash: txHash, timeout: 5000,
});
if (receipt.status !== 'success') throw new Error(`Transfer reverted: ${txHash}`);

// Include txHash in the x402 payment payload
const payment = { x402Version: 2, payload: { txHash } };

Concurrency: If sending multiple MegaETH payments in parallel, serialize the writeContract + waitForTransactionReceipt calls with a mutex. Without this, concurrent calls fetch the same nonce from getTransactionCount and all but one will fail with "nonce too low".

Common errors:

  • Transaction reverted — the USDm transfer failed on-chain. Check wallet balance, gas params, and token address.
  • Transaction not found — the receipt wasn't available. Wait for the receipt before sending the txHash.
  • Transaction already used — replay protection. Each txHash can only be used for one payment.

Solana Payment Notes

Solana payments use the @x402/svm SDK with the Coinbase CDP facilitator. The SDK handles transaction construction automatically, but there are important considerations for reliability:

SDK version: Use @x402/svm@2.2.0. Version 2.3.0 adds a Memo instruction that the CDP facilitator does not yet support, causing all payments to be rejected.

Wallet requirements: Your Solana wallet needs two things: USDC (SPL token) to cover the accepts.amount from the 402 response, and a small amount of SOL for transaction fees (~0.000005 SOL per payment). If either is missing, you'll get confusing "payment required" loops where the code looks correct but the transaction silently fails simulation.

Example (@x402/fetch + @x402/svm):

import { x402Client, wrapFetchWithPayment } from '@x402/fetch';
import { ExactSvmScheme } from '@x402/svm';      // v2.2.0
import { createKeyPairSignerFromBytes } from '@solana/kit';

const signer = await createKeyPairSignerFromBytes(keypairBytes);
const scheme = new ExactSvmScheme(signer);

const client = new x402Client().register('solana:*', scheme);
const paidFetch = wrapFetchWithPayment(fetch, client);

// Use paidFetch like normal fetch — payment is automatic
const res = await paidFetch('https://x402engine.app/api/crypto/price?ids=bitcoin');
console.log(await res.json());

Rate limiting: The Solana public RPC (api.mainnet-beta.solana.com) has a strict rate limit (~10 req/s). If you're making many payments, consider using a dedicated RPC endpoint (Helius, Alchemy, QuickNode) with higher limits.

Common errors:

  • transaction_simulation_failed: Custom:1 — Insufficient USDC balance. Check wallet balance before creating the payment.
  • No matching payment requirements — feePayer mismatch between client and server. Use @x402/svm@2.2.0 and ensure the feePayer from the 402 response is used.

Discovery

Agents can discover available services and payment options programmatically.

GET /.well-known/x402.json Free

Full discovery document — services, networks, payment routes, categories.

GET /api/services Free

List all services with IDs, descriptions, pricing, and endpoints.

GET /api/services/:id Free

Service details including payment options. Example: /api/services/crypto-price


Crypto & Blockchain

GET /api/crypto/price $0.001

Real-time cryptocurrency prices in any fiat currency.

Parameters

NameTypeDescription
ids requiredstringComma-separated CoinGecko IDs, e.g. bitcoin,ethereum
currencies optionalstringComma-separated fiat codes. Default: usd
include_24h optionalstringtrue or false. Default: true
include_mcap optionalstringtrue or false. Default: false

Example Response

{
  "bitcoin": { "usd": 97234.12, "usd_24h_change": 2.31 },
  "ethereum": { "usd": 3456.78, "usd_24h_change": -0.45 }
}
GET /api/crypto/markets $0.002

Market rankings with price, volume, and market cap.

Parameters

NameTypeDescription
currency optionalstringFiat currency. Default: usd
category optionalstringFilter by CoinGecko category
order optionalstringSort order. Default: market_cap_desc
limit optionalnumberResults per page, max 250. Default: 100
page optionalnumberPage number. Default: 1

Example Response

[
  { "id": "bitcoin", "symbol": "btc", "name": "Bitcoin",
    "current_price": 97234, "market_cap": 1920000000000, ... }
]
GET /api/crypto/history $0.003

Historical price, market cap, and volume data.

Parameters

NameTypeDescription
id requiredstringCoinGecko coin ID, e.g. bitcoin
currency optionalstringDefault: usd
days optionalstringDays of history or "max". Default: 30
interval optionalstringData interval, e.g. daily

Example Response

{
  "prices": [[1706745600000, 43012.5], [1706832000000, 43150.2], ...],
  "market_caps": [...],
  "total_volumes": [...]
}
POST /api/wallet/balances $0.005

Token balances for any wallet across 20+ chains. Powered by Allium.

Request Body

FieldTypeDescription
chain requiredstringChain name: ethereum, base, solana, etc.
address requiredstringWallet address

Example

Request
POST /api/wallet/balances
Content-Type: application/json

{ "chain": "base", "address": "0x7dd5Be069f2d2eAd75eC7C3423B116fF043c2629" }
Response
{
  "balances": [
    { "token_symbol": "USDC", "balance": "164.23", "usd_value": 164.23, ... },
    { "token_symbol": "ETH", "balance": "0.05", "usd_value": 162.50, ... }
  ]
}
POST /api/wallet/transactions $0.005

Transaction history with asset transfers and labels.

Request Body

FieldTypeDescription
chain requiredstringChain name
address requiredstringWallet address
POST /api/wallet/pnl $0.01

Portfolio profit/loss with realized and unrealized P&L per token.

Request Body

FieldTypeDescription
chain requiredstringChain name
address requiredstringWallet address
min_liquidity optionalnumberMinimum liquidity filter
min_volume_24h optionalnumberMinimum 24h volume filter
POST /api/token/prices $0.005

Real-time DEX-derived token prices with OHLC data. Up to 200 tokens per request.

Request Body

FieldTypeDescription
tokens requiredarrayArray of { token_address, chain } objects. Max 200.

Example

POST /api/token/prices
Content-Type: application/json

{
  "tokens": [
    { "token_address": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", "chain": "base" }
  ]
}
GET /api/token/metadata $0.002

Token/asset metadata — name, symbol, decimals, chain info.

Parameters (at least one required)

NameTypeDescription
chainstringChain name
addressstringToken contract address
slugstringToken slug
idstringToken ID
GET

/api/ens/resolve

$0.001

Resolve an ENS name to an Ethereum address. Uses public Ethereum RPCs — no API key needed.

ParamTypeDescription
name requiredstringENS name (e.g. "vitalik.eth")
GET /api/ens/resolve?name=vitalik.eth

// Response
{
  "name": "vitalik.eth",
  "address": "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045"
}
GET

/api/ens/reverse

$0.001

Reverse lookup — find the ENS name for an Ethereum address. Returns null if no reverse record is set.

ParamTypeDescription
address requiredstringEthereum address (0x...)
GET /api/ens/reverse?address=0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045

// Response
{
  "address": "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045",
  "name": "vitalik.eth"
}
GET

/api/nft/metadata

$0.005

Get NFT name, description, image, traits, and collection info. Supports Ethereum, Base, Polygon, Arbitrum, Optimism, and Zora.

ParamTypeDescription
chain requiredstringChain name (ethereum, base, polygon, arbitrum, optimism, zora)
contract requiredstringContract address (0x...)
tokenId requiredstringToken ID (numeric)
GET /api/nft/metadata?chain=ethereum&contract=0xbc4ca0eda7647a8ab7c2061c2e118a18a936f13d&tokenId=1

// Response
{
  "name": "BAYC #1",
  "description": "...",
  "image": "https://...",
  "traits": [{"trait_type": "Background", "value": "Orange"}],
  "collection": "BoredApeYachtClub",
  "token_standard": "ERC721"
}
GET

/api/nft/ownership

$0.005

Get the current owner(s) of an NFT.

ParamTypeDescription
chain requiredstringChain name
contract requiredstringContract address
tokenId requiredstringToken ID
GET

/api/nft/collection

$0.005

Get collection metadata — name, symbol, total supply, floor price, description.

ParamTypeDescription
chain requiredstringChain name
contract requiredstringContract address

Compute

POST /api/image/fast $0.015

Quick image generation using FLUX Schnell (~2s). Good for drafts and iteration.

Request Body

FieldTypeDescription
prompt requiredstringImage description
width optionalnumber256–2048 pixels. Default: 1024
height optionalnumber256–2048 pixels. Default: 1024
seed optionalnumberFor reproducible results

Example

POST /api/image/fast
Content-Type: application/json

{ "prompt": "A cyberpunk cityscape at sunset, neon lights reflecting off rain-slicked streets" }
POST /api/image/quality $0.05

High-quality image generation using FLUX.2 Pro (~5s). Production-ready output.

Same parameters as /api/image/fast.

POST /api/image/text $0.12

Image generation with accurate text rendering using Ideogram v3. Best for logos, signs, and typography.

Same parameters as /api/image/fast.

POST /api/code/run $0.005

Run code in an isolated sandbox. Supports Python, JavaScript, Bash, and R.

Request Body

FieldTypeDescription
code requiredstringCode to execute (max 100KB)
language optionalstringpython, javascript, bash, r. Default: python
timeout optionalnumber1–300 seconds
files optionalobjectAdditional files for the sandbox, keyed by filename

Example

POST /api/code/run
Content-Type: application/json

{
  "code": "import math\nprint(f'Pi to 10 decimals: {math.pi:.10f}')",
  "language": "python"
}
Response
{
  "success": true,
  "exit_code": 0,
  "stdout": "Pi to 10 decimals: 3.1415926536\n",
  "stderr": ""
}
POST /api/transcribe $0.10

Audio transcription with speaker identification using Deepgram Nova-3.

Request Body

FieldTypeDescription
audio_url required*stringURL to audio file
audio_base64 required*stringBase64-encoded audio (max 50MB)
audio_mimetype optionalstringRequired with base64, e.g. audio/mp3
language optionalstringLanguage code. Default: en
diarize optionalbooleanSpeaker identification. Default: true
model optionalstringnova-3 or whisper-large

* Provide either audio_url or audio_base64, not both.

Example Response

{
  "text": "Hello, welcome to the meeting. Today we'll discuss...",
  "segments": [
    { "text": "Hello", "start": 0.0, "end": 0.5, "speaker": 0, "confidence": 0.98 }
  ],
  "speakers": [{ "id": 0, "segments_count": 12 }, { "id": 1, "segments_count": 8 }],
  "duration_seconds": 145.2,
  "language": "en",
  "model": "nova-3"
}

Storage

POST /api/ipfs/pin $0.01

Pin JSON, files, or URLs to IPFS for decentralized storage. Powered by Pinata.

Request Options

Option 1: File upload

Send as multipart/form-data with a file field. Max 100MB.

Option 2: JSON data

Send { "json": { ... }, "name": "optional-name" } as JSON body.

Option 3: Pin from URL

Send { "url": "https://...", "name": "optional-name" } as JSON body.

Example

POST /api/ipfs/pin
Content-Type: application/json

{ "json": { "name": "Test", "value": 42 }, "name": "my-data" }
Response
{
  "cid": "bafkreihdwdcefgh4dqkjv67uzcmw7ojee6xedzdetojuzjevtensgqas7y",
  "name": "my-data",
  "size": 28,
  "gateway_url": "https://gateway.pinata.cloud/ipfs/bafkrei..."
}
GET /api/ipfs/get $0.001

Fetch files from IPFS by CID via Pinata gateway.

Parameters

NameTypeDescription
cid requiredstringIPFS Content Identifier

Response

For JSON content: returns the stored JSON object directly. For binary content: streams the raw file with appropriate Content-Type.


LLM & AI

POST

/api/llm/{model}

Chat completion via 20 models from OpenAI, Anthropic, Google, DeepSeek, Meta, xAI, Qwen, Mistral, and Perplexity. All models use the same request/response format.

FieldTypeDescription
messages requiredarrayArray of {role, content} objects
max_tokens optionalnumberMax tokens (1-4096, default 1024)
POST /api/llm/claude-sonnet
{
  "messages": [{"role": "user", "content": "Explain x402 in one sentence"}],
  "max_tokens": 100
}

// Response
{
  "content": "x402 is a protocol that enables...",
  "model": "anthropic/claude-sonnet-4.5",
  "usage": {"prompt_tokens": 12, "completion_tokens": 24, "total_tokens": 36}
}

Available Models

EndpointModelPrice
/api/llm/gpt-4oGPT-4o$0.04
/api/llm/gpt-4o-miniGPT-4o Mini$0.003
/api/llm/gpt-4.1GPT-4.1$0.03
/api/llm/gpt-4.1-miniGPT-4.1 Mini$0.006
/api/llm/gpt-5GPT-5$0.035
/api/llm/gpt-5-miniGPT-5 Mini$0.007
/api/llm/o3o3 (reasoning)$0.03
/api/llm/o4-minio4 Mini (reasoning)$0.02
/api/llm/claude-opusClaude Opus 4.6$0.09
/api/llm/claude-sonnetClaude Sonnet 4.5$0.06
/api/llm/claude-haikuClaude Haiku 4.5$0.02
/api/llm/gemini-proGemini 2.5 Pro$0.035
/api/llm/gemini-flashGemini 2.5 Flash$0.009
/api/llm/deepseekDeepSeek V3$0.005
/api/llm/deepseek-r1DeepSeek R1 (reasoning)$0.01
/api/llm/llamaLlama 3.3 70B$0.002
/api/llm/grokGrok 4$0.06
/api/llm/qwenQwen3 235B$0.004
/api/llm/mistralMistral Large 3$0.006
/api/llm/perplexityPerplexity Sonar Pro (search)$0.06
POST

/api/embeddings

$0.001

Generate text embeddings using OpenAI text-embedding-3-small (1536 dimensions). Useful for semantic search, clustering, and RAG.

FieldTypeDescription
text option 1stringSingle text to embed
texts option 2string[]Array of texts (1-100)
POST /api/embeddings
{ "text": "What is x402?" }

// Response (single)
{ "embedding": [0.012, -0.034, ...] }  // 1536 dimensions

POST /api/embeddings
{ "texts": ["What is x402?", "How do payments work?"] }

// Response (batch)
{ "embeddings": [[0.012, ...], [-0.005, ...]] }

Web

GET

/api/web/scrape

$0.005

Scrape any URL and get clean markdown content. Powered by Firecrawl.

ParamTypeDescription
url requiredstringURL to scrape
formats optionalstringComma-separated: markdown, html, text (default: markdown)
GET /api/web/scrape?url=https://example.com

// Response
{
  "content": "# Example Domain\n\nThis domain is for use in...",
  "markdown": "# Example Domain\n\nThis domain is for use in...",
  "metadata": { "title": "Example Domain", "statusCode": 200 }
}
GET

/api/web/screenshot

$0.01

Capture a screenshot of any URL. Returns a base64-encoded image.

ParamTypeDescription
url requiredstringURL to screenshot
full_page optionalbooleanCapture full page (default: false)
GET /api/web/screenshot?url=https://example.com&full_page=true

// Response
{
  "screenshot": "iVBORw0KGgoAAAANSUhEUgAA...",  // base64 PNG
  "metadata": { "title": "Example Domain", "statusCode": 200 }
}

Text-to-Speech

POST

/api/tts/openai

$0.01

Convert text to speech using OpenAI TTS. Returns base64-encoded audio.

FieldTypeDescription
text requiredstringText to speak (max 4096 chars)
voice optionalstringalloy, echo, fable, onyx, nova, shimmer (default: alloy)
model optionalstringtts-1 or tts-1-hd (default: tts-1)
format optionalstringmp3, opus, aac, flac, wav, pcm (default: mp3)
POST /api/tts/openai
{ "text": "Hello, I am an AI agent.", "voice": "nova", "model": "tts-1-hd" }

// Response
{
  "audio": "//uQxAAAAAANIAAAAAExB...",  // base64 audio
  "format": "mp3",
  "model": "tts-1-hd"
}
POST

/api/tts/elevenlabs

$0.02

Premium text-to-speech with ElevenLabs. Ultra-realistic voices with multilingual support.

FieldTypeDescription
text requiredstringText to speak (max 5000 chars)
voice_id optionalstringElevenLabs voice ID (default: Rachel)
model_id optionalstringModel ID (default: eleven_multilingual_v2)
format optionalstringmp3_44100_128, pcm_16000, etc. (default: mp3_44100_128)
POST /api/tts/elevenlabs
{ "text": "Welcome to x402engine.", "voice_id": "21m00Tcm4TlvDq8ikWAM" }

// Response
{
  "audio": "//uQxAAAAAANIAAAAAExB...",  // base64 audio
  "format": "mp3_44100_128"
}

POST

/api/tx/simulate

$0.01

Simulate EVM transactions before sending. Get gas estimates, execution traces, and revert reasons via Tenderly.

FieldTypeDescription
network_id requiredstringChain ID (e.g. "1" for mainnet, "8453" for Base)
from requiredstringSender address (0x...)
to requiredstringRecipient/contract address (0x...)
value optionalstringETH value in wei
data optionalstringCalldata hex (0x...)
gas optionalnumberGas limit override
POST /api/tx/simulate
{
  "network_id": "1",
  "from": "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045",
  "to": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
  "data": "0xa9059cbb000000000000000000000000..."
}

// Response
{
  "success": true,
  "gasUsed": 51234,
  "logs": [...],
  "trace": { "type": "CALL", "from": "0x...", "to": "0x...", ... }
}

Error Handling

All errors return JSON with an error field.

StatusMeaning
400Missing or invalid parameters
402Payment required — check PAYMENT-REQUIRED header
404Resource not found
408Execution timeout (code execution)
500Internal server error
503Upstream temporarily unavailable (retryable)
{
  "error": "Missing required parameter: ids",
  "details": "Provide comma-separated CoinGecko coin IDs"
}