Quickstart
Every toll lives at one URL. Call it without paying and you get 402 Payment Required with the price. Pay it and retry, and the request goes through.
curl -i https://usecallo.app/api/x402/sol-price
Anything after the toll id is passed along: /api/x402/<toll>/v1/search?q=solana reaches the builder’s upstream as /v1/search?q=solana. All HTTP methods work.
x402 on Solana
Callo speaks x402 version 1 with the exact scheme on the solana network. The asset is always USDC (EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v, 6 decimals).
The 402 response
{
"x402Version": 1,
"error": "X-PAYMENT header is required",
"accepts": [{
"scheme": "exact",
"network": "solana",
"maxAmountRequired": "1000", // USDC base units: $0.001
"resource": "https://usecallo.app/api/x402/sol-price",
"description": "SOL Price Oracle: ...",
"mimeType": "application/json",
"payTo": "<the toll's vault>",
"maxTimeoutSeconds": 60,
"asset": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
"extra": { "name": "USDC", "decimals": 6, "feePayer": "<optional>" }
}]
}
| Header | Direction | Contents |
|---|---|---|
X-PAYMENT | agent → booth | base64 JSON: { x402Version, scheme, network, payload: { transaction } } |
X-PAYMENT-RESPONSE | booth → agent | base64 JSON receipt: { success, transaction, network, payer } |
PAYMENT-REQUIRED | booth → agent | The 402 body again, base64, for clients that read headers only. |
Building the payment
The payload is a signed Solana transaction containing a USDC TransferChecked of at least maxAmountRequired to the vault’s USDC account. It may also create that account (idempotent) and set a compute budget. Nothing else is accepted.
If the 402 names an extra.feePayer, the agent can set it as the fee payer and leave its signature empty: the booth co-signs and pays the network fee. Otherwise the agent pays its own fee.
import { getAssociatedTokenAddressSync, createAssociatedTokenAccountIdempotentInstruction, createTransferCheckedInstruction } from '@solana/spl-token' import { PublicKey, TransactionMessage, VersionedTransaction } from '@solana/web3.js' export async function pay(req, wallet, connection) { const mint = new PublicKey(req.asset), to = new PublicKey(req.payTo) const src = getAssociatedTokenAddressSync(mint, wallet.publicKey) const dst = getAssociatedTokenAddressSync(mint, to, true) const { blockhash } = await connection.getLatestBlockhash() const tx = new VersionedTransaction(new TransactionMessage({ payerKey: wallet.publicKey, recentBlockhash: blockhash, instructions: [ createAssociatedTokenAccountIdempotentInstruction(wallet.publicKey, dst, to, mint), createTransferCheckedInstruction(src, mint, dst, wallet.publicKey, BigInt(req.maxAmountRequired), 6), ], }).compileToV0Message()) tx.sign([wallet]) const transaction = Buffer.from(tx.serialize()).toString('base64') return Buffer.from(JSON.stringify({ x402Version: 1, scheme: 'exact', network: 'solana', payload: { transaction }, })).toString('base64') }
The booth verifies the transfer, lands it on Solana and only then serves the request. Each transaction pays for exactly one call.
Launching a toll
On the launchpad you set a name, ticker, toll per call, an optional upstream URL and a stock pairing. Deploying does three things:
- Derives a vault wallet for the toll. It is the x402
payTofor every call. - Deploys a pump.fun coin in a transaction you sign, with the vault as the coin’s creator, so its creator fees land in the same vault.
- Opens the gate at
/api/x402/<mint>and lists the toll on the board.
Stock pairing
Pick up to three tokenized stocks from the xStocks board (NVDAx, TSLAx, AAPLx, MSFTx, GOOGLx, METAx, AMZNx, SPYx, QQQx, COINx, HOODx, CRCLx, MSTRx, GLDx) and the share of earnings to pair.
Agents pay the builder's price plus a 25% Callo fee on top; the builder keeps 100% of the price they set. Every few minutes the vault is split: Callo's fee goes to the Callo treasury, then the paired share of its USDC and SOL is swapped into those stocks through Jupiter, weighted as you chose, and held in the vault. The remainder is sent to the wallet that launched the toll.
| Example | Value |
|---|---|
| Builder price | $0.002 per call |
| Agents pay | $0.0025 per call (builder price + 25% Callo fee) |
| Calls in a day | 50,000 → $125 paid by agents: $100 to the builder side, $25 Callo fee |
| Pairing | 40%: 50% NVDAx, 50% TSLAx |
| Bought and held | $20 NVDAx + $20 TSLAx |
| Paid to the builder | $60 USDC |
Simulation vs live
This deployment is live: payments settle in USDC on Solana mainnet, launches deploy real pump.fun coins and the vault split runs on a schedule.
Live mode needs LIVE=1, NEXT_PUBLIC_LIVE=1, a Solana RPC, Redis, a treasury key for gas, a vault seed and an image-pinning key. See .env.example.