v1

latestOpenAPI 3.0.32026-08-041747125.8 KB
Deposits

Create a deposit

Initiates a deposit transaction to move funds into an optimal DeFi protocol.<br><br> User owned rebalancer contract must be pre-approved to spend tokens. The address of this contract is returned by the GET /v1/config/{walletAddress} endpoint. This contract gets deployed during first deposit and its address is pre-computed using CREATE2.<br><br> Both signature-based (gasless) and approval-based approvals are supported.<br><br> Actual deposit transaction is executed by an operator on behalf of the user after validating the request and JWT token.

Required Fields (All Deposits)

These fields are always required regardless of deposit method:

  • token: The symbol of the deposit token (e.g., "USDC", "USDT", "MUSD", "RLUSD", "USDG", "USDE", "PYUSD")
  • walletAddress: The user address making the deposit (must match JWT token). Currently only EOAs are supported (no smart contract wallets).
  • amount: The amount to deposit in token's raw unit (e.g., for USDC with 6 decimals, "1000000" = 1 USDC). Token details can be found in the GET /v1/pools endpoint. Minimum deposit amount is 0.1 of the token to cover gas fees for on behalf transaction.

Deposit Methods

Signature-Based Deposits (EIP-3009)

Supported for USDC, MUSD, and PYUSD tokens. This method enables gasless approval where the user signs an authorization permit off-chain, and MetaLend executes the transfer on-chain.

Additional required fields:

  • signature: The user's signature authorizing the transfer
  • validAfter: Unix timestamp indicating when the signature becomes valid
  • validBefore: Unix timestamp indicating when the signature expires. This must be greater than validAfter and within a short time window (max 1 minute in future).
  • nonce: A unique 32-byte hex string to prevent replay attacks
  • tokenName: The official name of the token (e.g., "USD Coin"), can be read on token contract (ERC20 standard).
  • tokenVersion: The token contract version, can be read on token contract (ERC20 standard).

Sign ReceiveWithAuthorization EIP-712 typed data structure as defined by the token contract.

Approval-Based Deposits

Supported for all tokens (USDT, USDC, MUSD, RLUSD, USDG, USDE, PYUSD). This method requires the user to approve the rebalancer contract before initiating the deposit by sending a transaction.

Additional requirements:

  • Standard ERC-20 approval via the token contract before calling this endpoint
  • Only the base required fields (chain, token, walletAddress, amount) are allowed in the request
  • Do NOT include signature, timestamp, or nonce fields for approval-based deposits

Authentication & Security

  • Requires JWT authentication via JWT token in the Authorization header
  • The JWT must contain the same wallet address as specified in the request body

Maintenance — deposits paused

MetaLend can temporarily pause new deposit creation while other API features (withdrawals, balances, config, pools, etc.) stay available.

When paused, this endpoint returns 503 Service Unavailable with internalCode DEPOSITS_PAUSED and does not create a deposit or return a tracking ID.

Processing Flow

  1. Check whether deposits are paused
  2. JWT verification to ensure the caller owns the specified wallet
  3. Request validation (chain, token, amount, address, signature/approval requirements)
  4. Deposit request is queued for processing with a unique tracking ID
  5. Returns immediately tracking ID
  6. Use GET /v1/deposits/{trackingId} to monitor the deposit progress

Response

Returns a tracking ID that can be used to poll the deposit status. The tracking ID is:

  • A randomly generated UUID

The tracking ID can be used with the status endpoint to check if the deposit was successful, failed, is still processing or is bridging.

Source of Funds — User's Own Wallet ERC20 Balance

Deposits move tokens from the user's own wallet (their personal ERC20 balance on-chain) into a DeFi protocol via the MetaLend rebalancer contract.

The chain field must be the chain where the user currently holds the ERC20 token balance in their wallet. For example, if the user has USDC on Ethereum, chain must be "ETHEREUM". If they have USDC on Base, chain must be "BASE".

Before calling this endpoint:

  1. Check the user's ERC20 balance: token.balanceOf(userWalletAddress) on the target chain — this is what they are depositing from.
  2. For approval-based deposits: call token.approve(rebalancerAddress, amount) on the same chain before calling this endpoint.
  3. For signature-based deposits (USDC/MUSD/PYUSD only): sign the ReceiveWithAuthorization permit off-chain — no on-chain approval transaction needed.

The rebalancer contract address to approve is returned by GET /v1/config/{walletAddress} in the rebalancerAddress field.

Notes

  • Smart contract wallets that do not comply with standard signature length are currently not supported
  • For signature-based deposits, ensure timestamps are within valid range

Rate limiting: 1 request per 6 seconds per client IP. Excess requests receive HTTP 429 with Retry-After, X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset headers (see RateLimitExceeded response).

post/v1/deposits

Request body

chain'ETHEREUM' | 'BASE' | 'POLYGON' | 'ARBITRUM' | 'OPTIMISM' | 'AVALANCHE' | 'LINEA' required

The blockchain network for this deposit. IMPORTANT: Do NOT derive this from wagmi's chain.name or chain.network — those use different naming conventions. Always use PoolBalance.chain from GET /v1/balances which is already in the correct API format. For chain switching before the on-chain approve() call, use PoolBalance.chainId (integer EVM chain ID) with switchChain({ chainId }). If you must map from wagmi/viem chainId to this field, use: - chainId 1 → "ETHEREUM" - chainId 8453 → "BASE" - chainId 137 → "POLYGON" - chainId 42161 → "ARBITRUM" - chainId 10 → "OPTIMISM" - chainId 43114 → "AVALANCHE" - chainId 59144 → "LINEA"

token'USDC' | 'MUSD' | 'USDT' | 'RLUSD' | 'USDG' | 'USDE' | 'PYUSD' required

Token symbol to configure (must be uppercase)

walletAddressstring required

User's Ethereum wallet address (must be checksummed per EIP-55)

amountstring required

Amount in token's smallest unit (minimum 0.1 to cover gas fees)

validAfterstring

Unix timestamp after which signature is valid (required for signature based approvals)

validBeforestring

Unix timestamp before which signature is valid (required for signature based approvals, max 1 min in future, > validAfter)

noncestring

Unique nonce for signature (required for signature based approvals)

signaturestring

EIP-712 signature for authorization (required for signature based approvals)

tokenNamestring

Token name for EIP-712 domain (required for signature based approvals)

tokenVersionstring

Token version for EIP-712 domain (required for signature based approvals)

Example request

{
  "amount": "1000000",
  "validAfter": "1700000000",
  "validBefore": "1700000100",
  "tokenName": "USD Coin",
  "tokenVersion": "2"
}

Response

Deposit initiated successfully

trackingIdstring required

Unique identifier to track deposit status

Example response

{
  "trackingId": "550e8400-e29b-41d4-a716-446655440000"
}