{"title":"XRPL.to API","version":"1.20","baseUrl":"https://api.xrpl.to/v1","baseUrlNotes":"https://api.xrpl.to/v1 is the canonical base. https://api.xrpl.to/api serves the identical API (internal alias) — use /v1 in new integrations.","openapi":"https://api.xrpl.to/v1/openapi.json","openapiNotes":"Full OpenAPI 3.1 spec (270+ paths with parameter/response schemas) — use it for codegen, Postman, and LLM tooling.","humanDocs":"https://xrpl.to/docs","quickStart":{"example":"curl \"https://api.xrpl.to/v1/tokens?limit=10\"","authenticatedExample":"curl -H \"X-Api-Key: YOUR_KEY\" \"https://api.xrpl.to/v1/tokens?limit=10\"","websocket":"wss://api.xrpl.to/ws/sync/","notes":"Quote URLs in shells (zsh globs on \"?\"). No key needed to start — see rateLimits.anonymous. Get a key: POST /v1/keys (wallet signature) or via https://xrpl.to/docs."},"authentication":{"apiKey":{"description":"Pass your API key via header","header":"X-Api-Key: YOUR_API_KEY","gettingAKey":"Create one with POST /v1/keys (requires a wallet signature — see the keys section) or through the dashboard at https://xrpl.to/dashboard. Free tier: 1 active key, 1M credits/mo.","notes":"Most read endpoints work without a key (anonymous tier). API keys provide higher rate limits and credit allocations."},"walletSignature":{"description":"Required for key management and account operations","headers":{"X-Wallet":"Your XRPL r-address","X-Signature":"Hex signature of message \"{wallet}:{timestamp}\"","X-Timestamp":"Unix milliseconds timestamp (5 min validity window)","X-Public-Key":"Hex public key (always required for /user and /watchlist signed routes; optional for /keys routes after first on-ledger transaction)"}},"userAgent":"Requests with generic programmatic User-Agent strings (e.g. Python-urllib) may be challenged by the CDN/WAF with a non-JSON 403 before reaching the API. Always send a descriptive User-Agent identifying your app (e.g. \"myapp/1.0\")."},"usagePolicy":{"appliesTo":"Every caller — no key, Free, and every paid tier alike.","attribution":"REQUIRED. Any app, website, bot, or dashboard that displays xrpl.to data must show a visible, clickable credit to xrpl.to on the same screen as that data — not buried in an about page. Use: <a href=\"https://xrpl.to\" target=\"_blank\" rel=\"noopener\">Data by xrpl.to</a>","redistribution":"Storing our data and re-serving it from your own API, dataset, or public dashboard requires written permission first. Email hello@xrpl.to — the answer is usually yes, we just need to know who is doing it.","indexers":"Use the paginated list endpoints instead of looping one item at a time, cache what you fetch, and honour Retry-After on a 429 — a repeated 429 means back off, not retry. Get a key rather than running anonymous so we can raise your limits instead of blocking you.","partner":"The invitation-only Partner tier (100 req/sec, 20M credits/mo, direct support) is free for integrations that credit us properly. Email hello@xrpl.to or DM @xrplto on X.","contact":"hello@xrpl.to"},"rateLimits":{"description":"Four independent layers apply to every request; the strictest one wins. All 429 responses carry Retry-After plus X-RateLimit-Limit/-Remaining/-Reset headers and a JSON body with retryAfter.","layers":{"ipBurst":"All clients: 100 requests per 2s per IP (DDoS backstop). 429 with Retry-After: 2.","perSecond":"Sustained rate enforced over a 10s window, plus a hard 1-second burst cap. Anonymous: 2/sec burst, 30/min sustained, per IP. Free: 10/sec sustained with 20/sec bursts (shared per IP across keys). Keyed tiers per key — developer 50/sec (burst 100), partner 100/sec (burst 200), business 200/sec (burst 300), professional 500/sec (burst 750).","perMinute":"Anonymous and free: 30 req/min and 600 req/min per IP respectively.","perEndpoint":"Expensive endpoints have their own request windows, matched by path prefix (so /tokens and /tokens/slugs share one bucket). Base limits are per 60s and scale by tier multiplier: anonymous 0.25x, free 1x, developer 3x, partner 5x, business 10x, professional 15x, enterprise uncapped. Examples at anonymous tier: /tokens 5/min, /search 7/min, /amm 7/min, /account/tx 5/min. Some endpoints pin per-tier caps directly instead of the multiplier (unpinned tiers use the standard multiplier): /dex/quote 1/min anonymous, 3/min free, 45/min partner (10 credits/call); /mentions/x-search 1/min anonymous, 2/min free (10 credits/call); /web-search 1/min anonymous, 3/min free; /tx-explain 3/min free; /account-tx-explain 2/min free. The 429 body names the endpoint bucket and its window."},"daily":"Anonymous: 333 requests/day per IP. Free: 33K/day per IP. Keyed tiers per key: developer 400K/day, partner 1M/day, business 4M/day, professional 8M/day. Successful responses include X-RateLimit-Daily-Remaining where a daily cap applies.","headers":"Successful responses include X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset (seconds until the window resets). For anonymous clients these reflect the per-minute window; for keyed clients the per-second window. Credit-metered keys also get X-Credits-Used / X-Credits-Remaining.","anonymous":"2 req/sec burst, 30 req/min, 333/day (no key) + 0.25x endpoint windows","free":"10 req/sec (burst 20, 600/min), 33K req/day per IP, 1M credits/mo (free API key)","developer":"50 req/sec (burst 100), 5 tx/sec, 400K req/day, 10M credits/mo, 3x endpoint windows","partner":"100 req/sec (burst 200), 10 tx/sec, 1M req/day, 20M credits/mo, 5x endpoint windows (invitation-only, for integration partners)","business":"200 req/sec (burst 300), 50 tx/sec, 4M req/day, 100M credits/mo, 10x endpoint windows","professional":"500 req/sec (burst 750), 100 tx/sec, 8M req/day, 200M credits/mo, 15x endpoint windows","notes":"Each endpoint has a credit cost (0-10 credits per call). Check /keys/costs for details. WebSocket messages cost 0.1 credits each. Scam-blocklist reads (/scams/*, /nft/scam) are never rate-limited or capped."},"tokenIdFormat":{"description":"All {id} parameters accept any of these formats:","formats":{"md5":"32-char hex hash","slug":"issuer-currency (e.g. rhcyBrowwApgNonehKBj8Po5z4gTyRknaU-VGB)","issuer_currency":"issuer_currencyHex (40-char hex currency, underscore separator)","mpt":"mpt-<48-char mptIssuanceID> (MPT slug form)","xrp":"Native XRP: use the literal \"XRP\" (or its canonical md5 84e5efeb89c4eae8f68188982dc290d8). Works everywhere a token {id} is accepted, e.g. /token/XRP, /stats/rates?token1=XRP&token2={md5}, /ohlc/XRP."}},"conventions":{"took":"Server-side processing time: integer MILLISECONDS as a JSON number, on every endpoint. Excludes network transfer.","countAndTotal":"One meaning everywhere: count = rows in THIS response; total (also pagination.total / meta.total) = rows matching the query pre-pagination. Exception: on single-resource + metrics responses (/stats, /stats/rates, /token/{id}), the envelope's total is the count of all indexed tokens — a platform stat, not pagination. A few older endpoints use length; its meaning is stated per endpoint.","clamping":"Out-of-range numeric params are clamped, not rejected (limit above max -> max, negative offset -> 0, non-numeric -> default); the effective value is echoed in the response. Invalid enum values fall back to the documented default (e.g. an unknown range/interval/sort). An unknown tag returns 200 with 0 rows and empty tagName — check tagName to distinguish a typo from genuinely no data.","numericStrings":"Very-high-precision amounts (amount, supply, usd, exch on some endpoints, sparkline prices) are serialized as STRINGS on purpose — XRPL token amounts exceed IEEE-754 float precision. Parse with a decimal library if you need exact math.","timestamps":"Unix milliseconds (13 digits) unless a field is explicitly documented otherwise.","attribution":"Successful responses on the tiers that pay nothing (anonymous, free, partner) carry an `attribution` string right after `success`, restating the requirement in usagePolicy. It is informational — safe to ignore in code, but not optional to comply with. Paid tiers omit it and owe the same attribution."},"tokenFields":{"identity":{"md5":"canonical token id — md5(issuer + \"_\" + currency)","issuer":"issuer r-address (\"XRPL\" for native XRP)","currency":"3-char code or 40-char hex currency","name":"display ticker/name","user":"issuer display name","slug":"URL slug (issuer-currency)","tokenType":"trustline|lp|mpt|xls14|demurrage|nonstandard","origin":"launchpad/source platform (FirstLedger, XPMarket, LedgerMeme, ...)","tags":"category tags (see /tags)","dateon":"listing time (unix ms)"},"price":{"exch":"current price in XRP (string, precision-preserving)","usd":"current price in USD (string)","dom":"market dominance % of total XRPL token marketcap","pro5m":"% price change, last 5 minutes","pro1h":"% 1h","pro24h":"% 24h","pro7d":"% 7d","pro30d":"% 30d","maxMin24h":"[max, min] price over 24h — MAX FIRST","athDistance":"% below all-time high"},"market":{"marketcap":"live marketcap in XRP (number; price x circulating supply, computed server-side — do not recompute)","vol24hxrp":"24h volume in XRP","vol24htx":"24h trade count","vol24h":"24h token-side volume","amount":"total issued supply (string)","supply":"circulating supply (string)","tvl":"AMM total value locked (XRP)","holders":"trustline holders with balance","holders24h":"24h holder-count CHANGE (negative = net loss)","trustlines":"total trustlines","uniqueTraders24h":"distinct traders in 24h","buyerPressure":"buy/sell volume ratio (24h); 1.0 = balanced, above 1 = net buying","buy24hxrp":"24h BUY volume in XRP","sell24hxrp":"24h SELL volume in XRP","buy24htx":"24h buy trade count","sell24htx":"24h sell trade count","vol24hAMM":"24h volume filled by AMM pools (XRP)","vol24hOrderbook":"24h volume filled on the order book (XRP)","liquidityRatio":"24h volume / marketcap (ratio, not a percent)","depthPlus2":"XRP that can be BOUGHT against the AMM pool before its price rises 2%","depthMinus2":"XRP received SELLING against the AMM pool before its price falls 2%","tvlChange24h":"TVL change vs ~24h ago in XRP (from hourly pool snapshots; absent = no 24h-old baseline)","vol6hxrp":"6h traded volume in XRP (hourly recompute)","vol7dxrp":"7d traded volume in XRP (hourly recompute)","gini":"holder-balance Gini coefficient 0-1 (1 = max inequality; basis-independent)","hhi":"Herfindahl concentration index, Σ(holding%)² 0-10000, on total supply","tradingFee":"AMM pool trading fee in rippled TradingFee units: 1/100000 (1000 = 1%)"},"signals":{"rsi15m_90d":"RSI oscillator per timeframe (rsi15m, rsi1h, rsi4h, rsi24h, rsi7d, rsi30d, rsi90d)","trendingScore":"decaying pageview+activity trend score","assessmentScore":"raw risk/quality score (see /token/review for the graded verdict)","creatorHoldingPercent":"% of supply held by the creator wallet","top10":"% of supply held by the top 10 holders","lpBurnedPercent":"% of AMM LP tokens burned","isOMCF":"\"yes\" = listed/indexed token (On Main Chart Filter); tokens without it are unlisted","verified":"verification tier: 1 (company) | 2 | 4 (paid); absent/false = unverified","kyc":"issuer passed Xaman wallet KYC","xVerified":"linked X account is verified","views24h":"site pageviews (24h)"},"notes":"The full object carries additional self-describing metric variants (7d/30d windows, per-fiat conversions). lightweight=true on /tokens strips to the ~50 essential fields listed here."},"tokens":[{"method":"GET","path":"/tokens","description":"List all tokens with metrics","params":{"limit":"int (max 100; default 100, or 50 with tag/filter/filterNe, 20 with sort=assessmentScore|pro5m|trendingScore)","offset":"int (default 0)","sort":"token field name: vol24hxrp|marketcap|pro5m|pro1h|pro24h|pro7d|exch|holders|tvl|trendingScore|assessmentScore|dateon (unknown field = no-op)","order":"asc|desc (default: desc)","tag":"filter by tag (see /tags, case-insensitive)","filter":"text search on token name","watchlist":"watchlist owner account (r-address) — filters to that account's watchlist tokens","show_new":"bool - only tokens created in the last 7 days","show_slug":"bool - only tokens whose slug equals their md5","show_date":"bool - only tokens with missing/unknown date","tags":"yes - include tags array","token_type":"trustline|lp|mpt|xls14|demurrage|nonstandard (invalid value = no filter, echoed back as token_type: null)","skip_metrics":"bool - skip the global metrics envelope (exch/H24/global) — combine with lightweight for the smallest payload","lightweight":"bool - strip each token to ~50 essential fields (~77% smaller per token; see tokenFields)","filterNe":"text - exclude matching tokens (negative filter)"},"response":"{ success, took (ms), total (tokens matching the query, pre-pagination), count (tokens in this response), start, limit, tagName, sortBy, sortType, tokens[], exch, H24, global (metrics omitted when skip_metrics=true) }"},{"method":"GET","path":"/tokens/slugs","description":"All token slugs","response":"{ success, count (rows returned), total (all matching), truncated, slugs[] }"},{"method":"GET","path":"/token/{id}","description":"Single token by id (see tokenFields for the token object dictionary)","params":{"desc":"yes - include description","skip_metrics":"bool - omit the global metrics envelope (exch/total/H24/global)"},"response":"{ success, took, total, exch, H24, global, token }"},{"method":"POST","path":"/search","body":"{ search, offset?, limit? }","description":"Search tokens, NFTs, collections, and accounts. limit max 100; offset clamped so offset+limit <= 100","response":"{ success, took, tokens[], collections[] (up to 20, best match first; tolerates one typo, missing spaces, initials like \"baxc\" and extra words like \"nft\" or \"the\"), nfts[] (up to 20; identical names in one collection collapse to one row with editions: N; \"name #N\" queries resolve item N of the named collection), order (result groups strongest match first, e.g. [\"nfts\",\"collections\",\"tokens\"]), account (always present: account object when search is an r-address, null otherwise), pagination: { offset, limit, total, hasMore, maxResults: 100 } }"},{"method":"GET","path":"/tags","description":"List all token tags","response":"{ success, took, exch, H24, global, tags }"},{"method":"POST","path":"/token/{md5}/metadata","auth":"wallet signature (token creator/issuer or admin)","body":"{ user?, domain?, whitepaper?, description?, social?, tags? (max 15; origin/launchpad tags admin-only), linkedCollections? (max 10) }","description":"Update token metadata. 3s per-token write cooldown.","response":"{ success, updated[] }"},{"method":"POST","path":"/token/{md5}/image","auth":"wallet signature (token creator/issuer or admin)","body":"{ imageData: base64 PNG/JPEG/GIF/WebP (max ~650KB decoded) }","description":"Upload token logo image. 3s per-token write cooldown.","response":"{ success, md5, imgUpdated }"}],"charts":[{"method":"GET","path":"/ohlc/{id}","description":"OHLC candlestick data","params":{"range":"1D|5D|7D|1M|3M|1Y|5Y|ALL","interval":"1m|5m|15m|30m|1h|2h|4h|1d|1w","vs_currency":"XRP|USD|EUR|JPY|CNH (default: XRP)","resolution":"int (minutes), or D|W","cb":"int (candle bar count, max 5000)","invert":"bool"},"response":"{ success, took, length, format, resolution, interval, interval_seconds, vs_currency, inverted, base_interval, preAgg?, ohlc: [[time, open, high, low, close, volume, ...]] }"},{"method":"GET","path":"/sparkline/{id}","description":"Price sparkline","params":{"period":"24h|7d (default: 7d)","vs_currency":"XRP|USD (default: XRP)","lightweight":"bool - sample data points","max_points":"int (default: 20, range 2-500; only applies when lightweight=true)","pro24h":"float - override percentChange/chartColor when period=24h","pro7d":"float - override when period=7d"},"response":"{ success, chartColor, period, percentChange, lightweight, vsCurrency, data: { prices[], timestamps[], max, min } }"},{"method":"GET","path":"/holders/info/{id}","description":"Holder concentration (top10/20/50/100 %)","response":"{ success, took, richInfo: { time, length, holders, top10, top20, top50, top100, active24H } }"},{"method":"GET","path":"/holders/graph/{id}","description":"Holder count history","params":{"range":"1D|7D|1M|3M|1Y|5Y|ALL (default: 7D)"},"response":"{ success, took, length, history[] }"},{"method":"GET","path":"/holders/list/{id}","description":"Paginated holder richlist with acquisition tracking","params":{"offset":"int","limit":"int (default: 20, max 200)","freeze":"bool - only frozen trustlines","sort":"balance|value|holding|percent|change24h|pnl (value/percent are balance/holding aliases; default: balance desc)","order":"asc|desc","search":"account address (min 3 chars)","minBalance":"float - min balance (token units)","maxBalance":"float - max balance (token units)"},"response":"{ success, took, summary: { top10Hold, top20Hold, top50Hold, top100Hold, frozen }, length (total holders; filtered count when search/minBalance/maxBalance set), richList[]: { account, balance, holding, rank, freeze, frozenByIssuer?, isCreator, xrpBalance, lastActive, name, domain, funder, tradedPct?, tradeCount?, source?, acquisition?, isAMM?, pnl? (realized+residual XRP), roi?, unrealized?, bought?/sold? (XRP volume), lastTrade? } }"},{"method":"GET","path":"/holders/movers/{id}","description":"Top 24h buyers and sellers by holder balance delta","params":{"limit":"int per side (default: 20, max 50)"},"response":"{ success, took, limit, holders (total), movers (holders with a 24h change), buyersTotal, sellersTotal, boughtTotal/soldTotal (token-unit sums over all movers) + boughtTotalXrp/soldTotalXrp, pressure?: { m15/m30/h1/h4/h24: { sellers, sellPressureXrp (holdings value of recently-active sellers), buyers, buyPressureXrp (XRP balances of recently-active buyers) } }, buyers[]/sellers[] (capped at limit): { account, name, balance, balance24h, change (token delta, signed), holding (% of supply), value? (current holdings worth, XRP), pnl?/roi? (trading gain/loss XRP + %), lastTrade? (last trade of this token), breakevenMcap? (entry breakeven: mcap XRP where their held tokens equal their FIFO cost), trades? (24h balance-change events [timeMs, side, xrpValue, mcapAtEvent, kind] from trusts_24h + hourly candles; side 1=received/-1=sent, kind 0=trade/1=LP/2=transfer, max 120), isAMM?, isCreator?, freeze? } }"},{"method":"GET","path":"/rsi","description":"RSI indicator data","params":{"offset":"int","limit":"int (max 100)","sort":"rsi15m|rsi1h|rsi4h|rsi24h|rsi7d|rsi30d|rsi90d|marketcap|vol24hxrp|pro24h|pro7d|pro30d|holders|tvl|uniqueTraders24h (default: rsi24h; invalid values fall back)","order":"asc|desc","timeframe":"15m|1h|4h|24h|7d|30d|90d","filter":"text search","tag":"string","origin":"string","minMarketCap":"float","maxMarketCap":"float","minVolume24h":"float","maxVolume24h":"float","minPriceChange24h":"float","maxPriceChange24h":"float","minRsi15m":"float","maxRsi15m":"float","minRsi1h":"float","maxRsi1h":"float","minRsi4h":"float","maxRsi4h":"float","minRsi24h":"float","maxRsi24h":"float","minRsi7d":"float","maxRsi7d":"float","minRsi30d":"float","maxRsi30d":"float","minRsi90d":"float","maxRsi90d":"float","activeOnly":"bool","minHolders":"int","minTVL":"float","excludeNeutral":"bool","minUniqueTraders":"int"},"response":"{ success, took, timeframe, sort, order, filters, tokens[], count, total, start, limit, cached? }"},{"method":"GET","path":"/stats","description":"Platform metrics","response":"{ success, took, total, exch, H24, global }"},{"method":"GET","path":"/stats/rates","description":"Exchange rates between tokens","params":{"token1":"token id","token2":"token id"},"response":"{ success, took, total, exch, H24, global, rate1, rate2 }"},{"method":"POST","path":"/stats/metrics","body":"{ timestamps: [unix_ms, ...] }","description":"Historical exchange rates by timestamps (XRP base)","response":"{ success, took, length, history[]: { timestamp, XRP (USD price), USD (XRP per 1 USD), EUR (XRP per 1 EUR), JPY (XRP per 1 JPY), CNY (XRP per 1 CNY) } }"},{"method":"GET","path":"/stats/marketcap-history","description":"Daily OMCF-filtered marketcap (same as homepage gMarketcap) back to 2021-09-26","params":{"from":"YYYY-MM-DD (required)","to":"YYYY-MM-DD (optional, default today)"},"response":"{ success, took, from, to, length, history[]: { date, gMarketcap (XRP, filtered), unfilteredMarketcap (XRP, incl. illiquid), tokenCount } }"},{"method":"GET","path":"/holders/ranks/{id}","description":"Bulk account-to-rank lookup within the holder richlist","params":{"accounts":"comma-separated r-addresses (max 200)"},"response":"{ success, ranks: { account: rank|null }, total, source: redis|mongo }"},{"method":"GET","path":"/holders/position/{id}/{address}","description":"One account's stake in a token — balance, share of supply and rank, without building the holder list","params":{},"response":"{ success, took, account, md5, balance, holding (% of supply, 2dp rounded down — same figure as /holders/list), rank (null until the worker ranks the token), holders }"},{"method":"GET","path":"/sparkline/batch","description":"Batch sparklines for multiple tokens (cached 30s)","params":{"md5s":"comma-separated md5 hashes (required, max 100)","period":"24h|7d (default: 7d)","maxPoints":"int (default: 50, range 2-500)","vs_currency":"XRP|USD (default: XRP)"},"response":"{ sparklines: { <md5>: [price, ...] } }"},{"method":"GET","path":"/holders/empty/{id}","description":"Zero-balance trustlines (dust/airdrop accounts; precomputed bot accounts excluded)","params":{"limit":"int (1-1000; omit to return the full list)","offset":"int (default: 0, only with limit)"},"response":"{ success, accounts[], count, total, excluded, offset?, limit? }"}],"trading":[{"method":"GET","path":"/history","description":"Trade history by token, account, or both","params":{"md5":"token id (optional if account provided)","account":"r-address","limit":"int (max 1000)","offset":"int","start_time":"unix ms","end_time":"unix ms","type":"trades|liquidity|all (default: trades)","liquidity_type":"create|deposit|withdraw","pair_type":"xrp|token","xrp_only":"bool","xrp_amount":"float (min XRP threshold)","cursor":"int","direction":"asc|desc (default: desc)"},"response":"{ success, took, data[], meta: { total, offset, limit, direction, nextCursor, hasMore, truncated?, timeRange } }","notes":"Offset pagination capped at 100k rows (meta.truncated: true, total capped to servable window; use cursor for deeper history). Trades carry sourceTag (numeric, on-chain SourceTag) and/or platform (canonical name for memo-identified platforms, e.g. SPYDEX)"},{"method":"GET","path":"/amm","description":"List AMM pools","params":{"sort":"fees|apy|liquidity|volume|created","status":"active|all","limit":"int (max 100)","offset":"int","token":"token id","currency":"currency code filter","issuer":"issuer address filter"},"response":"{ success, took, summary, offset, limit, total (matching pools), count (pools in this response), totalPages, pools[] }"},{"method":"GET","path":"/amm/info","description":"Live AMM pool info","params":{"amm_account":"AMM account address","asset":"XRP | token id","asset2":"XRP | token id"}},{"method":"GET","path":"/amm/liquidity-chart","description":"Historical TVL chart data","params":{"token":"token id","token2":"token id","ammAccount":"address","period":"1d|5d|1w|1m|3m|6m|1y|5y|all","poolType":"xrp|token|all"}},{"method":"GET","path":"/pairs","params":{"md5":"token id (required)"},"description":"Trading pairs for a token","response":"{ success, took, count, limit: 100, truncated, pairs[] }"},{"method":"GET","path":"/orderbook","description":"Live DEX orderbook","params":{"base":"token id","quote":"token id","limit":"int (max 400, default 20)"},"response":"{ success, pair, base, quote, bids[], asks[], ledger_index (falls back to ledger_current_index) }"},{"method":"POST","path":"/dex/quote","description":"Get swap quote with routing / path finding (successor to POST /account/path-find). Exact-output via destination_value, or exact-input via source_value","body":"{ source_account, destination_token, destination_value?, source_value?, source_token?, slippage?, destination_account? (the Payment Destination when the output goes to another account; the price is the same, the receive-side checks read that account) }","response":"{ status, took, requiresTrustline, quote: { source_amount, destination_amount, execution_rate, price_impact, amm_price_change (pool spot price % change if the fill executes — buys positive, sells negative; single-leg XRP routes with AMM participation, else null), suggested_slippage (percent — recommended DeliverMin tolerance for this trade; use it instead of a flat value), paths (XRPL Paths the Payment must include — required for token-to-token routes, empty otherwise), warnings[] ({code, message} pre-flight checks: insufficient_balance | line_frozen | dest_limit_low | token_frozen | split_recommended; with a destination_account: recipient_no_trustline | recipient_not_authorized | recipient_line_frozen | recipient_limit_low | recipient_unverified — each means the Payment would fail), destination_account (echoed when it differs from source_account), route, paths_count }, alternatives[] }"},{"method":"GET","path":"/pairs/{id}","description":"Trading pairs for a specific token","response":"{ success, took, count, limit: 100, truncated, pairs[] }"}],"account":[{"method":"GET","path":"/account/balance/{account}","description":"XRP balance with reserves","params":{"simple":"bool - minimal response","rank":"bool - include rank (slow)"},"response":"{ balance, total, balanceDrops, spendableDrops, ownerCount, sequence, flags, reserve, reserveDrops, name, inception, parent, rank? }"},{"method":"POST","path":"/account/balance","body":"{ accounts[] }","description":"Batch balance lookup (max 100)","response":"{ success, took, count, data[]: { account, balance (spendable after reserves), total } }"},{"method":"GET","path":"/account/balance/pair/{account}","params":{"curr1":"currency","issuer1":"issuer","curr2":"currency","issuer2":"issuer"},"description":"Token pair balances"},{"method":"GET","path":"/account/offers/{account}","params":{"pair":"pair hash","md5":"token id (filters offers to that token)","offset":"int (snaps down to a limit-multiple; effective offset echoed)","limit":"int (1-50, default 10; out-of-range resets to 10)"},"description":"Open DEX offers","response":"{ success, took, offset, limit, total, offers[] }"},{"method":"GET","path":"/account/tx/{account}","description":"Full transaction history","params":{"limit":"int (1-200, default 200)","marker":"JSON string (URL-encoded), e.g. {\"ledger\":N,\"seq\":M}","types":"comma-separated TransactionTypes","forward":"bool (default: false)","ledgerMin":"int - ledger index lower bound","ledgerMax":"int - ledger index upper bound"},"response":"{ success, took, count, hasMore, marker, txs[] }","notes":"Own rate window: 20 requests/min per IP on Free, 5/min without a key, more on paid tiers (see rateLimits.layers.perEndpoint)"},{"method":"GET","path":"/account/info/{account}","description":"Account info with DB enrichment"},{"method":"GET","path":"/account/trustlines/{account}","params":{"limit":"int (max 400)","marker":"string","peer":"r-address (filter to single counterparty)"},"description":"Account trustlines"},{"method":"GET","path":"/account/trustline/{account}/{issuer}/{currency}","description":"Single trustline lookup"},{"method":"GET","path":"/account/objects/{account}","params":{"type":"offer|escrow|check|nft_offer|...","limit":"int (max 400)","marker":"string"},"description":"Account objects"},{"method":"GET","path":"/account/currencies/{account}","description":"Sendable/receivable currencies"},{"method":"GET","path":"/account/nfts/{account}","params":{"limit":"int (max 400)","marker":"string"},"description":"NFTs owned by account"},{"method":"GET","path":"/account/gateway/{account}","params":{"hotwallet":"comma-separated addresses"},"description":"Gateway balances (issuer totals)","notes":"Returns 503 \"Account too large, retry shortly\" on issuer-scale timeouts"},{"method":"GET","path":"/account/noripple/{account}","params":{"role":"gateway|user"},"description":"NoRipple check"},{"method":"GET","path":"/account/channels/{account}","params":{"destination":"string","limit":"int (max 400)","marker":"string"},"description":"Payment channels"},{"method":"GET","path":"/account/deposit-authorized","params":{"source":"r-address","destination":"r-address"},"description":"Check deposit authorization"},{"method":"GET","path":"/account/ancestry/{account}","description":"Account ancestry tree","params":{"direction":"up|down|both","limit":"int (max 200)","include_tokens":"bool","token_limit":"int (1-500, default 100)"},"notes":"Requires Developer tier or above (403 otherwise)"},{"method":"GET","path":"/account/token-stats/{account}/{md5}","description":"Per-token trading stats for account","response":"{ success, account, md5, balance, avgBuyPrice, totalBought, totalSold, totalSpentXRP, totalReceivedXRP, realizedPnl, unrealizedPnl, totalPnl, holdingValue, avgBuyMcap, currentMcap, totalRoi, firstTradeTime, tradeCount, exit, took }","notes":"holdingValue/unrealizedPnl mark the bag at the pool SPOT price. `exit` is what selling the WHOLE balance returns right now through the swap engine (same fill as POST /dex/quote): { xrp (proceeds), impactPct (execution vs spot, negative), poolChangePct (pool spot after the fill, null off-AMM), pnl (P&L at that price, same basis as totalPnl — never above it), split (true when one transaction cannot fill it) }. null when the holding is dust, the pair has no liquidity, or the engine cannot price it. Refreshed every 10 s."},{"method":"GET","path":"/trustlines/{account}","description":"Trustlines with token values","params":{"offset":"int (exact, no page snapping)","limit":"int (1-50, default 20; up to 2000 when sort_by_value=true)","format":"raw|default|full","sort_by_value":"bool","search":"text - filter by currency/name/symbol","includeZero":"bool - include zero-balance lines","lightweight":"bool - strip each line’s token join to the ~30 essential fields (see tokenFields; ~90% smaller per line)"},"response":"{ success, took, account, accountActive, accountData, xrp, total, zeroCount, offset, limit, lines[], issued[]?, tokenCount?, totalValue?, truncated? + subsetSize? (sort_by_value on accounts >2000 lines), partial? }"},{"method":"GET","path":"/watchlist","auth":"wallet signature","params":{"account":"r-address"},"description":"Get token watchlist"},{"method":"GET","path":"/watchlist/nft","auth":"wallet signature","params":{"account":"r-address"},"description":"Get NFT watchlist"},{"method":"GET","path":"/account/recent-trades/{account}","description":"Recent trades for an account","params":{"limit":"int (1-100, default 30)","since":"unix ms - only trades after this time"},"response":"{ success, account, count, trades[] }"},{"method":"POST","path":"/account/names","body":"{ accounts[] }","description":"Resolve account display names + verification status in bulk (max 50)","response":"{ success, names: { address: name } }"},{"method":"POST","path":"/watchlist","auth":"wallet signature","body":"{ md5, account, action: \"add\"|\"remove\" }","description":"Add/remove token on watchlist"},{"method":"POST","path":"/watchlist/nft","auth":"wallet signature","body":"{ nftokenId, account, action: \"add\"|\"remove\" }","description":"Add/remove NFT on watchlist"},{"method":"GET","path":"/account/snapshot/{account}","description":"Point-in-time XRP + token holdings valued in XRP at a historical ledger (resolve time to ledger via /ledger/at first)","params":{"ledger":"int (required) - ledger index","closeMs":"unix ms - close time; selects historical vs current pricing"},"response":"{ success, took, account, ledger, close_time, exists, xrp, tokens[], totalXrp, truncated? + maxLines? }"},{"method":"GET","path":"/account/checks/{account}","description":"Check ledger objects with live funding status for cashable checks","response":"{ success, took, account, objects[], truncated? }"},{"method":"GET","path":"/account/search-by-name","params":{"q":"string (min 2 chars; name, domain, or X handle)"},"description":"Search accounts by display name / X profile","response":"{ success, resolvedName, results[] }"}],"ledger":[{"method":"GET","path":"/ledger","description":"Current validated ledger info","response":"{ ledger_index, ledger_hash, close_time (ms), close_time_human, parent_hash, total_coins, txn_count, validated, reserve_base_drops, reserve_inc_drops }","notes":"reserve_base_drops / reserve_inc_drops are the validator-voted account reserve settings, in drops. reserve_inc_drops is the Fee an AccountDelete or AMMCreate MUST carry (one owner reserve) — read it here, never hardcode it: validators can vote the increment, and a stale constant means telINSUF_FEE_P if it rose or a silent overpayment if it fell."},{"method":"GET","path":"/ledger/{index}","description":"Ledger by index with transactions","params":{"index":"ledger index or: validated|closed|current","transactions":"bool (default: true)","expand":"bool (default: false)"}},{"method":"GET","path":"/ledger/entry","description":"Fetch specific ledger object","params":{"index":"entry index","account_root":"address","offer":"JSON { account, seq }","amm":"JSON { asset, asset2 }","check":"ID","escrow":"JSON { owner, seq }","directory":"JSON { dir_root | owner, sub_index? } or plain 64-hex index","payment_channel":"ID","deposit_preauth":"JSON { owner, authorized }","ticket":"JSON { account, ticket_seq }","nft_page":"index"},"notes":"Malformed JSON in object params returns 400"},{"method":"GET","path":"/tx/{hash}","description":"Transaction by hash (64-char hex)"},{"method":"GET","path":"/ledger/at","params":{"time":"unix ms or ISO date (required)"},"description":"Resolve a datetime to the last ledger closed at or before it (binary search)","response":"{ ledger_index, close_time, clampedToHead?, clampedToGenesis? }"}],"submit":[{"method":"POST","path":"/submit","description":"Submit signed transaction","body":"{ tx_blob, fail_hard? }","constraints":"Max tx_blob: 131KB hex. Per-tier rate limit: Free 1/sec, Developer 5/sec, Partner 10/sec, Business 50/sec, Professional 100/sec.","response":"{ success, took, engine_result, engine_result_code, engine_result_message, tx_json, hash, accepted, applied, broadcast, kept, queued, account_sequence_available, account_sequence_next, validated_ledger_index, outcome? }","notes":"Duplicate tx_blob within 30s returns 409"},{"method":"POST","path":"/submit/preview","body":"{ tx_json } or { tx_blob }","description":"Dry-run transaction preview (400 on invalid tx input); sender_after = simulated sender position {balance, reserve, spendable}, null when no sender AccountRoot change","response":"{ success, took, engine_result, engine_result_message, meta, tx_json, sender_after }"},{"method":"POST","path":"/rpc","description":"The XRP Ledger's own READ commands against MAINNET — the twin of POST /testnet/rpc, so a developer who learned the sandbox changes the prefix and nothing else. Reads only (submitting is POST /submit); the node's in-band error (actNotFound, entryNotFound) rides in result with a 200, as on the node","body":"{ method (one of the read commands), params (the command's own fields as an object) }","response":"{ success, took, method, result (the node's own result, verbatim) }","notes":"Same list as /testnet/rpc: account_channels, account_currencies, account_info, account_lines, account_nfts, account_objects, account_offers, account_tx, amm_info, book_changes, book_offers, channel_verify, deposit_authorized, feature, fee, gateway_balances, get_aggregate_price, ledger, ledger_closed, ledger_current, ledger_data, ledger_entry, ledger_header, ledger_index, manifest, mpt_holders, nft_buy_offers, nft_history, nft_info, nft_sell_offers, nfts_by_issuer, noripple_check, owner_info, ping, random, ripple_path_find, server_definitions, server_info, server_state, simulate, transaction_entry, tx, tx_history, tx_reduce_relay, vault_info, version. subscribe, unsubscribe and path_find need a session — use the WebSocket"},{"method":"GET","path":"/submit/types","description":"Every transaction type POST /submit relays, each with an example: examples[type] = { json (the reference example, unsigned), txid (a real Mainnet transaction of that type, when the reference names one), summary }","response":"{ success, types[], examples: { [type]: { json, txid, summary } }, pool_size }"},{"method":"GET","path":"/submit/fee","description":"Current network fees","response":"{ success, base_fee, median_fee, minimum_fee, open_ledger_fee, current_ledger, current_queue_size, max_queue_size }"},{"method":"GET","path":"/submit/account/{address}/sequence","description":"Account sequence number","response":"{ success, sequence, ledger_index, balance, ownerCount, flags, regularKey, cached? }"},{"method":"GET","path":"/submit/account/{address}/inbound-tags","description":"Destination-tag usage of recent inbound payments (send-screening advisory; tagsExpected = recent deposits overwhelmingly tagged)","response":"{ success, took, account, sampleSize, tagged, taggedPct, distinctSenders, tagsExpected }"},{"method":"GET","path":"/submit/tx/{hash}","description":"Lookup a submitted XRPL transaction by hash"},{"method":"GET","path":"/submit/ledger-entry/check/{checkId}","description":"Lookup a Check ledger entry by id"}],"nft":[{"method":"GET","path":"/nft","params":{"cid":"collection id","issuer":"address","taxon":"int (NFTokenTaxon; requires issuer)","offset":"int (>=0)","limit":"int (max 200, default 20; response echoes effective limit)","sort":"created|time|rarity_rank|volume|cost.amount","order":"asc|desc"},"description":"List NFTs"},{"method":"GET","path":"/nft/{nftId}","params":{"includeCollection":"bool"},"description":"NFT by NFTokenID (64-char hex)"},{"method":"GET","path":"/nft/{nftId}/offers","description":"Buy/sell offers for NFT"},{"method":"GET","path":"/nft/history","params":{"NFTokenID":"64-char hex","account":"r-address","limit":"int (max 200; up to 50 ownership events past the limit, such as sales and transfers, are included too)","types":"comma-separated: SALE|MINT|BURN|TRANSFER|CREATE_BUY_OFFER|CANCEL_BUY_OFFER|CREATE_SELL_OFFER|CANCEL_SELL_OFFER|ACCEPT_OFFER"},"description":"NFT transaction history"},{"method":"GET","path":"/nft/history/{nftId}","params":{"limit":"int (max 100)","marker":"string"},"description":"Live NFT history"},{"method":"GET","path":"/nft/activity","params":{"cid":"collection id","limit":"int (max 200)"},"description":"Recent NFT activity feed"},{"method":"GET","path":"/nft/transactions/{hash}","description":"NFT transaction by hash"},{"method":"GET","path":"/nft/offers/buy/{nftId}","params":{"limit":"int (max 500)","marker":"string"},"description":"Live buy offers"},{"method":"GET","path":"/nft/offers/sell/{nftId}","params":{"limit":"int (max 500)","marker":"string"},"description":"Live sell offers"},{"method":"GET","path":"/nft/collections","description":"List NFT collections","params":{"sort":"vol24h|totalVol24h|volume|new|created|latest|trendingScore (or any collection field)","order":"asc|desc","interval":"24h|7d|30d (default 24h) — trending window; with sort=trendingScore ranks by the 7d/30d score","limit":"int (max 200, default 20)","offset":"int (>=0)","tag":"string","origin":"string","minOwners":"int (>=0, default 0) — only collections held by at least this many distinct owners","includeGlobalMetrics":"bool","lightweight":"bool — strip each collection to the essential discover/trending fields","skip_metrics":"bool — omit the tags/countries facets"}},{"method":"GET","path":"/nft/collections/resolve","params":{"account":"issuer r-address (alias: issuer)","taxon":"int (NFTokenTaxon)"},"description":"Resolve a collection from its XLS-20 on-chain identity (issuer account + taxon) to the full collection object incl. slug/cid. Every {slug} param on /nft/* endpoints ALSO accepts this identity directly as \"<issuer>:<taxon>\" (e.g. /nft/collections/rLyr...:1234/history)"},{"method":"GET","path":"/nft/collections/{slug}","params":{"includeNFTs":"bool","nftLimit":"int (max 100, default 20)","nftSort":"created|time|rarity_rank|volume|cost.amount","nftOrder":"asc|desc"},"description":"Collection details"},{"method":"GET","path":"/nft/collections/{slug}/nfts","description":"NFTs in collection","params":{"sort":"activity|price-low|price-high|offer-low|offer-high|minted-latest|minted-earliest|rarity-rare|rarity-common|volume-high|volume-low|recent-sale|recent-listed","listed":"true|false|xrp|non-xrp","traits":"type:value (comma-separated)","limit":"int (max 200, default 50)","offset":"int","owner":"r-address","lightweight":"bool"}},{"method":"GET","path":"/nft/collections/{slug}/related","description":"Related projects: other tokens and NFT collections that share the audience of this collection. An edge means wallets hold both and accounts post about both — it is NOT a wallet link and does not assert a shared operator (see /token/review for that).","response":"{ success, took, count (rows in this response), truncated, subject, related[] } — each row: { type: token|collection, md5|collectionId, slug, name, sharedHolders, posters, wallets[] (a sample of the wallets holding both), posts[] (posts naming both), sameProject }"},{"method":"GET","path":"/nft/collections/{slug}/traits","description":"Collection trait breakdown"},{"method":"GET","path":"/nft/collections/{slug}/traders","params":{"sort":"volume7d|all","limit":"int (max 200, default 100)"},"description":"Top traders"},{"method":"GET","path":"/nft/collections/{slug}/orderbook","params":{"limit":"int (max 200, default 50)"},"description":"Collection orderbook"},{"method":"GET","path":"/nft/collections/{slug}/metrics","description":"Collection metrics snapshot (floor + deltas, volumes, sales, owners, listings)"},{"method":"GET","path":"/nft/collections/{slug}/history","params":{"type":"SALE|MINT|BURN|TRANSFER|OFFER|LIST|DELIST|CANCEL","account":"r-address — only events where this account is buyer or seller","limit":"int (max 200, default 20)","offset":"int","since":"unix ms — only events at/after this time","sinceLedger":"ledger index — only events at/after this ledger (sorts by ledger desc)"},"description":"Collection activity history"},{"method":"GET","path":"/nft/collections/{slug}/floor/history","params":{"limit":"int (max 500, default 100)"},"description":"Floor price history"},{"method":"GET","path":"/nft/collections/{slug}/ohlc","params":{"limit":"int (max 1000, default 365; legacy daily mode)","offset":"int","resolution":"5|15|30|60|240|D|W","range":"1D|5D|1M|3M|1Y|ALL","cb":"int candle count (max 2000)"},"description":"Collection OHLC chart data"},{"method":"GET","path":"/nft/collections/{slug}/ohlc/{date}/sales","params":{"date":"YYYY-MM-DD (also accepts unix timestamp with optional interval)","interval":"string (with unix timestamp date)","limit":"int (max 100)","offset":"int","sortBy":"costXRP|time"},"description":"NFTs sold on specific date"},{"method":"GET","path":"/nft/collections/{slug}/sparkline","params":{"period":"7d|30d|365d","lightweight":"bool","maxPoints":"int (2-500, default 20)"},"description":"Collection floor price sparkline"},{"method":"GET","path":"/nft/collections/{slug}/ownership","params":{"limit":"int (max 100, default 20)"},"description":"Ownership distribution"},{"method":"GET","path":"/nft/traders/{account}/volume","description":"Trader volume stats"},{"method":"GET","path":"/nft/account/{account}/nfts","params":{"cid":"collection id","limit":"int (max 100; max 50 in search mode)","skip":"int","sortByValue":"bool","search":"string"},"description":"NFTs/collections owned with portfolio value"},{"method":"GET","path":"/nft/account/{account}/offers","params":{"type":"buy|sell","limit":"int (max 200, default 50)","skip":"int"},"description":"NFT offers owned + incoming buy/sell offers (top 500 newest owned NFTs scanned; incomingOffersTruncated flag; fraud/fraudType detection)"},{"method":"GET","path":"/nft/stats/global","description":"Global NFT market stats (same source as /nft/global-metrics)"},{"method":"GET","path":"/nft/global-metrics","description":"Global NFT metrics"},{"method":"GET","path":"/nft/analytics/market","description":"NFT market analytics","params":{"startDate":"YYYY-MM-DD","endDate":"YYYY-MM-DD","period":"24h|7d|30d|all","includeDailyHistory":"bool"}},{"method":"GET","path":"/nft/holders/{slug}","description":"Collection holder list","params":{"offset":"int","limit":"int (max 100)"}},{"method":"GET","path":"/nft/holders/address/{account}","description":"Collections/NFTs held by wallet","params":{"offset":"int","limit":"int (max 100)"}},{"method":"GET","path":"/nft/holders/{slug}/distribution","description":"Holder distribution by tier (whales/orcas/dolphins/fish/shrimp)"},{"method":"GET","path":"/nft/floor/history/{cid}","params":{"limit":"int (max 500, default 100)"},"description":"Floor history by collection ID"},{"method":"GET","path":"/nft/brokers/stats","description":"Broker fee statistics"},{"method":"GET","path":"/nft/analytics/traders","description":"NFT trader leaderboard","params":{"offset":"int","limit":"int (max 100, default 50)","sort":"volume|profit|trades|roi|winRate|combinedProfit|lastTrade|xrpBalance","order":"asc|desc","interval":"24h|7d|30d|all","minVolume":"number","minTrades":"number","minProfit":"number","minROI":"number","address":"substring","marketplace":"string (see /nft/analytics/marketplaces)"}},{"method":"GET","path":"/nft/analytics/trader/{account}","description":"Single NFT trader profile"},{"method":"GET","path":"/nft/analytics/trader/{account}/history","params":{"startDate":"YYYY-MM-DD","endDate":"YYYY-MM-DD","limit":"int (default 365; returns last N days)"},"description":"Trader daily history","notes":"total = pre-slice count"},{"method":"GET","path":"/nft/analytics/trader/{account}/collections","params":{"sort":"volume|profit|roi","order":"asc|desc","limit":"int"},"description":"Trader per-collection breakdown"},{"method":"GET","path":"/nft/analytics/trader/{account}/trades","params":{"offset":"int","limit":"int (max 200, default 50)","type":"SALE|MINT|BURN|TRANSFER|OFFER"},"description":"Trader trade history"},{"method":"GET","path":"/nft/analytics/collection/{slug}/traders","description":"Top traders for collection","params":{"limit":"int (max 200, default 50)","page":"int (1-based, default 1)","sort":"volume|sales|profit|roi|globalVolume|globalProfit|combinedProfit|holdingsCount","order":"asc|desc","interval":"24h|7d|30d|all","address":"substring filter"}},{"method":"GET","path":"/nft/analytics/rotations","description":"NFT collection rotation analytics","params":{"period":"24h|7d|30d (default 7d)","minXrp":"number (default 1)","limit":"int (max 100, default 50)"}},{"method":"GET","path":"/nft/analytics/rotations/{cid}","description":"NFT collection rotations by collection id","params":{"period":"24h|7d|30d (default 24h)","minXrp":"number (default 1)"}},{"method":"GET","path":"/nft/analytics/trader/{account}/rotations","description":"NFT trader rotations history","params":{"period":"24h|7d|30d (default 24h)"}},{"method":"GET","path":"/nft/pin/status/{hash}","description":"IPFS pin status by hash","notes":"hash must be an IPFS CID (Qm… or bafy…)"},{"method":"GET","path":"/nft/scam","description":"NFT-scam insights snapshot — totals (XRP/token drained, NFTs flagged, scam wallets), monthly timeline, top scammers/victims, tokens drained with XRP values, recent drain feed, and scamIssuersList (flat array of every flagged-issuer address for client-side filtering). For per-NFT checks, use GET /nft/:nftId — it already returns scam + scamType."},{"method":"GET","path":"/nft/collections/{slug}/listings/distribution","description":"Listed-price distribution vs floor (buckets at 1x/1.25x/1.5x/2x/3x/5x/10x floor), floor/median/avg/max"},{"method":"GET","path":"/nft/collections/{slug}/listings/history","params":{"from":"unix ms","to":"unix ms"},"description":"Daily listed-count history merged with floor/volume/sales"},{"method":"GET","path":"/nft/collections/{slug}/holders/history","params":{"from":"unix ms","to":"unix ms"},"description":"Daily holder-count history"},{"method":"GET","path":"/nft/collections/{slug}/mints","params":{"interval":"day|hour","from":"unix ms","to":"unix ms"},"description":"Mint counts over time with cumulative total"},{"method":"GET","path":"/nft/collections/sparkline/batch","params":{"slugs":"comma-separated (max 100)","period":"7d|30d|365d","maxPoints":"int (2-500)"},"description":"Batch floor sparklines for multiple collections"},{"method":"GET","path":"/nft/analytics/marketplaces","description":"Distinct NFT marketplaces with trader counts"},{"method":"POST","path":"/nft/pin","body":"{ NFTokenID? (64-hex), ipfsHash? (CID) }","description":"Pin NFT media to platform IPFS node (resolves hash from NFT URI if only NFTokenID given)"},{"method":"POST","path":"/nft/collections/{slug}/metadata","auth":"wallet signature (collection account/issuer or admin)","body":"{ description?, twitter?, website? }","description":"Edit collection metadata"}],"txExplain":[{"method":"GET","path":"/tx-explain/{hash}","description":"Human-readable transaction explanation (20 credits)","response":"{ hash, extracted, summary: { summary, keyPoints[] }, timestamp }"}],"accountTxExplain":[{"method":"GET","path":"/account-tx-explain/{account}","description":"Wallet activity analysis and profiling (20 credits)","params":{"limit":"int (200-400, default 200)"},"response":"{ account, accountInfo, period, txCount, stats, analysis: { profile, headline, keyFindings[], riskLevel }, topAddresses[], model, disclaimer, timestamp }"}],"tokenReview":[{"method":"GET","path":"/token/review/{id}","description":"Token risk assessment (score 1-10, lower = safer)","response":"{ md5, token, score, riskLevel, riskCount, positiveCount, supplyControl, creatorTokens[], timestamp }"},{"method":"GET","path":"/token/{md5}/related","description":"Related projects: other tokens and NFT collections that share the audience of this token. An edge means wallets hold both and accounts post about both — it is NOT a wallet link and does not assert a shared operator (see /token/review for that).","response":"{ success, took, count (rows in this response), truncated, subject, related[] } — each row: { type: token|collection, md5|collectionId, slug, name, sharedHolders, posters, wallets[] (a sample of the wallets holding both), posts[] (posts naming both), sameProject }"}],"traders":[{"method":"GET","path":"/traders/{account}","description":"Full trader profile","params":{"limit":"int (max 200, default 50)","offset":"int","sortTokensBy":"volume|profit|trades|roi|lastTradeDate","tokenIds":"comma-separated token md5s (filter, skips pagination)"},"response":"{ success, address, rank, totalTokensTraded, holdingValue, tokenPerformance[], recentTokens[], pagination: { totalTokens (servable, capped 500), lifetimeTokens, truncated, limit, offset, hasMore } }"},{"method":"GET","path":"/traders/token-traders/{id}","description":"Top traders for a token","params":{"interval":"24h|7d|30d|all","sortBy":"volume|pnl|trades|bought|sold|roi|wash|lastActive|unrealized|balance","limit":"int (max 500, default 50)","offset":"int","minVolume":"float (filters all-time buyVolume)","search":"address prefix"},"response":"{ success, tokenId, interval, traders[], count (rows in this response), total (matching traders), offset, sortBy, limit }"},{"method":"GET","path":"/traders/rotations","description":"Cross-token trader rotation analytics","params":{"period":"24h|7d|30d (default 24h)","minXrp":"float (default 1)","limit":"int (max 100, default 50)"}},{"method":"GET","path":"/traders/rotations/{tokenId}","description":"Trader rotations for a specific token","params":{"period":"24h|7d|30d (default 24h)","minXrp":"float (default 1)"},"notes":"tokenId must be a raw md5 (no slug resolution)"},{"method":"GET","path":"/traders/{account}/rotations","description":"Per-account token rotation flow (XRP bought/sold per token in window)","params":{"period":"24h|7d|30d (default 24h)","minXrp":"float (default 0.01)"},"response":"{ success, period, account, totalTrades, tokensTraded, rotationCount, tokens[] }"}],"analytics":[{"method":"GET","path":"/token/analytics/token/{id}","description":"Token analytics"},{"method":"GET","path":"/token/analytics/token/{id}/traders","params":{"offset":"int","limit":"int (max 100, default 50)","sort":"volume24h|volume7d|volume30d|volumeTotal|trades24h|tradesTotal|realizedPnl|unrealizedPnl|totalPnl|holding|lastTradeAt|firstTradeAt","address":"filter"},"description":"Top traders for token"},{"method":"GET","path":"/token/analytics/trader/{address}","description":"Trader cumulative stats"},{"method":"GET","path":"/token/analytics/trader/{address}/tokens","params":{"token":"token id"},"description":"Trader token-specific metrics"},{"method":"GET","path":"/token/analytics/traders","description":"All traders with cumulative stats","params":{"offset":"int","limit":"int (max 500, default 50)","sort":"volume24h|volume7d|totalVolume|totalProfit|totalTrades|avgROI|winRate|lastTradeDate|washTradingScore|activityScore (unknown values fall back to volume24h)","order":"asc|desc","period":"24h|7d|30d|all","startDate":"ISO","endDate":"ISO","minVolume":"float (filters volume24h)","minTrades":"int","minProfit":"float","minROI":"float","minTokens":"int","address":"partial match","includeAMM":"bool (default true)","sourceTag":"int","compact":"bool"}},{"method":"GET","path":"/token/analytics/market","description":"Daily market metrics","params":{"startDate":"ISO (required)","endDate":"ISO"}},{"method":"GET","path":"/token/analytics/trader/{address}/history","params":{"startDate":"ISO","endDate":"ISO","page":"int (1-based, default 1; page 1 = most recent window)","limit":"int (max 500, default 100)"},"description":"Trader volume history","notes":"Returns a bare JSON array"},{"method":"GET","path":"/token/analytics/trader/{address}/trades","params":{"startDate":"ISO","endDate":"ISO","page":"int (1-based, default 1; page 1 = most recent window)","limit":"int (max 500, default 100)"},"description":"Trader trade history","notes":"Returns a bare JSON array"},{"method":"GET","path":"/token/analytics/traders/summary","description":"Trader balance snapshots summary"},{"method":"GET","path":"/token/analytics/sources","description":"Distinct trade sourceTags with trader counts and volume totals"}],"tokenFlow":[{"method":"GET","path":"/token/flow/{id}","description":"Creator allocation and distribution analysis (precomputed)","response":"{ success, token, summary, linkedAddresses[], exchangeBreakdown[], graph: { nodes[], edges[] }, processedAt, lastLedger } or { success, pending: true }","notes":"{id} must be a raw md5 (no slug resolution); serves a precomputed document, no query params. summary.creatorAllocated/Delivered/Locked* describe the creator's own cut (escrow / check / issuer payment) and where it went; their percentages are measured against circulating supply PLUS anything still locked in escrow, since escrowed tokens sit outside every trustline. summary.placed* account for everything the creator passed on and sum to totalTransferred exactly: Held, Sold, Pooled, Burned, ToExchange, Returned (back to the creator), plus two residuals that are never merged into the others - Untraced (a hop we do not follow) and Unscanned (a wallet whose history exceeded the page budget)."}],"news":[{"method":"GET","path":"/news","auth":"Developer tier+ API key","params":{"offset":"int (clamped >= 0)","limit":"int (1-100, default 20)","source":"filter (approved sources only)","date":"YYYY-MM-DD (single-day filter)"},"description":"Latest XRP news with sentiment","response":"{ sentiment: { 24h, 7d, 30d, all }, sources[], data[], pagination: { offset, limit, total, totalPages } }"},{"method":"GET","path":"/news/search","auth":"Developer tier+ API key","params":{"q":"string (required)","offset":"int (clamped >= 0)","limit":"int (1-100, default 20)"},"description":"Search news articles","response":"{ query, sentiment, data[], pagination }"},{"method":"GET","path":"/news/unapproved-sources","auth":"Developer tier+ API key","params":{"offset":"int","limit":"int (1-100, default 20)"},"description":"News sources pending approval"},{"method":"GET","path":"/news/sentiment-chart","auth":"Developer tier+ API key","params":{"days":"int (1-365, default 30)"},"description":"Historical sentiment analysis chart","response":"{ labels[], bullish[], bearish[], neutral[], updated }"}],"mentions":[{"method":"GET","path":"/mentions/search","auth":"Developer tier+ API key","params":{"q":"string (full-text search on tweet content, max 200 chars)","author":"string (username prefix match, case-insensitive)","token":"string (token name, ticker, or md5)","from":"ISO date or unix ms (lower bound on tweetCreatedAt)","to":"ISO date or unix ms (upper bound)","minLikes":"int","minViews":"int","excludeSpam":"bool (default true; pass false to include spam-flagged tweets)","excludeImpostors":"bool (filter out impostor accounts)","sort":"recent|engagement|views|relevance (relevance requires q)","limit":"int (max 100, default 20)","offset":"int (default 0)"},"description":"Agent-friendly search across X/Twitter mentions with full-text + filters. Returns enriched tweets with token name, spam/impostor flags."},{"method":"GET","path":"/mentions/feed","auth":"Developer tier+ API key","params":{"limit":"int (max 100, default 20)","offset":"int (clamped >= 0)","period":"1d|7d|30d|90d|all","author":"string","q":"string (full-text)","excludeSpam":"bool (default true — spam rows removed in-query; pagination and count share the filtered row space; pass false to include)","excludeImpostors":"bool (impostor rows removed in-query; also filters topAuthors)","minViews":"int","minLikes":"int","sort":"recent|engagement|views|likes (default recent)"},"description":"Global social feed with trending tokens, top authors, activity chart, and impostor list"},{"method":"GET","path":"/mentions/{md5}","auth":"Developer tier+ API key","params":{"period":"1d|7d|30d|90d|all","author":"string","limit":"int (max 100, default 20)","offset":"int (clamped >= 0)"},"description":"Per-token mention feed with stats, top mentioners, and activity chart"},{"method":"GET","path":"/mentions/spaces","auth":"Developer tier+ API key","params":{"limit":"int (hosts, max 500, default 200)","offset":"int","spacesLimit":"int (spaces per host, max 100, default 10)"},"description":"X Space hosts with full history and inferred schedule (days/hour UTC). Returns all known space hosts sorted by most recent activity."},{"method":"GET","path":"/mentions/openapi.json","auth":"Developer tier+ API key","description":"OpenAPI 3.0 spec for the mentions endpoints (agent/MCP discoverable)"},{"method":"GET","path":"/mentions/timeline","params":{"limit":"int (max 100, default 50)","offset":"int","period":"1d|7d|30d|90d|all (default 30d)","author":"string","sort":"recent|engagement|views|likes"},"description":"Full timeline of tracked influencer tweets (not just token matches)","response":"{ mentions[], count, period }"},{"method":"GET","path":"/mentions/x-search","params":{"q":"string (required, min 3 chars)","limit":"int (max 20, default 10)"},"description":"Live X/Twitter search via scraper (503 if scraper unavailable)","response":"{ query, count, tweets[] }"},{"method":"GET","path":"/mentions/grok-pulse","params":{"topic":"string (optional)"},"description":"Grok-generated XRPL insight topics with sentiment"},{"method":"GET","path":"/mentions/profile/{username}","description":"Latest X profile snapshot + change history for a handle","response":"{ username, latest, updates, followersDelta, samples }"}],"launch":[{"method":"POST","path":"/launch-token","body":"{ currencyCode, tokenSupply, ammXrpAmount, name, origin, user, antiSnipe?, shield? (default true), imageData?, domain?, description?, telegram?, twitter?, userCheckAmount?, platformRetentionPercent?, ammTradingFee?, bundleRecipients?[] }","description":"Create new token with AMM"},{"method":"GET","path":"/launch-token/status/{sessionId}","description":"Launch session status"},{"method":"GET","path":"/launch-token/queue-status/{sessionId}","description":"Queue position status"},{"method":"POST","path":"/launch-token/authorize","body":"{ sessionId, userAddress }","description":"Authorize trustline (anti-snipe)"},{"method":"GET","path":"/launch-token/auth-info/{issuer}/{currency}","description":"Token authorization info"},{"method":"GET","path":"/launch-token/check-auth/{issuer}/{currency}/{address}","description":"Check if address is authorized"},{"method":"GET","path":"/launch-token/calculate-funding","params":{"amm_xrp_amount":"float (1-100000000000)","anti_snipe":"bool","token_supply":"float (positive)","user_check_amount":"float (>=0)","bundle_count":"int (max 10)","bundle_percent":"float (max 50 per recipient)","vesting_tranches":"int (0-12)","platform_retention_percent":"float (0-10)"},"description":"Calculate required XRP funding (400 on invalid params)"},{"method":"GET","path":"/launch-token/my-launches","auth":"your own API key (the shared browser key gets 403)","params":{"sessionId":"string (optional)","start":"int (default 0)","limit":"int (default 50, max 100)"},"description":"Launches created with your API key, with total count (a wallet lists its own with /launch-token/my-launches-wallet)"},{"method":"POST","path":"/launch-token/{sessionId}/image","body":"{ imageData }","description":"Upload token image (base64, max 500KB)"},{"method":"GET","path":"/launch-token/my-launches-wallet","auth":"wallet signature","params":{"start":"int (default 0)","limit":"int (default 20, max 100)"},"description":"Token launches by wallet with total count"},{"method":"GET","path":"/launch-token/vesting-by-token/{issuer}/{currency}","description":"Vesting schedule for a launched token (response includes truncated flag when escrow list is incomplete)"}],"presale":[{"method":"GET","path":"/presale","params":{"status":"'all' to include non-open"},"description":"List presales (open by default)"},{"method":"POST","path":"/presale","body":"{ currencyCode, name, origin, tokenSupply, goalXrp, softCapXrp, durationHours, tradingFee, creatorPct?, creatorVestDays?, buyerUnlockPct?, buyerVestDays?, imageData?, description?, twitter?, telegram?, website? }","description":"Create a presale (issuer + sale wallets are provisioned server-side)"},{"method":"POST","path":"/presale/{id}/join","body":"{ address, amountXrp }","description":"Join — checks the wallet can fund the escrow above its reserve, returns the conditional EscrowCreate to sign; an unconfirmed slot may join again, an escrow that already landed is confirmed instead"},{"method":"POST","path":"/presale/{id}/confirm","body":"{ address, txHash }","description":"Confirm a signed escrow contribution"},{"method":"POST","path":"/presale/{id}/finalize","description":"Finalize after deadline/goal: capture escrows, deliver claim Checks, seed AMM, blackhole wallets"},{"method":"GET","path":"/presale/{id}","description":"Presale status (public view: raise, socials, confirmed contributors, vesting; refreshes claim states on success)"},{"method":"GET","path":"/presale/{id}/claim-info","params":{"address":"contributor r-address"},"description":"Per-buyer claim (CheckCash) or refund (EscrowCancel) transaction to sign"},{"method":"GET","path":"/presale/{id}/refund-info","params":{"address":"contributor r-address"},"description":"Alias of claim-info"}],"xaman":[{"method":"POST","path":"/xaman/payload","auth":"xrpl.to platform key (our own surfaces only; 403 otherwise)","body":"{ txjson: { TransactionType, ... }, options?: { submit?, expire? (min, 1-60), return_url?: { web?, app? }, multisign?, pathfinding? }, custom_meta?: { identifier?, instruction? } }","description":"Create a Xaman sign request — returns { uuid, next.always (open in Xaman), refs.qr_png, refs.websocket_status }. xrpl.to surfaces only (platform key); user_token is refused"},{"method":"GET","path":"/xaman/payload/{uuid}","description":"Sign request status (live, never cached): meta.signed/expired/cancelled, response.account (SignIn answer), response.txid (submitted transaction)"},{"method":"DELETE","path":"/xaman/payload/{uuid}","auth":"xrpl.to platform key (our own surfaces only; 403 otherwise)","description":"Cancel an unsigned sign request (xrpl.to surfaces only)"}],"referral":[{"method":"GET","path":"/referral/{address}","description":"Get soldier profile"},{"method":"GET","path":"/referral/{address}/stats","description":"Badge progress and tier stats"},{"method":"GET","path":"/referral/leaderboard/{type}","params":{"type":"recruits|streak|season|whales","limit":"int (default 100, max 500)","offset":"int (default 0)"},"description":"Leaderboard"},{"method":"GET","path":"/referral/meta/tiers","description":"Tier definitions"},{"method":"GET","path":"/referral/meta/badges","description":"Badge definitions"},{"method":"GET","path":"/referral/meta/missions","description":"Mission quest chains"},{"method":"GET","path":"/referral/meta/season","description":"Seasonal leaderboard rewards"},{"method":"GET","path":"/referral/{address}/earnings","description":"Referral earnings breakdown for an address"},{"method":"GET","path":"/referral/{address}/fees","params":{"limit":"int (default 50, max 100)","offset":"int (default 0)"},"description":"Referral fee history; response includes asReferrerTotal/asRecruitTotal for paging"},{"method":"GET","path":"/referral/resolve/{code}","description":"Resolve a referral code to validity/owner"}],"promotion":[{"method":"GET","path":"/promotion/pool/{md5}","description":"Get promotion pool info (status, amounts, expiry)"},{"method":"GET","path":"/promotion/reward/{md5}/{account}","description":"Get reward status for a token"},{"method":"GET","path":"/promotion/leaderboard/{md5}","params":{"offset":"int (default 0)","limit":"int (default 20, max 1000)"},"description":"Per-token promoter leaderboard"},{"method":"GET","path":"/promotion/profile/{account}","description":"Global promotion stats"},{"method":"GET","path":"/promotion/tiers","description":"Promoter tier metadata"},{"method":"POST","path":"/promotion/claim","body":"{ md5, account }","description":"Claim earned promotion rewards (paid in XRP)"}],"bridge":[{"method":"GET","path":"/bridge/currencies","description":"List available exchange currencies"},{"method":"GET","path":"/bridge/estimate","params":{"fromCurrency":"string","toCurrency":"string","fromAmount":"string","fromNetwork":"string","toNetwork":"string"},"description":"Get exchange rate estimate"},{"method":"GET","path":"/bridge/min-amount","params":{"fromCurrency":"string","toCurrency":"string"},"description":"Get minimum exchange amount"},{"method":"POST","path":"/bridge/create","body":"{ fromCurrency, toCurrency, fromAmount, address, refundAddress? }","description":"Create exchange"},{"method":"GET","path":"/bridge/status","params":{"id":"string"},"description":"Get exchange status"},{"method":"GET","path":"/bridge/validate-address","params":{"currency":"string","address":"string"},"description":"Validate destination address"}],"verify":[{"method":"GET","path":"/verify/pricing","description":"Verification tier pricing"},{"method":"GET","path":"/verify/stripe/status/{sessionId}","params":{"id":"string (required — token md5 or collection id)"},"description":"Check Stripe verification payment status; fulfills if webhook was missed"},{"method":"POST","path":"/verify/request","body":"{ type, id, tier, account }","description":"Create XRP invoice for token/collection verification"},{"method":"POST","path":"/verify/confirm","body":"{ invoiceId | txHash }","description":"Confirm verification payment"},{"method":"POST","path":"/verify/stripe/checkout","body":"{ type, id, tier, account }","description":"Stripe checkout for verification"}],"tweetVerify":[{"method":"GET","path":"/tweet/token/{md5}","params":{"limit":"int (max 1000, default 20)","offset":"int (clamped >= 0)"},"description":"Tweet verifications for a token (md5) or NFT collection (slug)"},{"method":"GET","path":"/tweet/account/{account}","params":{"limit":"int (max 1000, default 20)","offset":"int (clamped >= 0)"},"description":"Tweet verifications by account"},{"method":"POST","path":"/tweet/verify","auth":"wallet signature","body":"{ md5 (token md5 or NFT slug), tweetUrl, account, type?: token|nft }","description":"Verify a promotional tweet and credit the wallet. One verification per wallet every 2 hours, up to 6 tokens per X account per UTC day, and a tweet earns from one pool."}],"boost":[{"method":"GET","path":"/boost/quote/{md5}","params":{"rank":"int"},"description":"Get quote for boosting a token"},{"method":"POST","path":"/boost/purchase","body":"{ md5, boostAmount, payerAddress }","description":"Create boost payment request"},{"method":"GET","path":"/boost/verify/{invoiceId}","description":"Verify payment and apply boost"},{"method":"POST","path":"/boost/stripe","body":"{ md5, packId, payerAddress }","description":"Create Stripe checkout for boost"},{"method":"GET","path":"/boost/stripe/{sessionId}","params":{"wallet":"r-address (required, must match invoice payer)"},"description":"Check Stripe boost payment status"},{"method":"GET","path":"/boost/active","auth":"X-Admin-Key","description":"Currently active token boosts (admin only)"},{"method":"GET","path":"/boost/nft/quote/{slug}","description":"Quote price for boosting an NFT collection (slug also accepts \"<issuer>:<taxon>\")"},{"method":"POST","path":"/boost/nft/purchase","body":"{ slug, boostAmount, ... }","description":"Initiate XRP-paid NFT collection boost"},{"method":"GET","path":"/boost/nft/verify/{invoiceId}","description":"Verify NFT boost payment"},{"method":"POST","path":"/boost/nft/stripe","body":"{ slug, boostAmount }","description":"Initiate Stripe-paid NFT collection boost"},{"method":"GET","path":"/boost/nft/stripe/{sessionId}","params":{"wallet":"r-address (required, must match invoice payer)"},"description":"Check Stripe checkout status for NFT boost"}],"scams":[{"method":"GET","path":"/scams/addresses","params":{"category":"wallet_drainer|dust_spam|phishing|impersonation|fake_airdrop|other (optional)"},"description":"THE canonical scam blocklist: top-level addresses[] is the deduped union of every blocked account (drainers, dust/token spam, phishing, impersonation, fake airdrops, NFT-scam issuers). Check a Destination/counterparty against it BEFORE a user signs. Real-time, never cached (Cache-Control: no-store) — poll every ~5s. Per-category sections (nftPhishing, paymentDrain) are additive metadata and may overlap; addresses is deduped."},{"method":"GET","path":"/scams","description":"Full scam report with abuse statistics"},{"method":"GET","path":"/scams/tokens","params":{"issuer":"address (REQUIRED)","page":"int (default 1)","limit":"int (default 50, max 100)"},"description":"Tokens issued by one named issuer. issuer is required — this endpoint lists an issuer's tokens, it does not classify them. For a scam verdict use /scams/addresses or /scams/check/{account}."},{"method":"GET","path":"/scams/domains","description":"Known scam domains with registrar info"},{"method":"GET","path":"/scams/nft","description":"NFT scam accounts and recent sales"},{"method":"GET","path":"/scams/check/{account}","description":"Check if account is a known scam. is_scam is true ONLY for accounts on the verified blocklist or confirmed scam NFT issuers — never inferred from an account's token names or token count. Also returns first_seen/age_seconds/new_account (advisory counterparty freshness, independent of is_scam)"},{"method":"GET","path":"/scams/report-scam","params":{"page":"int (default 1)","limit":"int (default 50, max 100)","status":"pending|reviewed|confirmed|dismissed"},"description":"List community scam reports"},{"method":"GET","path":"/scams/report/{domain}","description":"Confirmations for a reported domain"},{"method":"POST","path":"/scams/report","body":"{ domain, ... }","description":"Report a scam domain"}],"creatorActivity":[{"method":"GET","path":"/creator-activity/{id}","description":"Token creator trading activity","params":{"id":"md5 or creator r-address","since":"unix ms — return events strictly newer (exclusive)","before":"unix ms — return events strictly older (exclusive cursor)","limit":"int (max 200)","side":"buy|sell","type":"event type","stream":"bool"}},{"method":"GET","path":"/creator-activity/{id}/receiver/{address}","description":"Creator activity filtered by recipient address"},{"method":"GET","path":"/whale-activity/feed","description":"Global whale tape — the newest notable trades across ALL tokens. `tokens` maps each event md5 to its display identity (name, user, slug, verified)","params":{"limit":"int (default 30, max 100)","since":"unix ms — return events strictly newer (exclusive)","minXrp":"float — minimum XRP size","side":"buy|sell"},"response":"{ success, took, count, events[], tokens{} }"},{"method":"GET","path":"/whale-activity/{id}","description":"Whale social-proof trade events — top holders of major tokens, smart money, named accounts, whale-sized and fresh-wallet trades on this token","params":{"id":"md5 or trader r-address","since":"unix ms — return events strictly newer (exclusive)","limit":"int (max 200)"}}],"platformStats":[{"method":"GET","path":"/platform-stats","params":{"period":"24h|7d|30d (default: 24h)"},"description":"Aggregated trading stats grouped by platform key (numeric SourceTag, or canonical name for memo-identified platforms like SPYDEX)","response":"{ success, took, period, totals, platforms[]: { sourceTag, name, slug, txCount, uaw, uniqueTraders, volume, buyVolumeXrp, sellVolumeXrp, pctVolume, pctUAW, pctTx, ... } }"},{"method":"GET","path":"/platform-stats/detail/{sourceTag}","params":{"sourceTag":"numeric tag or platform slug","period":"24h|7d|30d (default: 7d)","limit":"int (default 50, clamped 1-200)"},"description":"Top tokens traded via a single platform; summary covers ALL tokens for the platform/period, not just returned rows"},{"method":"GET","path":"/platform-stats/hourly/{sourceTag}","params":{"sourceTag":"numeric tag or platform slug","period":"24h|7d|30d (default: 24h)"},"description":"Hourly breakdown for a single platform"}],"platformReport":[{"method":"GET","path":"/platform-report","params":{"date":"YYYY-MM-DD (default: today)"},"description":"Full daily platform report","notes":"404 if no report exists for the date (today's report generates at 00:05 UTC)"},{"method":"GET","path":"/platform-report/dates","params":{"offset":"int (default 0)","limit":"int (default 90, max 365)"},"description":"Daily report dates with metadata, newest first","response":"[{ date, generatedAt, durationMs, errorCount }]"}],"webSearch":[{"method":"GET","path":"/web-search","description":"Web search via SearXNG","auth":"API key required (401 without)","params":{"q":"string (required)","categories":"general|images|videos|news|...","engines":"google|brave|duckduckgo|...","language":"en|de|fr|...","pageno":"int"},"response":"{ query, number_of_results, results[], answers[], infoboxes[], suggestions[], cached }"}],"websocket":[{"endpoint":"wss://api.xrpl.to/ws/sync/","description":"Multi-token market sync (handshake first, token data via updates)","messages":"subscribe { tokens: [md5,...] } OR { filter: { minVolume?, tags?, topN? (max 500) } }, optionally + { lightweight: true (strip tokens to the ~30 tokenFields essentials), skip_metrics: true (omit exch/H24/global from updates), snapshot: false (skip the initial snapshot frame) }; addTokens { tokens }, removeTokens { tokens }, unsubscribe, getSubscriptions, checkSeq { lastSeq }, resync, auth { apiKey }","response":"initial: { res, initial: true, connectionInfo, tier, session, total, exch, H24, global, tags, tokens: [] }. subscribe ack: { type: \"subscribed\", mode, ... } — in tokens mode its tokens[] is the ECHOED md5 list, not token data. Right after the ack (both modes) comes a snapshot frame { res, snapshot: true, seq, time, count, tokens[] } with the current state of the subscribed set (cap 100 tokens; same lightweight shaping as updates; suppress with snapshot: false). updates: { res, seq, prevSeq, time, session, total, exch, H24, global, tokens[] } — updates carry NO type field; identify them by seq/prevSeq (also your gap detector); tokens[] may be EMPTY (heartbeat/envelope tick, every ~10th seq during quiet periods). lightweight/skip_metrics shrink updates per the subscribe flags"},{"endpoint":"wss://api.xrpl.to/ws/token/{md5}","description":"Single token real-time updates","query":{"fields":"ticker|price|trading|full|all or comma-separated field list","delta":"true|1 — only changed fields in updates"},"messages":"setFields { fields }, setDelta { enabled: bool }, resync, auth { apiKey }","response":"{ res, type: \"initial\", seq, time, fieldPreset, fieldCount, deltaMode, exch, H24, global, token }"},{"endpoint":"wss://api.xrpl.to/ws/ohlc/{md5}","description":"OHLC candlestick streaming","query":{"interval":"1m|5m|15m|30m|1h|2h|4h|1d|1w (default: 5m)","vs_currency":"XRP|USD|EUR|JPY|CNH (default: USD)","snapshot":"0 to skip the initial frame (default: 1)"},"response":"initial: { type, md5, interval, vs_currency, count, ohlc: [[time, o, h, l, c, volume]] } — last 100 intervals (omitted with snapshot=0); updates: { e: \"kline\", E, s, k: { t, T, i, o, h, l, c, v, x } }","notes":"Max 10 subscriptions per connection"},{"endpoint":"wss://api.xrpl.to/ws/history/{md5}","description":"Trade history streaming","query":{"limit":"int 1-100 (default: 20, initial snapshot rows)","type":"trades|liquidity|all (default: trades)","pair_type":"xrp — only fills with an XRP side"},"response":"initial: { type, md5, count, trades[] }; updates: { e: \"trades\", E, s, trades[] } (filters apply per-socket)"},{"endpoint":"wss://api.xrpl.to/ws/holders/{id}","description":"Token holder richlist streaming (id = token md5)","query":{"limit":"int 1-100 (default: 50) — honored per-socket in snapshot and broadcasts"},"response":"initial: { type, md5, total, summary: { top10Hold, top20Hold, top50Hold, top100Hold }, holders[] }; updates: { e: \"update\", E, s, total, holders[] }"},{"endpoint":"wss://api.xrpl.to/ws/orderbook","description":"DEX orderbook depth streaming","query":{"base_currency":"currency code/hex or XRP (required)","base_issuer":"issuer address (omit for XRP)","quote_currency":"currency code/hex or XRP (required)","quote_issuer":"issuer address (omit for XRP)","limit":"int 1-100 (default: 20, depth per side)"},"response":"initial: { type: \"snapshot\", pair, bids[], asks[], ledger }; updates: { e: \"depth\", E, s, b[], a[], l }","notes":"Params are base_currency/quote_currency — the REST-style base={md5} form is NOT supported and closes the socket (4020)"},{"endpoint":"wss://api.xrpl.to/ws/ledger","description":"Ledger close stream","response":"initial: last closed ledger; then { e: \"ledger\", E, ledger_index, ledger_hash, ledger_time, close_time, txn_count, validated, reserve_base, reserve_inc, fee_base, fee_ref } per close"},{"endpoint":"wss://api.xrpl.to/ws/trustlines/{account}","description":"Account trustlines streaming","query":{"page":"int >= 0 (default: 0)","limit":"int 1-50 (default: 10)","format":"default|raw|full","sort_by_value":"true — rank by XRP value"},"messages":"setParams { page?, limit?, format?, sort_by_value? } (strict integer validation; ack: { type: \"paramsUpdated\", params }); resync (max 1 per 5s)","response":"{ account, accountActive, accountData, total, page, limit, lines[] } as type:\"initial\" then e:\"update\" (first frame may be either). With sort_by_value only the first 1000 trustlines are ranked: total <= 1000, totalLines = real count, truncated: true"},{"endpoint":"wss://api.xrpl.to/ws/news","description":"Real-time news feed","messages":"filter { sentiment: \"Bullish\"|\"Bearish\"|\"Neutral\"|null }","response":"initial: { type, data: [10 latest] }; updates: { e: \"news\", E, data }"},{"endpoint":"wss://api.xrpl.to/ws/account/balance/{account}","description":"Account XRP balance streaming","response":"initial adds inception/parent/domain/name; updates: { e: \"balance\", E, account, balance, total, balanceDrops, spendableDrops, reserve, ownerCount, sequence, flags }"},{"endpoint":"wss://api.xrpl.to/ws/account/balance/pair/{account}","description":"Token pair balance streaming","query":{"curr1":"currency (XRP allowed)","issuer1":"issuer (required even for XRP)","curr2":"currency","issuer2":"issuer"},"notes":"All four params required or socket closes (4021)"},{"endpoint":"wss://api.xrpl.to/ws/account/offers/{account}","description":"Open DEX offers streaming","query":{"pair":"pair hash","md5":"token id (32-hex) — filter offers to one token","page":"int >= 0 (default: 0)","limit":"int 1-50 (default: 10)"}},{"endpoint":"wss://api.xrpl.to/ws/amm/info","description":"Live AMM pool info streaming (5s poll)","query":{"amm_account":"AMM account address","asset":"\"XRP\", token id, or {\"currency\",\"issuer\"} JSON","asset2":"same forms as asset"},"notes":"Provide amm_account OR both asset and asset2; response: initial { type, amm } then { e: \"amm\", E, amm } on change"},{"endpoint":"wss://api.xrpl.to/ws/account/watch/{account}","description":"Live account activity feed (parsed tx events)","query":{"history":"int 0-25 (default: 10) — recent txs replayed with historical: true"},"response":"{ type: \"subscribed\", account } then per-tx event payloads"},{"endpoint":"wss://api.xrpl.to/ws/account/tx/{account}","description":"Raw account transaction stream (same shape as GET /account/tx)","query":{"history":"int 0-50 (default: 0)"},"response":"{ type: \"subscribed\", account }; { e: \"history\", txs[] } if history > 0; then live { ...event, tx } per transaction"},{"endpoint":"wss://api.xrpl.to/ws/creator/{identifier}","description":"Creator activity stream (identifier = token md5 or creator address)","response":"initial: { type, identifier, count, events[] }; live: { type: \"activity\", h (tx hash), r (engine result — anything but tesSUCCESS is a rejected attempt), t, s (side), y (tx type), x (xrp), a (token amount), c (currency), token, creator?, fa? }"},{"endpoint":"wss://api.xrpl.to/ws/social","description":"X/Twitter mentions feed","query":{"md5":"token id (omit for global feed)"},"messages":"subscribe { md5 } to switch scope","response":"{ type: \"subscribed\", md5|\"global\" }, 2-min backfill { e: \"mention\", backfill: true }, live { e: \"mention\" } and sentiment patches { e: \"sentiment\" }"}],"websocketNotes":{"heartbeat":"Send { type: \"ping\" } to receive { type: \"pong\", time }","compression":"All endpoints support permessage-deflate","reconnection":"Implement exponential backoff","malformedMessages":"Non-JSON frames on /ws/sync get an error frame { error, errorCode: 4026 } (connection stays open)","closeCodes":"4010 rate limit, 4011 max connections/subscriptions, 4012 message size, 4020-4025 invalid params, 4029 connection limit reached ({ error } sent before close)"},"keys":[{"method":"POST","path":"/keys","description":"Create new API key (1 active key on free tier, 5 on paid tiers)","headers":"X-Wallet, X-Signature, X-Timestamp, X-Public-Key","body":"{ name?: string, project: { name, url: \"https://…\", category: \"wallet|explorer|trading_bot|analytics|ai_agent|other\", description, expectedDaily: \"lt1k|1k-10k|10k-100k|100k+\", contact?: \"email or @handle\" }, agreePolicy: true }","response":"{ success, apiKey, keyPrefix, wallet, credits, project }","notes":"Requires wallet signature. Save the API key immediately - it cannot be retrieved later. The project block and agreePolicy record which project the key serves and that it accepted the usage policy (attribution, no redistribution); the agreement is stamped server-side. Legacy name-only bodies are still accepted for now."},{"method":"GET","path":"/keys/{wallet}","auth":"wallet signature","description":"List API keys for wallet"},{"method":"DELETE","path":"/keys/{wallet}/{id}","auth":"wallet signature","description":"Revoke API key (first call revokes; calling again on a revoked key permanently deletes it)","headers":"X-Wallet, X-Signature, X-Timestamp, X-Public-Key"},{"method":"PUT","path":"/keys/{wallet}/{id}","auth":"wallet signature","body":"{ name: string (1-64) }","description":"Rename an active API key (metadata only)","headers":"X-Wallet, X-Signature, X-Timestamp, X-Public-Key"},{"method":"GET","path":"/keys/{wallet}/credits","auth":"wallet signature","description":"Remaining credits and billing info"},{"method":"GET","path":"/keys/{wallet}/usage","auth":"wallet signature","description":"Usage breakdown by key and endpoint"},{"method":"GET","path":"/keys/{wallet}/subscription","auth":"wallet signature","description":"Subscription details, available upgrades and partnerRequest { status: pending|approved|declined, creditUrl, requestedAt, decidedAt, reason } (null when never requested). billingCycle.end is the paid term end: 30 days for a monthly purchase, 365 for yearly. Buying the same tier again before it ends extends the term; an ended term downgrades the wallet and its keys to Free."},{"method":"POST","path":"/keys/{wallet}/partner-request","auth":"wallet signature","description":"Apply for the free Partner tier (see usagePolicy.partner)","body":"{ creditUrl: \"https://… page where the Data by xrpl.to credit is visible\", contact: \"email or @handle\" }","notes":"Needs an active key created with project details that has made real requests; one open request per wallet (409 while pending). A person opens creditUrl, checks the credit, and approving upgrades every active key on the wallet. Result appears in GET /keys/{wallet}/subscription."},{"method":"GET","path":"/keys/tiers","description":"Available API tiers with live XRP pricing. Developer, Business and Professional are bought for a term (30 days monthly, 365 yearly) and renew by buying the same tier again; Partner is by application."},{"method":"GET","path":"/keys/packages","description":"Credit top-up packages with pricing"},{"method":"GET","path":"/keys/costs","description":"Per-endpoint credit costs"},{"method":"POST","path":"/keys/purchase","description":"Create XRP payment request","body":"{ wallet, type: \"credits\"|\"tier\", package?: \"starter|standard|bulk|mega\", tier?: \"developer|business|professional\", billing?: \"monthly|yearly\" }","notes":"Invoice expires in 30 minutes. After payment, call POST /keys/verify-payment with the tx hash."},{"method":"POST","path":"/keys/verify-payment","body":"{ txHash: \"64-char hex\" }","description":"Verify XRP payment and apply credits/tier"},{"method":"GET","path":"/keys/xrp/status/{txHash}","description":"Check XRP payment status"},{"method":"POST","path":"/keys/stripe/checkout","body":"{ wallet, type, package?, tier?, billing? }","description":"Create Stripe checkout session"},{"method":"GET","path":"/keys/stripe/status/{sessionId}","params":{"wallet":"XRPL address that created the session (required)"},"description":"Check Stripe payment status"},{"method":"GET","path":"/keys/payment/{txHash}","auth":"wallet signature","description":"Look up processed payment by tx hash"},{"method":"GET","path":"/keys/{wallet}/logs","auth":"wallet signature","description":"Recent API request logs for a wallet"},{"method":"GET","path":"/keys/payments/{wallet}","auth":"wallet signature","params":{"limit":"int (max 200, default 200)","offset":"int"},"description":"Payment history for wallet","response":"{ success, total, payments[] }"},{"method":"GET","path":"/keys/invoices/{paymentId}","auth":"wallet signature","description":"Invoice detail for a payment (sequential INV-YYYY-NNNNN number assigned on first fetch)"}],"user":[{"method":"GET","path":"/user/tiers","description":"User tiers with pricing (member, vip, nova, diamond, verified)"},{"method":"GET","path":"/user/{account}","description":"Get user profile"},{"method":"POST","path":"/user/{account}","auth":"wallet signature","body":"{ username?, referredBy? }","description":"Create user profile"},{"method":"GET","path":"/user/{account}/perks","description":"Resolved perks (tier + roles merged)"},{"method":"GET","path":"/user/{account}/badges","description":"All unlocked badges"},{"method":"GET","path":"/account/{address}/admin","auth":"X-Admin-Key or ADMIN_WALLETS signature","description":"Full account doc split into editable editorial fields vs read-only ledger/derived state, plus the manualFields lock list, the lockedByChain list (fields tx derives from the ledger) and a derived block (decoded on-chain Domain, attributed domain, desc kind)","response":"{ success, took, account, editable, readOnly, manualFields, lockedByChain, fieldOwners, derived }"},{"method":"PATCH","path":"/account/{address}/admin","auth":"X-Admin-Key or ADMIN_WALLETS signature","body":"{ name?, desc?, domain?, twitter?, adminVerified?, verifiedLogo?, verifiedTagRequired? }","description":"Edit editorial fields. Each written field is added to manualFields so the owning background service skips it (tokendata + grok-whale-labeler honour this) — null/empty unsets. Raw ledger fields and scam flags are not editable; `domain` returns 409 when the account sets an on-chain Domain, because tx re-derives it from the ledger."},{"method":"POST","path":"/account/{address}/logo","auth":"X-Admin-Key or ADMIN_WALLETS signature","body":"{ imageData: base64 (PNG/JPEG/GIF/WebP, ~650KB) }","description":"Upload an account logo; served self-hosted at GET /api/account-thumb/{address}"},{"method":"GET","path":"/account-thumb/{address}","description":"Admin-set account logo image bytes (404 when unset)","notes":"Needs an API key (401 without one): send X-Api-Key, or ?apiKey= where headers cannot be sent."},{"method":"POST","path":"/account/resolve","body":"{ addresses: string[] (max 100) }","description":"Batch-resolve admin-verified destination identity (name, logo, tagRequired). Only verified accounts are returned — absence means unknown, which is the safety signal.","response":"{ success, took, count, accounts[] }"},{"method":"PUT","path":"/account/{address}/verified","auth":"X-Admin-Key","body":"{ name (1-60), logo (image id), tagRequired? }","description":"Set verified destination identity (admin only — never user-settable)"},{"method":"DELETE","path":"/account/{address}/verified","auth":"X-Admin-Key","description":"Remove verified destination identity"},{"method":"GET","path":"/user/{account}/labels","auth":"wallet signature (owner only)","description":"Get your own wallet labels — private data, owner-authenticated"},{"method":"GET","path":"/user/{account}/nfts","params":{"limit":"int (max 100)","offset":"int"},"description":"NFTs owned (with thumbnails)","response":"{ success, count, total, nfts[] }"},{"method":"GET","path":"/user/badges/meta","description":"Badge system metadata"},{"method":"GET","path":"/user/badges/{badge}/holders","params":{"limit":"int (max 500)","offset":"int"},"description":"Users holding a specific badge","response":"{ success, badge, count, total, holders[] }"},{"method":"PUT","path":"/user/{account}","auth":"wallet signature","body":"{ username? }","description":"Update username (VIP+ required to change an existing one; tier field is admin-only)"},{"method":"PUT","path":"/user/{account}/display-badge","auth":"wallet signature","body":"{ badge: \"category:id\" | null }","description":"Set displayed badge (must be unlocked)"},{"method":"GET","path":"/user/{account}/labels/watched","auth":"wallet signature (owner only)","description":"Only actively-watched wallet labels — private data, owner-authenticated"},{"method":"POST","path":"/user/{account}/labels","auth":"wallet signature","body":"{ wallet, label (1-50 chars), watching? }","description":"Create/update a wallet label (per-tier cap; 402 when limit reached)"},{"method":"PUT","path":"/user/{account}/labels/{wallet}/watch","auth":"wallet signature","body":"{ watching: bool }","description":"Toggle live-watch on a label (per-tier watcher cap)"},{"method":"DELETE","path":"/user/{account}/labels/{wallet}","auth":"wallet signature","description":"Delete a wallet label"},{"method":"PUT","path":"/user/{account}/avatar","auth":"wallet signature","body":"{ nftId: 64-hex }","description":"Set avatar from an owned NFT"},{"method":"POST","path":"/user/tier/purchase","body":"{ tier: \"vip|nova|diamond\", address }","description":"Create XRP invoice for user tier (expires 30 min)"},{"method":"GET","path":"/user/tier/verify/{invoiceId}","description":"Verify tier XRP payment (scans fee collector; expired invoices honored if exact payment exists)"},{"method":"POST","path":"/user/tier/stripe","body":"{ tier, address }","description":"Stripe checkout for user tier"},{"method":"GET","path":"/user/tier/stripe/{sessionId}","params":{"wallet":"required"},"description":"Check Stripe tier payment status"},{"method":"POST","path":"/user/tier/gift/purchase","body":"{ gifterAddress, recipientAddress, tier }","description":"Gift a tier via XRP invoice"},{"method":"GET","path":"/user/tier/gift/verify/{invoiceId}","description":"Verify gift tier payment"},{"method":"POST","path":"/user/tier/gift/stripe","body":"{ gifterAddress, recipientAddress, tier }","description":"Gift a tier via Stripe"}],"ai":[{"method":"GET","path":"/ai/models","description":"Models available for inference, with cost in cents per query and each model's published intelligence index (Artificial Analysis, reconciled against OpenRouter's benchmarks API)"}],"chat":[{"method":"GET","path":"/chat/status","params":{"wallet":"r-address"},"description":"Online count + unread status"},{"method":"GET","path":"/chat/messages","params":{"limit":"int (max 100, default 50)","before":"unix ms cursor"},"description":"Public chat history"},{"method":"GET","path":"/chat/session","params":{"wallet":"r-address"},"auth":"X-Api-Key","description":"5-min WebSocket session token"},{"method":"GET","path":"/chat/access","auth":"X-Api-Key","description":"Check chat access for key tier"}],"embed":[{"method":"GET","path":"/embed/{md5}","description":"Embeddable candlestick chart (HTML iframe)","params":{"theme":"dark|light","interval":"string","range":"string","height":"int","showVolume":"bool","showLogo":"bool","logoUrl":"https URL to image (whitelisted formats)"}},{"method":"GET","path":"/embed/score/{md5}","description":"Embeddable token safety-score badge (HTML iframe)","params":{"theme":"dark|light","size":"full - include name + check counts"}}],"lpPositions":[{"method":"GET","path":"/lp-positions/{account}","description":"AMM LP positions with impermanent loss analysis","response":"{ result, positions: { <poolId>: { ilPercent, holdValueXrp, poolValueXrp, currentAsset1, currentAsset2, feesEarnedXrp, currentLpBalance, poolShare, ... } } } (uses result: \"success\", not success: true)"}],"thumbnails":[{"method":"GET","path":"/thumb/{md5}","description":"Token thumbnail (WebP)","params":{"md5":"the token id","w":"16|32|40|48|64|96|128 (default: 48)","v":"source mtime (ms) — exact match returns immutable 1-year cache headers"},"notes":"Needs an API key (401 without one): send X-Api-Key, or ?apiKey= where headers cannot be sent. Fetch it from your server and cache it — a key in a public page's <img> src is visible to everyone."},{"method":"GET","path":"/nft-thumb/{hash}","description":"NFT image/thumbnail (original format, CSP-sandboxed for SVG)","params":{"hash":"an NFT's files[].thumbnail.small, .medium or .large from GET /nft/{nftId} (or a collection's logoNft)"},"notes":"Needs an API key (401 without one): send X-Api-Key, or ?apiKey= where headers cannot be sent."},{"method":"GET","path":"/nft-collection-thumb/{hash}","description":"NFT collection cover image","params":{"hash":"the collection's logoImage from GET /nft/collections/{slug}; without one, show /nft-thumb/{logoNft}"},"notes":"Needs an API key (401 without one): send X-Api-Key, or ?apiKey= where headers cannot be sent."}],"utilities":[{"method":"GET","path":"/health","description":"Service health check with per-service latency","response":"{ status: healthy|degraded, timestamp, version, uptime (s), services: { database, rippled, cache: { status, latency } } }"},{"method":"GET","path":"/openapi.json","description":"OpenAPI 3.1 spec for the whole API (270+ paths)"},{"method":"GET","path":"/docs","description":"This documentation (JSON). Browsers (Accept: text/html) are redirected to the human-readable docs."}],"testnet":[{"method":"GET","path":"/testnet/fixtures","description":"What the simulation keeps alive on Testnet: live accounts, its tokens (tokens[]: name, currency, issuer, holders, amm, role — stablecoin | deep (the high-liquidity pool) | volatile (a thin pool, swung every round) | crowd — with a note saying what each does, and peg_usd on the stablecoin), its collections (collections[]: name, issuer, taxon, role blue-chip | drop, note, items), an NFT with offers, one of every ledger object, and a real transaction of each type (catalogue[]: id, kind, about, result, hash, and tx — the JSON it sent, without fee, sequence, expiry or signature, a working template for that variation) — start here","response":"{ network_id, generated_at, age_seconds, population, accounts: { issuer, holders[], trader, busy[] }, tokens[], nft, objects, catalogue[] }","notes":"Rebuilt every few minutes by the simulation; age_seconds past a few minutes means Testnet was reset and it is catching up."},{"method":"GET","path":"/testnet/health","description":"Both collectors' head ledger against the network, and whether that is current","response":"{ ok, validated, node: { state, networkId, ledgers }, stages: { tokens: { ledger, at, lag }, nfts: { ledger, at, lag } } }"},{"method":"GET","path":"/testnet/tokens","description":"Testnet tokens. tvl is the token's XRP pool valued on both sides (twice its XRP reserve); a token with no XRP pool has none","params":{"sort":"vol24h | holders | trades24h | trustlines | tvl | firstSeen (default vol24h)","limit":"1-100 (default 50)","page":"from 1"},"response":"{ tokens: [{ _id (md5), issuer, currency, name, exch, spot, amm, vol24h, trades24h, holders, trustlines, supply, firstSeen }], count, total, page, limit, sortBy }"},{"method":"GET","path":"/testnet/tokens/{md5}","description":"A Testnet token with its AMM pool","response":"{ token, pool }"},{"method":"GET","path":"/testnet/tokens/{md5}/holders","description":"Holders of a Testnet token, largest first","params":{"limit":"1-200","page":"from 1"},"response":"{ holders: [{ account, balance, limit, time }], count, total }"},{"method":"GET","path":"/testnet/tokens/{md5}/offers","description":"The order book of a Testnet token against XRP","params":{"limit":"per side, 1-100"},"response":"{ bids[], asks[] } — price is XRP per token; a bid gives XRP, an ask takes it"},{"method":"GET","path":"/testnet/tokens/{md5}/trades","description":"Fills of a Testnet token, newest first","params":{"limit":"1-200","page":"from 1"},"response":"{ trades: [{ maker, taker, paid, got, price, xrp, isAMM, hash, ledger, time }], count, total }"},{"method":"GET","path":"/testnet/tokens/{md5}/ohlc","description":"5-minute candles of a Testnet token","params":{"from":"unix ms (default 7 days ago)","to":"unix ms (default now)","limit":"1-5000"},"response":"{ interval: \"5m\", candles: [{ time, open, high, low, close, xrp_volume, trades, vwap }] }"},{"method":"GET","path":"/testnet/accounts/{address}","description":"A Testnet account as the collector last saw it, with its trust lines, resting offers and last 20 trades","response":"{ account, lines[], offers[], trades[] }"},{"method":"GET","path":"/testnet/amm","description":"Testnet AMM pools, deepest first. A pool of two tokens has token and token2 (in a fixed order, by code) and xrp 0; its spot is token2 per token","params":{"limit":"1-100","page":"from 1"},"response":"{ pools: [{ _id (pool account), xrp, token: { currency, issuer, value }, token2?: { currency, issuer, value }, spot, fee, lp }], count, total }"},{"method":"GET","path":"/testnet/amm/{account}","description":"A Testnet AMM pool by its account","response":"{ pool }"},{"method":"GET","path":"/testnet/nft/collections","description":"Testnet NFT collections, by issuer and taxon. volume/sales are all-time XRP sales; vol24h/sales24h the last 24 h, recounted every minute","params":{"sort":"volume | items | sales | time | vol24h | sales24h (default volume)","limit":"1-100","page":"from 1"},"response":"{ collections: [{ _id, issuer, taxon, items, burned, owners, listed, floor, sales, volume, vol24h, sales24h, time }], count, total, sortBy }"},{"method":"GET","path":"/testnet/nft/collections/{id}","description":"A Testnet NFT collection","params":{"id":"issuer:taxon"},"response":"{ collection }"},{"method":"GET","path":"/testnet/nft/collections/{id}/nfts","description":"The live NFTs of a Testnet collection","params":{"id":"issuer:taxon","owner":"only this owner's","limit":"1-200","page":"from 1"},"response":"{ nfts: [{ _id (NFTokenID), owner, minter, URI, serial, minted }], count, total }"},{"method":"GET","path":"/testnet/nft/history","description":"Testnet NFT events, newest first","params":{"collection":"issuer:taxon","nft":"NFTokenID","account":"the sending account (one of the three is required)","type":"MINT | BURN | LIST | BID | CANCEL | SALE | TRANSFER | MODIFY","limit":"1-200","page":"from 1"},"response":"{ history: [{ type, NFTokenID, cid, account, buyer, seller, amount, broker, hash, ledger, time }], count, total }"},{"method":"GET","path":"/testnet/nft/{id}","description":"A Testnet NFT with the offers standing on it","response":"{ nft, offers[] }"},{"method":"GET","path":"/testnet/nft/{id}/offers","description":"The offers standing on a Testnet NFT, split by side","response":"{ sell[], buy[], count }"},{"method":"GET","path":"/testnet/{address}","description":"Live Testnet XRP balance, reserve, sequence and settings of an account, straight from the network","response":"{ address, activated, balance (drops), balanceXRP, reserve: { baseReserveXRP, ownerReserveXRP, ownerCount, totalReserveXRP }, available: { drops, xrp }, sequence, domain (the Domain field as text), domainHex, flags, ledgerIndex }"},{"method":"POST","path":"/testnet/rpc","description":"The XRP Ledger's own READ commands against our Testnet node — the half of Testnet that is not in the index: account_objects, book_offers, amm_info, ledger_entry, server_info and the rest. Reads only (submitting is POST /testnet/submit); the node's in-band error (actNotFound, entryNotFound) rides in result with a 200, as on Mainnet","body":"{ method (one of the read commands), params (the command's own fields as an object) }","response":"{ success, took, method, result (the node's own result, verbatim) }","notes":"Every public read command of rippled's own table (src/xrpld/rpc/detail/Handler.cpp, Role::USER), minus the ones that sign or submit and the ones that need a session: account_channels, account_currencies, account_info, account_lines, account_nfts, account_objects, account_offers, account_tx, amm_info, book_changes, book_offers, channel_verify, deposit_authorized, feature, fee, gateway_balances, get_aggregate_price, ledger, ledger_closed, ledger_current, ledger_data, ledger_entry, ledger_header, ledger_index, manifest, mpt_holders, nft_buy_offers, nft_history, nft_info, nft_sell_offers, nfts_by_issuer, noripple_check, owner_info, ping, random, ripple_path_find, server_definitions, server_info, server_state, simulate, transaction_entry, tx, tx_history, tx_reduce_relay, vault_info, version (the Clio-only ones answer unknownCmd on a node that is not Clio, which is itself the answer). subscribe, unsubscribe and path_find are WebSocket commands — open wss://api.xrpl.to/v1/testnet/ws (our Testnet node, no key) and send them there"},{"method":"POST","path":"/testnet/submit","description":"Submit a SIGNED transaction to Testnet through our own node — the contract of POST /submit with the prefix changed. Nothing here signs or holds a seed; fund an account with POST /faucet first","body":"{ tx_blob, fail_hard? }","constraints":"tx_blob is the signed transaction as hex, max 131KB. Duplicate tx_blob within 30s returns 409.","response":"{ success, took, engine_result, engine_result_code, engine_result_message, tx_json, hash, accepted, applied, broadcast, kept, queued, account_sequence_available, account_sequence_next, validated_ledger_index, outcome? }","notes":"engine_result is PRELIMINARY — only a validated ledger is final; follow hash with GET /testnet/tx/{hash} until validated is true or a validated ledger passes the LastLedgerSequence. A 400 with error_code is the node refusing it before processing; outcome:\"unknown\" (502, 409, or no engine_result) means it may still apply — resolve by hash, never by re-signing on a fresh Sequence. Every response carries hash."},{"method":"GET","path":"/testnet/tx/{hash}","description":"A Testnet transaction and its final result, from our node: validated, the ledger it closed in, result (meta.TransactionResult), the transaction and its meta. 404 until the node has seen it","response":"{ hash, validated, ledger_index, result, close_time_iso, tx, meta }"}],"internalEndpoints":["/diagnostics","/faucet","/dapp-session","/ai"],"tierInfo":{"free":{"price":"$0/mo","credits":"1M","rate":"10 req/sec","submit":"1 tx/sec","support":"Community"},"developer":{"price":"$49/mo","credits":"10M","rate":"50 req/sec","submit":"5 tx/sec","support":"Chat"},"partner":{"price":"Invitation-only","credits":"20M","rate":"100 req/sec","submit":"10 tx/sec","support":"Direct"},"business":{"price":"$499/mo","credits":"100M","rate":"200 req/sec","submit":"50 tx/sec","support":"Priority chat"},"professional":{"price":"$999/mo","credits":"200M","rate":"500 req/sec","submit":"100 tx/sec","support":"Telegram + Slack"}},"mcp":{"endpoint":"POST /v1/mcp","description":"MCP server (Model Context Protocol, stateless Streamable HTTP). Connect any MCP client to xrpl.to token analytics: JSON-RPC 2.0 with initialize / tools/list / tools/call. Read-only.","tools":"32 read-only tools, 8 prompts (token-audit, investigate-wallet, trace-funds, market-brief, swap-check, new-launch-scan, whale-watch, compare-tokens) 6 reference resources and 2 resource templates (xrplto://token/{id}, xrplto://account/{address}) — call tools/list, prompts/list, resources/list, resources/templates/list for the authoritative sets","auth":"Optional X-Api-Key header — anonymous callers get anonymous rate limits","clientConfig":"{\"url\": \"https://api.xrpl.to/v1/mcp\"} (Streamable HTTP transport)"},"reference":{"tokenId":"md5 | slug (issuer-currency) | issuer_currency | mpt-<mptIssuanceID>","account":"^r[1-9A-HJ-NP-Za-km-z]{24,34}$","NFTokenID":"64-char hex","txHash":"64-char hex","timestamps":"Unix milliseconds (13 digits)","pagination":"offset + limit, or cursor-based with marker","sorting":"sort + order params"},"errors":{"400":"Bad Request (malformed JSON bodies return { success: false, error: \"Invalid JSON in request body\" })","401":"Unauthorized - Missing or invalid API key","402":"Insufficient credits","403":"Forbidden - Wallet does not match resource owner. A NON-JSON 403 comes from the CDN/WAF, not the API — usually a generic programmatic User-Agent; send a descriptive one (see authentication.userAgent).","404":"Not Found","410":"Gone - Invoice expired","429":"Too Many Requests - Rate limit exceeded (Retry-After + X-RateLimit-* headers, retryAfter in body; see rateLimits)","500":"Internal Server Error","format":"JSON: { success: false, error: string, ... }. error is either a short human-readable sentence OR a stable UPPER_SNAKE code for machine matching (e.g. ACCOUNT_NOT_FOUND) — whenever it is a code, a message field carries the human sentence. Bodies may add context fields (retryAfter, docs, hint, balance). requestId (mirroring the x-request-id response header) is included on gateway-level errors — quote it in support requests."}}