XMR ROOTS / DEVELOPER API

Read the roots.
Plant from anywhere.

The same chain data and the same planting builder xmrroots.xyz uses, as JSON. No key. Nothing to sign on our side.

REST · JSONSolana mainnetUnsigned transactionsv1

One base URL, no key.

Read coins, stats and receipts, and build a planting your user signs in their own wallet.

Base URLhttps://api.xmrroots.xyz/v1

Every answer is read from Solana: the XMR ROOTS vault program, the coin accounts, the liquidity ledgers and the ROOTS mint. Planting builds come back as an unsigned v0 transaction with empty signature slots. The API holds no key, signs nothing and sends nothing; always verify a returned transaction against your request before signing it.

A planting made through the API pays exactly what a planting on xmrroots.xyz pays: the 2% creator fee and its split are enforced on chain, for every trade from anywhere. There is no integrator fee and no referral.

A first readcurl https://api.xmrroots.xyz/v1/stats
Privacy.

The API keeps no record of who calls it. Your address is used only as an in-memory rate-limit key, hashed with a salt that changes when the service restarts, and is never written to a log or to disk. Requests reach the service through Cloudflare, which sees connections as it does for xmrroots.xyz.

Built to be polled.

RouteLimit per clientEdge cache
GET /v1/params60 / min5 min
GET /v1/coins, /v1/coins/{mint}, /v1/stats60 / min30 s
GET /v1/receipts60 / min60 s
GET /v1/monero-gf/receipts60 / min60 s
POST /v1/plant/build3 / hournever

Data refreshes from chain about once a minute, so polling faster than every 15 seconds returns the same answer. X-RateLimit-Limit and X-RateLimit-Remaining come with every answer; a 429 also carries Retry-After.

GET routes answer any origin (Access-Control-Allow-Origin: *). Browser builds are accepted from xmrroots.xyz; from your own app, call /v1/plant/build from your server and hand the unsigned transaction to the browser.

Every error has the same shape{ "error": { "code": "rate_limited", "message": "Too many requests. Try again in 12 seconds." } }
codeStatusMeaning
invalid_param400A parameter or body field is missing or malformed. The message names it.
pair_closed · planting_closed · origin_not_allowed403That pair or planting is not open, or the browser origin is not accepted.
not_found404No such route or coin.
mint_exists409The mint key is already used. Generate a new one.
refused422The planting did not pass simulation. The message says why in plain words.
rate_limited429Wait for Retry-After seconds.
unavailable503Data is loading or the last chain snapshot is over five minutes old.

Base units, as strings.

Every amount is an integer in base units sent as a decimal string. Parse with BigInt, never with floats.

AssetDecimalsExample
wXMR12"1000000000000" is 1 wXMR
ROOTS and every coin6"1000000" is one token
hSOL · SOL9"200000000" is 0.2
Pool LP token9"1000000000" is 1 LP

A coin's vault amounts are in its rewardAsset: wXMR for wXMR and hSOL pairs (hSOL fees are converted to wXMR on chain before the split), ROOTS for ROOTS pairs. Times are ISO 8601 in UTC.

GET/v1/params

Everything a builder needs, so nothing is typed in: program ids and the verified program hash, the protocol config, treasury and lookup tables, the mints, quotes and pairs, the planting rules and the fee split.

answer (shortened){ "network": "mainnet-beta", "programs": { "rootsVault": "9RSfkTWckTiuCQTae86bgqZWumcLcj4fzDLxi9qNoVeM", "pump": "…", "pumpSwap": "…" }, "program": { "sha256": "…", "verified": true, "config": "…" }, "mints": { "wXMR": "WXMRyRZhsa19ety5erZhHg4N3xj3EVN92u94422teJp", "ROOTS": "4PbxcLPioEQNQT8jCdTnvfM2CddTzHrDStnxniRypump", "hSOL": "he1iusmfkpAdwvxLNGV8Y1iSbj4rUy6yMhEA3fotn9A" }, "quotes": [ { "symbol": "wXMR", "kind": "wxmr", "decimals": 12, "rewardAsset": { "symbol": "wXMR" }, "plantable": true }, { "symbol": "ROOTS", "kind": "roots", "decimals": 6, "rewardAsset": { "symbol": "ROOTS" }, "plantable": true }, { "symbol": "hSOL", "kind": "lst", "decimals": 9, "rewardAsset": { "symbol": "wXMR" }, "plantable": true } ], "stocks": { "api": false, "count": 38 }, "planting": { "open": true, "creatorFeeBps": 200, "name": { "maxBytes": 32 }, "ticker": { "pattern": "^[A-Za-z0-9]{1,12}$" }, "signers": ["wallet", "mint"] }, "split": { "creatorFeeBps": 200, "ofCreatorFee": { "rewards": 4000, "buyback": 2500, "liquidity": 2500, "treasury": 1000 } } }

Stock pairs are not part of API v1: coins already paired with a stock are listed read-only, and /v1/plant/build refuses them.

GET/v1/coins

