visionary
Docs / developer api / v1

build on visionary.

A free, open JSON API with everything visionary knows, and everything a wallet can do: start a coin, take a spot, buy and sell, set take home. Write calls hand back an unsigned transaction for your own wallet to sign, so visionary never sees a key. No API key, no sign up. Every read below is live, so press Send and you get real data.

Base
/api/v1
JSON over HTTPS
Methods
GET, POST
read and build
Key
none
CORS open
Times
unix ms
header x-visionary-api: 1
01 / api

basics.

Base URLhttps://usevisionary.fun/api/v1
Read and writeGET endpoints read. POST endpoints start coins, take spots, trade and set take home: each returns an unsigned transaction (or a message) for your wallet to sign, then you send it yourself or through /send.
KeysYour keys stay with you. visionary only ever sees signed transactions and public addresses.
OpenNo key. CORS is open, so you can call it from a browser, a bot or a server.
Version headerEvery v1 response carries x-visionary-api: 1.
UnitsSOL as plain numbers, times as unix milliseconds, raw token amounts as strings (coin tokens have 6 decimals; pay coins use payCoin.decimals), addresses as base58.
StableFields under v1 won't be renamed or removed. New fields may be added.
02 / api

endpoints, live.

Ids, mints and wallets are prefilled from the live API, so every Send works as is.

list coins

cached 5s
/api/v1/coins

Every coin, newest first. Filter by status to watch circles filling or coins going live. Drafts that never paid the start fee aren't listed.

Returns{ coins: Coin[], count, updatedAt }

GET/api/v1/coins
curl -s "https://usevisionary.fun/api/v1/coins"

get a coin

cached 3s
/api/v1/coins/{id}

One coin with every detail list: the circle (every wallet, what it paid, accepted, refunded, tokens, delivery tx, linked), each payday with the milestone that set it off and its claim, swap and transfer transactions, every take home send, every burn, every payment and the top 50 holders.

ReturnsCoin plus buyers, linkedPairs, paydays, takeHome, burns, joins, holderList

GET/api/v1/coins/coin%20id
curl -s "https://usevisionary.fun/api/v1/coins/coin%20id"

look up a mint

cached 3s
/api/v1/coins/mint/{mint}

Is this token a visionary coin? Returns the full coin with isVisionary: true, or a 404 with isVisionary: false. Made for terminals and bots that see a token address first.

Returns{ isVisionary: true, ...Coin with detail lists } or 404 { error, isVisionary: false }

GET/api/v1/coins/mint/token%20mint
curl -s "https://usevisionary.fun/api/v1/coins/mint/token%20mint"

look up a wallet

cached 10s
/api/v1/wallets/{address}

Every coin a wallet started, joined or holds: what it put in, what was accepted and refunded, its tokens, whether it held at the last payday, its hold streak and its starter lock, next to each coin's totals. Unknown wallets come back with empty lists, not a 404.

Returns{ wallet, totals: { coinsStarted, coinsJoined, solIn, solAccepted, solRefunded }, coins: [...], updatedAt }

GET/api/v1/wallets/wallet%20address
curl -s "https://usevisionary.fun/api/v1/wallets/wallet%20address"

leaderboard

cached 30s
/api/v1/leaderboard

Three lists of up to 20 rows: live coins ranked by fees returned (paid to holders plus bought back and burned), the biggest circles, and the starters with the most coins live.

GET/api/v1/leaderboard
curl -s "https://usevisionary.fun/api/v1/leaderboard"

stats

cached 15s
/api/v1/stats

Totals across visionary: coins by status, SOL that went into live coins' pots, wallets that bought in at go live, and creator fees paid to holders.

GET/api/v1/stats
curl -s "https://usevisionary.fun/api/v1/stats"

rules

cached 5m
/api/v1/rules

The constants every coin runs on (spots, spot price, payday milestone limits, fees, payout thresholds, pay coins, curve) and the Meteora program and visionary config addresses. Read from the same file the server enforces.

ReturnsSee the rules object below.

GET/api/v1/rules
curl -s "https://usevisionary.fun/api/v1/rules"

take home, read only

cached never
/api/home

