Every recipe below runs against the real, live gateway

The WickedAPI
Cookbook.

Copy-paste recipes for two audiences: builders who want to monetize an API, and buyers — humans or agents — who want to pay for one. No sandbox, no mocked responses. Every example here works against paywall.wickedapi.com right now.

Monetize your API.

Five recipes, start to finish: get a key, paywall a real endpoint, edit pricing live, import in bulk, and check what you've earned.

1

Get your API key — no approval needed

Self-serve signup is public. Pick a name and a slug; you get a working API key back immediately, shown once.

$ curl -X POST https://paywall-admin.wickedapi.com/signup \
    -H "Content-Type: application/json" \
    -d '{"name":"My API","slug":"myapi"}'

{
  "tenant": { "id": "clx...", "slug": "myapi" },
  "apiKey": "x402_live_..."  // save this — shown once
}

Rate-limited to 5 signups/hour/IP — plenty for a real signup, not much use for spam.

2

Paywall a real endpoint — not a demo response

Set upstreamUrl and a paid request gets forwarded to your real backend; the real response comes back to the caller. Omit it and callers just get a generic confirmation payload instead — useful for testing the payment flow before your backend is ready.

$ curl -X POST https://paywall-admin.wickedapi.com/tenants/me/routes \
    -H "Authorization: Bearer x402_live_..." \
    -H "Content-Type: application/json" \
    -d '{
  "method":      "GET",
  "path":        "/forecast",
  "price":       "$0.01",
  "network":     "eip155:8453",
  "payTo":       "0xYourWalletAddress",
  "upstreamUrl": "https://your-real-api.com/forecast"
}'

# Live at https://paywall.wickedapi.com/myapi/forecast — GET/POST query
# params and JSON body are forwarded through to your backend as-is.

upstreamUrl must be a public https:// address — localhost, private IPs, and internal hostnames are rejected at write time.

3

Change your price — no redeploy, no downtime

Edits apply within about 20 seconds. The gateway polls Postgres and picks up price and payout-wallet changes live.

$ curl -X PATCH https://paywall-admin.wickedapi.com/tenants/me/routes/<route-id> \
    -H "Authorization: Bearer x402_live_..." \
    -H "Content-Type: application/json" \
    -d '{"price": "$0.005"}'
4

Import your whole API surface at once

Have ten endpoints to paywall? Send them all in one call — it upserts, so re-running the same import is safe.

$ curl -X POST https://paywall-admin.wickedapi.com/tenants/me/routes/import \
    -H "Authorization: Bearer x402_live_..." \
    -H "Content-Type: application/json" \
    -d '{
  "routes": [
    { "method":"GET",  "path":"/search",  "price":"$0.002", "network":"eip155:8453", "payTo":"0xYourWallet", "upstreamUrl":"https://your-api.com/search" },
    { "method":"POST", "path":"/analyze", "price":"$0.05",  "network":"eip155:8453", "payTo":"0xYourWallet", "upstreamUrl":"https://your-api.com/analyze" }
  ]
}'
5

Check what you've earned

Every settlement is recorded with tx hash, payer address, amount, and route — real on-chain data, queryable per-tenant.

$ curl https://paywall-admin.wickedapi.com/tenants/me/settlements \
    -H "Authorization: Bearer x402_live_..."

{ "settlements": [{ "status": "settled", "amount": "10000", "txHash": "0x0c6d48...", ... }] }
Good to know: agents with staked reputation on our partner reputation service automatically get tiered rate limits and fee discounts on any route you paywall — no setup required on your end. See Recipe 10 for how buyers opt in.

Pay per call.

Three ways to pay, depending on where your code runs: a Node.js backend, a browser, or an autonomous agent discovering endpoints on its own.

6

Pay from Node.js — the official SDK

The simplest path for a backend or an agent: the @x402/fetch interceptor handles the 402 → sign → retry cycle for you.

$ npm install @x402/fetch @x402/core viem

import { withPaymentInterceptor } from "@x402/fetch";
import { createWalletClient, http } from "viem";
import { privateKeyToAccount } from "viem/accounts";
import { base } from "viem/chains";

const account = privateKeyToAccount(process.env.PRIVATE_KEY);
const wallet = createWalletClient({ account, chain: base, transport: http() });
const fetchWithPay = withPaymentInterceptor(fetch, wallet);

const res = await fetchWithPay("https://paywall.wickedapi.com/wickedapi/weather");
const data = await res.json();  // 0.01 USDC paid automatically
7

Pay from the browser — a connected wallet, no backend

The "exact" scheme is just an EIP-712-signed EIP-3009 authorization under the hood, so a browser wallet can sign it directly via eth_signTypedData_v4 — no bundler, no SDK. This is exactly what powers the live demo on our homepage.

// 1. Fetch unpaid, decode the 402
const res = await fetch("/wickedapi/weather");
const required = JSON.parse(atob(res.headers.get("payment-required")));
const accepted = required.accepts[0];

// 2. Sign the EIP-3009 authorization (domain comes from accepted.extra)
const signature = await window.ethereum.request({
  method: "eth_signTypedData_v4",
  params: [account, JSON.stringify(typedData)], // see full source below
});

// 3. Retry with X-PAYMENT — real weather comes back on success
const paid = await fetch("/wickedapi/weather", {
  headers: { "x-payment": btoa(JSON.stringify(paymentPayload)) },
});

Full working source (typed-data construction, nonce generation, chain switching): /pay-demo.js — it's the exact script running our own live demo, unminified.

8

Discover paywalled endpoints automatically

Every route here is indexed on the x402 Bazaar the first time it settles a real payment — an autonomous agent can search it instead of being told which URL to call.

import { HTTPFacilitatorClient } from "@x402/core/server";
import { withBazaar } from "@x402/extensions/bazaar";

const client = withBazaar(new HTTPFacilitatorClient());
const resources = await client.extensions.bazaar.listResources({ type: "http" });
// -> paywalled endpoints, their prices, and their input/output shapes
9

Get a discount by staking reputation

Declare your wallet on the initial request to get a tier-discounted price quote. It's optimistic — we independently re-verify against your real, signature-backed wallet before settling, so declaring someone else's wallet gets you a cheaper quote, never a payment that actually goes through.

$ curl https://paywall.wickedapi.com/wickedapi/weather \
    -H "X-Agent-Wallet: 0xYourStakedWalletAddress"

# Tiers (live, from the reputation service):
# unranked 1x rate · bronze 1.5x, 5% off · silver 2x, 10% off · gold 4x, 25% off

Staking itself happens on the reputation service, not here — see stake.wickedapi.com for its registration and staking endpoints.

10

Handle failures the way the protocol intends

Three things worth building into any agent that pays autonomously:

  • A 402 is expected, not an error — it's the price list. Parse accepts[] and decide whether to pay.
  • Retrying the same signed payload after a network blip is safe — idempotency keys mean it settles at most once, never twice.
  • A 502 after payment means the seller's own backend failed after settlement went through — there's no automatic refund yet, so budget for that like any real payment-then-fulfill system.