# An account's earn positions, every chain, both venue kinds

Endpoint reference for the 1delta API. Index: https://docs.1delta.io/llms.txt · every endpoint: https://docs.1delta.io/llms-full.txt

---

### GET /v1/data/earn/positions

- operationId: `earn-positions`
- docs: https://docs.1delta.io/1delta-api/earn-positions/
- markdown: https://docs.1delta.io/1delta-api/earn-positions.md
- tags: Earn

An account's earn positions, every chain, both venue kinds

Lending accounts (one row per chain × lender, markets as `legs`) and vault share balances (one row each), with totals. A lender with isolated sub-accounts (Euler, Dolomite, Fluid / Jupiter Lend NFTs, Kamino obligations …) lists each in `subAccounts[]`: `accountId` is what the action routes take, `label` the venue's own name where it has one, `accountAddress` the address it acts as on chain, and `unsupported` — when set — why the action routes cannot build for it (a Kamino Multiply / Leverage obligation).

Every position asset (`legs[].asset` on lending rows, `asset` on vault rows) carries `issuer`, `issuerExposures` (wrappers), `desk`, `denomination`, `assetClass` and `underlyingTicker`, stamped from the token map exactly as on `/v1/data/earn` rows, so a holding groups under the same desk as the listing row it came from.

On a BORROW leg the asset's desk is whose money is OWED — a debt is not an exposure; group a loop by its collateral.

**Parameters**

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `chainIds` | query | string | yes | CSV of chain ids (aliases `chainId`, `chains`). See the `ChainId` schema for the full set of supported chains. |
| `account` | query | string | yes | A 0x address (EVM chains) or a base58 pubkey (solana). Chains the account cannot exist on are dropped; none left is a 400. |
| `venueKind` | query | "lending" \| "vault" | no | Fetch one half only. |
| `lenders` | query | string | no | CSV — narrows the lending half. See the `LenderId` schema for the full set of accepted values. |
| `vaults` | query | string | no | CSV of vault addresses — skips vault discovery for those chains. |
| `includeZero` | query | boolean | no | Keep dust and zero-share rows. |

**Response `200`** — The positions envelope: `items`, `totals`, `sources`, `partial?`, `stale?`. Position assets carry `issuer`, `issuerExposures`, `desk`, `denomination`.

| Field | Type | Description |
| --- | --- | --- |
| `success` | true |  |
| `data` | object | Informational payload. `null` when the endpoint only builds calldata. |
| `actions` | null |  |

**Example response**

```json
{
  "success": true,
  "data": {}
}
```

**Response `400`** — Validation error

**Response `429`** — Rate limited. Unauthenticated callers share a per-IP budget; send an `x-api-key` header to lift it. Retry with exponential backoff.

**Response `500`** — Unexpected server error. Safe to retry with backoff.

**Response `502`** — An upstream data source or protocol origin failed (`error.code` is `ORIGIN_FAILED`). `error.details` carries the per-origin status. This is also what a missing or malformed required parameter currently returns, rather than a 400.
