Give an AI a budget and let it safely purchase useful internet resources.

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.

$0.001 demo endpoint price
< 1s 402 to settled data
5 MCP tools
0 keys exposed to the model
codex — equinox402 mcp live

        
How it works

One request. One 402. One signed payment.

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.

Equinox payment flow The agent calls Equinox, Equinox requests the paid API, receives a 402 payment-required response, checks the spending policy, signs a USDG payment, retries with the payment signature, receives the data with a payment response, and returns it to the agent. Agent codex · claude · any MCP Equinox policy · wallet · signer Paid API x402 · $0.001 / call 402 PAYMENT-REQUIRED 200 + PAYMENT-RESPONSE policy ✓ · sign USDG request result GET · retry + signature 402 · 200

  1. Agent calls x402_fetch with a max price
  2. Equinox requests the resource
  3. API answers 402 with PAYMENT-REQUIRED
  4. Policy check: max, daily limit, allowlist
  5. Sign USDG exact Permit2 transfer locally
  6. Retry with PAYMENT-SIGNATURE
  7. 200 + PAYMENT-RESPONSE (tx signature)
  8. Data and receipt returned to the agent
Guardrails first

Everything an agent needs to spend, nothing it needs to steal.

Budgets are enforced in Equinox, not in the prompt. The model can ask; it can never sign.

Spending policy

Max per payment, daily limit, and an auto-pay threshold above which a human must approve. Every rule is checked before signing.

Domain allowlist

Only pay hosts you trust. The allowlist is re-checked on every hop, so a sneaky redirect can't route funds elsewhere.

Replay protection

Idempotency keys and nonce tracking mean a retried request never double-pays, and a captured signature can't be replayed.

Never exposes keys

The private key lives in Equinox's process. Tools return balances, receipts and data — never secrets, never to the model.

MCP + REST + SDK

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.

Gasless payments

Approve USDG for Permit2 once; after that every payment is a signature, with no ETH gas per call. Settles on Robinhood Chain (eip155:4663).

MCP tools

Five tools. A complete wallet your agent can reason about.

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.

input
{
  "url": "https://api.example.com/weather?city=Miami",
  "method": "GET"
}
output
{
  "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.

input
{
  "url": "https://api.example.com/weather?city=Miami",
  "method": "GET",
  "maxPriceUsd": 0.03
}
output
{
  "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.

input
{}
output
{
  "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.

input
{}
output
{
  "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.

input
{ "limit": 10 }
output
{
  "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
    }
  ]
}
Integrate

Three ways in. Same policy engine.

Drop the MCP server into Codex, call the local REST API from any language, or use the TypeScript SDK directly.

examples/simple-fetch.ts
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…" }
.codex/config.toml
# 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."

request
curl -s http://localhost:4020/fetch \
  -H "Content-Type: application/json" \
  -d '{
    "url": "http://localhost:4020/demo/weather",
    "method": "GET",
    "maxPriceUsd": 0.01
  }'
response · 200
{
  "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." }
Five-minute setup

From download to a paid request on Robinhood Chain.

Everything runs on your machine. The only network calls are to Robinhood Chain and the APIs your agent buys from.

Get the project

Node 20 or newer is required. Every file and command you need is in the README.

cd equinox402

Install dependencies

Pulls the official x402 packages and viem.

npm install

Create and fund a wallet

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.

npm run wallet:new
# → buyer 0x87E2…7A53  (send USDG + a little ETH)

Approve USDG once

A one-time Permit2 approval (a little ETH for gas). After this every payment is a gasless signature. Spending limits live in .env.

npm run approve
# limits: EQUINOX402_MAX_PAYMENT_USD, EQUINOX402_DAILY_LIMIT_USD …

Start Equinox

Runs the REST API, the console at http://localhost:4020/app.html, and the paid demo GET /demo/weather ($0.001 USDG).

npm run dev:api   # API + console + demo seller

Add to Codex

Register the MCP server (see the config.toml tab), then give Codex a budget and a URL.

codex             # inside the repo: .codex/config.toml is picked up
# "Fetch localhost:4020/demo/weather — spend at most $0.03"
Roadmap

Where this is going.

x402 is the payment rail; the interesting part is what agents buy with it.

Now · 0.1

  • x402 V2 exact on Robinhood Chain USDG payments via Permit2
  • Five MCP tools inspect, fetch, balance, spending, history
  • Spending policy engine max, daily, auto-pay threshold, allowlist
  • Replay protection idempotency keys and nonce tracking
  • Local REST API + console this site, served from web/

Next

  • Metered inference pay per token for hosted models behind 402
  • Paid MCP tools tools that charge per call, settled in USDG
  • upto payments authorize a ceiling, settle the exact usage
  • Approval inbox approve above-threshold payments from any device

Later

  • Agent-to-agent payments sub-agents with sub-budgets
  • Multi-wallet and team policies per-project limits and receipts export
  • Facilitator support gasless settlement, more chains via x402 facilitators
  • Signed audit trail tamper-evident history for compliance

Ready to give your agent a wallet?

Open the console to see balances, budgets and a live paid request against the demo endpoint.

Open console Read the setup