> ## 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.

# Property insights

> How many records fill each CRM property, and which custom properties have no data or are rarely filled

**Properties** in CRM Cleaning lists every property of your contacts, companies and
deals with how many records fill it. Custom properties with no data, or rarely filled,
are flagged, so you can archive them in your CRM and keep forms and views short.

It is a report. Clustr never archives, deletes or edits a property.

> [!NOTE]
>
> Property insights are available for HubSpot. With Salesforce or Attio connected, the
> view says so and lists nothing.

## What you see

Pick **Contacts**, **Companies** or **Deals**. Each tab shows how many of its
properties are flagged. Above the table:

* **How filled the properties are**: a bar splitting the counted properties into five
  bands, 0%, 1-20%, 20-50%, 50-80% and 80-100% of records filled, with the count in
  each band.
* **Since last count**: how the number of properties with no data and rarely filled
  changed since the previous count, for example "No data: 30 → 28 since last count",
  with a small line of No data over the last 12 counts.

For every property:

| Column | Meaning |
| - | - |
| Property | The label your team sees. **Custom** marks a property your portal added. |
| Internal name | The name the API uses, for example `acme_region` |
| Type | The property's type: `string`, `number`, `date`, `enumeration`, ... |
| Filled | The share of records with a value. **Counting…** while a count has not reached it yet. |
| Without value | How many records have no value |
| Usage | A badge for a flagged property, and the fill in words, for example "Filled on 3% of contacts" |

Properties are sorted with the flagged ones first, then by how rarely they are filled.
Search by label or internal name, or turn on **Only flagged** to see the flagged ones only.

### What gets flagged

| Badge | When |
| - | - |
| No data | No record has a value |
| Rarely filled | Fewer than 5% of records have a value |

Only **custom** properties are flagged. HubSpot's own default properties are listed with
their fill rate but never flagged: they are not yours to archive. Archived and calculated
properties are left out. An object with no records flags nothing.

## When the counts are taken

Counting asks HubSpot one question per property, so it runs in the background, never
while you wait:

* **Every month, at night**, for every workspace with CRM Cleaning whose
  [scan schedule](https://docs.clustr-ai.com/crm-cleaning/history.md#scheduled-scans) is on. The count starts
  between 01:00 and 05:00 in your workspace's time zone (the one set on the cleaning
  schedule, or Paris time when none is set), each workspace at its own time in that
  window. A count that runs past 05:00 carries on.
* **When you click Refresh**, at most once an hour. Counting starts within a minute,
  whatever the hour.

The count asks **one question a second**. HubSpot shares one search allowance between
every app connected to your portal, Clustr's own sync included, so a steady pace leaves
room for the rest. A portal with 1,800 properties takes about half an hour. If HubSpot
asks us to slow down, or another CRM error stops it, counting pauses for 15 minutes and
the view says so. A count that still cannot finish two days after it was asked for stops
with what it has, and the view says why.

While a count runs, a progress bar shows how far it is, for example "Counting 394 of
1,741 properties · about 25 min left", and the table fills in as it goes. A property
keeps its last count until it is counted again. When no count is running, the line
reads "Last counted ... · next count ...". Every finished count is kept for the trend
(the last 26).

## API

### Get property insights

`GET /api/crm/cleaning/property-insights`

| Query | Description |
| - | - |
| `object_type` | `contact`, `company` or `deal`. Optional; the `objects` summaries cover every object either way. |

