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

# Monitors API: create, list, update, and delete monitors

> List, create, retrieve, update, delete, and pause monitors; query check results; full request and response reference for all five monitor types.

Monitors are the core resource in Overwatch. Each monitor represents a single check — an HTTP endpoint, TCP port, TLS certificate, DNS record, or scheduled job — that your workers run on a recurring interval. This page covers every monitor endpoint: listing, creating, reading, updating, deleting, pausing, and retrieving historical check results.

***

## List monitors

```
GET /api/v1/monitors
```

Returns all monitors in your organization, enriched with uptime percentage, the latest check result, and a bucketed status history for the selected time range.

### Query parameters

<ParamField query="type" type="string">
  Filter monitors by type. One of `HTTP`, `TCP`, `TLS`, `DNS`, `SCHEDULED`. Omit to return all types.
</ParamField>

<ParamField query="range" type="string">
  Time range for the history buckets and uptime calculation. One of `1d`, `7d`, `30d`, `90d`. Defaults to `90d`. Uptime percentage is always computed over the trailing 90 days regardless of this value.
</ParamField>

### Response

```json theme={null}
{
  "data": [
    {
      "id": "mon_01j...",
      "name": "API health",
      "type": "HTTP",
      "config": { "url": "https://api.example.com/health", "interval": 60 },
      "status": "up",
      "enabled": true,
      "latestResult": {
        "status": "up",
        "latencyMs": 142,
        "createdAt": "2025-04-15T10:00:00.000Z"
      },
      "uptime": "99.87%",
      "history": [
        { "status": "up", "label": "Apr 13–14" },
        { "status": "degraded", "label": "Apr 14–15" }
      ],
      "createdAt": "2025-01-01T00:00:00.000Z",
      "updatedAt": "2025-04-15T10:00:00.000Z"
    }
  ]
}
```

