Spending policy
Max per payment, daily limit, and an auto-pay threshold above which a human must approve. Every rule is checked before signing.
Equinox lets AI agents automatically pay for APIs using USDG on Robinhood Chain. Your agent hits a paid endpoint, gets an HTTP 402, and Equinox checks the spending policy, signs the payment and retries — in under a second, without ever exposing a private key.
The x402 protocol turns HTTP 402 into a real payment handshake. Equinox sits between your agent and the paid API, enforcing your budget before a single cent of USDG moves.
x402_fetch with a max pricePAYMENT-REQUIREDexact Permit2 transfer locallyPAYMENT-SIGNATUREPAYMENT-RESPONSE (tx signature)Budgets are enforced in Equinox, not in the prompt. The model can ask; it can never sign.
Max per payment, daily limit, and an auto-pay threshold above which a human must approve. Every rule is checked before signing.
Only pay hosts you trust. The allowlist is re-checked on every hop, so a sneaky redirect can't route funds elsewhere.
Idempotency keys and nonce tracking mean a retried request never double-pays, and a captured signature can't be replayed.
The private key lives in Equinox's process. Tools return balances, receipts and data — never secrets, never to the model.
Use it as an MCP server in Codex or Claude, a local REST API for any language, or a typed TypeScript SDK in your own code.
Approve USDG for Permit2 once; after that every payment is a signature, with no ETH gas per call. Settles on Robinhood Chain (eip155:4663).
Each tool returns structured JSON so the model can inspect a price, decide, pay, and report back with a transaction signature.
x402_inspect makes an unpaid request and decodes the x402 V2 PAYMENT-REQUIRED header so the agent can decide whether the price is worth it.
{
"url": "https://api.example.com/weather?city=Miami",
"method": "GET"
}{
"paymentRequired": true,
"price": "$0.01",
"amountUsd": 0.01,
"asset": "USDG",
"network": "robinhood",
"networkId": "eip155:4663",
"recipient": "0x5486905ba2d92fdFDD6521eA67c7616C25690631",
"scheme": "exact",
"resource": "https://api.example.com/weather"
}x402_fetch requests the URL and, if it gets a 402 within maxPriceUsd and policy, signs a USDG payment, retries, and returns the data together with the on-chain transaction.
{
"url": "https://api.example.com/weather?city=Miami",
"method": "GET",
"maxPriceUsd": 0.03
}{
"success": true,
"paid": true,
"amountUsd": 0.01,
"network": "robinhood",
"transaction": "0x9c4e1f2a7b3d5c8e0f6a2b4d8c1e3f5a7b9d0c2e4f6a8b1d3c5e7f9a0b2c4d6e",
"status": 200,
"data": { "city": "Miami", "temperature": 82, "conditions": "Sunny" }
}wallet_balance reports the agent wallet's public address and current ETH (gas for the one-time approval) and USDG (for payments) balances on Robinhood Chain.
{}{
"address": "0x87E28526C44Fa00a1836650d3Ca94ea843fa7A53",
"network": "eip155:4663",
"networkName": "mainnet",
"eth": 0.0042,
"usdg": 9.87,
"permit2Approved": true
}spending_status lets the agent plan: how much of today's budget is left, the per-payment ceiling, and the threshold above which it must ask a human.
{}{
"spentTodayUsd": 1.24,
"dailyLimitUsd": 5,
"remainingTodayUsd": 3.76,
"maxPaymentUsd": 0.1,
"autoPayLimitUsd": 0.02
}payment_history returns recent payments with domain, amount, recipient, status and the Robinhood Chain transaction hash — an audit trail the agent can cite.
{ "limit": 10 }{
"payments": [
{
"id": "pay_01J9X4",
"timestamp": "2026-09-19T14:02:11.000Z",
"url": "http://localhost:4020/demo/weather",
"domain": "localhost",
"amountUsd": 0.001,
"asset": "USDG",
"network": "eip155:4663",
"recipient": "0x5486905ba2d92fdFDD6521eA67c7616C25690631",
"transaction": "0x3f8a2c6e1b9d4f7a0c5e8b2d6f1a9c3e7b0d4f8a2c6e1b5d9f3a7c0e4b8d2f6a",
"status": "settled",
"latencyMs": 812
}
]
}Drop the MCP server into Codex, call the local REST API from any language, or use the TypeScript SDK directly.
import { Equinox } from "equinox402";
// Wallet is read from .env (EQUINOX402_PRIVATE_KEY) — never passed around
const equinox = new Equinox({
maxPaymentUsd: 0.05,
dailyLimitUsd: 5,
autoPayLimitUsd: 0.02, // above this, a human must approve
allowedDomains: ["api.example.com", "localhost"],
});
// Look before you leap: decode the 402 without paying
const quote = await equinox.inspect("http://localhost:4020/demo/weather");
console.log(quote); // { paymentRequired: true, price: "$0.001", ... }
// Works like fetch() — pays if needed, capped at $0.03 for this call
const response = await equinox.fetch("http://localhost:4020/demo/weather", {
maxPriceUsd: 0.03,
});
console.log(await response.json()); // { city: "Miami", temperature: 82, conditions: "Sunny" }
console.log(response.payment); // { paid: true, amountUsd: 0.001, transaction: "5Ukx…" }
# Register Equinox as an MCP server for OpenAI Codex
[mcp_servers.equinox402]
command = "node"
args = ["--import", "tsx", "/path/to/equinox402/src/mcp/server.ts"]
tool_timeout_sec = 120
# Optional — overrides equinox402/.env (the wallet key stays in .env)
[mcp_servers.equinox402.env]
EQUINOX402_NETWORK = "mainnet"
EQUINOX402_MAX_PAYMENT_USD = "0.05"
EQUINOX402_DAILY_LIMIT_USD = "5"
EQUINOX402_AUTO_PAY_LIMIT_USD = "0.02"
EQUINOX402_ALLOWED_DOMAINS = "localhost,api.example.com"
Then ask Codex: "Get the Miami weather from http://localhost:4020/demo/weather. You can spend up to $0.03."
curl -s http://localhost:4020/fetch \
-H "Content-Type: application/json" \
-d '{
"url": "http://localhost:4020/demo/weather",
"method": "GET",
"maxPriceUsd": 0.01
}'
{
"success": true,
"paid": true,
"amountUsd": 0.001,
"network": "robinhood",
"transaction": "0x3f8a2c6e1b9d4f7a0c5e8b2d6f1a9c3e7b0d4f8a2c6e1b5d9f3a7c0e4b8d2f6a",
"status": 200,
"data": { "city": "Miami", "temperature": 82, "conditions": "Sunny" }
}
// price above autoPayLimitUsd → ask a human, then re-send with "approved": true
{ "success": false, "approvalRequired": true, "amountUsd": 0.08,
"resource": "https://api.example.com/report", "recipient": "0x5486…0631" }
// price above maxPriceUsd
{ "success": false, "code": "PRICE_EXCEEDS_REQUEST_LIMIT",
"error": "Price $0.08 exceeds the requested maxPriceUsd of $0.01." }
Everything runs on your machine. The only network calls are to Robinhood Chain and the APIs your agent buys from.
Node 20 or newer is required. Every file and command you need is in the README.
Pulls the official x402 packages and viem.
Writes a fresh wallet into .env and prints only the public address. Send it a few dollars of USDG and a little ETH on Robinhood Chain.
A one-time Permit2 approval (a little ETH for gas). After this every payment is a gasless signature. Spending limits live in .env.
Runs the REST API, the console at http://localhost:4020/app.html, and the paid demo GET /demo/weather ($0.001 USDG).
Register the MCP server (see the config.toml tab), then give Codex a budget and a URL.
x402 is the payment rail; the interesting part is what agents buy with it.
exact on Robinhood Chain USDG payments via Permit2web/upto payments authorize a ceiling, settle the exact usageOpen the console to see balances, budgets and a live paid request against the demo endpoint.