Where a wallet's Zcash payouts go and what is waiting for it on every Zcash coin. Same origin, not versioned and not cached. To set the address from code, use the take home endpoints under launch and trade.

Returns{ wallet, to (Zcash address or null), since, coins: [{ id, ticker, waitingSol, carriedSol, sent: [{ at, sol, zecOut, tx, to, status }] }] }

GET/api/home
curl -s "https://usevisionary.fun/api/home"
03 / api

launch and trade.

Everything the site does with a wallet, over HTTP. Build, sign locally, send. Same rules and limits as the start page.

EndpointBodyReturns
POST /api/v1/coinsstarter, name, ticker, description?, image (data URL or https URL), start (instant | circle), payCoin (zec | xmr), feeMode?, mcapGoalUsd?, mcapStep?, openingBuySol? (instant, 0 to 0.5), spotPriceSol (circle), takeSpot? (circle), starterLock?, scheduledFor? (circle, unix ms), links? { website, twitter, telegram, tweet }, priorityMicroLamports?201 { id, pot, amountSol, breakdown { startFeeSol, buySol, deliverySol }, transaction, lastValidBlockHeight }. The starter signs transaction (it pays the pot).
POST /api/v1/coins/{id}/startsignedTransaction (we send it) or signature (you sent it){ signature, coin }. Instant coins come back live with their mint; circles come back open (or scheduled).
POST /api/v1/coins/{id}/spotwallet, priorityMicroLamports?{ amountSol, breakdown { spotSol, deliverySol }, transaction }: one spot in an open circle, one per wallet.
POST /api/v1/coins/{id}/spot/confirmsignedTransaction or signature{ signature, seated, rejected, departing, status, mint }. rejected says why (linked, late, full); refused payments are refunded.
POST /api/v1/tradewallet, coin (id) or mint, side (buy | sell), amount (buy: SOL; sell: tokens or a percent like "100%"), slippageBps? (default 300), priorityMicroLamports?{ venue (curve | damm_v2), amountIn, expectedOut, minimumOut, outUnit, transaction }: a swap on the coin's Meteora curve, or its DAMM v2 pool after graduation.
POST /api/v1/sendsignedTransaction (base64 or base58, legacy or v0){ signature, landed: true } once it's confirmed (up to about 45 s), or 422 with the chain's error.
GET /api/v1/wallets/{address}/take-home?to=to: a Zcash address (leave it out to switch take home off){ to, since, sign { to, time, message, validForSeconds } }: the exact message the wallet signs.
POST /api/v1/wallets/{address}/take-hometo, time, signature (base58 ed25519 over sign.message){ wallet, to }. Only the wallet's own signature changes where its Zcash payouts go. Nothing moves funds.

Flow: call a build endpoint, sign the returned transaction (base64, legacy) with the wallet it names as fee payer, then either pass signedTransaction to the confirm step (we send it and wait) or send it through your own RPC and pass its signature. A transaction is good for about a minute (lastValidBlockHeight); build a fresh one if it expires. Trades go straight to Meteora, so a coin trades the same here as on Jupiter or any terminal.

04 / api

launch and trade, code.

Node with @solana/web3.js. The same calls work from Python, Rust or a browser wallet.

launch a coin
// Launch an instant coin from a script. You sign locally; visionary never sees your key.
import { Keypair, Transaction } from "@solana/web3.js";
const wallet = Keypair.fromSecretKey(/* your key */);
const api = (path, body) => fetch("https://usevisionary.fun" + path, {
  method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify(body),
}).then((r) => r.json());
const sign = (b64) => { const tx = Transaction.from(Buffer.from(b64, "base64")); tx.partialSign(wallet); return tx.serialize().toString("base64"); };

