OpenMid

Quick Start (x402 Server)

#Integrate ERC-8004 Registration in Minutes

Adding ERC-8004 agent registration to your x402 server is incredibly simple with OpenMid. By passing an "erc-8004" extension in your payment middleware configuration, the facilitator automatically handles agent registration during the first payment settlement.

What You Get

  • Automatic Registration - Facilitator registers your agent on-chain using EIP-7702
  • Onchain Identity - Your agent gets a unique ID in the ERC-8004 registry
  • Feedback System - Enable authenticated client evaluations
  • No Extra Requests - Registration happens as part of payment settlement

Network Information

Payment Networks: Base Mainnet, Base Sepolia

Facilitator URL: https://facilitator.openmid.xyz

Facilitator Address: 0x16e47d275198ed65916a560bab4af6330c36ae09

ERC-8004 Network: Base Sepolia

Delegation Contract: 0xFdc90fCC6929a2f42a9D714bD10520eEE98bD378

#How Simple Is It?

Just add the extensions field to your payment middleware configuration:

app.use(
  paymentMiddleware(
    {
      "/weather": {
        accepts: {
          payTo,
          scheme: "exact",
          price: "$0.001",
          network: "eip155:8453",
        },
        extensions: {
          "erc-8004": {
            registerAuth: registerAuth,        // (required) EIP-7702 authorization
            tokenURI: "https://...",           // (required) metadata URI
            metadata: [{ key: "name", ... }],  // (required) onchain data
            feedbackAuthEndpoint: "/sign",     // (optional) feedback endpoint
            feedbackEnabled: true,             // (optional) enable feedback system
          },
        },
      },
    },
    service,
  ),
);

💡 That's it! The facilitator handles registration, identity management, and feedback authorization automatically.

#Step 1: Environment Setup

Create a .env file with your configuration:

# OpenMid facilitator URL
FACILITATOR_URL=https://facilitator.openmid.xyz

# Your agent's address (receives payments)
ADDRESS=0x...

# Your agent's private key (for signing)
AGENT_PRIVATE_KEY=0x...

# ERC-8004 delegation contract (Base Sepolia)
DELEGATE_CONTRACT_ADDRESS=0xFdc90fCC6929a2f42a9D714bD10520eEE98bD378

#Step 2: Generate EIP-7702 Authorization

The authorization allows the facilitator to register your agent with ERC-8004. Create this helper function:

import { createWalletClient, http, type Address } from "viem";
import { baseSepolia } from "viem/chains";
import { privateKeyToAccount } from "viem/accounts";

async function generateSerializedRegistrationAuthorization(
  delegateContractAddress: Address,
  agentPrivateKey: `0x${string}`,
  chainId: number,
) {
  const agentAccount = privateKeyToAccount(agentPrivateKey);

  const walletClient = createWalletClient({
    account: agentAccount,
    chain: baseSepolia,
    transport: http(),
  });

  const authorization = await walletClient.signAuthorization({
    account: agentAccount,
    contractAddress: delegateContractAddress,
    chainId,
  });

  // Serialize for JSON transmission
  return {
    chainId: authorization.chainId.toString(),
    address: authorization.address,
    nonce: authorization.nonce.toString(),
    yParity: authorization.yParity,
    r: authorization.r,
    s: authorization.s,
  };
}

#Step 3: Initialize x402 with OpenMid Facilitator

Set up your x402 server to use the OpenMid facilitator:

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

const app = express();
app.use(express.json());

const facilitatorUrl = process.env.FACILITATOR_URL;
const payTo = process.env.ADDRESS as `0x${string}`;
const agentPrivateKey = process.env.AGENT_PRIVATE_KEY as `0x${string}`;
const delegateContractAddress = process.env.DELEGATE_CONTRACT_ADDRESS as `0x${string}`;

// Initialize OpenMid facilitator client
const facilitatorClient = new HTTPFacilitatorClient({ url: facilitatorUrl });
const service = new x402ResourceServer(facilitatorClient);
registerExactEvmScheme(service);

#Step 4: Configure Payment Middleware with ERC-8004 Extension

Generate the authorization and configure your payment-protected endpoints:

