What It Does
One product, one account, two asset families:- Tokenized equities (Ondo) — fractional-share ERC-20s traded via 1inch Fusion intent orders (this page’s main flow).
- RWA yield tokens (Midas) — NAV-accruing ERC-20s (
mTBILL,mBASIS,mBTC) traded via swap-basedtransact/buy/transact/sell. See RWA Yield Assets below.
Supported Markets
Ondo lists 250+ tokenized US equities on Ethereum. Use/v2/tokenized_assets/markets to fetch the live catalog with current prices, 24h price change, and sector tags. Examples:
| Symbol | Underlying | Sector |
|---|---|---|
TSLAon | TSLA | Consumer Discretionary |
AAPLon | AAPL | Technology |
NVDAon | NVDA | Technology |
SPYon | SPY (ETF) | Broad Market |
End-to-End Flow
- One-time: create a Tokenized Assets Account for the owner.
- Per order: build → sign the approval if returned + sign the order → relay the approval → submit the order → poll for status.
1. Create a Tokenized Assets Account (one-time per owner)
POST /v2/tokenized_assets/create_account returns the deterministic account address for owner and an unsigned creation transaction. If the account already exists, transaction is null and you can skip straight to building orders.
transaction: null on the second call. You can cache it client-side after the first deploy.
2. Build an Order
POST /v2/tokenized_assets/order returns three things in one round-trip:
quote— preview of the input/output amounts and fees.approval_safe_tx_eip712— present only when the account’s allowance to the settlement contract is belowamount. The owner signs it once per token; subsequent orders against the samefrom_tokenskip this step.nullwhen the allowance is already sufficient.order— the order metadata (order_hash,order_message,extension,quote_id) plussafe_message_eip712, an EIP-712 payload the owner signs off-chain to authorize the order.
400 ACCOUNT_NOT_DEPLOYED — go back to step 1. If from_token or to_token isn’t a supported tokenized equity (or the literal USDC), the API returns 404 MARKET_NOT_FOUND.
3. Sign the Approval (only when returned)
Whenbuild.approval_safe_tx_eip712 is non-null, the owner signs it with signTypedData. The payload is a one-time max-approve for the settlement contract; once it’s on-chain, future orders against the same from_token skip this step entirely.
Relay the approval
Submit the signed approval toPOST /v2/gas_sponsorship/prepare with the sender who will pay gas (typically your relayer). The endpoint returns an unsigned transaction for sender to sign and broadcast.
If you’d rather have the owner pay their own gas, the owner can broadcast the execTransaction against the product account directly instead of going through gas sponsorship.
FUSION_NO_LIQUIDITY or a 502 from the relayer.
4. Sign the Order
The owner signsorder.safe_message_eip712 — an EIP-712 payload that authorizes the order’s order_hash for the Tokenized Assets Account. Unlike the approval, this signature does not get broadcast on-chain: it’s relayed off-chain to the resolver network, which validates it against the product account at fill time.
5. Submit the Signed Order
POST /v2/tokenized_assets/order/submit relays the signature to the resolver network. The body echoes the order fields from the build step plus the owner’s signature.
signed_order.maker is the Tokenized Assets Account, not the owner’s wallet — pass the dict back unchanged.
Including order_hash is optional but recommended: the upstream relayer occasionally returns a 2xx response with an empty body, and supplying the hash lets the API still return a usable handle for status / cancel lookups.
6. Poll for Fill Status
GET /v2/tokenized_assets/order/{order_hash} returns the lifecycle state:
pending— waiting for a resolver to fill (covers partial fills too;filled_amountis populated as fills come in).filled— fully settled.fill_tx_hashandfilled_amountare populated. The output token lands in the Tokenized Assets Account.expired— auction window closed without a fill.cancelled— the order was cancelled on-chain before it filled.
Cancel an Unfilled Order
POST /v2/tokenized_assets/order/{order_hash}/cancel returns cancel_safe_tx_eip712 — an EIP-712 payload that, when signed and broadcast, cancels the order on-chain. Cancellation follows the same pattern as the approval: owner signs, relayer (or owner) broadcasts.
Cancellation works on pending and expired orders; calling it on a filled or already-cancelled order returns 409.
403 OWNER_NOT_MAKER.
Read Markets and Candles
UseGET /v2/tokenized_assets/markets/{symbol} to fetch a single market with extended detail (52-week range, volume, market cap, holder count, tradable sessions) and an optional OHLC candle series.
Pass interval and range together to include candles. They must form one of the supported pairs:
interval | Allowed range values |
|---|---|
1min | 1day |
5min | 1day |
15min | 1day |
1hour | 1month |
4hour | 1month |
12hour | 3month |
1day | 3month, 6month, 1year, all |
candles field.
Python
Read Positions
GET /v2/tokenized_assets/positions?owner=0x... returns ERC-20 balances of every Ondo tokenized equity held in the owner’s Tokenized Assets Account, enriched with current USD prices and a total_usd aggregate.
Pass the owner’s wallet address — the API derives the Tokenized Assets Account address from it and reads balances from the derived account (proceeds from filled orders land there, not in the owner’s wallet). If the account hasn’t been created yet, the call returns 400 ACCOUNT_NOT_DEPLOYED.
Python
Errors
All4xx/5xx responses use the standard Compass { "error": "<CODE>", "message": "<text>" } envelope, except standard input-validation 422s — those come from FastAPI in the form { "detail": [...] }. The codes below are the ones Compass raises with the envelope:
| Code | Status | When |
|---|---|---|
ACCOUNT_NOT_DEPLOYED | 400 | The owner doesn’t have a Tokenized Assets Account yet — call /create_account first. |
MARKET_NOT_FOUND | 404 | Unknown symbol on a markets read, or from_token/to_token cannot be resolved on /order / /quote. |
ORDER_NOT_FOUND | 404 | Unknown order hash on status or cancel. |
OWNER_NOT_MAKER | 403 | The Tokenized Assets Account predicted from owner is not the order’s maker. |
FUSION_NO_LIQUIDITY | 409 | No resolver could fill at this size — try a smaller size or retry shortly. |
ORDER_ALREADY_FILLED | 409 | Cancel attempted on a filled order. |
ORDER_ALREADY_CANCELLED | 409 | Cancel attempted on an already-cancelled order. |
FUSION_QUOTE_EXPIRED | 410 | Quote stale at submit time — re-quote and retry. |
FUSION_SLIPPAGE_EXCEEDED | 422 | On /order: Fusion’s auction may fill below your slippage_bps tolerance — raise slippage_bps or pick a more liquid market. |
ONDO_API_UNAVAILABLE | 502 | Ondo read API (markets, prices, order status) is unavailable. |
FUSION_API_UNAVAILABLE | 502 | 1inch Fusion API (quote, order, submit, cancel) is unavailable. |
Key Concepts
The maker is the Tokenized Assets Account, not the owner’s wallet. The product account holds the input tokens, signs orders, and receives the output tokens. The owner’s wallet is its sole controller and signs all EIP-712 payloads off-chain. Three EIP-712 payloads, two purposes.approval_safe_tx_eip712andcancel_safe_tx_eip712authorize on-chain transactions (allowance approval and order cancellation). The owner signs them, then a relayer or the owner broadcasts the resulting transaction.order.safe_message_eip712authorizes the off-chain order sent to the resolver auction. The signature goes back to/order/submitand is never broadcast.
from_token skip step 3 entirely.
Don’t inspect extension or quote_id. They are opaque values from the upstream quote — pass them back to /order/submit unchanged.
Status mapping. The upstream protocol publishes finer-grained states (partially-filled, refunded, false-predicate, …) which Compass collapses onto the 4-value enum (pending, filled, expired, cancelled). Unknown upstream states return 502 rather than guessing.
Use Cases
Brokerage app for retail. Let users buy fractional Tesla / Apple shares with USDC, hold them as on-chain tokens, and trade out at any time without going through a centralized broker. On-chain portfolio diversification. Crypto-native users get equity exposure without leaving their wallet — same UX as a token swap, settlement is just-in-time on Ethereum. Treasury allocation. DAOs and on-chain orgs can rebalance treasuries into tokenized equities while keeping signing authority with the owner wallet — no third-party custody.Next Steps
Product Accounts
Background on the per-product account model used here.
Gas Sponsorship
How
/v2/gas_sponsorship/prepare broadcasts the signed approval and cancel transactions.Global Markets
Synthetic stock perps via Hyperliquid — different product, leverage available.
RWA Yield Assets (Midas)
Alongside equities, the same product account holds and trades Midas RWA yield tokens — permissionless ERC-20s whose NAV accrues yield from real-world assets:| Symbol | Underlying | Asset class | Networks |
|---|---|---|---|
mTBILL | US Treasury Bills | T_BILLS | Ethereum, Base |
mBASIS | Crypto basis trading | BASIS_TRADE | Ethereum, Base |
mBTC | BTC yield | BTC_YIELD | Ethereum |
Discover markets
GET /v2/tokenized_assets/markets returns equities and RWA assets in one list.
Each entry carries provider (ondo | midas), asset_class, and chain;
RWA entries add apy_7d / apy_30d (trailing annualized NAV growth — null
until enough history exists) and tvl_usd. Filter with the provider,
asset_class, and chain query params.
Trade
RWA assets do not use the order endpoints. Instead:- Fund the account — transfer the input token (e.g. USDC) to the Tokenized Assets Account address (plain ERC-20 transfer).
- Buy —
POST /v2/tokenized_assets/transact/buywithtoken_in,token_out(the RWA symbol),amount_in,slippage,owner,chain. Returns an unsigned transaction executing the swap inside the product account (or an EIP-712 payload withgas_sponsorship: true), plusestimated_amount_out. - Sell —
POST /v2/tokenized_assets/transact/sellwith the RWA symbol astoken_in.
transact/buy/transact/sell returns a 422
pointing back to the order flow, and vice versa: RWA symbols are not valid in
/quote or /order.
Positions
GET /v2/tokenized_assets/positions includes RWA holdings next to equities,
valued at the latest indexed NAV. Pass chain=base to read Base positions
(equities are Ethereum-only). On Base, create the account first with
POST /v2/tokenized_assets/create_account and "chain": "base" — the account
address is identical on every network.