Skip to main content

Overview

GET /v2/api/companies/{id}/alert-records returns alert records as AlertDto items. This guide polls it with an overlapping time window and processes each record once in normal operation. Polling is best-effort: read Limits before you rely on it. Key fields per record: No single field identifies a record. This guide uses id, vehicleId, utcTime, lat and lng together. Because utcTime has whole-second precision, two records can rarely share that key.

Step 1 — Map alert types to names

Each record carries its type in alertType, an integer from 3 to 12. Map it to a name with the TYPE_NAMES table below; these are the type names GET /v2/api/companies/{id}/alerts shows on alert configurations. Use the record’s own alertType rather than looking up its configuration by id: it is the type the record was raised with, while the configuration shows its current settings. TELEMAX_COMPANY_ID is your level-0 company (the item with level 0 in GET /v2/api/companies). The settings come from environment variables; the request helper waits out a short 429 and stops when an hourly or daily budget is used up.
Python
Python

Step 2 — Poll with an overlapping window

Each poll asks for every record dated after from = (start time of the previous poll that finished without error) − OVERLAP. The first run uses now − OVERLAP.
  • Records are dated by the vehicle, and can reach the API late — for example after a vehicle has been out of coverage — or be dated up to an hour ahead. The overlap gives late records a chance to be picked up; the de-duplication keys stop them being processed twice.
  • Without from, the call returns the newest num records of each type from all history. Without num, it returns nothing.
  • num applies per alert type. When a type returns num records, older records of that type in the window may have been cut; the sample warns, and you should raise NUM.
  • Send page=1 explicitly, and the X-Session-Token header on the following pages, so those pages do not count against the rate limit (Pagination sessions). Keep from identical on every page.
  • Decide what to process from your own saved keys, not from isRead: Dashboard users can mark records read before you poll.
  • Save the keys and last_completed_start after processing. A record whose handler fails is not saved, so the next poll retries it.

Step 3 — Route alerts by type

Use the name from Step 1 to choose a handler, for example "Exceed Maximum Speed", "Above Speed Limit", "Geofence" or "Low Battery".
Python
Python

Step 4 — Acknowledge alerts

Mark one record as read

PUT /v2/api/alerts/{id}/{date}/update-read-status takes isRead as a query parameter; there is no request body. Omitting isRead marks the record unread. {id} is the record’s id and {date} its utcTime. The call returns 200 even when it changed nothing, so it does not confirm the update; see Update alert read status. Each call counts against the rate limits, so mark records only if you need to.
cURL
Python

Mark everything as read

PUT /v2/api/companies/{id}/set-all-alerts-read marks the unread records as read in one call:
cURL
PUT /v2/api/companies/{id}/set-all-alerts-read marks all alerts as read, and Telemax Dashboard users see the change. Only call it when every consumer of the read state is caught up. See Mark all alerts read.

Building notification rules

To route each alert to a channel, call dispatch_notification(handler, rec) from process_alert in Step 3. send_sms, send_email and log_to_dashboard stand for your own functions.
Python

Limits

This pattern is best-effort. A record can be missed in the cases below, and it can reach your handler more than once, so make your handler idempotent. A record can be missed when:
  • it reaches the API more than OVERLAP after the time it is dated, for example after a long coverage gap. Size OVERLAP to the longest gap you expect;
  • one alert type has more records in a window than NUM — the sample warns;
  • a multi-page poll is under way. Every page re-runs the query, so a record can shift past a page boundary when records change meanwhile, or when records share the same time, which the server does not order consistently;
  • an alert configuration is deleted before its records are polled;
  • two records share the same key (same alert, vehicle, second and location);
  • a handler keeps failing for longer than OVERLAP;
  • the client clock drifts. Keep it synchronised (NTP).
A record can reach your handler more than once when:
  • the process stops after handling a record but before saving the state;
  • OVERLAP is raised between runs;
  • two instances share one state file;
  • the state file is lost (the next run behaves like a first run and processes the last OVERLAP of alerts).
Cost: each record is fetched about OVERLAP ÷ poll interval times, and every page reverse-geocodes its records on the server. The first page of each poll counts against the rate limits; follow-up pages in a pagination session do not. A long OVERLAP suits a less frequent poll. To receive alerts as they are processed instead of polling, use webhooks. Webhooks deliver only some alert types (see Supported alert types), and deliveries are retried a few times and can still fail.

Gotchas

  • Use an overlapping window. Poll from the previous poll’s start minus OVERLAP, not from the newest utcTime you have seen.
  • isRead is shared. Dashboard users and set-all-alerts-read change it, so do not use it to decide what is new.
  • Route by the record’s alertType. It is the type the record was raised with; GET /v2/api/companies/{id}/alerts shows each configuration’s current settings.
  • utcTime has no Z suffix but is always UTC — treat it as UTC when parsing.