> ## Documentation Index
> Fetch the complete documentation index at: https://docs.redbark.com/llms.txt
> Use this file to discover all available pages before exploring further.

# List Holdings

> Retrieve current portfolio holdings for a brokerage connection

<Info>
  The REST API is in **beta**. This endpoint's response shape may change.
</Info>

Returns a list of current holdings for a brokerage connection. Holdings are fetched live from the brokerage provider. No investment data is stored on Redbark servers.

<Warning>
  This endpoint requires brokerage access. Trialing subscriptions on any plan receive full brokerage access. Outside a trial, brokerage access requires an `active` (or `past_due`) subscription on a **Professional** price. A key with no general API access (for example a Saver-plan key) gets a `403` with `"code": "plan_upgrade_required"`. A Developer-plan key that has API access but not brokerage gets a `403` with `"code": "professional_required"` on this endpoint.
</Warning>

## Request

```
GET /v1/holdings
```

### Headers

| Header          | Required | Description           |
| --------------- | -------- | --------------------- |
| `Authorization` | Yes      | `Bearer YOUR_API_KEY` |

Trialing subscriptions on any plan receive full brokerage access, so you can evaluate `/holdings` and `/trades` during a trial. Outside a trial, brokerage access requires an `active` (or `past_due`) subscription on a Professional price.

### Query parameters

| Parameter      | Type     | Required | Description                                                                                                                                                                             |
| -------------- | -------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `connectionId` | `string` | Yes      | Brokerage connection to fetch holdings from                                                                                                                                             |
| `accountId`    | `string` | No       | Filter to a specific brokerage account. Defaults to all accounts on the connection.                                                                                                     |
| `accountIds`   | `string` | No       | Comma-separated subset of brokerage account UUIDs on the connection (max 4 000 chars). Takes precedence over `accountId` when both are passed. Any id not on the connection is a `404`. |

<Info>
  `connectionId` must refer to a brokerage connection. Passing a banking connection ID returns a `400` error. Use the [List Connections](/api-reference/connections) endpoint to find your brokerage connection IDs.
</Info>

## Response

Responses are not cached; every request fetches live from the brokerage provider.

```json theme={null}
{
  "data": [
    {
      "id": "abc123def456ghi789jkl012",
      "accountId": "d4e5f6a7-b8c9-0123-d4e5-f6a7b8c90123",
      "accountName": "Trading Account",
      "symbol": "VAS.AX",
      "name": "Vanguard Australian Shares ETF",
      "exchange": "ASX",
      "currency": "AUD",
      "quantity": "150.0000",
      "averagePrice": "85.50",
      "currentPrice": "92.30",
      "marketValue": "13845.00",
      "unrealizedPnl": "1020.00"
    },
    {
      "id": "mno345pqr678stu901vwx234",
      "accountId": "d4e5f6a7-b8c9-0123-d4e5-f6a7b8c90123",
      "accountName": "Trading Account",
      "symbol": "AAPL",
      "name": "Apple Inc.",
      "exchange": "NASDAQ",
      "currency": "USD",
      "quantity": "25.0000",
      "averagePrice": "178.20",
      "currentPrice": "195.40",
      "marketValue": "4885.00",
      "unrealizedPnl": "430.00"
    }
  ]
}
```

### Holding object

| Field           | Type             | Description                                                       |
| --------------- | ---------------- | ----------------------------------------------------------------- |
| `id`            | `string`         | Opaque holding identifier from the brokerage provider             |
| `accountId`     | `string`         | UUID of the brokerage account this holding belongs to             |
| `accountName`   | `string`         | Account display name                                              |
| `symbol`        | `string`         | Ticker symbol (e.g. `AAPL`, `VAS.AX`)                             |
| `name`          | `string \| null` | Security name                                                     |
| `exchange`      | `string \| null` | Exchange the security is listed on (e.g. `ASX`, `NASDAQ`)         |
| `currency`      | `string`         | Currency code (e.g. `AUD`, `USD`)                                 |
| `quantity`      | `string`         | Number of units held (decimal string; supports fractional shares) |
| `averagePrice`  | `string \| null` | Average cost basis per unit                                       |
| `currentPrice`  | `string \| null` | Latest market price per unit                                      |
| `marketValue`   | `string \| null` | Current total value of the position                               |
| `unrealizedPnl` | `string \| null` | Unrealised gain or loss since purchase                            |