const draft = await api("/api/v1/coins", {
  starter: wallet.publicKey.toBase58(),
  name: "hush", ticker: "HUSH", description: "a quiet coin",
  image: "https://example.com/hush.png",   // or a data URL
  start: "instant", payCoin: "zec",
  openingBuySol: 0.1, mcapGoalUsd: 25000, mcapStep: 2,
});
if (draft.error) throw new Error(draft.error);
const { coin } = await api(`/api/v1/coins/${draft.id}/start`, { signedTransaction: sign(draft.transaction) });
console.log("live:", coin.url, "mint", coin.mint);
buy and sell
// Buy 0.5 SOL of a coin, then sell all of it (same api and sign helpers as above)
const buy = await api("/api/v1/trade", { wallet: wallet.publicKey.toBase58(), coin: "{id}", side: "buy", amount: 0.5, slippageBps: 300 });
console.log(buy.venue, "expect", buy.expectedOut, "tokens, at least", buy.minimumOut);
console.log(await api("/api/v1/send", { signedTransaction: sign(buy.transaction) }));

const sell = await api("/api/v1/trade", { wallet: wallet.publicKey.toBase58(), coin: "{id}", side: "sell", amount: "100%" });
console.log(await api("/api/v1/send", { signedTransaction: sign(sell.transaction) }));
take a spot in a circle
// Take a spot in an open circle
const spot = await api(`/api/v1/coins/${id}/spot`, { wallet: wallet.publicKey.toBase58() });
const r = await api(`/api/v1/coins/${id}/spot/confirm`, { signedTransaction: sign(spot.transaction) });
console.log(r.seated ? "in" : `refused: ${r.rejected}`, r.departing ? "(that was the last spot, going live)" : "");
take home
// Point a wallet's Zcash payouts at a Zcash address (one signed message, no funds move)
import nacl from "tweetnacl"; import bs58 from "bs58";
const me = wallet.publicKey.toBase58();
const { sign: s } = await fetch(`https://usevisionary.fun/api/v1/wallets/${me}/take-home?to=${zcashAddress}`).then((r) => r.json());
const signature = bs58.encode(nacl.sign.detached(new TextEncoder().encode(s.message), wallet.secretKey));
console.log(await api(`/api/v1/wallets/${me}/take-home`, { to: s.to, time: s.time, signature }));
05 / api

the coin object.

What /coins returns per coin. Single coin and mint lookups add the detail lists below.

FieldTypeMeaning
id, urlstringCoin id and its coin page.
name, ticker, descriptionstringAs set by the starter. Ticker is uppercase, 2 to 10 characters.
imagestringAbsolute URL to the coin image.
linksobjectwebsite, twitter, telegram and tweet, each a URL or null.
statusstringSee the lifecycle below.
starteraddressWallet that started the coin.
potaddressThe coin's pot address. Circle payments go here, it creates the pool on chain, claims the fee, pays holders and keeps the burn vault.
mint, pooladdress | nullNull until the coin goes live. The mint is never revealed early.
createdAt, opensAt, closesAt, launchedAt, scheduledForunix ms | nullDrafted, circle opened, circle deadline, went live, and the requested start of a scheduled coin.
startstringcircle or instant.
spotPriceSolnumber | nullSOL per spot. Null on instant coins.
spotsTaken, spotsTotalnumber | nullSpots taken out of 20. Null on instant coins.
potSolnumberSOL in the pot. Live while the circle fills, then the amount that bought.
walletsnumberWallets in the pot (the circle, or the starter on an instant coin).
entryPriceSolnumber | nullSOL per token everyone in the pot paid.
tokensBoughtstring | nullRaw token amount the pot bought (6 decimals).
launchTxsignature | nullThe block zero transaction that created the pool and bought.
failReason, lookalikeOfstring | nullWhy a coin refunded; the ticker of an earlier coin this one looks like.
feeModestringholders, burn or split.
payCoinobject{ key, symbol, name, mint, decimals, takeHome }: zec or xmr, its SPL mint on Solana, and whether take home is possible.
paidCoinstringRaw pay coin units that reached holders, all paydays (use payCoin.decimals).
feesPaidSolnumberCreator fee SOL routed to holders across all paydays (swapped, sent home or carried).
carriedSolnumberSOL waiting in the pot for holders whose shares were too small to send yet.
takeHomeWaitingSol, takeHomeSentSolnumberTake home SOL still collecting, and SOL already sent through NEAR Intents.
holdersnumber | nullWallets holding the coin at the last payday.
burnVaultSol, burnSavedTargetSolnumberSOL saved toward the next burn, and the burn target.
burnedSol, burnedTokensnumber, stringSOL spent on buybacks, and raw tokens burned.
goalsobjectThe coin's market cap milestones and how close it is to the next one. See payday milestones below.
starterLockobject | null{ until: "bond", totalTokens, releasedTokens, releaseSig } when the starter locked their tokens until the coin bonds. releasedTokens equals totalTokens once it bonded.
marketobject | nullLive Meteora curve (or its DAMM v2 pool after graduation): priceSol, marketCapSol, raisedSol, goalSol, progress (0 to 1), graduated.
06 / api

