# Update a monitor — API reference

> Updates selected monitor fields.

Source: https://upfour.io/docs/api/monitors/update-a-monitor

[Developers](https://upfour.io/docs/api.md)/[Monitors](https://upfour.io/docs/api/monitors.md)

Updates selected monitor fields.

PATCH https://app.upfour.io/v1/monitors/{monitorID}

scope monitor.write stable [Idempotency-Key supported](https://upfour.io/docs/api/idempotency.md) returns 200

## Parameters

| Field | Type | Description |
| --- | --- | --- |
| `monitorID` required | uuid | path parameter |

## Body

The 6 fields most calls use come first; the rest are grouped below.

`application/json` required 56 fields

urlstring

In the app: **URL to watch**

monitor_typestring

httptcppingdns

namestring

In the app: **Name**

interval_secondsinteger

In the app: **Check every**

regionsstring[]

euusasiaaudefault

In the app: **Regions**

notification_channel_idsuuid[]

What counts as up5 fields

alert_typestring

""statuskeywordkeyword_absenceexpected_status_code

In the app: **Counts as down when**

keywordstring

In the app: **Text to look for**

keyword_case_insensitiveboolean · nullable

In the app: **Ignore case**

expected_status_codeinteger · nullable

In the app: **Expected status code**

ssl_verificationboolean · nullable

In the app: **Verify the TLS certificate**

Request15 fields

http_methodstring

In the app: **HTTP method**

request_headersRequestHeader[]

Custom request headers, at most 20 and 8 KB in total. On update they are kept unless request_headers_action is replace or clear.

In the app: **Headers**

Nested fields 2 fields

| Field | Type | Description |
| --- | --- | --- |
| `name` optional | string | |
| `value` optional | string | |

request_headers_actionstring

keepreplaceclear

request_bodystring

In the app: **Request body**

request_timeout_sinteger

In the app: **Request timeout**

follow_redirectsboolean · nullable

In the app: **Follow redirects**

keep_cookiesboolean

In the app: **Keep cookies when redirecting**

auth_usernamestring

In the app: **Username**

auth_passwordstring

Basic-auth password. Write-only: responses carry has_auth_password instead.

In the app: **Password**

auth_password_actionstring

""keepreplaceclear

proxy_hoststring

In the app: **Proxy**

proxy_portinteger · nullable

ip_versionstring

""46

In the app: **IP version**

Alerting11 fields

notification_modestring

quietimmediate

In the app: **When should we alert you?**

alert_channel_namesstring[]

escalation_policy_iduuid · nullable

In the app: **Alert plan**

alert_plan_namestring

default_alert_planboolean

confirmation_periodinteger

In the app: **Extra confirmation time**

recovery_periodinteger

In the app: **Recovery period**

notify_recoveryboolean · nullable

degraded_alert_enabledboolean

degraded_threshold_msinteger · nullable

capture_on_incident_openboolean · nullable

In the app: **Incident screenshots**

Port and DNS checks6 fields

tcp_hoststring

In the app: **Host**

tcp_portinteger · nullable

In the app: **Port**

dns_querystring

In the app: **Domain to look up**

dns_typestring

""AAAAAMXCNAMETXTNS

In the app: **Record type**

dns_serverstring

In the app: **DNS server**

dns_expectedstring

In the app: **Expected answer**

Expiry warnings2 fields

ssl_expiry_alert_daysinteger · nullable

In the app: **Certificate expiry warning**

domain_expiry_alert_daysinteger · nullable

In the app: **Domain expiry warning**

Maintenance window4 fields

maintenance_fromstring · nullable

In the app: **From**

maintenance_tostring · nullable

In the app: **Until**

maintenance_weekdaysstring[]

montuewedthufrisatsun

In the app: **On these days**

maintenance_timezonestring

In the app: **Timezone**

Organizing9 fields

client_iduuid · nullable

client_namestring

monitor_group_iduuid · nullable

monitor_group_namestring

public_namestring · nullable

pronounceable_namestring

metadatamap of stringmax 100 keyseach value max length 4096

On update, omitted or null leaves the stored metadata unchanged, {} removes all keys and any other object replaces them.

statestring

UP, DOWN or PAUSED. Required on PUT; PATCH keeps the current state when omitted.

UPDOWNPAUSED

creation_keyuuid · nullable

## Returns

A successful request returns `200` with application/json.

Response fields 1 top-level fields

| Field | Type | Description |
| --- | --- | --- |
| `data` | Monitor | |
| Monitor · 70 fields FieldTypeDescription `alert_type` string one of`status` `keyword` `keyword_absence` `expected_status_code` `auth_username` string `capture_on_incident_open` boolean `confirmation_period` integer `created_at` string (date-time) `degraded_alert_enabled` boolean `degraded_threshold_ms` integer  · nullable `domain_expiry_alert_days` integer  · nullable `escalation_policy_id` uuid  · nullable `expected_status_code` integer  · nullable `feature_pause_reasons` string[]  · nullable `follow_redirects` boolean `has_auth_password` boolean `has_request_headers` boolean `http_method` string `id` uuid `interval_seconds` integer `ip_version` string one of`""` `4` `6` `is_degraded` boolean `is_pending` boolean `keep_cookies` boolean `keyword` string `keyword_case_insensitive` boolean `maintenance_from` string  · nullable `maintenance_timezone` string `maintenance_to` string  · nullable `maintenance_weekdays` string[]  · nullable one of`mon` `tue` `wed` `thu` `fri` `sat` `sun` `monitor_type` string one of`http` `tcp` `ping` `dns` `name` string `next_check_at` string (date-time)  · nullable `notification_mode` string one of`quiet` `immediate` `notify_recovery` boolean `pronounceable_name` string `proxy_host` string `proxy_port` integer  · nullable `public_name` string `recovery_period` integer `regions` string[]  · nullable one of`eu` `us` `asia` `au` `default` `request_body` string `request_headers` any[]  · nullable Always empty: header values are never returned. has_request_headers says whether the monitor sends any. `request_timeout_s` integer `ssl_expiry_alert_days` integer  · nullable `ssl_verification` boolean `state` string one of`UP` `DOWN` `PAUSED` `url` string `user_id` uuid `badge_token` string `client_id` uuid `dns_expected` string `dns_query` string `dns_server` string `dns_type` string one of`A` `AAAA` `MX` `CNAME` `TXT` `NS` `freshness_timeout_seconds` integer `last_checked_at` string (date-time) `last_result_at` string (date-time) `last_state_change_at` string (date-time) `latency_p50_ms` integer `latency_p95_ms` integer `latency_samples_24h` integer `latest_result_successful` boolean `monitor_group_id` uuid `paused_until` string (date-time) `recent_incidents` MonitorRecentIncident[] Each item · 5 fields FieldTypeDescription `id` uuid `resolved_at` string (date-time)  · nullable `started_at` string (date-time) `status` string `resolved_by_type` string `tcp_host` string `tcp_port` integer | | |

## Errors

Only the errors this operation can return. Every error uses the [same envelope](https://upfour.io/docs/api/responses.md).

| Status | Code | Meaning |
| --- | --- | --- |
| 400 | [bad_request](https://upfour.io/docs/api/errors#code-bad_request) | The request is malformed or fails validation. |
| 403 | [check_capacity_exceeded](https://upfour.io/docs/api/errors#code-check_capacity_exceeded) | The change would push the subscription's projected monthly check load over its included budget. **When:** Creating a monitor, directly or through a client template, or changing one, when the projected cost including the change exceeds the budget; running monitors are not affected, and details carries projected_cents, included_cents and change_cents. **Fix:** Use a longer interval, fewer regions or fewer monitors, or raise the included budget. `check_capacity_exceeded` (subscriptions only): the change would raise the projected 30-day list usage of all active monitors above the included check budget. `error.details` carries `projected_cents`, `included_cents` and `change_cents`; a longer interval, fewer regions or fewer monitors fit. Running monitors and changes that lower the load are never refused. |
| 403 | [feature_disabled](https://upfour.io/docs/api/errors#code-feature_disabled) | The monitor uses a feature that is currently switched off. **When:** Saving a monitor whose configuration needs a feature the platform has disabled; the saved configuration stays as it was. **Fix:** Remove that feature from the monitor, or try again once the feature is back. |
| 404 | [not_found](https://upfour.io/docs/api/errors#code-not_found) | The requested resource does not exist or is outside the caller's scope. |
| 402 | [payment_required](https://upfour.io/docs/api/errors#code-payment_required) | The account does not have the credit or plan required for this action. |
| 403 | [permission_denied](https://upfour.io/docs/api/errors#code-permission_denied) | The credentials do not permit this action. |

Every call can also return `unauthorized` (401), `rate_limit_exceeded` (429) or `internal_error` (500 / 502). See [Responses and errors](https://upfour.io/docs/api/responses.md).

## Related

[guideWatch a website](https://upfour.io/docs/watch-a-website.md)[guideChecks and regions](https://upfour.io/docs/how/checks-and-regions.md)[guideCheck page content](https://upfour.io/docs/check-page-content.md)[guideWhen you get alerted](https://upfour.io/docs/how/when-you-get-alerted.md)

[PreviousGet a monitor](https://upfour.io/docs/api/monitors/get-a-monitor.md) [NextReplace a monitor](https://upfour.io/docs/api/monitors/replace-a-monitor.md)

## Request

### cURL

```bash
curl -s -X PATCH "https://app.upfour.io/v1/monitors/00000000-0000-4000-8000-000000000001" \
  -H "Authorization: Bearer $UP4_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "interval_seconds": 120
  }'
```

### JavaScript

```javascript
const res = await fetch("https://app.upfour.io/v1/monitors/00000000-0000-4000-8000-000000000001", {
  method: "PATCH",
  headers: {
    Authorization: `Bearer ${process.env.UP4_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    interval_seconds: 120,
  }),
});
console.log(res.status, await res.json());
```

### Python

```python
import os
import requests

res = requests.patch(
    "https://app.upfour.io/v1/monitors/00000000-0000-4000-8000-000000000001",
    headers={"Authorization": f"Bearer {os.environ['UP4_API_KEY']}"},
    json={
        "interval_seconds": 120,
    },
)
print(res.status_code, res.json())
```

### Go

```go
package main

import (
	"fmt"
	"io"
	"net/http"
	"os"
	"strings"
)

func main() {
	payload := strings.NewReader(`{
  "interval_seconds": 120
}`)
	req, _ := http.NewRequest("PATCH", "https://app.upfour.io/v1/monitors/00000000-0000-4000-8000-000000000001", payload)
	req.Header.Set("Authorization", "Bearer "+os.Getenv("UP4_API_KEY"))
	req.Header.Set("Content-Type", "application/json")
	res, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()
	out, _ := io.ReadAll(res.Body)
	fmt.Println(res.StatusCode, string(out))
}
```

### PHP

```php
<?php
$payload = <<<'JSON'
{
  "interval_seconds": 120
}
JSON;

$ch = curl_init("https://app.upfour.io/v1/monitors/00000000-0000-4000-8000-000000000001");
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => "PATCH",
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        "Authorization: Bearer " . getenv("UP4_API_KEY"),
        "Content-Type: application/json",
    ],
    CURLOPT_POSTFIELDS => $payload,
]);
$response = curl_exec($ch);
echo curl_getinfo($ch, CURLINFO_RESPONSE_CODE), " ", $response, "\n";
curl_close($ch);
```

## Response

### 200

```json
{
  "data": {
    "alert_type": "status",
    "auth_username": "",
    "capture_on_incident_open": false,
    "confirmation_period": 0,
    "created_at": "2026-10-27T09:00:00Z",
    "degraded_alert_enabled": false,
    "degraded_threshold_ms": null,
    "dns_type": "A",
    "domain_expiry_alert_days": null,
    "escalation_policy_id": null,
    "expected_status_code": null,
    "feature_pause_reasons": [],
    "follow_redirects": true,
    "freshness_timeout_seconds": 180,
    "has_auth_password": false,
    "has_request_headers": false,
    "http_method": "HEAD",
    "id": "00000000-0000-4000-8000-000000000001",
    "interval_seconds": 120,
    "ip_version": "",
    "is_degraded": false,
    "is_pending": false,
    "keep_cookies": false,
    "keyword": "",
    "keyword_case_insensitive": true,
    "last_result_at": "2026-10-27T08:50:00Z",
    "latest_result_successful": true,
    "maintenance_from": null,
    "maintenance_timezone": "UTC",
    "maintenance_to": null,
    "maintenance_weekdays": [
      "mon",
      "tue",
      "wed",
      "thu",
      "fri",
      "sat",
      "sun"
    ],
    "monitor_type": "http",
    "name": "Marketing website",
    "next_check_at": "2026-10-27T09:00:00Z",
    "notification_mode": "immediate",
    "notify_recovery": true,
    "pronounceable_name": "",
    "proxy_host": "",
    "proxy_port": null,
    "public_name": "",
    "recovery_period": 0,
    "regions": [
      "eu"
    ],
    "request_body": "",
    "request_headers": [],
    "request_timeout_s": 30,
    "ssl_expiry_alert_days": null,
    "ssl_verification": true,
    "state": "UP",
    "url": "https://example.com",
    "user_id": "00000000-0000-4000-8000-000000000002"
  }
}
```

### 400

```json
{
  "error": {
    "code": "bad_request",
    "message": "The request is malformed or fails validation.",
    "request_id": "req_…"
  }
}
```

### 402

```json
{
  "error": {
    "code": "payment_required",
    "message": "The account does not have the credit or plan required for this action.",
    "request_id": "req_…"
  }
}
```

### 403

```json
{
  "error": {
    "code": "check_capacity_exceeded",
    "message": "The change would push the subscription's projected monthly check load over its included budget.",
    "request_id": "req_…"
  }
}
```

### 404

```json
{
  "error": {
    "code": "not_found",
    "message": "The requested resource does not exist or is outside the caller's scope.",
    "request_id": "req_…"
  }
}
```
