TL;DR
-
CoinGecko API's RWA list and RWA market data endpoints let you screen live RWAs, including stocks, commodities, ETFs, and pre-IPO assets tokenized by multiple issuers, such as OpenAI and SpaceX.
-
Use the RWA by ID endpoint to verify the underlying asset, then compare prices and liquidity across centralized and decentralized exchanges with the RWA tickers endpoint.
-
Build a repeatable, scriptable RWA watchlist with RWA markets data and use the exchange rates endpoint to track premiums and discounts for tokenized commodities.
Tokenized real-world assets (RWAs) are moving beyond a niche use case in crypto and digital finance. Onchain tokenized stocks crossed $1 billion in aggregate value in March 2026 and reached roughly $2.3 billion by July 2026. Nasdaq secured SEC approval to list tokenized securities, while DTCC conducted production trades with BlackRock, J.P. Morgan, and Goldman Sachs. Robinhood also launched its own blockchain for issuing tokenized shares.
A "tokenized" label alone does not tell you who backs an asset, whether it is redeemable, or whether multiple platforms represent the same underlying asset through different contracts. The issuer, contract, and supporting documentation provide the details needed to understand what each token represents.
In this guide, we'll use CoinGecko's RWA API endpoints with the same API and key used for crypto price and market data across 44M+ assets. You'll learn how to find tokenized real-world assets including stocks, commodities, and ETFs, check for assets offered by multiple issuers, verify what they represent, and compare prices and liquidity across CEX and DEX venues.