// Generate the EIP-7702 authorization
const registerAuth = await generateSerializedRegistrationAuthorization(
  delegateContractAddress,
  agentPrivateKey,
  84532, // Base Sepolia chain ID for ERC-8004
);

// Configure payment middleware with ERC-8004 extension
app.use(
  paymentMiddleware(
    {
      "/weather": {
        accepts: {
          payTo,
          scheme: "exact",
          price: "$0.001",
          network: "eip155:8453", // Base Mainnet for payments
        },
        extensions: {
          "erc-8004": {
            registerAuth: registerAuth,
            tokenURI: "https://example.com/tokenURI",
            metadata: [
              { key: "name", value: "Weather Agent" },
              { key: "description", value: "Provides weather data" }
            ],
            feedbackAuthEndpoint: "/signFeedbackAuth",
            feedbackEnabled: true,
          },
        },
      },
    },
    service,
  ),
);

💡 Key Point: Payments happen on Base Mainnet (eip155:8453), while ERC-8004 registration happens on Base Sepolia (chain ID 84532). The facilitator handles both networks automatically.

#Step 5: Create Your Protected Endpoint

Define your payment-protected API endpoint as usual:

app.get("/weather", (req, res) => {
  res.send({
    report: {
      weather: "sunny",
      temperature: 70,
    },
  });
});

The middleware handles everything: payment verification, settlement, and agent registration on the first payment.

#Step 6: Implement Feedback Signing (Optional)

If you enabled feedback, implement the signing endpoint:

app.post("/signFeedbackAuth", async (req, res) => {
  try {
    const { hash } = req.body;

    if (!hash) {
      return res.status(400).json({
        success: false,
        error: "Missing required field: hash",
      });
    }

    const normalizedHash = hash.startsWith("0x") ? hash : `0x${hash}`;
    const agentAccount = privateKeyToAccount(agentPrivateKey);
    const signature = await agentAccount.sign({ hash: normalizedHash });

    res.json({
      success: true,
      signature,
    });
  } catch (error) {
    res.status(500).json({
      success: false,
      error: error.message,
    });
  }
});

The facilitator will POST feedback authorization hashes to this endpoint after successful payments, allowing clients to submit authenticated evaluations.

#Step 7: Start Your Server

const PORT = 4021;

app.listen(PORT, () => {
  console.log(`Server listening at http://localhost:${PORT}`);
});

#Step 8: Verify Agent Registration

After your first payment, you can verify that your agent was successfully registered with ERC-8004:

# Query your agent ID
curl "https://facilitator.openmid.xyz/agent?address=0xYourAgentAddress"

# Response if registered:
{
  "success": true,
  "address": "0xyouragentaddress",
  "agentId": "1842"
}

# Response if not registered yet:
{
  "success": false,
  "error": "Agent not found for address: 0x..."
}

💡 Note: Registration happens automatically during your first payment settlement. Use this endpoint to check if your agent has been registered and to retrieve your agent ID for future reference.

#What Happens During Payment

1. Payment Verification

Middleware sends payment payload to POST /verify on facilitator

2. Payment Settlement

If valid, facilitator settles payment on-chain via POST /settle

3. Agent Registration (First Payment Only)

Facilitator uses your EIP-7702 authorization to register agent with ERC-8004 registry

4. Feedback Authorization (If Enabled)

Facilitator generates feedback auth hash and POSTs to your signing endpoint

#ERC-8004 Extension Options

registerAuth (required)

EIP-7702 authorization object from generateSerializedRegistrationAuthorization

tokenURI (required)

URI pointing to JSON metadata for your agent (follows NFT metadata standard)

metadata (required)

Array of { key: string, value: string } pairs stored onchain with the agent

feedbackAuthEndpoint (optional)

Endpoint path where facilitator POSTs feedback authorization hashes for signing

feedbackEnabled (optional)

Set to true to enable the feedback system for this endpoint

#Testing Your Integration

Use curl to see the payment flow:

# Request without payment
curl http://localhost:4021/weather

# Response: 402 Payment Required
{
  "error": "X-PAYMENT header is required",
  "paymentRequirements": {
    "scheme": "exact",
    "network": "eip155:8453",
    "price": "1000",
    "payTo": "0x...",
    ...
  }
}

#Complete Working Example

See the full implementation in our example repository:

#Next Steps