402Revnuvo/ developersGitHub

Gateway

The Gateway is Revnuvo's facilitator — it verifies signatures, checks balances, and settles payments on Base. It never custodies funds; every transfer moves directly between buyer and seller wallets.

Endpoints

POST/verify

Validates a signed payment authorization against the resource's price and network, without moving funds.

POST/settle

Submits the verified authorization on-chain. USDC transfers directly from buyer to seller.

Sequence

verify → settle
Client          Resource Server        Gateway            Base
  |  GET /resource     |                    |                |
  |-------------------->|                    |                |
  |  402 + terms        |                    |                |
  |<--------------------|                    |                |
  |  GET + X-Payment     |                    |                |
  |-------------------->|                    |                |
  |                     |  POST /verify       |                |
  |                     |------------------->|                |
  |                     |  valid: true        |                |
  |                     |<-------------------|                |
  |                     |  POST /settle       |                |
  |                     |------------------->|                |
  |                     |                    |  transferWithAuthorization
  |                     |                    |--------------->|
  |                     |                    |  confirmed      |
  |                     |                    |<---------------|
  |  200 + resource      |                    |                |
  |<--------------------|                    |                |

Protecting an endpoint

The SDK (@revnuvo/x402) is client-side — it signs payments, it doesn't gate resource servers. To protect your own endpoint, call the gateway's /quote, /verify, and /settle directly, the same way Revnuvo's own Assess Worker does:

worker.ts
const GATEWAY = "https://gateway.revnuvo.site";

export default {
  async fetch(req: Request) {
    const payment = req.headers.get("X-Payment");

    if (!payment) {
      // No payment yet — get a fresh signed quote and return it as the 402 body
      const quoteRes = await fetch(`${GATEWAY}/quote`, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          path: "/your-resource",
          maxAmountRequired: "50000", // atomic units
          payTo: "0xYourAddress",
          network: "eip155:8453",
          asset: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
        }),
      });
      return new Response(await quoteRes.text(), { status: 402 });
    }

    const { quote, payment: signedPayment } = JSON.parse(atob(payment));

    const verifyRes = await fetch(`${GATEWAY}/verify`, {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ quote, payment: signedPayment }),
    });
    const { valid, receipt } = await verifyRes.json();
    if (!valid) return new Response("Payment invalid", { status: 402 });

    const settleRes = await fetch(`${GATEWAY}/settle`, {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ receipt }),
    });
    if (!(await settleRes.json()).settled) {
      return new Response("Settlement failed", { status: 402 });
    }

    return new Response(JSON.stringify({ trust_score: 92 }));
  },
};