x402 SDK

Use the OptimAI x402 SDK to create paid searches and keep access across agents.

@optimai-network/x402-sdk is a typed client SDK for OptimAI x402 search endpoints.

It wraps two awkward parts of the flow:

  • the initial 402 Payment Required challenge
  • the follow-up payment-signature header generation

It also returns a serializable paymentContext object, including the original payment-signature, so another agent or process can keep working with the same paid search later.

Install

pnpm add @optimai-network/x402-sdk

Quick start: EVM / Base

import {
  createOptimaiX402Client,
  createViemPaymentHandler,
} from "@optimai-network/x402-sdk"

const paymentHandler = createViemPaymentHandler({
  privateKey: process.env.X402_EVM_PAYER_PRIVATE_KEY!,
  rpcUrls: {
    "eip155:8453": "https://mainnet.base.org",
    "eip155:84532": "https://sepolia.base.org",
  },
})

const client = createOptimaiX402Client({
  baseUrl: "https://api-onchain.optimai.network",
  paymentHandler,
})

const { search, paymentContext } = await client.createSearch({
  query: "What is liquidation?",
})

const completed = await client.waitForSearchCompletion(search.id, {
  paymentContext,
})

console.log(completed.result?.answer)

X402_EVM_PAYER_PRIVATE_KEY is the payer wallet private key used to sign the x402 payment payload. It is not a server key, not a Coinbase facilitator key, and not an API key.

Quick start: Solana

import {
  createOptimaiX402Client,
  createSolanaPaymentHandler,
} from "@optimai-network/x402-sdk"

const paymentHandler = createSolanaPaymentHandler({
  privateKey: process.env.X402_SOLANA_PAYER_PRIVATE_KEY!,
  rpcUrls: {
    "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp": "https://api.mainnet-beta.solana.com",
    "solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1": "https://api.devnet.solana.com",
  },
})

const client = createOptimaiX402Client({
  baseUrl: "https://api-onchain.optimai.network",
  paymentHandler,
})

const { search, paymentContext } = await client.createSearch({
  query: "What is liquidation?",
})

const completed = await client.waitForSearchCompletion(search.id, {
  paymentContext,
})

console.log(completed.result?.answer)

X402_SOLANA_PAYER_PRIVATE_KEY is the Solana payer wallet private key used to sign the x402 payment payload. The payer wallet needs enough USDC for the payment and enough SOL to pay Solana network fees.

Client methods

createOptimaiX402Client(config) creates the high-level SDK client.

Available methods:

  • createSearch(input, options?)
  • getSearch(id, options?)
  • cancelSearch(id, options?)
  • waitForSearchCompletion(id, options?)
  • rememberPaymentContext(context)
  • forgetPaymentContext(id)

Payment handlers

createViemPaymentHandler(config) creates a payment handler backed by @x402/evm, @x402/fetch, and viem.

Built-in network support:

CAIP-2Network
eip155:8453Base
eip155:84532Base Sepolia

createSolanaPaymentHandler(config) creates a payment handler backed by the Solana x402 path.

Built-in Solana network support:

CAIP-2Network
solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdpSolana mainnet
solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1Solana devnet

Payment requirements and payTo

SDK users do not manually set payTo, amount, asset, network, or Solana feePayer values in normal usage. Those values come from the OptimAI server's 402 Payment Required challenge.

The SDK reads the server challenge, chooses the first supported payment option for the handler you configured, signs the payment, and retries the paid request. If your app needs to display the receiver or payment details, inspect paymentContext.paymentRequired.accepts after createSearch().

Payment statuses

x402_payment_status in responses can be:

StatusMeaning
verified_unsettledPayment is verified, but settlement is not finalized in OptimAI yet. A chain transfer may already exist while the server is still confirming and persisting the settlement ID.
settledSettlement is finalized and the settlement ID, usually a transaction hash, is persisted.
voidedPayment was voided, usually because the request was cancelled or failed before settlement.
settlement_failedThe server exhausted settlement retries and needs manual or operator follow-up.

Persist access across agents

GET /external/v1/x402/search/:id works best when the client replays the exact original payment-signature used for the paid create call.

Because of that, the SDK returns:

type SearchPaymentContext = {
  id: string
  paymentRequired: X402PaymentRequired
  paymentSignature?: string
}

Persist this object alongside the search ID if another agent or process will poll or fetch the search later:

const { search, paymentContext } = await client.createSearch({ query: "..." })

// Store paymentContext somewhere durable.

client.rememberPaymentContext(paymentContext)
const latest = await client.getSearch(search.id)

If you retry createSearch() with the same Idempotency-Key from another process, pass the previously stored context back in options.existingPaymentContext so the SDK can authenticate the 303 redirect target with the original signature:

const retry = await client.createSearch(
  { query: "..." },
  {
    idempotencyKey: "search-123",
    existingPaymentContext: paymentContext,
  }
)

Local smoke tests

The package includes a smoke script for testing the built SDK against a live OptimAI x402 endpoint:

X402_EVM_PAYER_PRIVATE_KEY=0x... pnpm smoke:local:evm

For backward compatibility, pnpm smoke:local still runs the EVM smoke path.

Solana smoke testing is optional and additive:

X402_SOLANA_PAYER_PRIVATE_KEY='[...]' pnpm smoke:local:solana

Defaults:

  • OPTIMAI_X402_BASE_URL=https://api-onchain.optimai.network
  • mainnet RPC for eip155:8453 defaults to https://mainnet.base.org
  • Solana mainnet RPC defaults to https://api.mainnet-beta.solana.com

Optional overrides:

  • OPTIMAI_X402_QUERY="What is liquidation?"
  • OPTIMAI_X402_BASE_URL=http://localhost:3002
  • X402_EVM_BASE_RPC_URL=https://mainnet.base.org
  • X402_EVM_BASE_SEPOLIA_RPC_URL=https://sepolia.base.org
  • X402_SOLANA_MAINNET_RPC_URL=https://api.mainnet-beta.solana.com
  • X402_SOLANA_DEVNET_RPC_URL=https://api.devnet.solana.com
  • X402_PAYER_PRIVATE_KEY=0x... for legacy EVM setups
  • X402_RPC_URL_BASE=https://mainnet.base.org
  • X402_RPC_URL_BASE_SEPOLIA=https://sepolia.base.org
  • X402_RPC_URL=https://mainnet.base.org
  • OPTIMAI_X402_RUN_CANCEL=1