Client Integration (AI Agents)
How AI Agents interact with the Zion Protocol.
Client-Side Integration
The Zion SDK allows AI Agents and developers to easily monetize their APIs using the Zion X-402 Facilitator. It handles the HTTP 402 Payment Required protocol, standardized payment requests, verification, and settlement on the Solana blockchain.
[!NOTE] Subscription Model (0% Platform Fee) Zion operates on a subscription-based model with 0% platform fees. Developers receive 100% of payments directly. Usage is tracked for subscription tier limits (Free: 10,000 txn/month).
Usage (Client-Side / AI Agent)
The SDK provides a ZionAgent class that makes integrating paid APIs as simple as a standard fetch call. It automatically handles the entire 402 Payment Required flow, including:
- Detecting 402 responses
- Creating and signing the transaction
- Submitting to the Solana blockchain
- Retrying the request with payment proof
1. Initialize the Agent
Initialize the agent with your Solana private key.
import { ZionAgent } from "@ziongateway/sdk";
const agent = new ZionAgent({
privateKey: process.env.SOLANA_PRIVATE_KEY!, // Base58 encoded
rpcUrl: "https://api.mainnet-beta.solana.com" // Optional
});2. Make Requests
Use agent.fetch() exactly like the standard fetch API. If payment is required, it happens automatically in the background.
// Just call fetch - payment happens automatically if needed
const response = await agent.fetch("https://api.merchant.com/premium-data");
if (response.ok) {
const data = await response.json();
console.log("Received paid content:", data);
}
// Optional: Check if a payment was made
if (response.paymentMade) {
console.log(`Paid via tx: ${response.txSignature}`);
}That's it! No transaction building, no buffer decoding, no manual retries.
Manual Integration (Advanced)
If you prefer to build the transaction manually (or are using a different language), follow these steps when you receive a 402 Payment Required response.
1. Handling the 402 Response
The server returns payment requirements in x402 v2 format:
{
"scheme": "exact",
"payTo": "FjK...", // Developer's Wallet
"amount": "100000", // Atomic units (0.1 USDC)
"asset": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", // USDC Mint
"network": "solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1", // CAIP-2 format
"maxTimeoutSeconds": 3600
}[!IMPORTANT] x402 v2 Changes
- Field name changed:
recipient→payTo- Network uses CAIP-2 format:
solana:<genesisHash>- Payment goes 100% to developer (no treasury split)
2. Creating the Transaction
Transfer the exact amount to the payTo address. No fee splitting required.
import { PaymentBuilder } from "@ziongateway/sdk";
const instructions = await PaymentBuilder.createExactInstructions({
sender: wallet.publicKey.toBase58(),
recipient: requirements.payTo,
amount: requirements.amount,
asset: requirements.asset,
connection
});
const tx = new Transaction().add(...instructions);
const signature = await wallet.sendTransaction(tx, connection);
await connection.confirmTransaction(signature, "confirmed");3. Creating the Payment Header
After confirmation, create the payment header and retry the request. The header is a base64-encoded JSON object containing the transaction signature.
const paymentHeader = PaymentBuilder.createHeader({
transaction: signature,
resource: "https://api.example.com/endpoint",
paymentRequirements: requirements
});
const response = await fetch("/api/protected", {
headers: { "X-Payment": paymentHeader }
});Header Payload Structure (x402 v2):
{
"x402Version": 2,
"resource": {
"url": "https://api.example.com/endpoint"
},
"accepted": {
"scheme": "exact",
"payTo": "DeveloperWalletAddress",
"amount": "100000",
"asset": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
"network": "solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1",
"maxTimeoutSeconds": 3600
},
"payload": {
"transaction": "base64EncodedTxOrSignature"
}
}Manual Integration (Without SDK)
If you don't want to use the Zion SDK, you can manually build the transaction using @solana/web3.js and @solana/spl-token.
import { Connection, Transaction, PublicKey } from "@solana/web3.js";
import {
createTransferInstruction,
getAssociatedTokenAddress
} from "@solana/spl-token";
async function payAndFetch(url: string, wallet: any) {
// 1. Initial Request
let response = await fetch(url);
if (response.status === 402) {
// Parse Payment-Required header (x402 v2)
const paymentRequiredHeader = response.headers.get("Payment-Required");
const requirements = JSON.parse(atob(paymentRequiredHeader));
// 2. Build Transaction (100% to developer)
const connection = new Connection("https://api.mainnet-beta.solana.com");
const transaction = new Transaction();
const assetMint = new PublicKey(requirements.asset);
const senderPubkey = wallet.publicKey;
// Get ATAs
const sourceATA = await getAssociatedTokenAddress(assetMint, senderPubkey);
const recipientPubkey = new PublicKey(requirements.payTo);
const recipientATA = await getAssociatedTokenAddress(assetMint, recipientPubkey);
// Single transfer: 100% to developer (no fee split)
transaction.add(
createTransferInstruction(
sourceATA,
recipientATA,
senderPubkey,
BigInt(requirements.amount)
)
);
// 3. Sign & Send
const { blockhash } = await connection.getLatestBlockhash();
transaction.recentBlockhash = blockhash;
transaction.feePayer = senderPubkey;
const signature = await wallet.sendTransaction(transaction, connection);
await connection.confirmTransaction(signature, "confirmed");
// 4. Create x402 v2 Payment Header
const paymentPayload = {
x402Version: 2,
resource: { url },
accepted: requirements,
payload: { transaction: signature }
};
const paymentHeader = btoa(JSON.stringify(paymentPayload));
// 5. Retry with X-Payment header
response = await fetch(url, {
headers: { "X-Payment": paymentHeader }
});
}
return response.json();
}