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

# Monitor Endpoints

> Create, read, update, trigger, and cancel monitors, and read a row's change history and table snapshots.

## Use case

Watch fields on a list of people or companies and read what changed. Use these endpoints to create a monitor from rows, inspect its rows and events, export the table at any point in time, and change or stop it. See [Monitors Overview](/api-reference/monitors/monitors-overview) for how checks work.

<Note>Monitors are available to organizations with Monitors enabled. Requests from other organizations return `403`.</Note>

<Card title="API Reference" icon="code" href="/api-reference/monitors/create-monitor">
  See the full request/response schema and parameters in the API Reference.
</Card>

## Pricing

After a row's first check, every tick bills a probe per active row. A full re-check at the monitor's tier is billed only when the probe finds a likely change. See [Credits & Pricing Guide](/guides/credits-and-pricing) for more information.

## Errors

For error responses (400, 403, 404, 409, etc.), see [Handling Errors](/api-reference/errors).

## Create monitor

Create one monitor from a table, with one row per subject.

```http theme={null}
POST https://api.sixtyfour.ai/monitors
```

| Field                 | Type             | Required | Description                                                                                                                                                                                                                      |
| --------------------- | ---------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `name`                | string           | Yes      | Monitor name, 1–120 characters. Each row is named after it, followed by the row's key values.                                                                                                                                    |
| `rows`                | array of objects | Yes      | The table. At least one row.                                                                                                                                                                                                     |
| `key_columns`         | array of strings | Yes      | Columns that identify each row. Every row needs a value in at least one of them.                                                                                                                                                 |
| `struct`              | object           | Yes      | Watched fields: field name → description, or an object with `type`, `description`, and `subfields`. At least one field. A row column with the same name as a watched field sets that field's starting value.                     |
| `frequency`           | string           | No       | How often to check, `1h` to `30d`. Default `1d`.                                                                                                                                                                                 |
| `tier`                | string           | No       | Depth of the full re-check: `low` (default), `medium`, or `high`.                                                                                                                                                                |
| `subject_type`        | string           | No       | `company` (default) or `lead`.                                                                                                                                                                                                   |
| `research_plan`       | string           | No       | Instructions for the enrichment that re-derives the fields.                                                                                                                                                                      |
| `webhook_url`         | string           | No       | Public URL that receives notifications. See [Monitor Notifications](/api-reference/monitors/monitor-notifications).                                                                                                              |
| `webhook_event_types` | array of strings | No       | Which notifications to send. A monitor with no event types sends none.                                                                                                                                                           |
| `metadata`            | object           | No       | Free-form data stored on the monitor and echoed in events and notifications.                                                                                                                                                     |
| `is_active`           | boolean          | No       | Default `true`. Set to `false` to create the monitor inactive: nothing is checked until you resume it with `POST /monitors/{monitor_id}/update` and `"is_active": true`. A monitor created inactive has `disabled_reason: null`. |
| `first_check`         | string           | No       | `now` (default) checks every row immediately. `next_tick` waits for the first scheduled fire.                                                                                                                                    |
| `idempotency_key`     | string           | No       | Up to 200 characters. Resending a request with the same key returns what the first attempt created. When omitted, the key is derived from the request body, so an identical resend also replays.                                 |

Creation is all or nothing. If any row is invalid, nothing is created. The response is `201` with the monitor and its rows.

### Example request

```json theme={null}
{
  "name": "Portfolio leadership",
  "key_columns": ["company_name", "domain"],
  "rows": [
    { "company_name": "Acme Robotics", "domain": "acmerobotics.com", "ceo_name": "Dana Lee" },
    { "company_name": "Northwind Labs", "domain": "northwindlabs.io" }
  ],
  "struct": {
    "ceo_name": "Full name of the current CEO",
    "headcount": { "type": "int", "description": "Current number of employees" }
  },
  "frequency": "1d",
  "tier": "low",
  "subject_type": "company",
  "webhook_url": "https://example.com/hooks/sixtyfour",
  "webhook_event_types": ["monitor.field.changed", "monitor.execution.failed"],
  "metadata": { "portfolio_id": "p_42" }
}
```

