x402 · Robinhood Chain · chain 4663

Charge for an API call
without an account on either side.

Wrap a route, name a price. The caller pays per request in USDG and the money lands in your wallet — no signup, no subscription, no processor in between.

app/api/your-endpoint/route.ts
import { withX402Payment } from '@/lib/x402/middleware';

export const POST = withX402Payment(handler, "0.01");
Protocol fee
0%
Settles in
USDG
Accounts required
none

How a paid request works

Four steps, all of them in lib/x402/middleware.ts. No facilitator required, no account anywhere in the loop.

  1. 01

    The request arrives without payment

    Your handler is wrapped once. Payless intercepts before your code runs.

    GET /api/data/weather?city=Istanbul
  2. 02

    Payless answers 402

    The response carries the price, your address, the chain ID and the tokens you accept.

    HTTP/1.1 402 Payment Required
    
    {
      "amount": "0.01",
      "currency": "USDG",
      "recipient": "0x…",
      "network": "4663"
    }
  3. 03

    The caller pays on chain

    A real USDG transfer on Robinhood Chain. The caller retries with its transaction hash — not a promise to pay, but a receipt.

    X-Payment: {"from":"0x…","amount":"0.01",
      "token":"USDG","chainId":"4663",
      "transactionHash":"0x13c8…"}
  4. 04

    Payless reads the receipt

    It confirms the transfer landed, paid the right address, cleared the price, and has not been spent before. Only then does your handler run.

    HTTP/1.1 200 OK
    x-payment-chain: robinhood
    
    { "city": "Istanbul", "temperature": 22 }

The transaction hash is also the replay key: one transfer buys exactly one response. Reuse it and the request is rejected. What is still open is a shared store for that ledger, so replay protection holds across serverless instances — see the chain docs.

One wrapper on the handler you already wrote

Your route keeps its signature. The price is the second argument.

app/api/your-endpoint/route.ts
import { withX402Payment } from '@/lib/x402/middleware';

async function handler(req: NextRequest) {
  // Your API logic here
  const data = await processRequest(req);
  return NextResponse.json({ data });
}

// Add payment requirement - that's it!
export const POST = withX402Payment(handler, "0.01");
caller side
// 1. Pay on Robinhood Chain
const hash = await usdg.transfer(recipient, amount);

// 2. Call again with the receipt
const response = await fetch('/api/your-endpoint', {
  method: 'POST',
  headers: {
    'X-Payment': JSON.stringify({
      transactionHash: hash,   // proof, not a promise
      amount, token: 'USDG', chainId: '4663'
    })
  },
  body: JSON.stringify({ data })
});

Selling data about the assets the chain carries

Reading a tokenised equity on Robinhood Chain is permissionless. Moving one is not. So these endpoints sell data about them and settle in USDG — no securities held, no upstream key, and every answer checkable against the explorer.

/api/rwa/tokens$0.02 USDGEvery Robinhood stock token, supply read live
/api/rwa/token$0.01 USDGOne tokenised equity, by ticker
/api/rwa/holdings$0.02 USDGAn address’s tokenised equity position
/api/chain/receipt$0.02 USDGDid this transaction actually pay me?
/api/chain/balance$0.01 USDGETH and token balances for any address
/api/chain/token$0.01 USDGERC-20 metadata, read live from chain 4663
/api/data/crypto$0.015 USDGSpot prices, no API key on your side
/api/tools/qrcode$0.005 USDGHalf a cent a QR code
Call them in the playground