```json theme={null}
{
  "data": {
    "provider": "hubspot",
    "supported": true,
    "status": "running",
    "startedAt": "2026-10-08T23:37:00Z",
    "finishedAt": "2026-10-01T23:58:00Z",
    "nextRefreshAt": null,
    "refreshAvailableAt": null,
    "counted": 394,
    "toCount": 1741,
    "etaSeconds": 1482,
    "lastError": "",
    "objects": [
      {
        "objectType": "contact",
        "records": 12480,
        "properties": 214,
        "custom": 38,
        "counted": 120,
        "toCount": 214,
        "empty": 6,
        "rarelyUsed": 4,
        "fillBands": [
          { "band": "0", "count": 31 },
          { "band": "1-20", "count": 52 },
          { "band": "20-50", "count": 40 },
          { "band": "50-80", "count": 47 },
          { "band": "80-100", "count": 44 }
        ],
        "history": [
          { "finishedAt": "2026-09-24T23:51:00Z", "objectType": "contact", "properties": 212, "custom": 37, "counted": 212, "noData": 8, "rarelyFilled": 4 },
          { "finishedAt": "2026-10-01T23:58:00Z", "objectType": "contact", "properties": 214, "custom": 38, "counted": 214, "noData": 6, "rarelyFilled": 4 }
        ],
        "previous": { "finishedAt": "2026-09-24T23:51:00Z", "objectType": "contact", "properties": 212, "custom": 37, "counted": 212, "noData": 8, "rarelyFilled": 4 }
      }
    ],
    "properties": [
      {
        "objectType": "contact",
        "name": "acme_region",
        "label": "Region",
        "type": "enumeration",
        "fieldType": "select",
        "groupName": "acme",
        "hubspotDefined": false,
        "filled": 0,
        "total": 12480,
        "recordsWithoutValue": 12480,
        "fillPercent": 0,
        "issue": "empty",
        "phrase": "Never filled",
        "countFailed": false,
        "counting": false,
        "computedAt": "2026-10-08T23:41:12Z"
      }
    ]
  }
}
```

| Field | Meaning |
| - | - |
| `status` | `never` (no count yet), `pending` (queued), `running` (counting), `idle` (done) or `unsupported` (not HubSpot) |
| `counted`, `toCount`, `etaSeconds` | While running: properties counted so far, how many the count covers, and the seconds left at one search a second plus a small margin. `null` otherwise. |
| `requestedAt` | When the latest count was asked for, by the monthly schedule or a refresh |
| `nextRefreshAt` | When idle: when the next monthly count starts, about 30 days after the last one, at night in your time zone |
| `lastError` | Why counting paused or stopped short, in plain words; empty when all went well |
| `issue` | `empty` (shown as No data), `rarely_used` (Rarely filled) or `none` |
| `filled`, `total`, `recordsWithoutValue`, `fillPercent` | `null` until the property is counted |
| `counting` | A count is queued or running and has not reached this property yet |
| `countFailed` | HubSpot would not count this property |
| `objects[].counted`, `objects[].toCount` | While running, this object's progress; otherwise `counted` is the properties with a count |
| `objects[].fillBands` | Counted properties per band of records filled: `0`, `1-20`, `20-50`, `50-80`, `80-100` |
| `objects[].history`, `objects[].previous` | The latest 12 finished counts of the object, oldest first, and the one before the latest |
| `refreshAvailableAt` | When a manual refresh is next allowed; `null` when now |

An `object_type` other than `contact`, `company` or `deal` answers `400` with
`INVALID_OBJECT_TYPE`.

### Refresh

`POST /api/crm/cleaning/property-insights/refresh`

Queues a count and answers `202` with `status` (`pending`, or `running` when a count is
already under way), `requestedAt` and `refreshAvailableAt`. A count already running
carries on from where it is. Counting starts within a minute, whatever the hour. Nothing is
written to your CRM.

| Status | Code | Why |
| - | - | - |
| `202` | | Queued |
| `429` | `REFRESH_RATE_LIMITED` | The last refresh was less than an hour ago. `Retry-After` says how many seconds to wait. |

## From your AI assistant

| Tool | Parameters | What it does |
| - | - | - |
| `get_crm_property_insights` | `object_type`, `issue` (`flagged` by default, `empty`, `rarely_used` or `all`), `limit` (default 100, at most 500) | The report, with the flagged properties by default, the progress while a count runs, and the trend |
| `refresh_crm_property_insights` | none | Queue a count, once an hour |

Ask, for example, "Which contact properties have no data?" or "How far is the property
count?"


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.