MetaLend User Configuration API

User rebalancer configuration management

Operations 3

PUT /v1/config Update rebalancer configuration #
GET /v1/config/{walletAddress} Get rebalancer configuration #
GET /v1/config/default/{token} Get default configuration for token #

Work with this as data

Every API here is available over the APIs.io API and to AI agents over MCP.

MCP server

One button, every client — Claude, Cursor, VS Code and the rest.

https://apis.io/mcp

Tools for apis

7 MCP tools reach this
  • find_apisBrowse and filter every API in the catalog.
  • get_api_artifactsOne API's artifacts, grouped by type.
  • get_openapiThe primary OpenAPI for this API.
  • find_similar_apisAPIs that look like this one.
  • apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.
  • resolveTurn a domain, URL or GitHub org into the provider it belongs to.
  • find_cohortsEvery scored population of providers in the catalog.
All 92 tools →

Call it yourself

curl for this page
This API
curl "https://apis.io/api/v1/apis/metalend-user-configuration-api"
All apis
curl "https://apis.io/api/v1/apis?limit=25"

Discovery needs no key. Ratings and market analysis are Pro.

Get an API key

Free tier, no form to fill in. Signing in shares your email address with us — we store it to create your key and to recognise you if you sign in with another provider. See our Privacy Policy and Terms.

A second provider on the same verified email joins the account you already have.

OpenAPI Specification

metalend-user-configuration-api-openapi.yml Raw ↑
openapi: 3.2.0
info:
  title: MetaLend Rebalancing User Configuration API
  version: 0.1.0
  description: 'API for managing cross-protocol cross-chain DeFi rebalancing operations exposing:


    Auth – challenge/verify flow for JWT issuance.'
  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: User Configuration
  description: User rebalancer configuration management
