Skip to main content
x402 uses the HTTP 402 Payment Required status code to gate access to APIs, digital content, and machine-to-machine interactions with onchain micropayments, instead of accounts or subscriptions. A client makes an API request and is prompted to authorize a payment with any supported ERC-3009 token on peaq, such as USDC or bridged stgUSDT. Once the facilitator confirms the payment on-chain, either through a delegated or a self-hosted verifier, access is granted. There is no account creation and no manual verification. In this guide, you’ll learn how to implement a full x402 payment flow on peaq, using Express and TypeScript. You’ll build the following components:
  1. Facilitator - verifies and broadcasts the payment on-chain
  2. Resource Server - defines which tokens are accepted and which APIs require payment
  3. Client(s) - initiates payments and accesses paid endpoints, either through an automated backend wallet representing a machine identity, or a web wallet like MetaMask
These are the three roles in the x402 standard: client, resource server, and facilitator. This setup demonstrates both machine-to-machine and human-to-API interactions. On peaq, machines can sign and authorize x402 transactions using their on-chain identity keys, enabling autonomous payment flows between themselves.

Facilitator

The facilitator is responsible for verifying payment authorization and broadcasting transactions to the peaq blockchain. It acts as the verification layer between the client’s signed request and the resource’s API logic. There are two modes of operation:
  • Delegated Verification The resource server delegates payment verification to an external facilitator running on peaq. The facilitator validates transaction proofs and returns a signed receipt via HTTPS. This suits smaller resource servers that prefer not to run blockchain nodes. Check that the facilitator lists peaq as a supported network before you use it; otherwise run the facilitator from the x402-peaq repository. It listens on the port set in FACILITATOR_PORT (3333 in the repository’s .env.example). The facilitator snippet below listens on 4020, so point FACILITATOR_URL at whichever one you run. The x402 docs list more facilitators.
  • Self-Hosted Verification The resource server deploys a facilitator service connected directly to a peaq RPC node. You validate payment proofs locally and control signing, verification, and the transaction lifecycle yourself. It takes more work to run, and it is the usual choice for high-throughput API systems.

Resource Server

The resource server exposes one or more API endpoints protected by x402. When a client requests a protected resource, the server responds with a 402 Payment Required response. The resource server specifies payment requirements per endpoint, including accepted EIP-3009 tokens using contract address and pricing units. These settings determine when the HTTP 402 response is triggered. Once the payment is confirmed via the facilitator, the resource server grants access and returns the API response. This layer bridges the facilitator verification with client authorization.

Client

Clients can be human users interacting through web wallets like MetaMask or Rabby, or autonomous agents using backend wallets linked to peaq machine identities. These clients read the payment requirements from the server’s 402 response, sign a payment authorization, and retry the original API call with that authorization in the X-PAYMENT header. The server has the facilitator verify and settle the payment and returns the settlement in the X-PAYMENT-RESPONSE header. We’ll demonstrate the full flow with two example clients:
  • Backend Autonomous Agent - a programmatic client (with its own private key/machine identity) signs the authorization automatically, representing a “machine paying a machine” flow. x402-peaq-1
  • Frontend User (MetaMask) - a human user signs a payment authorization with their wallet to access an API feature. x402-peaq-2

Project setup

The x402-peaq repository contains the complete implementation examples for:
  • Facilitator
  • Resource Server
  • Clients (frontend + backend)
Clone the repository and follow the instructions in its README.md to get started.

Facilitator

Code Snippet:

Explanation

  • verify() - checks if the client’s signed authorization is valid for the given payment terms.
  • settle() - broadcasts the authorized payment on-chain once verified.
  • PaymentRequirementsSchema / PaymentPayloadSchema - ensure incoming data follows the x402 spec.
  • createSigner() - connects the facilitator’s private key to the correct peaq RPC endpoint.

Resource Server

USDC Code Snippet:
USDT Code Snippet:

Explanation

  • paymentMiddleware(payTo, rules, { url }) - protects routes with x402. On first request returns 402 Payment Required with how-to-pay details; after payment + receipt, it lets the request through.
  • payTo - the receiver address on peaq (e.g., your machine or service wallet) that will receive funds.
  • rules map - keys like “METHOD /path” (e.g., “GET /data”) define which endpoints require payment and at what price/network.
  • Human-price format - price: “$0.01” (USDC on peaq); easy to read and configure for standard ERC-3009 tokens.
  • Atomic-price format - price: { amount, asset } for custom tokens (e.g., stgUSDT). Include asset.address, asset.decimals, and optional eip712 { name, version }.
  • network - which chain to use (here: “peaq”). Must align with the client and facilitator.
  • { url: facilitatorUrl } - points to your Facilitator (delegated or self-hosted) that verifies/settles the payment.
  • app.get("/data", ...) - your protected handler. It only runs after a valid payment receipt is presented on the retried request.
  • Env vars - FACILITATOR_URL, MACHINE_B_ADDRESS, SERVER_PORT; keep the client’s displayed price in sync with the server rule.

Clients

Code Snippet:

Explanation

  • privateKeyToAccount(MACHINE_A_PRIVATE) - loads the machine identity (Machine A) as an EOA used to sign x402 authorizations on peaq.
  • createWalletClient({ account, transport: http(), chain: peaq }).extend(publicActions) - creates a viem wallet client bound to peaq for signing the EIP-3009 payment authorization. x402 types require the public actions; you can also pass account directly.
  • wrapFetchWithPayment(fetch, client, 200000n) - decorates fetch so that when a 402 Payment Required is returned, it:
    • reads the x402 payment requirements from the 402 response
    • signs an authorization with client
    • retries the original request with that authorization in the X-PAYMENT header
    • the server has the facilitator verify and settle the payment, then returns the settlement in the X-PAYMENT-RESPONSE header
    The 3rd argument caps the max value you’re willing to authorize (here, “$0.20 USDC” represented in atomic units set by your integration).
  • await fetchWithPay(url, { method: "GET" }) - performs the request; if payment is needed, the wrapper handles the pay-then-retry flow automatically.
  • response.headers.get("X-PAYMENT-RESPONSE") - base64-encoded JSON “settlement receipt” returned by your server after successful payment; decode to inspect tx details.
  • await response.json() - the actual protected resource payload (e.g., machine data) you wanted after settlement.

Next steps

The facilitator, the resource server, and the client together give you a native x402 payment flow on peaq. For the full examples and configuration options, see the x402-peaq repository.