On environments where yield is enabled, eligible partner wallets can use it by default. You do not need separate enrollment or yield-specific permissions setup. Existing wallet authorization, configured transaction permissions, and REST rate limits apply.
Before you start
Use an API key from the Developer Portal and an API-created, unclaimed EVM wallet that has completed key generation and share persistence. See wallet lifecycle. The wallet needs USDC and ETH for gas.Choose a market
Before using Morpho, confirm with Para that the Morpho backend release is deployed and yield execution is enabled in your API environment. Beta and production availability must be verified separately. Listing a market identifies supported contracts; it does not guarantee that execution is enabled. SetPARA_API_KEY and WALLET_ID for your environment, then list the supported markets:
markets.sh
id as marketId in deposit and withdrawal requests and position queries. Para derives the chain and USDC contract from the selected market, so you can use the same request format for Aave and Morpho.
Existing requests that specify only chainId continue to select Aave V3 on that chain. You can also send both fields, but chainId must match the selected market.
Only market IDs returned by the catalog in your API environment are accepted. Omitting both
marketId and chainId, passing an unsupported market ID, passing a mismatched chainId, or including additional request fields returns 400 before an operation is created or any transaction is signed. You cannot supply an arbitrary token or vault address.
Mainnet markets use native USDC; USDT and Base USDbC are not supported. Sepolia uses Aave test USDC.
The selected Morpho Vault V2 contracts are 0xbeef088055857739C12CD3765F20b7679Def0f51 on Ethereum and 0xbeef0e0834849aCC03f0089F01f4F1Eeb06873C9 on Base. Para supports these two production vaults and does not select or manage strategies. Use a fork of the corresponding mainnet to test their strategies locally. The sandbox demo vault below exercises the API flow with test funds.
The wallet needs funds on the selected network. Use https://api.beta.getpara.com for test access and https://api.getpara.com for production access. The selected market determines the network independently of the API environment; mainnet requests use real funds.
Deposit, check, withdraw
This example requests a 10 USDC deposit into Aave V3 on Sepolia:deposit.sh
marketId: "aave-v3:1:usdc" or marketId: "aave-v3:8453:usdc" in deposit and withdrawal requests and position queries.
Send amounts as positive decimal USDC strings with at most six decimal places. The market fixes the token and contract; the recipient is the same wallet. Para approves the requested amount if needed, confirms that approval, then submits the deposit.
The response contains an operation id, status, and transactions array. A 202 response means Para accepted the work; it does not mean funds have moved. Set OPERATION_ID to the returned id and poll:
status.sh
position.sh
confirmed, withdraw a specific amount (for example, "amount":"5") or use "all" to request the full position:
withdraw.sh
OPERATION_ID to the withdrawal response’s id and poll the same status endpoint until it reaches confirmed. Then read the position again to verify the remaining supplied balance.
Morpho deposits and withdrawals
Use the same endpoints and operation polling with the Morpho market ID. This example requests a 10 USDC deposit on Base mainnet, which uses real funds even through the Beta API. For Ethereum, usemarketId: "morpho-v2-ethereum-steakhouse-usdc" in each request and position query:
morpho-deposit.sh
morpho-position.sh
amount to "all" to redeem the full share balance captured when Para prepares the transaction:
morpho-withdraw.sh
shares.balance is a raw integer with shares.decimals: 18; request amounts and suppliedBalance are USDC with six decimals. suppliedBalance uses previewRedeem for the current shares. Deposits round shares down, fixed-amount withdrawals round the shares burned up, and full redemptions round USDC received down.
Para deposits through Morpho’s official VaultBundlesV1 contract with a fixed 0.03% maximum share-price increase from the preview captured when the transaction is prepared, subject to integer rounding. The contract enforces that bound during execution. Para approves only the requested USDC amount when approval is needed and sets no referral fee. The guard has no time expiry; retries preserve it without refreshing or widening it. If an unsigned prepared deposit can no longer meet the guard, cancel it and use a new idempotency key for a new preview. The API does not expose a configurable slippage limit.
Morpho V2’s maxWithdraw and maxRedeem return zero and do not report withdrawal capacity. Para simulates a full redemption: withdrawal.availableAmount is the previewed full-position USDC value if that simulation succeeds, null if it fails, and zero for an empty position. This is not an exact maximum. A partial withdrawal may still succeed when a full exit cannot be simulated.
Para simulates the requested withdrawal before preparing it. A simulation failure pauses the operation as requires_action with SIGNING_REQUIRES_ACTION; this can indicate insufficient liquidity or another execution restriction. Correct the issue and retry the same request, or cancel unsigned work. A full withdrawal never silently becomes a partial withdrawal. Once prepared, retries preserve the exact transaction, including the captured share amount for "all"; shares received later are not included.
Test the Aave and Morpho demo
The sandbox demo supports both providers on Base Sepolia (84532) with the same test USDC. Select the provider with marketId; deposit, position, withdrawal, and operation polling use the same endpoints:
For example, the Morpho deposit body is:
morpho-demo-deposit.json
Switch markets
Select a differentmarketId to deposit into or query another market. Existing positions stay in their original markets. To move funds from Aave to Morpho (or between any supported markets), withdraw from the original market, wait for the operation to reach confirmed, then deposit into the new market. When the markets are on different chains, fund the wallet with USDC on the destination chain separately; yield requests do not bridge funds.
Status and retries
Idempotency-Key is required for deposits and withdrawals. Keep it stable for one intended operation, including after a timeout. Keys remain attached to yield operations; they do not use the generic REST 24-hour response cache. Changing the wallet, chain, market, action, or normalized amount with the same key returns 409.
Recognized temporary RPC failures before signing and waiting for another yield operation on the same wallet keep the operation pending; Para retries automatically. After signing, Para retries uncertain submissions using the stored signed bytes, without increasing fees or creating a replacement transaction. A prepared or signed yield transaction can block other REST broadcasts on the same wallet and chain until it is resolved or safely cancelled.
If the saved nonce has been consumed in a finalized block but Para cannot find a receipt for the original hash, the operation and transaction step become failed with error.code: "NONCE_CONSUMED" on the operation. The signed bytes can no longer execute, but this does not prove that no funds moved: check the position and transaction history before creating a new request. A dropped transaction whose nonce remains unused stays unresolved.
If error.code is AAVE_SUPPLY_CAP_EXCEEDED, the operation pauses as requires_action before signing the deposit. Retry the same request after Aave market capacity becomes available, or cancel the unsigned work. Any token approval that already confirmed remains in place.
Permissions and cancellation
Para can temporarily disable new yield execution or pause deposits during an incident. New affected operations return409 with code: "YIELD_DISABLED". Position reads, operation status, and cancellation of eligible unsigned work remain available.
Existing wallet authorization and V1/V2 transaction permissions apply to each signature, including token approval and the yield action. Configure those policies through the existing permissions API; yield has no separate policy setup.
For Morpho, deposit policies must allow vaultBundlesV1Deposit on the official wrapper: 0x02912516d49dE997db75B9D7858faAE59209650B on Ethereum or 0x2B08A911f48dE25A7e305D910Afb5597aBE8ea7B on Base. Withdrawals call withdraw or redeem on the selected vault. Token approvals name the wrapper as spender.
A policy review appears as error.code: "POLICY_REVIEW_REQUIRED" with error.reviewId. After the existing review is approved, retry the same yield request. Para reuses the exact prepared transaction and review ID, including its nonce and fees. Yield does not add a separate aggregate deposit spending limit. For "all", policies evaluate Aave’s maximum-uint256 withdrawal sentinel or Morpho’s captured share amount in the prepared redemption.
If another yield operation is active on the same wallet and chain, resuming a paused prepared transaction returns 409 with code: "YIELD_OPERATION_IN_PROGRESS". Wait for the active operation to resolve, then retry the same request.
If unsigned work cannot proceed, cancel it:
cancel.sh
409 for an unresolved signed transaction or a confirmed/failed operation. Cancelling after a confirmed approval stops the remaining deposit work but leaves that allowance in place. A cancelled operation cannot restart; use a new key for a new operation.
Position and transaction records
suppliedBalance is the current position value in USDC, not historical earnings. withdrawal.availableAmount is advisory and can be null when simulation fails or Aave debt prevents an estimate. Liquidity, protocol restrictions, and other wallet activity can change before execution. Use blockNumber and blockTimestamp to identify the snapshot.
Aave positions include reserve and availableLiquidity. Morpho positions include vaultAddress and shares; they omit the Aave reserve fields. Both include marketId and protocol.
Each signed step has a transactionId in transaction history, with intentKind: "yield". Existing rest.transaction.confirmed and rest.transaction.failed webhooks describe individual steps, so an approval confirmation does not mean the deposit is complete. Poll the yield operation for the overall result.