# Do anything in HostTracker: task map

This is the index to read first when you need to **do** something in a HostTracker account - by hand, from a
script, or as an AI assistant acting for a user. Each row names one task, where it lives in the app, the REST API v2
call (base URL `https://api2.host-tracker.com`, header `Authorization: Bearer <token>`), the scope the token needs,
and the MCP tool when one exists. Read the [safe operating rules](#safe-operating-rules) before any write.

How to read the tables:

- **API** is `METHOD /path`. `{id}` is the object's id as the API returned it. Every list that pages also answers
  `POST <same path>/q` with the parameters as a JSON body (same result, same scope) - useful for long id lists.
- **MCP** is the exact tool name on the HostTracker MCP server. A dash means there is no dedicated tool: an MCP
  client reaches that call through `api_request` (look it up with `describe_api` first). Writes under `/account` are
  refused by the MCP server whatever the token allows.
- **Scope** "none" means the call works without a token (reference data).
- The object behind each row is described in [How your account is organised](/reference/operator-object-model/).

## Monitors

| Task | In the app | API | Scope | MCP | Docs |
|---|---|---|---|---|---|
| List, search and filter monitors | **Sites** (`/sites`) | `GET /monitor` (`q`, `type`, `tag`, `state`, `enabled`, `url`, `sort`, `expand`) | `monitor:read` | `list_monitors` | [What a monitor is](/monitors/what-a-monitor-is/) |
| Read one monitor's full configuration | **Sites** -> open the monitor | `GET /monitor/{id}` | `monitor:read` | `get_monitor` | [Monitor fields by type](/reference/operator-monitor-fields/) |
| See the monitor types, their minimum interval and whether the plan includes them | **Sites** -> **Add monitor** -> **Monitoring Type** | `GET /monitor/type` | none (a token adds your limits) | `list_monitor_types` | [Monitor types](/monitors/monitor-types/) |
| Get one type's settings schema | - | `GET /monitor/type/{type}` | none | - | [Monitor fields by type](/reference/operator-monitor-fields/) |
| Get the combined settings schema for every type | - | `GET /monitor/type/schema` | none | - | [Monitor settings reference](/reference/monitor-settings/) |
| Create a monitor | **Sites** -> **Add monitor** -> **Save** | `POST /monitor` | `monitor:write` (+ `contact:write` when the body creates contacts) | `create_monitor` | [Quickstart](/getting-started/quickstart/) |
| Check a create without saving | - | `POST /monitor?dryRun=true` | `monitor:write` | `create_monitor` with `dryRun=true` | [Monitor fields by type](/reference/operator-monitor-fields/) |
| Change name, address, interval, settings, locations or tags | **Sites** -> open the monitor -> **Save** | `PATCH /monitor/{id}` | `monitor:write` | `update_monitor` | [Monitor fields by type](/reference/operator-monitor-fields/) |
| Add or remove tags without replacing the rest | **Sites** -> select -> **Edit** (**Tags to add** / remove) | `PATCH /monitor/{id}` with `addTags` / `removeTags` | `monitor:write` | `update_monitor` (`addTags`, `removeTags`) | [Tags](/monitors/tags/) |
| Pause a monitor | **Sites** -> row menu -> **Disable** | `PATCH /monitor/{id}` `{"enabled": false}` | `monitor:write` | `pause_monitor` | [Pause, enable and delete](/monitors/pause-enable-delete/) |
| Resume a monitor | **Sites** -> row menu -> **Enable** | `PATCH /monitor/{id}` `{"enabled": true}` | `monitor:write` | `resume_monitor` | [Pause, enable and delete](/monitors/pause-enable-delete/) |
| Delete a monitor | **Sites** -> row menu -> **Delete** | `DELETE /monitor/{id}` | `monitor:write` | `delete_monitor` | [Pause, enable and delete](/monitors/pause-enable-delete/) |
| Copy a monitor to other addresses | **Sites** -> row menu -> **Copy** | `POST /monitor/{id}/copy` | `monitor:write` | `copy_monitor` | [Copy a monitor](/monitors/copying/) |
| Add many monitors | **Sites** -> **Add monitor** -> **add list** | `POST /monitor/bulk-validate`, then `POST /monitor/bulk` (job) | `monitor:write` | `bulk_create_monitors` | [Importing a list of monitors](/monitors/importing/) |
| Edit many monitors | **Sites** -> select -> **Edit** | `POST /monitor/bulk-update-validate`, then `POST /monitor/bulk-update` (job) | `monitor:write` | `bulk_update_monitors` | [Bulk operations](/monitors/bulk-operations/) |
| Delete many monitors | **Sites** -> select -> **Delete** | `POST /monitor/bulk-delete-validate`, then `POST /monitor/bulk-delete` with `expectedCount` (job) | `monitor:write` | `bulk_delete_monitors` | [Bulk operations](/monitors/bulk-operations/) |
| Reset a monitor's uptime statistics | **Sites** -> row menu -> **Reset Stats** | `POST /monitor/{id}/reset-stats` (job) | `monitor:write` | `bulk_update_monitors` with `operation="resetStats"` | [Pause, enable and delete](/monitors/pause-enable-delete/) |
| Check a cron expression before saving | Monitor editor -> cron schedule | `POST /monitor/validate-cron` `{"cronSchedule": "..."}` | `monitor:read` | - | [Cron scheduling](/monitors/advanced/cron-scheduling/) |
| Look up the IPs an address resolves to | Monitor editor -> expected IPs -> resolve automatically | `POST /monitor/resolve` `{"url": "..."}` | `monitor:read` | - | [HTTP request configuration](/monitors/advanced/http-request-config/) |
| Read attached sub-check results (blacklists, certificate, domain, Web Risk) | Monitor statistics page | `GET /monitor/{id}/attached` | `monitor:read` | `get_monitor` with `expand="attached"` | [Attached sub-checks](/monitors/types/attached-sub-checks/) |
| Mute or unmute blacklist listings | Monitor editor -> **Blacklist status** -> **Mute** | `POST /monitor/{id}/attached/dnsbl/mute` `{"listings": [...], "muted": true}` | `monitor:write` | - | [DNSBL monitor](/monitors/types/dnsbl/) |

## Alerts and contacts

| Task | In the app | API | Scope | MCP | Docs |
|---|---|---|---|---|---|
| List contacts | **Alerts & Contacts** (`/contacts`) | `GET /contact` (`q`, `type`, `confirmed`, `id`) | `contact:read` | `list_contacts` | [What a contact is](/alerts/contacts/) |
| Read one contact | **Alerts & Contacts** -> the contact | `GET /contact/{id}` (`expand=subscription,group,template`) | `contact:read` | `get_contact` | [What a contact is](/alerts/contacts/) |
| See the contact types and what each supports | **+ Add contact** -> **Contact Type** | `GET /contact/type` | none | - | [Alert channel matrix](/reference/channel-matrix/) |
| Add a contact | **Alerts & Contacts** -> **+ Add contact** | `POST /contact` | `contact:write` | `create_contact` (see the caution below) | [Alert channels](/alerts/channels/) |
| Change a contact (name, address, language, alert delay, active hours, grouping) | Contact -> **Main Settings** -> **Save** | `PATCH /contact/{id}` | `contact:write` | `update_contact` | [Alert delays and escalation](/alerts/escalation/) |
| Delete a contact | **Alerts & Contacts** -> the contact's row | `DELETE /contact/{id}` | `contact:write` | `delete_contact` | [What a contact is](/alerts/contacts/) |
| Send the confirmation code again | Contact row -> resend | `POST /contact/{id}/confirmation` | `contact:write` | `send_contact_confirmation` | [What a contact is](/alerts/contacts/#confirmation---why-an-unconfirmed-contact-gets-nothing) |
| Confirm a contact with its code | Contact -> enter the code | `POST /contact/{id}/confirmation/verify` `{"code": "..."}` | `contact:write` | `confirm_contact` | [What a contact is](/alerts/contacts/) |
| Send a test alert | Contact -> **Send test** | `POST /contact/{id}/test` `{"alertType": "down"}` | `contact:write` | `test_contact` | [Test a contact](/alerts/test-a-contact/) |
| Create, update or delete many contacts | - | `POST /contact/bulk-validate`, then `POST /contact/bulk` (job) | `contact:write` | - | [What a contact is](/alerts/contacts/) |
| Delete every contact a filter selects | - | `POST /contact/bulk-delete-validate`, then `POST /contact/bulk-delete` with `expectedCount` (job) | `contact:write` | - | [What a contact is](/alerts/contacts/) |
| List contact groups | **Alerts & Contacts** -> **Groups** | `GET /contact/group` | `contact:read` | `list_contact_groups` | [Contact groups](/alerts/contact-groups/) |
| Read one contact group | **Groups** -> the group | `GET /contact/group/{id}` | `contact:read` | - | [Contact groups](/alerts/contact-groups/) |
| Create a contact group | **Groups** -> **Add group** | `POST /contact/group` | `contact:write` | `create_contact_group` | [Contact groups](/alerts/contact-groups/) |
| Rename a group or replace its members | **Groups** -> the group | `PATCH /contact/group/{id}` | `contact:write` | `update_contact_group` | [Contact groups](/alerts/contact-groups/) |
| Delete a contact group | **Groups** -> the group | `DELETE /contact/group/{id}` | `contact:write` | `delete_contact_group` | [Contact groups](/alerts/contact-groups/) |
| Set which groups one contact belongs to | Contact -> groups | `PUT /contact/{id}/group` `{"groups": [{"id": "..."}]}` | `contact:write` | - | [Contact groups](/alerts/contact-groups/) |
| See what was sent to whom | **Notifications** (`/notification`) | `GET /contact/notification`, `GET /contact/{id}/notification` | `contact:read` | - | [An alert arrived late](/troubleshooting/notification-late/) |
| Read one sent notification with its content | **Notifications** -> the row | `GET /contact/notification/{id}` | `contact:read` | - | [An alert arrived late](/troubleshooting/notification-late/) |
| Count deliveries per contact and day | **Notifications** | `GET /contact/notification/summary` | `contact:read` | - | [Alerts overview](/alerts/overview/) |
| Re-send a scheduled report for a past period | **Notifications** -> **Resend reports** | `POST /contact/notification/resend` `{"frequency": "monthly", "at": <unix>}` | `contact:write` | - | [Schedule report subscriptions](/reports/scheduling/) |

:::caution[MCP `create_contact` and confirmable contacts]
The API requires an `Idempotency-Key` header to create an `email`, `sms` or `voiceCall` contact (a retry would
send a second paid code), and the `create_contact` tool does not send one, so it is refused with
`400 idempotency_key_required` for those types. Until the tool is fixed, create them with
`api_request(method="POST", path="/contact", bodyJson="{...}", idempotencyKey="<unique value>")`.
:::

## Alert and report subscriptions

A subscription is the link between one monitor and one contact. Writes are available from both sides: the monitor
side needs `monitor:write`, the contact side `contact:write`.

| Task | In the app | API | Scope | MCP | Docs |
|---|---|---|---|---|---|
| See who a monitor alerts | Monitor editor -> **Alert Subscriptions** | `GET /monitor/{id}/alert`, one pair: `GET /monitor/{id}/alert/{contactId}` | `monitor:read` | `list_subscriptions` with `monitorId` | [Subscribe monitors to a contact](/alerts/subscribe-monitors/) |
| See which monitors alert a contact | **Alerts & Contacts** -> **Subscriptions** on the contact's row | `GET /contact/{id}/alert`, one pair: `GET /contact/{id}/alert/{monitorId}` | `contact:read` | `list_subscriptions` with `contactId` | [Subscribe monitors to a contact](/alerts/subscribe-monitors/) |
| List every alert subscription on the account | - | `GET /alert`, `GET /alert/by-monitor`, `GET /alert/by-contact`, one row: `GET /alert/{id}` | `subs:read` | `list_subscriptions` | [Subscriptions](/alerts/subscriptions/) |
| See the alert types | - | `GET /alert/type` | none | - | [Subscriptions](/alerts/subscriptions/) |
| Subscribe a contact to a monitor's alerts | Contact -> **Alert Subscriptions** grid (**Down**, **Up**, **Repeat**) | `PUT /monitor/{id}/alert/{contactId}` `{"alertTypes": ["down","up"]}` or `PUT /contact/{id}/alert/{monitorId}` | `monitor:write` / `contact:write` | `subscribe_contact` with `alertTypes` | [Subscribe monitors to a contact](/alerts/subscribe-monitors/) |
| Stop one contact's alerts from one monitor | Clear the toggles in the grid | `DELETE /monitor/{id}/alert/{contactId}` or `DELETE /contact/{id}/alert/{monitorId}` | `monitor:write` / `contact:write` | `unsubscribe_contact` with `kind="alert"` | [Subscribe monitors to a contact](/alerts/subscribe-monitors/) |
| Remove all of a monitor's (or a contact's) alert subscriptions | - | `DELETE /monitor/{id}/alert` or `DELETE /contact/{id}/alert` | `monitor:write` / `contact:write` | - | [Subscriptions](/alerts/subscriptions/) |
| Add or remove many alert subscriptions at once | **Groups** -> **Apply to monitors** | `POST /alert/bulk` `{"create": [...], "delete": [...]}` | `monitor:write` and `contact:write` | `api_request` with `confirmed=true` (or `subscribe_contact` per pair) | [Contact groups](/alerts/contact-groups/) |
| See a monitor's report recipients | Monitor editor -> **Reports** | `GET /monitor/{id}/report`, one pair: `GET /monitor/{id}/report/{contactId}` | `monitor:read` | `list_subscriptions` with `kind="report"` | [Schedule report subscriptions](/reports/scheduling/) |
| See the reports a contact receives | Contact -> report subscriptions | `GET /contact/{id}/report`, one pair: `GET /contact/{id}/report/{monitorId}` | `contact:read` | `list_subscriptions` with `kind="report"` | [Schedule report subscriptions](/reports/scheduling/) |
| List every report subscription on the account | - | `GET /report`, `GET /report/by-monitor`, `GET /report/by-contact`, one row: `GET /report/{id}` | `subs:read` | `list_subscriptions` with `kind="report"` | [Schedule report subscriptions](/reports/scheduling/) |
| Send a monitor's scheduled report to an email contact | Monitor editor -> **Reports** | `PUT /monitor/{id}/report/{contactId}` `{"frequencies": ["weekly"]}` or `PUT /contact/{id}/report/{monitorId}` | `monitor:write` / `contact:write` | `subscribe_contact` with `frequencies` | [Schedule report subscriptions](/reports/scheduling/) |
| Stop a scheduled report | Monitor editor -> **Reports** | `DELETE /monitor/{id}/report/{contactId}` or `DELETE /contact/{id}/report/{monitorId}` | `monitor:write` / `contact:write` | `unsubscribe_contact` with `kind="report"` | [Schedule report subscriptions](/reports/scheduling/) |
| Remove all of a monitor's (or a contact's) report subscriptions | - | `DELETE /monitor/{id}/report` or `DELETE /contact/{id}/report` | `monitor:write` / `contact:write` | - | [Schedule report subscriptions](/reports/scheduling/) |
| Add or remove many report subscriptions at once | - | `POST /report/bulk` | `monitor:write` and `contact:write` | `api_request` with `confirmed=true` (or `subscribe_contact` per pair) | [Schedule report subscriptions](/reports/scheduling/) |

