Monitors

Update monitor

Partially updates a monitor. Only include fields you want to change. Unchanged fields retain their current values. An explicit "type" other than http, tcp, or ping is rejected with 400 (issue #209), the same rule POST /api/v1/monitors enforces; omitting type leaves the stored value untouched and re-validates nothing about it.

Per-account scan heuristic (issue #335): a request that changes url or type is evaluated by the identical port-fan/host-fan heuristic POST /api/v1/monitors uses — see that endpoint's description for the exact signatures, the SCAN_PORTFAN_TCP_THRESHOLD TCP-widened ceiling, and the sliding window. A request that leaves both url and type unchanged never consults the heuristic at all. A port-fan trip returns 403 (see "Account suspended" below); a host-fan trip returns 429 with the same HostFanError body and headers POST /api/v1/monitors documents (see "Rate limit exceeded" below) — this endpoint's 429 never includes the creation-cap case, since there is no per-route creation limiter on PUT.

put/api/v1/monitors/{monitorID}

Request

  • Base URL: https://api.uptimemonitoring.com
  • URL: https://api.uptimemonitoring.com/api/v1/monitors/{monitorID}
  • Auth: HTTP bearer

Path parameters

monitorIDinteger required

Monitor ID.

Request body

namestring
urlstring

Target URL. Format depends on type:

  • http — full http(s) URL.
  • tcp — host:port or tcp://host:port, port restricted to a fixed allowlist (issue #331): 21, 22, 25, 80, 110, 143, 443, 465, 587, 993, 995, 2222, 3000, 3306, 5000, 5432, 6379, 8000, 8080, 8443, 8888, or 27017. Every create, and every update whose body includes url or type, stores the canonical tcp://host:port form (lowercase, no path) regardless of which shape was sent — example.com:443, tcp://example.com:443, and tcp://EXAMPLE.com:443/ all store as tcp://example.com:443. An update that changes neither url nor type leaves the stored URL as it is. A bracketed IPv6 literal is required ([2001:db8::1]:443); an unbracketed one is rejected as ambiguous.
  • ping — a bare hostname or IP literal (e.g. api.example.com, 1.1.1.1) — no scheme, path, query, userinfo, or port.
  • dns / ssl — reserved formats (a bare hostname for dns) for a type that is defined but not yet serviced by the check engine; see the type field.
type'http' | 'tcp' | 'ping'

http, tcp, and ping are accepted on create or update. dns and ssl are defined in the wire format but rejected with 400 (issue #209): type must be one of: http, tcp, ping, dns, ssl (currently available: http, ping, tcp) for an unrecognized value, or type '<type>' is not available yet; the check engine currently supports: http, ping, tcp for one of those two.

interval_secinteger

Check interval in seconds. Default 60.

expected_statusstring

HTTP status range. Default: 200-399. Accepted but silently ignored for type: tcp or type: ping (neither has an HTTP response to evaluate it against).

body_matchstring

Optional string to match in the response body. HTTP only — rejected with 400 (body_match is not applicable to tcp monitors) when type is tcp. Accepted but silently ignored (a harmless no-op; wopher's ping check never reads it) when type is ping.

enabledboolean

Default true.

method'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' | 'OPTIONS'

HTTP request method (issue #364). Default GET. HTTP only — sending this field at all (including its default value) on a tcp or ping create/update is 400 (method is only applicable to http monitors). On update, omitting it leaves the stored method unchanged; an explicit null is 400 (method must not be null) — but only when null is the value the request body actually decodes to: exact-duplicate JSON keys (same spelling) resolve via encoding/json's last-value-wins before this check ever runs, so {"method":null,"method":"POST"} is accepted as POST; only a differently-cased duplicate (e.g. Method alongside method) is itself rejected, as more than one key for the same field. The same caveat applies to body/timeout_sec below, which share this rejection rule.

bodystring

Request body (issue #364). Default "" — a bodiless POST is allowed. Must be valid UTF-8 with no null bytes. HTTP only, same rejection rule as method. Cleared by sending "" on update.

timeout_secinteger

Request timeout in seconds (issue #364). Default 30. HTTP only, same rejection rule as method.

Example request

{
  "maintenance": {
    "start_time": "23:00",
    "end_time": "03:00",
    "timezone": "Europe/Lisbon"
  }
}

Response

Monitor updated.

last_check_skippedstring

Populated only on POST /monitors when the create-time initial check did not produce a usable result — either short-circuited before any probe ran, or the probe started but did not finish within the create-time budget, leaving the first check pending. The state row's last_check_at remains null in either case; clients distinguish "no data yet" from "skipped on purpose" via this field.

Vocabulary:

  • domain_rate_limited — the per-domain dispatch cap (DomainLimiter) consumed the slot; the next scheduled tick will retry once the bucket refills.
  • initial_check_timeout — the create-time probe did not return within the server's bounded wait; the monitor is registered normally and the next scheduled tick resolves it.
recipient_idsinteger[]

Attached recipient ids (issue #212). Always present, [] for none. On POST /monitors, reflects any account default recipients attached inside the create transaction — though a monitor born down does not notify them at creation; see Recipient.default.

Example response

{
  "monitor": {
    "name": "Production API",
    "url": "https://api.example.com/health",
    "interval_sec": 60,
    "expected_status": "200",
    "maintenance": {
      "start_time": "23:00",
      "end_time": "03:00",
      "timezone": "Europe/Lisbon"
    }
  }
}

Changes

No recorded changes to this operation across all 1 revision of this API.