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