DeFi Positions
BetaThis documents the new DeFi Positions response structure. The endpoint is in beta and the shape may still evolve as protocol coverage expands. It runs in parallel with the current
defi-positionsendpoint during the migration window.
Breaking change vs the current DeFi Positions endpoint (roll out by week of Aug 3, 2026)The new endpoint is faster and covers many more protocols and position types, but the response body is a different shape. Today's endpoint returns positions grouped by platform → sections → assets. The new endpoint returns a flat list of self-contained position "elements", each with a typed structure. See Breaking changes below before migrating.
Endpoint
GET https://api.vybenetwork.xyz/v4/wallets/{ownerAddress}/defi-positions
Authentication: send your API key in the X-API-KEY header.
| Path parameter | Type | Description |
|---|---|---|
ownerAddress | string | Solana wallet address (base58). |
Response envelope
The payload is wrapped in a standard envelope. data is an object with a portfolio array — one entry per position — so more top-level data can be added under data later without another breaking change.
{
"message": "success",
"data": {
"portfolio": [ /* PortfolioElement[] — see below */ ]
},
"partial_failures": [ /* present only on a 502 partial result */ ]
}There is no platform grouping. Each element carries its own platformId — group by it client-side to reconstruct a per-platform view.
Element — one position
Every element shares these top-level fields:
| Field | Type | Notes |
|---|---|---|
type | string | borrowlend | liquidity | leverage | trade | multiple — determines the data shape |
networkId | string | "solana" |
platformId | string | e.g. "kamino" — group by this to reconstruct "platforms" |
value | number | null | USD value of the position (null = unknown) |
label | string | e.g. Lending, LiquidityPool, Leverage, LimitOrder, Staked |
name | string? | optional |
tags | string[]? | optional |
netApy | number? | optional |
data | object | shape depends on type (below) |
The 5 element types
borrowlend— supply/borrow (Kamino, MarginFi, Save, Drift, Jupiter Lend).data:suppliedAssets[],borrowedAssets[],rewardAssets[],suppliedValue,borrowedValue,rewardValue,suppliedYields[][],borrowedYields[][],healthRatio(nullable),ref?,sourceRefs?,link?.liquidity— LP / concentrated liquidity / farms / vaults (Orca, Raydium, Meteora, …).data.liquidities[], each withassets[],assetsValue,rewardAssets[],rewardAssetsValue,value,yields[],name?.leverage— perps / margin (Jupiter Perps, Drift, Phoenix Perps).data.isolated?/data.cross?; positions carryside(long/short),entryPrice,markPrice,size,sizeValue,pnlValue,liquidationPrice,leverage?.trade— limit orders / DCA (Jupiter, Phoenix Spot).data.assets.{input,output},inputAddress,outputAddress,initialInputAmount,withdrawnOutputAmount,inputPrice,outputPrice,filledPercentage?.multiple— holdings / staked / rewards / vesting / airdrops.data.assets[]+data.assetsYields[][].
Asset — tagged union (token | generic | collectible)
token | generic | collectible){
"type": "token",
"networkId": "solana",
"value": 8.0,
"attributes": { "isClaimable": true, "lockedUntil": 1735689600000, "tags": ["Staked"] },
"name": "Wrapped SOL",
"imageUri": "https://...",
"ref": "8omWcZPoo...",
"sourceRefs": [{ "name": "Market", "address": "7u3HeH..." }],
"link": "https://app.kamino.finance",
"data": {
"address": "So1111...112",
"amount": 0.1,
"price": 80.0,
"yield": { "apr": 0.042, "apy": 0.043 }
}
}The generic (e.g. prediction markets) and collectible (NFT) variants share the same envelope with a different data block — both are shown in the complete example below.
Complete example — one of every element & asset type
The array below contains all 5 element types and all 3 asset variants (token, generic, collectible), with every field each can carry. Inline // notes are annotations, not part of the payload: fields marked optional are omitted when absent; null means "known-unknown" (e.g. an unpriced token).
{
"message": "success",
"data": {
"portfolio": [
// ─── type: "borrowlend" — supply/borrow (Kamino, MarginFi, Save, Drift, Jupiter Lend) ───
{
"type": "borrowlend",
"networkId": "solana",
"platformId": "kamino",
"value": 8.45,
"label": "Lending", // Lending | Leverage | Vault | Deposit | Farming | Staked
"name": "Main Market", // optional
"tags": ["Multiply"], // optional
"netApy": 0.043, // optional
"data": {
"value": 8.45,
"suppliedAssets": [
{
"type": "token", "networkId": "solana", "value": 8.0,
"attributes": {}, "name": "Wrapped SOL", "imageUri": "https://.../sol.png",
"data": { "address": "So1111...112", "amount": 0.1, "price": 80.0,
"yield": { "apr": 0.042, "apy": 0.043 } }
}
],
"borrowedAssets": [
{
"type": "token", "networkId": "solana", "value": 1.1, "attributes": {},
"data": { "address": "EPjFWdd5...v", "amount": 1.1, "price": 1.0 }
}
],
"rewardAssets": [],
"unsettled": { "assets": [], "value": 0 }, // optional
"suppliedValue": 8.0,
"borrowedValue": 1.1,
"rewardValue": 0,
"suppliedYields": [ [ { "apr": 0.042, "apy": 0.043 } ] ],
"borrowedYields": [ [ { "apr": -0.08, "apy": -0.077 } ] ], // borrow cost is negative
"suppliedLtvs": null,
"borrowedWeights": null,
"healthRatio": 1.0, // nullable
"expireOn": 1735689600000, // optional (ms)
"contract": "8omWcZPoo...", // optional
"ref": "8omWcZPoo...", // optional
"sourceRefs": [ { "name": "Market", "address": "7u3HeH..." } ], // optional
"link": "https://app.kamino.finance" // optional
}
},
// ─── type: "liquidity" — LP / concentrated liquidity / farms / vaults (Orca, Raydium, Meteora) ───
{
"type": "liquidity",
"networkId": "solana",
"platformId": "orca",
"value": 155.5,
"label": "LiquidityPool", // LiquidityPool | Farming | Vault | Deposit | Staked
"name": "Whirlpool", // optional
"netApy": 0.116, // optional
"data": {
"liquidities": [
{
"assets": [
{ "type": "token", "networkId": "solana", "value": 80.0, "attributes": {},
"data": { "address": "So1111...112", "amount": 1.0, "price": 80.0 } },
{ "type": "token", "networkId": "solana", "value": 72.4, "attributes": {},
"data": { "address": "EPjFWdd5...v", "amount": 72.4, "price": 1.0 } }
],
"assetsValue": 152.4,
"rewardAssets": [
{ "type": "token", "networkId": "solana", "value": 3.1, "attributes": { "isClaimable": true },
"data": { "address": "orcaEKTd...", "amount": 2.0, "price": 1.55 } }
],
"rewardAssetsValue": 3.1,
"value": 155.5,
"yields": [ { "apr": 0.11, "apy": 0.116 } ],
"name": "SOL-USDC", // optional
"contract": "HJPjkq...", // optional
"ref": "9xQeWv...", // optional
"sourceRefs": [ { "name": "Pool", "address": "HJPjkq..." } ], // optional
"link": "https://www.orca.so" // optional
}
]
}
},
// ─── type: "leverage" — perps / margin (Jupiter Perps, Drift, Phoenix Perps) ───
{
"type": "leverage",
"networkId": "solana",
"platformId": "jupiter",
"value": 416.5,
"label": "Leverage", // Leverage | Margin
"data": {
"isolated": { // optional — isolated-margin positions
"positions": [
{
"address": "5Cx...", // optional
"name": "SOL-PERP", // optional
"imageUri": "https://...", // optional
"collateralValue": 100.0,
"side": "long", // long | short
"entryPrice": 78.2,
"markPrice": 80.0,
"size": 2.5,
"sizeValue": 200.0,
"pnlValue": 4.5,
"liquidationPrice": 41.0,
"leverage": 2.0, // optional
"tp": 120.0, // optional
"sl": 60.0, // optional
"value": 104.5,
"ref": "5Cx...", // optional
"sourceRefs": [ { "name": "Pool", "address": "5Cx..." } ] // optional
}
],
"value": 104.5
},
"cross": { // optional — cross-margin; positions omit collateralValue
"leverage": 1.5, // optional
"collateralAssets": [ // optional
{ "type": "token", "networkId": "solana", "value": 300.0, "attributes": {},
"data": { "address": "EPjFWdd5...v", "amount": 300.0, "price": 1.0 } }
],
"collateralValue": 300.0,
"positions": [
{ "side": "short", "entryPrice": 80.0, "markPrice": 78.0, "size": 1.0,
"sizeValue": 78.0, "pnlValue": 2.0, "liquidationPrice": 130.0, "value": 80.0 }
],
"value": 312.0
},
"value": 416.5,
"contract": "PERPHjGB...", // optional
"ref": "5Cx...", // optional
"sourceRefs": [ { "name": "Pool", "address": "5Cx..." } ], // optional
"link": "https://jup.ag/perps" // optional
}
},
// ─── type: "trade" — limit orders / DCA (Jupiter, Phoenix Spot) ───
{
"type": "trade",
"networkId": "solana",
"platformId": "jupiter",
"value": 100.0,
"label": "LimitOrder", // LimitOrder | DCA | SmartDCA
"data": {
"assets": {
"input": { "type": "token", "networkId": "solana", "value": 100.0, "attributes": {},
"data": { "address": "EPjFWdd5...v", "amount": 100.0, "price": 1.0 } },
"output": null // input or output may be null
},
"inputAddress": "EPjFWdd5...v",
"outputAddress": "So1111...112",
"initialInputAmount": 100.0,
"withdrawnOutputAmount": 0.0,
"expectedOutputAmount": 1.25, // optional
"inputPrice": 1.0,
"outputPrice": 80.0,
"filledPercentage": 0.0, // optional (0..1); omitted when unknown
"createdAt": 1730000000000, // optional (ms)
"expireAt": 1735000000000, // optional (ms)
"contract": "jupoNjAx...", // optional
"ref": "H9dQ...", // optional
"sourceRefs": [ { "name": "Order", "address": "H9dQ..." } ], // optional
"link": "https://jup.ag/limit" // optional
}
},
// ─── type: "multiple" — holdings / staked / rewards / vesting / airdrops. Shows all 3 asset variants ───
{
"type": "multiple",
"networkId": "solana",
"platformId": "pyth",
"value": 162.2,
"label": "Staked", // Wallet | Staked | Rewards | Vesting | Deposit | Airdrop
"name": "Staked", // optional
"netApy": 0.0, // optional
"data": {
"assets": [
// asset variant: "token" — full shape
{
"type": "token",
"networkId": "solana",
"value": 124.7,
"attributes": {
"lockedUntil": 1735689600000, // optional (ms)
"isDeprecated": false, // optional
"isClaimable": true, // optional
"tags": ["Staked"] // optional
},
"name": "Wrapped SOL", // optional
"imageUri": "https://.../sol.png", // optional
"ref": "GHDyCXmc...", // optional
"sourceRefs": [ { "name": "Pool", "address": "7u3HeHq..." } ], // optional
"link": "https://staking.pyth.network/", // optional
"data": {
"address": "So1111...112",
"amount": 1.56,
"price": 80.0,
"yield": { "apr": 0.07, "apy": 0.072 } // optional
}
},
// asset variant: "generic" — carries prediction-market detail (Jupiter Predict); every data field optional
{
"type": "generic",
"networkId": "solana",
"value": 25.0,
"attributes": {
"prediction": {
"sideName": "Yes", "entryPrice": 0.42, "markPrice": 0.55,
"size": 100.0, "sizeValue": 55.0,
"pnlValue": 13.0, "pnlPercent": 0.31,
"pnlAfterFeesValue": 12.5, "pnlAfterFeesPercent": 0.30,
"feesPaidValue": 0.5, "payoutValue": 100.0, "claimable": false,
"status": "open", "result": null, "createdAt": 1730000000000,
"market": { "marketTitle": "BTC > 100k?", "eventTitle": "Crypto",
"closeTime": 1735000000000, "settlementTime": null }
}
},
"data": { "address": "3ZZuTbwC...", "amount": 100.0, "price": 0.55 }
},
// asset variant: "collectible" — NFTs
{
"type": "collectible",
"networkId": "solana",
"value": 12.5,
"attributes": {},
"name": "Mad Lad #123", // optional
"data": {
"address": "9xQeWvG...",
"amount": 1,
"price": 12.5,
"name": "Mad Lad #123", // optional
"description": "...", // optional
"imageUri": "https://.../123.png", // optional
"dataUri": "https://.../123.json", // optional
"attributes": [ { "trait_type": "Background", "value": "Blue" } ], // optional
"collection": { "id": "J1S9H...", "floorPrice": 12.5, "name": "Mad Lads" } // optional
}
}
],
"assetsYields": [ [ { "apr": 0.07, "apy": 0.072 } ], [], [] ],
"ref": "GHDyCXmc...", // optional
"sourceRefs": [ { "name": "Pool", "address": "7u3HeHq..." } ], // optional
"link": "https://staking.pyth.network/" // optional
}
}
]
}
}Breaking changes vs the current endpoint (roll out by week of Aug 3, 2026)
1 · Overall shape
- Grouped → flat. Old:
data[].sections[].assets[]. New:data.portfolio[]is a flat list of position elements. Grouping by platform is now the client's job (group elements byplatformId). - New envelope. Response is
{ message, data, partial_failures? }, anddatais an object (data.portfolioholds the array) — not a top-level array.
2 · Asset fields
| Old (v4 asset) | New | Change |
|---|---|---|
type: "supplied"/"borrowed" | separate suppliedAssets / borrowedAssets / rewardAssets arrays | type now means token/generic/collectible, not the lending side |
address | data.address | moved |
symbol | — | removed (resolve from name/address client-side) |
logourl | imageUri | renamed |
amount | data.amount | moved |
usdValue | value | renamed + moved to asset top-level |
price (string) | data.price (number, nullable) | type change: string → number, may be null |
apy (number) | data.yield {apr, apy} + element netApy/suppliedYields/borrowedYields | number → object; APR and APY provided |
marketId, lendingMarketId | ref, sourceRefs[{name,address}] | replaced |
mev, mevValueUsd, stakeStatus, netStakeChange | — | removed as first-class fields; staking/MEV modeled as multiple/borrowlend elements + attributes |
3 · Platform fields
| Old | New | Change |
|---|---|---|
platform (display name) | — | removed (use platformId / a platforms lookup) |
platformPid | — | removed |
platformLogourl, platformLabels, platformWebsite | — | removed from this response |
totalValueUsd (per platform) | — | removed (sum element.value per platformId) |
platformId | platformId (per element) | kept, moved to element |
section.label/.type/.name | element.label/.type/.name | flattened onto the element |
4 · Value / number semantics
Monetary values (value, data.price) are now numbers and can be null (= unknown / unpriced). The old price was a decimal string. Clients must handle null.
5 · HTTP semantics
On a partial failure (one protocol handler errors), the new endpoint returns HTTP 502 with the successful data plus a partial_failures: [...] list — instead of failing the whole request. Treat 502-with-body as "render what's there, optionally retry."
6 · Newly available
Not representable in the old format: LP / concentrated-liquidity pairs with reward assets and yields, perps / margin (entry / mark / liquidation price, PnL, leverage), limit orders & DCA (input / output / fill), NFTs / collectibles, per-asset yield, healthRatio, lockedUntil / isClaimable, and prediction markets. Integrators that only handled supplied/borrowed will now see additional element types and should default-handle unknown types gracefully.
Migration checklist
- Stop reading
data[].sections[].assets[]; iteratedata.portfolio[]and switch onelement.type. - Group by
platformIdif you need the old platform view; sumelement.valuefor platform totals. - Update field access:
usdValue → value,pricestring → number (+null),logourl → imageUri,apy → data.yield.apy;symbolis gone. - Handle 502 +
partial_failuresas a soft failure. - Default-handle unknown element
types so new position kinds don't break parsing.
Updated about 17 hours ago