protocol: "Ondo", network: bsc). The market-share position always lives on BSC, but clients
can fund a buy from — or receive a sell payout on — another EVM chain. Pods handles the bridge and the
async order fill.
Overview
| Item | Value |
|---|---|
| Strategy ID format | Ondo-<TICKER>-bsc (e.g. Ondo-AAPL-bsc) |
| Position chain | BSC (56) |
| Strategy asset | Market-share token on BSC (symbol ends in ON, e.g. AAPLON) |
| Underlying reference | USDC (6 decimals) |
| Buy / Sell actions | request-lend (buy) / request-withdraw (sell) |
| Minimum buy | $10 USDC (strategy.metadata.minRequestLendUsd) |
| Auth | Header x-api-key: <your-key> |
Settlement is asynchronous. The on-chain transaction submits the request in seconds; the order
reaches SUCCESS only after Ondo fills it (minutes later). For crosschain, the bridge leg settles
first, then the order. Track both the on-chain receipt and the action status via WebSocket or
history polling.
Quote and bytecode come from the same call.GET /strategies/:id/bytecodereturns a pricedquote(for your UI) andbytecode[](to execute on-chain).
Authentication
Every request requires:- The key identifies your customer. Fee configuration and strategy catalog are scoped to it.
- Success responses are the bare JSON body (HTTP 200). Errors use
{ "error": { "code", "message", "details?" } }. - Keep the API key on your backend — never expose it in a browser app.
Integration flow
1. Market status
Gate buy/sell when the market is closed.isOpen — block submit when false.
2. List Stocks & ETFs
categoryaccepts comma-separated values (stock,etf).- Each token:
{ symbol, name, address, decimals, chainId, category, priceInUSD, logoURI? }. - Ondo symbols end in
ON(e.g.AAPLON). StripONfor display if desired.
3. Resolve strategy ID
A market-share token address alone is not enough — you need the strategy id.{ data: [...], pagination }. Pick the strategy where:
assetmatches the market-share token addressnetworkId === 56
request-lend (buy) and request-withdraw (sell) from availableActions.
4. Buy — request-lend
| Parameter | Required | Description |
|---|---|---|
action | yes | request-lend |
wallet | yes | Address that signs on the funding chain |
amount | yes | Funding token in base units (USDC = 6 decimals) |
fromChainId | yes | Funding chain (56 for same-chain BSC, or another supported chain) |
fromTokenAddress | yes* | Funding token on fromChainId; omit to default to USDC on that chain |
fromChainId is set, fromTokenAddress defaults to USDC on that chain.
Same-chain (BSC): fromChainId=56, fromTokenAddress= USDC on BSC. The client signs on BSC.
Crosschain: fromChainId= origin chain (e.g. 8453 Base). The client signs only on the origin
chain; Pods bridges funds to BSC and fills the order asynchronously.
Response (relevant fields):
- Filter
bytecodewherechainId === chainIdIn(same-chain:56; crosschain: the origin chain). - Sign and broadcast on that chain in a single transaction.
- Wait for async completion (crosschain: bridge → BSC → CoW order fill).
- Minimum: $10 USDC (enforced server-side, error
REQUEST_LEND_AMOUNT_TOO_LOW). For crosschain the minimum is checked on the bridged USDC amount that lands on BSC. - Use
quotefor pricing UI; usequote.feeBreakdown.summaryfor fee display.
Crosschain: the client only signs on the origin chain. Bridge + market-share purchase are handled by Pods.
5. Sell — request-withdraw
| Parameter | Required | Description |
|---|---|---|
action | yes | request-withdraw |
wallet | yes | Address on BSC (where market shares are held) |
amountInShares | yes | Share amount in wei (18 decimals) |
toChainId | yes | Payout chain (56 for same-chain BSC, or another supported chain) |
toTokenAddress | yes* | Payout token on toChainId; omit to default to USDC on that chain |
toChainId is set, toTokenAddress defaults to USDC on that chain.
- Use
amountInShares(notamount) for Ondo sells. No minimum sell amount. - Response shape matches buy (
id,chainIdIn,chainIdOut,crossChain,singleUseAddress,orderUid,quote,bytecode).
toChainId=56, toTokenAddress= USDC on BSC. The client signs on BSC.
Crosschain: toChainId= destination chain. The client signs only on BSC (shares live there);
Pods sells the market share for USDC on BSC, then bridges the proceeds to the destination chain.
Client execution
- Filter
bytecodewherechainId === 56(always BSC — shares are on BSC). - Sign and broadcast on BSC.
- Wait for async completion (CoW order fill → crosschain: bridge USDC to
toChainId).
Crosschain: the client only signs on BSC. Market share → USDC redemption and the bridge payout are async.
6. Positions & pending requests
Thewallet is always normalized to BSC (same EVM address regardless of funding/payout chain).
Wallet snapshot (all positions)
earn.positions where strategy.protocol === "Ondo".
Single strategy position
fromActions=1 for correct accounting (principal, profit, in-flight operations).
Position shape
requestedTo* fields
These arrays represent pending async orders not yet settled (same on same-chain and crosschain):
| Field | Meaning |
|---|---|
requestedToLend | USDC committed to a pending buy |
requestedToLendInShares | Equivalent shares for pending buy |
requestedToWithdraw | USDC value of a pending sell |
requestedToWithdrawInShares | Shares committed to a pending sell |
- Buy submitted, shares not yet credited →
requestedToLend/requestedToLendInSharespopulated. - Sell submitted, USDC not yet paid out →
requestedToWithdraw/requestedToWithdrawInSharespopulated. - Settled → all pending arrays empty;
currentPositionInShares/underlyingBalanceUSDreflect the real balance.
Available balance for sell
availableShares as amountInShares
when selling the full position.
7. Track order status
After submittingbytecode[] on-chain, the action is not complete until status is SUCCESS.
HTTP — pending actions for one strategy
Poll when you want a strategy-scoped snapshot without loading the full wallet or strategy position. The handler refreshes in-flight operations before responding.| Parameter | Required | Description |
|---|---|---|
strategyId | yes (path) | Strategy slug or id (e.g. Ondo-AAPL-bsc) |
wallet | yes | Same wallet used in the bytecode call |
What appears in actions[]
| Action state | Listed? | Where to track instead |
|---|---|---|
PENDING | yes | This endpoint |
INITIAL (user has not sent the funding tx yet) | no | GET /actions/:id, WebSocket |
SUCCESS, REFUNDED, FAILED, etc. | no | History, wallet position, WebSocket |
Root response (always)
| Field | Type | Description |
|---|---|---|
strategyId | string | Strategy slug |
wallet | string | Checksummed address from query |
hasPending | boolean | true when actions.length > 0 |
message | string | Human-readable summary |
actions | array | Pending actions only (see below) |
orderBook:
orderBook field | Meaning |
|---|---|
canOpenOrder | Whether a new buy/sell request is likely to succeed right now |
code | Stable error code when canOpenOrder is false |
errorType | Additional machine-readable reason (nullable) |
message | Human-readable reason (nullable) |
retryable | Client may retry later (e.g. market closed) |
probeSellAmount | Amount used for the availability probe (raw units) |
probeBuyAmount | Expected output from probe when canOpenOrder is true (optional) |
actions is empty.
Each item in actions[]
Base fields (every pending action)
| Field | Notes |
|---|---|
type | Buy: SAMECHAIN_INVESTMENT_DEPOSIT or CROSSCHAIN_INVESTMENT_DEPOSIT. Sell: SAMECHAIN_INVESTMENT_WITHDRAW or CROSSCHAIN_INVESTMENT_WITHDRAW |
currentStep | First step still INITIAL or PENDING; null if none |
steps | Full pipeline snapshot |
steps[].legs[] | { kind, status, operator } — leg kind examples: SWAP, PRESIGN, TRANSFER, BRIDGE |
suw).
suw block (Ondo Global Markets request-lend / request-withdraw only)
suw field | Meaning |
|---|---|
singleUseAddress | Ephemeral wallet executing the async settlement |
phase | High-level lifecycle — see table below |
fundsReturnedToWallet | Final transfer to the user wallet completed |
order | Settlement order metadata; null if not created yet |
balances | Tokens on the single-use wallet during settlement; null after funds returned |
timing | Request age, SLA, refund countdown |
pricing | Reference vs live market price; null if unavailable |
suwSteps | Internal settlement substeps (presign, swap_and_settlement, forward_to_wallet) |
suw.phase lifecycle
| Phase | UI meaning |
|---|---|
awaiting_transfer | User has not completed the funding transfer |
awaiting_presign | Funds received; Pods preparing settlement |
order_in_progress | Settlement order open, awaiting fill |
awaiting_forward | Fill complete; final transfer to user wallet pending |
completed | Fully settled |
refunded / expired / failed / cancelled | Terminal — drops out of actions[] on next poll |
suw.order shapes
Not posted yet (posted: false):
posted: true): adds validTo, creationDate, executionDate,
executedSellAmount, executedBuyAmount, txHash. Typical status values: open,
fulfilled, unknown (with providerError when lookup fails).
Empty pending example
hasPending is true, or until suw.phase reaches a
terminal value.
Example
orderBook or suw.
WebSocket (recommended)
action_update events where action.id matches the bytecode response id:
| Status | Meaning |
|---|---|
PENDING | Awaiting settlement |
SUCCESS | Order filled |
FAILED | Order failed |
REFUNDED | Order refunded |
ACTION_UPDATE events).
History
Embedded inGET /v2/wallets/:address?include=all&fromActions=1 or:
SAMECHAIN_INVESTMENT_DEPOSIT; sells as SAMECHAIN_INVESTMENT_WITHDRAW. Ignore
INITIAL status (quote artifact).
Refresh positions
Refetch wallet/strategy endpoints after on-chain confirmation and after WebSocketSUCCESS.
8. Supported chains & USDC addresses
Stocks & ETFs settle on BSC; funding (buy) and payout (sell) can use any supported USDC chain.| Network | Chain ID | USDC |
|---|---|---|
| BSC | 56 | 0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d |
| Base | 8453 | 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913 |
| Arbitrum | 42161 | 0xaf88d065e77c8cC2239327C5EDb3A432268e5831 |
| Polygon | 137 | 0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359 |
fromChainId / toChainId are set, fromTokenAddress / toTokenAddress can be omitted — the
API defaults to USDC on that chain. A non-USDC token triggers an extra same-chain swap leg.
9. Errors
| Code | HTTP | When |
|---|---|---|
REQUEST_LEND_AMOUNT_TOO_LOW | 422 | Buy below $10 USDC |
LEND_AMOUNT_TOO_SMALL | 422 | Amount too small for quote |
WITHDRAW_AMOUNT_TOO_SMALL | 422 | Sell amount too small |
WITHDRAW_AMOUNT_REQUIRED | 400 | Missing amount/amountInShares |
FROM_TOKEN_NOT_SUPPORTED | 400 | Funding token not supported |
FROM_TOKEN_REQUIRED | 400 | Crosschain buy without funding token |
CROSSCHAIN_BRIDGE_NO_OUTPUT | 422 | Bridge returned no USDC for the buy |
USDC_NOT_SUPPORTED | 400 | USDC not configured for the chain |
UNSUPPORTED_CHAIN | 400 | Unknown fromChainId/toChainId |
QUOTE_NOT_FOUND | 404 | Re-quote |
QUOTE_EXPIRED | 400 | Re-quote |
NO_API_KEY / INVALID_API_KEY | 401 | Auth failure |
error.code in your UI for user-friendly messages.
10. Integration notes
- Use the correct actions:
request-lend(buy) andrequest-withdraw(sell). Do not use the genericlend/withdraw. - Sign on the right chain: buy = funding chain (
chainIdIn); sell = always BSC; position = BSC wallet. - Async completion: after the origin tx, Pods completes bridge (if crosschain) + order fill;
monitor via the action status, position, or
history. - Sells use shares: pass
amountInShares(18 decimals), notamount. - Smart accounts: pass
output=userOperationoroutput=fireblocks(withaccountId) on the bytecode endpoint. - Same EVM wallet works across funding/payout chains; the market-share position always lives on BSC.
Minimal example
Buy $10 of AAPL from Base (crosschain):response.bytecode (legs where chainId === 8453) on Base, then poll:
response.bytecode (legs where chainId === 56) on BSC, then poll the position until the
pending arrays clear.
Endpoint reference
| Concern | Method & Path |
|---|---|
| Market open? | GET /ondo/stocks/market-status |
| List Stocks & ETFs | GET /tokens?category=stock&chainId=56 |
| List strategies | GET /v2/strategies?protocol=Ondo&network=bsc |
| Strategy + position | GET /v2/strategies/:id?wallet=<addr>&fromActions=1 |
| Position per wallet | GET /v2/wallets/:addr/strategies/:id |
| Quote + bytecode | GET /strategies/:id/bytecode |
| Pending actions | GET /strategies/:id/status?wallet=<addr> |
| Wallet snapshot | GET /v2/wallets/:addr?include=all |
| History | GET /wallets/:wallet/history/:strategyId |
| Status updates | wss://<host>/updates |
x-api-key.