paths:
  /v1/config:
    put:
      summary: Update rebalancer configuration
      description: Creates or updates the rebalancing configuration for a specific wallet address and token.
      operationId: updateConfig
      tags:
      - User Configuration
      security:
      - ApiKeyAuth: []
        JwtAuth: []
        OriginHeader: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateOrUpdateConfigRequest'
            example:
              walletAddress: '0x1234567890123456789012345678901234567890'
              token: USDC
              domainIds:
              - 11
              - 11
              - 11
              protocolIds:
              - 0
              - 1
              - 2
              poolAddresses:
              - '0xabcdefabcdefabcdefabcdefabcdefabcdefabcd'
              - '0x1111111111111111111111111111111111111111'
              - '0x2222222222222222222222222222222222222222'
              signature: '0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef01'
              includeRewardsApy: true
              requiredTvl: 5000000
              requiredLiquidityMultiplier: 10
              collateralExposure:
              - WETH
              - cbBTC
              - wstETH
              spendingCapRaw: '0'
      responses:
        '200':
          description: Configuration updated successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CreateOrUpdateConfigResponse'
              example:
                walletAddress: '0x1234567890123456789012345678901234567890'
                rebalancerAddress: '0x1234567890123456789012345678901234567890'
                configuredToken: USDC
                operation: UPDATED
        '201':
          description: Configuration created successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CreateOrUpdateConfigResponse'
              example:
                walletAddress: '0x1234567890123456789012345678901234567890'
                rebalancerAddress: '0x1234567890123456789012345678901234567890'
                configuredToken: USDC
                operation: CREATED
        '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'
                configProtocolsPoolsAndDomains:
                  $ref: '#/components/examples/ConfigProtocolsPoolsAndDomains'
                configValidationFailed:
                  $ref: '#/components/examples/ConfigValidationFailed'
                configInvalidSignature:
                  $ref: '#/components/examples/ConfigInvalidSignature'
        '401':
          $ref: '#/components/responses/UnauthorizedNoHeader'
        '403':
          $ref: '#/components/responses/Forbidden'
        '409':
          description: Conflict - config update not allowed
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              examples:
                updateConfigRejectedBridgeInProgress:
                  $ref: '#/components/examples/UpdateConfigRejectedBridgeInProgress'
                updateConfigRejectedRefillInProgress:
                  $ref: '#/components/examples/UpdateConfigRejectedRefillInProgress'
                updateConfigRejectedPoolWithBalance:
                  $ref: '#/components/examples/UpdateConfigRejectedPoolWithBalance'
                invalidCollateralExposureUnknownSymbols:
                  $ref: '#/components/examples/InvalidCollateralExposureUnknownSymbols'
                invalidCollateralExposureEmptyList:
                  $ref: '#/components/examples/InvalidCollateralExposureEmptyList'
                invalidCollateralExposureMaxSize:
                  $ref: '#/components/examples/InvalidCollateralExposureMaxSize'
                invalidCollateralExposureBlankEntry:
                  $ref: '#/components/examples/InvalidCollateralExposureBlankEntry'
                invalidCollateralExposureDuplicates:
                  $ref: '#/components/examples/InvalidCollateralExposureDuplicates'
                invalidCollateralExposureRequiresAave:
                  $ref: '#/components/examples/InvalidCollateralExposureRequiresAave'
                invalidCollateralExposureRequiredTvlNotMet:
                  $ref: '#/components/examples/InvalidCollateralExposureRequiredTvlNotMet'
        '429':
          $ref: '#/components/responses/RateLimitExceeded'
        '500':
          $ref: '#/components/responses/InternalError'
      x-agentcash-auth:
        mode: free
  /v1/config/{walletAddress}:
    get:
      summary: Get rebalancer configuration
      description: 'Retrieves the current rebalancing configuration state for a specific wallet address across all supported tokens.


        This endpoint returns configurations for each supported token, including:

        - **Rebalancer Address**: The smart contract address of the user''s rebalancer

        - **Rebalancing Manager Address**: The address of the rebalancing manager contract

        - **Configurations**: List of configuration items, one per supported token, each containing:

        - Token information

        - Domain IDs, Protocol IDs, and Pool contracts

        - **hasSignedConfig**: Boolean flag indicating the configuration state for this specific token


        **Understanding hasSignedConfig (per token):**

        - `true`: The user has signed and set their own custom configuration for this token

        - `false`: The user has not signed any configuration for this token yet, and the returned values represent the default configuration


        When `hasSignedConfig` is false for a token, the configuration data shows what the default state allows, but it hasn''t been actively set by the user for that token. This state must be signed by user to confirm the configuration. Each token can have a different `hasSignedConfig` status.


        **Note:** Requires a valid API key to query configurations.


        **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: getConfig
      tags:
      - User Configuration
      parameters:
      - name: walletAddress
        in: path
        required: true
        description: Ethereum wallet address
        schema:
          type: string
          pattern: ^0x[a-fA-F0-9]{40}$
        example: '0x1234567890123456789012345678901234567890'
      responses:
        '200':
          description: Configuration retrieved successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GetConfigResponse'
              example:
                walletAddress: '0x1234567890123456789012345678901234567890'
                rebalancerAddress: '0xabcdefabcdefabcdefabcdefabcdefabcdefabcd'
                rebalancingManagerAddress: '0x971ad06e6fde83b0265bd3ced5f5eaf30e269962'
                rebalancerExists: true
                configurations:
                - token: USDC
                  domainIds:
                  - 11
                  protocolIds:
                  - 0
                  poolAddresses:
                  - '0xc47b8c00b0f69a36fa203ffeac0334874574a8ac'
                  includeRewardsApy: true
                  lastRebalanceTimestamp: '2025-01-15T10:30:00Z'
                  rebalanceFrequency: 7
                  totalGasFee: '0.00'
                  totalDeposits: '0.00'
                  totalWithdrawals: '0.00'
                  requiredTvl: '0'
                  requiredLiquidityMultiplier: '0'
                  spendingCapRaw: null
                  spendingCapFormatted: null
                  hasSignedConfig: true
                - token: MUSD
                  domainIds:
                  - 11
                  protocolIds:
                  - 2
                  poolAddresses:
                  - '0xa7ada0d422a8b5fa4a7947f2cb0ee2d32435647d'
                  includeRewardsApy: true
                  lastRebalanceTimestamp: null
                  rebalanceFrequency: 7
                  totalGasFee: '0.00'
                  totalDeposits: '0.00'
                  totalWithdrawals: '0.00'
                  requiredTvl: '0'
                  requiredLiquidityMultiplier: '0'
                  spendingCapRaw: null
                  spendingCapFormatted: null
                  hasSignedConfig: false
                - token: USDT
                  domainIds:
                  - 11
                  - 11
                  protocolIds:
                  - 0
                  - 2
                  poolAddresses:
                  - '0xc47b8c00b0f69a36fa203ffeac0334874574a8ac'
                  - '0xcbef9be95738290188b25ca9a6dd2bec417a578c'
                  includeRewardsApy: true
                  lastRebalanceTimestamp: null
                  rebalanceFrequency: 7
                  totalGasFee: '0.00'
                  totalDeposits: '0.00'
                  totalWithdrawals: '0.00'
                  requiredTvl: '0'
                  requiredLiquidityMultiplier: '0'
                  collateralExposure:
                  - cbBTC
                  - WETH
                  spendingCapRaw: null
                  spendingCapFormatted: null
                  hasSignedConfig: false
        '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':
          $ref: '#/components/responses/InternalError'
      x-agentcash-auth:
        mode: free
  /v1/config/default/{token}:
    get:
      summary: Get default configuration for token
      description: 'Retrieves the default pool configuration state for a specific token including domain IDs, protocol IDs, and pool contract addresses.


        This endpoint returns the initial default configuration that shows how the system is set up for the specified token. The configuration includes:

        - **Domain IDs**: Cross-chain domain identifiers for the token

        - **Protocol IDs**: Identifiers of the supported DeFi protocols (e.g., Aave, Morpho, Euler)

        - **Pool Contracts**: Smart contract addresses for the respective pools

        - **Rebalancing Manager Address**: The address of the rebalancing manager contract


        This represents the default state of the configuration, which can be used as a reference or starting point for rebalancing operations. Use this to compare against user''s existing configuration.


        **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: getDefaultConfig
      tags:
      - User Configuration
      parameters:
      - name: token
        in: path
        required: true
        description: Token symbol (uppercase)
        schema:
          type: string
          enum:
          - USDC
          - MUSD
          - USDT
          - RLUSD
        example: USDC
      responses:
        '200':
          description: Default configuration retrieved successfully
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GetDefaultConfigResponse'
        '400':
          description: Validation error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
              examples:
                tokenNotSupported:
                  $ref: '#/components/examples/TokenNotSupported'
        '401':
          $ref: '#/components/responses/UnauthorizedNoHeader'
        '429':
          $ref: '#/components/responses/RateLimitExceeded'
        '500':
          $ref: '#/components/responses/InternalError'
      x-agentcash-auth:
        mode: free
