Skip to content

Pending Updates

TravStats enriches your flights automatically with external data — AirLabs / Aviationstack status updates, OpenSky tracking, historical aggregation. Rather than silently overwriting your existing values, the result is a Pending Update: a proposal you can review, accept, edit, or reject in the Pending Updates dashboard.

This is the answer to “the API has a different aircraft than I manually entered — who wins?”. Default: nobody. You decide.

Three sources produce proposals:

For scheduled future flights, the flightAutoUpdate service polls AirLabs / Aviationstack at regular intervals. If a difference is detected (different gate, changed departure time, new aircraft registration), a Pending Update is created.

For older flights without API data, a nightly cron (default 02:00 UTC) attempts to reconstruct the route — e.g. via OpenSky-Historic. A match score, distance plausibility, and aircraft-common-sense feed into a confidence value. High confidence becomes a proposal.

When you re-parse a confirmation email (after a template update, for example) and the result diverges from the existing flight row, this also creates a Pending Update instead of a direct overwrite.

Each proposal contains:

  • originalData — what’s currently in the database
  • proposedData — what the source suggests
  • changes — per-field diff with type added / removed / changed
  • apiSource — which source proposed it (airlabs, aviationstack, opensky, historical_enrichment, re_parse)
  • statisticsImpact — preview of how distance / flight time / top-K change if you apply
  • expiresAt — pending updates auto-expire after 24 h (or after flight end, whichever is later) so the dashboard doesn’t fill up endlessly

Settings → Pending Updates (or /pending directly in the URL). What you see:

  • Filter by status: pending / applied / rejected / edited / expired
  • Sort by creation date or expiry time
  • Statistics banner at the top: total updates processed, top-3 most-changed fields, average review time
  • List of individual updates with source badge, change count, expiry time

Three actions per entry:

ActionWhat happens
ApplyproposedData is written to the flight, all derived fields (distance, duration, country) recompute, achievements re-check
Edit & ApplyYou edit fields in the update before applying (e.g. the API has the gate but you know the right terminal)
RejectThe proposal is discarded, the flight stays as it was. The next API poll won’t immediately re-create the same proposal (rejected updates are remembered for a while)

Before you hit Apply, the dashboard calls POST /api/v1/pending-updates/:id/preview — that shows:

  • Distance before / after / Δ in km
  • Flight time before / after / Δ in minutes
  • Set counters (airlines, airports) — what gets added / removed from your diversity counts

This makes Apply less nervous — you immediately see whether the change shifts your top-line statistics noticeably or is purely cosmetic.

Default is propose, don’t overwrite, because:

  • API data isn’t always correct — Aviationstack has been observed swapping aircraft on codeshare flights
  • Manual edits (“I was in Premium Economy, the system says Economy”) shouldn’t be silently overwritten
  • Historical enrichment is heuristic, not ground truth

If you want auto-apply, you can set per-source confidence thresholds (roadmap; currently code-only configuration).

The dashboard only uses these endpoints — you can talk to them directly, e.g. to script Apply:

Terminal window
TOKEN="$(cat ~/.travstats-token)"
BASE="https://travstats.example.com/api/v1"
# List pending updates
curl -fsS -H "Authorization: Bearer $TOKEN" \
"$BASE/pending-updates?status=pending"
# Apply one
curl -fsS -X POST -H "Authorization: Bearer $TOKEN" \
"$BASE/pending-updates/<id>/apply"
# Reject
curl -fsS -X POST -H "Authorization: Bearer $TOKEN" \
"$BASE/pending-updates/<id>/reject"
# Edit (change preview fields, then Apply via separate call)
curl -fsS -X PUT -H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"editedData":{"aircraft":"Airbus A321neo"}}' \
"$BASE/pending-updates/<id>"

Full endpoint list: REST API → Pending Updates.

Pending updates clean up after themselves:

  • Expired — automatically after 24 h or flight end
  • Applied / Rejected are kept with their status so the dashboard’s aggregate counters stay meaningful
  • Cleanup job runs daily and deletes updates older than 90 days regardless of status

If you ever want to reset the dashboard entirely:

docker exec -i travstats-db psql -U flights flights -c \
"DELETE FROM pending_flight_updates WHERE userId = '<user-id>'"
docker exec -i travstats-db psql -U flights flights -c \
"DELETE FROM pending_update_statistics WHERE userId = '<user-id>'"

(That deletes only the proposals — your flight data is untouched.)

  • No bulk apply. Each update has to be confirmed individually. Mass-apply by filter is on the roadmap
  • No 3-way diff merge. If you manually edit the flight between two API polls, the next pending update sees the current state as originalData, not the previous one — that’s almost always what you want, but can occasionally surprise you
  • The statistics impact is a preview, not a lock. If other achievement / statistics computations run between preview and apply (rare, but possible during heavy activity), the actual delta may shift slightly