> ## Documentation Index
> Fetch the complete documentation index at: https://docs.getpara.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Yield

> Deposit USDC into a supported yield market, check the position, and withdraw through the REST API

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.

<Note>
  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.
</Note>

## Before you start

Use an API key from the [Developer Portal](https://developer.getpara.com) and an API-created, unclaimed EVM wallet that has completed key generation and share persistence. See [wallet lifecycle](/v3/rest/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.

Set `PARA_API_KEY` and `WALLET_ID` for your environment, then list the supported markets:

```bash markets.sh theme={null}
curl -H "X-API-Key: $PARA_API_KEY" \
  "https://api.beta.getpara.com/v1/wallets/$WALLET_ID/yield/markets"
```

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.

| Market | Chain ID | Market ID |
| - | - | - |
| Aave V3 Ethereum | `1` | `aave-v3:1:usdc` |
| Aave V3 Base | `8453` | `aave-v3:8453:usdc` |
| Aave V3 Sepolia | `11155111` | `aave-v3:11155111:usdc` |
| Morpho Steakhouse Prime V2 USDC (Ethereum) | `1` | `morpho-v2-ethereum-steakhouse-usdc` |
| Morpho Steakhouse Prime V2 USDC (Base) | `8453` | `morpho-v2-base-steakhouse-usdc` |

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`](https://etherscan.io/address/0xbeef088055857739C12CD3765F20b7679Def0f51) on Ethereum and [`0xbeef0e0834849aCC03f0089F01f4F1Eeb06873C9`](https://basescan.org/address/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:

```bash deposit.sh theme={null}
curl -X POST "https://api.beta.getpara.com/v1/wallets/$WALLET_ID/yield/deposits" \
  -H "X-API-Key: $PARA_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: aave-deposit-001" \
  -d '{"marketId":"aave-v3:11155111:usdc","amount":"10"}'
```

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.

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:

```bash status.sh theme={null}
curl -H "X-API-Key: $PARA_API_KEY" \
  "https://api.beta.getpara.com/v1/wallets/$WALLET_ID/yield/operations/$OPERATION_ID"
```

Read the supplied balance independently:

```bash position.sh theme={null}
curl -H "X-API-Key: $PARA_API_KEY" \
  "https://api.beta.getpara.com/v1/wallets/$WALLET_ID/yield/position?marketId=aave-v3:11155111:usdc"
```

After the deposit operation reaches `confirmed`, withdraw a specific amount (for example, `"amount":"5"`) or use `"all"` to request the full position:

```bash withdraw.sh theme={null}
curl -X POST "https://api.beta.getpara.com/v1/wallets/$WALLET_ID/yield/withdrawals" \
  -H "X-API-Key: $PARA_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: aave-withdraw-001" \
  -d '{"marketId":"aave-v3:11155111:usdc","amount":"all"}'
```

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:

```bash morpho-deposit.sh theme={null}
curl -X POST "https://api.beta.getpara.com/v1/wallets/$WALLET_ID/yield/deposits" \
  -H "X-API-Key: $PARA_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: morpho-deposit-001" \
  -d '{"marketId":"morpho-v2-base-steakhouse-usdc","amount":"10"}'
```

After the operation confirms, read its position:

```bash morpho-position.sh theme={null}
curl -H "X-API-Key: $PARA_API_KEY" \
  "https://api.beta.getpara.com/v1/wallets/$WALLET_ID/yield/position?marketId=morpho-v2-base-steakhouse-usdc"
```

Withdraw a USDC amount or set `amount` to `"all"` to redeem the full share balance captured when Para prepares the transaction:

```bash morpho-withdraw.sh theme={null}
curl -X POST "https://api.beta.getpara.com/v1/wallets/$WALLET_ID/yield/withdrawals" \
  -H "X-API-Key: $PARA_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: morpho-withdraw-001" \
  -d '{"marketId":"morpho-v2-base-steakhouse-usdc","amount":"5"}'
```

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:

| Provider | Market ID |
| - | - |
| Aave V3 | `aave-v3:84532:usdc` |
| Morpho V2 demo | `morpho-v2-base-sepolia-demo-usdc` |

For example, the Morpho deposit body is:

```json morpho-demo-deposit.json theme={null}
{"marketId":"morpho-v2-base-sepolia-demo-usdc","amount":"10"}
```

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.

## Status and retries

| Status | What your application should do |
| - | - |
| `pending` | Keep polling; Para has accepted the operation. |
| `submitted` | Keep polling. Signed bytes are stored and Para is tracking the transaction, even if RPC acceptance is uncertain. |
| `confirmed` | The final action succeeded with two confirmations in the canonical chain. This is not finality. |
| `failed` | A transaction reverted or its nonce was consumed. Check `error`, the position, and transaction history before creating a new request. |
| `requires_action` | Read `error`, correct the issue, then repeat the same POST with the same key and body. |
| `cancelled` | Unsigned work has stopped. |

`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 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](/v3/rest/permissions); yield has no separate policy setup.

For Morpho, deposit policies must allow `vaultBundlesV1Deposit` on the official wrapper: [`0x02912516d49dE997db75B9D7858faAE59209650B`](https://etherscan.io/address/0x02912516d49dE997db75B9D7858faAE59209650B) on Ethereum or [`0x2B08A911f48dE25A7e305D910Afb5597aBE8ea7B`](https://basescan.org/address/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:

```bash cancel.sh theme={null}
curl -X POST -H "X-API-Key: $PARA_API_KEY" \
  "https://api.beta.getpara.com/v1/wallets/$WALLET_ID/yield/operations/$OPERATION_ID/cancel"
```

Cancellation returns `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](/v3/rest/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.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.