Skip to content

What a contact is

View as Markdown

A contact is a place HostTracker can deliver an alert or a scheduled report to: an email address, a phone number, a chat app account, a webhook, an on-call integration key, and so on. Creating a contact does not alert anyone by itself - a monitor has to be subscribed to it first, and even then an unconfirmed contact receives nothing at all (see below).

The API’s contact-type catalogue (GET /contact/type) publishes every type it knows about. Not all of them can be created today - a few are registered for reads only (a stray/legacy row must still display correctly) but hidden from creation:

Type (API token) Addressed by Creatable via a plain address Confirmable Can receive reports
email Email address Yes Yes (code) Yes - the only type that can
sms Phone number (international format) Yes Yes (code) No
voiceCall Phone number Yes Yes (code) No
http A URL you control, or a gateway-recognized webhook (Slack, Teams, PagerDuty, Opsgenie, Pushover, Pushbullet, Mattermost - see below) Yes No (born confirmed - there’s no channel to verify) No
webPush A browser push subscription Yes, but only from the browser’s own subscription handshake, not a typed address No (the browser step already proves it) No
telegram, viber, discord A messenger chat, linked by registering with the HostTracker bot No - minted only by the bot’s registration handshake No (linking proves it) No
facebook, googleChat Same as above No, and hidden from the New Contact picker too No No
skype Retired channel No - reads only, for accounts that still hold one No No
whatsApp Phone number, via the Meta Cloud API Not yet - parked pending Meta onboarding, hidden from the picker for every account Yes (once it ships) No

So in the app’s Add contact picker you see fourteen live options: Email, SMS, Call, HTTP (webhook), Slack, Microsoft Teams, PagerDuty, Pushover, Pushbullet, Mattermost, Telegram, Viber, Discord, and Web push. WhatsApp, Opsgenie, Skype, Facebook and Google Chat are excluded from that picker today (WhatsApp and Opsgenie because they aren’t fully wired up yet; Skype because it’s retired; Facebook and Google Chat by product decision even though the underlying bot channels exist). See all channels for a setup guide per type.

Confirmation - why an unconfirmed contact gets nothing

Section titled “Confirmation - why an unconfirmed contact gets nothing”

Email, SMS and voice contacts must be confirmed before they receive anything real. This exists so a mistyped address can’t silently swallow alerts (or run up an SMS bill) forever.

  • On create, HostTracker sends a 5-digit numeric code to the address, valid for 30 minutes with 3 attempts to enter it correctly. A still-valid, still-unused code is returned again on a resend request rather than replaced - so resending never invalidates a code you’re already looking at.
  • Chat-app and key-addressed contacts (Telegram, Viber, Discord, PagerDuty, Opsgenie, Pushover, Pushbullet, webhooks, web push) are confirmed implicitly, by the setup step itself - there’s nothing separate to verify, because either the bot’s own registration handshake or the browser’s push-subscription exchange already proved the endpoint is real.
  • If the account already holds a confirmed contact with the same type, address and delivery settings, a new one you create with that same address is born already confirmed - so adding a second alert-delay tier for a phone number you’ve already verified doesn’t ask you to re-verify it. Changing a contact’s address always resets it back to unconfirmed.
  • The gate is silent and it’s enforced twice: first when HostTracker decides who should hear about an event at all (an unconfirmed or over-package-limit contact is dropped from that list before anything is rendered), and again right before sending. Nothing surfaces this as an error anywhere - a subscription can exist, look correctly configured, and simply never deliver. Always confirm a contact right after creating it, and send it a test alert to be sure.

These are the fields on every contact, from the Main Settings group of the editor. A few (mimeType, httpHeaders, templates) only apply to http contacts; plainText only to email.

