@402md/client
Agent SDK reference for building AI agents with USDC wallets
Installation
npm install @402md/clientcreateAgent(config)
import { createAgent } from '@402md/client'
const agent = createAgent({
wallet: {
privateKey: process.env.AGENT_WALLET_KEY!,
network: 'base'
},
budget: {
daily: '100.00',
perTransaction: '50.00'
}
})AgentConfig
| Field | Type | Required | Description |
|---|---|---|---|
wallet.privateKey | string | Yes | Hex private key for USDC wallet |
wallet.network | 'base' | 'base-sepolia' | No | Network. Defaults to 'base-sepolia' |
budget.daily | string | No | Max USDC per day (e.g. '100.00') |
budget.perTransaction | string | No | Max USDC per transaction (e.g. '50.00') |
apiBaseUrl | string | No | Override API URL. Defaults to 'https://api.402.md' |
Methods
agent.call(skill, path, options?)
Call a paid API endpoint. Handles x402 payment automatically.
const result = await agent.call('sentiment-api', '/analyze', {
method: 'POST',
body: { text: 'Hello world' },
headers: { 'X-Custom': 'value' }
})Flow: request → 402 response → check budget → sign payment → retry with X-402-Payment header → return response.
CallOptions
| Field | Type | Required | Description |
|---|---|---|---|
body | unknown | No | Request body (JSON-serialized) |
headers | Record<string, string> | No | Additional request headers |
method | string | No | HTTP method. Defaults to 'GET' |
Returns: Promise<unknown> — the API response body.
agent.subscribe(skill)
Subscribe to a SaaS service.
const sub = await agent.subscribe('analytics-dashboard')Returns: Promise<SubscriptionResult>
interface SubscriptionResult {
ticket: string // JWT access ticket
accessUrl: string // URL to access the service
expiresAt: string // ISO 8601 expiration
}agent.purchase(skill, path, options?)
Purchase a product.
const order = await agent.purchase('store', '/buy/SKU-001', {
quantity: 2,
shipping: {
name: 'Jane Doe',
address: '456 Oak Ave',
city: 'Austin',
state: 'TX',
zip: '73301',
country: 'US'
}
})PurchaseOptions
| Field | Type | Required | Description |
|---|---|---|---|
quantity | number | No | Number of items |
shipping.name | string | No | Recipient name |
shipping.address | string | No | Street address |
shipping.city | string | No | City |
shipping.state | string | No | State/province |
shipping.zip | string | No | ZIP/postal code |
shipping.country | string | No | Country code |
Returns: Promise<PurchaseResult>
interface PurchaseResult {
orderId: string // Order identifier
status: string // Order status
txHash: string // On-chain transaction hash
}agent.search(query)
Search for available skills on 402.md.
const results = await agent.search('image generation')Returns: Promise<SearchResult>
interface SearchResult {
skills: Array<{
name: string
description: string
pricing: {
model: string // 'per_call', 'subscription', etc.
price: string // Price in USDC
}
category: string
}>
}agent.getBalance()
Returns the current USDC balance of the agent's wallet.
const balance = await agent.getBalance() // '847.50'Returns: Promise<string> — USDC balance as a decimal string.
agent.getSpentToday()
Returns the total USDC spent today (tracked locally).
const spent = agent.getSpentToday() // 52.5Returns: number — total spent today as a number.
getSpentToday() returns a number, not a string. It tracks spend locally based on transactions signed during the current process.
agent.address
Getter that returns the agent's wallet address.
console.log(agent.address) // '0x742d...5f0b'Returns: string
Budget enforcement
The SDK enforces spending limits locally before signing any transaction:
perTransaction— checked first. If the payment amount exceeds this limit, an error is thrown immediately.daily— checked second. If cumulative spend today + the new payment would exceed this limit, an error is thrown.
Daily spend resets at midnight (local time). Spend is tracked in-memory — restarting the process resets the counter.
try {
await agent.call('expensive-api', '/endpoint')
} catch (err) {
if (err.message.includes('budget') || err.message.includes('limit')) {
console.log('Budget exceeded:', err.message)
}
}No USDC is spent when a budget error is thrown — the check happens before the payment is signed.
Wallet utilities
The client package also exports lower-level wallet functions:
createWalletClient(privateKey, network?)
Creates viem wallet and public clients from a private key.
import { createWalletClient } from '@402md/client'
const clients = createWalletClient('0xabc...', 'base')
// { wallet, public, network, address }signPayment(clients, amount, recipient)
Signs a USDC transfer and returns the transaction hash and encoded payment header.
import { signPayment } from '@402md/client'
const { txHash, payment } = await signPayment(clients, '0.05', '0x742d...')
// payment is a Base64-encoded JSON string for the X-402-Payment headergetBalance(clients)
Queries the on-chain USDC balance.
import { getBalance } from '@402md/client'
const balance = await getBalance(clients) // '847.50'