NetDollarx402 rails

API monetization for the agent era

Agents are ready to pay. Most API stacks are not.

NetDollar is an x402 facilitator for HTTP 402 API monetization. Remove human checkout bottlenecks and let autonomous buyers pay in-band so high-intent usage converts immediately.

The biggest pain point: monetization breaks autonomous demand.
APIs respond in milliseconds, but payment often still expects human steps: account creation, card entry, and billing setup. Agents drop, conversion collapses, and valuable usage never becomes revenue.
Recover lost demand
Convert agent intent at request time instead of losing it in account setup.
Keep flows autonomous
Buyers retry with payment headers directly, no manual checkout interruptions.
Ship revenue safely
Verify, settle, and enforce policy at the edge with deterministic payment rails.

Payment flow

End-to-end sequence

  1. Step 1Buyer Agent

    Request premium endpoint

    Agent calls the protected route without payment on first request.

    GET /v1/premium/quote
  2. Step 2Seller API / Gateway

    Return HTTP 402

    Seller enforces payment and returns payment requirements for the route.

    status=402paymentRequirements
  3. Step 3Buyer Agent

    Run buyer guardrails

    Client validates max spend, network, asset, and payTo policy before signing.

    maxAmountallowedNetworksallowedAssetsallowedPayTo
  4. Step 4Buyer Agent

    Sign payment + retry

    Client creates signed payload with payment identifier and retries request.

    PAYMENT-SIGNATUREpayment identifier
  5. Step 5Seller API / Gateway

    Validate and verify

    Seller validates payload and calls facilitator verify endpoint.

    POST /v2/x402/verifyx402VersionpaymentPayload
  6. Step 6NetDollar Facilitator

    Verify checks

    Facilitator verifies signature, amount, network, asset, and payTo.

    isValidpayerinvalidReason
  7. Step 7Seller API / Gateway

    Idempotency gate

    Seller checks payment identifier to prevent duplicate settlement.

    paymentId lookupcached outcome
  8. Step 8Seller API / Gateway

    Settle payment

    If not already settled, seller calls facilitator settle endpoint.

    POST /v2/x402/settletransaction hash
  9. Step 9Seller API / Gateway

    Return protected response

    On settlement success, seller returns premium response payload.

    status=200premium data
  10. Step 10Async Jobs

    Post-settlement pipeline

    Emit analytics, persist receipts, and queue webhook/confirmation jobs.

    event logsreceiptswebhooks
Decision points
Critical pass/fail gates in the payment lifecycle.

Payment header present?

Seller API / Gateway

Pass: Proceed to verify pipeline.

Fail: Return HTTP 402 with payment requirements.

Verify result valid?

NetDollar Facilitator

Pass: Proceed to idempotency + settle.

Fail: Return payment failure with invalidReason.

Already settled for payment identifier?

Seller API / Gateway

Pass: Return cached response and skip double-settlement.

Fail: Call settle endpoint.

Settle success?

NetDollar Facilitator

Pass: Return premium response.

Fail: Return settlement failure and do not serve paid payload.

Data contracts
Payloads exchanged across buyer, seller, and facilitator.

402 Payment Required response

Seller API / GatewayBuyer Agent

errorx402VersionpaymentRequirements

Payment requirements

Seller API / GatewayBuyer Agent

schemenetworkassetmaxAmountRequiredpayToresource

Paid retry request

Buyer AgentSeller API / Gateway

PAYMENT-SIGNATUREpaymentPayloadpayment identifier

Verify payload

Seller API / GatewayNetDollar Facilitator

x402VersionpaymentPayloadpaymentRequirements

Verify response

NetDollar FacilitatorSeller API / Gateway

isValidpayerinvalidReason

Settle response

NetDollar FacilitatorSeller API / Gateway

successpayertransactionnetworkerrorReason
  1. 1. `GET /v2/x402/supported` to confirm network and scheme support.
  2. 2. `POST /v2/x402/verify` before service delivery.
  3. 3. `POST /v2/x402/settle` to finalize payment execution.

Integration

Endpoints
Use staging for test traffic and production for live settlement.

Staging: https://api.staging.netdollar.dev

Production: https://api.netdollar.dev

GET /v2/x402/supported

POST /v2/x402/verify

POST /v2/x402/settle

GET /v1/discovery/resources

Implementation checklist
  • Define payment requirements for each paid route (scheme, network, asset, amount, payTo).
  • Return HTTP 402 when `PAYMENT-SIGNATURE` is missing.
  • On retry, call `POST /v2/x402/verify` with your seller API key.
  • If valid, call `POST /v2/x402/settle` and then return the protected response.
  • Optionally publish capabilities through `GET /v1/discovery/resources`.
