MetaLend Balances API

Balance queries across pools and protocols

OpenAPI Specification

metalend-balances-api-openapi.yml Raw ↑
openapi: 3.0.3
info:
  title: MetaLend Rebalancing AI Agent Guide Balances API
  version: 0.1.0
  description: "API for managing cross-protocol cross-chain DeFi rebalancing operations exposing: <ul>\n  <li><b>Auth</b> – challenge/verify flow for JWT issuance.</li>\n  <li><b>Project settings</b> – fetch current project settings.</li>\n  <li><b>User configuration</b> – register or update token-level user-rebalancer settings and fetch current wallet configs.</li>\n  <li><b>Deposits</b> – create deposit intents, receive tracking IDs, and poll status through PROCESSING -> BRIDGING (cross-chain only) -> SUCCESS/FAILED/EMERGENCY_WITHDRAW. New deposits may return <b>503</b> with <b>DEPOSITS_PAUSED</b> during maintenance.</li>\n  <li><b>Withdrawals</b> – submit signed withdrawal requests, receive tracking IDs, and monitor status PROCESSING -> SUCCESS/FAILED.</li>\n  <li><b>Balances</b> – query wallet-level balances and withdraw details, as well as balances in bridge progress.</li>\n  <li><b>Rewards</b> – aggregated rewards and claim details per wallet.</li>\n  <li><b>Pools</b> – list supported protocols (Aave, Morpho, Euler, etc.), their pools, APY breakdowns, and TVL snapshots.</li>\n  <li><b>Transaction Costs</b> – current deposit/withdraw on-behalf transaction fees and minimum amounts by chain.</li>\n  <li><b>AI Agent Guide</b> – Markdown flow guide at <code>/SKILL.md</code> with signing formats, wizard requirements, and known integration gotchas.</li>\n</ul> All endpoints require an <b>X-API-Key</b>. <b>JWT authentication</b> is required on <b>deposit, withdrawal, and config update</b> operations.\n<b>Obtain API key by <a href=\"https://developer.metalend.tech/\" target=\"_blank\" rel=\"noopener noreferrer\">creating a new project</a>.</b>\nAll requests must include the Origin header. Use Origin: https://app.metalend.tech unless you have been assigned a different allowed origin."
  contact:
    name: MetaLend API Support
    email: support@metalend.tech
  termsOfService: https://metalend-inc.gitbook.io/litepaper/terms-of-service
  x-guidance: AI agents MUST read https://api.metalend.tech/SKILL.md before implementing any MetaLend operation. It contains critical signing formats, required headers, wizard flows for config setup, and known failure modes.
  x-default-api-key: a7f2b8c4d9e1f3a6b5c8d2e7f1a4b9c3d6e8f2a5b7c1d4e9f3a6b8c2d5e7f1a4
  x-api-key-guidance: Use x-default-api-key as X-API-Key for agent testing/integration. If you are the project owner, create or use your own project API key from https://developer.metalend.tech instead.
servers:
- url: https://api.metalend.tech
  description: Production server
security:
- ApiKeyAuth: []
  OriginHeader: []
tags:
- name: Balances
  description: Balance queries across pools and protocols
