# How your account is organised

This page describes every object your HostTracker account holds, how the objects point at each other, and which
API call reads each one. Read it before you automate anything: most "why did nothing happen" questions come from a
missing link between two objects (a monitor with no subscription, a contact that was never confirmed).

## The objects at a glance

```mermaid
flowchart LR
    ACC[Account] --> MON[Monitor]
    ACC --> CON[Contact]
    ACC --> GRP[Contact group]
    ACC --> MW[Maintenance window]
    ACC --> SP[Status page]
    ACC --> WH[Webhook]
    ACC --> TOK[API token]
    ACC --> MEM[Shared-access member]
    MON --> ATT[Attached sub-check]
    MON --> RES[Check result]
    MON --> INC[Incident / down span]
    MON -- alert subscription --- CON
    MON -- report subscription --- CON
    GRP -. preset of .-> CON
    MW -- covers --> MON
    SP --> CMP[Component]
    CMP -- shows --> MON
    SP --> SPI[Status page incident]
    SPI --> UPD[Timeline entry]
    SP --> SUB[Subscriber]
    SP --> TPL[Template]
    CON --> NOT[Notification]
    WH --> DEL[Delivery]
    ACC --> JOB[Job]
    JOB -. produces .-> REP[Generated report]
```

## Rules that hold for every object

- **Ids are opaque.** Most are GUIDs; results, incidents, notifications, subscriptions and generated reports use
  prefixed string ids (`res_...`, `inc_...`, `alt_...`, `als_...`, `rsub_...`, `rep_...`). Pass them back exactly as
  you received them; never build or parse one.
- **Everything is private to the account.** An id that belongs to another account answers `404 not_found`, the same
  as an id that does not exist.
- **Timestamps are Unix seconds** on every read and write. Intervals and durations are also in **seconds**, except
  the alert delay on a contact, which is in **minutes**.
- **Scopes.** Every API call needs one scope (for example `monitor:read`). See
  [API authentication, tokens and scopes](/integrations/api-authentication/).
- **Deletes are permanent.** The API answers a delete with a receipt of what was removed (`cascaded` counts). There
  is no trash or undo.

## Account and shared access

**What it is.** Your HostTracker account: login, profile, time zone, language, plan (package), usage against the
plan's limits, and the default monitoring locations new monitors start with. Teammates get **shared access**
(subaccounts) with a set of rights instead of your password.

- **Id:** the account id (`GET /account` -> `id`). A shared-access member is identified by the contact it was granted
  to.
- **Links:** owns every other object on this page. A member's rights are tokens such as `monitor:write`,
  `contact:read`, `billing:read`, `profile:write`, `api:access`, `member:write`, `statusPage:read`.
- **Read:** `GET /account` (identity, plan, usage, limits including the allowed check intervals, flags),
  `GET /account/usage`, `GET /account/quota` (API quota and the scopes your token carries),
  `GET /account/member` (shared-access members). Scope `account:read`. MCP: `get_account`, `get_account_usage`,
  `get_account_quota`.
- **Lifecycle:** the account is created by signing up. `PATCH /account` (scope `account:write`) changes name,
  company, phone, country, time zone, language and default locations. Members are invited and removed in the app
  under **Shared access** (`/access`); there is no API for that. Plan changes and payments are app-only.

See [Account and billing overview](/account/overview/) and [Invite teammates with subaccounts](/account/subaccounts/).

## API token

**What it is.** A bearer token that lets a script, SDK, CLI or AI assistant act on the account with a chosen set of
scopes, an expiry and an optional IP allow list. An MCP client can instead connect with OAuth, which issues
short-lived tokens behind the scenes.

- **Id:** none you can read through the API. The token value is shown once, when you create it.
- **Links:** belongs to the account; its scopes decide which of the calls on this page it may make.
- **Read:** `GET /account/quota` lists the scopes the calling token carries.
- **Lifecycle:** created and deleted in the app at **Integrations -> API** (`/integrations/api`); OAuth connections
  are revoked under **Connected apps** on the same page. Tokens cannot be created through the API. OAuth
  connections are never granted the `account` scope family.

## Monitor

