Skip to content

API authentication, tokens and scopes

View as Markdown

The API authenticates every call with a bearer token you create in the app. A token carries the account it belongs to, the scopes (operations) it may perform, an expiry and, optionally, an IP allow-list. The same token works for raw HTTP calls, the SDKs, ht-cli, the Terraform provider and the MCP server.

Your plan must include API access - the app refuses to create a token otherwise. See which plans include the API. Subaccounts need the API access right.

Setting (UI label) Mint field Allowed values Default What it does for you
Token name name Free text (placeholder “e.g. CI server”) Empty Lets you recognise the token later.
Token scopes (allowed operations) scopes Any of the scopes below; at least one None ticked What the token may do. A token with no scope is refused.
Token expiration tokenDuration or tokenExpiration 10 years, 1 day, 7 days, 30 days, 120 days, 1 year, Custom date 10 years When the token stops working.
Token IP white list (optional) ipWhiteList Up to 10 entries: an address (1.2.3.4) or a range (1.2.3.4-4.3.2.1) Empty (any address) Calls from any other address answer 403 ip_not_allowed.
  1. Open Integrations -> API in the app (/integrations/api).
  2. In New access token, enter a Token name.
  3. Under Token scopes (allowed operations), tick the scopes the integration needs (each family has All and None shortcuts).
  4. Choose a Token expiration. Prefer a short one for anything you hand to a person, a CI job or an AI tool.
  5. Optionally list the addresses allowed to use it in Token IP white list.
  6. Click Create Access Token and copy the token. It is shown once and is not stored on HostTracker’s side - if you lose it, create another.

Send it on every request:

Authorization: Bearer YOUR_HOSTTRACKER_API_TOKEN
Terminal window
curl https://api2.host-tracker.com/account -H "Authorization: Bearer $HT_TOKEN"

There is no account id in URLs or bodies - the token says who is calling.

There are 13 leaf scopes, one per action on an area, and 7 family scopes (the bare area name):

Family Leaves Covers
monitor monitor:read, monitor:write Monitors, results, incidents, uptime summaries, maintenance windows, reports, per-monitor subscriptions
contact contact:read, contact:write Contacts, contact groups, confirmations, tests, the notification log, per-contact subscriptions
subs subs:read The flat account-wide subscription lists (GET /alert, GET /report)
webhook webhook:read, webhook:write Webhooks, their delivery log, tests and redelivery
statuspage statuspage:read, statuspage:write Status pages, components, declared incidents, templates, subscribers
account account:read, account:write Account details, usage, limits, quota; account:write changes profile, time zone, language and default locations
check check:read, check:write Instant checks

Rules:

  • A leaf does not imply its sibling. monitor:write does not grant monitor:read, and the reverse is also false. An integration that both reads and writes monitors needs both leaves, or the family.
  • A family covers every leaf in it - monitor passes both monitor:read and monitor:write. A family also grows automatically if its area gains a new action later; grant leaves when you want the token pinned to today’s surface.
  • A write that reaches two areas needs both. Creating a monitor with inline contacts needs monitor:write and contact:write; the bulk subscription writes (POST /alert/bulk, POST /report/bulk) need both writes too.
  • Subscription writes ride their parent: PUT /monitor/{id}/alert/{contactId} needs monitor:write, the mirror PUT /contact/{id}/alert/{monitorId} needs contact:write.
  • Jobs need the scope of the operation that created them.
  • The old spellings ic, ic:read, ic:write and subs:write no longer exist.

GET /account/quota returns the full scope catalogue with a one-line description of each, and shows which scopes the calling token carries.

Integration Scopes
Status dashboard (read-only) monitor:read
Provisioning script (create monitors, never read them back) monitor:write
Monitors as code (Terraform, CI) monitor (plus contact, webhook, statuspage for those resources; account:read for the account data source)
Deploy smoke test with instant checks check
Alert routing sync contact, monitor:write, subs:read
Status page automation statuspage
Status and code Meaning Fix
401 invalid_token, reason missing No Authorization header. Send the header.
401 invalid_token, reason invalid Malformed, tampered or expired token (the two look identical on purpose). Mint a new token.
403 missing_scope The token is valid but lacks the scope. errors[0] carries required and granted. Mint a token with the missing scope - scopes cannot be added to an existing token.
403 ip_not_allowed Called from an address outside the token’s allow-list. errors[0].clientIp shows your address. Call from an allowed address or mint a new token.
403 insufficient_rights A subaccount token lacks the subaccount right for this operation. Ask the account owner to grant the right.
{
"code": "missing_scope",
"status": 403,
"errors": [ { "required": "monitor:write", "granted": ["monitor:read"] } ]
}

A token is a password for its scopes. It is not stored on HostTracker’s side - the grant lives inside the signed token - so:

  • A token cannot be revoked before it expires. Changing your password or signing out everywhere does not stop it. Only an account-wide API disable (a support action) stops every token at once.
  • Limit the damage in advance: scope narrowly, set a short expiration, use the IP allow-list for anything that runs from a fixed address, and use one token per integration.
  • A token with a past tokenExpiration is refused at creation.
  • If a token leaks, remove it everywhere, mint a replacement and contact [email protected]. Never send the token itself.

The minting endpoint also accepts a self-cap (the most calls this one token may spend from the account’s quota); the form does not have a field for it yet.

Some clients - AI assistants such as Claude and ChatGPT connecting to the MCP server - sign in with OAuth 2.1 instead of a pasted token. You sign in to HostTracker, see a consent card listing the scopes, and approve.

  • Access tokens last an hour and are refreshed automatically; refresh tokens rotate on every use.
  • A client that asks for no scopes gets check and monitor:read. The account family is never granted to a connected app.
  • Unlike pasted tokens, a connected app can be revoked: Integrations -> API -> Connected apps lists every app with its scopes and connection date; Revoke cuts it off at once (its last access token expires within the hour).