← Journal Playbook

Build a Flight Delay Notification System (Email, SMS, Webhook)

A step-by-step playbook for a delay-alert system your users actually trust: point a webhook at your app, create a monitor per flight, then fan out to email, SMS and Slack — with a debounce so you never spam anyone.

August 2, 2026 · · 5 min read

"Your flight is delayed" is one of the most valuable messages a product can send — if it arrives early, once, and only when it's true. Build it badly and you either miss the delay or bury the user in noise every time an estimate wobbles by a minute. This playbook walks through a delay-notification system built entirely on the consumer side of FlightNerve: you create monitors, receive webhooks, and fan out to email, SMS and Slack. No polling loop, and no change-detection code to maintain.

The shape of the system

Four moving parts, and FlightNerve is the one you don't have to build:

  1. A webhook endpoint on your side that receives alerts.
  2. A monitor per flight your users care about.
  3. A dispatch layer that turns an alert into email / SMS / Slack.
  4. A mapping from each alert back to the user or booking it belongs to.
FlightNerve watches the flight webhook Your endpoint map id → user Email SMS Slack / push
FlightNerve pushes the change; your endpoint maps it to a user and fans it out. You build the last two boxes only.

Step 1 — Point a webhook at your app

Set one endpoint URL for your account. FlightNerve POSTs a JSON alert to it whenever a monitored flight changes; reply with any 2xx to acknowledge.

curl -X POST "https://api.flightnerve.com/webhook/YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"url":"https://your-app.example/hooks/flightnerve"}'

You can fire a test alert at the same URL before a single flight is monitored, so you confirm your receiver works up front:

curl -X POST "https://api.flightnerve.com/webhook/YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"test": true, "url": "https://your-app.example/hooks/flightnerve"}'

 { "success": true, "delivered": true, "code": 200 }

Step 2 — Create a monitor per flight

When a user adds a flight to track, create a monitor for it. Store the monitoring_id you get back against that user or booking — it is how you will route the alert later.

curl -X POST "https://api.flightnerve.com/monitor/YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "flight": "EK72", "date": "20260802", "monitor": { "sensitivity_min": 15 } }'

 { "success": true, "monitoring_id": "mon_fbba35cd573ca081" }

Step 3 — Receive the alert and route it

A delay alert arrives as a compact delta — what changed, by how much, and the new local time — with the monitoring_id so you know whose flight it is:

{
  "event": "flightnerve.alert",
  "monitoring_id": "mon_fbba35cd573ca081",
  "flight": "EK72",
  "route": "DXB-MUC",
  "changes": [
    { "field": "arrival_estimate", "type": "delayed",
      "from": "2026-08-02T14:00:00Z", "to": "2026-08-02T14:25:00Z",
      "delta_min": 25, "to_local": "16:25" }
  ]
}

Your handler looks up the user by monitoring_id and fans out. The alert is already diffed, so there is nothing to compute:

# pseudo-code for your webhook handler
def on_flightnerve_alert(payload):
    user = lookup_user(payload["monitoring_id"])
    for c in payload["changes"]:
        if c["field"] == "arrival_estimate" and c["type"] == "delayed":
            msg = f'{payload["flight"]} now arriving {c["to_local"]} (+{c["delta_min"]} min)'
            send_email(user.email, msg)
            send_sms(user.phone, msg)
            post_slack(user.slack, msg)

Step 4 — Keep it from becoming noise

The fastest way to get your alerts muted is to send too many. Two habits prevent it:

Step 5 — Match the channel to the moment

Because every alert carries the monitoring_id, the same pipeline serves a consumer app (one traveller) and an operations desk (hundreds of flights) without changing the routing logic.

Frequently asked questions

Do I need a polling job anywhere in this?

No. You create monitors and receive webhooks. There is no timer and no status-diffing code in the system.

How do I stop alerting users over tiny estimate changes?

Set sensitivity_min when you create the monitor. Time alerts only re-fire once the estimate moves past that threshold from the last value you were told.

How do I know which user an alert belongs to?

Store the monitoring_id returned at creation against the user or booking; every alert for that flight includes it, so routing is a lookup.

What if my endpoint is down when an alert fires?

Alerts are stored with their delivery result, so you can reconcile misses, and you can re-test your endpoint at any time to confirm it is receiving.

Can the same system handle cancellations and gate changes?

Yes. A monitor covers the whole journey — delays, gate and terminal changes, diversions, cancellation and landing — so you choose which of them become notifications.

A trustworthy delay alert is a small system: one webhook, one monitor per flight, a lookup, and a fan-out — with a sensitivity threshold keeping it quiet until it matters. FlightNerve handles the watching and the diffing; you handle the message. Point a webhook at your app and send the alert your users actually want.

Build it in minutes — free to start.Get an API key →