<ResponseField name="data" type="EnrichedMonitor[]">
  Array of monitor objects. Each object includes all monitor fields plus enrichment.

  <Expandable title="EnrichedMonitor fields">
    <ResponseField name="id" type="string">Unique monitor ID (UUID).</ResponseField>
    <ResponseField name="name" type="string">Display name of the monitor.</ResponseField>
    <ResponseField name="type" type="string">Monitor type: `HTTP`, `TCP`, `TLS`, `DNS`, or `SCHEDULED`.</ResponseField>
    <ResponseField name="config" type="object">Type-specific configuration. See [Monitor config by type](#monitor-config-by-type).</ResponseField>
    <ResponseField name="status" type="string">Current status. See [Monitor statuses](#monitor-statuses).</ResponseField>
    <ResponseField name="enabled" type="boolean">Whether the monitor is actively running checks.</ResponseField>

    <ResponseField name="latestResult" type="object | null">
      The most recent check result within the selected range, or `null` if none exists.

      <Expandable title="latestResult fields">
        <ResponseField name="status" type="string">Status from the last check.</ResponseField>
        <ResponseField name="latencyMs" type="number | null">Round-trip latency in milliseconds, if applicable.</ResponseField>
        <ResponseField name="createdAt" type="string">ISO 8601 timestamp of the check.</ResponseField>
      </Expandable>
    </ResponseField>

    <ResponseField name="uptime" type="string | null">Uptime percentage over the trailing 90 days, e.g. `"99.87%"`. `null` if there are no results yet.</ResponseField>

    <ResponseField name="history" type="object[]">
      Bucketed status history for the selected range.

      <Expandable title="history item fields">
        <ResponseField name="status" type="string">Worst status observed in that bucket, or `unknown` if no checks ran.</ResponseField>
        <ResponseField name="label" type="string">Human-readable label for the time bucket, e.g. `"Apr 7–8"`.</ResponseField>
      </Expandable>
    </ResponseField>

    <ResponseField name="createdAt" type="string">ISO 8601 creation timestamp.</ResponseField>
    <ResponseField name="updatedAt" type="string">ISO 8601 last-updated timestamp.</ResponseField>
  </Expandable>
</ResponseField>

### Example

```bash theme={null}
curl https://overwatchapp.dev/api/v1/monitors?type=HTTP&range=7d \
  -H "Authorization: Bearer $API_KEY"
```

***

## Create a monitor

```
POST /api/v1/monitors
```

Creates a new monitor. Requires `admin` or `owner` role. Returns `402` if your organization has no active subscription, and `422` with `"upgrade": true` if you have reached your monitor limit.

### Request body

<ParamField body="name" type="string" required>
  Display name for the monitor.
</ParamField>

<ParamField body="type" type="string" required>
  Monitor type. One of `HTTP`, `TCP`, `TLS`, `DNS`, `SCHEDULED`.
</ParamField>

<ParamField body="config" type="object" required>
  Type-specific configuration object. See [Monitor config by type](#monitor-config-by-type) below.
</ParamField>

<ParamField body="alertChannelIds" type="string[]">
  Optional list of alert channel IDs to bind to this monitor. Alerts fire on status changes.
</ParamField>

### Monitor config by type

<CodeGroup>
  ```json HTTP theme={null}
  {
    "url": "https://api.example.com/health",
    "interval": 60
  }
  ```

  ```json TCP theme={null}
  {
    "host": "db.example.com",
    "port": 5432,
    "interval": 60
  }
  ```

  ```json TLS theme={null}
  {
    "host": "example.com",
    "port": 443,
    "interval": 300
  }
  ```

  ```json DNS theme={null}
  {
    "hostname": "example.com",
    "interval": 300
  }
  ```

  ```json SCHEDULED theme={null}
  {
    "interval": 300
  }
  ```
</CodeGroup>

<Note>
  For `SCHEDULED` monitors, the `interval` field in `config` is always set to `300` seconds regardless of what you submit. The interval for scheduled job monitors is determined by how often your job calls the checkin URL — not by the config.
</Note>

### Monitor statuses

The statuses a monitor can report depend on its type:

| Type        | Possible statuses                               |
| ----------- | ----------------------------------------------- |
| `HTTP`      | `up`, `down`, `degraded`                        |
| `TCP`       | `up`, `down`, `degraded`                        |
| `TLS`       | `active`, `expiring_soon`, `expired`, `no_cert` |
| `DNS`       | `present`, `missing`, `changed`                 |
| `SCHEDULED` | `ok`, `failed`, `havent_heard`                  |

### Response

Returns `201 Created` with the new monitor object. For `SCHEDULED` monitors, the response also includes a `checkinUrl` field — the public URL your cron job should call to register a successful run.

```json theme={null}
{
  "data": {
    "id": "mon_01j...",
    "name": "Nightly export job",
    "type": "SCHEDULED",
    "config": { "interval": 300 },
    "status": "unknown",
    "enabled": true,
    "checkinUrl": "https://overwatchapp.dev/api/v1/monitors/mon_01j.../checkin",
    "createdAt": "2025-04-15T10:00:00.000Z",
    "updatedAt": "2025-04-15T10:00:00.000Z"
  }
}
```

### Example

```bash theme={null}
curl -X POST https://overwatchapp.dev/api/v1/monitors \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "API health",
    "type": "HTTP",
    "config": { "url": "https://api.example.com/health", "interval": 60 },
    "alertChannelIds": ["alc_01j..."]
  }'
```

***

## Get a monitor

```
GET /api/v1/monitors/:id
```

Returns a single monitor by ID, including its bound alert channels.

### Path parameters

<ParamField path="id" type="string" required>
  The monitor ID.
</ParamField>

### Response

```json theme={null}
{
  "data": {
    "id": "mon_01j...",
    "name": "API health",
    "type": "HTTP",
    "config": { "url": "https://api.example.com/health", "interval": 60 },
    "status": "up",
    "enabled": true,
    "alertBindings": [
      {
        "monitorId": "mon_01j...",
        "alertChannelId": "alc_01j..."
      }
    ],
    "createdAt": "2025-01-01T00:00:00.000Z",
    "updatedAt": "2025-04-15T10:00:00.000Z"
  }
}
```

### Example

```bash theme={null}
curl https://overwatchapp.dev/api/v1/monitors/$MONITOR_ID \
  -H "Authorization: Bearer $API_KEY"
```

***

## Update a monitor

```
PATCH /api/v1/monitors/:id
```

Updates one or more fields on a monitor. All fields are optional — only the fields you include are changed. Requires `admin` or `owner` role.

When you supply `alertChannelIds`, the full list of bindings is replaced with the new set. Pass an empty array (`[]`) to remove all alert bindings.

### Path parameters

<ParamField path="id" type="string" required>
  The monitor ID.
</ParamField>

### Request body

<ParamField body="name" type="string">
  New display name.
</ParamField>

<ParamField body="config" type="object">
  Updated type-specific configuration. For `SCHEDULED` monitors, `interval` is always forced to `300`.
</ParamField>

<ParamField body="enabled" type="boolean">
  Set to `false` to pause this monitor, `true` to resume it.
</ParamField>

<ParamField body="alertChannelIds" type="string[]">
  Replaces the monitor's alert channel bindings with this list.
</ParamField>

### Response

Returns the updated monitor object with `200 OK`.

### Example

```bash theme={null}
curl -X PATCH https://overwatchapp.dev/api/v1/monitors/$MONITOR_ID \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "enabled": false }'
```

***

## Delete a monitor

```
DELETE /api/v1/monitors/:id
```

Permanently deletes a monitor and all associated check results. Requires `admin` or `owner` role.

### Path parameters

<ParamField path="id" type="string" required>
  The monitor ID.
</ParamField>

### Response

```json theme={null}
{
  "data": { "id": "mon_01j..." }
}
```

### Example

```bash theme={null}
curl -X DELETE https://overwatchapp.dev/api/v1/monitors/$MONITOR_ID \
  -H "Authorization: Bearer $API_KEY"
```

***

## Pause all monitors

```
POST /api/v1/monitors/pause-all
```

Sets `enabled: false` on every currently-enabled monitor in your organization. Useful as an emergency kill switch during deployments or incidents. Requires `admin` or `owner` role.

### Response

Returns the count of monitors that were paused.

```json theme={null}
{
  "data": { "paused": 12 }
}
```

<ResponseField name="data.paused" type="number">
  The number of monitors that were paused by this request. Monitors that were already disabled are not counted.
</ResponseField>

### Example

```bash theme={null}
curl -X POST https://overwatchapp.dev/api/v1/monitors/pause-all \
  -H "Authorization: Bearer $API_KEY"
```

***

## Get check results for a monitor

```
GET /api/v1/monitors/:id/results
```

Returns paginated check results for a single monitor, ordered most-recent first.

### Path parameters

<ParamField path="id" type="string" required>
  The monitor ID.
</ParamField>

### Query parameters

<ParamField query="limit" type="number">
  Number of results to return. Maximum `200`, default `50`.
</ParamField>

<ParamField query="cursor" type="string">
  Cursor from a previous response to fetch the next page.
</ParamField>

### Response

```json theme={null}
{
  "data": [
    {
      "id": "res_01j...",
      "monitorId": "mon_01j...",
      "status": "up",
      "latencyMs": 137,
      "detail": null,
      "alertTriggered": false,
      "alertOutcome": null,
      "createdAt": "2025-04-15T10:00:00.000Z"
    }
  ],
  "cursor": "res_01j..."
}
```

<ResponseField name="data" type="CheckResult[]">
  Array of check result objects.
</ResponseField>

<ResponseField name="cursor" type="string | null">
  Pass this value as `?cursor=` in your next request to fetch the following page. `null` when there are no more results.
</ResponseField>

### Example

```bash theme={null}
curl "https://overwatchapp.dev/api/v1/monitors/$MONITOR_ID/results?limit=100" \
  -H "Authorization: Bearer $API_KEY"
```
