Production
Avery SDK is a Node-only SDK. Run it on a server-side Node.js runtime with Node.js >=20.19.0, keep private keys out of client bundles, and treat every agent-triggered paid call as real spend.
This page focuses on deployment, runtime, and secret handling. For production agent spend policy, see Agent Spend Controls. For audit logs and dashboards, see Observability and Audit Logging. For symptom-based operator fixes, see Troubleshooting.
Supported Runtimes
| Runtime | Support | Notes |
|---|---|---|
| Vercel Node.js Functions | Supported | Use the Node.js runtime for API routes or functions. |
| Next.js App Router route handlers | Supported | Keep Avery SDK in server-only modules and use the Node.js runtime. |
| Next.js Server Actions | Supported | Use only from server-side code paths. |
| Docker, Fly.io, or a regular Node server | Supported | Inject secrets at runtime and run Node.js >=20.19.0. |
| Browser or client component | Not supported | Private keys and payment signing must not ship to the client. |
| Static frontend bundle | Not supported | There is no secure server-side signing boundary. |
| Next.js Edge runtime | Not recommended | Edge runtime has a limited API set and does not provide full Node.js compatibility. |
| Cloudflare Workers direct Avery SDK usage | Not recommended | Use Cloudflare native x402 and Agents support, or call a Node service that runs Avery SDK. |
Next.js Pattern
Put X402Client in a server-only module:
// lib/x402-client.ts
import "server-only";
import { X402Client, X402Networks } from "@averyso/alpha";
export const x402Client = new X402Client(process.env.X402_PRIVATE_KEY!, {
network: process.env.X402_NETWORK ?? X402Networks.baseSepolia,
rpcUrl: process.env.X402_RPC_URL,
maxAmount: BigInt(process.env.X402_MAX_AMOUNT ?? "50000"),
logLevel: process.env.X402_LOG_LEVEL === "debug" ? "debug" : "info",
});Use it from a route handler, server action, or backend service:
// app/api/paid-weather/route.ts
import { x402Client } from "@/lib/x402-client";
export const runtime = "nodejs";
export async function GET(request: Request) {
const city = new URL(request.url).searchParams.get("city") ?? "Lisbon";
const result = await x402Client.call(
{
url: "https://api.example.com/weather",
query: { city },
},
undefined,
{ maxAmount: 50_000n },
);
if (result.kind !== "success") {
return Response.json({ error: result.kind }, { status: result.status || 500 });
}
return Response.json(result.body);
}Do not import this module from a "use client" component. Do not prefix private variables with NEXT_PUBLIC_; that opt-in exposes values to the browser bundle.
Environment Variables
Use environment variables or runtime secrets for deployment-specific values:
X402_PRIVATE_KEY=0x...
X402_NETWORK=base-sepolia
X402_RPC_URL=https://example-rpc
X402_MAX_AMOUNT=50000
X402_LOG_LEVEL=infoSuggested handling:
X402_PRIVATE_KEY: Required. Store in the platform secret manager.X402_NETWORK: Required by your app config. Match endpoint requirements.X402_RPC_URL: Recommended in production. Treat as secret when it contains an API key.X402_MAX_AMOUNT: Store as an atomic-unit integer string.X402_LOG_LEVEL: Useinfoin production unless actively debugging.
Platform Configuration
On Vercel, use Project Environment Variables and deploy Avery SDK only in Node.js Functions or Next.js server routes with runtime = "nodejs".
On Fly.io, inject sensitive values with fly secrets set:
fly secrets set X402_PRIVATE_KEY=0x... X402_RPC_URL=https://example-rpcOn Docker or Docker Compose, use runtime secrets or environment injection. Do not write private keys, RPC API keys, or .env contents into a Dockerfile, image layer, or build argument. Docker secrets are commonly mounted as files, so read the secret file at process startup when your deployment uses that model.
Private Key Rotation
Use a small hot wallet and make rotation routine:
- Create a new hot wallet for the same network family.
- Inject the new key through the deployment secret manager.
- Deploy to a low-traffic environment and run a low-value paid request.
- Gradually shift traffic to the new key.
- Transfer, drain, or abandon the old hot wallet balance according to your treasury policy.
- Review logs for unexpected failures or duplicate payments.
- Remove the old key from every environment.
Hot Wallet Balance
Keep only enough funds for near-term payment needs. A practical starting estimate is:
hot_wallet_balance =
maxAmount * expected_paid_calls_during_refill_window
+ gas_or_network_fees
+ operational_bufferMonitor wallet balances, failed settlement counts, RPC error rates, and payment failure rates. Alert before the wallet reaches the minimum balance required for the next refill window. Do not store funds beyond short-term operating needs in the hot wallet. Use an application budget ledger and reservation flow to avoid accepting more concurrent paid work than the hot wallet can support; see Agent Spend Controls.
Redaction
Redact sensitive fields before logging or sending errors to observability tools:
- Private keys, seeds, and Solana secret keys.
- RPC URLs with query strings, account ids, or API keys.
AuthorizationandCookieheaders.X-PAYMENTandX-PAYMENT-RESPONSEheaders.- Payment payloads and signed authorization data.
- Raw provider responses that include signed payment data.
Addresses can usually be logged in shortened form, such as the first and last few characters. Use debug logs for detailed payment diagnostics and keep production info logs focused on endpoint name, result kind, status, redacted network, and request id. For logger adapters, audit fields, redaction rules, and dashboard patterns, see Observability and Audit Logging.