Blog · Release notes
Telegram notifications: the right message to the right person
A new Wintertrace module sends winter-service notifications over Telegram — to drivers, customers, and admins. Consent first, no instant send, and a building block other modules can use.
Most of what Wintertrace does is about recording the work: a driver clears a site, the phone notes where and when, the weather is pulled from an independent source, and the whole thing comes out as a service proof. That part is solved.
But a winter service does not only happen — it has to be coordinated. And coordination is mostly about telling people things at the right moment. The driver needs to know a shift starts at four. The customer wants to hear that their car park was actually cleared before they set off. The person running the operation wants to know, quickly, when something failed. Until now, in most small operations, all of that lived in phone calls and a scatter of text messages.
There has been one channel inside Wintertrace for a while: email. When an operation ends, the customer can have the PDF in their inbox minutes later. Email is good for the document — it carries an attachment, it sits in a record, it is easy to forward. What email is not good at is reaching someone on the move. A driver about to start a round does not check email. A customer wondering at 7 a.m. whether the path is safe does not want to open a mail client.
So there is now a second channel, as an optional module: Telegram notifications.
Why Telegram
The honest reason is that it removes friction in exactly the places email adds it. Telegram runs on a phone people already carry. It is free, there is no per-message cost, and it has a proper bot interface — which means a self-hosted application can send through it without a paid gateway and without routing customer data through a marketing platform. For a small contractor that is the difference between “a channel I can actually turn on” and “a line item I will never sign off.”
The module sends to the three groups that actually need telling: drivers, customers, and admins. A driver gets the operational nudge. A customer gets the “your site was serviced” confirmation. An admin gets the things that need a person — a delivery that failed, a recipient who dropped off.
That is the easy part to describe. The part I spent the most time on is making sure it behaves like a tool and not like spam.
Consent before any message
Nobody receives a Telegram message because their number ended up in a spreadsheet. Telegram does not even work that way — the bot cannot message a person until that person has started a conversation with it. The module leans into that rather than fighting it.
Each recipient connects their own account, once. The comfortable way is a QR code or a deep link: the admin generates a one-time, time-limited link, the recipient scans it on their phone, Telegram opens the bot, and the link is consumed. There is also a manual path for people who would rather paste an identifier and confirm with a test message. Either way, the recipient is the one who opts in, on their own device.
That connection is stored with a timestamp, and only recipients who are genuinely connected and active receive anything. If someone blocks the bot, the system notices and stops trying. None of this is a compliance badge — it is just the data-protection-minded way to build a messaging feature, and it lines up with the rest of the data-protection tooling: consent recorded, status visible, nothing sent to someone who did not ask for it.
No instant send — and why that is deliberate
Here is the part that surprises people, so I would rather be plain about it: when an event happens, the module does not immediately call Telegram. It writes the message to an outbox — a queue in the database — and a small scheduled job drains that queue a moment later and does the actual sending.
The reason is the same constraint that shapes the whole of Wintertrace: it has to run on ordinary, cheap, shared web hosting. That kind of hosting does not give you a background worker or a long-running daemon. So instead of trying to send during a web request — which is slow, and fails badly when Telegram is briefly unreachable — the work is handed to a cron job, the one scheduled task Wintertrace already relies on.
This buys real things. Sending never blocks the person clicking a button. A brief outage at Telegram’s end does not lose a message; it is retried, with a sensible back-off, and a recipient who has blocked the bot is marked rather than retried forever. Every attempt is written to a delivery log, the same way the email channel logs every send — so “I never got a message” has a definite answer instead of a shrug.
The trade-off, and I will not hide it: this depends on the cron job being set up. It is one line in the server’s crontab, the same line that already drives weather fetches and updates. But if that scheduled task is not running, messages sit in the outbox and are not delivered. The setup page is blunt about this, because a silent non-delivery is the worst kind of bug.
A building block, not just a feature
There is a second audience for this module that most users will never see: other modules.
A notification channel is only worth building once. So the Telegram module is also the place that owns Telegram for the whole installation. Another module — say a future contracts module that wants to nudge a customer when a document is waiting — should not have to learn the Bot API, store its own token, or worry about consent. It should just say “tell this person this,” and be done.
That is exactly what the module exposes. There are two ways in. One is a direct call for modules that want a result back — did this get queued, was there no active recipient, was it a duplicate. The other is a fire-and-forget event that requires no hard link to the Telegram module at all: a module can announce “I would like to send this” into the void, and if the Telegram module is installed it picks it up, and if it is not, nothing happens — no error, no crash. That decoupling matters on self-hosted software, where you cannot assume which modules a given operator has chosen to install.
If you write Wintertrace modules, the Telegram module page explains both paths, and the module package itself ships full developer documentation under docs/ — copy-paste examples for the direct call and the decoupled event.
Where it fits
Email and Telegram are not competitors here. Email is for the document — the PDF that needs to land in a record and be forwarded to an insurer or a property manager. Telegram is for the moment — the short, timely “it happened” or “it failed” that reaches a person on their phone. Most operations will want both, on different events, for different people.
The module is published in the module catalogue, installed the same way as any other Wintertrace add-on — from the admin area in one click, or by uploading the folder over FTP. As with everything else, it is optional. The core runs without it, and turning it on is a decision an operator makes when they actually want a phone to buzz.