payday milestones.

Every coin carries goals: its market cap milestones. A payday runs each time the market cap reaches the next milestone, and at no other time.

FieldTypeMeaning
firstMcapUsd, mcapStepnumberFirst market cap milestone in USD, and the step: each milestone is the last one times this (1.5, 2 or 3).
nextMcapUsdnumberThe next milestone still to reach. A payday runs when marketCapUsd reaches it. Each milestone pays once.
marketCapUsdnumber | nullMarket cap in USD at the last check. Null before the first check or when the price couldn't be read.
feesCollectedSolnumber | nullFee waiting for the next milestone at the last check (unclaimed creator fee plus anything held over). Paid out when the milestone is reached. Null before the first check.
checkedAtunix ms | nullWhen the market cap was last read from the chain. Live coins are checked once per 60 seconds.
milestonesReached[]array{ at, usd, marketCapUsd }: each milestone reached, when, and the market cap at the time.

The starter picks the first milestone and the step when starting the coin, within the limits in paydayGoals on /rules, and both are locked at start. Coins started before milestones existed report the defaults. If the market cap never reaches nextMcapUsd there is no payday and the fee keeps waiting on Meteora, so read marketCapUsd against nextMcapUsd as progress, not as a time.

07 / api

detail lists.

Only on /coins/{id} and /coins/mint/{mint}.

