Skip to main content

Alerts

Alert history

Every time an alert fired, and whether the email arrived.

GET/sites/{siteId}/alerts/history
Alert history
curl --request GET \
  --url 'https://truestat.io/api/v1/sites/{siteId}/alerts/history' \
  --header 'Authorization: Bearer <token>'
{
  "data": [
    {
      "id": "7c1f0b2e-1f5a-4a1e-9f77-2a2f0f6b1e11",
      "error": null,
      "status": "sent",
      "alert_id": "ed054a7c-696a-4db4-809e-531a169da959",
      "fired_at": "2026-09-15T09:00:00.000Z",
      "alert_name": "Traffic dropped by half"
    }
  ],
  "meta": {
    "page": {
      "limit": 100,
      "offset": 0,
      "has_more": false
    },
    "site_id": "6fed8980-a119-4a9c-a4d4-53e448ef9f9e"
  }
}

What your alerts actually did.

Read status, not the row count

The case this endpoint exists for is an alert that fired and failed to send. The condition happened, the rule worked, the email did not arrive — and from the inbox that is indistinguishable from nothing happening at all.

What you seeWhat it means
No rowsNothing triggered. The rules are quiet.
Rows with status: sentTriggered, and somebody was told.
Rows with another statusTriggered, and nobody was told. error says why.

A monitoring script that only checks whether alerts exist will miss the third case entirely. Checking for non-sent rows in the last day is the version that catches it.

Scope and filtering

Covers every alert on the site by default, newest first. Narrow it with alert_id:

GET /sites/{siteId}/alerts/history?alert_id=$ALERT_ID&period=last30d

A window filters by fired_at — when the condition was met.

An alert_id that is not on this site returns an empty list, not an error. That is the same answer a real alert that never fired gives, so the parameter cannot be used to discover which ids exist elsewhere.

alert_name is the current name

Not the name at the time of firing. A renamed alert shows its new name against old deliveries.

It is included so rendering a list does not need a second request. If you need the historical name, record it yourself when you rename.

History disappears with the alert

Deleting an alert cascades to its deliveries. If the record matters, switch the alert off rather than deleting it — see Alerts.

Authorizations

Authorizationstringheaderrequired

An API key from Settings → API keys. Scopes available: analytics:read, sites:read, sites:write, settings:read, settings:write, goals:read, goals:write, funnels:read, funnels:write, notes:read, notes:write, alerts:read, alerts:write, team:read, team:write, revenue:read, revenue:write.

Bearer authentication header of the form Bearer <token>, where <token> is your auth token.

Path parameters

siteIdstring (uuid)pathrequired
The site's id, from `GET /sites`. A site that is not yours and a site that does not exist both answer 403, so this cannot be used to discover other people's ids.

Query parameters

alert_idstring (uuid)query
Narrow to one alert. An id that is not on this site returns an empty list rather than an error — the same answer a real alert that never fired gives.
periodenum<string>query
A named window, resolved in `tz`. Cannot be combined with `from`/`to` — a request carrying both is refused rather than guessed at.
options:todayyesterdaylast24hlast7dlast30dlast12mmonthyearall
fromstring (date-time)query
Start of the window, ISO 8601 with an offset. Must be given together with `to`.
tostring (date-time)query
End of the window. Must be given together with `from`.
tzstringquerydefault: UTC
IANA timezone for day boundaries. `period=today&tz=Europe/Istanbul` means the reader's today, not the server's. Defaults to UTC.
botsenum<string>querydefault: excluded
Whether crawler traffic is counted. Excluded by default — the `/ai/*` endpoints report it separately and always include it.
options:excludedincluded
limitintegerquerydefault: 100
Rows per page, 1 to 1000.
offsetintegerquerydefault: 0
Rows to skip.

Response

application/json

The answer.

dataunknown
See the example.
metaobject