Constructor Options
import { BoltzPay } from "@boltzpay/sdk";
const agent = new BoltzPay({
// ...options
});
All options are optional. An empty {} creates a read-only instance (explore mode).
| Option | Type | Default | Description |
|---|
coinbaseApiKeyId | string | — | Coinbase CDP API key ID. Required for payments. |
coinbaseApiKeySecret | string | — | Coinbase CDP API key secret. Required for payments. |
coinbaseWalletSecret | string | — | Coinbase CDP wallet secret. Required for payments. |
nwcConnectionString | string | — | NWC connection string (nostr+walletconnect://...). Enables L402 protocol. |
wallets | WalletConfig[] | — | Multi-wallet configuration. See Wallets. |
mppPreferredMethods | string[] | — | Preferred MPP method order (e.g. ["tempo", "stripe"]). |
registryUrl | string | "https://status.boltzpay.ai" | Registry API base URL. |
sessionMaxDeposit | string | number | — | Max deposit per session in USD. |
network | "base" | "base-sepolia" | "base" | Blockchain network. Use base-sepolia for testing. |
preferredChains | ("evm" | "svm")[] | — | Chain preference when endpoint accepts multiple chains. |
budget | BudgetConfig | — | Spending limits. See Budget. |
persistence | { enabled?: boolean; directory?: string; historyMaxRecords?: number } | — | Persist budget and history to disk. See Budget. |
storage | "file" | "memory" | StorageAdapter | — | Storage backend for budget and history. |
logLevel | "debug" | "info" | "warn" | "error" | "silent" | "warn" | SDK log verbosity. |
logFormat | "text" | "json" | "text" | Log output format. JSON sanitizes sensitive fields. |
maxAmountPerRequest | string | number | — | Global per-request payment cap. |
allowlist | string[] | — | Only pay endpoints matching these URL patterns. |
blocklist | string[] | — | Never pay endpoints matching these URL patterns. |
retry | RetryConfig | — | Retry policy for transient failures. |
rateLimit | RateLimitConfig | — | Rate limiting for outgoing requests. |
timeouts | TimeoutConfig | See below | Per-phase timeouts. |
Credentials
Coinbase CDP (x402 protocol)
The three Coinbase fields must all be provided together. If any are missing, the SDK runs in explore mode: quote(), discover(), diagnose(), getBudget(), and getHistory() work normally, but fetch() will fail on paid endpoints.
const agent = new BoltzPay({
coinbaseApiKeyId: process.env.COINBASE_API_KEY_ID!,
coinbaseApiKeySecret: process.env.COINBASE_API_KEY_SECRET!,
coinbaseWalletSecret: process.env.COINBASE_WALLET_SECRET!,
});
The Coinbase SDK (@coinbase/cdp-sdk) is loaded lazily. It is only imported when the first payment is executed, not at construction time.
NWC (L402 protocol)
Adding an NWC connection string enables the L402 (Lightning) adapter alongside x402. The SDK auto-detects which protocol each endpoint uses.
const agent = new BoltzPay({
coinbaseApiKeyId: process.env.COINBASE_API_KEY_ID!,
coinbaseApiKeySecret: process.env.COINBASE_API_KEY_SECRET!,
coinbaseWalletSecret: process.env.COINBASE_WALLET_SECRET!,
nwcConnectionString: process.env.NWC_CONNECTION_STRING!,
});
The NWC connection string must start with nostr+walletconnect://. Get one for free from Coinos, Primal, or any wallet listed on nwc.dev. See Installation for step-by-step instructions.
Wallets
The wallets array configures multiple payment methods. Each wallet targets a specific protocol. The SDK selects the appropriate wallet based on endpoint protocol detection.
const agent = new BoltzPay({
wallets: [
{
type: "coinbase",
name: "main",
coinbaseApiKeyId: process.env.COINBASE_API_KEY_ID!,
coinbaseApiKeySecret: process.env.COINBASE_API_KEY_SECRET!,
coinbaseWalletSecret: process.env.COINBASE_WALLET_SECRET!,
},
{
type: "nwc",
name: "lightning",
nwcConnectionString: process.env.NWC_CONNECTION_STRING!,
},
{
type: "tempo",
name: "tempo-main",
tempoPrivateKey: process.env.TEMPO_PRIVATE_KEY!,
},
{
type: "stripe-mpp",
name: "stripe",
stripeSecretKey: process.env.STRIPE_SECRET_KEY!,
},
{
type: "visa-mpp",
name: "visa",
visaJwe: process.env.VISA_JWE!,
},
],
});
| Type | Protocol | Required field | Description |
|---|
coinbase | x402 | coinbaseApiKeyId, coinbaseApiKeySecret, coinbaseWalletSecret | USDC on Base via Coinbase CDP |
nwc | L402 | nwcConnectionString | Bitcoin Lightning via NWC |
tempo | MPP | tempoPrivateKey | Payment channels via Tempo network |
stripe-mpp | MPP | stripeSecretKey | MPP via Stripe |
visa-mpp | MPP | visaJwe | MPP via Visa |
Legacy flat credentials (coinbaseApiKeyId, nwcConnectionString at root level) still work for backward compatibility. The wallets array is preferred for new integrations.
Registry URL
The registry is the source of truth for discover(). Points to the BoltzPay registry by default.
const agent = new BoltzPay({
registryUrl: "https://my-registry.example.com", // default: https://status.boltzpay.ai
});
Session Deposit
Cap the maximum deposit per payment session. Useful for controlling exposure on long-running agents.
const agent = new BoltzPay({
sessionMaxDeposit: "5.00", // Cap session deposits at $5
});
Actual deposit = min(available budget, sessionMaxDeposit, user-provided maxDeposit). Defaults to $10 if no constraints are set.
Budget
Set spending limits to protect against unexpected costs. All amounts are in USD.
Configuration
const agent = new BoltzPay({
// ...credentials
budget: {
daily: "5.00",
monthly: "100.00",
perTransaction: "1.00",
warningThreshold: 0.8,
},
});
| Field | Type | Default | Description |
|---|
daily | string | number | — | Maximum USD spend per day. |
monthly | string | number | — | Maximum USD spend per month. |
perTransaction | string | number | — | Maximum USD per single fetch() call. |
warningThreshold | number (0-1) | 0.8 | Emit budget:warning event at this usage ratio. |
Amounts accept both strings ("5.00") and numbers (5). All fields are optional. If no budget is configured, payments proceed without caps.
How Enforcement Works
Budget checks run before every payment:
- Checks
perTransaction: rejects if the amount exceeds the per-request cap.
- Checks
daily: rejects if dailySpent + amount > daily limit.
- Checks
monthly: rejects if monthlySpent + amount > monthly limit.
If any check fails, a BudgetExceededError is thrown and the payment is not executed. After a successful payment, the amount is recorded against both daily and monthly totals.
import { BudgetExceededError } from "@boltzpay/sdk";
try {
const response = await agent.fetch("https://emc2ai.io/x402/bitquery/whale-intel/raw");
} catch (error) {
if (error instanceof BudgetExceededError) {
console.log(error.code); // "daily_budget_exceeded" | "monthly_budget_exceeded" | "per_transaction_exceeded"
console.log(error.requested); // Money — the amount requested
console.log(error.limit); // Money — the limit exceeded
}
}
Checking Budget State
const budget = agent.getBudget();
console.log("Daily spent:", budget.dailySpent.toDisplayString()); // "$0.10"
console.log("Daily remaining:", budget.dailyRemaining?.toDisplayString()); // "$4.90"
getBudget() returns a BudgetState:
interface BudgetState {
dailySpent: Money; monthlySpent: Money;
dailyLimit?: Money; monthlyLimit?: Money;
perTransactionLimit?: Money;
dailyRemaining?: Money; monthlyRemaining?: Money;
}
Resetting Budget
agent.resetDailyBudget();
Resets the daily counter to zero. The monthly counter is not affected. Useful if you implement your own daily reset cron.
Budget state is in-memory by default. Enable persistence to keep budget and history across restarts:const agent = new BoltzPay({
// ...credentials
persistence: {
enabled: true,
directory: "~/.boltzpay", // default
historyMaxRecords: 500, // default, FIFO rotation
},
});
When persistence is enabled, budget counters and payment history survive process restarts. Daily budgets auto-reset on calendar day change. Files are stored as budget.json and history.jsonl in the configured directory.
Events
Subscribe with agent.on(event, listener).
payment
Emitted after every successful payment.
agent.on("payment", (record) => {
console.log(record.url); // "https://invy.bot/api"
console.log(record.protocol); // "x402"
console.log(record.amount.toDisplayString()); // "$0.05"
console.log(record.txHash); // "0xabc..." or undefined
});
interface PaymentRecord {
readonly id: string;
readonly url: string;
readonly protocol: string;
readonly amount: Money;
readonly timestamp: Date;
readonly txHash: string | undefined;
readonly network: string | undefined;
}
budget:warning
Emitted when spending reaches the warningThreshold (default 80%) of a daily or monthly limit.
// BudgetWarningEvent { spent: Money, limit: Money, period: "daily"|"monthly", usage: number }
agent.on("budget:warning", (event) => {
console.log(`${(event.usage * 100).toFixed(0)}% of ${event.period} budget used`);
});
budget:exceeded
Emitted when a payment is blocked because it would exceed a budget limit.
// BudgetExceededEvent { requested: Money, limit: Money, period: "daily"|"monthly"|"per_transaction" }
agent.on("budget:exceeded", (event) => {
console.log(`Blocked: ${event.period} limit of ${event.limit.toDisplayString()} reached`);
});
error
Emitted on any error during payment (budget exceeded, protocol error, network error).
agent.on("error", (error) => {
console.log(error.name, error.message);
});
session:open
Emitted when a payment session channel is opened.
agent.on("session:open", (event) => {
console.log(`Session opened: channel ${event.channelId}, deposit ${event.depositAmount.toDisplayString()}`);
});
session:voucher
Emitted when a voucher is issued within a session.
agent.on("session:voucher", (event) => {
console.log(`Voucher #${event.index}: ${event.cumulativeAmount} (channel ${event.channelId})`);
});
session:close
Emitted when a session is closed and the channel is settled.
agent.on("session:close", (event) => {
console.log(`Session closed: spent ${event.totalSpent}, refunded ${event.refunded}`);
});
session:error
Emitted on session-level errors (channel failures, deposit errors).
agent.on("session:error", (event) => {
console.error(`Session error: ${event.error.message}`);
});
mcp:payment
Emitted when a payment is triggered by an MCP tool call.
agent.on("mcp:payment", (event) => {
console.log(`MCP payment: tool ${event.toolName}, amount ${event.amount.toDisplayString()}`);
});
Payment History
The SDK keeps a history of payments (last 500 by default). When persistence is enabled, history survives restarts. Returns readonly PaymentRecord[] (same type as the payment event payload).
const history = agent.getHistory();
for (const record of history) {
console.log(`${record.url} — ${record.amount.toDisplayString()} via ${record.protocol}`);
}
Multi-Chain
Supported Chains
All payments use USDC as the settlement currency, regardless of chain.
| Namespace | Chain | Network ID (CAIP-2) | Currency |
|---|
evm | Base mainnet | eip155:8453 | USDC |
evm | Base Sepolia testnet | eip155:84532 | USDC (test) |
svm | Solana | solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp | USDC |
Auto-Negotiation
When you call agent.fetch(url), the SDK probes the endpoint, receives one or more accept options (each specifying a chain, amount, and payment address), and selects the best match.
The selection algorithm (selectBestAccept):
- Filters out unsupported chains.
- If
preferredChains is set, narrows to those (falls back to all supported if none match).
- Picks the cheapest option among remaining candidates.
- On ties, EVM wins over SVM.
Server offers: [evm $0.05, svm $0.05] → evm $0.05 (EVM wins tie)
Server offers: [evm $0.05, svm $0.03], pref: ["evm"] → evm $0.05
Server offers: [evm $0.05, svm $0.03], pref: none → svm $0.03
Chain Preferences
Set a default preference at construction time:
const agent = new BoltzPay({
// ...credentials
preferredChains: ["evm"], // Always prefer EVM when available
});
Override per-request (takes priority over config-level preferredChains):
const response = await agent.fetch("https://invy.bot/api", {
chain: "svm", // Force Solana for this request
});
Via the CLI:
boltzpay fetch https://invy.bot/api --chain svm
Network
Testnet vs Mainnet
| Network | Use case | Funds |
|---|
base (default) | Production | Real USDC |
base-sepolia | Development & testing | Testnet USDC (free) |
const agent = new BoltzPay({
network: "base-sepolia",
});
Or via environment variable:
export BOLTZPAY_NETWORK=base-sepolia
Testnet endpoints only accept testnet payments and vice versa. The Nickel Joke endpoint (nickeljoke.vercel.app) runs on Base Sepolia and is useful for testing without spending real funds.
Get free testnet USDC from the Circle faucet (select Base Sepolia). No gas fees needed — x402 uses EIP-3009 (gasless signatures).
Log Level
const agent = new BoltzPay({
logLevel: "debug",
});
| Level | Output |
|---|
"debug" | Everything, including protocol detection and adapter decisions. |
"info" | Successful operations and notable events. |
"warn" | Warnings like testnet usage. (default) |
"error" | Only errors. |
"silent" | No output. |
Timeouts
Configure per-phase timeouts for protocol detection, quoting, and payment execution.
const agent = new BoltzPay({
timeouts: {
detect: 10_000, // Protocol detection (ms)
quote: 15_000, // Price quote (ms)
payment: 30_000, // Payment execution (ms)
},
});
| Phase | Default | Description |
|---|
detect | 10000 | Protocol detection timeout in milliseconds. |
quote | 15000 | Price quote timeout in milliseconds. |
payment | 30000 | Payment execution timeout in milliseconds. |
Environment Variables
The CLI and MCP server read configuration from environment variables. The SDK constructor does not read env vars automatically. You pass them explicitly.
| Variable | Used by | Description |
|---|
COINBASE_API_KEY_ID | CLI, MCP | Coinbase CDP API key ID. |
COINBASE_API_KEY_SECRET | CLI, MCP | Coinbase CDP API key secret. |
COINBASE_WALLET_SECRET | CLI, MCP | Coinbase CDP wallet secret. |
NWC_CONNECTION_STRING | CLI, MCP | NWC connection string. Enables L402 protocol. |
TEMPO_PRIVATE_KEY | CLI, MCP | Tempo wallet private key (hex). Enables MPP. |
STRIPE_SECRET_KEY | CLI, MCP | Stripe secret key. Enables Stripe MPP. |
BOLTZPAY_NETWORK | CLI, MCP | Network selection: base or base-sepolia. |
BOLTZPAY_LOG_LEVEL | CLI, MCP | Log level: debug, info, warn, error, silent. |
BOLTZPAY_DAILY_BUDGET | CLI, MCP | Daily spending limit in USD (e.g., 5.00). |
BOLTZPAY_MONTHLY_BUDGET | CLI, MCP | Monthly spending limit in USD. |
BOLTZPAY_PER_TRANSACTION | CLI, MCP | Per-transaction limit in USD. |
Example .env file
# Required for payments
COINBASE_API_KEY_ID=your-key-id
COINBASE_API_KEY_SECRET=your-key-secret
COINBASE_WALLET_SECRET=your-wallet-secret
# Optional — enables L402 (Lightning) protocol
NWC_CONNECTION_STRING=nostr+walletconnect://...
# Optional — enables MPP protocols
TEMPO_PRIVATE_KEY=your-tempo-private-key
STRIPE_SECRET_KEY=sk_live_...
BOLTZPAY_NETWORK=base
BOLTZPAY_LOG_LEVEL=warn
BOLTZPAY_DAILY_BUDGET=5.00
BOLTZPAY_MONTHLY_BUDGET=100.00
BOLTZPAY_PER_TRANSACTION=1.00
The MCP server and CLI both use dotenv, so they automatically read from a .env file in your working directory.