**What it is.** One recurring check of one target: a type (`http`, `ping`, `port`, `api`, `waterfall`, `cntCheck`,
`tran`, `dnsbl`, `domainExp`, `sslExp`, `webRisk`, `counter`, `database`, `snmp`), a url or host, a schedule
(`interval` in seconds or a `cronSchedule`), locations, type-specific `settings`, tags, and a state (`up`, `down`,
`paused`, `maintenance`).

- **Id:** GUID.
- **Links:** has attached sub-checks, check results, incidents and state spans; is linked to contacts by alert and
  report subscriptions; can be covered by maintenance windows; can appear as a component on status pages; can be in
  a webhook's scope.
- **Read:** `GET /monitor` (list, filter by `type`, `tag`, `state`, `q`, `url`, `enabled`...), `GET /monitor/{id}`
  (full configuration). Add `expand=` for related data: `settings`, `subscription`, `lastResult`, `lastIncident`,
  `uptime`, `spans`, `maintenance`, `attached`. Scope `monitor:read`. MCP: `list_monitors`, `get_monitor`.
- **Lifecycle:** create `POST /monitor`; change `PATCH /monitor/{id}`; pause or resume `PATCH` with
  `"enabled": false|true`; delete `DELETE /monitor/{id}` (removes its alert, report and maintenance
  subscriptions); copy `POST /monitor/{id}/copy`; many at once through the bulk jobs. The `type` cannot be changed
  after creation. Scope `monitor:write`.

Field-by-field detail: [Monitor fields by type](/reference/operator-monitor-fields/). Concepts:
[What a monitor is](/monitors/what-a-monitor-is/).

:::caution[A monitor created through the API alerts nobody]
A monitor created in the app is subscribed to your contacts by default. A monitor created with `POST /monitor`,
`create_monitor` or a bulk job has **no subscriptions** unless the request adds them (`alertSubscriptions`,
`reportSubscriptions`) or you add them afterwards. Location-based types also need `locations.pools` in the create
request.
:::

## Attached sub-check

**What it is.** A blacklist (DNSBL), certificate expiry, domain expiry or Web Risk check that rides on a parent
monitor instead of being a monitor of its own. Website/HTTPS monitors take all four; Ping and Port monitors take
DNSBL only.

- **Id:** none of its own - it is addressed through the parent monitor.
- **Links:** belongs to one monitor; its alerts go to that monitor's subscribed contacts.
- **Read:** `GET /monitor/{id}/attached` (current result per kind), or `expand=attached` on a monitor read. MCP:
  `get_monitor` with `expand="attached"`.
- **Lifecycle:** switched on and off with the monitor's `attached` member (`{"attached": {"sslExp": true}}`) on
  create or `PATCH /monitor/{id}`. Blacklist zones can be muted with `POST /monitor/{id}/attached/dnsbl/mute`.
  Removed with the parent.

See [Attach sub-checks to a monitor](/monitors/types/attached-sub-checks/).

## Contact

**What it is.** A destination for alerts and reports: an email address, a phone number for SMS or voice calls, a
messenger chat (Telegram, Viber, Discord and others), a browser for web push, or an HTTP endpoint (the webhook
alert contact used for Slack, Teams, PagerDuty and similar). It carries a language, an alert delay, active hours and
grouping options.

- **Id:** GUID.
- **Links:** linked to monitors by alert and report subscriptions; can be a member of contact groups; receives
  notifications.
- **Read:** `GET /contact`, `GET /contact/{id}` (`expand=subscription`, `group`, `template`),
  `GET /contact/type` (the types and what each can do). Scope `contact:read`. MCP: `list_contacts`, `get_contact`.
- **Lifecycle:** create `POST /contact` (email, sms, voiceCall, http and webPush through the API; messenger
  contacts are created by connecting the messenger bot in the app). Email, SMS and voice contacts start
  **unconfirmed** and receive nothing until confirmed with the code they were sent
  (`POST /contact/{id}/confirmation/verify`; resend with `POST /contact/{id}/confirmation`). Change with
  `PATCH /contact/{id}` (a new address needs confirming again), test with `POST /contact/{id}/test`, delete with
  `DELETE /contact/{id}` (removes all its subscriptions). Scope `contact:write`.

See [What a contact is](/alerts/contacts/).

## Contact group