paths:
  /v1/balances/{walletAddress}:
    get:
      summary: Get rebalancer balances
      description: "Retrieves detailed balance information across all protocols and pools for a wallet address. This endpoint provides comprehensive financial data including token balances, net earnings, aggregate APY, and per-protocol/per-pool breakdowns.<br><br>\n\n**Authentication**: Requires a valid API key. The wallet address must be a valid checksummed EOA address.<br><br>\n\n**Token Filtering**: The optional `tokens` query parameter accepts a comma-separated list of token symbols (e.g., `USDC,MUSD,USDT`). If not provided, balances for all supported tokens are returned.<br><br>\n\n**Balance Details**: For each token, the response includes:\n- Total balance across all chains (raw units and human-readable format)\n- Net earnings in USD (calculated as current balance minus net deposits/withdrawals)\n- Aggregate APY (weighted average across all protocols)\n- Per-chain breakdown with per-protocol and per-pool details<br><br>\n\n**Spending / Card Balance (USDC only)**: For users with the MetaLend card \n  feature active in their configuration, the total rebalancer balance consists \n  of **two parts**:\n\n- **Regular rebalancing balance** — funds held across DeFi pools on all chains, \n  shown in `perToken[n].perChain[m].perProtocol[p].perPool[q]`.\n- **Card balance** — funds reserved on Linea for card spending, shown in \n  `perToken[n].spendingInfo`. This is USDC only and has two sub-components:\n  - Liquid USDC held in the rebalancer contract on Linea (`lineaUsdcBalance`)\n  - USDC deposited in Aave V3 on Linea, earning yield while available for \n    card spending (`lineaAaveUsdcBalance`)\n\n`spendingInfo` is `null` when the card feature is not active for the user. \n  When displaying total balance to the user, include both the pool balances \n  AND `spendingInfo` amounts — they are additive parts of the same rebalancer.\n\n**Withdraw Request**: Each pool balance includes optional `withdrawRequest` containing EIP-712 domain parameters, type definitions, and value structure for creating withdrawal signatures. The `value` field includes `token` and `poolContract` addresses, while `amount` and `deadline` must be supplied by the user when creating a withdrawal via `/v1/withdrawals` endpoint.<br><br>\n\n**Summary**: The response includes an aggregate summary with total balance across all queried tokens, total net earnings, queried tokens, and queried chains.<br><br>\n\n**Error Handling**: If blockchain queries fail or the wallet has no rebalancer configuration, appropriate error responses are returned. The endpoint uses an all-or-nothing approach - if any token query fails, the entire request fails with a 500 or 503 status code.\n\n**Rate limiting**: 1 request per 12 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).\n"
      operationId: getRebalancerBalances
      tags:
      - Balances
      parameters:
      - name: walletAddress
        in: path
        required: true
        description: User's Ethereum wallet address
        schema:
          type: string
          pattern: ^0x[a-fA-F0-9]{40}$
        example: '0x1234567890123456789012345678901234567890'
      - name: tokens
        in: query
        required: false
        description: Comma-separated list of token symbols to query
        schema:
          type: string
        example: USDC,MUSD,USDT
      responses:
        '200':
          description: Rebalancer balances retrieved successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GetBalancesResponse'
        '400':
          description: Validation error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              examples:
                walletAddressBlank:
                  $ref: '#/components/examples/WalletAddressBlank'
                invalidAddressFormat:
                  $ref: '#/components/examples/InvalidAddressFormat'
                invalidAddressCheckSum:
                  $ref: '#/components/examples/InvalidAddressCheckSum'
                tokenNotSupported:
                  $ref: '#/components/examples/TokenNotSupported'
        '401':
          $ref: '#/components/responses/UnauthorizedNoHeader'
        '429':
          $ref: '#/components/responses/RateLimitExceeded'
        '500':
          description: Internal error or query failed
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              examples:
                failedBalances:
                  $ref: '#/components/examples/FailedBalances'
                userDoesNotExist:
                  $ref: '#/components/examples/UserDoesNotExist'
                rebalancerDoesNotExistForWallet:
                  $ref: '#/components/examples/RebalancerDoesNotExistForWallet'
        '503':
          $ref: '#/components/responses/ServiceUnavailable'
      x-agentcash-auth:
        mode: free
  /v1/balances/bridge/{walletAddress}:
    get:
      summary: Get bridge balances
      description: 'Retrieves bridge balances for the specified wallet address.


        **Rate limiting**: 1 request per 3 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).

        '
      operationId: getBridgeBalances
      tags:
      - Balances
      parameters:
      - name: walletAddress
        in: path
        required: true
        description: User's Ethereum wallet address
        schema:
          type: string
          pattern: ^0x[a-fA-F0-9]{40}$
        example: '0x1234567890123456789012345678901234567890'
      responses:
        '200':
          description: Bridge balances retrieved successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GetBridgeBalancesResponse'
        '400':
          description: Validation error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              examples:
                walletAddressBlank:
                  $ref: '#/components/examples/WalletAddressBlank'
                invalidAddressFormat:
                  $ref: '#/components/examples/InvalidAddressFormat'
                invalidAddressCheckSum:
                  $ref: '#/components/examples/InvalidAddressCheckSum'
        '401':
          $ref: '#/components/responses/UnauthorizedNoHeader'
        '429':
          $ref: '#/components/responses/RateLimitExceeded'
        '500':
          description: Internal error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              examples:
                userDoesNotExist:
                  $ref: '#/components/examples/UserDoesNotExist'
                rebalancerDoesNotExistForWallet:
                  $ref: '#/components/examples/RebalancerDoesNotExistForWallet'
      x-agentcash-auth:
        mode: free
