Skip to content

Latest commit

 

History

2 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 

Repository files navigation

⚡ Flash402

Turn any API into a pay-per-call endpoint — an onchain USDC paywall over HTTP 402.

Live → flash402.xyz · Built on the x402 protocol · Base Sepolia

demo.mp4

This is a case study. The product is live; the source is private (it's on a path to monetization). Below is the architecture and the engineering decisions behind it, with representative code.


The problem

Charging for an API today means one of two bad options: bolt on an entire billing stack (accounts, API keys, Stripe, metering, invoicing), or give the data away. Neither fits machine callers — an AI agent can't sign up, hold an API key, or fill in a checkout form.

x402 revives the dormant HTTP 402 Payment Required status code so a caller pays for a request in the request itself, in stablecoin, with no account. Flash402 makes that a no-code product: paste any API URL, set a per-call price, share a gateway link. Humans or agents pay per call; the money settles onchain in USDC.


How it works

sequenceDiagram
    participant C as Caller / AI agent
    participant G as Flash402 Gateway
    participant F as x402 Facilitator
    participant U as Your API (upstream)

    C->>G: GET /api/gw/{id}
    G-->>C: 402 Payment Required (price · asset · payTo)
    Note over C: sign EIP-3009 authorization<br/>(a signature, no gas)
    C->>G: GET /api/gw/{id} + payment header
    G->>F: verify + settle onchain (USDC)
    F-->>G: settled ✓
    G->>U: proxy the original request (path/query/method intact)
    U-->>G: 200 + data
    G-->>C: 200 + data (unlocked)
Loading

The gateway is a thin, payment-gated reverse proxy. Your API never changes; the proxy sits in front of it and only forwards the request once payment settles.


Engineering deep-dives

1. The gateway is a single Next.js route handler

The whole product hinges on one server file: a catch-all route that proxies any path/query/method to the upstream and records the payment only when the upstream actually succeeds. No separate backend, no SDK for the API owner.

// app/api/gw/[id]/[[...path]]/route.ts
if (upstream.ok) {
  const payer = payerFrom(r);           // decode the signed payment header
  await store.incrementHits(endpoint.id);
  await store.recordPayment({ endpointId: endpoint.id, owner: endpoint.owner,
                              payer, status: "paid", trace: /* real trace */ });
}
export const GET = handle;
export const POST = handle;

withX402 gates the handler on status < 400, so a payment is only ever recorded against a genuine 200 from the real API — never a 402 or an error.

2. SSRF hardening — the gateway fetches arbitrary user URLs

A proxy that fetches any URL a stranger submits is a textbook SSRF risk: point it at 169.254.169.254 (cloud metadata) or localhost and it leaks internal services.

The gateway resolves every upstream host and rejects private/reserved ranges — loopback, RFC-1918 private blocks, CGNAT, link-local (including the cloud-metadata address), and their IPv6 equivalents. Crucially, it fetches with redirects handled manually and re-runs that host check on every redirect hop, because a perfectly public URL can 3xx into an internal one. Requests are also bounded by a hard timeout so a slow or hostile upstream can't tie up the proxy.

3. Gasless payments — the caller signs, never pays gas

Payments use the exact scheme over EIP-3009 transferWithAuthorization: the caller signs a typed-data authorization (no gas, no onchain tx from them); the facilitator submits it and covers gas. Flash402 adapts a connected viem wallet into the shape x402's client expects:

// lib/x402-browser.ts
function signerFromWallet(wallet: WalletClient) {
  const address = wallet.account!.address;
  return {
    address,
    signTypedData: (msg) => wallet.signTypedData({ account: address, ...msg }),
  };
}

const client = new x402Client().register(NETWORK, new ExactEvmScheme(signer));
const paidRes = await wrapFetchWithPayment(fetch, client)(url, { cache: "no-store" });

4. Data you never lose — a delete that doesn't delete

Payment records are revenue history; endpoints have earnings attached. So nothing is ever hard-deleted. "Delete an endpoint" flips an archived flag (the gateway 404s, but earnings still count toward lifetime stats); "Clear" on the payment log flips a hidden flag. There is no DELETE handler at all — the API layer makes destruction impossible.

// lib/store.ts — soft-hide, never destroy
async hidePayments(owner: string, ids: string[]): Promise<void> {
  /* set hidden = true on matching rows; the rows stay in the DB */
}
// app/api/payments/route.ts
// No DELETE handler: payment records are never destroyed.

Tech stack & why

Layer Choice Why
Framework Next.js 16 (App Router, Turbopack) One repo for the landing, the console, and the gateway API — the proxy is just a route handler. Server/client boundary keeps secrets off the client.
Payments x402 (@x402/next, @x402/evm, @x402/fetch) Native HTTP-402 rail; withX402 gates route handlers; EIP-3009 gasless settlement.
Wallet wagmi v3 + viem + Reown AppKit Multi-wallet connect modal; viem wallet client feeds the x402 signer.
Data Supabase (Postgres) Server-side service_role only; RLS on; soft-delete/soft-hide flags.
Hosting Vercel Per-request serverless scaling suits spiky pay-per-call traffic; single-push deploys.

Secrets (SUPABASE_SERVICE_ROLE_KEY, x402 config) live only in server code and never reach the browser. The gateway, the store, and the SSRF guard are all server-side.


Roadmap

  • Multichain. The protocol is chain-agnostic; Base / Ethereum / Arbitrum / Polygon have USDC + x402 support. The current single-network limit is the facilitator, not the code: the public x402.org facilitator settles Base Sepolia only. Mainnet means swapping to a facilitator that covers it (e.g. Coinbase CDP) — one config change.
  • Payment-log export, per-endpoint analytics, and richer agent-facing docs.

About

Turn any API into a pay-per-call endpoint — an onchain USDC paywall over HTTP 402, built on the x402 protocol. Live product case study.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors