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

Equinox lets AI agents automatically pay for APIs using USDC on Solana. 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 lamport 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 USDC 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 USDC 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 USDC exact 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 keypair 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.

Devnet → Mainnet

Develop on devnet with faucet USDC, then flip one CAIP-2 network id to go live on Solana mainnet. Same code, same policy.

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": "USDC",
  "network": "solana",
  "networkId": "solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1",
  "recipient": "7YhZ9pQ4kTn2xWm8bCvLr3sJfHd6Ee1uKpNa5qRtVx2",
  "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 USDC 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": "solana",
  "transaction": "4xK9vQ2mN8pLrT6wYc3hJb1dFgE5sA7uZi9oPq2RmWf2Qe",
  "status": 200,
  "data": { "city": "Miami", "temperature": 82, "conditions": "Sunny" }
}

wallet_balance reports the agent wallet's public address and current SOL (for fees) and USDC (for payments) balances on the configured network.

input
{}
output
{
  "address": "9uGkA3wRt5nMzq2Pv7xLc8JbHfYe4dSaWo6TiNpQr1Km",
  "network": "solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1",
  "networkName": "devnet",
  "sol": 1.5,
  "usdc": 9.87
}

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 Solana transaction signature — 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": "USDC",
      "network": "solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1",
      "recipient": "7YhZ9pQ4kTn2xWm8bCvLr3sJfHd6Ee1uKpNa5qRtVx2",
      "transaction": "5UkxR2mN8pLrT6wYc3hJb1dFgE5sA7uZi9oPq2RmWf2Qe",
      "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_SOLANA_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 = "devnet"
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": "solana",
  "transaction": "5UkxR2mN8pLrT6wYc3hJb1dFgE5sA7uZi9oPq2RmWf2Qe",
  "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": "7YhZ…Vx2" }

// 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 clone to a paid request on devnet.

Everything runs locally. The only network calls are to Solana devnet and the faucets.

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 x402 and Solana Kit packages.

npm install

Create and fund a wallet

Writes a fresh wallet into .env and prints only the public address. Fund devnet SOL at faucet.solana.com and devnet USDC at faucet.circle.com.

npm run wallet:new
# → address: 9uGk…Q1Km  (fund with devnet SOL + USDC)

Configure your policy

Open .env (created from .env.example) and set your limits and allowed domains.

# .env
# EQUINOX402_MAX_PAYMENT_USD=0.05  EQUINOX402_DAILY_LIMIT_USD=5
# EQUINOX402_AUTO_PAY_LIMIT_USD=0.02  EQUINOX402_ALLOWED_DOMAINS=localhost

Start Equinox

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

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 Solana USDC payments on devnet and mainnet
  • 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 USDC
  • 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