← Back to the feed
2026 · Automation / n8n

Bus 351

Is the bus late? A message answers before I get to the stop.

Automation · n8n · Transport for NSW · WhatsApp

A workflow checks the live departure board for route 351 a few times each weekday, compares the estimated time with the timetable, and sends one sentence to WhatsApp. On schedule, running late, running early, or not tracked yet.

The n8n canvas showing five connected nodes: Schedule, Select stop, Get departures, Format message and Send text
The workflow: a weekday trigger, a stop chosen by local time, the departure board, the message logic and a WhatsApp send. Open the full screenshot.

A message, not a departure board

The trip planning API returns a full board: every route at the stop, with planned and estimated times. Reading it on a phone while walking is a poor experience. The workflow reduces all of it to the one decision I actually make — leave now, or wait.

The steps

  1. Schedule — three cron expressions on weekdays: every 10 minutes from 8:00, 14:50, then every 10 minutes from 15:00.
  2. Select stop — a Code node reads the hour inAustralia/Sydney and picks a stop ID. Morning runs use one stop, afternoon runs use another. This matters because the schedule events fire in server time, not local time.
  3. Get departures — calls the Transport for NSWdeparture_mon endpoint with rapidJSON output and an API key header.
  4. Format message — filters stopEvents to route 351, drops anything that has already left, sorts by estimated time and compares it with the planned time.
  5. Send text — posts the sentence to a WhatsApp group through the Evolution API node.

The message the code produces

If there is live tracking, the difference between planned and estimated becomes plain language. A difference of zero is “Bus 351 is on schedule.” A positive difference reports how many minutes late it is, a negative one how many minutes early. Without tracking, the message falls back to the scheduled time so the silence is not mistaken for a delay.

No departures in the window produces “Bus 351: no upcoming departures found.” Matching on the route number, rather than the first result in the board, is what keeps a neighbouring route out of the message.

What is still fragile

Buses that left in the last two minutes are kept, so a slightly stale departure does not vanish mid-check. Code and time zone logic live inside the workflow rather than next to the rest of the codebase, so there are no tests around the format step. The stop IDs are also hard-coded; replacing them with a lookup by stop name would make the workflow portable.

Next automation: Solar State of Charge ↗