Euler Finance Accounts API
Account activity, discovered positions, and sub-account relationships. Legacy nested account payloads are flattened into account-vault rows in v3.
Account activity, discovered positions, and sub-account relationships. Legacy nested account payloads are flattened into account-vault rows in v3.
openapi: 3.1.0
info:
title: Euler Data API (V3) Accounts API
version: 3.0.0
description: "API specification for Euler Data v3. This spec defines the current\nresource-oriented contract for the platform, with emphasis on consistent\nschemas, predictable REST semantics, caching, observability, and a uniform\ndeveloper experience.\n\nMigration notes\n- Euler Data v3 is not a path-for-path clone of v1/v2. Some endpoints map\n directly, some require multiple v3 calls, and some legacy aggregates were\n intentionally removed.\n- The live [migration guide](/v3/docs/migration) explains how legacy v1/v2\n endpoints and payloads map into the v3 resource model.\n- Important semantic changes:\n - Vault base APY and rewards APY are exposed separately in v3.\n - Account positions are flattened into account-vault rows instead of the\n legacy nested sub-account shape.\n - All supported API paths live under `/v3`; legacy paths return `410`.\n - Summary endpoints prefer smaller, focused resources over large\n BFF-style payloads.\n\nBase path: /v3\n\nConventions\n- JSON field naming: camelCase\n- Addresses: accept lowercase or checksum; responses are EIP-55 checksummed\n- Public APY values (`*Apy`, `apy*`): percent numbers with 6 decimal places (e.g., 5.123456 = 5.123456%)\n- Contract interest-rate fields (`borrowAPY`, `supplyAPY` in `interestRates`): decimal strings in contract fraction units\n- Ratios (utilization, LTV, etc.): numbers with 6 decimal places\n- Response timestamps: ISO-8601 strings (UTC). Some legacy fields still expose unix\n seconds for compatibility and include `*Iso` companions.\n- Query time ranges: unix seconds (from/to)\n\nUnit policy\n- v3 separates market metadata from contract verdicts by both name and type.\n- Market-normalized USD prices and USD values are JSON numbers. These are values\n derived from off-chain pricing, cached price snapshots, or API-level market math.\n This includes `/v3/prices`, token price routes, vault/earn/protocol USD totals,\n portfolio market values, portfolio USD liquidation/risk fields such as\n `liabilityValueUsd`, `totalCollateralValueUsd`, `borrowLiquidationPriceUsd`,\n and `collateralLiquidationPricesUsd`, and vault holder `assetsUsd`.\n- Contract-derived oracle and raw account-liquidity verdict values are exact strings.\n These preserve the integer value used by contracts, normalized to 18 decimals\n for API exposure. Oracle prices are quoted in the vault unit of account, which\n can be USD, ETH, or another asset. This includes `/v3/oracles/prices`, raw\n account-liquidity `liabilityValue` and `totalCollateralValue` objects,\n `liabilityValueBorrowing`, `liabilityValueLiquidation`, and collateral verdict\n values.\n- On-chain token quantities are bigint strings in their native unit scale. This\n includes amounts, balances, shares, assets, borrows, reward amounts, liquidation\n repay/yield amounts, and block numbers.\n- Caps are also bigint strings, but EVK caps are exposed as resolved underlying\n asset-unit amounts rather than packed contract config words.\n- LTV config values use canonical basis-point strings. Legacy decimal aliases\n may remain on config-history payloads for compatibility when explicitly named.\n\nRate limiting\n- Optional API keys for higher limits\n- Default limits are configurable; current defaults: free tier 100 req/min (IP-based)\n and authenticated 1000 req/min (per API key), 60s window.\n- By default, proxy headers are not trusted for IP identity unless explicitly enabled.\n- Redis failures default to fail-closed (503) for strict enforcement; fail-open is opt-in.\n- RateLimit-* (IETF draft-6) and legacy X-RateLimit-* headers are returned.\n\nCORS\n- Public API responses use wildcard CORS, including preflight responses for unsafe methods.\n- Unsafe methods with request bodies must use a JSON media type.\n\nCaching\n- Cache-Control headers are returned for cacheable endpoints.\n- Defaults (may be adjusted in config):\n - Prices: 300s\n - APYs: 600s\n - Rewards: 900s\n - General responses: 60s (short 30s, long 300s)\n\nErrors\n- All errors use a standard envelope: { error: { code, message, requestId, details? } }\n- Domain error codes are documented in this spec.\n- JSON request bodies must use `Content-Type: application/json` or another `application/*+json` media type.\n- Request bodies larger than 1 MiB are rejected before route parsing with `413 PAYLOAD_TOO_LARGE`.\n"
servers:
- url: /
description: Current environment
security: []
tags:
- name: Accounts
description: Account activity, discovered positions, and sub-account relationships. Legacy nested account payloads are flattened into account-vault rows in v3.
paths:
/v3/accounts/{address}/portfolio:
get:
tags:
- Accounts
summary: Account portfolio
description: 'Returns a position-first portfolio view for an owner on a single chain.
The backend builds SDK Account and Portfolio entities from internal V3
account, vault, price, and label data sources; it does not recursively
call `/v3/accounts/{address}/positions`. When `forceFresh=true`, the
endpoint enqueues or promotes account snapshot refresh work and waits
briefly for refreshed snapshots before falling back to the current
indexed portfolio view. Freshness metadata indicates whether the refresh
completed, timed out, or was rate-limited.
'
x-status: implemented
x-cache-ttl: 60
parameters:
- $ref: '#/components/parameters/AddressPath'
- name: chainId
in: query
required: true
schema:
type: integer
description: Chain ID. Exactly one chain is required.
- name: labeledVaultsOnly
in: query
required: false
schema:
type: boolean
description: Filter positions to the product-facing labeled vault universe.
- name: includeAccount
in: query
required: false
schema:
type: boolean
description: Include the backing SDK account-shaped payload for debugging and migration.
- name: forceFresh
in: query
required: false
schema:
type: boolean
description: 'When true, enqueue or promote account snapshot refresh for discovered tuples.
The endpoint waits briefly for refreshed snapshots before falling back to
the current indexed portfolio view. Inspect `data.freshness` for completion,
timeout, rate-limit, and fallback metadata.
'
responses:
'200':
description: Account portfolio
headers:
Cache-Control:
$ref: '#/components/headers/Cache-Control'
X-Request-Id:
$ref: '#/components/headers/X-Request-Id'
content:
application/json:
schema:
type: object
properties:
data:
$ref: '#/components/schemas/AccountPortfolioResponse'
meta:
$ref: '#/components/schemas/PaginationMeta'
'400':
$ref: '#/components/responses/Error400'
'404':
$ref: '#/components/responses/Error404'
operationId: getAccountsByAddressPortfolio
/v3/accounts/{address}/positions:
get:
tags:
- Accounts
summary: Account positions across chains
description: 'Returns paginated account positions across the selected chain scope.
Uses `meta.hasMore` for pagination continuation on the hot path rather than an exact `meta.total`.
'
x-status: implemented
x-cache-ttl: 60
parameters:
- $ref: '#/components/parameters/AddressPath'
- $ref: '#/components/parameters/ChainIdParam'
- $ref: '#/components/parameters/OffsetParam'
- $ref: '#/components/parameters/LimitParam'
- name: forceFresh
in: query
required: false
schema:
type: boolean
description: 'When true, trigger bounded synchronous account snapshot refresh for the returned tuples.
On timeout/failure, response safely falls back to stored snapshots and indicates cached mode in freshness metadata.
'
responses:
'200':
description: Account positions
headers:
Cache-Control:
$ref: '#/components/headers/Cache-Control'
X-Request-Id:
$ref: '#/components/headers/X-Request-Id'
content:
application/json:
schema:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/AccountPosition'
meta:
$ref: '#/components/schemas/PaginationMeta'
freshness:
type: object
properties:
latestSnapshotTimestamp:
type: string
format: date-time
nullable: true
ageSeconds:
type: integer
nullable: true
timestamp:
type: string
format: date-time
mode:
type: string
enum:
- fresh
- cached
forceFreshRequested:
type: boolean
refreshTriggered:
type: boolean
refreshCompleted:
type: boolean
timedOut:
type: boolean
rateLimited:
type: boolean
fallbackReason:
type: string
nullable: true
waitedMs:
type: integer
operationId: getAccountsByAddressPositions
/v3/accounts/{address}/activity:
get:
tags:
- Accounts
summary: Account vault activity discovery
description: 'Discovers vault tuples an account interacts with (shares and/or controller-enabled debt),
including sub-accounts when available.
Uses `meta.hasMore` for pagination continuation on the hot path rather than an exact `meta.total`.
'
x-status: implemented
x-cache-ttl: 60
parameters:
- $ref: '#/components/parameters/AddressPath'
- $ref: '#/components/parameters/ChainIdParam'
- $ref: '#/components/parameters/OffsetParam'
- $ref: '#/components/parameters/LimitParam'
responses:
'200':
description: Account activity
headers:
X-Request-Id:
$ref: '#/components/headers/X-Request-Id'
content:
application/json:
schema:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/AccountActivity'
meta:
$ref: '#/components/schemas/PaginationMeta'
operationId: getAccountsByAddressActivity
/v3/accounts/{address}/sub-accounts:
get:
tags:
- Accounts
summary: Sub-accounts for an EVC-enabled account
x-status: implemented
x-cache-ttl: 60
parameters:
- $ref: '#/components/parameters/AddressPath'
- name: chainId
in: query
required: true
schema:
type: string
description: Comma-separated list of chain IDs (single value allowed).
example: '1'
- $ref: '#/components/parameters/OffsetParam'
- $ref: '#/components/parameters/LimitParam'
responses:
'200':
description: Sub-accounts
headers:
X-Request-Id:
$ref: '#/components/headers/X-Request-Id'
content:
application/json:
schema:
type: object
properties:
data:
type: array
items:
$ref: '#/components/schemas/SubAccount'
meta:
$ref: '#/components/schemas/PaginationMeta'
operationId: getAccountsByAddressSubAccounts
components:
schemas:
AccountPosition:
type: object
properties:
chainId:
type: integer
account:
type: string
vault:
type: string
vaultType:
type: string
enum:
- evk
- earn
- securitize
asset:
type: string
nullable: true
shares:
type: string
nullable: true
description: Raw vault share amount as a bigint string.
assets:
type: string
nullable: true
description: Raw underlying asset amount as a bigint string.
borrowed:
type: string
nullable: true
description: Raw borrowed asset amount as a bigint string.
assetsValue:
type: string
nullable: true
description: Contract-derived account-liquidity asset value, raw 18-decimal bigint string.
debtValue:
type: string
nullable: true
description: Contract-derived account-liquidity debt value, raw 18-decimal bigint string.
isCollateral:
type: boolean
nullable: true
balanceForwarderEnabled:
type: boolean
nullable: true
isController:
type: boolean
nullable: true
liquidity:
$ref: '#/components/schemas/AccountPositionLiquidity'
subAccount:
type: object
nullable: true
properties:
owner:
type: string
nullable: true
timestamp:
type: string
format: date-time
nullable: true
lastAccountStatusCheckTimestamp:
type: string
format: date-time
nullable: true
enabledControllers:
type: array
nullable: true
items:
type: string
enabledCollaterals:
type: array
nullable: true
items:
type: string
isLockdownMode:
type: boolean
nullable: true
isPermitDisabledMode:
type: boolean
nullable: true
snapshot:
type: object
properties:
timestamp:
type: string
format: date-time
nullable: true
ageSeconds:
type: integer
nullable: true
source:
type: string
nullable: true
method:
type: string
nullable: true
YieldApyBreakdown:
type: object
properties:
lending:
type: number
description: Lending APY contribution as a percent number.
borrowing:
type: number
description: Borrowing APY contribution as a percent number.
rewards:
type: number
description: Rewards APY contribution as a percent number.
intrinsicApy:
type: number
description: Intrinsic APY contribution as a percent number.
total:
type: number
description: Total APY as a percent number.
SerializedPortfolioVault:
type: object
properties:
address:
type: string
type:
type: string
enum:
- evk
- earn
- securitize
- unknown
asset:
type: object
properties:
address:
type: string
symbol:
type: string
decimals:
type: integer
name:
type: string
shares:
type: object
properties:
address:
type: string
symbol:
type: string
decimals:
type: integer
name:
type: string
supplyApy:
type: number
description: Public supply APY as a percent number.
borrowApy:
type: number
description: Public borrow APY as a percent number.
supplyApy1h:
type: number
description: One-hour public supply APY as a percent number.
strategyCount:
type: integer
SubAccount:
type: object
required:
- chainId
- owner
- addressPrefix
- blockNumber
- timestamp
properties:
chainId:
type: integer
owner:
type: string
addressPrefix:
type: string
blockNumber:
type: string
timestamp:
type: string
format: date-time
SerializedPortfolioAccountPosition:
type: object
properties:
account:
type: string
vaultAddress:
type: string
vault:
$ref: '#/components/schemas/SerializedPortfolioVault'
asset:
type: string
shares:
type: string
description: Raw vault share amount as a bigint string.
assets:
type: string
description: Raw underlying asset amount as a bigint string.
borrowed:
type: string
description: Raw borrowed asset amount as a bigint string.
isController:
type: boolean
isCollateral:
type: boolean
balanceForwarderEnabled:
type: boolean
marketPriceUsd:
type: number
description: Market USD price number for this position's asset.
suppliedValueUsd:
type: number
description: Market USD value number for this supplied position.
borrowedValueUsd:
type: number
description: Market USD value number for this borrowed position.
liquidity:
$ref: '#/components/schemas/AccountPositionLiquidity'
borrowLiquidationPriceUsd:
type: number
description: Borrow liquidation price in USD.
collateralLiquidationPricesUsd:
type: object
description: Liquidation prices in USD keyed by collateral address.
additionalProperties:
type: number
ErrorResponse:
type: object
required:
- error
properties:
error:
type: object
required:
- code
- message
- requestId
properties:
code:
type: string
description: 'Domain error code. Examples:
- INVALID_ADDRESS
- CHAIN_NOT_SUPPORTED
- VAULT_NOT_FOUND
- TOKEN_NOT_FOUND
- ACCOUNT_NOT_FOUND
- VALIDATION_ERROR
- RATE_LIMIT_EXCEEDED
- UNSUPPORTED_MEDIA_TYPE
- UNAUTHORIZED
- FORBIDDEN
- INTERNAL_ERROR
'
message:
type: string
requestId:
type: string
details:
type: object
additionalProperties: true
DataIssue:
type: object
properties:
code:
type: string
severity:
type: string
enum:
- info
- warning
- error
message:
type: string
locations:
type: array
items:
type: object
properties:
owner:
type: object
additionalProperties: true
path:
type: string
source:
type: string
originalValue: {}
normalizedValue: {}
AccountPortfolioResponse:
type: object
properties:
chainId:
type: integer
owner:
type: string
portfolio:
type: object
properties:
savings:
type: array
items:
$ref: '#/components/schemas/PortfolioSavingsPosition'
borrows:
type: array
items:
$ref: '#/components/schemas/PortfolioBorrowPosition'
positions:
type: array
items:
$ref: '#/components/schemas/SerializedPortfolioAccountPosition'
managedLending:
type: array
items:
$ref: '#/components/schemas/PortfolioSavingsPosition'
directLending:
type: array
items:
$ref: '#/components/schemas/PortfolioSavingsPosition'
totals:
type: object
properties:
suppliedValueUsd:
type: number
description: Market USD number for total supplied value.
borrowedValueUsd:
type: number
description: Market USD number for total borrowed value.
netAssetValueUsd:
type: number
description: Market USD number for supplied minus borrowed value.
netApy:
type: number
description: Public net APY as a percent number.
roe:
type: number
description: Return-on-equity ratio number.
apyBreakdown:
$ref: '#/components/schemas/YieldApyBreakdown'
roeBreakdown:
$ref: '#/components/schemas/YieldApyBreakdown'
account:
type: object
nullable: true
additionalProperties: true
errors:
type: array
items:
$ref: '#/components/schemas/DataIssue'
freshness:
type: object
properties:
latestSnapshotTimestamp:
type: integer
nullable: true
ageSeconds:
type: integer
nullable: true
timestamp:
type: string
format: date-time
mode:
type: string
enum:
- fresh
- cached
forceFreshRequested:
type: boolean
refreshTriggered:
type: boolean
refreshCompleted:
type: boolean
timedOut:
type: boolean
rateLimited:
type: boolean
fallbackReason:
type: string
nullable: true
waitedMs:
type: integer
AccountPositionLiquidity:
type: object
nullable: true
properties:
vaultAddress:
type: string
unitOfAccount:
type: string
daysToLiquidation:
oneOf:
- type: integer
- type: string
enum:
- Infinity
- MoreThanAYear
liabilityValue:
$ref: '#/components/schemas/AccountLiquidityValue'
totalCollateralValue:
$ref: '#/components/schemas/AccountLiquidityValue'
collaterals:
type: array
items:
type: object
properties:
address:
type: string
value:
$ref: '#/components/schemas/AccountLiquidityValue'
marketPriceUsd:
type: number
description: Market USD price number for the collateral asset.
valueUsd:
type: number
description: Market USD value number for this collateral.
liabilityValueUsd:
type: number
description: Market USD liability value number.
totalCollateralValueUsd:
type: number
description: Market USD collateral value number.
PortfolioSavingsPosition:
type: object
properties:
position:
$ref: '#/components/schemas/SerializedPortfolioAccountPosition'
vault:
$ref: '#/components/schemas/SerializedPortfolioVault'
subAccount:
type: string
shares:
type: string
description: Raw vault share amount as a bigint string.
assets:
type: string
description: Raw underlying asset amount as a bigint string.
suppliedValueUsd:
type: number
description: Market USD value number for this savings position.
apy:
type: number
description: Public APY as a percent number.
apyBreakdown:
$ref: '#/components/schemas/YieldApyBreakdown'
PortfolioBorrowPosition:
type: object
properties:
borrow:
$ref: '#/components/schemas/SerializedPortfolioAccountPosition'
collaterals:
type: array
items:
$ref: '#/components/schemas/SerializedPortfolioAccountPosition'
collateral:
$ref: '#/components/schemas/SerializedPortfolioAccountPosition'
borrowVault:
$ref: '#/components/schemas/SerializedPortfolioVault'
collateralVault:
$ref: '#/components/schemas/SerializedPortfolioVault'
collateralVaults:
type: array
items:
type: string
subAccount:
type: string
healthFactor:
type: string
userLTV:
type: string
description: Contract-derived account LTV ratio, raw 18-decimal bigint string.
currentLTV:
type: string
description: Contract-derived current LTV ratio, raw 18-decimal bigint string.
borrowed:
type: string
description: Raw borrowed asset amount as a bigint string.
supplied:
type: string
description: Raw supplied asset amount as a bigint string.
price:
type: number
description: Borrow liquidation price in USD.
borrowLiquidationPriceUsd:
type: number
description: Borrow liquidation price in USD.
collateralLiquidationPricesUsd:
type: object
description: Liquidation prices in USD keyed by collateral address.
additionalProperties:
type: number
borrowLTV:
type: number
description: Borrow LTV ratio number.
liquidationLTV:
type: number
description: Liquidation LTV ratio number.
accountLiquidationLTV:
type: number
description: Account liquidation LTV ratio number.
liabilityValueBorrowing:
type: string
description: Contract-derived liability value for borrowing, raw 18-decimal bigint string.
liabilityValueLiquidation:
type: string
description: Contract-derived liability value for liquidation, raw 18-decimal bigint string.
liabilityValueUsd:
type: number
description: Market USD liability value number.
totalCollateralValueUsd:
type: number
description: Market USD total collateral value number.
collateralValueLiquidation:
type: string
description: Contract-derived collateral liquidation value, raw 18-decimal bigint string.
timeToLiquidation:
oneOf:
- type: integer
- type: string
enum:
- Infinity
- MoreThanAYear
multiplier:
type: number
description: Leverage multiplier ratio number.
netApy:
type: number
description: Public net APY as a percent number.
roe:
type: number
description: Return-on-equity ratio number.
apyBreakdown:
$ref: '#/components/schemas/YieldApyBreakdown'
roeBreakdown:
$ref: '#/components/schemas/YieldApyBreakdown'
AccountActivity:
type: object
properties:
type:
type: string
chainId:
type: integer
vault:
type: string
assets:
type: string
description: Raw underlying asset amount as a bigint string.
shares:
type: string
description: Raw vault share amount as a bigint string.
txHash:
type: string
blockNumber:
type: string
timestamp:
type: string
format: date-time
PaginationMeta:
type: object
required:
- timestamp
properties:
total:
type: integer
description: Exact total count when the endpoint provides one.
hasMore:
type: boolean
description: Indicates whether another page exists beyond the current page.
offset:
type: integer
limit:
type: integer
description: Echoed page size after endpoint-side clamping.
timestamp:
type: string
format: date-time
chainId:
type: string
description: Comma-separated chain IDs for multi-chain responses.
AccountLiquidityValue:
type: object
description: Contract-derived account-liquidity value in unit-of-account terms; each field is a raw 18-decimal bigint string.
properties:
borrowing:
type: string
description: Borrowing value, raw 18-decimal bigint string.
liquidation:
type: string
description: Liquidation value, raw 18-decimal bigint string.
oracleMid:
type: string
description: Oracle midpoint value, raw 18-decimal bigint string.
headers:
X-Request-Id:
description: Request identifier for tracing.
schema:
type: string
Cache-Control:
description: Cache policy for this response.
schema:
type: string
parameters:
OffsetParam:
name: offset
in: query
required: false
schema:
type: integer
default: 0
AddressPath:
name: address
in: path
required: true
schema:
type: string
ChainIdParam:
name: chainId
in: query
required: false
schema:
type: string
description: Comma-separated list of chain IDs (single value allowed).
example: 1,10,8453
LimitParam:
name: limit
in: query
required: false
description: Requested page size. Values above the endpoint cap are clamped; the default shared cap is 100.
schema:
type: integer
default: 20
maximum: 100
responses:
Error400:
description: Bad request
headers:
X-Request-Id:
$ref: '#/components/headers/X-Request-Id'
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
Error404:
description: Not found
headers:
X-Request-Id:
$ref: '#/components/headers/X-Request-Id'
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
securitySchemes:
ApiKeyAuth:
type: apiKey
in: header
name: X-API-Key
description: API key authentication (optional; higher rate limits).
BearerAuth:
type: http
scheme: bearer
bearerFormat: API key
description: 'Alternative to X-API-Key using Authorization: Bearer <key>'
AdminSecret:
type: apiKey
in: header
name: X-Admin-Secret
description: Admin secret (server-to-server) for API key management.
PlatformSession:
type: apiKey
in: cookie
name: euler_platform_session
description: Signed, httpOnly platform-operator browser session cookie.
PlatformCsrf:
type: apiKey
in: header
name: X-CSRF-Token
description: Double-submit CSRF token required for unsafe cookie-authenticated methods.