WDK logoWDK documentation

x402

Accept and make instant USD₮0 payments over HTTP using WDK self-custodial wallets

What Is x402?

x402 is an open payment protocol, originally developed by Coinbase, that gives the long-reserved HTTP 402 Payment Required status code a concrete, blockchain-native meaning: if you want this resource, pay for it. No accounts, API keys, or checkout flows. Just plain HTTP.

This matters for AI agents because they need to pay for resources programmatically. x402 makes payment a first-class part of the web stack, so an agent can discover a price, sign a payment, and retry the HTTP request automatically.

The Three Roles

RoleDescription
Client (Buyer)The entity requesting a paid resource. Can be a human application, an AI agent, or any service with a wallet.
Resource Server (Seller)The API or service providing the paid resource. Defines payment requirements and returns 402 for unpaid requests.
FacilitatorAn intermediary that verifies payment signatures and submits transactions on-chain. Never holds funds, only executes signed authorizations.

How the Protocol Works

Client requests a resource

A standard HTTP request. GET, POST, whatever your API expects.

Server responds with 402 Payment Required

With x402 v2, the base64-encoded PAYMENT-REQUIRED response header describes the protected resource and accepted payment options. Decoded, it has this shape:

{
  "x402Version": 2,
  "resource": {
    "url": "https://api.example.com/data",
    "description": "Example data",
    "mimeType": "application/json"
  },
  "accepts": [{
    "scheme": "exact",
    "network": "eip155:9745",
    "amount": "1000000",
    "asset": "0xB8CE59FC3717ada4C02eaDF9682A9e934F625ebb",
    "payTo": "0x1111111111111111111111111111111111111111",
    "maxTimeoutSeconds": 60,
    "extra": { "name": "USDT0", "version": "1", "decimals": 6 }
  }],
  "extensions": {}
}

Client signs a payment

The client constructs an EIP-3009 transferWithAuthorization and signs it with their wallet. No tokens leave the wallet yet. It's a signed intent, not a transfer.

Client retries with payment header

The signed payload goes in the PAYMENT-SIGNATURE header on a retry of the same request. X-PAYMENT is the x402 v1 header.

Facilitator verifies

The server forwards the payload to the facilitator's /verify endpoint. The facilitator checks that the signature is valid, the amount is sufficient, and the payer has funds. No money moves yet.

Server performs the work

Inference, database query, generation, whatever the resource requires. This only happens after verification succeeds.

Facilitator settles on-chain

The server calls the facilitator's /settle endpoint. The facilitator submits the signed authorization on-chain, transferring tokens from buyer to seller.

Server returns the resource

200 OK with the result in the body and a settlement receipt in the PAYMENT-RESPONSE header. X-PAYMENT-RESPONSE is the x402 v1 header.

For the full protocol specification, see x402.org and the x402 GitHub repository.

How to Use x402 With WDK

WDK wallets work as drop-in client signers for the versions used below. WalletAccountEvm beta.19 satisfies the x402 2.26.0 client signer interface directly. Each integration still needs a configured RPC, a supported x402 scheme and network, and an asset contract that implements the selected authorization method.

This guide walks through three things:

  1. Client (Buyer) - Pay for x402-protected resources using a WDK wallet
  2. Server with Hosted Facilitator - Accept x402 payments by delegating verification and settlement to a third-party facilitator
  3. Server with Self-Hosted Facilitator - Assess the current community adapter's version constraints before adopting it

Community modules are developed and maintained independently by third-party contributors.

Tether and the WDK Team do not endorse or assume responsibility for their code, security, or maintenance. Use your own judgment and proceed at your own risk.

The x402 integration described on this page also uses third-party facilitator services. Tether does not operate or guarantee any third-party facilitator. You are solely responsible for using any service.

Artificial intelligence and blockchain transactions carry inherent risks and limitations.

The EVM exact scheme can be configured for a CAIP-2 EVM network when the chosen token implements EIP-3009 and the client, resource server, and facilitator all support that scheme and network. The examples use Plasma and Stable. Buyers sign an EIP-3009 authorization and do not submit an ERC-20 approval or pay settlement gas; they still need enough USD₮0, and the facilitator needs the chain's native gas token.

