Skip to main content
Deposit USDC into a supported yield market, read the position, and withdraw to the same Para wallet. Your application selects the market and amount; Para prepares and signs the required transactions.
Eligible partner wallets can use yield 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

Set PARA_API_KEY and WALLET_ID for your environment, then list the supported markets:
markets.sh
Pass the returned 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
For Ethereum mainnet or Base mainnet, use 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. Add "urgency":"urgent" to a deposit or withdrawal body to use the shared EVM fee policy. Omit it or use "normal" for normal pricing. The saved choice applies to fresh unsigned approval and action transactions, including phases using autoRetry. Each phase estimates its own gas units; urgency changes prices only and does not guarantee confirmation time. Recovery still honors each phase’s original fee ceiling and deadline. The operation retains urgency through restarts. Omitted and explicit normal share the legacy durable identity; changing urgency under the same key returns 409. Prepared, reviewed and signed bytes stay unchanged on replay. 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
Read the supplied balance independently:
position.sh
After the deposit operation reaches confirmed, withdraw a specific amount (for example, "amount":"5") or use "all" to request the full position:
withdraw.sh
Set 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, use marketId: "morpho-v2-ethereum-steakhouse-usdc" in each request and position query:
morpho-deposit.sh
After the operation confirms, read its position:
morpho-position.sh
Withdraw a USDC amount or set amount to "all" to redeem the full share balance captured when Para prepares the transaction:
morpho-withdraw.sh
Morpho deposits mint vault shares. 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
Use that same market ID when reading the position or withdrawing. The Morpho demo vault holds test USDC idle and earns no lending yield. It tests deposits and withdrawals, not the production vaults’ strategies or returns. Base Sepolia demo markets are available only in sandbox and local test environments; Beta and production exclude them.

Switch markets

Select a different marketId 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.

Authorize automatic phase recovery

Add autoRetry to a deposit or withdrawal to recover its existing approval and action transactions within explicit fee ceilings. This works with the same supported Aave and Morpho markets. The wallet pays gas; retry authorization does not enroll gas sponsorship. Save yield-deposit.json once before submitting. Replace the wallet ID, choose a unique key and set a deadline in the next 24 hours. Keep this file unchanged after any submission attempt.
yield-deposit.json
Run with Node.js 22 or later and PARA_API_KEY set. The script reads the saved body, key and deadline on every run.
yield-auto-retry.mjs
If the request times out, rerun with the same file. Never create a new key or extend the deadline to bypass an unclear outcome. The SDK example below uses walletId, idempotencyKey and body loaded from this same saved job. Each ceiling uses the existing per-transaction semantics: gasLimit × maxFeePerGas for type 2, or gasLimit × gasPrice for type 0. An approval and an action are distinct transactions and can each incur fees up to their separately authorized ceiling. These are not an operation-wide cumulative budget; unused approval allowance does not increase the action ceiling. Separate chain charges, such as OP Stack L1 data and operator fees, are excluded. If allowance already covers a deposit, Para skips approval and uses only the action authorization. Withdrawals never need an approval transaction and use only the action authorization. If approval is needed but its ceiling is absent, signing pauses before that approval; an action ceiling does not implicitly authorize it. Reusing the key with changed ceilings or a changed deadline returns 409; an existing operation’s authorization cannot be enlarged or renewed. If a needed approval has no ceiling (AUTO_RETRY_PHASE_FEE_REQUIRED), or the prepared first transaction exceeds its ceiling (RECOVERY_FEE_CAP_REACHED), the operation becomes requires_action before that phase is signed. Replaying the same request cannot fix these immutable authorizations. Cancel the unsigned operation, then submit a new request with a new key and adequate ceilings. Cancellation must succeed first; an uncertain or already signed phase remains tracked and cannot be replaced this way. Any earlier confirmed approval stays in place. Each phase reuses shared automatic recovery. EVM replacements keep the same nonce, destination, value, calldata, gas limit and access list. Fees rise by at least 12.5%, rounded up, with fresh higher recommendations when affordable, at least 60 seconds after the prior broadcast. There is no fixed attempt count. Para checks the original ceiling, deadline, wallet authority, enrolling key and current policies before each attempt. Approval must confirm under the existing chain checks before the action can be signed. Para preserves the operation ID and each phase transaction ID through restarts and replacements, reconciles original and replacement hashes, and never repeats a confirmed or reverted phase with a fresh nonce. An ambiguous MPC outcome is not signed again automatically. Replacements reuse that phase’s principal accounting; a distinct action still receives its own policy evaluation. Initial policy review retains its exact prepared bytes and review ID. Current policy and same-transaction spend accounting must still be re-proven; incompatible accounting, including approved-overage authorization that shared recovery cannot safely reuse, stops signing before MPC. After approving the review, explicitly replay the same yield POST to resume an original phase proven never dispatched, while its original grant remains valid. Ambiguous signing and stops after signing cannot be reopened by replay. An approval of the original transaction does not authorize changed fees: a replacement must receive a fresh policy allow without a new transaction-bound approval, or retry signing stops. Poll the existing yield operation. autoRetry.phases[] contains each admitted phase, its transactionId, and the same public retry fields as a transaction lookup, including state, reason, attempts, bumpCount and latestAttemptHash. Phases can appear before a signature is available. The transactions array preserves signed phase progress; status: "confirmed" means the final yield action completed, not merely its approval. If the deadline expires after approval, the confirmed approval remains visible and the unsigned action does not run. Check error and the recorded phases for partial progress. Stopping authorization does not cancel a potentially submitted attempt: Para continues monitoring it and keeps wallet/chain exclusion while its outcome is unresolved. Never create another deposit or withdrawal just because a retry stopped or an RPC response was lost. After initializing the REST SDK, the same body is accepted by createYieldDeposit or createYieldWithdrawal, and getYieldOperation reads its progress. CreateYieldRequest types the request; RestYieldOperation.autoRetry.phases combines each phase and transaction ID with the shared RestAutoRetryDetails fields:
The REST SDK has no method for markets, positions, or cancellation. Call those endpoints directly, as shown on this page. Omitting autoRetry preserves the existing saved-byte recovery behavior below.

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, normalized amount, urgency, or retry authorization 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. Without autoRetry, 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. Without autoRetry, 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. With autoRetry, the same outcome uses error.code: "RECOVERY_NONCE_CONSUMED". 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 return 409 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 limits on decoded per-call amounts, use Contract argument limits. It includes complete Aave and Morpho USDC deposit policies, decode-gap fallback behavior, and the different amount semantics of fixed withdrawals, withdraw-all sentinels and share redemptions. 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 your backend approves the review, 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
Cancellation returns 409 for an unresolved signed transaction, uncertain signing outcome, or a confirmed/failed operation. For managed recovery, each attempt must have no signature or transaction hash and must be either prepared without dispatch authorization or definitively rejected before signing. Para releases any undispatched spend reservation atomically when cancelling. 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.