Hoodx402 docs

Everything you need to accept per-call payments from AI agents on Robinhood Chain — or to let an agent pay for anything without an account.

testnet pilot Everything on this page describes the testnet pilot. Interfaces may change before mainnet. Pin your SDK version.

Overview

Hoodx402 has three roles. Most readers are one of the first two:

  • API provider — wraps an HTTP endpoint with a price. Agents pay you per call; you never handle keys, invoices, or merchant infrastructure.
  • Agent — any HTTP client with a wallet. It calls an API, receives a price, signs one payment, and gets the response plus an on-chain receipt.
  • Facilitator — Hoodx402's service that verifies signed payments and settles them on-chain, so neither side waits on the other.

Payments use the x402 open standard: the API answers 402 Payment Required with terms in a header, the agent signs an EIP-3009 transfer-with-authorization, and the facilitator settles in USDG. No subscriptions, no API keys, no chargebacks.

Quickstart — provider

Wrap an existing route. If it answers today, it can earn per call.

import { x402 } from "@Hoodx402/sdk";

// your server, unchanged
const api = x402.wrap(app, {
  asset: "0x…",           // EIP-3009 token contract
  assetName: "USDG",      // EIP-712 domain name
  assetVersion: "1",
  chainId: 31337,
  payTo: "0x…",           // your payout address
  decimals: 6,
});

api.route("GET /v1/quote", handler, {
  price: "0.001",   // human decimal — converted once, at registration
});

What the SDK does for you

  • Intercepts the first unauthenticated request and answers 402 with a challenge header.
  • Forwards the request with an X-PAYMENT signature to your handler once payment is verified.
  • Returns a receipt header on every paid call, so both sides can audit it later.

Requirements

  • Node 20+ and any HTTP framework (Express, Fastify, Hono — wrap adapts to the request/response objects).
  • A payout address on Robinhood Chain testnet. Settlement lands there; you never sign anything as a provider.

The settlement flow

One call moves through four states. Each header below is part of the pilot spec.

1 · API answers 402

HTTP/2 402 PAYMENT REQUIRED
x-402: asset=0x…           # EIP-3009 token contract
       amount=1000         # smallest units (0.001, 6 decimals)
       decimals=6 name=USDG version=1
       chain-id=31337 facilitator=Hoodx402
       pay-to=0x…          # provider payout address
       nonce=0x…           # bytes32, single-use
       valid-before=1787903890

Values are URL-encoded when they contain spaces (a token named USDG Mock arrives as name=USDG%20Mock). The provider stores every issued challenge — the payer must satisfy the exact quote.

2 · Agent signs once

The agent signs an EIP-3009 TransferWithAuthorization for amount of the asset, payable to pay-to, valid until valid-before. The signature is a header — not a transaction.

x-payment: scheme=eip3009 from=0x… # payer — must equal the recovered signer
           signature=<65-byte rsv> nonce=0x…

3 · Facilitator settles

The facilitator verifies the signature against the challenge, submits the settled transfer on-chain, and returns the receipt hash. Settlement is idempotent per nonce — a retried call never pays twice.

4 · 200 OK with receipt

HTTP/2 200 OK
x-receipt: 0x91c4…8e02 - settled 0.001 USDG

Agent side

Agents get one helper that handles the 402 round-trip. Give it a wallet-capable signer and a spending cap; it never exceeds the cap.

import { x402Fetch } from "@Hoodx402/sdk";

const res = await x402Fetch(
  "https://quotes.example/v1/quote?symbol=NVDA",
  { signer, maxPrice: "0.01" }
);

const quote = await res.json();
console.log(res.headers.get("x-receipt"));
agent rule of thumb Set maxPrice to the highest amount acceptable for one call. The SDK refuses any challenge above it — treat unexpected prices as untrusted data.

Chain config

ParameterValueNotes
chainrobinhoodEVM. Testnet pilot only for now.
settlement assetUSDGAddress: TBD — published with the pilot contracts.
second assetcbBTCPlanned, routed via the Chainlink CCIP lane.
RPCTBDTestnet endpoint shared with whitelist participants.

Prices are strings denominated in the asset's smallest unit unless the route declares decimals. "0.001" USDG means 0.001 USDG — the SDK converts once, at the route definition, not per call.

Facilitator API

Providers and agents talk to the facilitator over two endpoints. Both are idempotent and safe to retry.

POST /verify

Checks a signed payment against a challenge. Returns valid or a machine-readable reason — nothing moves.

{ "valid": true, "payer": "0x7a…f3", "amount": "0.001" }

POST /settle

Submits the verified payment on-chain. Retries with the same nonce return the original receipt.

{ "receipt": "0x91c4…8e02", "tx": "0x7d3b…01aa",
  "settled": "0.001" }

Registry

Paid endpoints are discoverable. Providers list routes on-chain; agents query the registry instead of hard-coding URLs.

registry.list({ tag: "market-data", chain: "robinhood" });
// → [{ url, price, asset, provider, updatedAt }]

Listing requires a small registration stake (returned on delisting). The stake exists so the registry stays worth reading.

Errors

StatusCodeWhat happened, what to do
402payment_required Expected on the first call. Read x-402, decide, pay or walk away.
400invalid_signature The signature did not match the challenge. Re-fetch the 402 — nonces are single-use.
402insufficient_balance The payer wallet lacks amount USDG. Top up or quote a smaller route.
413price_above_cap Challenge exceeded the agent's maxPrice. The SDK stopped before signing.
429rate_limited Facilitator throttle. Wait for Retry-After, then retry — settlement is idempotent.
503facilitator_unreachable The facilitator is down, your API keeps serving free traffic. Retry paid calls after backoff.

Status

  • Facilitator: live on testnet with design partners.
  • SDK: @Hoodx402/sdk 0.1.x — internal, shared with whitelist participants.
  • Registry: on-chain listing lands with v0.2.
  • Mainnet: gated on the audit — see the roadmap.

Questions or an endpoint you want wrapped? Get whitelist access or open an issue on GitHub.