ChainCAIP-2RPCUSD₮0 ContractExplorer
Plasmaeip155:9745https://rpc.plasma.to0xB8CE59FC3717ada4C02eaDF9682A9e934F625ebbplasmascan.to
Stableeip155:988https://rpc.stable.xyz0x779Ded0c9e1022225f8E0630b35a9b54bE713736stablescan.xyz

Client: Paying for Resources

npm install @tetherto/wdk-wallet-evm@1.0.0-beta.19 @x402/fetch@2.26.0 @x402/evm@2.26.0

Create a wallet

import WalletManagerEvm from "@tetherto/wdk-wallet-evm";

const account = await new WalletManagerEvm(process.env.SEED_PHRASE, {
  provider: "https://rpc.plasma.to", // or "https://rpc.stable.xyz"
}).getAccount();

Register with x402

WalletAccountEvm satisfies the ClientEvmSigner interface directly. No adapter needed.

import { x402Client, wrapFetchWithPayment } from "@x402/fetch";
import { registerExactEvmScheme } from "@x402/evm/exact/client";

const client = new x402Client();
registerExactEvmScheme(client, { signer: account });

const fetchWithPayment = wrapFetchWithPayment(fetch, client);

Make a paid request

fetchWithPayment parses a compatible 402 response, signs an EIP-3009 authorization with your WDK wallet, and makes one paid retry. Check the returned status before consuming the body; a failed verification or settlement can return another error response.

const response = await fetchWithPayment("https://api.example.com/weather", {
  method: "GET",
});

if (!response.ok) {
  throw new Error(`x402 request failed (${response.status})`);
}

const data = await response.json();
console.log("Response:", data);

Your seed phrase controls your funds. Never commit it to version control. Use environment variables or a secrets manager.

Getting USD₮0 on Plasma or Stable

Before making a payment, fund the buyer with USD₮0 on the selected network. If you need to bridge a supported source token, follow the USD₮0 bridge guide for the current route, spender, bounded allowance, quote, and settlement steps.

For EVM wallet beta.19 with bridge beta.10, construct the account directly with its original RPC URL. Manager-derived accounts contain a provider that the bridge rejects. This direct account does not inherit WDK Core transaction policies or middleware; retain required application checks before approval and bridging. See bridge setup.


Server: Accepting Payments (Hosted Facilitator)

Your server delegates verification and settlement to a hosted facilitator. You never interact with the chain directly.

About the Semantic facilitator: Semantic documents a public x402 facilitator at https://x402.semanticpay.io for USD₮0 payments on Plasma and Stable. This is a third-party service not operated, endorsed, or guaranteed by Tether.

The x402 protocol is an open standard. Anyone can build and host their own facilitator. For the API reference, see the Semantic facilitator docs.

Before enabling payments, request GET https://x402.semanticpay.io/supported as described in the facilitator API and confirm that the response advertises x402 v2, your payment scheme, and your network. If the request fails or that combination is absent, do not enable the hosted integration. Select a facilitator verified for the required x402 version, scheme, and network; also review the current self-hosting limitations.

npm install @tetherto/wdk-wallet-evm@1.0.0-beta.19 @x402/express@2.26.0 @x402/evm@2.26.0 @x402/core@2.26.0 express@5.2.1 dotenv@17.2.3

Derive your receiving address

import WalletManagerEvm from "@tetherto/wdk-wallet-evm";

const account = await new WalletManagerEvm(process.env.SEED_PHRASE, {
  provider: "https://rpc.plasma.to", // or "https://rpc.stable.xyz"
}).getAccount();

const sellerAddress = await account.getAddress();

Create the facilitator client

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

const facilitatorClient = new HTTPFacilitatorClient({
  url: "https://x402.semanticpay.io/",
});

Configure payment middleware

import express from "express";
import { paymentMiddleware, x402ResourceServer } from "@x402/express";
import { ExactEvmScheme } from "@x402/evm/exact/server";

