FlexPay

Reference

Integrate the checkout widget, wire Solana wallet adapters, and optionally proxy Jupiter and RPC from your own origin so keys and CORS behave like production infrastructure.

Overview

FlexPay packages a Jupiter Swap API v2 flow (quote via /order, submit via /execute) with the Tokens and Price APIs for surface-level UX: token metadata, slippage safety, and optional volatility checks before the user signs.

Cluster: Jupiter's swap routes are mainnet. Point rpcEndpoint at a mainnet RPC. The demo can use /api/solana-rpc to avoid public-RPC 403s in the browser.

Install

Start with the SDK only, then add wallet adapter packages used by the React widget.

pnpm add @flexpay/sdk
npm i @flexpay/sdk

Add wallet adapters (required for connect/sign in widget mode):

pnpm add @solana/wallet-adapter-react @solana/wallet-adapter-react-ui
npm i @solana/wallet-adapter-react @solana/wallet-adapter-react-ui

What each URL is for

In proxy mode the widget calls your origin instead of Jupiter or a raw RPC directly. Your server attaches secrets, avoids CORS issues, and can rate-limit.

  • rpcEndpoint: Solana JSON-RPC transport (balances, blockhash, tx confirmation context).
  • quoteApiUrl: route discovery + quote/order.
  • swapApiUrl: execute/broadcast of signed swap transaction.
  • tokensApiUrl: token metadata/list for the selector UX.
ConfigRoleTypical path (this demo)
rpcEndpointSolana JSON-RPC: balances, blockhash, and other chain reads the widget needs before and after the swap. Not Jupiter—use your provider or a same-origin proxy./api/solana-rpc (browser) with SSR fallback to a public or private HTTPS RPC
quoteApiUrlBase URL for Jupiter Swap API v2 quote / order requests./api/flexpay/quote
swapApiUrlBase URL for execute (signed transaction submit) and related swap execution calls./api/flexpay/swap
tokensApiUrlBase for token metadata and list endpoints the UI uses for labels, icons, and input selection./api/flexpay/tokens

Environment

In direct mode the widget calls Jupiter with jupiterApiKey from the client. For production, prefer server routes that inject the key so it is not exposed in the bundle.

# Browser-safe keys only where intended
NEXT_PUBLIC_FLEXPAY_MERCHANT_WALLET=<merchant_pubkey>
NEXT_PUBLIC_JUPITER_API_KEY=<jupiter_browser_key>
NEXT_PUBLIC_SOLANA_RPC_URL=<https_rpc_or_omit_for_demo_proxy>

Widget (direct API key)

Wrap your app (or subtree) with the same wallet provider you use for any Solana dApp.

import { FlexPayWidget } from "@flexpay/react";

export function Checkout() {
  return (
    <FlexPayWidget
      merchantWallet={process.env.NEXT_PUBLIC_FLEXPAY_MERCHANT_WALLET!}
      amount={29.99}
      rpcEndpoint="https://api.mainnet-beta.solana.com"
      jupiterApiKey={process.env.NEXT_PUBLIC_JUPITER_API_KEY}
      onSuccess={(p) => console.log(p.signature)}
    />
  );
}

Proxy mode (recommended)

Point quoteApiUrl, swapApiUrl, and tokensApiUrl at your Next.js API routes. Implementations in this repo forward to Jupiter and attach the API key on the server.

<FlexPayWidget
  merchantWallet={process.env.NEXT_PUBLIC_FLEXPAY_MERCHANT_WALLET!}
  amount={29.99}
  rpcEndpoint={typeof window !== "undefined"
    ? new URL("/api/solana-rpc", window.location.origin).toString()
    : "https://api.mainnet-beta.solana.com"}
  quoteApiUrl="/api/flexpay/quote"
  swapApiUrl="/api/flexpay/swap"
  tokensApiUrl="/api/flexpay/tokens"
/>

FlexPayWidget — fields

PropTypeNotes
amountnumberUSDC-equivalent target amount for the swap route.
merchantWalletstringReceiver pubkey (USDC destination).
rpcEndpointstringMainnet HTTP RPC; use your provider or the demo proxy URL.
jupiterApiKeystring?Direct-to-Jupiter mode; omit when using proxy routes.
quoteApiUrlstring?Jupiter quote/order base; omit if using jupiterApiKey on the client.
swapApiUrlstring?Swap execute base; pairs with quoteApiUrl in proxy mode.
tokensApiUrlstring?Token list/metadata base for picker and display.
slippageBpsnumber?Basis points passed through to Jupiter order requests.
onSuccess / onError / onCancelcallbacksPayment lifecycle hooks.
onTelemetry / onVolatilitycallbacksLatency stages and optional Price API volatility verdict.
themeobject?CSS variable overrides for widget chrome.

Operations

  • Insufficient funds / SOL for fees: Ensure the payer wallet has enough of the input token and reserved SOL for transaction fees on mainnet.
  • 403 on public RPC: Use an authenticated RPC provider or the demo /api/solana-rpc proxy pattern.
  • Devnet RPC + mainnet Jupiter: Not supported; configs guard against mixed clusters.