**What it is.** A named set of contacts, each with the events it should get (`up`, `down`, `repeatedlyDown`,
`daily`, `weekly`, `monthly`, `quarterly`, `yearly`). A group is a **preset**: applying it to monitors writes
ordinary subscriptions once. It keeps no live link to those monitors and subscribes nobody by itself.

- **Id:** GUID.
- **Links:** lists contacts; nothing points back at it after it has been applied.
- **Read:** `GET /contact/group`, `GET /contact/group/{id}`. Scope `contact:read`. MCP: `list_contact_groups`.
- **Lifecycle:** `POST /contact/group`, `PATCH /contact/group/{id}` (a new member list replaces the whole set),
  `DELETE /contact/group/{id}` (contacts stay). A contact's own memberships: `PUT /contact/{id}/group`.

See [Group contacts and subscribe them together](/alerts/contact-groups/).

## Alert subscription

**What it is.** The link that makes a monitor alert a contact: one (monitor, contact) pair plus the set of alert
types it carries - `down`, `up`, `repeatedlyDown` (still-down reminders).

- **Id:** the pair itself (`/monitor/{monitorId}/alert/{contactId}`). The flat account-wide list also gives each
  pair an `als_...` id.
- **Links:** one monitor, one contact.
- **Read:** per monitor `GET /monitor/{id}/alert` (scope `monitor:read`), per contact `GET /contact/{id}/alert`
  (`contact:read`), whole account `GET /alert`, `/alert/by-monitor`, `/alert/by-contact` (`subs:read`). MCP:
  `list_subscriptions`.
- **Lifecycle:** set a pair with `PUT /monitor/{monitorId}/alert/{contactId}` `{"alertTypes": ["down","up"]}` - the
  set replaces the previous one. Remove with `DELETE` on the same path, or all of a monitor's with
  `DELETE /monitor/{id}/alert`. Many pairs in one transaction: `POST /alert/bulk`. MCP: `subscribe_contact`,
  `unsubscribe_contact`.

## Report subscription

**What it is.** The link that sends a contact a scheduled uptime report about a monitor: one (monitor, contact) pair
plus frequencies (`daily`, `weekly`, `monthly`, `quarterly`, `yearly`). Email contacts only.

- **Id:** the pair (`/monitor/{monitorId}/report/{contactId}`); the flat list gives an `rsub_...` id.
- **Links:** one monitor, one email contact.
- **Read:** `GET /monitor/{id}/report`, `GET /contact/{id}/report`, `GET /report` (+ `/by-monitor`, `/by-contact`,
  `/report/{id}`). MCP: `list_subscriptions` with `kind="report"`.
- **Lifecycle:** `PUT /monitor/{monitorId}/report/{contactId}` `{"frequencies": ["weekly"]}`, `DELETE` on the same
  path, `POST /report/bulk`. Frequencies your plan does not include are refused. MCP: `subscribe_contact` with
  `frequencies`.

See [Subscriptions - alert vs report](/alerts/subscriptions/) and [Schedule report subscriptions](/reports/scheduling/).

## Maintenance window

**What it is.** A planned period (one-off, or weekly on chosen days) during which the covered monitors hold back
alerts and/or keep the time out of uptime statistics. Suppression is chosen **per monitor** (`alerts`, `stats`).

- **Id:** GUID.
- **Links:** covers an explicit list of monitors; can be shown on status pages (`showOnStatusPage`).
- **Read:** `GET /maintenance` (filter by `state`: `scheduled`, `active`, `finished`), `GET /maintenance/{id}`,
  `GET /monitor/{id}/maintenance`. Scope `monitor:read`. MCP: `list_maintenance`.
- **Lifecycle:** `POST /maintenance`, `PATCH /maintenance/{id}` (a new monitor list replaces the coverage),
  `DELETE /maintenance/{id}` (cancelling an active window makes its monitors alert again at once). Scope
  `monitor:write`. MCP: `create_maintenance`, `update_maintenance`, `delete_maintenance`.

See [What a maintenance window is](/maintenance/overview/).

## Status page and its parts

**What it is.** A public page at its own address that shows the health of chosen services, with its own branding,
settings and audience. It has four kinds of child object:

