Integration Notes
The mistakes AI agents actually make wiring up Ozmium - pending orders versus positions, parameter scaling, prepended approvals, and safe unsupervised defaults.
This page is the accumulated list of things that go wrong. Read it before you write the integration, not after.
Pending Orders Are Not Positions
GET /v1/positions/{address} returns open positions. GET /v1/pending-orders/{address} returns
resting limit and stop orders that have not filled.
Pending orders hold collateral but carry no market exposure. An agent that sums both into "current exposure" will over-report risk and refuse trades it should take. An agent that ignores pending orders entirely will over-commit collateral it does not have.
Query both. Treat them separately.
Do Not Modify the Calldata
Transaction builders return { to, data, value } encoded for the exact contracts, parameter scales,
decimals, and market ids on Base mainnet. That encoding is the product.
If you re-encode, round, or "fix" any field, you own the result. The most common self-inflicted reverts come from an agent adjusting a value it did not need to touch.
Scaling Is Already Done
Gains gTrade uses leverage at 1e3, prices at 1e10, USDC at 6 decimals, and slippage at 1e3. Morpho Blue uses market ids and per-asset decimals. Aave uses its own. Uniswap v3 uses ticks.
The builders handle all of it. Send human-scale values in the request body; do not pre-scale them.
Approvals
Where an approve is required and the live allowance is short, builders prepend it. That means:
- Some responses contain more than one transaction. Broadcast them in the order given.
- A leverage decrease requires a collateral top-up, so the USDC approve is prepended automatically.
- LP adds prepend approves for both sides.
An agent that only broadcasts the first transaction in a multi-step response will approve and never act, or act and never approve.
Never Fabricate a Zero
GET /v1/portfolio/{address} returns confidence-gated USD valuation. When a valuation is not
confident, the endpoint says so rather than returning 0.
Read the Price from the Challenge
Prices may surge during congestion. Do not hardcode the prices from the docs. Read the amount from the 402 challenge on every call and sign that exact amount. See x402 Payments.
Payment Is Not Prop Authorization
The x402 fee buys the call. A prop desk action additionally requires a real onchain OZ transfer,
passed as payTxHash (agents) or burnTxHash (humans). Missing or invalid hashes are refused with
bad payTxHash or bad burnTxHash. See Prop.
Safe Defaults for Unsupervised Execution
An agent that will not be watching should behave differently from one a human is supervising:
- Full range on Uniswap v3. A concentrated position that leaves its band stops earning and sits fully converted into the losing side. Ozmium defaults to full range for exactly this reason. Do not narrow it unless something is monitoring it.
- Set TP and SL at open. Not later. There may not be a later.
- Size against what the market has done to this asset.
GET /v1/ideas/asset/{sym}returns a range-survival leverage. Use it as a ceiling. - Budget the rollover. Perpetual funding accrues continuously and moves the real liquidation point closer on a position left alone. A position held for a week is not the same trade as the same position held for an hour.
- Cap total spend. Both the USDC you pay in x402 fees and the capital you deploy. An unbounded retry loop against a 402 is an expensive bug.
Treat the Marker Feeds as Unproven
/v1/ta and /v1/ta/scan are experimental. There is no established out-of-sample edge, and none of
it is financial advice. If your agent acts on them, it should treat them as one input among several,
not as a trigger.
Idempotency and Retries
There is no idempotency key. A retried transaction builder call costs another $0.01 and returns fresh calldata against fresh market state, which is the correct behavior - stale calldata is a good deal worse than a second penny.
Retry the build. Never the broadcast. Do not rebroadcast a transaction you are not certain failed; check the chain first.
Rate Limits
Anonymous traffic has a low ceiling. Paid traffic is granted a far higher one automatically, keyed to the paying wallet. If you are rate limited while paying, you are probably retrying unpaid requests in a loop rather than sending the payment header.
Discovery for Frameworks
- MCP tool manifest:
https://ozmium.org/v1/tools.json - MCP server card:
https://ozmium.org/.well-known/mcp/server-card.json - OpenAPI 3.1 with
x-paymentpricing:https://ozmium.org/v1/openapi.json - Agent skills index:
https://ozmium.org/.well-known/agent-skills/index.json