- Facilitator - verifies and broadcasts the payment on-chain
- Resource Server - defines which tokens are accepted and which APIs require payment
- Client(s) - initiates payments and accesses paid endpoints, either through an automated backend wallet representing a machine identity, or a web wallet like MetaMask
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
peaqas a supported network before you use it; otherwise run the facilitator from the x402-peaq repository. It listens on the port set inFACILITATOR_PORT(3333in the repository’s.env.example). The facilitator snippet below listens on4020, so pointFACILITATOR_URLat 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 a402 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 theX-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.

-
Frontend User (MetaMask) - a human user signs a payment authorization with their wallet to access an API feature.

Project setup
The x402-peaq repository contains the complete implementation examples for:- Facilitator
- Resource Server
- Clients (frontend + backend)
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: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). Includeasset.address,asset.decimals, and optionaleip712 { 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 passaccountdirectly. -
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-PAYMENTheader - the server has the facilitator verify and settle the payment, then returns the settlement in the
X-PAYMENT-RESPONSEheader
-
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.