Prerequisites & Setup
You'll need a CoinGecko API key. If you don't have a key yet, sign up for a free Demo API key to get started. The free Demo plan covers finding RWAs, screening pre-IPO stocks, and verifying what a token represents. To compare liquidity across exchanges and analyze historical RWA data, you'll need a paid API plan.
You'll also need Python 3.9+ and the requests library.
1 2
requests==2.32.3 python-dotenv==1.0.1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
import os from dotenv import load_dotenv load_dotenv() API_KEY = os.getenv("COINGECKO_API_KEY") # Use the Demo base URL if you have a free Demo key. # Switch to the Pro base URL once you upgrade to a paid plan. BASE_URL = "https://api.coingecko.com/api/v3" # BASE_URL = "https://pro-api.coingecko.com/api/v3" HEADERS = { "accept": "application/json", "x-cg-demo-api-key": API_KEY, # Swap the header above for "x-cg-pro-api-key" if you switch to the Pro base URL. }
How to Discover Tokenized Real-World Assets in Real-Time
CoinGecko's RWA list endpoint gives you a complete view of its tracked RWAs in a single call, with no pagination required. It returns the ID, symbol, name, and asset type for each tokenized stock, commodity, and ETF, providing the identifiers needed for the next steps.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
import requests from config import BASE_URL, HEADERS def get_rwa_list(asset_type=None): url = f"{BASE_URL}/rwas/list" params = {} if asset_type: # asset_type accepts "stock", "commodity", or "etf" params["asset_type"] = asset_type response = requests.get(url, headers=HEADERS, params=params) response.raise_for_status() return response.json() def get_rwa_markets(ids=None, asset_type=None, price_change_percentage="24h,7d"): url = f"{BASE_URL}/rwas/markets" params = {"price_change_percentage": price_change_percentage} if ids: params["ids"] = ",".join(ids) if isinstance(ids, list) else ids if asset_type: params["asset_type"] = asset_type response = requests.get(url, headers=HEADERS, params=params) response.raise_for_status() return response.json() if __name__ == "__main__": rwas = get_rwa_list() print(f"Total RWAs tracked: {len(rwas)}") # Screen a mix of tokenized stocks, a leveraged ETF, and a tokenized commodity sample = get_rwa_markets(ids=["amazon", "adobe", "2x-bitcoin-strategy-etf", "gold"]) for m in sample: data = m["tokenized_market_data"] print(m["id"], m["asset_type"], data["current_price"], data["market_cap"])
Here's what the response looks like:
Total RWAs tracked: 647
gold commodity 4372.67 5191355414
amazon stock 258.39 17034367
adobe stock 292.15 984006
2x-bitcoin-strategy-etf etf 17.32 5182.87
For price, market cap, and trading volume, CoinGecko's RWA market data endpoint provides up to 250 results per page. Use the ids, names, symbols, or issuer filters to narrow the results. You can also browse the same RWA data without code on CoinGecko's Real World Assets page.
How to Find and Track Pre-IPO Stock Prices in Real-Time
CoinGecko lets you find tokenized pre-IPO stocks through the Coin Markets endpoint by filtering for the Tokenized Pre-IPO Stocks category. Each tokenized pre-IPO share is returned as an individual coin, regardless of which platform issued it. To compare tokens representing the same company, use the RWA by ID endpoint, which groups them into a single aggregated view where available.
Pre-IPO assets can also be identified through the RWA endpoints without using the category filter. Call RWA List endpoint, then filter the results for names containing "(Pre-IPO)". As of writing, this returns Anduril, Anthropic, Kalshi, OpenAI, Polymarket, SpaceX, and xAI. Each result includes an RWA ID that you can use with the RWA Data by ID endpoint.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
import requests from config import BASE_URL, HEADERS def get_pre_ipo_stocks(): url = f"{BASE_URL}/coins/markets" params = { "vs_currency": "usd", "category": "tokenized-pre-ipo-stocks", "order": "market_cap_desc", "per_page": 20, "page": 1, } response = requests.get(url, headers=HEADERS, params=params) response.raise_for_status() return response.json() def get_rwa_by_id(rwa_id): url = f"{BASE_URL}/rwas/{rwa_id}" params = {"tokens": "true", "tokenized_market_data": "true"} response = requests.get(url, headers=HEADERS, params=params) response.raise_for_status() return response.json() if __name__ == "__main__": coins = get_pre_ipo_stocks() print(f"Tokenized pre-IPO stocks live: {len(coins)}") for c in coins: print(c["id"], c["symbol"], c["name"], c["market_cap"]) openai = get_rwa_by_id("openai-pre-ipo") print(f"\n{openai['name']} aggregate price: {openai['tokenized_market_data']['current_price']}") for t in openai["tokens"]: print(" -", t["name"], "issued by", t["issuer_details"]["name"])
Running this script produces output like the following:
Tokenized pre-IPO stocks live: 13
openai-republic-pre-ipo preopai OpenAI (Republic Pre-IPO) 22058404
spacex-republic-pre-ipo prespcx SpaceX (Republic Pre-IPO) 13527865
anthropic-prestocks-2 anthropic Anthropic PreStocks 6692073
spacex-prestocks-2 spacex SpaceX PreStocks 4523886
openai-prestocks-2 openai OpenAI PreStocks 1915965
anduril-prestocks-2 anduril Anduril PreStocks 1678669
kalshi-prestocks kalshi Kalshi PreStocks 1189298
polymarket-prestocks polymarket Polymarket PreStocks 665296
tessera-spacex-tokenized-share tspacex SpaceX (Tessera Pre-IPO) 665058
tessera-kalshi-tokenized-share tkalshi Kalshi (Tessera Pre-IPO) 652143
openai-tessera-pre-ipo topenai OpenAI (Tessera Pre-IPO) 579310
xai-prestocks-2 xai xAI PreStocks 155923
openai-gate-pre-ipo openai OpenAI (Gate Pre-IPO) 0.0
OpenAI (Pre-IPO) aggregate price: 1214.36
- OpenAI (Republic Pre-IPO) issued by Republic
- OpenAI PreStocks issued by PreStocks
- OpenAI (Tessera Pre-IPO) issued by Tessera Tokenized Pre-IPO Assets
- OpenAI (Gate Pre-IPO) issued by Gate
OpenAI appears multiple times in the first block, once per issuing platform. Each entry represents a different token issued on a different platform, with its own coin ID, symbol, and market cap. Looking at all the tokens gives you a complete view of the market for that asset.
The second block shows CoinGecko's aggregated RWA view. OpenAI is tracked as a single RWA with asset_type set to stock, combining its issuer tokens into one price and market cap. This provides a single view of the market for tokenized OpenAI shares.
How to Find Other Assets Tokenized by an Issuer
A "tokenized" label does not guarantee that an asset is genuinely backed. Some tokens provide only tokenization infrastructure, exist only on a testnet, claim partnerships without holding the underlying asset, or synthetically track an asset's price without holding it. Every RWA listed on CoinGecko has passed CoinGecko's published three-step classification methodology:
-
Identify the real-world asset it represents.
-
Verify that the asset is backed and redeemable.
-
Confirm that token holders can redeem the token for the asset rather than only gain or lose value as its price changes.
Tokens are excluded if they:
-
Only supply tokenization infrastructure, with no real asset behind them
-
Exist only on a test network
-
Claim a partnership without their own asset backing
-
Synthetically track an asset's price without holding the real asset
We'll use OpenAI as an example. Its RWA record shows the tokens representing the company. From there, follow a token to its issuer through the RWA issuer data endpoint to see the other assets that issuer has tokenized.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
import requests from config import BASE_URL, HEADERS def get_rwa_by_id(rwa_id): url = f"{BASE_URL}/rwas/{rwa_id}" # tokens and tokenized_market_data default to false. # Leave either one out and you will only get bare metadata back. params = {"tokens": "true", "tokenized_market_data": "true"} response = requests.get(url, headers=HEADERS, params=params) response.raise_for_status() return response.json() def get_issuer(issuer_id): url = f"{BASE_URL}/rwas/issuers/{issuer_id}" response = requests.get(url, headers=HEADERS) response.raise_for_status() return response.json() if __name__ == "__main__": rwa = get_rwa_by_id("openai-pre-ipo") print(f"{rwa['name']} is tracked as {len(rwa['tokens'])} separate tokens:") for token in rwa["tokens"]: # Not every token lists a platform yet, so only add the clause when one exists platform = next(iter(token["platforms"]), None) platform_note = f" on {platform}" if platform else "" print(f" - {token['name']} ({token['symbol'].upper()}){platform_note}, issued by {token['issuer_details']['name']}") issuer = get_issuer("republic-tokenized-pre-ipo-assets") print(f"\n{issuer['name']} has tokenized {len(issuer['tokens'])} assets worth ${issuer['market_cap']:,.0f} total") for t in issuer["tokens"]: print(" -", t["name"])
Here's what the response looks like:
OpenAI (Pre-IPO) is tracked as 4 separate tokens:
- OpenAI (Republic Pre-IPO) (PREOPAI) on solana, issued by Republic
- OpenAI PreStocks (OPENAI) on solana, issued by PreStocks
- OpenAI (Tessera Pre-IPO) (TOPENAI) on solana, issued by Tessera Tokenized Pre-IPO Assets
- OpenAI (Gate Pre-IPO) (OPENAI), issued by Gate
Republic has tokenized 2 assets worth $42,507,662 total
- OpenAI (Republic Pre-IPO)
- SpaceX (Republic Pre-IPO)
How to Compare RWA Token Liquidity Across CEXs and DEXs
CoinGecko's RWA tickers endpoint gives you a detailed view of an RWA's liquidity across exchanges. It returns centralized and decentralized exchange listings with price, volume, and bid-ask spread for each venue. An optional order-book depth check shows how much it takes to move the venue's price.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
import requests from config import BASE_URL, HEADERS def get_rwa_tickers(rwa_id, order="volume_desc", depth=False): url = f"{BASE_URL}/rwas/{rwa_id}/tickers" params = {"order": order, "depth": str(depth).lower()} response = requests.get(url, headers=HEADERS, params=params) response.raise_for_status() return response.json() if __name__ == "__main__": tickers = get_rwa_tickers("openai-pre-ipo", depth=True) for t in tickers["tickers"][:5]: spread = t["bid_ask_spread_percentage"] print(f"{t['market']['name']}: {t['converted_last']['usd']} USD, spread {spread}%, volume {t['converted_volume']['usd']}")
The script returns the following output:
Meteora: 1625.91 USD, spread 0.605413%, volume 3452228
Meteora: 1628.68 USD, spread 0.625411%, volume 1748664
Bitget: 962.45 USD, spread 0.027003%, volume 1270445
Gate: 959.84 USD, spread 0.259875%, volume 389365
Meteora: 885.32 USD, spread 0.603285%, volume 281689
exchange_ids to focus on specific exchanges. For example, exchange_ids=gate,bitget lets you compare the two CEX listings shown above. For DEX pairs, add dex_pair_format=symbol to show readable tickers like SOL/USDC instead of raw contract addresses.How to Compare Tokenized Real-World Assets for Premiums or Discounts
CoinGecko API can show whether a tokenized commodity trades above or below its spot price. For gold and silver, the exchange rates endpoint tracks their spot prices in BTC, providing the reference price needed to measure the premium or discount.
This method works for tokenized commodities, which have spot price data available through the exchange rates endpoints. For tokenized equities, you'll need a reference price of the underlying stock from a third-party provider, such as the Finnhub API, to compare against the tokenized asset data from CoinGecko API.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
import requests from config import BASE_URL, HEADERS def get_implied_spot_price(commodity_code): # commodity_code is "xau" for gold or "xag" for silver url = f"{BASE_URL}/exchange_rates" response = requests.get(url, headers=HEADERS) response.raise_for_status() rates = response.json()["rates"] # Both rates are quoted against BTC, so dividing USD by the commodity # rate gives you the implied USD spot price for one troy ounce return rates["usd"]["value"] / rates[commodity_code]["value"] def get_tokenized_price(rwa_id): url = f"{BASE_URL}/rwas/{rwa_id}" params = {"tokenized_market_data": "true"} response = requests.get(url, headers=HEADERS, params=params) response.raise_for_status() return response.json()["tokenized_market_data"]["current_price"] if __name__ == "__main__": for rwa_id, code in [("gold", "xau"), ("silver", "xag")]: tokenized = get_tokenized_price(rwa_id) spot = get_implied_spot_price(code) premium = (tokenized - spot) / spot * 100 label = "premium" if premium >= 0 else "discount" print(f"{rwa_id}: tokenized ${tokenized:,.2f} vs implied spot ${spot:,.2f}, a {abs(premium):.2f}% {label}")
Running this script produces output like the following:
gold: tokenized $4401.50 vs implied spot $4401.98, a 0.01% discount
silver: tokenized $66.39 vs implied spot $66.65, a 0.39% discount
How to Get Historical RWA Market Data
CoinGecko's RWA historical chart data endpoint provides historical price, market cap, and volume for an RWA as time-series arrays. History varies by asset type: stocks and ETFs go back to July 2025, and commodities to September 2019.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
import requests from config import BASE_URL, HEADERS def get_market_chart(rwa_id, days=30): url = f"{BASE_URL}/rwas/{rwa_id}/market_chart" params = {"days": days} response = requests.get(url, headers=HEADERS, params=params) response.raise_for_status() return response.json() if __name__ == "__main__": chart = get_market_chart("openai-pre-ipo", days=30) print(f"\n{len(chart['tokenized_prices'])} price points over the last 30 days") print("First point:", chart["tokenized_prices"][0]) print("Last point:", chart["tokenized_prices"][-1])
Here's what the response looks like:

