Docs / Developer API
Endpoints
Every path is under https://api.sapling.cash/v1. Samples are shortened: <mint>, <wallet> and <signature> stand for real values, and … for figures left out. Amounts are base units as strings (amounts).
Reads
No key needed. Cached for a few seconds at the edge, so polling is fine. Lists answer { data, next }: pass next as cursor for the next page; it is null at the end.
GET/v1/params
Everything a builder needs, so nothing is typed in: program ids, the ZEC mint, the treasury, the launch fee, the creator fee and its split (read from the vault program on chain), pump.fun's fee recipients and reserves, the lookup table, priority and slippage caps, name, ticker and image rules.
{
"network": "mainnet-beta",
"programs": {
"pump": "<address>",
"pumpSwap": "<address>",
"saplingVault": "<address>",
"jupiter": "<address>"
},
"zecMint": "<address>",
"decimals": {
"zec": 8,
"coin": 6,
"sol": 9
},
"treasury": "<address>",
"lookupTable": "<address>",
"planting": {
"launchFeeLamports": "10000000",
"creatorFeeBps": 200,
"open": true,
"name": {
"maxBytes": 32
},
"ticker": {
"pattern": "^[A-Z0-9]{2,10}$"
},
"uri": {
"maxLength": 100,
"schemes": [
"https",
"ipfs"
]
},
"image": {
"types": [
"image/png",
"image/jpeg",
"image/webp",
"image/gif"
],
"maxBytes": 4194304
},
"maxPriorityLamports": "50000000"
},
"split": {
"lp": 2500,
"rootstock": 2500,
"treasury": 1000,
"deployer": 4000
},
"pump": {
"feeRecipient": "<address>",
"buybackFeeRecipient": "<address>",
"protocolFeeBps": 95,
"initialVirtualTokenReserves": "…",
"initialVirtualQuoteReserves": "…",
"initialRealTokenReserves": "…",
"tokenTotalSupply": "1000000000000000"
},
"trading": {
"slippageBps": {
"curveDefault": 100,
"poolDefault": 200,
"max": 2000
},
"maxPriorityLamports": "10000000"
},
"api": {
"version": "v1",
"limits": {
"reads": {
"anonymous": "60/min",
"standard": "600/min",
"raised": "3000/min"
}
}
}
}GET/v1/coins
Coin summaries. Hidden coins are never listed.
- sort
- trending (the default), new, mcap or volume
- stage
- seed, sapling or orchard
- pays
- holders: only coins whose deployer share pays holder rewards
- limit
- 1 to 100, 50 by default
- cursor
- from the last page's next
{
"data": [
{
"mint": "<mint>",
"name": "Night Owl",
"symbol": "OWL",
"image": {
"ipfs": "ipfs://<cid>",
"thumb": "https://sapling.cash/media/coins/<id>/thumb.webp",
"tile": "https://sapling.cash/media/coins/<id>/tile.webp",
"large": "https://sapling.cash/media/coins/<id>/large.webp"
},
"stage": "sapling",
"curveProgress": "0.4127",
"priceZecE9": "31200000000",
"marketCapZec": "31200000000",
"marketCapUsd": 12480,
"holderCount": 214,
"buyCount": 1290,
"sellCount": 611,
"volume24hZec": "1834500000",
"launchedAt": "2026-10-01T14:03:11.000Z",
"lastTradeAt": "2026-10-01T18:40:02.000Z",
"holderRewards": true,
"official": false
}
],
"next": "<cursor>"
}GET/v1/coins/search
Coins whose ticker, name or address matches: exact first, then by the start, inside, then close spellings, as the site's search.
- q
- the text, 1 to 64 characters; a full mint address finds that coin
{
"data": [
{
"mint": "<mint>",
"name": "Night Owl",
"symbol": "OWL",
"image": {
"ipfs": "ipfs://<cid>",
"thumb": "https://sapling.cash/media/coins/<id>/thumb.webp",
"tile": "https://sapling.cash/media/coins/<id>/tile.webp",
"large": "https://sapling.cash/media/coins/<id>/large.webp"
},
"stage": "sapling",
"curveProgress": "0.4127",
"priceZecE9": "31200000000",
"marketCapZec": "31200000000",
"marketCapUsd": 12480,
"holderCount": 214,
"buyCount": 1290,
"sellCount": 611,
"volume24hZec": "1834500000",
"launchedAt": "2026-10-01T14:03:11.000Z",
"lastTradeAt": "2026-10-01T18:40:02.000Z",
"holderRewards": true,
"official": false
}
],
"next": null
}GET/v1/coins/{mint}
One coin: its metadata and links, who planted it, where the deployer's share goes, reserves, price, supply, the stage and graduation, and its fee totals. payee.mode is 'wallet', 'holders' (holder rewards) or 'zcash-foundation' (the share is donated to the Zcash Foundation; address is the donation pot). payee.isPlanter is false when the share goes to a wallet other than the one that planted it. A shielded launch never names its deployer: launcher and launchSignature are null, and so is payee.address when the payee is the deployer.
{
"mint": "<mint>",
"name": "Night Owl",
"symbol": "OWL",
"image": {
"ipfs": "ipfs://<cid>",
"thumb": "https://sapling.cash/media/coins/<id>/thumb.webp",
"tile": "https://sapling.cash/media/coins/<id>/tile.webp",
"large": "https://sapling.cash/media/coins/<id>/large.webp"
},
"stage": "sapling",
"curveProgress": "0.4127",
"priceZecE9": "31200000000",
"marketCapZec": "31200000000",
"marketCapUsd": 12480,
"holderCount": 214,
"buyCount": 1290,
"sellCount": 611,
"volume24hZec": "1834500000",
"launchedAt": "2026-10-01T14:03:11.000Z",
"lastTradeAt": "2026-10-01T18:40:02.000Z",
"holderRewards": true,
"official": false,
"uri": "ipfs://<cid>",
"description": "Hoots at dawn.",
"links": {
"twitter": null,
"website": null,
"telegram": null
},
"creator": "<coin authority PDA>",
"launcher": "<wallet>",
"deployerShielded": false,
"launchSignature": "<signature>",
"bondingCurve": "<address>",
"supply": "1000000000000000",
"reserves": {
"curve": {
"virtualToken": "…",
"virtualQuote": "…",
"realToken": "…",
"realQuote": "…"
},
"pool": null
},
"graduation": {
"complete": false,
"completedAt": null,
"migrated": false,
"migratedAt": null,
"pool": null,
"raiseAtCompletionZec": "…",
"raisedSoFarZec": "…"
},
"payee": {
"mode": "holders",
"address": null,
"isPlanter": false,
"unclaimedZec": "1240000",
"paidZec": "0",
"holderRewardsPaidZec": "38110000"
},
"creatorFeesZec": "98000000",
"volumeTotalZec": "4900000000"
}GET/v1/coins/{mint}/candles
Open, high, low and close as priceZecE9 strings, with volume and trade count per bucket. t is the bucket's start, unix seconds.
- interval
- 1m, 5m, 1h or 1d
- from, to
- unix seconds
- limit
- 1 to 1000
{
"data": [
{
"t": 1759327200,
"o": "30900000000",
"h": "31400000000",
"l": "30800000000",
"c": "31200000000",
"volumeZec": "84000000",
"trades": 17
}
],
"next": null
}GET/v1/coins/{mint}/trades
The coin's trades, newest first: venue, side, amounts, the creator fee, price and signature. A shielded launch's deployer is never named: its trades stay with user and signature null.
- cursor
- from the last page's next
- limit
- 1 to 500
- user
- only this wallet's trades
{
"data": [
{
"signature": "<signature>",
"blockTime": "2026-10-01T18:40:02.000Z",
"venue": "curve",
"side": "buy",
"user": "<wallet>",
"zec": "25000000",
"tokens": "792310044210",
"creatorFeeZec": "500000",
"priceZecE9": "31200000000"
}
],
"next": "<cursor>"
}GET/v1/coins/{mint}/holders
The largest holders, with their share of the supply. tag marks the curve, the pool and the wallet that planted it. A shielded launch's deployer stays in the list, with no address.
- limit
- 1 to 200
{
"data": [
{
"owner": "<bonding curve>",
"balance": "612000000000000",
"pct": 61.2,
"tag": "curve"
},
{
"owner": "<wallet>",
"balance": "18200000000000",
"pct": 1.82,
"tag": null
}
],
"next": null
}GET/v1/coins/{mint}/fees
What the coin's creator fee has earned and where it went: LP, rootstock, the deployer's share, what was paid to the payee or to holders.
{
"mint": "<mint>",
"creatorFeesZec": "98000000",
"claimedZec": "96500000",
"toLpZec": "24125000",
"toRootstockZec": "24125000",
"toDeployerZec": "38600000",
"payeePaidZec": "0",
"holderRewardsPaidZec": "38110000"
}GET/v1/coins/{mint}/quote
What a trade would get now, on whichever venue the coin trades: amount out after fees, and the limit your slippage sets. No wallet needed.
- side
- buy or sell
- pay
- ZEC or SOL (buy)
- amount
- base units: ZEC or lamports to spend (buy), tokens to sell (sell)
- slippageBps
- 100 on the curve and 200 on the pool by default, at most 2000
{
"venue": "curve",
"side": "buy",
"amountIn": "25000000",
"amountOut": "792310044210",
"limit": "25250000",
"priceImpactBps": 41,
"slippageBps": 100
}GET/v1/trades
Recent trades on every coin, newest first; each names its mint. A shielded launch's deployer is never named: its trades stay with user and signature null.
- cursor
- from the last page's next
- limit
- 1 to 100
{
"data": [
{
"signature": "<signature>",
"blockTime": "2026-10-01T18:40:02.000Z",
"venue": "curve",
"side": "buy",
"user": "<wallet>",
"zec": "25000000",
"tokens": "792310044210",
"creatorFeeZec": "500000",
"priceZecE9": "31200000000",
"mint": "<mint>"
}
],
"next": "<cursor>"
}GET/v1/graduations
Coins that moved to their PumpSwap pool, most recent first.
- cursor
- from the last page's next
{
"data": [
{
"mint": "<mint>",
"name": "Night Owl",
"symbol": "OWL",
"image": {
"ipfs": "ipfs://<cid>",
"thumb": "https://sapling.cash/media/coins/<id>/thumb.webp",
"tile": "https://sapling.cash/media/coins/<id>/tile.webp",
"large": "https://sapling.cash/media/coins/<id>/large.webp"
},
"stage": "orchard",
"curveProgress": "1",
"priceZecE9": "31200000000",
"marketCapZec": "31200000000",
"marketCapUsd": 12480,
"holderCount": 214,
"buyCount": 1290,
"sellCount": 611,
"volume24hZec": "1834500000",
"launchedAt": "2026-10-01T14:03:11.000Z",
"lastTradeAt": "2026-10-01T18:40:02.000Z",
"holderRewards": true,
"official": false
}
],
"next": null
}GET/v1/stats
Sapling as a whole: coins planted, volume, $SAPLING burned, LP added, holder rewards and payee payouts, and the prices used.
{
"coinsPlanted": "<number>",
"volume24hZec": "<ZEC base units>",
"volume24hUsd": "<number>",
"saplingBurned": "<coin base units>",
"lpZecTotal": "<ZEC base units>",
"lpRuns": "<number>",
"holderRewardsPaidZec": "<ZEC base units>",
"payeePaidZec": "<ZEC base units>",
"zecUsd": "<number>",
"solUsd": "<number>",
"updatedAt": "<time>"
}GET/v1/stats/daily
One row a UTC day: the creator fees trades paid, the ZEC that went to the LP, the number of trades.
- days
- 7 to 365
{
"data": [
{
"day": "<YYYY-MM-DD>",
"creatorFeesZec": "<ZEC base units>",
"lpZec": "<ZEC base units>",
"trades": "<number>"
}
]
}GET/v1/rewards/runs
Holder-reward runs, newest first: status, the snapshot's slot and hash, the pot, what was paid and to how many holders. Sapling pays holder rewards itself on every run; there is nothing to claim.
- mint
- one coin's runs
- cursor
- from the last page's next
{
"data": [
{
"id": 4182,
"mint": "<mint>",
"symbol": "OWL",
"status": "done",
"snapshotSlot": "371204411",
"snapshotHash": "<sha256>",
"potZec": "62000000",
"paidZec": "61400000",
"paidCount": 38,
"eligible": 38,
"rolledOverZec": "0",
"releaseSignature": "<signature>",
"returnSignature": null,
"startedAt": "2026-10-01T17:12:00.000Z",
"finishedAt": "2026-10-01T17:13:40.000Z"
}
],
"next": "<cursor>"
}GET/v1/rewards/runs/{id}
One run with every payout, its snapshot, and how to recompute the snapshot yourself (verify). When the snapshot names a shielded launch's deployer, it is withheld (null), and that payout has no address and no signature.
{
"id": 4182,
"mint": "<mint>",
"symbol": "OWL",
"status": "done",
"snapshotSlot": "371204411",
"snapshotHash": "<sha256>",
"snapshot": "…",
"payouts": [
{
"owner": "<wallet>",
"balance": "18200000000000",
"shareZec": "2210000",
"status": "paid",
"signature": "<signature>"
}
],
"verify": "…"
}GET/v1/wallets/{address}/rewards
Holder rewards paid to this wallet, newest first.
- cursor
- from the last page's next
{
"data": [
{
"runId": 4182,
"mint": "<mint>",
"shareZec": "2210000",
"status": "paid",
"signature": "<signature>",
"at": "2026-10-01T17:13:12.000Z"
}
],
"next": null
}Transaction builders
Each answers unsigned transactions for your user's wallet to sign. Nothing is signed or sent until you do it. Every build is simulated first, and refused in plain words (422 refused) when its simulation fails.
POST/v1/plant/upload
The coin's image and metadata, as on the site: checked, re-encoded without EXIF, pinned to IPFS. Multipart form: name, symbol, description, twitter, website, telegram, image, payer (the planter's wallet), mint (the new coin's address, its public key only), and holders (1 when the deployer's share will pay holder rewards: the description's footer says so). An image that needs a person to look at it is not published: the answer is 409 image_in_review, and the same image uploaded after the review passes or is refused.
{
"mediaId": "<id>",
"uri": "ipfs://<cid>",
"image": "https://sapling.cash/media/coins/<id>/large.webp",
"metadata": {
"name": "Night Owl",
"symbol": "OWL",
"image": "ipfs://<cid>"
}
}POST/v1/plant/build
The planting: one transaction that creates the coin, pays the launch fee, makes the first buy if you ask for one, and declares where the deployer's share goes. Signed by the wallet, then by the mint key. The name, symbol and uri must be the upload's.
{
"wallet": "<wallet>",
"mint": "<mint>",
"name": "Night Owl",
"symbol": "OWL",
"uri": "ipfs://<cid>",
"payee": "holders",
"firstBuy": {
"zec": "50000000",
"slippageBps": 100
}
}{
"buildId": "b_<id>",
"kind": "plant",
"transactions": [
{
"base64": "<unsigned v0 transaction>",
"signers": [
"<wallet>",
"<mint>"
],
"lookupTables": [
"<lookup table>"
],
"lastValidBlockHeight": 312345678,
"size": 1183
}
],
"simulation": {
"ok": true,
"solCostLamports": "14328760",
"reason": null
},
"costs": {
"priorityLamportsMax": "150000",
"launchFeeLamports": "10000000"
},
"expected": {
"tokensOut": "1601240000000",
"minTokensOut": "1585227600000"
},
"intent": {
"wallet": "<wallet>",
"mint": "<mint>",
"payee": "holders",
"firstBuyZec": "50000000"
},
"expiresAt": "2026-10-01T18:41:30.000Z"
}POST/v1/trade/build
A buy or a sell on the curve or the pool, whichever the coin trades on now (read from chain). A buy paid in SOL swaps to ZEC in the same transaction when it fits; otherwise the answer has two steps and then says what to call once the first lands. A sell of "all" closes the emptied token account.
{
"wallet": "<wallet>",
"mint": "<mint>",
"side": "buy",
"pay": "ZEC",
"amount": "25000000",
"slippageBps": 100
}{
"buildId": "b_<id>",
"kind": "buy",
"transactions": [
{
"base64": "<unsigned v0 transaction>",
"signers": [
"<wallet>"
],
"lookupTables": [
"<lookup table>"
],
"lastValidBlockHeight": 312345678,
"size": 742
}
],
"simulation": {
"ok": true,
"solCostLamports": "2039280",
"reason": null
},
"costs": {
"priorityLamportsMax": "150000"
},
"expected": {
"tokensOut": "792310044210",
"minTokensOut": "784386943768",
"maxZecIn": "25250000",
"priceImpactBps": 41
},
"intent": {
"wallet": "<wallet>",
"mint": "<mint>",
"side": "buy",
"pay": "ZEC",
"amount": "25000000",
"slippageBps": 100
},
"expiresAt": "2026-10-01T18:41:30.000Z"
}POST/v1/swap/build
SOL to ZEC or back through Jupiter, for a first buy or a sale paid out in SOL. Simulated, and refused when it would cost more than it should.
{
"wallet": "<wallet>",
"from": "SOL",
"to": "ZEC",
"amount": "200000000",
"slippageBps": 100
}{
"buildId": "b_<id>",
"kind": "swap",
"transactions": [
{
"base64": "<unsigned v0 transaction>",
"signers": [
"<wallet>"
],
"lookupTables": [
"<lookup table>"
],
"lastValidBlockHeight": 312345678,
"size": 742
}
],
"simulation": {
"ok": true,
"solCostLamports": "2039280",
"reason": null
},
"costs": {
"priorityLamportsMax": "150000"
},
"expected": {
"zecOut": "74100000",
"minZecOut": "73359000"
},
"intent": {
"wallet": "<wallet>",
"from": "SOL",
"to": "ZEC",
"amount": "200000000"
},
"expiresAt": "2026-10-01T18:41:30.000Z"
}POST/v1/claim/build
Pays what waits in a coin's fee account to its payee. Anyone can send it, and it always pays the payee recorded on chain, never the sender.
{
"wallet": "<wallet>",
"mint": "<mint>"
}{
"buildId": "b_<id>",
"kind": "claim",
"transactions": [
{
"base64": "<unsigned v0 transaction>",
"signers": [
"<wallet>"
],
"lookupTables": [
"<lookup table>"
],
"lastValidBlockHeight": 312345678,
"size": 742
}
],
"simulation": {
"ok": true,
"solCostLamports": "2039280",
"reason": null
},
"costs": {
"priorityLamportsMax": "150000"
},
"expected": {
"zecOut": "1240000"
},
"intent": {
"wallet": "<wallet>",
"mint": "<mint>"
},
"expiresAt": "2026-10-01T18:41:30.000Z"
}POST/v1/payee/build
Moves the deployer's share to another wallet, or turns it into holder rewards. Signed by the current payee only. What waits is paid to the current payee first, in the same transaction. Holder rewards are permanent: the answer says permanent: true.
{
"wallet": "<current payee>",
"mint": "<mint>",
"payee": "holders"
}{
"buildId": "b_<id>",
"kind": "payee",
"transactions": [
{
"base64": "<unsigned v0 transaction>",
"signers": [
"<wallet>"
],
"lookupTables": [
"<lookup table>"
],
"lastValidBlockHeight": 312345678,
"size": 742
}
],
"simulation": {
"ok": true,
"solCostLamports": "2039280",
"reason": null
},
"costs": {
"priorityLamportsMax": "150000"
},
"expected": {},
"intent": {
"wallet": "<current payee>",
"mint": "<mint>",
"payee": "holders"
},
"expiresAt": "2026-10-01T18:41:30.000Z",
"permanent": true
}Sending
Send signed transactions through your own RPC, or through the relay. The relay sends only what it built.
POST/v1/tx/send
Sends a build's signed transactions. Each one must be byte for byte the build's, apart from what a wallet may add (a compute budget, Lighthouse assertions), and pass the same check again with every signature verified. A build is sent once.
{
"buildId": "b_<id>",
"signed": [
"<signed transaction, base64>"
]
}{
"signature": "<signature>",
"status": "confirmed"
}GET/v1/tx/{signature}
A transaction's status: sent, confirmed, finalized or failed. For a planting, whether Sapling registered the coin.
{
"signature": "<signature>",
"status": "finalized",
"err": null,
"registered": true,
"mint": "<mint>"
}