Skip to content

x402 Payment Flow

Bloomfilter uses x402 for payments — an open protocol that adds native USDC payments to HTTP using the 402 Payment Required status code.

Every paid request follows the same flow:

  1. Send request to a paid endpoint
  2. Receive 402 with payment requirements in the PAYMENT-REQUIRED header
  3. Sign payment — create a USDC payment on Base L2
  4. Retry request with PAYMENT-SIGNATURE header
  5. Server settles the payment on-chain and processes your request

Domain registration and renewal use dynamic pricing — the price depends on the TLD and number of years.

Terminal window
curl -X POST https://api.bloomfilter.xyz/domains/register \
-H "Content-Type: application/json" \
-d '{"domain": "example.io", "years": 1}'
HTTP/1.1 402 Payment Required
PAYMENT-REQUIRED: eyJhY2NlcHRzIjpb... (base64-encoded JSON)
Content-Type: application/json
{
"error": "Payment required",
"domain": "example.io",
"price_usd": "34.99",
"years": 1,
"currency": "USDC",
"network": "eip155:8453"
}

The PAYMENT-REQUIRED header contains a base64-encoded JSON object with:

  • accepts — array of accepted payment schemes (network, asset, price)
  • resource — description of what you’re paying for
Terminal window
curl -X POST https://api.bloomfilter.xyz/domains/register \
-H "Content-Type: application/json" \
-H "PAYMENT-SIGNATURE: eyJwYXlsb2FkIj..." \
-d '{"domain": "example.io", "years": 1}'
HTTP/1.1 201 Created
{
"transactionId": "01JMXYZ...",
"domain": "example.io",
"status": "active",
"years": 1,
"price_usd": "34.99",
"registeredAt": "2026-02-21T12:00:00Z",
"expiresAt": "2027-02-21T00:00:00Z",
"nameservers": ["ns1.bloomfilter.xyz", "ns2.bloomfilter.xyz"],
"dnsRecords": []
}

DNS add, update, and delete operations use a fixed price of $0.10 USDC per operation. The x402 middleware handles this automatically — same flow as above, just with a fixed price.

EndpointPrice
POST /dns/{domain}$0.10
PUT /dns/{domain}/{recordId}$0.10
DELETE /dns/{domain}/{recordId}$0.10

DNS read (GET /dns/{domain}) is free but requires authentication.

PropertyValue
CurrencyUSDC
NetworkBase L2 (chain ID 8453)
CAIP-2 identifiereip155:8453
SettlementOn-chain, immediate
RefundsPayment only settles on 2xx success. If the operation fails, no payment is taken.

The easiest way to integrate x402 in TypeScript:

import axios from "axios";
import { wrapAxiosWithPayment, x402Client } from "@x402/axios";
import { ExactEvmScheme } from "@x402/evm";
import { privateKeyToAccount } from "viem/accounts";
const account = privateKeyToAccount("0xYOUR_PRIVATE_KEY");
const client = new x402Client().register("eip155:*", new ExactEvmScheme(account));
const http = wrapAxiosWithPayment(
axios.create({ baseURL: "https://api.bloomfilter.xyz" }),
client
);
// Payment happens automatically on 402 responses
const { data } = await http.post("/domains/register", {
domain: "example.io",
years: 1,
});

If your wallet doesn’t have enough USDC, the payment will fail:

{
"error": "Payment verification failed",
"message": "insufficient_funds: insufficient balance",
"code": "PAYMENT_INSUFFICIENT"
}

Fund your wallet with USDC on Base before retrying.