Add pay-per-use capability to your AI agent skills and Node.js applications with the x402 protocol.
x402 is a payment protocol built on HTTP status code 402 Payment Required. When you call an x402-enabled API without paying, the server returns a 402 response with payment requirements. This SDK handles the entire payment flow automatically:
Your App Paid API Server
│ │
│──── GET /api/data ─────────────────>│
│<─── 402 Payment Required ───────────│ (includes: price, token, chain, payTo)
│ │
│ [SDK auto-signs & pays on-chain] │
│ │
│──── GET /api/data + payment proof ─>│
│<─── 200 OK + data ─────────────────│
└─────────────────────────────────────┘
You don't need to handle any of this yourself. Just use createX402FetchClient() and call your API like normal — the SDK intercepts 402 responses, pays on-chain, and retries automatically.
npm install @springmint/x402-paymentThe SDK needs a private key to sign on-chain payments. It searches in this order:
| Priority | Source | Keys |
|---|---|---|
| 1 | Environment variables | TRON_PRIVATE_KEY, EVM_PRIVATE_KEY, ETH_PRIVATE_KEY, PRIVATE_KEY |
| 2 | Project config | ./x402-config.json |
| 3 | User config | ~/.x402-config.json |
| 4 | mcporter config | ~/.mcporter/mcporter.json |
Quickest way:
# For EVM chains (BSC, Ethereum, Base, etc.)
export EVM_PRIVATE_KEY=your_private_key_hex
# For TRON
export TRON_PRIVATE_KEY=your_private_key_hex
# Verify
npx @springmint/x402-payment --check
# [OK] EVM Wallet: 0x1234...abcd
# [OK] TRON Wallet: TXyz...Or use a config file:
// x402-config.json
{
"evm_private_key": "your_evm_key",
"tron_private_key": "your_tron_key",
"tron_grid_api_key": "your_trongrid_key"
}Import the SDK in your skill or Node.js application to call paid APIs:
import { createX402FetchClient } from "@springmint/x402-payment";
// Create a client — keys are auto-discovered
const client = await createX402FetchClient();
// Use it like a normal fetch — 402 payments are handled automatically
const response = await client.request(
"https://www.cpbox.io/api/rpc/x402/batch-balance",
{
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
chain: "ethereum",
token: "",
addresses: ["0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045"],
}),
},
);
const data = await response.json();
console.log(data);For the common pattern of calling an x402 agent's entrypoint, use the high-level helper:
import { invokeEndpoint } from "@springmint/x402-payment";
// Entrypoint mode — automatically calls POST {url}/entrypoints/{name}/invoke
const result = await invokeEndpoint("https://api.example.com", {
entrypoint: "chat",
input: { prompt: "hello" },
});
console.log(result.status); // 200
console.log(result.body); // { response: "..." }You can also pass keys explicitly instead of relying on auto-discovery:
const client = await createX402FetchClient({
evmPrivateKey: "0x...",
tronPrivateKey: "...",
silent: true, // suppress [x402] log output
});AI agents and command-line users can invoke paid APIs directly:
# Call an agent's entrypoint
npx @springmint/x402-payment \
--url https://api.example.com \
--entrypoint chat \
--input '{"prompt": "hello"}'
# Call a URL directly
npx @springmint/x402-payment \
--url https://www.cpbox.io/api/rpc/x402/batch-balance \
--method POST \
--input '{"chain":"ethereum","token":"","addresses":["0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045"]}'| Option | Required | Description |
|---|---|---|
--url |
Yes | Target API endpoint URL |
--entrypoint |
No | Entrypoint name (constructs /entrypoints/{name}/invoke URL, forces POST) |
--input |
No | JSON request body |
--method |
No | HTTP method (default: GET for direct, POST for entrypoint) |
--check |
No | Verify wallet configuration and exit |
--approve |
No | Approve token spending (requires --token and --network) |
--allowance |
No | Check current token allowance (requires --token and --network) |
--token |
No | Token contract address (used with --approve / --allowance) |
--network |
No | Network identifier, e.g. eip155:97, tron:nile (used with --approve / --allowance) |
--type |
No | Chain type: evm (default) or tron (used with --approve / --allowance) |
Output goes to stdout as JSON. Logs go to stderr.
Token approval examples:
# Check USDT allowance on BSC testnet
npx @springmint/x402-payment --allowance --token 0x337610d27c682E347C9cD60BD4b3b107C9d34dDd --network eip155:97
# Approve USDT on BSC testnet
npx @springmint/x402-payment --approve --token 0x337610d27c682E347C9cD60BD4b3b107C9d34dDd --network eip155:97
# Approve USDT on TRON nile
npx @springmint/x402-payment --approve --token TXYZopYRdj2D9XRtbG411XZZ3kM5VkAeBf --network tron:nile --type tronCreate a fetch client that automatically handles 402 payment flows.
Returns an X402FetchClient instance. Use client.request(url, init) to make requests — the same interface as fetch().
Create the underlying X402Client with all payment mechanisms registered. Use this when you need lower-level control over payment mechanisms and policies.
High-level helper that creates a client, sends the request, and returns the parsed response.
const result = await invokeEndpoint(url, {
entrypoint?: string, // entrypoint name (switches to invoke mode)
input?: any, // request body (auto-serialized to JSON)
method?: string, // HTTP method
clientOptions?: { // passed to createX402FetchClient
tronPrivateKey?: string,
evmPrivateKey?: string,
tronGridApiKey?: string,
silent?: boolean,
},
});
// result: { status: number, headers: Record<string, string>, body: any }Search for a private key following the lookup order described in Wallet Configuration.
Search for TronGrid API key using the same lookup order.
Check current token allowance for the wallet.
const allowance = await checkAllowance("evm", "0x55d3...7955", "eip155:56");
console.log(`Allowance: ${allowance}`);Approve unlimited token spending for x402 payments.
await approveToken("evm", "0x55d3...7955", "eip155:56");| Chain | Network | Tokens | Example USDT Contract |
|---|---|---|---|
| TRON | mainnet |
USDT, USDD | TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t |
| TRON | nile |
USDT, USDD | TXYZopYRdj2D9XRtbG411XZZ3kM5VkAeBf |
| BSC | bsc |
USDT, USDC | 0x55d398326f99059fF775485246999027B3197955 |
| BSC | bsc-testnet |
USDT, USDC, DHLU | 0x337610d27c682E347C9cD60BD4b3b107C9d34dDd |
Both direct transfer and permit-based payment mechanisms are supported on all chains.
If you have a paid API protected by x402, you can create a skill file so AI agents can call it automatically.
Create a SKILL.md file for your API:
---
name: my-api-skill
description: "Description of your API and when to use it."
version: 1.0.0
dependencies:
- "@springmint/x402-payment"
---
# My API Skill
> **Prerequisites**: Install and configure `@springmint/x402-payment`.
> See [wallet configuration](https://github.com/springmint/x402-payment#wallet-configuration).
>
> ```bash
> npm install @springmint/x402-payment
> npx @springmint/x402-payment --check
> ```
## Endpoint
\`\`\`
POST https://your-api.com/api/your-endpoint
Content-Type: application/json
\`\`\`
## Using with x402-payment
### CLI (AI Agent)
\`\`\`bash
npx @springmint/x402-payment \
--url https://your-api.com/api/your-endpoint \
--method POST \
--input '{"key": "value"}'
\`\`\`
### Library (Node.js)
\`\`\`ts
import { createX402FetchClient } from "@springmint/x402-payment";
const client = await createX402FetchClient();
const response = await client.request("https://your-api.com/api/your-endpoint", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ key: "value" }),
});
const data = await response.json();
\`\`\`
## Request / Response
[Document your API parameters and response format here]
## Error Handling
### Insufficient Allowance
\`\`\`bash
npx @springmint/x402-payment --approve --token <TOKEN_ADDRESS> --network <NETWORK>
\`\`\`When an AI agent receives your skill, the complete flow is:
1. Agent reads SKILL.md
│
2. Checks if @springmint/x402-payment is installed
└─ If not: runs `npm install @springmint/x402-payment`
│
3. Verifies wallet: `npx @springmint/x402-payment --check`
└─ If no wallet: asks user to configure private key
│
4. Calls your API via CLI or library
│
5. Gets 402 → SDK auto-pays → gets result
│
6. If allowance error: runs --approve, then retries
Put your SKILL.md in a git repository. AI agents can use it by reading the file:
Read my-api-skill/SKILL.md and call the API with {"key": "value"}
See cpbox-skills/batch-balance for a real-world example.
- Private keys are never output to stdout or logs
- Error messages are automatically sanitized to redact any leaked key material
console.logis redirected tostderrin CLI mode to prevent library output from polluting your data pipeline- Always use testnet (
nile,bsc-testnet) for development
x402-payment/
├── README.md
├── LICENSE
├── package.json # @springmint/x402-payment
├── SKILL.md # AI Agent instruction file
├── src/
│ ├── index.ts # Library exports
│ ├── config.ts # Key discovery
│ ├── client.ts # Client factory & invokeEndpoint
│ └── cli.ts # CLI entry point
└── dist/
├── lib/ # Library build (import)
└── cli/ # CLI build (npx / bin)