Why This Matters
Leverage is the most requested feature in every lending product, and the hardest to ship. Doing it by hand means a dozen supply/borrow/swap round trips, a new liquidation risk on every leg, and a partially-built position if any step fails. Most teams never ship it. We’ve done that work. One call returns one transaction that builds the whole position - or unwinds it - atomically. If any leg fails, nothing happens.What It Does
Let users take a leveraged position on a lending market: supply collateral, borrow against it, swap the borrowed token back to collateral, and repeat until they reach the leverage they asked for. Unwinding runs the same loop in reverse. Both are a single signature. You call our API, we return a transaction payload. You or your users sign and broadcast. Users get leverage, you capture the flow. Important: Users must first create a Credit Account and fund it with the collateral token. Looping never pulls from the user’s wallet mid-transaction - the Credit Account must already holdinitial_collateral_amount.
How a Loop Works
A loop is one transaction containing many iterations. Each iteration:- Supply the collateral token to the lending market
- Borrow the loan token at the requested
loan_to_value - Swap the borrowed token back to the collateral token
multiplier × initial_collateral_amount.
Every swap has a guaranteed floor
The API never chains one leg onto a hoped-for swap output. Each swap carries a minimum output enforced on-chain, and the next supply is sized against that minimum. A fill anywhere inside your slippage tolerance can never break a later step. Anything a swap delivers above the floor stays in the Credit Account as recoverable surplus, never lost.preview.estimated_max_dust is the worst-case bound on it. Tighter max_slippage_percent means less surplus.
estimated_max_dust is not a cost - it is money kept. The cost of entering a loop is preview.estimated_swap_cost: DEX fees plus price impact, in collateral-token units, excluding gas. That’s the amount the position has to earn back before it’s ahead.When the collateral is a vault share
Some markets take an ERC-4626 vault share as collateral - a yield-bearing token like a Morpho vault’ssteakUSDC. Those tokens have no honest DEX route: aggregators will still quote them, but through dust pools at prices far off net asset value. Since the loop derives its guaranteed floors from the quote, a mispriced quote would be executable rather than merely unroutable.
So the conversion goes through the vault instead of a DEX: a loop swaps the borrow token to the vault’s underlying asset and calls the vault’s own deposit(), and an unwind redeem()s the shares and swaps the underlying back. Both settle at net asset value. A direct route for the share token is only ever used when it prices within 1% of NAV. You do not configure any of this - pass the share token as collateral_token and the engine picks the path. Browse the vaults themselves with GET /v2/earn/vaults.
Supported Venues
Select the protocol per request with the
protocol field. It defaults to AAVE, so existing integrations need no changes. HyperLend and Felix are not separate protocol values — they are what Aave and Morpho resolve to on HyperEVM.
Euler V2 markets are available today for plain borrowing through Crypto-Backed Loans; full leverage support for them is on the way.
Finding a market to loop
Both discovery endpoints return everything you need to populate a market picker, and both accept achain filter:
/v2/earn/aave_marketsreturns each Aave reserve with its supply and borrow APY per chain. Despite living underearn, it is the rates source for Aave-style credit too — including HyperLend, which it serves as a read-only exception onchain=hyperevm. Pick a collateral token and a borrow token from it and pass their symbols straight to/loop./v2/credit/morpho_marketsreturns the curated Morpho market set with livelltv,borrow_apy,utilization, andavailable_liquidity, read on-chain per request. Sort bytvl_usd,liquidity_usd, orlltv. Themarket_idyou pass to/loopcomes from here, and the market’s own pair fixes yourcollateral_tokenandborrow_token.
lltv (Morpho) or the reserve LTV (Aave) is the ceiling on loan_to_value, and available_liquidity must exceed the loop’s total borrow or the build returns a 400.
Neither discovery endpoint knows anything about a particular user - both describe the market, not the account. Two per-account reads complement them:
GET /v2/credit/looped_positions- the leveraged positions this Credit Account already holds, with live leverage, health factor, and net APY. This is the one to poll for a dashboard; see Track Looped Positions.GET /v2/credit/positions- the account’s raw collateral and debt, plus aborrowable_tokensarray giving the maximum each token can still be borrowed at and its current APY. Only this endpoint reports remaining borrow capacity;looped_positionsdoes not carry it.
Chain coverage
Other chains in the
chain enum have no credit venue deployed yet and return a 422 naming the chains that do.
Preview Before You Build
preview: true gives you the projected end state without spending a firm quote. Use it on every call made while a user is moving a slider, and leave it false only for the build they actually intend to sign.
This matters: on firm-quoted pairs, quotes are single-use maker commitments. Requesting them for displays that are never executed degrades the pricing available to everyone on the API.
Three outcomes are possible:
These endpoints omit null fields from the JSON entirely rather than sending
null. Test for absence (?. / .get(...)), not for a null value - "quote_expires_at": null never appears on the wire.Pricing policy
Thepricing field controls how swap legs are routed:
pricing: "firm" is incompatible with gas_sponsorship: true - sponsored transactions always route through the aggregator.
The two routes differ in where the price comes from. A firm provider commits a quote at a fixed price for a short window, so the fill is exact: zero slippage and no dust, but the quote expires. A DEX aggregator routes the swap across on-chain pool liquidity at the prevailing rate, so the fill moves with the market and is protected by an on-chain minimum output derived from max_slippage_percent. The pricing values are named firm and market after the two.
Reading the pricing fields back
Open a Loop
Build a 2x WETH position on Aave, borrowing USDC at 70% LTV against 1 WETH already sitting in the Credit Account.preview: false for the build the user is about to sign, then sign and broadcast the returned transaction as usual.
What the loop preview tells you
Looping on Morpho
Same call, swapping the market identifier for amarket_id. This is the wstETH/WETH market at 96.5% LLTV on Ethereum; the body also carries owner and chain.
collateral_token and borrow_token must match the market’s own pair, or the call is a 422. market_id is Morpho-only and emode_category is Aave-only — sending either on the wrong protocol is a 422 rather than a silent no-op.
Track Looped Positions
GET /v2/credit/looped_positions reconstructs each leveraged position from indexed on-chain events - a transaction carrying lending, borrowing, and swap legs is a loop. It takes chain and owner, with no filters or pagination.
Detection is event-shaped, not API-created: a position assembled by hand through /v2/credit/bundle shows up the same way. The events do have to belong to the Credit Account derived from owner - leverage held directly by an EOA is invisible here. If the Credit Account isn’t deployed yet, the call is a 400.
status (OPEN / CLOSED), live current state, lifetime totals, and a full history of classified transactions (loop_open, loop_increase, unwind, liquidation, and single-sided actions), each with the detected swap leg.
Two fields deserve care:
health_factor_scopeis"market"on Morpho (isolated per market) and"account"on Aave. Aave collateral is pooled, so one health factor is shared by every Aave position on the account - seeaave_account_summaryfor the account-level figures.net_apyis the levered carry on equity:leverage × collateral_apy − (leverage − 1) × borrow_apy. It is a snapshot at today’s rates, not a forecast, and it is denominated in the debt asset - a positivenet_apystill loses USD value if the pair moves against the user. It isnullwhen either leg is unknown rather than guessed.
Unwind a Loop
POST /v2/credit/unloop runs the loop in reverse: withdraw collateral, swap it to the borrow token at a guaranteed minimum, repay.
Positions that need two transactions
Each withdrawal is sized to keep the health factor at or above 1.02 at that step. A position opened very close to its liquidation threshold may not have enough headroom to reach the target in one transaction. Setallow_partial: true to take the maximum single-transaction progress instead of a 400. The response comes back with preview.fully_unwound: false; call unloop again from the now much lower leverage to finish. Without it, an unreachable target is an error.
The unloop preview adds ending_collateral, ending_debt, ending_multiplier, and fully_unwound to the shared fields.
Closing an Aave position that shares a reserve
Aave holds one pooled balance per reserve, not one per pair. So if an account has two open Aave loops using the same collateral token, a full close of one does not withdraw the whole reserve balance - it withdraws only that position’s attributed share, leaving the rest supplied to back the other loop.preview.ending_collateral reports what stays behind, so read it rather than assuming zero on a full close. Morpho markets are isolated and have no such interaction.
Rebalance a Whole Book
POST /v2/credit/rebalance moves several positions toward their desired end states in one atomic transaction. Each entry in targets names a position and a goal - target_equity_usd (size), target_multiplier (leverage), both, or close: true.
The engine derives one of seven directions per target and reports it as preview.per_target[].direction:
Three properties are worth designing around:
- Scoped, not a portfolio wipe. Positions not named in
targetsare left untouched. - It releases capital before it consumes it. Delevers and closes run first, freed collateral is routed between positions with capital-routing swaps when the tokens differ, then grows and opens run. A shrink on one position can fund a grow on another - including across protocols, in the same transaction.
- Growth beyond freed capital comes from the Credit Account’s idle balance. If the book grows past what’s available you get a 422 asking you to fund the account first with
/v2/credit/transfer.
preview still comes back with every direction set to noop, and there is no transaction to sign. That makes rebalance safe to poll in a converge loop.
Rebalance runs on Ethereum, Base, Arbitrum, and BNB Chain. It is not available on HyperEVM - use
/loop and /unloop there. Also note that at most one Aave target per collateral token and per borrow token is allowed per call, because Aave pools collateral and debt per reserve rather than per pair.HyperEVM: HyperLend and Felix
Looping runs on HyperEVM (chainhyperevm) against two venues:
HyperLend is registered as the chain’s Aave, so you address it with
protocol: "AAVE" - there is no separate protocol value.
/v2/credit/borrow when token_in differs from collateral_token. Supply the collateral token directly.
Rebalance is not available on HyperEVM. Use /loop and /unloop.
Only four tokens are registered on HyperEVM: WHYPE, wstHYPE, stHYPE, and a chain-native USDC at its own address (not the mainnet one).
Errors Worth Handling
The OpenAPI spec only declares200 and 422. These runtime errors are the ones a real integration hits, so handle them explicitly. Each carries a prose message with the actionable figure - surface it rather than a generic failure.
Loop
Unloop
Both
Under
pricing: "auto" the 409 and 502 cases never surface - a firm-provider failure falls back to the aggregator transparently.
Use Cases
Levered staking carry: Loop a liquid-staking token against the asset it stakes. The collateral earns the staking rate, the debt costs the borrow rate, and leverage multiplies the spread. Example: 10 wstETH looped to 4x against WETH. Collateral earns 3.1%, WETH borrows at 2.4%. Levered carry on equity: 4 × 3.1% − 3 × 2.4% = 5.2% versus 3.1% unlevered. One-click leverage in a lending UI: Add a leverage slider next to an existing borrow flow. Call/loop with preview: true on every slider move to show projected health factor and entry cost, then build once on confirm.
Automated deleveraging: Poll looped_positions, watch health_factor, and call /unloop with a target_multiplier when a position drifts toward its threshold. Users never see a liquidation.
Call /unloop with preview: true first to read projected_health_factor, so you can pick the target multiplier that restores the buffer you want.
Book-level portfolio moves: Use /rebalance to shift a whole set of loops at once - close a Morpho position and open an Aave one, funded by the same freed collateral, in a single signature.
API Reference
Open a Leveraged Loop
Build a levered position in one atomic transaction.
Unwind a Leveraged Loop
Delever or fully close a position.
List Looped Positions
Live leverage, health factor, net APY, and full history.
Rebalance the Book
Move several positions to their target states at once.
Next Steps
Crypto-Backed Loans
Plain borrowing, repayment, and position tracking.
Product Accounts
Create and fund the Credit Account a loop runs from.
Gas Sponsorship
Sponsor gas so users never need a native token.