### Example response

```json theme={null}
{
  "id": "0b7f2c6e-4a1d-4a8e-9f3b-2d5c8e1a7b90",
  "org_id": "org_abc123",
  "team_id": "5e1d9c3a-7b2f-4e6a-8c1d-3f9a2b4c6d8e",
  "name": "Portfolio leadership",
  "frequency": "1d",
  "watched": {
    "ceo_name": "Full name of the current CEO",
    "headcount": { "type": "int", "description": "Current number of employees" }
  },
  "tier": "low",
  "subject_type": "company",
  "research_plan": null,
  "is_active": true,
  "disabled_reason": null,
  "webhook_url": "https://example.com/hooks/sixtyfour",
  "metadata": { "portfolio_id": "p_42" },
  "last_run_at": null,
  "next_run_times": [
    "2026-09-29T00:00:00+00:00",
    "2026-09-30T00:00:00+00:00",
    "2026-10-01T00:00:00+00:00"
  ],
  "row_count": 2,
  "active_row_count": 2,
  "created_at": "2026-09-28T17:05:12.482Z",
  "updated_at": "2026-09-28T17:05:12.482Z",
  "rows": [
    {
      "id": "8c3e1f2a-6b4d-4c9e-a1f7-2e5d9b3c7a10",
      "org_id": "org_abc123",
      "team_id": "5e1d9c3a-7b2f-4e6a-8c1d-3f9a2b4c6d8e",
      "name": "Portfolio leadership — Acme Robotics, acmerobotics.com",
      "frequency": "1d",
      "subject": { "company_name": "Acme Robotics", "domain": "acmerobotics.com" },
      "watched": {
        "ceo_name": "Full name of the current CEO",
        "headcount": { "type": "int", "description": "Current number of employees" }
      },
      "baseline": { "ceo_name": "Dana Lee" },
      "tier": "low",
      "subject_type": "company",
      "research_plan": null,
      "is_active": true,
      "disabled_reason": null,
      "webhook_url": "https://example.com/hooks/sixtyfour",
      "metadata": { "portfolio_id": "p_42" },
      "last_run_at": null,
      "next_run_times": [
        "2026-09-29T00:00:00+00:00",
        "2026-09-30T00:00:00+00:00",
        "2026-10-01T00:00:00+00:00"
      ],
      "created_at": "2026-09-28T17:05:12.531Z",
      "updated_at": "2026-09-28T17:05:12.531Z"
    }
  ]
}
```

The response lists every row. The example shows one for brevity.

***

## List monitors

Retrieve your team's monitors, newest first. Rows are not included.

```http theme={null}
GET https://api.sixtyfour.ai/monitors
```

| Query parameter    | Default | Description                            |
| ------------------ | ------- | -------------------------------------- |
| `include_inactive` | `false` | Include cancelled and paused monitors. |
| `limit`            | `50`    | Page size, 1–200.                      |
| `cursor`           | —       | `next_cursor` from the previous page.  |

The response is `{ "monitors": [...], "next_cursor": "..." }`. `next_cursor` is `null` on the last page.

***

## Get monitor

Retrieve a monitor and every row in it, switched-off rows included.

```http theme={null}
GET https://api.sixtyfour.ai/monitors/{monitor_id}
```

A row has no schedule of its own. Its `next_run_times` are the monitor's, and are empty when the row is switched off.

***

## Get the monitor a workflow run started

Retrieve the monitor that a workflow's `monitor` block started, with its rows.

```http theme={null}
GET https://api.sixtyfour.ai/monitors/for-run/{workflow_run_id}/{block_id}
```

