Skip to main content

Integration guide

This page covers integrating the confidential payment scheme into your own client application and API server. If you just want to run a quick end-to-end test using TACEO's hosted infrastructure, start with the Quickstart instead.

Install

npm install @taceo/confidential-x402 @x402/fetch viem

Client

The client library intercepts any 402 Payment Required response, constructs the ZK proof and signed payment payload, and retries the request automatically. Your application code makes a normal HTTP request, the payment is invisible to it.

Register the scheme

import { privateKeyToAccount } from 'viem/accounts';
import { x402Client, wrapFetchWithPayment } from '@x402/fetch';
import { ConfidentialEvmScheme } from '@taceo/confidential-x402/client';

const signer = privateKeyToAccount(process.env.PRIVATE_KEY as `0x${string}`);

const client = new x402Client();
client.register('eip155:*', new ConfidentialEvmScheme(signer));

export const fetchWithPayment = wrapFetchWithPayment(fetch, client);

fetchWithPayment is a drop-in replacement for fetch. Use it anywhere you would normally call fetch.

Make a payment-gated request

const response = await fetchWithPayment(
'https://api.example.com/api/premium-data',
{ method: 'GET' }
);

if (response.ok) {
const data = await response.json();
console.log(data);
}

When the server responds with 402, the client handles it invisibly: parses the PaymentRequired payload, generates the Groth16 ZK proof, retries the request with a PAYMENT-SIGNATURE header, and returns the final 200 OK to your code.


Server

The server middleware intercepts incoming requests, returns 402 Payment Required when no valid payment is attached, and verifies the payment against the TACEO facilitator before forwarding the request to your handler.

Basic example

The following examples protect a single route at GET /api/protected and price it at $1 of confidential USDC.

import express from 'express';
import { paymentMiddleware, x402ResourceServer } from '@x402/express';
import { HTTPFacilitatorClient } from '@x402/core/server';
import { ConfidentialEvmScheme } from '@taceo/confidential-x402/server';

const app = express();

const facilitatorClient = new HTTPFacilitatorClient({
url: 'https://x402-facilitator.merces1.taceo.io',
});

app.use(
paymentMiddleware(
{
'GET /api/protected': {
accepts: [
{
scheme: 'confidential',
price: '$1',
network: 'eip155:84532',
payTo: process.env.WALLET_ADDRESS as `0x${string}`,
},
],
},
},
new x402ResourceServer(facilitatorClient).register(
'eip155:84532',
new ConfidentialEvmScheme({ asset: process.env.TOKEN_ADDRESS as string })
)
)
);

app.get('/api/protected', (req, res) => {
res.json({ message: 'Payment verified. Here is your data.' });
});

app.listen(8080, () => console.log('Listening on http://localhost:8080'));

How the middleware works

When a request arrives without a valid PAYMENT-SIGNATURE header:

  1. The middleware returns HTTP 402 Payment Required with a base64-encoded PaymentRequired payload containing the scheme, required amount, your wallet address, and the MPC public keys (fetched from the facilitator's /supported endpoint).
  2. When the client retries with a payment, the middleware forwards it to the facilitator's /verify endpoint.
  3. If verification succeeds, the request is forwarded to your handler.
  4. After your handler responds, the middleware calls /settle asynchronously.

Protecting multiple routes

app.use(
paymentMiddleware(
{
'GET /api/basic': { accepts: [{ scheme: 'confidential', price: '$0.10', network: 'eip155:84532', payTo: address }] },
'GET /api/premium': { accepts: [{ scheme: 'confidential', price: '$5.00', network: 'eip155:84532', payTo: address }] },
'POST /api/action': { accepts: [{ scheme: 'confidential', price: '$1.00', network: 'eip155:84532', payTo: address }] },
},
resourceServer
)
);

Configuration reference

ParameterDescription
schemeMust be "confidential"
priceRequired payment amount, e.g. "$1", "$0.50"
networkCAIP-2 chain ID, e.g. "eip155:84532" for Base Sepolia
payToYour wallet address that receives payments
assetToken contract address (provided by the TACEO facilitator automatically)
Facilitator URLhttps://x402-facilitator.merces1.taceo.io for TACEO's hosted facilitator
Receiving payments

Payments are credited to your payTo address as confidential Merces balance. To withdraw tokens back to a regular ERC-20 balance, use the withdraw function in the Merces client library.