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.
How a pending update is created
Section titled “How a pending update is created”Three sources produce proposals:
Live API auto-update
Section titled “Live API auto-update”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.
Historical enrichment
Section titled “Historical enrichment”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.
Re-import / re-parse
Section titled “Re-import / re-parse”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 databaseproposedData— what the source suggestschanges— per-field diff with typeadded/removed/changedapiSource— which source proposed it (airlabs,aviationstack,opensky,historical_enrichment,re_parse)statisticsImpact— preview of how distance / flight time / top-K change if you applyexpiresAt— pending updates auto-expire after 24 h (or after flight end, whichever is later) so the dashboard doesn’t fill up endlessly
The dashboard
Section titled “The dashboard”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:
| Action | What happens |
|---|---|
| Apply | proposedData is written to the flight, all derived fields (distance, duration, country) recompute, achievements re-check |
| Edit & Apply | You edit fields in the update before applying (e.g. the API has the gate but you know the right terminal) |
| Reject | The 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) |
The statistics impact preview
Section titled “The statistics impact preview”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.
Why no auto-apply?
Section titled “Why no auto-apply?”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).
Programmatic API
Section titled “Programmatic API”The dashboard only uses these endpoints — you can talk to them directly, e.g. to script Apply:
TOKEN="$(cat ~/.travstats-token)"BASE="https://travstats.example.com/api/v1"
# List pending updatescurl -fsS -H "Authorization: Bearer $TOKEN" \ "$BASE/pending-updates?status=pending"
# Apply onecurl -fsS -X POST -H "Authorization: Bearer $TOKEN" \ "$BASE/pending-updates/<id>/apply"
# Rejectcurl -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.
Cleanup
Section titled “Cleanup”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.)
Limitations
Section titled “Limitations”- 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