## Maintenance windows

| Task | In the app | API | Scope | MCP | Docs |
|---|---|---|---|---|---|
| List maintenance windows | **Maintenance** (`/maintenance`) | `GET /maintenance` (`state`, `monitor`, `from`, `to`) | `monitor:read` | `list_maintenance` | [What a maintenance window is](/maintenance/overview/) |
| Read one window | **Maintenance** -> the window | `GET /maintenance/{id}` | `monitor:read` | - | [Create a maintenance window](/maintenance/create/) |
| See the windows covering one monitor | - | `GET /monitor/{id}/maintenance` | `monitor:read` | `get_monitor` with `expand="maintenance"` | [What a maintenance window is](/maintenance/overview/) |
| Schedule a window (one-off or weekly) | **Maintenance** -> **Add** | `POST /maintenance` | `monitor:write` | `create_maintenance` | [Create a maintenance window](/maintenance/create/), [Recurring windows](/maintenance/recurring/) |
| Silence every monitor with a tag | - (pick the monitors in the form) | `GET /monitor?tag=T` for the ids, then `POST /maintenance` with those `monitorIds` (there is no tag selector) | `monitor:read`, `monitor:write` | `list_monitors(tag="T")`, then `create_maintenance` | [Create a maintenance window](/maintenance/create/#cover-every-monitor-with-a-tag) |
| Reschedule, change coverage, switch off without deleting | **Maintenance** -> the window | `PATCH /maintenance/{id}` | `monitor:write` | `update_maintenance` | [Create a maintenance window](/maintenance/create/) |
| Cancel a window | **Maintenance** -> the window | `DELETE /maintenance/{id}` | `monitor:write` | `delete_maintenance` | [What it suppresses](/maintenance/what-it-suppresses/) |

## Status pages

| Task | In the app | API | Scope | MCP | Docs |
|---|---|---|---|---|---|
| List status pages | **Status pages** (`/status-pages`) | `GET /statuspage` | `statuspage:read` | `list_status_pages` | [Status pages overview](/status-pages/overview/) |
| Read one page with its settings and components | **Status pages** -> **Edit** | `GET /statuspage/{id}` | `statuspage:read` | `get_status_page` | [Status pages overview](/status-pages/overview/) |
| Create a page | **Status pages** -> **Create status page** | `POST /statuspage` | `statuspage:write` | `create_status_page` | [Create a status page](/status-pages/create/) |
| Change title, branding, layout or behaviour | Editor -> **Appearance** / **Settings** tabs | `PATCH /statuspage/{id}` | `statuspage:write` | `update_status_page` | [Branding](/status-pages/branding/) |
| Replace the page's components | Editor -> **Monitors** tab | `PUT /statuspage/{id}/component` | `statuspage:write` | - (`create_status_page` sets them at creation only) | [Components](/status-pages/components/) |
| Delete a page | **Status pages** | `DELETE /statuspage/{id}` | `statuspage:write` | `delete_status_page` | [Status pages overview](/status-pages/overview/) |
| List or read declared incidents | Editor -> **Announcements** | `GET /statuspage/{id}/incident`, `GET /statuspage/{id}/incident/{incidentId}` | `statuspage:read` | - | [Announcements](/status-pages/announcements/) |
| Declare an incident or scheduled maintenance | **Announcements** -> **New announcement** -> **Post** | `POST /statuspage/{id}/incident` | `statuspage:write` | `create_status_page_incident` | [Announcements](/status-pages/announcements/) |
| Post an update or resolve | Announcement card -> **Post update** / **Resolve** | `POST /statuspage/{id}/incident/{incidentId}/timeline` | `statuspage:write` | `add_status_page_incident_update` | [Announcements](/status-pages/announcements/#post-updates-and-resolve) |
| Fix title, type, components or window; set a postmortem | Announcement card -> **Edit** / **Add postmortem** | `PATCH /statuspage/{id}/incident/{incidentId}` | `statuspage:write` | - | [Announcements](/status-pages/announcements/) |
| Delete an announcement | Announcement card -> **Delete** | `DELETE /statuspage/{id}/incident/{incidentId}` | `statuspage:write` | - | [Announcements](/status-pages/announcements/) |
| List, save or delete announcement templates | **Use a template** / **Manage** | `GET` / `POST /statuspage/{id}/template`, `DELETE /statuspage/{id}/template/{templateId}` | `statuspage:read` / `statuspage:write` | - | [Announcements](/status-pages/announcements/#templates) |
| List subscribers | **Subscribers** panel | `GET /statuspage/{id}/subscriber` | `statuspage:read` | - | [Subscribers](/status-pages/subscribers/) |
| Add a Slack, Teams or webhook subscriber | **Subscribers** panel | `POST /statuspage/{id}/subscriber` `{"kind": "slack", "url": "..."}` | `statuspage:write` | - | [Subscribers](/status-pages/subscribers/) |
| Remove a subscriber | **Subscribers** panel -> **Remove** | `DELETE /statuspage/{id}/subscriber/{subscriberId}` | `statuspage:write` | - | [Subscribers](/status-pages/subscribers/) |

## Incidents, results and reports

| Task | In the app | API | Scope | MCP | Docs |
|---|---|---|---|---|---|
| Uptime, SLA and response time over a window | **Uptime reports** (`/sites/uptime`); monitor statistics page | `GET /monitor/result/summary` | `monitor:read` | `get_uptime_summary` | [Build reports and summaries](/reference/operator-reports-and-summaries/) |
| Uptime of every monitor for a window | **Sites** | `GET /monitor?expand=uptime&from=...&to=...` | `monitor:read` | `get_monitor` (one monitor, `expand` includes `uptime`) | [Build reports and summaries](/reference/operator-reports-and-summaries/) |
| List incidents (down episodes) | **Uptime reports** -> **Incidents**; statistics -> **Latest incidents** | `GET /monitor/incident`, `GET /monitor/{id}/incident` | `monitor:read` | `list_incidents` | [What is an incident](/incidents/what-is-an-incident/) |
| Read one incident with its timeline | Statistics -> the outage | `GET /monitor/incident/{id}` | `monitor:read` | `get_incident` | [What is an incident](/incidents/what-is-an-incident/) |
| List the failing checks inside an incident | Statistics -> the outage | `GET /monitor/incident/{id}/check` | `monitor:read` | - | [Reading results](/incidents/reading-results/) |
| Write a note on an incident | Outage panel -> **Note** | `POST /monitor/incident/{id}/comment` `{"comment": "..."}` | `monitor:write` | `comment_incident` | [What is an incident](/incidents/what-is-an-incident/#add-a-comment) |
| Up/down timeline of a monitor | Statistics page bars | `GET /monitor/{id}/span` | `monitor:read` | `get_monitor` with `expand="spans"` | [Reading results](/incidents/reading-results/) |
| Raw check results of one monitor | Statistics -> **Recent checks** | `GET /monitor/{id}/result` | `monitor:read` | `list_monitor_results` | [Reading results](/incidents/reading-results/) |
| Raw check results across monitors | - | `GET /monitor/result` | `monitor:read` | - | [Reading results](/incidents/reading-results/) |
| One check result in full | Recent checks -> the row | `GET /monitor/{id}/result/{resultId}` | `monitor:read` | - | [Reading results](/incidents/reading-results/) |
| Download a check's page snapshot | Outage panel -> **Snapshot** | `GET /monitor/{id}/result/{resultId}/snapshot` | `monitor:read` | - | [Page snapshots](/incidents/snapshots/) |
| See the report types, formats and sections | - | `GET /report/type` | none | `list_report_types` | [Uptime reports](/reports/uptime-reports/) |
| Generate an uptime report document | **Sites** -> select -> **Report**; **Uptime reports** | `POST /monitor/report` (job) | `monitor:write` | `generate_report` | [Uptime reports](/reports/uptime-reports/) |
| Read a generated report's details | - | `GET /monitor/report/{id}` | `monitor:read` | - | [Build reports and summaries](/reference/operator-reports-and-summaries/) |
| Download a generated report | - | `GET /monitor/report/{id}/content` | `monitor:read` | - | [Build reports and summaries](/reference/operator-reports-and-summaries/) |

## Account, quota and locations

| Task | In the app | API | Scope | MCP | Docs |
|---|---|---|---|---|---|
| Read plan, usage, limits and allowed intervals | **Billing** (`/billing`), **Profile** | `GET /account` | `account:read` | `get_account` | [Quotas and limits](/account/quotas/) |
| Read usage against the plan | **Billing** | `GET /account/usage` | `account:read` | `get_account_usage` | [Quotas and limits](/account/quotas/) |
| Read API quota headroom and the token's scopes | **Integrations -> API** | `GET /account/quota` | `account:read` | `get_account_quota` | [Rate limits and quotas](/integrations/rate-limits/) |
| List shared-access members | **Shared access** (`/access`) | `GET /account/member` | `account:read` | - | [Subaccounts](/account/subaccounts/) |
| Change profile, time zone, language, default locations | **Profile** (`/profile`) | `PATCH /account` | `account:write` | - (refused by the MCP server) | [Account settings](/account/settings/) |
| Invite or remove a teammate | **Shared access** -> **Invite** | - (app only) | - | - | [Subaccounts](/account/subaccounts/) |
| Create or revoke an API token | **Integrations -> API** (`/integrations/api`) | - (app only) | - | - | [API authentication](/integrations/api-authentication/) |
| Change plan or pay | **Billing**, **Upgrade plan** | - (app only) | - | - | [Upgrade or downgrade](/account/upgrade-downgrade/) |
| List location pools | **Our network** (`/agent/list`) | `GET /agent/pool` | none | `list_locations` | [Monitoring locations reference](/reference/locations/) |
| List individual monitoring locations | **Our network** | `GET /agent` | none | `list_locations` with `agents=true` | [Monitoring locations reference](/reference/locations/) |
| List the IP addresses checks come from (for firewall allow lists) | **Our network** | `GET /agent/ip` | none | - | [Monitoring locations reference](/reference/locations/) |

## Webhooks

There is no webhook page in the app; webhooks are managed through the API, SDKs, CLI, Terraform or MCP.

| Task | API | Scope | MCP | Docs |
|---|---|---|---|---|
| List webhooks | `GET /webhook` | `webhook:read` | `list_webhooks` | [Webhooks](/integrations/webhooks/) |
| Read one webhook | `GET /webhook/{id}` | `webhook:read` | - | [Webhooks](/integrations/webhooks/) |
| Register a webhook | `POST /webhook` `{"url", "events", "scope"}` | `webhook:write` | `create_webhook` | [Webhooks](/integrations/webhooks/#create-a-webhook) |
| Change url, events, scope, headers, name, or enable/disable | `PATCH /webhook/{id}` | `webhook:write` | `update_webhook` | [Webhooks](/integrations/webhooks/) |
| Delete a webhook | `DELETE /webhook/{id}` | `webhook:write` | `delete_webhook` | [Webhooks](/integrations/webhooks/) |
| Send a test delivery | `POST /webhook/{id}/test` | `webhook:write` | `test_webhook` | [Webhooks](/integrations/webhooks/) |
| See recent deliveries and their outcome | `GET /webhook/{id}/delivery` | `webhook:read` | `list_webhook_deliveries` | [Webhooks](/integrations/webhooks/#delivery-log-and-redelivery) |
| Send a recorded delivery again | `POST /webhook/{id}/delivery/{deliveryId}/redeliver` | `webhook:write` | `redeliver_webhook` | [Webhooks](/integrations/webhooks/#delivery-log-and-redelivery) |

## Jobs

| Task | In the app | API | Scope | MCP | Docs |
|---|---|---|---|---|---|
| Poll a job | Progress shown after a bulk action | `GET /job/{id}` | the scope of the call that created it | `get_job`, `wait_for_job` | [Asynchronous jobs](/integrations/rest-api/#asynchronous-jobs) |
| List recent jobs | - | `GET /job` (`state`, `kind`) | the scope of each job | - | [Asynchronous jobs](/integrations/rest-api/#asynchronous-jobs) |
| Cancel a running job | - | `POST /job/{id}/cancel` | the scope of the job | `cancel_job` | [Bulk operations](/monitors/bulk-operations/) |
| Continue an interrupted job | - | `POST /job/{id}/resume` | the scope of the job | `resume_job` | [Bulk operations](/monitors/bulk-operations/) |

## Instant checks

| Task | In the app | API | Scope | MCP | Docs |
|---|---|---|---|---|---|
| Run a one-off check | **Instant checks** (`/ic/check-http`) | `POST /check` `{"url", "type", "pools"}` | `check:write` | `run_instant_check` | [Instant checks vs monitors](/getting-started/instant-checks-vs-monitors/) |
| Read an instant check's results | The result page | `GET /check/{dbId}/{id}` | `check:read` | `get_check_result` | [Instant checks vs monitors](/getting-started/instant-checks-vs-monitors/) |
| List past instant checks | - | `GET /check` | `check:read` | - | [Instant checks vs monitors](/getting-started/instant-checks-vs-monitors/) |
| See instant-check types and device profiles | **Instant checks** | `GET /check/type`, `GET /check/device` | none | `list_check_types` | [Instant checks vs monitors](/getting-started/instant-checks-vs-monitors/) |

## The MCP server's generic doors

| Tool | What it is for |
|---|---|
| `describe_api` | Search the v2 operations by path or name (`describe_api("statuspage")`) and see their parameters and body members. Call it before `api_request`. |
| `api_request` | Call any v2 operation no curated tool covers (every "-" above). The method and path must match a real operation. Without `confirmed=true` it refuses, and sends nothing, for every `DELETE` and for every `POST`/`PATCH`/`PUT` whose path contains `/bulk` - that is `POST /alert/bulk`, `POST /report/bulk`, all the monitor and contact bulk doors, and their `...-validate` dry runs too (no v2 path ends in `/validate`). All other calls need no flag. It sends an `Idempotency-Key` only when you pass `idempotencyKey`. Writes under `/account` are always refused. Full rule: [The api_request confirmation rule](/integrations/mcp/#the-api_request-confirmation-rule). |

See [Connect an AI assistant with the MCP server](/integrations/mcp/).

## Opt-in operations

A few operations exist only for accounts where the site-crawl feature is switched on, and are left out of the
published API reference: the crawl run history (`GET /monitor/{id}/crawl`, `GET /monitor/{id}/crawl/page`,
`GET /monitor/{id}/crawl/{runAt}`), **run now** for a crawl monitor (`POST /monitor/{id}/run`) and its run hook
(`POST` / `GET` / `DELETE /monitor/{id}/hook`, and the hook url itself, `POST /hook/run/{token}`). A call on an
account without the feature is refused.

## Safe operating rules

Follow these whenever you change something in a user's account.

1. **Confirm destructive and public actions with the user first.** Deleting a monitor, contact, contact group,
   maintenance window, status page, announcement or webhook cannot be undone. So is a bulk delete, and removing a
   subscription silences alerts. Cancelling an **active** maintenance window makes its monitors alert again at once.
   Declaring an incident or posting an update on a status page is **public** and notifies its subscribers - agree
   the exact wording first. `test_contact` and `send_contact_confirmation` message a real person, and SMS or voice
   can cost account balance. The MCP delete tools answer with a preview first and act only when called again with
   `confirmed=true`; `bulk_delete_monitors` also needs the `expectedCount` its own validation reported.
2. **Validate before a bulk write.** Run the matching `bulk-validate`, `bulk-update-validate` or
   `bulk-delete-validate` call, show the user the count and sample it returns, then submit. A bulk delete must send
   the validated number as `expectedCount`; if the selection changed in between it is refused with
   `409 selection_mismatch`.
3. **Send an `Idempotency-Key` on creates and bulk writes.** Every write reads the header, and a repeat with the same
   key and body replays the first answer (`Idempotency-Replayed: true`) instead of acting twice. It is **required**
   by `POST /monitor/bulk`, `/monitor/bulk-update`, `/monitor/bulk-delete`, `/monitor/{id}/reset-stats`,
   `/contact/bulk`, `/contact/bulk-delete`, `/monitor/report`, `/statuspage/{id}/incident`,
   `/statuspage/{id}/incident/{incidentId}/timeline`, by `POST /monitor/{id}/copy` for more than 10 addresses, by
   `POST /monitor` when the body creates contacts, and by `POST /contact` for email, SMS and voice contacts. Use a
   fresh unique value per operation and reuse it only to retry that same operation; keys are remembered for 24
   hours. See [Idempotency-Key](/integrations/rest-api/#idempotency-key).
4. **Bulk writes are jobs.** They answer `202` with a `jobId` and a `Retry-After`. Poll `GET /job/{id}` (MCP
   `get_job` or `wait_for_job`) until the state is `succeeded`, `partial`, `failed` or `cancelled`; `partial` is a
   normal outcome - read the per-item results and report which items failed and why. A failed job still answers
   `200`, so check `state`, not the HTTP status. `POST /alert/bulk` and `POST /report/bulk` are the exception: they
   run in one transaction and answer directly.
5. **Timestamps are Unix seconds.** `from`, `to`, `at` and every `...At` value are seconds since 1970, never
   milliseconds or ISO strings. A millisecond value is refused as out of range.
6. **Intervals are seconds.** `interval` is how often a monitor runs, in **seconds** (`300` is five minutes), and
   must be one of the account's allowed values (`GET /account` -> `limits.intervals`) and at least the type's
   minimum (`GET /monitor/type` -> `minInterval`). The MCP tools `create_monitor`, `update_monitor` and the bulk
   tools describe `interval` as minutes, but pass the number to the API unchanged - so send seconds to them too. An
   alert delay on a contact (`alertDelay`) is the one duration in **minutes**.
7. **Monitors created through the API or MCP alert nobody.** Unlike the app, `POST /monitor` and `create_monitor`
   add no subscriptions. Add them in the same request (`alertSubscriptions`, `reportSubscriptions`) or right after
   with `subscribe_contact` / `PUT /monitor/{id}/alert/{contactId}`, and tell the user which contacts will be
   alerted.
8. **Send locations for location-based types.** `http`, `api`, `ping`, `port`, `waterfall` (Page speed), `cntCheck`
   and `tran` need `locations.pools` on create - `["allworld"]` for everywhere, or pool ids from `GET /agent/pool`.
   The API does not apply the account's default locations. Common ids: `westeurope`, `easteurope`, `northamerica`
   (the app's default set), `southamerica`, `asia`, `australia`, `africa`; there is no `europe` pool - see
   [Common pool ids](/reference/locations/#common-pool-ids). The other types are placed by HostTracker itself (SSL
   expiry on the public fleet, the rest on its internal network) and refuse `locations`.
9. **Contacts must be confirmed.** A new email, SMS or voice contact receives nothing until it is confirmed with the
   code sent to it. The code is never returned to the API caller - ask the user to read it to you, then call
   `POST /contact/{id}/confirmation/verify` (`confirm_contact`).
10. **Change only what you mean to.** `PATCH` leaves omitted members alone, but a list you send replaces the stored
    list: `tags` (use `addTags` / `removeTags` instead), a transaction's `steps`, a maintenance window's
    `monitorIds` / `monitors`, a contact group's `items`, a status page's `features`, and the component set of
    `PUT /statuspage/{id}/component`. Read the object first, change the copy, send back what changed.
11. **After a `403`, check the token.** `GET /account/quota` (`get_account_quota`) lists the scopes the token
    carries. An MCP client connected with OAuth has no `account` scopes at all, so the account tools answer `403`
    there; by default an OAuth connection holds only `check` and `monitor:read`.
12. **Read the error body.** Refusals are `application/problem+json` with a `code`, a `pointer` to the member at
    fault and often `allowed[]` - fix the request from those rather than guessing. See
    [Error codes reference](/reference/error-codes/).
13. **MCP arguments are flat.** A tool's list arguments are comma-separated strings (`alertTypes="down,up"`,
    `componentIds="C1,C2"`, `events="monitor.down,monitor.up"`), and arguments ending in `Json` take a JSON document
    as a string (`itemsJson`, `settingsJson`, `filterJson`). A tool has no argument the REST body has unless it is
    listed - `create_contact_group` has no `items`, `create_webhook` has no `scope` (use `tags` or `monitorIds`).
    Every tool's exact arguments: [The tools](/integrations/mcp/#the-tools).
14. **Maintenance windows and contact groups are snapshots.** A window covers the monitor ids you send (no tag
    selector), and applying a group writes ordinary subscriptions once. Neither follows later changes on its own.

## Related

- [How your account is organised](/reference/operator-object-model/)
- [Monitor fields by type](/reference/operator-monitor-fields/)
- [Build reports and summaries](/reference/operator-reports-and-summaries/)
- [REST API v2](/integrations/rest-api/)