const PLASMA_NETWORK = "eip155:9745";   // or "eip155:988" for Stable
const USDT0_PLASMA = "0xB8CE59FC3717ada4C02eaDF9682A9e934F625ebb";   // or "0x779Ded0c9e1022225f8E0630b35a9b54bE713736" on Stable

const app = express();

app.use(
  paymentMiddleware(
    {
      "GET /weather": {
        accepts: [
          {
            scheme: "exact",
            network: PLASMA_NETWORK,
            price: {
              amount: "1000", // $0.001 (6 decimals)
              asset: USDT0_PLASMA,
              extra: { name: "USDT0", version: "1", decimals: 6 },
            },
            payTo: sellerAddress,
          },
        ],
        description: "Weather data",
        mimeType: "application/json",
      },
    },
    new x402ResourceServer(facilitatorClient).register(
      PLASMA_NETWORK,
      new ExactEvmScheme(),
    ),
  ),
);

The extra fields are passed to the buyer for EIP-712 signature construction. name and version must match what the on-chain USD₮0 contract expects.

Add your routes

// Gated - requires payment
app.get("/weather", (req, res) => {
  res.json({ weather: "sunny", temperature: 70 });
});

// Not gated - no payment config
app.get("/health", (req, res) => {
  res.json({ status: "ok" });
});

app.listen(4021);

Routes not listed in the middleware config behave like normal Express routes.

Multi-Chain (Plasma + Stable)

To accept payments on both chains, add both networks to the accepts array and register both with the resource server. The default x402 client selects the first compatible payment option; it does not select by wallet balance. Fund that network or provide an application-owned payment selector.

const NETWORKS = {
  plasma: { network: "eip155:9745", usdt0: "0xB8CE59FC3717ada4C02eaDF9682A9e934F625ebb" },
  stable: { network: "eip155:988",  usdt0: "0x779Ded0c9e1022225f8E0630b35a9b54bE713736" },
};

const resourceServer = new x402ResourceServer(facilitatorClient)
  .register(NETWORKS.plasma.network, new ExactEvmScheme())
  .register(NETWORKS.stable.network, new ExactEvmScheme());

// In paymentMiddleware config:
// accepts: [
//   { scheme: "exact", network: NETWORKS.plasma.network, price: priceOnChain("plasma"), payTo },
//   { scheme: "exact", network: NETWORKS.stable.network, price: priceOnChain("stable"), payTo },
// ]

Lifecycle Events

For facilitator-specific notifications, consult the Semantic facilitator API and confirm support with the provider. Use verification and settlement responses to decide whether a payment succeeded.


Server: Self-Hosted Facilitator (In-Process)

The @semanticio/wdk-wallet-evm-x402-facilitator community module is intended to adapt a WDK EVM account to the x402 facilitator signer interface. Verify an exact compatible package set before using it for in-process verification and settlement.

@semanticio/wdk-wallet-evm-x402-facilitator is a community module developed and maintained by Semantic Pay. Tether does not endorse, audit, or assume responsibility for this module. It is currently in beta. Test thoroughly before using in production.

The published @semanticio/wdk-wallet-evm-x402-facilitator@1.0.0-beta.2 package depends on @tetherto/wdk-wallet-evm@1.0.0-beta.7 and @x402/evm@2.2.0. Its facilitator signer implementation does not fully match the x402 2.26.0 signer contract used by the runnable client and hosted examples on this page. Do not combine beta.2 with those versions as a production recipe without maintainer-confirmed compatibility and end-to-end verification of rejection, settlement, timeout, and receipt behavior.

The published package and its source repository are the primary references. The related SemanticPay demo targets an older, differently named GitHub dependency and x402 2.2.0, so it is not a runnable example for the npm package and versions documented above.


Summary

RolePackagesNotes
Buyer (Client)WDK EVM beta.19; x402 fetch and EVM 2.26.0WalletAccountEvm satisfies ClientEvmSigner directly.
Seller (Hosted)WDK EVM beta.19; x402 Express, EVM, and core 2.26.0Enable only after the facilitator advertises x402 v2 and the exact scheme and network.
Seller (Self-Hosted)Community adapter beta.2No runnable pairing is documented here; verify a maintainer-supported package set first.

Resources

On this page