Setting (UI label) API field (v2) Type / allowed values Default Plan limits What it does for you
Contact Type type One of the tokens in the table above - (required on create) - Selects the channel; cannot be changed after creation (type_immutable)
Address address String - shape depends on type (email, E.164-ish phone, URL) - (required for address-bearing types) - Where the alert is delivered
Contact name name String, up to 100 characters Empty - A label to recognize it by later
Notification language language 2-letter code, or empty for “from profile” From profile - Renders alert content in this language when a translation exists, else falls back to the profile language, then English. Voice scripts are English only regardless.
Alert delay alertDelay Minutes - one of a fixed ladder: 0 (instant), 3, 5, 15, 30, 60, 180, 360, 720, 1440 0 (instant) - How long a confirmed Down must persist before this contact hears about it - see escalation
Grouped alerts groupedAlerts boolean Email: true (also when POST /contact omits it); HTTP-family: false - Combine alerts that fire close together into one message - see grouped alerts
Active hours activePeriod {start, end, days[], timezone} or null null (always active) - Restrict delivery to chosen hours/days/timezone - see Active hours
Billing notifications billingNotifications boolean (email only) false - Also receive billing/payment emails at this address
News and updates sendNews boolean (email only) false - Receive occasional product news
Plain-text emails plainText boolean (email only) false (HTML) - Send plain text instead of the HTML design
Gateway gateway String - a recognized value (e.g. Slack, Teams, PagerDuty, Opsgenie, Pushover, Pushbullet, Mattermost), or absent Server-routed (absent) - Pins an http contact to a specific channel’s formatting/delivery rules instead of a plain generic webhook
MIME type mimeType String, e.g. application/json (http only) application/json - The outgoing webhook body’s content type
HTTP headers httpHeaders Array of {header, value} (http only) Empty - Custom headers sent with every webhook request (auth tokens, routing headers)
Custom templates templates Array of {event, content}, event = up/down/repeatedlyDown (http only) Empty (uses the built-in payload) - Author the exact JSON/text HostTracker posts for each event - see Webhook for the [[token]] variables available

Two members exist only on the wire, not as an editor field: defaultSubscriptions: {alerts, reports} (on create only - seed this contact onto every existing monitor for Up+Down alerts and/or scheduled reports in the same call) and inline alertSubscriptions[] / reportSubscriptions[] (subscribe specific monitors at create time). Both are additive conveniences over calling the subscription endpoints separately afterward.

  1. Open Alerts & Contacts in the sidebar and click + Add contact.
  2. Choose the Contact Type. The fields below it change to match - a typed address box for Email/SMS/Call, a bot-connect flow for Telegram/Viber/Discord, a browser-permission prompt for Web push, or a URL + Request Template group for HTTP/Slack/Teams/etc.
  3. Enter the address (or complete the connect flow) and give the contact a name.
  4. Expand Main Settings to set language, alert delay, active hours, and the type-specific switches from the table above.
  5. Click Save. For Email/SMS/Call, HostTracker sends the confirmation code immediately.
  6. Confirm it (link, code entry, or resend from the contact’s row), then send a test alert.

Create an email contact:

POST /contact
{ "type": "email", "address": "[email protected]", "name": "Ops inbox", "alertDelay": 0 }

The response is the new ContactView, confirmed: false, plus a confirmation block ({sent, channel, expiresAt, triesAllowed}). Confirm it:

POST /contact/{id}/confirmation/verify
{ "code": "48213" }

Resend the code if it expired or wasn’t sent:

POST /contact/{id}/confirmation

Update settings (partial - only the fields you send change):

PATCH /contact/{id}
{ "alertDelay": 15, "groupedAlerts": true }

List, read, delete: GET /contact, GET /contact/{id}, DELETE /contact/{id}. MCP tools: create_contact (email, sms, voiceCall or webPush only - messenger contacts are registered from the messenger itself, and http/webhook is deliberately excluded from this tool: use create_webhook under Integrations for signed HTTP delivery instead), update_contact, delete_contact, send_contact_confirmation, confirm_contact, list_contacts, get_contact, test_contact.

A newly created contact is unconfirmed (except the implicitly-confirmed types) and has no subscriptions unless you set defaultSubscriptions/inline subscriptions on create. It receives nothing until it’s both confirmed and subscribed to at least one monitor for at least one event. Once both are true, it’s evaluated against its own alert delay, active hours and grouping settings at send time - not at subscribe time.

  • 422 validation_failed (reason unknown_member) - the create/update body has a closed vocabulary; an unrecognized top-level member, or a misspelled nested one (like activePeriod.timeZone instead of timezone), is refused with an allowed[] list rather than silently dropped.
  • 422 type_immutable - you can’t change type after creation. Create a new contact instead.
  • 422 validation_failed (reason undeliverable_domain) - a new email address is checked for a working MX record at create/update time and refused if the domain can’t receive mail at all (this check fails open on DNS trouble, so it never blocks a real domain having a bad day).
  • 429 rate_limited on a confirmation resend - capped at roughly 10 per contact per day and 50 per account per day, plus a short per-request cooldown; the response carries Retry-After.
  • 422 invalid_confirmation_code - wrong, expired, or attempts exhausted; carries attemptsLeft and expiresAt so a client can tell a user exactly what’s wrong. 409 if the contact is already confirmed.
  • A contact can be deleted with everything it’s subscribed to - DELETE /contact/{id} also removes its subscriptions. There is no undo.
  • Plan limits cap the total number of contacts and, per type, how many of each; an over-limit create either refuses (403 package_limit on v2) or, on the app’s create-anyway path, lands the contact paused (unconfirmable, no send) until you free up room.