- **Component** - one row on the page. Either shows a monitor's live state (`monitorId`) or is a **third-party**
  component whose state you set by hand (`manualState`: `operational`, `degraded`, `down`). Id: GUID.
- **Status page incident** - an incident or scheduled maintenance you **declare** on the page (`kind`: `incident`
  or `maintenance`), with a title, impact (`minor`, `major`), affected components and a lifecycle `state`
  (`investigating`, `identified`, `monitoring`, `resolved`). Id: GUID.
- **Timeline entry (update)** - each message posted on a status page incident, with the state it moved to. The
  timeline is append-only; posted messages cannot be edited.
- **Subscriber** - someone following the page: an email address (joins only through the public page's double
  opt-in) or a Slack, Teams or webhook channel you add. Id: GUID.
- **Template** - a saved title, message and default impact for announcements you post often. Id: GUID.

Reading and writing:

- **Read:** `GET /statuspage`, `GET /statuspage/{id}` (settings and components),
  `GET /statuspage/{id}/incident`, `GET /statuspage/{id}/incident/{incidentId}`, `GET /statuspage/{id}/subscriber`,
  `GET /statuspage/{id}/template`. Scope `statuspage:read`. MCP: `list_status_pages`, `get_status_page`.
- **Lifecycle:** `POST /statuspage` (public at its slug immediately; the slug cannot change later),
  `PATCH /statuspage/{id}`, `PUT /statuspage/{id}/component` (replaces the whole component set),
  `DELETE /statuspage/{id}` (removes components, incidents, subscribers and templates). Declare with
  `POST /statuspage/{id}/incident`, post updates with `POST /statuspage/{id}/incident/{incidentId}/timeline` - both
  notify subscribers. Scope `statuspage:write`.

See [Status pages overview](/status-pages/overview/).

