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 inalertType, 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 afterfrom = (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 newestnumrecords of each type from all history. Withoutnum, it returns nothing. numapplies per alert type. When a type returnsnumrecords, older records of that type in the window may have been cut; the sample warns, and you should raiseNUM.- Send
page=1explicitly, and theX-Session-Tokenheader on the following pages, so those pages do not count against the rate limit (Pagination sessions). Keepfromidentical 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_startafter 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
Building notification rules
To route each alert to a channel, calldispatch_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
OVERLAPafter the time it is dated, for example after a long coverage gap. SizeOVERLAPto 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).
- the process stops after handling a record but before saving the state;
OVERLAPis 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
OVERLAPof alerts).
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 newestutcTimeyou have seen. isReadis shared. Dashboard users andset-all-alerts-readchange 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}/alertsshows each configuration’s current settings. utcTimehas noZsuffix but is always UTC — treat it as UTC when parsing.