components:
  schemas:
    Token:
      type: object
      required:
      - symbol
      - name
      - address
      - decimals
      properties:
        symbol:
          type: string
          description: Token symbol
          enum:
          - USDC
          - MUSD
          - USDT
          - RLUSD
          example: USDC
        name:
          type: string
          description: Token full name
          example: USD Coin
        address:
          type: string
          pattern: ^0x[a-fA-F0-9]{40}$
          example: '0x1234567890123456789012345678901234567890'
          description: Token contract address
        decimals:
          type: integer
          description: Token decimals
          example: 6
        version:
          type: string
          nullable: true
          description: Token contract version
    SpendingInfo:
      description: 'Breakdown of USDC funds reserved on Linea for MetaLend card spending. Only returned when the card feature is active in the user''s config. The total rebalancer balance = regular pool balances (perChain) +  lineaUsdcBalance + lineaAaveUsdcBalance from this object.

        '
      type: object
      required:
      - lineaUsdcBalanceRaw
      - lineaUsdcBalanceFormatted
      - lineaAaveUsdcBalanceRaw
      - lineaAaveUsdcBalanceFormatted
      - lineaAaveApy
      properties:
        lineaUsdcBalanceRaw:
          type: string
          description: 'Liquid USDC held directly in the rebalancer contract on Linea (raw units,  6 decimals). This is uninvested and immediately available for card spending.

            '
        lineaUsdcBalanceFormatted:
          type: string
          description: Human-readable liquid USDC balance on Linea (formatted to 2 decimals).
        lineaAaveUsdcBalanceRaw:
          type: string
          description: 'USDC deposited in Aave V3 on Linea (raw units, 6 decimals). This is earning  yield and also counts toward the card spending balance. Add to  lineaUsdcBalanceRaw to get the full card balance.

            '
        lineaAaveUsdcBalanceFormatted:
          type: string
          description: 'Human-readable USDC balance in Aave V3 on Linea (formatted to 2 decimals).

            '
        lineaAaveApy:
          type: string
          description: 'Current APY of the Aave V3 USDC pool on Linea where card funds earn yield  (formatted to 2 decimals, e.g. "2.01").

            '
    GetBridgeBalancesResponse:
      type: object
      required:
      - walletAddress
      - rebalancerAddress
      - token
      - balances
      properties:
        walletAddress:
          type: string
          description: Wallet address
        rebalancerAddress:
          type: string
          description: Rebalancer contract address
        token:
          type: string
          description: Token symbol
        balances:
          type: array
          items:
            $ref: '#/components/schemas/BridgeBalance'
    Pool:
      description: "**Important: `poolAddress` is NOT globally unique across tokens.** For Aave V3, the same `poolAddress` (the Aave lending pool contract) is shared  across all tokens on a given chain. For example, Aave V3 USDC, USDT, and RLUSD  on Ethereum all have the same `poolAddress`.\nA pool is uniquely identified by the combination of THREE fields together:\n  - `poolAddress`\n  - `chain`\n  - `underlyingToken.symbol`\n\nWhen filtering pools by token (e.g. \"show only USDC pools\"), ALWAYS filter on  `underlyingToken.symbol`. Never filter on `poolAddress` alone for Aave pools.\n"
      type: object
      required:
      - protocolName
      - protocolVersion
      - protocolDescription
      - protocolUrl
      - poolAddress
      - poolName
      - chain
      - chainId
      - underlyingToken
      - poolTvl
      - poolLiquidity
      - poolApy
      - signData
      - blacklisted
      properties:
        protocolName:
          type: string
          description: Protocol name
          example: Aave
        protocolVersion:
          type: string
          description: Protocol version
          example: V3
        protocolDescription:
          type: string
          description: Protocol description
        protocolUrl:
          type: string
          format: uri
          description: Protocol website URL
        poolAddress:
          type: string
          description: Pool contract address. The pool contract address. For Aave V3 pools, this is the Aave lending pool contract address, which is the SAME for all tokens (USDC, USDT, RLUSD, MUSD) on a given chain. Do NOT use this field alone as a unique pool identifier — it must always be combined with `chain` and `underlyingToken.symbol`. For Morpho and Euler, this address IS unique per pool
          example: '0xabcdefabcdefabcdefabcdefabcdefabcdefabcd'
        poolName:
          type: string
          description: Pool name
        chain:
          type: string
          description: Chain name
          example: linea
        chainId:
          type: integer
          description: Chain ID
          example: 59144
        underlyingToken:
          $ref: '#/components/schemas/Token'
        poolTvl:
          type: string
          description: Total Value Locked for the pool
        poolLiquidity:
          type: string
          description: Available liquidity for the pool
        collateralExposure:
          type: object
          additionalProperties:
            type: string
          nullable: true
          description: 'Collateral exposure for the pool. Keys are Morpho market identifiers, values are the collateral token symbols for each market. Null for non-Morpho pools (Aave, Euler).

            '
          example:
            '0x3b3769cfb1649e84374e7f0e0e46cbf9a1a39a62fa6a8b82e9e9edd1b3a3e3f7': WETH
            '0xa1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2': cbBTC
        poolApy:
          $ref: '#/components/schemas/PoolApyInfo'
        signData:
          $ref: '#/components/schemas/PoolSignData'
        blacklisted:
          type: boolean
          description: Indicates whether the pool has been blacklisted (banned) due to a third party critical security issue. Blacklisted pools are deprecated and retained solely for backwards compatibility. New deposits are never routed to blacklisted pools, and all existing balances are automatically rebalanced out of such pools when possible (balance is large enough to pay on-behalf fee and there is enough liquidity to withdraw).
    Summary:
      type: object
      required:
      - totalBalanceFormatted
      - totalNetEarnings
      - queriedTokens
      - queriedChains
      properties:
        totalBalanceFormatted:
          type: string
          description: Total balance across all tokens (formatted to 2 decimals)
          example: '5000.00'
        totalNetEarnings:
          type: string
          description: Total net earnings in USD (formatted to 2 decimals)
          example: '45.67'
        queriedTokens:
          type: array
          items:
            type: string
          description: List of queried token symbols
          example:
          - USDC
          - MUSD
          - USDT
        queriedChains:
          type: array
          items:
            type: string
          description: List of queried chain names
          example:
          - linea
    GetBalancesResponse:
      type: object
      required:
      - walletAddress
      - rebalancerAddress
      - perToken
      - summary
      properties:
        walletAddress:
          type: string
          pattern: ^0x[a-fA-F0-9]{40}$
          example: '0x1234567890123456789012345678901234567890'
          description: User's Ethereum wallet address
        rebalancerAddress:
          type: string
          pattern: ^0x[a-fA-F0-9]{40}$
          example: '0xabcdefabcdefabcdefabcdefabcdefabcdefabcd'
          description: Rebalancer contract address
        perToken:
          type: array
          items:
            $ref: '#/components/schemas/TokenBalance'
        summary:
          $ref: '#/components/schemas/Summary'
    ProtocolBalance:
      type: object
      required:
      - protocolName
      - protocolIconUrl
      - totalBalanceRaw
      - totalBalanceFormatted
      - perPool
      properties:
        protocolName:
          type: string
          description: Protocol name
        protocolIconUrl:
          type: string
          description: Protocol icon URL
        totalBalanceRaw:
          type: string
          description: Total balance in protocol (raw units)
        totalBalanceFormatted:
          type: string
          description: Human-readable balance in protocol (formatted to 2 decimals)
          example: '28.05'
        perPool:
          type: array
          items:
            $ref: '#/components/schemas/PoolBalance'
    Value:
      type: object
      required:
      - token
      - poolContract
      properties:
        token:
          type: string
          description: Token address
        poolContract:
          type: string
          description: Pool contract address
        amount:
          type: string
          nullable: true
          description: 'The server always returns this as null. You MUST substitute your chosen withdrawal amount here before signing. Use the same value you will send in the WithdrawalRequest body. Must be ≤ PoolBalance.balanceRaw and ≥ minimum (e.g. 100000 for USDC = $0.10).

            '
        deadline:
          type: string
          nullable: true
          description: 'The server always returns this as null. You MUST substitute your chosen deadline here before signing. Use the same value you will send in the WithdrawalRequest body. Must be a unix timestamp no more than 60 seconds in the future.

            '
          example: '1763558621'
    PoolApyInfo:
      type: object
      required:
      - native
      - rewards
      - total
      - totalNet
      - performanceFee
      properties:
        native:
          type: string
          description: Native APY percentage (formatted to 2 decimals)
          example: '3.45'
        rewards:
          type: object
          additionalProperties:
            type: string
          description: Map of reward tokens to their APYs (formatted to 2 decimals)
          example:
            Merkle: '1.23'
            Brevis: '0.87'
        total:
          type: string
          description: Total APY percentage (formatted to 2 decimals)
          example: '5.55'
        totalNet:
          type: string
          description: Total net APY percentage (formatted to 2 decimals)
          example: '4.55'
        performanceFee:
          type: string
          description: Performance fee percentage (formatted to 2 decimals)
          example: '1.00'
    BridgeBalance:
      type: object
      required:
      - destinationPool
      - balanceRaw
      - balanceFormatted
      - estimatedCompletion
      - estimatedCompletionTimestamp
      - isForSpending
      properties:
        sourcePool:
          $ref: '#/components/schemas/Pool'
          nullable: true
        destinationPool:
          $ref: '#/components/schemas/Pool'
        balanceRaw:
          type: string
          description: Balance in raw units
        balanceFormatted:
          type: string
          description: Balance formatted
        estimatedCompletion:
          type: string
          description: Estimated completion timestamp or duration
        estimatedCompletionTimestamp:
          type: integer
          format: int64
          description: Estimated completion as Unix timestamp (seconds)
        isForSpending:
          type: boolean
          description: Whether the balance is reserved for spending
    TypeDetail:
      type: object
      required:
      - name
      - type
      properties:
        name:
          type: string
          description: Field name
          example: token
        type:
          type: string
          description: Field type
          example: address
    ChainBalance:
      type: object
      required:
      - chain
      - chainId
      - totalBalanceRaw
      - totalBalanceFormatted
      - perProtocol
      properties:
        chain:
          type: string
          description: Chain name
          example: linea
        chainId:
          type: integer
          description: Chain ID
          example: 59144
        totalBalanceRaw:
          type: string
          description: Total balance in raw units
        totalBalanceFormatted:
          type: string
          description: Total balance formatted
        perProtocol:
          type: array
          items:
            $ref: '#/components/schemas/ProtocolBalance'
    ApiError:
      type: object
      required:
      - code
      - internalCode
      - message
      properties:
        code:
          type: string
          description: Error category identifier
        internalCode:
          type: string
          description: More specific error identifier
        message:
          type: string
          description: Human-readable error message
        requestId:
          type: string
          format: uuid
          description: Unique request identifier for tracking
        retryAfterSeconds:
          type: integer
          description: Seconds to wait before retrying (for rate limiting)
    Domain:
      type: object
      required:
      - name
      - version
      - chainId
      - verifyingContract
      properties:
        name:
          type: string
          example: MetaLend Rebalancing
        version:
          type: string
          example: 4.0.0
        chainId:
          type: integer
          example: 59144
        verifyingContract:
          type: string
          description: Contract address
    Types:
      type: object
      required:
      - Withdrawal
      properties:
        Withdrawal:
          type: array
          items:
            $ref: '#/components/schemas/TypeDetail'
    TokenBalance:
      type: object
      required:
      - token
      - totalBalanceRaw
      - totalBalanceFormatted
      - netEarning
      - aggregateApy
      - perChain
      properties:
        token:
          type: string
          description: Token symbol
          example: USDC
        totalBalanceRaw:
          type: string
          description: Total balance in raw units
          example: '1000000000'
        totalBalanceFormatted:
          type: string
          description: Human-readable balance (formatted to 2 decimals)
          example: '1000.00'
        netEarning:
          type: string
          description: Net earnings in USD (formatted to 2 decimals)
          example: '12.34'
        aggregateApy:
          type: string
          description: Weighted average APY across all protocols (formatted to 2 decimals)
          example: '4.56'
        perChain:
          type: array
          items:
            $ref: '#/components/schemas/ChainBalance'
        spendingInfo:
          $ref: '#/components/schemas/SpendingInfo'
          nullable: true
          description: 'Card spending balance breakdown for USDC on Linea. Only present when the  user has the MetaLend card feature active in their configuration.  This balance is SEPARATE from the pool balances in `perChain` but is part  of the user''s total rebalancer balance. Display alongside pool balances  when showing the user their total holdings.

            '
        bridgeBalances:
          type: array
          nullable: true
          items:
            $ref: '#/components/schemas/BridgeBalance'
    PoolBalance:
      type: object
      required:
      - poolAddress
      - poolName
      - balanceRaw
      - balanceFormatted
      - apy
      - chain
      - chainId
      - withdrawRequest
      properties:
        poolAddress:
          type: string
          description: Pool contract address
          example: '0xabcdefabcdefabcdefabcdefabcdefabcdefabcd'
        poolName:
          type: string
          description: Pool name
        balanceRaw:
          type: string
          description: Balance in pool (raw units)
        balanceFormatted:
          type: string
          description: Human-readable pool balance (formatted to 2 decimals)
          example: '11.23'
        apy:
          type: string
          description: Current APY for this pool (formatted to 2 decimals)
          example: '4.56'
        chain:
          type: string
          description: Chain name
        chainId:
          type: integer
          description: Chain ID
        withdrawRequest:
          $ref: '#/components/schemas/WithdrawalRequestData'
    PoolSignData:
      type: object
      required:
      - protocolId
      - poolAddress
      - domainId
      properties:
        protocolId:
          type: integer
          description: Protocol ID (0=Aave, 1=Morpho, 2=Euler)
        poolAddress:
          type: string
          description: Pool contract address
        domainId:
          type: integer
          description: Domain ID for the chain
    WithdrawalRequestData:
      description: 'Always present when this pool has a non-zero balance. Contains the pre-filled EIP-712 domain, types, and partial value needed to sign a withdrawal. The `value.amount` and `value.deadline` are returned as null — you MUST fill them in with your chosen values before signing.

        '
      type: object
      required:
      - domain
      - types
      - value
      properties:
        domain:
          $ref: '#/components/schemas/Domain'
        types:
          $ref: '#/components/schemas/Types'
        value:
          $ref: '#/components/schemas/Value'
  examples:
    InvalidAddressCheckSum:
      summary: Invalid address checksum
      value:
        code: ILLEGAL_ARGUMENT_ERROR
        internalCode: INVALID_ADDRESS_CHECKSUM
        message: Invalid Ethereum address checksum. Please ensure the address is properly checksummed (EIP-55)
        requestId: 2c2f3dc1-d19a-49cb-b695-37d025e551b3
        retryAfterSeconds: null
    DepositsPaused:
      summary: Deposits temporarily paused (maintenance)
      value:
        code: SERVICE_UNAVAILABLE
        internalCode: DEPOSITS_PAUSED
        message: Deposits are temporarily paused
        requestId: 2c2f3dc1-d19a-49cb-b695-37d025e551b3
        retryAfterSeconds: null
    InvalidAddressFormat:
      summary: Invalid address format
      value:
        code: ILLEGAL_ARGUMENT_ERROR
        internalCode: INVALID_ADDRESS_FORMAT
        message: 'Invalid address format. Expected: 0x followed by 40 hexadecimal characters.'
        requestId: 2c2f3dc1-d19a-49cb-b695-37d025e551b3
        retryAfterSeconds: null
    UnauthorizedNoHeader:
      summary: No authorization header
      value:
        code: AUTHENTICATION_FAILED
        internalCode: NO_AUTH_INFO
        message: No authentication information provided
        requestId: 2c2f3dc1-d19a-49cb-b695-37d025e551b3
        retryAfterSeconds: null
    WalletAddressBlank:
      summary: Wallet address blank
      value:
        code: ILLEGAL_ARGUMENT_ERROR
        internalCode: BLANK_ADDRESS
        message: Wallet address cannot be blank
        requestId: 2c2f3dc1-d19a-49cb-b695-37d025e551b3
        retryAfterSeconds: null
    TokenNotSupported:
      summary: Token not supported
      value:
        code: ILLEGAL_ARGUMENT_ERROR
        internalCode: TOKEN_NOT_SUPPORTED
        message: 'Token ''RLUSD'' is not supported. Supported tokens: USDC, MUSD, USDT'
        requestId: 2c2f3dc1-d19a-49cb-b695-37d025e551b3
        retryAfterSeconds: null
    UserDoesNotExist:
      summary: User does not exist
      value:
        code: INTERNAL_ERROR
        internalCode: USER_DOES_NOT_EXIST
        message: User does not exist for wallet address '0x1234567890123456789012345678901234567890'
        requestId: 2c2f3dc1-d19a-49cb-b695-37d025e551b3
        retryAfterSeconds: null
    FailedBalances:
      summary: Failed to query balances
      value:
        code: INTERNAL_ERROR
        internalCode: FAILED_BALANCES
        message: Failed to query balances.
        requestId: 2c2f3dc1-d19a-49cb-b695-37d025e551b3
        retryAfterSeconds: null
    RebalancerDoesNotExistForWallet:
      summary: Rebalancer does not exist for wallet
      value:
        code: INTERNAL_ERROR
        internalCode: REBALANCER_DOES_NOT_EXIST_FOR_WALLET
        message: Rebalancer does not exist for wallet address '0x1234567890123456789012345678901234567890'
        requestId: 2c2f3dc1-d19a-49cb-b695-37d025e551b3
        retryAfterSeconds: null
  responses:
    ServiceUnavailable:
      description: Service temporarily unavailable
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ApiError'
          examples:
            DepositsPaused:
              $ref: '#/components/examples/DepositsPaused'
            Blockchain Unavailable:
              summary: Blockchain unavailable
              value:
                code: INTERNAL_ERROR
                internalCode: BLOCKCHAIN_UNAVAILABLE
                message: 'Failed to check token approval: ${e.message}'
                requestId: 2c2f3dc1-d19a-49cb-b695-37d025e551b3
                retryAfterSeconds: null
    UnauthorizedNoHeader:
      description: No authorization header provided
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ApiError'
          examples:
            unauthorizedNoHeader:
              $ref: '#/components/examples/UnauthorizedNoHeader'
    RateLimitExceeded:
      description: 'Too many requests for this endpoint. Limits are enforced per client IP for the public API routes backed by `RebalancerResource` (and related resources using the same filter).


        Response headers (when throttled):

        - `Retry-After`: seconds to wait before retrying (matches the rate-limit window duration for that endpoint).

        - `X-RateLimit-Limit`: maximum requests allowed in the window (e.g. `1`).

        - `X-RateLimit-Remaining`: remaining requests in the window (`0` when throttled).

        - `X-RateLimit-Reset`: Unix timestamp (seconds) when the limit window resets.


        `internalCode` in the JSON body is `THROTTLE_PER_IP` for IP-scoped limits (other values may apply for different scopes in the backend).

        '
      headers:
        Retry-After:
          description: Seconds to wait before retrying this endpoint.
          schema:
            type: integer
            example: 3
        X-RateLimit-Limit:
          description: Max

# --- truncated at 32 KB (34 KB total) ---
# Full source: https://raw.githubusercontent.com/api-evangelist/metalend/refs/heads/main/openapi/metalend-balances-api-openapi.yml