Returns `404` when that block did not start a monitor, or when the monitor belongs to another team. See the [`monitor` block](/api-reference/workflows/workflow-blocks#monitor).

***

## Update monitor

Change what a monitor watches, how often, how deeply, or where it notifies.

```http theme={null}
POST https://api.sixtyfour.ai/monitors/{monitor_id}/update
```

All body fields are optional: `name`, `frequency`, `tier`, `struct`, `webhook_url`, `metadata`, `is_active`. Changes apply to every row. Send `null` for `webhook_url` or `metadata` to clear them.

`is_active` pauses or resumes the whole monitor. Pausing through this endpoint sets `disabled_reason: "paused"`, and resuming clears it. A row you switched off stays off when the monitor resumes.

### Example request

```json theme={null}
{
  "frequency": "6h",
  "tier": "medium"
}
```

***

## Trigger monitor

Check every active row now, without waiting for the next scheduled fire.

```http theme={null}
POST https://api.sixtyfour.ai/monitors/{monitor_id}/trigger
```

Returns `202` with `{ "status": "accepted", "monitor_id": "..." }`. Returns `409` if the monitor is not active. If a check of the monitor is already running, the triggered one is skipped.

***

## Cancel monitor

Stop checking the whole monitor. Rows keep their on/off switches, baselines, and history, so resuming with `POST /monitors/{monitor_id}/update` and `"is_active": true` restores the previous selection.

```http theme={null}
POST https://api.sixtyfour.ai/monitors/{monitor_id}/cancel
```

Returns the monitor with `is_active: false` and `disabled_reason: "cancelled"`.

***

## Get row

Retrieve one row, including the values its watched fields currently hold in `baseline`.

```http theme={null}
GET https://api.sixtyfour.ai/monitors/{monitor_id}/rows/{row_id}
```

***

## Switch a row on or off

Include or exclude one row from checks.

```http theme={null}
POST https://api.sixtyfour.ai/monitors/{monitor_id}/rows/{row_id}?is_active=false
```

`is_active` is a required query parameter. A switched-off row is skipped on every tick, is not billed, and keeps its baseline and history. Its `disabled_reason` is `excluded`.

***

## List row events

Retrieve one row's events, newest first.

```http theme={null}
GET https://api.sixtyfour.ai/monitors/{monitor_id}/rows/{row_id}/events
```

| Query parameter       | Default | Description                                                                           |
| --------------------- | ------- | ------------------------------------------------------------------------------------- |
| `event_group_id`      | —       | Only the events from one check, for example the `event_group_id` from a notification. |
| `field`               | —       | Only one field's history.                                                             |
| `include_completions` | `false` | Include `completion` events for checks that found no change.                          |
| `limit`               | `20`    | 1–500.                                                                                |

### Example response

```json theme={null}
[
  {
    "id": "e41c7a2b-9d3f-4b6e-8a1c-5f2d7e9b3a60",
    "event_group_id": "a7d2e9f1-3c5b-4e8a-9b1d-6f4c2e8a0b37",
    "event_type": "change",
    "field": "ceo_name",
    "previous_value": "Dana Lee",
    "current_value": "Priya Raman",
    "payload": {
      "sources": ["https://acmerobotics.com/about/leadership"],
      "confidence": 92,
      "justification": "The company's leadership page lists Priya Raman as CEO as of September 2026.",
      "hint": "Leadership page updated with a new CEO.",
      "metadata": { "portfolio_id": "p_42" }
    },
    "created_at": "2026-10-02T00:04:51.118Z"
  }
]
```

See [Events](/api-reference/monitors/monitors-overview#events) for every event type.

***

## List snapshots

List every moment the monitor's data changed, newest first, each with a download link. A snapshot is recorded per change, not per check: the changes from one tick share one snapshot.

```http theme={null}
GET https://api.sixtyfour.ai/monitors/{monitor_id}/snapshots
```

Optional query parameter: `limit` — 1–500, default `100`.

### Example response

```json theme={null}
[
  {
    "as_of": "2026-10-02T00:04:51+00:00",
    "changed_fields": ["ceo_name"],
    "subjects_changed": 1,
    "url": "https://api.sixtyfour.ai/monitors/0b7f2c6e-4a1d-4a8e-9f3b-2d5c8e1a7b90/snapshots/2026-10-02T00%3A04%3A51%2B00%3A00"
  }
]
```

***

## Download snapshot

Download the table as it stood at a moment, as CSV: one row per subject, with the key columns followed by the watched fields.

```http theme={null}
GET https://api.sixtyfour.ai/monitors/{monitor_id}/snapshots/{as_of}
```

`as_of` is an `as_of` value from the snapshot list, URL-encoded, or `latest` for the current values. Any ISO 8601 timestamp is accepted and returns the values held at that time.

***

## Example usage

Create a monitor, then read the changes for one of its rows.

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST "https://api.sixtyfour.ai/monitors" \
    -H "x-api-key: YOUR_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "name": "Portfolio leadership",
      "key_columns": ["company_name", "domain"],
      "rows": [
        {"company_name": "Acme Robotics", "domain": "acmerobotics.com", "ceo_name": "Dana Lee"}
      ],
      "struct": {"ceo_name": "Full name of the current CEO"},
      "frequency": "1d",
      "subject_type": "company"
    }'

  curl "https://api.sixtyfour.ai/monitors/MONITOR_ID/rows/ROW_ID/events?field=ceo_name" \
    -H "x-api-key: YOUR_API_KEY"
  ```

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

  API_KEY = "YOUR_API_KEY"
  BASE_URL = "https://api.sixtyfour.ai"
  headers = {"x-api-key": API_KEY, "Content-Type": "application/json"}

  response = requests.post(
      f"{BASE_URL}/monitors",
      headers=headers,
      json={
          "name": "Portfolio leadership",
          "key_columns": ["company_name", "domain"],
          "rows": [
              {"company_name": "Acme Robotics", "domain": "acmerobotics.com", "ceo_name": "Dana Lee"}
          ],
          "struct": {"ceo_name": "Full name of the current CEO"},
          "frequency": "1d",
          "subject_type": "company",
      },
  )
  response.raise_for_status()
  monitor = response.json()
  row_id = monitor["rows"][0]["id"]

  events = requests.get(
      f"{BASE_URL}/monitors/{monitor['id']}/rows/{row_id}/events",
      headers=headers,
      params={"field": "ceo_name"},
  )
  events.raise_for_status()
  for event in events.json():
      print(event["event_type"], event["previous_value"], "->", event["current_value"])
  ```

  ```javascript JavaScript theme={null}
  const API_KEY = "YOUR_API_KEY";
  const BASE_URL = "https://api.sixtyfour.ai";
  const headers = { "x-api-key": API_KEY, "Content-Type": "application/json" };

  const response = await fetch(`${BASE_URL}/monitors`, {
    method: "POST",
    headers,
    body: JSON.stringify({
      name: "Portfolio leadership",
      key_columns: ["company_name", "domain"],
      rows: [
        { company_name: "Acme Robotics", domain: "acmerobotics.com", ceo_name: "Dana Lee" },
      ],
      struct: { ceo_name: "Full name of the current CEO" },
      frequency: "1d",
      subject_type: "company",
    }),
  });
  if (!response.ok) {
    throw new Error(`Failed to create monitor: ${await response.text()}`);
  }
  const monitor = await response.json();
  const rowId = monitor.rows[0].id;

  const eventsResponse = await fetch(
    `${BASE_URL}/monitors/${monitor.id}/rows/${rowId}/events?field=ceo_name`,
    { headers },
  );
  const events = await eventsResponse.json();
  for (const event of events) {
    console.log(event.event_type, event.previous_value, "->", event.current_value);
  }
  ```
</CodeGroup>
