← DOCS
// RAIL_02 · X402 · PAY_PER_CALL · MAINNET_LIVE

X402.
PAY PER CALL.

Pay direct from any Solana wallet, per inference call. No Bourse account, no API key, no prepaid balance to manage. The facilitator settles USDC on-chain in the same request, then the prompt routes through the same multi-provider stack as the API-key rail. Built for agents.

// TRY_IT

The widget below is sandboxed on devnet so you can try x402 without spending real USDC. We pre-fund the demo wallet, you click RUN, the facilitator settles a 0.01 devnet-USDC payment on-chain, and your prompt routes. The production rail at /api/x402/v1/chat/completions runs on mainnet — same flow, real Circle USDC.

// LIVE_DEMO · X402_PAID_INFERENCE · DEVNET0.01 USDC / CALL

Click RUN. We sign + send a 0.01 USDC payment from a server-funded devnet wallet, the x402 facilitator settles it on-chain, then your prompt routes to the cheapest provider. You see the model response + the on-chain tx in <5 seconds.

// THE_FLOW

  1. 1. POST without payment. Bourse responds 402 Payment Required with payment terms (network, asset, recipient, amount).
  2. 2. Sign the payment. Your client signs a Solana token-transfer transaction matching the terms and base64-encodes it.
  3. 3. POST again with X-PAYMENT. Bourse forwards the signed payment to the facilitator, which verifies and settles on-chain in the same request.
  4. 4. Inference routes + responds. Once payment is settled, the request resolves to the cheapest provider, response streams back. Failover applies same as Rail 1.

// CODE

import { x402Client, wrapFetchWithPayment } from "@x402/fetch";
import { registerExactSvmScheme } from "@x402/svm/exact/client";
import { createKeyPairSignerFromBytes } from "@solana/kit";
import { readFileSync } from "fs";

// Devnet keypair JSON (e.g. from `solana-keygen new`).
// Fund the wallet with devnet USDC: https://faucet.payai.network
const bytes = new Uint8Array(JSON.parse(readFileSync("./wallet.json", "utf8")));
const signer = await createKeyPairSignerFromBytes(bytes);

const client = new x402Client();
registerExactSvmScheme(client, { signer });
const fetchWithPay = wrapFetchWithPayment(globalThis.fetch, client);

const res = await fetchWithPay(
  "https://usebourse.xyz/api/x402/v1/chat/completions",
  {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({
      model: "google/gemma-3-27b-it",
      messages: [{ role: "user", content: "Hello, agent." }],
    }),
  },
);

const json = await res.json();
console.log(json.choices[0].message.content);
console.log("tx:", res.headers.get("x-payment-response"));

The TypeScript example uses the official @x402/fetch wrapper, which transparently handles the 402-then-retry dance. Same code works against any x402-compatible service.

// PARAMETERS

NETWORKSolana mainnet (live 2026-05-06)
ASSETCircle USDC · EPjFWdd5…wyTDt1v (mainnet)
FACILITATORhttps://facilitator.payai.network
PRICEPer call, sized by route — typical ~0.01 USDC

// WHERE_THE_MONEY_GOES

Unique to Bourse: the per-call USDC destination is dynamic per model.

  • If the model is tokenized on-chain, USDC lands in that model's revenue vault and feeds buyback-and-burn on the model's token. See /docs/creators for the full vault + buyback flow.
  • If the model is not yet tokenized, USDC lands in the protocol treasury and is held until the model lists. The demo on this page uses a non-tokenized example for reliability — the routing primitives are identical either way.
  • Either way: every paid call mechanically connects to the on-chain economy of the model that served it. No accounting layer. The wire is the ledger.