Bulk operations on monitors
Once you have more than a few monitors, change them together. Every bulk change - in the app or through the API - runs as a background job: it is accepted at once, applies to each monitor separately, and reports a result per monitor. One monitor that cannot be changed never blocks the others.
Select and act in the app
Section titled “Select and act in the app”- On Sites, tick the checkboxes of the monitors you want. Select all ticks the current page; click it again (Select all N) to select every monitor that matches your current filters, across pages.
- The bulk bar appears at the bottom. Choose an action:
| Action | What it does |
|---|---|
| Edit | Opens Edit N monitors (below). With exactly one monitor selected, opens that monitor’s own editor instead. |
| Report | Builds an uptime report for the selection. See Uptime reports. |
| Enable / Disable | Resumes or pauses every selected monitor. An all-enabled selection shows only Disable, an all-paused one only Enable, a mixed one both. |
| Reset Stats | Clears the uptime and state history of the selection (“This deletes the computed uptime and state history. Monitoring continues and starts with fresh statistics.”). |
| Delete | Deletes the selection after a confirmation that shows how many monitors the server will delete and a sample of them. |
The Edit N monitors panel
Section titled “The Edit N monitors panel”Every field starts at No change; only what you set is applied, and each monitor keeps everything else.
| Field | Values | Notes |
|---|---|---|
| Monitoring interval | No change or an interval | One interval for every selected monitor. Monitors whose type has a higher minimum are listed in a note. |
| Tags to add / Tags to remove | Tags | Adds or removes tags; each monitor keeps its other tags. |
| Full logging | No change / On / Off | On is disabled if your plan does not include Full Log. |
| Open statistics | No change / On / Off | The public statistics page. |
| Monitoring state | No change / Enabled / Paused | Pause or resume the selection. |
| Monitoring Locations and If selected locations are unavailable | Location tree; No change / Selected locations only / Closest locations / Any location | Shown only when the selection can share one location tree: any mix of web, API, ping and port monitors, or monitors of one browser type (Page speed, Transaction or Web content check). |
Click Update. The panel shows the job’s progress and then the per-monitor result; you can close it while the job runs.
Follow the job
Section titled “Follow the job”Running and finished jobs appear in the jobs indicator in the top bar and in the notification bell, whichever page you are on. A finished job shows how many monitors were updated, created disabled, skipped or failed, with the reason for each failure.
How a job ends
Section titled “How a job ends”Job state |
Meaning |
|---|---|
queued, running |
Still working. |
succeeded |
Every item was applied. |
partial |
Some items were applied and some failed. This is a normal outcome, not an error - read the per-item results. |
failed |
The job itself could not run, or every item failed. |
cancelled |
Stopped on request; items already applied stay applied. |
interrupted |
The server running it stopped; it keeps what it applied and can be resumed. |
Each item has a status: created, createdDisabled (created, but disabled because your plan’s monitor limit was
reached), updated, skipped, failed (with an error), deleted, cancelled (not run because the job stopped),
or pending.
Over your plan’s limit. The app always runs bulk jobs so that the batch continues past failures and anything
that would exceed your monitor limit lands disabled instead of failing: enabling 20 monitors with room for 15
enables 15 and leaves 5 disabled. The API does the same only when you ask for it (onOverlimit: "disable"); its
default is to fail those items.
Do it with the API or MCP
Section titled “Do it with the API or MCP”All bulk calls need scope monitor:write, answer 202 with a job id, and require an Idempotency-Key header, so a
retried request never starts a second job.
| Operation | Endpoint | Body |
|---|---|---|
| Preview a create batch | POST /monitor/bulk-validate |
Same as the create; nothing is written |
| Create many monitors | POST /monitor/bulk |
{ "defaults": {...}, "items": [ {...}, ... ] } |
| Preview which monitors an edit touches | POST /monitor/bulk-update-validate |
{ "ids": [...] } or { "filter": {...} }, plus patch |
| Edit (or reset statistics of) many monitors | POST /monitor/bulk-update |
{ "ids": [...] or "filter": {...}, "patch": {...}, "operation": "resetStats" } |
| Preview a delete | POST /monitor/bulk-delete-validate |
{ "filter": {...} } -> { matched, sample, truncated, max } |
| Delete many monitors | POST /monitor/bulk-delete |
{ "filter": {...}, "expectedCount": <matched> } |
| Reset one monitor’s statistics | POST /monitor/{id}/reset-stats |
none |
| Poll a job | GET /job/{id} |
- |
| List recent jobs | GET /job?kind=...&state=... |
- |
| Cancel / resume | POST /job/{id}/cancel, POST /job/{id}/resume |
- |
Pause every monitor tagged staging:
curl -X POST https://api2.host-tracker.com/monitor/bulk-update \ -H "Authorization: Bearer $HT_TOKEN" -H "Content-Type: application/json" \ -H "Idempotency-Key: pause-staging-2026-09-29" \ -d '{ "filter": { "tags": ["staging"] }, "patch": { "enabled": false } }'# 202 { "jobId": "...", "accepted": 12 } + Retry-After: seconds before the first poll
curl "https://api2.host-tracker.com/job/$JOB_ID" -H "Authorization: Bearer $HT_TOKEN"# { "state": "succeeded", "progress": { "done": 12, "total": 12 },# "summary": { "created": 0, "updated": 12, "skipped": 0, "failed": 0, "deleted": 0 },# "results": [ { "index": 0, "status": "updated", "entityId": "...", "result": { ...the monitor... } }, ... ],# "nextCursor": null, "hasMore": false }Targets. Name them with ids (a list of monitor ids) or a filter object - never both. The filter members are
monitorIds, types, tags (any of), states (up, down, paused, maintenance), enabled and q (text
search), combined with AND. A filter that narrows by nothing is refused (422 filter_required) rather than taken to
mean your whole account.
The patch is the same body as a single PATCH /monitor/{id}: interval, enabled, fullLog, openStat,
addTags / removeTags (or tags to replace), locations, recheck, settings, slaTarget…
Policy members (every bulk job):
| Member | Values | Default |
|---|---|---|
onError (alias continueOnError: true/false) |
continue, stop |
continue - one bad item costs one item |
onOverlimit |
fail, disable, stop |
fail - the item fails with package_limit; disable creates or leaves it disabled |
onDuplicate (create only) |
fail, skip, createAnyway |
fail - an item whose type and address already exist fails with duplicate_monitor |
callback |
{ "webhookId": "...", "on": "completed" or "progress" } |
none - calls your webhook with job.completed (and job.progress if asked) |
Deleting safely. Run bulk-delete-validate, show the matched count and sample to a person, then send the
same filter with expectedCount set to that count. If the selection changed in between, the delete is refused with
409 selection_mismatch - validate again.
Results. GET /job/{id} pages its results with limit and cursor; each item carries the full monitor as it
stands now (or the deletion receipt), or a problem document in error. A job is readable for 7 days
(expiresAt), then answers 404.
MCP. bulk_create_monitors, bulk_update_monitors and bulk_delete_monitors run the matching
validate call first and only submit on a second call (submit=true, or confirmed=true plus expectedCount for
the delete). Then wait_for_job (polls for up to about 30 seconds per call) or get_job, and
cancel_job / resume_job. Intervals in patchJson and defaultsJson are in seconds
({"interval":300} = 5 minutes).
Limits and gotchas
Section titled “Limits and gotchas”- Size. A create batch carries at most your plan’s monitor count, never more than 5000 items
(
GET /account->limits.maxBulkItems). An update or delete targets at most 2000 monitors (limits.maxBulkSelection). Larger requests are refused with422 too_many_items. - Mixed types. One patch goes to every monitor, so an interval below one type’s minimum fails for those
monitors (
interval_below_type_floor) while the rest are updated. Locations sent to types without a location picker (Database, SNMP, Counter, the expiry, DNSBL and Web Risk checks) fail for those monitors. - Cancel is not undo. Items processed before the cancel stay changed.
- A job whose state is
failedstill answers200onGET /job/{id}; checkstate, not the HTTP status.