Server example
1// Example: paid FX quote endpoint with real pricing tiers (Cloudflare Worker style)
2type Tier = "basic" | "pro";
3
4interface Env {
5  FACILITATOR_BASE_URL: "https://api.staging.netdollar.dev" | "https://api.netdollar.dev";
6  SELLER_API_KEY: string;
7  SELLER_PAY_TO: string;
8}
9
10interface PaymentRequirements {
11  scheme: "exact";
12  network: "base";
13  asset: "USDC";
14  maxAmountRequired: string; // USDC base units (6 decimals)
15  payTo: string;
16  resource: string;
17  description: string;
18  mimeType: "application/json";
19  maxTimeoutSeconds: number;
20  extra: {
21    tier: Tier;
22    paymentIdentifier: true;
23  };
24}
25
26interface VerifyResponse {
27  isValid: boolean;
28  payer?: string;
29  invalidReason?: string;
30}
31
32interface SettleResponse {
33  success: boolean;
34  payer?: string;
35  network?: string;
36  transaction?: string;
37  errorReason?: string;
38}
39
40const PRICE_USDC_6: Record<Tier, string> = {
41  basic: "25000",   // $0.025 for quote only
42  pro: "150000",    // $0.15 for quote + indicators
43};
44
45function buildPaymentRequirements(url: URL, payTo: string): PaymentRequirements {
46  const wantsIndicators = url.searchParams.get("detail") === "indicators";
47  const tier: Tier = wantsIndicators ? "pro" : "basic";
48
49  return {
50    scheme: "exact",
51    network: "base",
52    asset: "USDC",
53    maxAmountRequired: PRICE_USDC_6[tier],
54    payTo,
55    resource: url.pathname,
56    description: wantsIndicators ? "FX quote + indicators" : "FX quote",
57    mimeType: "application/json",
58    maxTimeoutSeconds: 60,
59    extra: {
60      tier,
61      paymentIdentifier: true,
62    },
63  };
64}
65
66async function facilitatorPost<TResponse>(
67  env: Env,
68  path: "/v2/x402/verify" | "/v2/x402/settle",
69  body: unknown,
70): Promise<TResponse> {
71  const response = await fetch(env.FACILITATOR_BASE_URL + path, {
72    method: "POST",
73    headers: {
74      authorization: "Bearer " + env.SELLER_API_KEY,
75      "content-type": "application/json",
76    },
77    body: JSON.stringify(body),
78  });
79
80  if (!response.ok) {
81    throw new Error("Facilitator call failed: " + path + " status=" + response.status);
82  }
83
84  return (await response.json()) as TResponse;
85}
86
87export default {
88  async fetch(request: Request, env: Env): Promise<Response> {
89    const url = new URL(request.url);
90    if (url.pathname !== "/v1/fx/quote") return new Response("Not found", { status: 404 });
91
92    const paymentRequirements = buildPaymentRequirements(url, env.SELLER_PAY_TO);
93    const signatureHeader = request.headers.get("PAYMENT-SIGNATURE");
94
95    if (!signatureHeader) {
96      return Response.json(
97        { error: "payment_required", x402Version: 2, paymentRequirements },
98        { status: 402 },
99      );
100    }
101
102    const paymentPayload: unknown = JSON.parse(signatureHeader);
103    const paymentIdentifier = request.headers.get("X-PAYMENT-ID") ?? crypto.randomUUID();
104    const idempotencyUrl = new URL("/__payments/" + paymentIdentifier, request.url).toString();
105    const idempotencyRequest = new Request(idempotencyUrl);
106
107    // Idempotency: if this payment identifier already settled, return cached response.
108    const cached = await caches.default.match(idempotencyRequest);
109    if (cached) return cached;
110
111    const verify = await facilitatorPost<VerifyResponse>(env, "/v2/x402/verify", {
112      x402Version: 2,
113      paymentPayload,
114      paymentRequirements,
115    });
116
117    if (!verify.isValid) {
118      return Response.json(
119        { error: "invalid_payment", invalidReason: verify.invalidReason ?? "unknown" },
120        { status: 402 },
121      );
122    }
123
124    const settle = await facilitatorPost<SettleResponse>(env, "/v2/x402/settle", {
125      x402Version: 2,
126      paymentPayload,
127      paymentRequirements,
128    });
129
130    if (!settle.success) {
131      return Response.json(
132        { error: "settlement_failed", errorReason: settle.errorReason ?? "unknown" },
133        { status: 402 },
134      );
135    }
136
137    const symbol = url.searchParams.get("symbol") ?? "EURUSD";
138    const response = Response.json({
139      symbol,
140      tier: paymentRequirements.extra.tier,
141      data: {
142        bid: 1.0832,
143        ask: 1.0834,
144        spreadBps: 1.8,
145        timestamp: new Date().toISOString(),
146      },
147      payment: {
148        payer: settle.payer,
149        transaction: settle.transaction,
150        network: settle.network,
151        amount: paymentRequirements.maxAmountRequired,
152        asset: paymentRequirements.asset,
153      },
154    });
155
156    response.headers.set("X-PAYMENT-ID", paymentIdentifier);
157    await caches.default.put(idempotencyRequest, response.clone());
158    return response;
159  },
160};

FAQ

Copy-ready prompts

Paste these directly into Cursor or your preferred coding agent to implement NetDollar integration. Each prompt is shown in a read-only textarea and can be copied with one click.

Seller integration prompt
For teams adding x402 payment enforcement to their API.
Buyer agent prompt
For teams building autonomous paid-request clients.