buyers[]wallet, committedSol, acceptedSol, refundSol, tokens, linked, group, deliveryTx, starter, streakSince, streakMultiplier. The circle (or the starter's opening buy).
paydays[]at, reason (mcap; older paydays may say fees or be null), marketCapUsd (market cap when it ran), milestoneUsd (the milestone it reached, on mcap paydays), sol, swappedSol, coin (raw units bought), coinSent (raw units delivered), recipients, takeHomeSol, carriedSol, claimTx, swapTx, payTxs[].
takeHome[]at, wallet, sol, zecOut (raw ZEC quoted), tx, depositAddress (the NEAR Intents deposit address), status (from 1Click).
burns[]at, sol, tokens, buyTx, burnTx.
joins[]wallet, sol, at, tx. Every payment to the pot, good for a live feed while the circle fills.
holderList[]Top 50 holders: wallet, tokens (held weight), since (streak start), daysHeld (full days held), multiplier.
linkedPairsPairs of wallets the trace found funding each other.
08 / api

status lifecycle.

scheduled then open then settling then launched, or refunded. A circle goes live the moment all 20 spots are taken; read spotsTaken, spotsTotal and spotPriceSol on each coin.

scheduled
open
settling
launched
refunding then refunded, from open or settling, when a circle isn't full within 24 hours or the pool can't be created
awaiting_feeDrafted, start fee not paid yet. Never listed; only visible by id.
scheduledStart fee paid, the circle opens at opensAt. Ticker already locked.
openThe circle is filling. Goes live the moment all 20 spots are taken; instant coins pass through for a few seconds.
settlingFull. The coin is going live and tokens are being sent.
launchedPool created, block zero bought, tokens sent (or sending). mint and pool are set.
refunding, refundedNot full within 24 hours, or the pool couldn't be created: every payment is sent back.
cancelledDraft expired unpaid. Never listed.
09 / api

the rules object.

What /rules returns. The same numbers as the rules page.

spots, spotPriceSol { min, max }, circleMaxHoursThe circle.
startStyles, feeModescircle or instant; holders, burn or split.
startFeeSol, deliverySol, walletCapSol, potCapSol, minCommitSolStart fee, the one off delivery charge per spot, opening buy cap and pot limits.
paydayGoals{ rule, firstMcapUsd { min, max, default }, mcapSteps[], mcapStepDefault, checkSeconds }. The limits a starter picks milestones within.
maxHoldersPerPayday, streak { days, maxMultiplier }Holders paid per payday and weights.
payCoins[]{ key, symbol, name, mint, decimals, home }. home is true where take home works (Zcash).
payout{ openAccountMinSol, sendMinSol, swapMinSol, accountRentSol, takeHomeMinSol, takeHomeVia }.
burnVaultSol, lockHours, starterLockUntilBurn target, ticker and name lock, starter lock ("bond": released when the coin bonds).
feesPercent { meteora, visionary, coin, total }Fee per trade, the same before and after graduation.
curve { ..., migratesTo, lockedLpPercent }, programs { meteoraDbc, psstConfig }Meteora curve shape, the graduated pool's locked LP split and the on chain addresses.
10 / api

recipes.

watch circles fill
// Alert on every circle filling (poll every 10s)
const seen = new Map();
setInterval(async () => {
  const { coins } = await fetch("https://usevisionary.fun/api/v1/coins?status=open").then((r) => r.json());
  for (const c of coins) {
    if (seen.get(c.id) === c.spotsTaken) continue;
    seen.set(c.id, c.spotsTaken);
    console.log(`$${c.ticker}: ${c.spotsTaken}/${c.spotsTotal} spots at ${c.spotPriceSol} SOL, pays ${c.payCoin.symbol} ${c.url}`);
  }
}, 10_000);
label visionary coins in a terminal or bot
// Label visionary coins in a terminal or bot
async function psstInfo(mint) {
  const r = await fetch(`https://usevisionary.fun/api/v1/coins/mint/${mint}`);
  if (r.status === 404) return null; // not a visionary coin
  const c = await r.json();
  return {
    devIsPot: c.pot,              // the "dev" wallet is the pot, not a person
    circle: c.buyers.length,      // the wallets terminals call bundle or insiders
    linked: c.buyers.filter((w) => w.linked).length,
    entryPriceSol: c.entryPriceSol,
    paysIn: c.payCoin.symbol,     // ZEC or XMR
    holders: c.holders,
  };
}

Why this matters: on a visionary coin the creator wallet is the pot, and its block zero buy is the whole circle buying together. The guide explains how that reads on terminals.

read each payday
// Each payday of a coin, the milestone that set it off, and its transactions
const c = await fetch("https://usevisionary.fun/api/v1/coins/{id}").then((r) => r.json());
const d = 10 ** c.payCoin.decimals;
for (const p of c.paydays) {
  const why = p.reason === "mcap" ? `market cap hit $${p.milestoneUsd}` : "payday"; // older rows: "fees" or null
  console.log(new Date(p.at).toISOString(), why, p.sol, "SOL claimed,",
    Number(p.coinSent ?? 0) / d, c.payCoin.symbol, "to", p.recipients, "holders,",
    p.carriedSol, "SOL carried, claim", p.claimTx, "swap", p.swapTx, "transfers", p.payTxs);
}
how close is the next payday
// How close a coin is to its next payday: market cap against the next milestone
const { ticker, goals: g } = await fetch("https://usevisionary.fun/api/v1/coins/{id}").then((r) => r.json());
if (g.marketCapUsd == null) console.log(`$${ticker}: market cap not checked yet`);
else {
  const pct = Math.min(100, Math.round((g.marketCapUsd / g.nextMcapUsd) * 100));
  console.log(`$${ticker}: $${g.marketCapUsd} of $${g.nextMcapUsd} (${pct}%), then x${g.mcapStep}`);
}
11 / api

errors and limits.

ErrorsCome back as { "error": "..." } with status 400 (bad input), 404 (not found), 409 (wrong state, like a full circle), 422 (a transaction failed on chain), 429 (slow down) or 500.
CachingResponses are cached at the edge for a few seconds (shown on each endpoint), so polling faster returns the same data. Every 5 to 10 seconds is plenty.
LimitsPOST endpoints: 30 a minute per IP, then 429 with retryAfterSeconds. GET endpoints are cached at the edge; every 5 to 10 seconds is plenty.
Source of truthThe chain. Every amount here links to a transaction you can open on any explorer.