
Equinox
Equinox lets AI agents automatically pay for APIs using USDG on Robinhood Chain.
AI Agent
↓
Equinox
↓
Paid API
↓
x402
↓
USDG on Robinhood ChainGive an AI a budget and let it safely buy useful things on the internet. Your agent says "use this paid API, but don't spend more than $0.05". Equinox detects the x402 payment request, checks your spending rules, signs a USDG payment on Robinhood Chain, retries the request and hands back the data.
- MCP server: plug it into OpenAI Codex or any MCP client.
- TypeScript SDK:
equinox.fetch()works likefetch(), but can pay. - Local REST API + web console: for other agent frameworks, and for you to watch the money.
- Demo paid API:
GET /demo/weatherfor $0.001, so you can try the whole buyer + seller loop.
Download the project
The complete source: MCP server, SDK, REST API, demo API, this website, tests and config templates. Wallet keys are never included.
Five-minute setup
You need Node.js 20+ (nodejs.org).
1. Unzip and install
Unzip equinox402-source.zip, open a terminal in the equinox402 folder and run:
cd equinox402
npm install2. Create a wallet
npm run wallet:newThis writes a fresh buyer wallet and a demo seller wallet into .env and prints only the public addresses. The private key never appears on screen.
3. Fund it on Robinhood Chain
| What | Where | Why |
|---|---|---|
| USDG → buyer | Send from any wallet or exchange that supports Robinhood Chain | This is what your agent spends |
| A little ETH → buyer | Robinhood Chain ETH (bridge or send) | Gas for the one-time Permit2 approval only |
| A little ETH → demo seller | Same | The demo seller settles payments on-chain and pays that gas |
4. Approve USDG once
npm run approveUSDG on Robinhood Chain has no built-in gasless approval, so x402 pays it through Permit2. This one transaction lets Permit2 move USDG when you sign. Every payment after it is a gasless signature.
5. Start Equinox
npm run dev:apiOpen the console at http://localhost:4020/app.html and hit Fetch & pay on the prefilled /demo/weather URL. You just paid $0.001 USDG.
6. Add it to Codex
The project includes .codex/config.toml, so running codex inside the folder picks it up. To use Equinox from any project, see Codex config. Then ask Codex:
Codex calls x402_inspect, sees $0.001, calls x402_fetch, Equinox pays, and Codex answers.
How a payment works
Codex ─▶ Equinox MCP ─▶ HTTP request ─▶ API answers 402
│
read PAYMENT-REQUIRED (x402 V2)
│
check policy: price, daily budget, domain, auto-pay
│
sign USDG Permit2 transfer (official @x402/evm scheme)
│
retry request with PAYMENT-SIGNATURE header
│
seller's facilitator verifies + settles on Robinhood Chain
│
PAYMENT-RESPONSE (tx signature) + the data
│
result returned to CodexEquinox uses the official x402 V2 packages (@x402/core, @x402/evm, @x402/express). Legacy X-PAYMENT headers are not supported.
MCP tools
| Tool | What it does |
|---|---|
x402_fetch | Fetch a URL. If it needs an x402 payment within policy, pay and return the data. Free URLs are returned as-is. |
x402_inspect | Return the price, asset, network, recipient and scheme without paying. |
wallet_balance | ETH and USDG balance of the payment wallet, and whether the Permit2 approval is done (never keys). |
spending_status | spentTodayUsd, dailyLimitUsd, remainingTodayUsd. |
payment_history | Past payments: timestamp, domain, amount, asset, recipient, tx signature, status. |
x402_fetch input
{ "url": "https://example.com/api/research", "method": "GET", "maxPriceUsd": 0.05 }Output
{
"success": true,
"paid": true,
"amountUsd": 0.01,
"network": "robinhood",
"transaction": "5Kx…",
"data": {}
}Above the auto-pay threshold
{ "success": false, "approvalRequired": true, "amountUsd": 0.08, "resource": "…", "recipient": "…" }If the MCP client supports elicitation, Equinox asks the human directly instead. The agent itself can never approve.
Instructions Equinox gives the agent
- Use
x402_inspectwhen you need to determine the cost of a paid endpoint. - Use
x402_fetchwhen the user has authorized sufficient spending. - Never intentionally split transactions to bypass a payment limit.
- Never increase the requested spending limit.
- Never reveal wallet secrets.
Spending policy
EQUINOX402_MAX_PAYMENT_USD=0.10 # any single payment above this is rejected
EQUINOX402_DAILY_LIMIT_USD=5.00 # total per UTC day
EQUINOX402_AUTO_PAY_LIMIT_USD=0.02 # at/below: pays automatically; above: approvalRequired
EQUINOX402_ALLOWED_DOMAINS=api.example.com,data.example.com # optional allowlist- The caller's
maxPriceUsdcan only tighten these limits, never loosen them. - In-flight payments are reserved against the daily budget, so firing many small requests in parallel can't sneak past it.
- Allowlist entries match the host and its subdomains. Redirects are followed manually and every hop is re-checked. A payment credential is never forwarded across a redirect.
- Version 1 pays USDG only,
exactscheme only, on Robinhood Chain only.
.env reference
This is the full .env.example. npm run wallet:new copies it to .env and fills in the wallet.
# ─── Network ──────────────────────────────────────────────
# Robinhood Chain. Internally mapped to CAIP-2:
# mainnet = eip155:4663 (default — real USDG)
# testnet = eip155:46630 (no official USDG: set EQUINOX402_TOKEN_ADDRESS)
EQUINOX402_NETWORK=mainnet
# Optional custom RPC (recommended for mainnet)
EQUINOX402_RPC_URL=
# ─── Wallet (buyer) ───────────────────────────────────────
# `npm run wallet:new` fills this in (0x-prefixed hex EVM private key).
# NEVER share this file. Equinox never returns this value through MCP/REST/logs.
EQUINOX402_PRIVATE_KEY=
# …or point at a file containing the key instead:
EQUINOX402_KEY_PATH=
# ─── Payment token ────────────────────────────────────────
# Default: USDG 0x5fc5360D0400a0Fd4f2af552ADD042D716F1d168 via Permit2.
EQUINOX402_TOKEN_ADDRESS=
# ─── Spending policy ──────────────────────────────────────
EQUINOX402_MAX_PAYMENT_USD=0.10
EQUINOX402_DAILY_LIMIT_USD=5.00
EQUINOX402_AUTO_PAY_LIMIT_USD=0.02
# ─── Domain protection ────────────────────────────────────
# Comma-separated. If set, payments only go to these hosts (and subdomains).
EQUINOX402_ALLOWED_DOMAINS=
# ─── Local REST API + console ─────────────────────────────
EQUINOX402_API_PORT=4020
EQUINOX402_API_HOST=127.0.0.1
# ─── Storage ──────────────────────────────────────────────
# Payment history, idempotency cache and logs. Default: ~/.equinox402
EQUINOX402_DATA_DIR=
# ─── Demo seller (GET /demo/weather, $0.001 USDG) ─────────
# Seller key: receives demo payments and pays settlement gas (ETH).
EQUINOX402_DEMO_SELLER_PRIVATE_KEY=
EQUINOX402_DEMO_PAY_TO=
EQUINOX402_DEMO_PORT=4021
# Optional: a hosted standard x402 facilitator instead of the built-in one.
EQUINOX402_FACILITATOR_URL=Codex config
Inside the project, .codex/config.toml is picked up automatically. To use Equinox from any project, add this to ~/.codex/config.toml with your own absolute path:
[mcp_servers.equinox402]
command = "node"
args = ["--import", "tsx", "/absolute/path/to/equinox402/src/mcp/server.ts"]
startup_timeout_sec = 20
tool_timeout_sec = 120
# Optional per-agent overrides (these win over .env).
# The wallet key stays in equinox402/.env — never put it here.
[mcp_servers.equinox402.env]
EQUINOX402_MAX_PAYMENT_USD = "0.05"
EQUINOX402_DAILY_LIMIT_USD = "2.00"
EQUINOX402_AUTO_PAY_LIMIT_USD = "0.02"
EQUINOX402_ALLOWED_DOMAINS = "localhost,api.example.com"On Windows, write the path with forward slashes, e.g. C:/Users/you/equinox402/src/mcp/server.ts.
Security
- The private key is loaded from
.envinto a signer that only exposesgetAddress()andsignPayment(). It is never returned by any tool, response or log. - Wallets implement a small interface, so a remote, KMS or hardware signer can be dropped in later.
- Replay protection: every authorization is hashed (SHA-256) and stored. A used authorization is never re-sent, and a settlement receipt already on record isn't counted as a new purchase.
- Idempotency: paid requests carry an
Idempotency-Key. Pass the sameidempotencyKeyagain and you get the stored result, with no second payment. - Logs (
~/.equinox402/equinox402.log): timestamp, URL, domain, amount, token, network, recipient, tx signature, settlement status and latency. Never keys or raw authorizations. - The REST API binds to
127.0.0.1, rejects non-localhostHostheaders and sends no CORS headers, so other websites can't drive your wallet.
interface PaymentSigner {
getAddress(): Promise<string>;
signPayment(requirements: PaymentRequirements, ctx): Promise<PaymentPayload>;
}.env file.SDK
import { Equinox } from "equinox402";
const equinox = new Equinox({
maxPaymentUsd: 0.05,
dailyLimitUsd: 5,
});
const response = await equinox.fetch("https://example.com/api", { maxPriceUsd: 0.01 });
console.log(await response.json());
console.log(response.payment); // { paid, amountUsd, transaction, … }equinox.fetch behaves like native fetch. Policy refusals throw EquinoxPaymentError (check .approvalRequired / .code). equinox.request() returns the structured result without throwing. Also available: inspect(), balance(), spendingStatus(), history().
Try it: npm run demo in one terminal, npm run example in another.
REST API
npm run dev:api serves it at http://localhost:4020.
| Method | Path | Body |
|---|---|---|
POST | /fetch or /api/fetch | { url, method?, maxPriceUsd?, headers?, body?, idempotencyKey?, approved? } |
POST | /inspect | { url, method? } |
GET | /balance · /spending · /history?limit=50 · /status | none |
curl -X POST http://localhost:4020/fetch \
-H "content-type: application/json" \
-d '{"url":"http://localhost:4020/demo/weather","maxPriceUsd":0.05}'approved: true is how a host app (like the console's approval dialog) confirms a payment above the auto-pay limit. Don't give that power to an agent.
Demo paid API
| Endpoint | Price | Purpose |
|---|---|---|
GET /demo/weather | $0.001 USDG | Auto-pays under the default policy |
GET /demo/premium | $0.05 USDG | Above the auto-pay limit, so it shows the approval flow |
curl -i http://localhost:4020/demo/weather # → HTTP 402 + PAYMENT-REQUIREDAfter payment:
{ "city": "Miami", "temperature": 82, "conditions": "Sunny" }Built with the official @x402/express middleware and settled by the official @x402/evm facilitator running inside Equinox: it verifies the buyer's Permit2 signature and submits the transfer on Robinhood Chain, paying gas from the demo seller wallet. It's mounted inside npm run dev:api, or runs standalone on port 4021 with npm run demo.
Network
EQUINOX402_NETWORK=mainnet # → eip155:4663 (default)
EQUINOX402_RPC_URL=https://your-rpc-provider # optionalRobinhood Chain testnet (eip155:46630) has no official USDG. To test there, deploy or pick a test token and set EQUINOX402_NETWORK=testnet plus EQUINOX402_TOKEN_ADDRESS.
Use a fresh wallet holding only what you're willing to let agents spend, and keep the limits tight.
Project files
src/
mcp/ server.ts (stdio), tools.ts (tools + agent instructions)
x402/ client.ts (payment flow), parser.ts (V2 headers), payment.ts
chain/ wallet.ts (PaymentSigner), permit2.ts, balance.ts, connection.ts
policy/ spending-policy.ts, domain-policy.ts
storage/ payments.ts (history, replay + idempotency store)
api/ server.ts (REST + web console)
sdk/ index.ts (Equinox class)
demo/ server.ts (paid /demo/*), setup.ts
config.ts
web/ this website (static, no build step)
examples/ simple-fetch.ts, codex-example.md
scripts/ new-wallet.ts, pack-source.ts, mcp-smoke.ts
test/ offline end-to-end tests
.codex/ config.toml
AGENTS.md .env.example package.json README.md LICENSEScripts
| Command | What it does |
|---|---|
npm run wallet:new | Create a buyer wallet and demo seller in .env |
npm run approve | One-time Permit2 approval for USDG |
npm run dev:api | REST API, console and demo API on :4020 |
npm run demo | Demo seller only, on :4021 |
npm run mcp | MCP server on stdio |
npm run example | SDK example |
npm test | Offline tests |
npm run mcp:smoke | Start the MCP server and call its tools |
npm run build | Compile to dist/ |
npm run pack:source | Rebuild the downloadable zip (keys excluded) |
Roadmap
Version 1 is deliberately small: Robinhood Chain, USDG, x402 V2, exact payments, MCP, fetch, budgets, history and a demo API. The core is shaped so these can be added without rewriting it:
- x402
uptopayments for metered AI inference and variable usage - Paid MCP tools and agent-to-agent payments
- Pay-per-search, pay-per-dataset, pay-per-compute
- Service discovery and API marketplaces
- Per-agent wallets and organization spending policies
- Remote and hardware signers
License: MIT.