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

# List Accounts

> The accounts your network reaches, with their heat and fit

Every company your connectors can reach, hottest first by default, with how
active it is right now (**heat**) and how well it matches your targeting
(**fit**).

This is the list the Accounts table draws: the same rows, filtered and ordered
the same way. It is not [Search Companies](/api-reference/search-companies):
that one searches the shared enrichment cache and can tell you a company exists,
which says nothing about whether your workspace cares about it or can get into
it.

## Heat and fit are two different questions

Heat is **timing**: is anything happening at this account? Fit is **quality**:
is this the kind of account you want? Neither moves the other. A cold `A+` is a
good account nobody is talking to; a burning `D` is activity at an account
outside your targeting. Rank on both, which is what the default order does:
heat first, then fit, then the latest signal.

## Heat

`temperature` is one of four bands. A **signal** is a LinkedIn engagement or a
CRM activity (email, call, meeting, note) at the account.

| Heat      | Rule                                                                    |
| --------- | ----------------------------------------------------------------------- |
| `burning` | An open CRM deal, or a signal in the last 14 days and another within 30 |
| `warm`    | A signal in the last 30 days                                            |
| `cool`    | A signal in the last 90 days                                            |
| `cold`    | Nothing in 90 days                                                      |

Path strength does not count: a strong path with no signal is `cold`. The band
is worked out when you read it, so an account cools on its own as its last
signal ages, without waiting for a refresh.

The evidence ships with the band:

* `last_signal_at`: the latest signal from either source.
* `last_signal_source`: `linkedin` or `crm`.
* `last_signal_type`: the engagement or CRM activity type of that signal, when known.
* `signals_30d`: how many signals landed in the last 30 days, both sources.
* `has_open_deal`: an open CRM deal is resolved to this account.

Signals are stored per account and refreshed in the background, at most about
15 minutes apart while the list is being read, so a brand-new engagement or CRM
activity can take up to that long to warm an account.

## The grade

`fit_grade` is `A+` to `D`, and it is the fraction of your **configured**
criteria this account meets, banded:

| Grade | Score                              |
| ----- | ---------------------------------- |
| `A+`  | ≥ 0.90                             |
| `A`   | ≥ 0.75                             |
| `B`   | ≥ 0.50                             |
| `C`   | ≥ 0.25                             |
| `D`   | anything below 0.25, zero included |

The criteria are your target-account list, your tier vocabulary and each
dimension of your Company ICP. The divisor is only the criteria you have
configured, so a criterion you never set cannot drag an account down, and
nothing earns an A+ for being the best of a bad list.

An ICP dimension we hold **no value** for (no known headcount, say) is skipped
for that account rather than counted as a miss. Its status in the breakdown is
`unknown`.

<Warning>
  **No `fit_grade` is not a bad grade.** It means the workspace has defined no
  ICP, no tiers and no target list, so there is nothing to grade against and no
  letter would be honest. `D` is the opposite: criteria exist and this account
  met none of them. Treat absent and `D` as different answers.
</Warning>

<Note>
  **`fit_score` is not comparable across workspaces.** It is a fraction of what
  *that* workspace configured, so 0.8 on a workspace with four criteria and 0.8
  on one with one criterion are not the same claim. Compare grades within a
  workspace, never between.
</Note>

`fit_reasons` ships with the grade and names what scored: the matched ICP's
title, then each criterion met (`["Mid-market SaaS", "Target account", "Tier 1",
"Industry"]`). Nothing downstream has to reconstruct the reasoning.

`fit_breakdown` goes further: every configured criterion, met or not, with the
points it is worth and the points the account earned. `fit_score` is the earned
points over the points available.

| Field            | Meaning                                                           |
| ---------------- | ----------------------------------------------------------------- |
| `icp_title`      | The Company ICP the dimensions were scored against                |
| `parts[].key`    | `target`, `tier`, `industry`, `headcount`, `revenue` or `country` |
| `parts[].weight` | Points this criterion is worth                                    |
| `parts[].earned` | Points the account earned on it, from 0 to `weight`               |
| `parts[].status` | `met`, `partial`, `missed` or `unknown`                           |