<Tip>
  All monetary and quantity fields are strings to preserve decimal precision. Parse them as decimals in your application.
</Tip>

## Error responses

Errors use the standard envelope `{ "error": { "message": string, "code"?: string, "details"?: string[] } }`. The optional `code` field is set for the structured cases below — clients should branch on `code` rather than parsing `message`.

| Status | `code`                                       | When                                                                                                                                                                                                                |
| ------ | -------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `400`  | *(none)*                                     | `Invalid request parameters` (missing `connectionId`; schema validation, offending fields in `details[]`)                                                                                                           |
| `400`  | `wrong_endpoint_for_category`                | `Holdings are only available for brokerage connections` (passed a banking connection)                                                                                                                               |
| `403`  | `plan_upgrade_required`                      | `Your plan does not include API access. The Redbark API and MCP server require the Developer or Professional plan (this is a plan limit, not a credentials issue)...` (keys with no API access, e.g. Saver plan)    |
| `403`  | `professional_required`                      | Developer-plan key hitting a brokerage endpoint                                                                                                                                                                     |
| `404`  | `connection_not_found` / `account_not_found` | Connection or account not found, or does not belong to you                                                                                                                                                          |
| `429`  | *(none)*                                     | Rate limit exceeded — heavy bucket is **30/min** per API key, plus a per-key cap of **4 concurrent in-flight requests** (excess returns `Too many concurrent requests`). See `Retry-After` and `X-RateLimit-Reset`. |
| `503`  | *(none)*                                     | Brokerage provider temporarily unavailable. Retry later.                                                                                                                                                            |

Example error body:

```json theme={null}
{
  "error": {
    "message": "Brokerage endpoints require a Professional plan",
    "code": "professional_required"
  }
}
```

## Examples

### All holdings for a brokerage connection

```bash theme={null}
curl -H "Authorization: Bearer YOUR_API_KEY" \
  "https://api.redbark.com/v1/holdings?connectionId=e8f1a2b3-7c4d-5e6f-8a9b-0c1d2e3f4a5b"
```

### Filter to a specific account

```bash theme={null}
curl -H "Authorization: Bearer YOUR_API_KEY" \
  "https://api.redbark.com/v1/holdings?connectionId=e8f1a2b3-7c4d-5e6f-8a9b-0c1d2e3f4a5b&accountId=d4e5f6a7-b8c9-0123-d4e5-f6a7b8c90123"
```

### Filter to a subset of accounts

```bash theme={null}
curl -H "Authorization: Bearer YOUR_API_KEY" \
  "https://api.redbark.com/v1/holdings?connectionId=e8f1a2b3-7c4d-5e6f-8a9b-0c1d2e3f4a5b&accountIds=d4e5f6a7-b8c9-0123-d4e5-f6a7b8c90123,a1b2c3d4-e5f6-7890-a1b2-c3d4e5f67890"
```

### Python

```python theme={null}
import requests

API_KEY = "YOUR_API_KEY"
BASE = "https://api.redbark.com"

resp = requests.get(
    f"{BASE}/v1/holdings",
    headers={"Authorization": f"Bearer {API_KEY}"},
    params={"connectionId": "e8f1a2b3-7c4d-5e6f-8a9b-0c1d2e3f4a5b"},
)
holdings = resp.json()["data"]

for h in holdings:
    print(f"{h['symbol']}: {h['quantity']} @ {h['currentPrice']} ({h['currency']})")
```

### JavaScript

```javascript theme={null}
const API_KEY = "YOUR_API_KEY";
const BASE = "https://api.redbark.com";

const params = new URLSearchParams({
  connectionId: "conn_abc123",
});

const resp = await fetch(`${BASE}/v1/holdings?${params}`, {
  headers: { Authorization: `Bearer ${API_KEY}` },
});
const { data: holdings } = await resp.json();

for (const h of holdings) {
  console.log(`${h.symbol}: ${h.quantity} @ ${h.currentPrice} (${h.currency})`);
}
```