The public catalog, as on xmrroots.xyz/coins (protocol validation coins are not listed). Parameters: pair (wXMR, ROOTS, hSOL or a quote mint), rewards (creator or holders), sort (mint, reserve or rewards), limit (1 to 100, 50 by default) and cursor (the previous page's next).

requestcurl "https://api.xmrroots.xyz/v1/coins?pair=wXMR&rewards=holders&limit=10"

GET/v1/coins/{mint}

One coin: its metadata and image, pair, reward asset and mode, vault totals (reserve, rewards, buyback, settled, treasury allocations, redeemed), supply and burned supply, and its liquidity ledger.

answer (shortened){ "mint": "J8P7uS4tufpsJaQoydaVivVh2Nw1vkE2RKwT6LK8YRdR", "name": "monero chan", "symbol": "MONEROCHAN", "uri": "https://api.xmrroots.xyz/metadata/….json", "image": "https://api.xmrroots.xyz/metadata/….png", "pair": { "symbol": "wXMR", "kind": "wxmr", "decimals": 12 }, "rewardAsset": { "symbol": "wXMR", "decimals": 12 }, "rewardsTo": "holders", "vault": { "reserve": "…", "rewards": "…", "buyback": "0", "settled": "…", "redeemed": "0", "nextEpoch": "3" }, "supply": "999…", "burned": "…", "liquidity": { "initialized": true, "budget": "…", "quoteSpent": "…", "lpBurned": "…" } }

The creator's wallet is not part of the answer.

GET/v1/stats

The figures of xmrroots.xyz/stats: coin counts, vault totals in wXMR and in ROOTS, treasury and outstanding rewards, shared liquidity spent and LP burned, ROOTS supply and ROOTS burned, and the automation counters the keeper publishes.

GET/v1/receipts

Buybacks, burns, payouts, liquidity deposits, reward epochs and conversions, newest first, each with its transaction signature, slot, coins, the amounts burned and the amounts that left a coin vault. Read from the program's confirmed transactions, plus the treasury's earlier buyback receipts. Payout receipts give the number of payments, never the recipients.

Parameters: kind (comma list: buyback, burn, liquidity, payout, holder-payout, creator-payout, rewards-epoch, conversion, reserve-migration, redemption, treasury-buyback, treasury-burn), coin, limit, cursor. index.complete is false while history is loading or if the safety limit of 20,000 signatures per source was reached before the oldest page. index.truncated makes that limit explicit. Amounts in receipts are not a complete count of every burn by every wallet.

requestcurl "https://api.xmrroots.xyz/v1/receipts?kind=buyback,burn&limit=20"

GET/v1/monero-gf/receipts

XMR sent to the Monero General Fund by coins whose 0.80% (the 40% rewards slice of the 2% creator fee) goes to it: rewardsTo: "monero-general-fund" and moneroGf.destination on a coin, rewards: "monero-general-fund" at /v1/plant/build, moneroGf in params and stats. Each payment lists the coins behind it (first in, first out) and coins gives each coin's total. One receipt per payout of the wxmr.io bridge: the Monero tx id and tx key the bridge published on Solana, the Solana signatures, and monero.status: verified only once the keeper ran check_tx_key on a Monero node and found the payment to the General Fund address. Check it yourself: check_tx_key <tx id> <tx key> 888tNkZr…avup3H in monero-wallet-cli, or Monero GUI, Advanced, Prove/Check. Parameters: limit, cursor. Empty while the option is closed. XMR ROOTS is not affiliated with the Monero Project.

requestcurl "https://api.xmrroots.xyz/v1/monero-gf/receipts?limit=20"

GET/v1/health

ok is true when the snapshot is under five minutes old and the deployed program matches its verified hash. It answers 503 otherwise.

POST/v1/plant/build

One unsigned transaction: it creates the coin on pump.fun with the chosen pair, registers its XMR ROOTS vault and opens its liquidity ledger.

  1. Make the mint key on your side.

    Keypair.generate(). Only its public key is ever sent.

  2. Host the metadata JSON.

    A public https URL up to 200 bytes whose JSON has the same name and symbol and an image. The API does not fetch it.

  3. Build.

    Send wallet, mint, name, symbol, uri, pair (wXMR, ROOTS or hSOL) and rewards (creator or holders). Every build is simulated on mainnet before it is answered.

  4. Verify, sign, send.

    Check the transaction against your own request, sign with the wallet first and then with the mint key, and send it through your own RPC before lastValidBlockHeight.

bodyPOST https://api.xmrroots.xyz/v1/plant/build content-type: application/json { "wallet": "<wallet>", "mint": "<new mint public key>", "name": "Night Owl", "symbol": "OWL", "uri": "https://example.com/owl.json", "pair": "wXMR", "rewards": "holders" }
answer (shortened){ "transactions": [{ "transaction": "<base64 v0 transaction, empty signature slots>", "signers": ["<wallet>", "<mint>"], "lookupTables": ["9xsTMu1qUdPs6ijzyD7Q555cgQh2BEF5PLqsbrppqs5E", "…"], "lastValidBlockHeight": 440210649, "size": 955 }], "simulation": { "ok": true, "unitsConsumed": 196039, "solCostLamports": "11527760", "networkFeeLamports": "11400" }, "coin": { "mint": "<mint>", "coinAuthority": "…", "liquidityLedger": "…", "pair": { "symbol": "wXMR" } }, "intent": { "wallet": "…", "mint": "…", "name": "Night Owl", "symbol": "OWL", "pair": "wXMR", "rewards": "holders" }, "expiresAt": "…" }

A first buy is a separate trade after the planting lands, as on the site. The blockhash expires in about a minute: build again after expiresAt.

Trust the chain, not the API.

Decode the transaction and check, on your side, before any signature:

  1. Signers.

    Exactly two: your wallet as fee payer, then your mint key.

  2. Programs.

    Only ComputeBudget, pump.fun (6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P), Associated Token, and the XMR ROOTS vault program from /v1/params.

  3. Creator.

    The pump.fun creator is the coin authority PDA ["coin-authority", mint] under the vault program, so the creator fee is split by the program, never paid to a wallet.

  4. Identity.

    Name, symbol, uri and reward mode match what you asked for. Then simulate it yourself with your own RPC.

OpenAPI.

The complete schema of every route and answer, for code generators and validators.

Your token.
Shared ROOTS liquidity.

Plant a coin →
$ROOTS CA4PbxcLPioEQNQT8jCdTnvfM2CddTzHrDStnxniRypumpX · @xmrroots ↗