WiSPDocs Open the app

Agents and developers

API reference

Every endpoint of wisp-x402, its price, what it returns and its errors, with a curl call and a minimal paying client.

On this page

For developers building agents or tools. x402 is a standard for paying per request over HTTP: the server answers 402 Payment Required with a price, and the client pays and asks again.

Base URL: https://wisp-x402.fly.dev. All endpoints are GET. Network: Solana mainnet (solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp).

Endpoints

PathPaidPrice
/x402/rug-check/{mint}Yes$0.005: 5000 USDC units, or $WiSP at the discount below
/burnsNo
/healthNo
/.well-known/x402.jsonNo

USDC mint: EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v. $WiSP mint: USEu5qroduzuvrSZfvs3xM1MwyU83joapQF5LMyWiSP. The $WiSP amount is quoted fresh in each 402 from the market price: 25% off the dollar price, plus a 2% margin for price movement, so about 23.5% below the USDC price; at 13:45 UTC on 24 October 2026 a rug check cost 41.434464 $WiSP.

Paying

A request without payment returns 402 with an empty JSON body and a payment-required header: base64 JSON listing what the service accepts.

curl -i https://wisp-x402.fly.dev/x402/rug-check/USEu5qroduzuvrSZfvs3xM1MwyU83joapQF5LMyWiSP

Decoded, the header looks like this (addresses shortened):

{
  "x402Version": 2,
  "error": "Payment required",
  "resource": { "url": "https://wisp-x402.fly.dev/x402/rug-check/USEu5q…WiSP", "mimeType": "application/json" },
  "accepts": [
    { "scheme": "exact", "network": "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp",
      "amount": "5000", "asset": "EPjFWdd5…Dt1v", "payTo": "4r2e4D2x…bra6",
      "maxTimeoutSeconds": 300, "extra": { "feePayer": "9vxA1Q5f…dG5k" } },
    { "scheme": "exact", "network": "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp",
      "amount": "41434464", "asset": "USEu5q…WiSP", "payTo": "4r2e4D2x…bra6",
      "maxTimeoutSeconds": 300, "extra": { "feePayer": "9vxA1Q5f…dG5k" } }
  ]
}

Your client signs a transfer for one of the offers and repeats the request with the payment header. The service checks it, works out the answer, and settles the payment on Solana only when the answer is a success: it then returns 200. A malformed address is refused with 400 before any 402, so there is nothing to sign. An address that is not a token mint gets 404 after your payment is checked, and that payment is not settled, so nothing is charged.

A payment pays for one answer. Sending the same signed payment again is refused (payment_already_used) and not charged: a payment's transaction is public once it lands, so it cannot work as a key. If the network is slow to confirm, the server checks the chain before answering, so a payment that landed still gets its answer in the same request.

A minimal client (JavaScript)

Uses the x402 reference packages, @x402/core and @x402/svm 2.28.0, and @solana/kit:

import { x402Client, x402HTTPClient } from '@x402/core/client';
import { registerExactSvmScheme } from '@x402/svm/exact/client';
import { createKeyPairSignerFromBytes } from '@solana/kit';

const NETWORK = 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp';
const WISP = 'USEu5qroduzuvrSZfvs3xM1MwyU83joapQF5LMyWiSP';
const signer = await createKeyPairSignerFromBytes(secretKeyBytes); // your agent's 64-byte Solana secret key
const YOUR_RPC_URL = 'https://…';                                    // any Solana mainnet RPC
const mint = 'DezXAZ8z7PnrnRJjz3wXBoRgixCa6xjnB7YaB1pPB263';         // the token to check

const core = new x402Client();
registerExactSvmScheme(core, { signer, networks: [NETWORK], rpcUrl: YOUR_RPC_URL,
  policies: [(version, offers) => offers.filter(o => o.asset === WISP)] });   // pay in $WiSP
// A standard client pays only its default stablecoins until told otherwise:
core.setSpendControls({ allowedAssets: [{ network: 'solana:*', asset: WISP, maxAmountPerPayment: '1000000000' }] });
const http = new x402HTTPClient(core);

const url = 'https://wisp-x402.fly.dev/x402/rug-check/' + mint;
const first = await fetch(url);                          // 402
const required = http.getPaymentRequiredResponse(name => first.headers.get(name), await first.json());
const payload = await http.createPaymentPayload(required);
const paid = await fetch(url, { headers: http.encodePaymentSignatureHeader(payload) });
console.log(paid.status, await paid.json());

To pay in USDC, filter for the USDC mint instead and drop setSpendControls.

Rug check

GET /x402/rug-check/{mint} reads the mint account and its largest holders.

FieldTypeMeaning
mintstringThe address you asked about
readAtstringISO time of the read
okbooleantrue
programstringtoken or token-2022
decimalsnumber
supplystringRaw supply
flagsarray{ key, active } for mint, freeze, permanentDelegate, transferFee, transferFeeChangeable, transferHook, pausable, nonTransferable, defaultFrozen, metadataMutable
allowsarrayOne sentence per active flag, such as "Someone can freeze holders' tokens."
top10Percentnumber or nullShare held by the ten largest token accounts, not counting a pump.fun curve. null when it could not be read
pumpCurveobject or nullWhile the token is on a pump.fun bonding curve: { address, tokenAccount, percent }, the curve, the account holding its unsold supply and that share of the supply. null when the curve holds none (graduated, or never on pump.fun) or the holder list could not be read
summarystringThe sentences joined, or a line saying nobody has special powers

Example, for $WiSP on 24 October 2026. Here top10Percent is null because the RPC used for the example refused the largest-holders read:

{
  "mint": "USEu5qroduzuvrSZfvs3xM1MwyU83joapQF5LMyWiSP",
  "readAt": "2026-10-24T13:47:27.880Z",
  "ok": true,
  "program": "token-2022",
  "decimals": 6,
  "supply": "931910509125656",
  "flags": [ { "key": "mint", "active": false }, { "key": "freeze", "active": false }, … ],
  "allows": [],
  "top10Percent": null,
  "pumpCurve": null,
  "summary": "Its rules give nobody special powers over holders' tokens: no minting, freezing, fees, hooks or forced transfers."
}

The check reports what the token's rules allow. It never calls a token safe.

Free endpoints

  • /burns: { mint, burnedRaw, burned, burns, last }, where last lists up to 20 recent burns with at, amount and signature.
  • /health: { ok, payTo, feePayer, wisp }. wisp is true while $WiSP is accepted.
  • /.well-known/x402.json: the service's name, description and resources.

Errors

StatusBody or reasonCause
400{"error":"Invalid mint"}The path is not a base58 address of 32 bytes. Answered before any 402, nothing to pay
404{"error":"Not a token mint"}The address is not a token mint. Your payment is not settled
404Unknown path
402payer_daily_limitMore than 300 paid calls from one payer in 24 hours
402service_daily_limitMore than 3,000 paid calls in total in 24 hours
402service_pausedFive failed settlements in ten minutes pause payments for 15 minutes
402payment_already_usedThe same payment was sent for a different path
402payment_in_progressThe same payment is still settling
402transaction_too_large, lookup_tables_not_allowed, fee_payer_mismatch, invalid_transactionThe payment transaction is malformed

Last checked against the app: 24 October 2026, build bf09a3f