---
title: "Monitors"
description: "Create, update, delete, and query monitors via the REST API."
doc_version: "1"
last_updated: "2026-06-02"
---

## Create a monitor

```bash
curl -X POST https://api.uptimemonitoring.com/api/v1/monitors \
  -H "Authorization: Bearer $UPTIMEMONITORING_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "api-prod",
    "url": "https://example.com/",
    "type": "http",
    "expected_status": "200"
  }'
```

The target hostname must resolve at creation time — the API runs an immediate test check, and unresolvable hosts are rejected up front.

The response wraps the monitor and its first state snapshot:

```json
{
  "monitor": {
    "id": 1287,
    "name": "api-prod",
    "url": "https://example.com/",
    "type": "http",
    "interval_sec": 60,
    "expected_status": "200",
    "enabled": true,
    "created_at": "2026-05-07T10:21:00Z"
  },
  "state": {
    "status": "up",
    "last_check_at": "2026-05-07T10:21:01Z",
    "evidence_buffer": [
      {
        "region": "EU",
        "status_code": 200,
        "ttfb_ms": 182
      }
    ]
  }
}
```

> **Notes for integrators:**
> - Unknown request fields are silently ignored — the API is forward-compatible.
> - Timestamps in responses (e.g. `last_check_at`) use RFC 3339 with nanosecond precision. If your client library caps at milliseconds, truncate before parsing.

### Required fields

| Field | Type | Description |
|-------|------|-------------|
| `name` | string | Monitor name (max 255 chars) |
| `url` | string | Target URL (max 2048 chars) |
| `type` | string | `http`, `tcp`, `ping`, `dns`, `ssl` |

All string fields must be valid UTF-8 with no null bytes; URL fields must additionally be free of ASCII control characters (`U+0000`–`U+001F` and `U+007F`). Violations return `400` before the SSRF guard runs.

The immediate test check populates `state.status` to `up` or `down` only for HTTP and SSL monitors. TCP, ping, and DNS monitors return `state.status: "unknown"` from the create response — the next scheduled tick fills it in. HTTP creates can also return `unknown` if the probe is unavailable, the kill switch is engaged, or the URL fails the dispatch-time SSRF guard (DNS rebind).

### Optional fields

| Field | Type | Default | Description |
|-------|------|---------|-------------|
| `expected_status` | string | `"200"` | Single HTTP status code as a string (`"100"`–`"599"`). Range or list values (e.g. `"200-399"`, `"200,201"`) are rejected — see Errors. |
| `body_match` | string | — | Response body must contain this string (max 1024 chars). The field may be absent from responses when unset; treat absent and `null` identically. |
| `interval_sec` | integer | `60` | Check interval in seconds (minimum 60) |
| `enabled` | boolean | `true` | Whether the monitor is actively checking. Set `false` to pause without deleting. |

## Monitor types

### HTTP / HTTPS
Checks status code, optional body match, full timing breakdown (DNS, connect, TLS, TTFB, download).

### TCP
Connects to a service port. Restricted to common service ports for abuse prevention.

### Ping (ICMP)
Basic reachability check.

### DNS
Verifies record presence and values.

### SSL
Monitors certificate expiry.

## Check behavior

- **60-second minimum interval** (30-second reserved for future paid tier)
- **Phase-spread scheduling** — checks are spread across the interval window, not clustered at the top of the minute
- **Cross-region confirmation** — any failure triggers re-checks from 2 additional regions. State flips only when 2 of 3 agree.
- **Exponential backoff** — sustained-down monitors back off from 1 min to 5 min after 10 minutes of continuous downtime
- **Flap detection** — monitors transitioning more than 10 times per hour are flagged as flapping

## List monitors

```bash
curl https://api.uptimemonitoring.com/api/v1/monitors \
  -H "Authorization: Bearer $UPTIMEMONITORING_API_KEY"
```

The list endpoint returns every monitor on the account in a single response. There is no filtering or pagination — `?limit`, `?offset`, `?status`, and `?type` are accepted but silently ignored. Apply filters client-side.

The list response is a **bare JSON array** of monitor records with the current `status` and `last_check_at` flattened into each entry (no `{monitor, state}` wrapping). For the full state — including `evidence_buffer` — use `GET /api/v1/monitors/{id}`.

Response shape (abridged):

```json
[
  {
    "id": 1287,
    "name": "api-prod",
    "url": "https://example.com/",
    "type": "http",
    "interval_sec": 60,
    "expected_status": "200",
    "enabled": true,
    "created_at": "2026-05-07T10:21:00Z",
    "status": "up",
    "last_check_at": "2026-05-07T10:21:01Z"
  }
]
```

## Get a monitor

```bash
curl https://api.uptimemonitoring.com/api/v1/monitors/1287 \
  -H "Authorization: Bearer $UPTIMEMONITORING_API_KEY"
```

Response (single envelope):

```json
{
  "monitor": {
    "id": 1287,
    "name": "api-prod",
    "url": "https://example.com/",
    "type": "http",
    "interval_sec": 60,
    "expected_status": "200",
    "enabled": true,
    "created_at": "2026-05-07T10:21:00Z"
  },
  "state": {
    "status": "up",
    "last_check_at": "2026-05-07T10:25:43Z",
    "evidence_buffer": [
      {
        "region": "EU",
        "timestamp": "2026-05-07T10:25:43Z",
        "status_code": 200,
        "ttfb_ms": 174
      },
      {
        "region": "US",
        "timestamp": "2026-05-07T10:24:42Z",
        "status_code": 200,
        "ttfb_ms": 198
      }
    ]
  }
}
```

A non-numeric path parameter (e.g. `/monitors/abc`) returns `400 invalid monitor ID`. A numeric-but-missing ID returns `404 monitor not found`.

## Update a monitor

```bash
curl -X PUT https://api.uptimemonitoring.com/api/v1/monitors/1287 \
  -H "Authorization: Bearer $UPTIMEMONITORING_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name": "api-prod-v2"}'
```

`PUT` accepts a partial body — fields you omit keep their current values. `PATCH` is not supported and returns `405`.

## Delete a monitor

```bash
curl -X DELETE https://api.uptimemonitoring.com/api/v1/monitors/1287 \
  -H "Authorization: Bearer $UPTIMEMONITORING_API_KEY"
```