:::note[Two different "incidents"]
A **monitor incident** is recorded automatically when a monitor goes down and closes when it recovers
(`GET /monitor/incident`). A **status page incident** is an announcement a person declares on a public page
(`POST /statuspage/{id}/incident`). Declaring one does not change any monitor. A monitor's outages show on a status
page only through its component (state, uptime bars and outage details, depending on the page's features), never as
an announcement.
:::

## Monitor incident and state span

**What it is.** An **incident** is one down episode of a monitor: from the confirmed down transition to the
confirmed recovery. It has a start, an end (for an open incident, the last moment the monitor was seen down), a
duration, a severity band (`minor` under 5 minutes, `major` 5 to 60 minutes, `critical` 1 hour or more), the error
that caused it, whether it began inside a maintenance window, and an optional comment. A **state span** is one
continuous up or down period; every down span names its incident.

- **Id:** incident `inc_...`; spans have no id of their own.
- **Links:** belongs to one monitor; groups the check results recorded during it.
- **Read:** `GET /monitor/incident` (whole account), `GET /monitor/{id}/incident`, `GET /monitor/incident/{id}`
  (with its timeline), `GET /monitor/incident/{id}/check` (the failing checks, plan feature),
  `GET /monitor/{id}/span`. Scope `monitor:read`. MCP: `list_incidents`, `get_incident`.
- **Lifecycle:** opened and closed by the monitoring itself. You can only add a comment
  (`POST /monitor/incident/{id}/comment`; MCP `comment_incident`) or wipe a monitor's statistics
  (`POST /monitor/{id}/reset-stats`).

See [What is an incident](/incidents/what-is-an-incident/).

## Check result

**What it is.** One logged check: when it ran, from which location, `up` or `down`, how long it took, the error for
a failure, measurements (response time and its phases, and type-specific values), and a page snapshot when one was
captured. Consecutive identical results are stored as one row with a `checkCount`.

- **Id:** `res_...`, addressed together with its monitor (`/monitor/{monitorId}/result/{id}`).
- **Links:** belongs to one monitor; may fall inside an incident.
- **Read:** `GET /monitor/{id}/result`, `GET /monitor/result` (across monitors), `GET /monitor/{id}/result/{resultId}`,
  `GET /monitor/{id}/result/{resultId}/snapshot`. One request covers at most 30 days. Scope `monitor:read`. MCP:
  `list_monitor_results`.
- **Lifecycle:** written by the monitoring. Read-only.

See [Reading a monitor's results and incidents](/incidents/reading-results/).

## Notification

**What it is.** One message HostTracker delivered (or tried to deliver) to a contact - an alert, a reminder, a test
or a scheduled report - with its outcome (`sent`, `blocked`, `sendFailed` and similar).

- **Id:** `alt_...`.
- **Links:** one contact, usually one monitor.
- **Read:** `GET /contact/notification`, `GET /contact/{id}/notification`, `GET /contact/notification/{id}` (with the
  rendered content), `GET /contact/notification/summary` (counts per contact and day). Scope `contact:read`.
- **Lifecycle:** written by the alerting. `POST /contact/notification/resend` re-sends a scheduled report for a past
  period.

## Generated report

**What it is.** An uptime document (PDF, CSV, XML or HTML) over chosen monitors and a time range, produced on
request. Scheduled reports sent to contacts are report subscriptions, not this object.

- **Id:** `rep_...`. It stays downloadable for 7 days.
- **Links:** covers a list of monitors; produced by a job.
- **Read:** `GET /monitor/report/{id}` (what it covers), `GET /monitor/report/{id}/content` (the file). Scope
  `monitor:read`. The catalogue of types, formats and sections: `GET /report/type`.
- **Lifecycle:** request with `POST /monitor/report` (scope `monitor:write`, `Idempotency-Key` required); the answer
  is a job. MCP: `generate_report`, then `wait_for_job`.

## Job

**What it is.** The record of an asynchronous operation: bulk monitor or contact writes, bulk deletes, statistics
resets, large copies and report generation answer `202` with a job instead of a result.

- **Id:** GUID.
- **Links:** points at the items it created, changed or deleted (per-item `entityId`, `status` and result).
- **Read:** `GET /job/{id}` (state, progress, summary, per-item results), `GET /job` (recent jobs). The scope is the
  one the operation that created it needed. MCP: `get_job`, `wait_for_job`.
- **Lifecycle:** `queued` -> `running` -> one of `succeeded`, `partial` (some items failed), `failed`, `cancelled`.
  `interrupted` means the server running it stopped; continue it with `POST /job/{id}/resume`. Cancel with
  `POST /job/{id}/cancel` (items already done are not rolled back). A job stays readable until its `expiresAt`.

See [Bulk operations on monitors](/monitors/bulk-operations/).

## Webhook

**What it is.** A signed HTTPS delivery of account events (`monitor.down`, `monitor.up`, `incident.opened`,
`monitor.created`, `certificate.expiring` and others) to your own endpoint, for integrations. It is a different
object from a webhook **alert contact**, which receives ordinary alerts in a template you design.

- **Id:** GUID. Each delivery has its own id (`d_...`).
- **Links:** scoped to the whole account, a list of monitors, or tags.
- **Read:** `GET /webhook`, `GET /webhook/{id}`, `GET /webhook/{id}/delivery` (recent deliveries and their
  outcome). Scope `webhook:read`. MCP: `list_webhooks`, `list_webhook_deliveries`.
- **Lifecycle:** `POST /webhook` (the signing secret is returned once), `PATCH /webhook/{id}`,
  `DELETE /webhook/{id}`, `POST /webhook/{id}/test`, `POST /webhook/{id}/delivery/{deliveryId}/redeliver`. After 20
  consecutive failures a webhook disables itself. There is no webhook page in the app.

See [Webhooks](/integrations/webhooks/) and [Webhook events reference](/reference/webhook-events/).

## Instant check

**What it is.** A one-off check of a url or host from HostTracker's locations, with no schedule and no alerts.

- **Id:** a pair - `dbId` (integer) and `id` (GUID).
- **Read:** `GET /check/{dbId}/{id}`, `GET /check` (history). Scope `check:read`. MCP: `get_check_result`.
- **Lifecycle:** `POST /check` (scope `check:write`; MCP `run_instant_check`). Results are read-only.

See [Instant checks vs monitors](/getting-started/instant-checks-vs-monitors/).

## Related

- [Do anything in HostTracker: task map](/reference/operator-task-map/)
- [Monitor fields by type](/reference/operator-monitor-fields/)
- [Build reports and summaries](/reference/operator-reports-and-summaries/)
- [REST API v2](/integrations/rest-api/)