components:
  examples:
    UpdateConfigRejectedBridgeInProgress:
      summary: Config update rejected - bridge in progress (USDC)
      value:
        code: CONFLICT_ERROR
        internalCode: UPDATE_CONFIG_REJECTED
        message: 'Config upsert rejected: Bridge in progress for USDC'
        requestId: 2c2f3dc1-d19a-49cb-b695-37d025e551b3
        retryAfterSeconds: null
    InvalidCollateralExposureDuplicates:
      summary: Duplicate symbols in collateralExposure list
      value:
        code: ILLEGAL_ARGUMENT_ERROR
        internalCode: INVALID_COLLATERAL_EXPOSURE
        message: 'Invalid collateral exposure: Collateral exposure list contains duplicate entries.'
        requestId: 2c2f3dc1-d19a-49cb-b695-37d025e551b3
        retryAfterSeconds: null
    ConfigInvalidSignature:
      summary: Invalid config signature
      value:
        code: ILLEGAL_ARGUMENT_ERROR
        internalCode: INVALID_SIGNATURE
        message: 'Invalid signature for address ''0x1234567890123456789012345678901234567890'': Config signature verification failed'
        requestId: 2c2f3dc1-d19a-49cb-b695-37d025e551b3
        retryAfterSeconds: null
    UpdateConfigRejectedRefillInProgress:
      summary: Config update rejected - refill in progress (USDC)
      value:
        code: CONFLICT_ERROR
        internalCode: UPDATE_CONFIG_REJECTED
        message: 'Config upsert rejected: Refill in progress for USDC'
        requestId: 2c2f3dc1-d19a-49cb-b695-37d025e551b3
        retryAfterSeconds: null
    InvalidCollateralExposureRequiresAave:
      summary: collateralExposure set but no Aave pool in configuration
      value:
        code: ILLEGAL_ARGUMENT_ERROR
        internalCode: INVALID_COLLATERAL_EXPOSURE
        message: 'Invalid collateral exposure: Collateral exposure is enabled: at least one Aave pool (protocol 0) is required. Set collateralExposure to null to save a configuration without Aave.'
        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
    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
    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
    InvalidCollateralExposureUnknownSymbols:
      summary: Unknown collateral symbols (not tracked in vault exposure)
      value:
        code: ILLEGAL_ARGUMENT_ERROR
        internalCode: INVALID_COLLATERAL_EXPOSURE
        message: 'Invalid collateral exposure: Unknown collateral symbol(s) not present in tracked vault exposure: FOO, XYZ'
        requestId: 2c2f3dc1-d19a-49cb-b695-37d025e551b3
        retryAfterSeconds: null
    ConfigProtocolsPoolsAndDomains:
      summary: Invalid configuration arrays (covers length mismatch, empty arrays, unsupported pools, and contract wallet rejected domain IDs)
      description: 'Returned for any of the following validation failures:

        - Array lengths of domainIds, protocolIds, and poolAddresses do not match

        - Any array is empty (at least 1 element required in each)

        - One or more pool addresses are not supported

        - Contract wallet signature was rejected on one or more chains in domainIds: "Contract wallets configs can only contain chains verified by supported signature. Found rejected domain IDs: $unsupportedDomainIds"

        '
      value:
        code: ILLEGAL_ARGUMENT_ERROR
        internalCode: INVALID_PROTOCOLS_POOLS_AND_DOMAINS
        message: 'Invalid configuration arrays: Domain IDs, protocol IDs, and pool contracts arrays must have the same length'
        requestId: 2c2f3dc1-d19a-49cb-b695-37d025e551b3
        retryAfterSeconds: null
    InvalidCollateralExposureRequiredTvlNotMet:
      summary: No configured Aave pool meets required minimum TVL
      value:
        code: ILLEGAL_ARGUMENT_ERROR
        internalCode: INVALID_COLLATERAL_EXPOSURE
        message: 'Invalid collateral exposure: Collateral exposure is enabled: at least one configured Aave pool must meet your required minimum TVL (5000000 USD). None qualify. LINEA: Aave market TVL 1000000 USD is below required minimum TVL 5000000 USD'
        requestId: 2c2f3dc1-d19a-49cb-b695-37d025e551b3
        retryAfterSeconds: null
    InvalidCollateralExposureBlankEntry:
      summary: Blank string in collateralExposure list
      value:
        code: ILLEGAL_ARGUMENT_ERROR
        internalCode: INVALID_COLLATERAL_EXPOSURE
        message: 'Invalid collateral exposure: Entry at index 0 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
    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
    ConfigValidationFailed:
      summary: Config validation failed
      value:
        code: ILLEGAL_ARGUMENT_ERROR
        internalCode: INVALID_SIGNATURE
        message: 'Invalid signature for address ''0x1234567890123456789012345678901234567890'': Config signature is blank'
        requestId: 2c2f3dc1-d19a-49cb-b695-37d025e551b3
        retryAfterSeconds: null
    InvalidCollateralExposureMaxSize:
      summary: collateralExposure list exceeds maximum length
      value:
        code: ILLEGAL_ARGUMENT_ERROR
        internalCode: INVALID_COLLATERAL_EXPOSURE
        message: 'Invalid collateral exposure: Collateral exposure list exceeds maximum allowed size of 200 entries.'
        requestId: 2c2f3dc1-d19a-49cb-b695-37d025e551b3
        retryAfterSeconds: null
    InvalidCollateralExposureEmptyList:
      summary: Empty collateralExposure array (use null to disable filter)
      value:
        code: ILLEGAL_ARGUMENT_ERROR
        internalCode: INVALID_COLLATERAL_EXPOSURE
        message: 'Invalid collateral exposure: Collateral exposure list cannot be empty. Use null to disable the filter.'
        requestId: 2c2f3dc1-d19a-49cb-b695-37d025e551b3
        retryAfterSeconds: null
    UpdateConfigRejectedPoolWithBalance:
      summary: Config update rejected - cannot remove pool with balance
      value:
        code: CONFLICT_ERROR
        internalCode: UPDATE_CONFIG_REJECTED
        message: 'Config upsert rejected: Cannot disable pool with balance'
        requestId: 2c2f3dc1-d19a-49cb-b695-37d025e551b3
        retryAfterSeconds: null
  responses:
    InternalError:
      description: Internal server error
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ApiError'
          examples:
            Internal Error:
              value:
                code: INTERNAL_ERROR
                internalCode: INTERNAL_ERROR
                message: An unexpected error occurred while processing your request
                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: Maximum number of requests allowed in the current window for this endpoint.
          schema:
            type: integer
            example: 1
        X-RateLimit-Remaining:
          description: Remaining requests in the current window.
          schema:
            type: integer
            example: 0
        X-RateLimit-Reset:
          description: Unix timestamp (seconds) when the current limit window resets.
          schema:
            type: integer
            format: int64
            example: 1713264123
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ApiError'
          examples:
            rateLimitExceededPerIp:
              summary: Rate limit exceeded (per client IP)
              value:
                code: RATE_LIMIT_EXCEEDED
                internalCode: THROTTLE_PER_IP
                message: Rate limit exceeded. Maximum 1 requests per 3 seconds allowed. Please try again later.
                requestId: 2c2f3dc1-d19a-49cb-b695-37d025e551b3
                retryAfterSeconds: 3
    Forbidden:
      description: User is not authorized to perform this action
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ApiError'
          examples:
            forbiddenGeneric:
              summary: Forbidden - not authorized
              value:
                code: FORBIDDEN
                internalCode: FORBIDDEN_GENERIC
                message: User is not authorized to perform this action
                requestId: 2c2f3dc1-d19a-49cb-b695-37d025e551b3
                retryAfterSeconds: null
  schemas:
    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)
    CreateOrUpdateConfigResponse:
      type: object
      required:
      - walletAddress
      - rebalancerAddress
      - configuredToken
      - operation
      properties:
        walletAddress:
          type: string
          description: User's wallet address
          example: '0x1234567890123456789012345678901234567890'
        rebalancerAddress:
          type: string
          description: Deployed rebalancer contract address
          example: '0x1234567890123456789012345678901234567890'
        configuredToken:
          type: string
          description: Configured token symbol
          example: USDC
        operation:
          type: string
          enum:
          - CREATED
          - UPDATED
          description: Operation performed
          example: CREATED
    GetDefaultConfigResponse:
      type: object
      required:
      - token
      - rebalancingManagerAddress
      - domainIds
      - protocolIds
      - poolAddresses
      properties:
        token:
          type: string
          description: Token symbol
          example: USDT
        rebalancingManagerAddress:
          type: string
          description: RebalancingManager contract address
          example: '0x971ad06e6fde83b0265bd3ced5f5eaf30e269962'
        domainIds:
          type: array
          items:
            type: integer
          description: Default domain IDs - match index values of protocolIds and poolAddresses
          example:
          - 11
          - 11
        protocolIds:
          type: array
          items:
            type: integer
          description: Default protocol IDs - match index values of domainIds and poolAddresses
          example:
          - 0
          - 2
        poolAddresses:
          type: array
          items:
            type: string
          description: Default pool contract addresses - match index values of domainIds and protocolIds
          example:
          - '0xc47b8c00b0f69a36fa203ffeac0334874574a8ac'
          - '0xcbef9be95738290188b25ca9a6dd2bec417a578c'
    GetConfigResponse:
      type: object
      required:
      - walletAddress
      - rebalancerAddress
      - rebalancingManagerAddress
      - rebalancerExists
      - configurations
      properties:
        walletAddress:
          type: string
          description: User's wallet address
          example: '0x1234567890123456789012345678901234567890'
        rebalancerAddress:
          type: string
          description: Deployed rebalancer contract address
          example: '0xabcdefabcdefabcdefabcdefabcdefabcdefabcd'
        rebalancingManagerAddress:
          type: string
          description: RebalancingManager contract address
          example: '0x971ad06e6fde83b0265bd3ced5f5eaf30e269962'
        rebalancerExists:
          type: boolean
          description: Whether a rebalancer contract has been deployed for this wallet
          example: true
        configurations:
          type: array
          items:
            $ref: '#/components/schemas/Configuration'
    CreateOrUpdateConfigRequest:
      type: object
      required:
      - walletAddress
      - token
      - domainIds
      - protocolIds
      - poolAddresses
      - signature
      properties:
        walletAddress:
          type: string
          pattern: ^0x[a-fA-F0-9]{40}$
          description: User's Ethereum wallet address (must be checksummed per EIP-55)
        token:
          type: string
          enum:
          - USDC
          - MUSD
          - USDT
          - RLUSD
          description: Token symbol to configure (must be uppercase)
        domainIds:
          type: array
          items:
            type: integer
          description: 'Domain IDs - must match length and index values must be relevant to protocolIds and poolAddresses.

            '
          example:
          - 11
          - 11
          - 11
        protocolIds:
          type: array
          items:
            type: integer
            enum:
            - 0
            - 1
            - 2
          description: Protocol IDs (0=Aave, 1=Morpho, 2=Euler) - must match length and index values must be relevant to domainIds and poolAddresses
          example:
          - 0
          - 1
          - 2
        poolAddresses:
          type: array
          items:
            type: string
            pattern: ^0x[a-fA-F0-9]{40}$
          description: Pool contract addresses (must be checksummed per EIP-55) - must match length and index values must be relevant to domainIds and protocolIds Each pool address must be unique within this configuration. The same pool cannot be included more than once.
        signature:
          type: string
          pattern: ^0x[a-fA-F0-9]{130}$
          description: User signature for configuration
        includeRewardsApy:
          type: boolean
          default: true
          description: Include rewards in APY calculations
        requiredTvl:
          type: number
          default: 0
          description: '*(Recommended)* Minimum TVL (in USD) a pool must have before the rebalancer will route funds into it. It is recommended to set this to avoid routing funds into low-liquidity pools. Pass `0` only to explicitly disable this filter. Example: `5000000` = $5M minimum TVL.

            '
        requiredLiquidityMultiplier:
          type: number
          default: 0
          description: '*(Recommended)* Minimum ratio of pool liquidity to the user''s position size. It is recommended to set this as a safety guard against thin markets. Pass `0` only to explicitly disable this filter. Example: `10` = pool must hold at least 10× the user''s position in available liquidity.

            '
        spendingCapRaw:
          type: string
          default: '0'
          description: '*(Optional)* Maximum amount in raw token units (unformatted integer) the rebalancer is allowed to move in a single transaction. Pass `"0"` for no cap. Example for USDC (6 decimals): `"1000000000"` = $1,000 cap.

            '
        collateralExposure:
          type:
          - array
          - 'null'
          default: null
          items:
            type: string
          description: 'Collateral exposure symbols for the pools in the configuration, must be taken from the pool catalog from GET /v1/pools, unique and not empty. If you want to disable the filter, pass null.

            '
          example:
          - WETH
          - cbBTC
          - wstETH
    Configuration:
      type: object
      required:
      - token
      - domainIds
      - protocolIds
      - poolAddresses
      - includeRewardsApy
      - totalGasFee
      - reba

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