# `POST /screener/institutional-holdings`

**Purpose:** Screen SEC Form 13F institutional filings across the whole library. One row = one manager-quarter, carrying that quarter's headline numbers (the [snapshot object](/documents/snapshot-object.md), plus the manager's `cik` and `name`). An empty body is the full listing, ordered by `total_positions_value` descending. Requires **Pro or higher**.

**Request:**

| Field | Type | Default | Notes |
|---|---|---|---|
| `start_date`, `end_date` | ISO date | omitted | Bound the calendar **quarter end**: quarters whose period end falls inside the range participate. Give one date to bound one side only; omit both to scan every quarter. |
| `conditions` | object[] | omitted | ≤ 8 of `{field, op, value}` — see below. |
| `is_amended` | bool | omitted | `true` → only quarters with merged amendments; `false` → only quarters without. |
| `confidential` | bool | omitted | Filter on the confidential-treatment flag. |
| `is_combination_report` | bool | omitted | `true` → 13F COMBINATION REPORT quarters (the filer also reports holdings managed by other managers); `false` → 13F HOLDINGS REPORT quarters. |
| `sort_by` | string | `total_positions_value` | One of `total_positions_value`, `positions_count`, `derivatives_count`, `total_derivatives_notional`, `portfolio_value_qoq_pct`, `top1_security_pct`, `top10_security_pct`, `est_turnover`, `period`, `filing_date`. |
| `sort_order` | `"desc"` \| `"asc"` | `"desc"` | |
| `page` | int ≥ 1 | 1 | |
| `page_size` | int 1–100 | 50 | |
| `detail` | string | `"full"` | Full and minimal views only: `"light"` returns the minimal view. A `cover_table_value` condition returns the full view. See [Response detail](/documents/responses.md#response-detail). |

**Pagination cap:** `page × page_size ≤ 500` (422 above it). When the next page would pass the cap, `has_more` is `false`, `next_page` is `null`, and `_warnings` says the limit was reached.

**`conditions`:** each is `{field, op, value}` with `op` ∈ `>`, `>=`, `<`, `<=`, `between` (`[lo, hi]`, `lo ≤ hi`, inclusive on both ends). `field` is one of `total_positions_value`, `positions_count`, `derivatives_count`, `total_derivatives_notional`, `portfolio_value_qoq_pct`, `top1_security_pct`, `top10_security_pct`, `est_turnover`, `cover_table_value`, `new_count`, `add_count`, `reduce_count`, `hold_count`, `sold_out_count` (the five counters read the quarter's `activity_counts`), or `filing_date` (values as ISO date strings).

A quarter where the compared field is null never matches. A quarter with no prior filed quarter to compare against has null `portfolio_value_qoq_pct`, `est_turnover` and `activity_counts`.

**Response:** `matches` (snapshot rows with `cik` / `name`), `page`, `page_size`, `total_items`, `has_more`, `next_page`, `credits_used`, and `_warnings`: a note on the EDGAR links (full view), a note when the returned rows span more than one quarter (the same manager can appear once per quarter), and a note when a returned quarter has confidential holdings.

**Errors:** `422 VALIDATION_ERROR`, `402 CREDITS_INSUFFICIENT`, `403 PLAN_TIER_INSUFFICIENT` below Pro (all rejected before any deduction), `504 QUERY_TIMEOUT` at the 30-second server timeout (charged).

**Example Request:**

```json
{
  "start_date": "2026-06-30",
  "end_date": "2026-06-30",
  "conditions": [
    {
      "field": "total_positions_value",
      "op": ">=",
      "value": 100000000000
    }
  ],
  "page_size": 20
}
```

## Credit formula (`/screener/institutional-holdings`)

`POST /screener/institutional-holdings` charges per call (paginate ⇒ each page bills independently):

```text title="Formula"
credits = max(65, 200
              + 40 × conditions        // numeric conditions + boolean filters actually passed
              − narrowWindowDiscount   // 40 when both dates are given and span ≤ 184 days (at most two quarters)
              + noWindowSurcharge)     // 80 when neither date is given
```

Range **160–720**.

| Scenario | Credits |
|---|---|
| Empty body (full listing) | **280** |
| One quarter (`start_date` = `end_date`), 1 condition | **200** |
| 1 condition + `is_amended`, no dates | **360** |

Charged even when `matches` is empty, and on `504 QUERY_TIMEOUT`. **No charge** on `422 VALIDATION_ERROR`, `402 CREDITS_INSUFFICIENT`, or `403 PLAN_TIER_INSUFFICIENT` (all rejected before any deduction).