How to Build an RWA Watchlist
CoinGecko's RWA markets endpoint lets you turn a list of vetted asset IDs into an RWA watchlist. Query those IDs on a schedule to monitor selected assets.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
import requests from config import BASE_URL, HEADERS WATCHLIST = ["openai-pre-ipo", "spacex-pre-ipo", "gold", "silver"] def get_watchlist_snapshot(ids): url = f"{BASE_URL}/rwas/markets" params = { "ids": ",".join(ids), "price_change_percentage": "24h", } response = requests.get(url, headers=HEADERS, params=params) response.raise_for_status() return response.json() if __name__ == "__main__": snapshot = get_watchlist_snapshot(WATCHLIST) # The markets endpoint can only sort by market cap, volume, or id, # so sorting by biggest mover has to happen client-side after the fetch snapshot.sort(key=lambda x: x["tokenized_market_data"]["price_change_percentage_24h_in_currency"] or 0, reverse=True) print(f"{'Asset':<20}{'Price':>12}{'24h %':>10}{'Market Cap':>18}") for rwa in snapshot: data = rwa["tokenized_market_data"] change = data["price_change_percentage_24h_in_currency"] or 0 print(f"{rwa['id']:<20}{data['current_price']:>12,.2f}{change:>+9.2f}%{data['market_cap']:>18,.0f}")
Here's what the response looks like:
Asset Price 24h % Market Cap
spacex-pre-ipo 136.46 +11.91% 20,538,126
openai-pre-ipo 1,441.55 +1.83% 31,283,335
silver 66.39 +0.75% 260,526,463
gold 4,401.50 +0.19% 5,271,132,459
Run this script on a schedule with cron or a GitHub Action to maintain a live watchlist without building a dashboard. Once you have the data flowing, the crypto portfolio dashboard in Python guide shows how to use it to build a portfolio dashboard.
Conclusion
CoinGecko's RWA API gives you the core data needed to find vetted RWAs, identify assets tokenized by multiple issuers, and compare liquidity across exchanges. These are the building blocks for an RWA tracker, screener, or research tool.
The liquidity comparison in this guide uses snapshot ticker data. If you need real-time streaming prices for tokenized stocks, CoinGecko also supports WebSocket streaming of tokenized real-world assets. For those new to RWAs, the primer on real-world asset protocols is a good place to start.
Ready to start building? Sign up for a free Demo API plan to start working with RWA data. When you need exchange-level liquidity or deeper historical data, a paid API plan or above gives you access to the RWA tickers and market chart endpoints, with more API credits, higher rate limits, and a commercial license included.