### When a grade changes

Grades are stored, not computed per request, and they are refreshed on the write
that makes them wrong:

* **Change your targeting** (a tier set on an account, an ICP edited, a tier
  added or reordered) and the affected grades are recomputed on that request.
  Set a tier with [Set Account State](/api-reference/set-account-state).
* **New accounts your network reaches** are graded when the accounts snapshot
  next rebuilds, along with anything whose targeting inputs moved with it. That
  is also when a change to the target list reaches the grade, because whether an
  account is a target is part of that snapshot.

So a grade can trail a target-list import by one snapshot rebuild. Everything
else is immediate.

## Two ids, and they are not interchangeable

`id` is the company's LinkedIn numeric id, which is how an account is addressed
in this API. `company_id` is the company UUID, which is what
[Set An Account's Tags](/api-reference/set-account-record-tags) and
[Set Account State](/api-reference/set-account-state) take. Both ship on every
row for that reason.

A row's `tags` are the account's [tags](/tags), each carrying the `group_id` of
the group it came from.

## Paging

Pages are `pageSize` rows (default 50, at most 200). `has_more` is `true` while
another page exists; there is no total count.

<RequestExample>
  ```bash cURL theme={null}
  curl "https://api.clustr-ai.com/api/public/network/accounts?temperature=burning&temperature=warm&fit=A%2B&fit=A" \
    -H "Authorization: Bearer YOUR_API_KEY"
  ```

  ```python Python theme={null}
  import requests

  res = requests.get(
      "https://api.clustr-ai.com/api/public/network/accounts",
      headers={"Authorization": "Bearer YOUR_API_KEY"},
      params={"temperature": ["burning", "warm"], "fit": ["A+", "A"], "pageSize": 100},
  ).json()["data"]["accounts"]

  for a in res:
      print(a["name"], a.get("temperature"), a.get("fit_grade"), a.get("last_signal_at"))
  ```

  ```javascript JavaScript theme={null}
  const qs = new URLSearchParams();
  qs.append("temperature", "burning");
  qs.append("temperature", "warm");
  qs.append("fit", "A+");
  qs.append("fit", "A");

  await fetch(`https://api.clustr-ai.com/api/public/network/accounts?${qs}`, {
    headers: { Authorization: "Bearer YOUR_API_KEY" },
  });
  ```
</RequestExample>

<ResponseExample>
  ```json 200 theme={null}
  {
    "success": true,
    "data": {
      "accounts": [
        {
          "id": "1035",
          "company_id": "9c4d5e6f-...",
          "name": "Acme Corp",
          "domain": "acme.com",
          "industry": "Software Development",
          "linkedin_url": "https://www.linkedin.com/company/acme",
          "is_target": true,
          "connector_count": 3,
          "best_strength": 0.82,
          "temperature": "burning",
          "has_open_deal": false,
          "last_signal_at": "2026-09-12T09:30:00Z",
          "last_signal_source": "crm",
          "last_signal_type": "MEETING",
          "signals_30d": 4,
          "fit_grade": "A",
          "fit_score": 0.8889,
          "fit_reasons": ["Mid-market SaaS", "Target account", "Tier 1", "Industry"],
          "fit_breakdown": {
            "icp_id": "5b1c...",
            "icp_title": "Mid-market SaaS",
            "parts": [
              { "key": "target", "label": "Target account", "weight": 3, "earned": 3, "status": "met" },
              { "key": "tier", "label": "Tier 1", "weight": 3, "earned": 3, "status": "met" },
              { "key": "industry", "label": "Industry", "weight": 2, "earned": 2, "status": "met" },
              { "key": "revenue", "label": "Revenue", "weight": 1, "earned": 0, "status": "missed" }
            ]
          },
          "tags": [
            { "id": "7f3e1a22-...", "name": "Common investor", "color": "#3B82F6" }
          ]
        }
      ],
      "has_more": true
    }
  }
  ```

  ```json 401 theme={null}
  {
    "success": false,
    "error": {
      "message": "Invalid or missing API key",
      "code": "UNAUTHORIZED"
    }
  }
  ```
</ResponseExample>
