Changelog

Stay up to date with the latest updates, features, and improvements.

Get every release delivered

vAMSYS v5.4.6

What's new

  • Slotted Events — departure-slot booking for events (launching in beta)

    A new activity type for running structured flyouts and delivery events. Instead of every pilot trying to depart at once, you publish a grid of departure times organised into Waves, and each pilot reserves a slot — reserving is their event registration, so there's no separate sign-up step. Waves can unlock progressively (immediately, once the previous wave fills, or at a set time), and slots are tracked separately per network, so the same 09:00 departure can be held by one pilot on VATSIM and another on IVAO. On the day, the pilot dispatches from the event page straight into the normal Dispatch flow, with their reserved callsign and network locked in. Set it all up from a new Slotted Events tab in Orwell. We're launching this in beta capacity — expect us to be watching closely and ironing out rough edges quickly in the days after release.

  • Fresh activity window for returning pilots

    When a pilot leaves and rejoins your Virtual Airline, you can now give them a fresh initial-activity window — exactly as if they were a new joiner — without changing their join date, stats, history or pilot number. This fixes the long-standing trap where a rejoining pilot would land back on the roster already past their activity window and get removed again the next night, with no way to tell why. When the window is reset, both the removal deadline and the activity reminder re-arm from the day the pilot returns. This applies to self-service rejoins and to staff restores alike. The new controls:

    • Reset Initial Activity Window on Rejoin — a toggle in Settings → Registration Settings (under your Rejoining options). Off by default, and only shown when Rejoining is enabled.

    • Returning Pilot Email — alongside it, choose what a returning pilot is emailed: Use the new-pilot welcome email (your existing one), or Use a separate returning-pilot email.

    • Returning-pilot email template — if you pick the separate option, write its own subject and content under Settings → Registration Emails. Leave it blank and no email is sent.

    • Restore action options — restoring a removed pilot in Orwell now offers a matching Reset initial activity window toggle (defaulting to your airline setting) and a Notify pilot by email toggle. Staff restores were previously silent, so this is the first time a restore can tell the pilot they're back.

  • A quick connection test

    Pilots will have seen a short invite on their dashboard to run a one-minute connection test from the browser. This is a temporary measurement exercise to help us understand connection quality around the world .

What's improved

  • One active booking per route

    You can now only hold one active booking for a given route at a time. Trying to book a route you've already got open is blocked. We also closed a related case where switching Virtual Airline mid-dispatch could create a booking under the wrong airline.

  • No more duplicate PIREPs or claims

    Double-submitting a flight report, or a tracker retrying after a dropped connection, could previously file the same flight twice or claim the same booking twice. Filing and claiming are now race-safe: a booking can only ever hold one active PIREP, and a retry returns a clear "already filed" or "already claimed" response instead of quietly creating a duplicate.

  • Clearer PIREP review with Submit & Decide

    Staff landing-rate decisions are now made on a single Submit & Decide panel (Reprocess, Accept, Reject or Invalidate). A decision made while a PIREP is still reprocessing is now applied safely once reprocessing finishes, instead of clashing with it — closing a race that could leave a PIREP in an inconsistent state. PIREPs that staff have already actioned no longer get re-flagged for review.

  • Alternate Finder no longer hides airports with old or missing weather

    Previously, any candidate airport whose weather was more than a few hours old — or that had no recent report at all — was silently dropped from the Alternate Finder, so viable diversion airports simply didn't appear. The finder now always lists the airport and shows its last known weather with a clear label ("Stale" with an age, or "No recent weather"), leaving the judgement to you. Relatedly, the booking page no longer blanks out a METAR once it's a couple of hours old — it shows the latest available observation.

  • Global weather data flowing again

    Fixed the upstream feeds that meant METAR and TAF data had stopped updating for many airports. Weather across the platform is being populated reliably again.

  • Operations API: older integrations no longer rejected

    Fixed a case where integrations built on older API clients could be unexpectedly rejected when their access token refreshed, despite nothing changing on their end.

  • Faster across the board

    The leaderboard year selector now loads roughly 250× faster, and a round of query work has sped up route creation, event filters, auto-reject rule editing, the hubs API, activity editing, the book-a-flight map and the flight generator. Behind the scenes we also rebuilt how flight position data is stored, reclaiming hundreds of gigabytes while keeping the live map fast as flight history keeps growing.

  • Saved OFP PDFs now kept for 90 days

    Downloadable OFP PDFs are now removed 90 days after a flight. Your flight history and PIREP details are kept in full — only the saved PDF for older flights is no longer available to re-download.

What's fixed

  • Flights with an incorrectly formatted alternate airport could silently fail to generate an OFP, leaving you with no flight plan and no error — alternates are now cleaned and validated so SimBrief planning works reliably

  • The connected-apps page (Your Apps) erroring for some users

  • Saving a route occasionally crashing, and switching Virtual Airline in another tab leaving you editing under the wrong airline

  • A malformed pagination cursor on Operations API list endpoints returning a server error instead of a clear validation message

  • Invalid filter values on the Operations API PIREPs endpoint returning a server error instead of a clear validation message


⚠️ Operations API breaking change

To comply with Planespotters' terms, aircraft image fields on the live flight-map endpoint now return null when the photo is sourced from Planespotters. If your integration reads aircraft photos from this endpoint, expect null values for Planespotters-sourced images — airline-uploaded images are unaffected. The Phoenix flight map and Pegasus continue to show these photos with attribution, so pilots see no change.

vAMSYS v5.4.5

What's new

  • Automatic invalidation of PIREPs awaiting a pilot reply

    PIREPs flagged as needing a pilot reply are now automatically invalidated when the pilot doesn't respond within your airline's reply window - a new setting on the PIREP Settings page in Orwell (PIREP Review section), configurable from 0 to 365 days and defaulting to 7. Auto-invalidation runs nightly, writes a clear entry to the PIREP's action log, and immediately unblocks the pilot from booking. Note: the first run after this release will clear out the existing platform-wide backlog of long-stale need-reply PIREPs.

  • Pending PIREPs no longer shield pilots from activity checks forever

    Previously, a pilot with any pending PIREP was exempt from activity-requirement removal indefinitely - creating roster entries that could neither fly (blocked by the need-reply check) nor be removed. The exemption is now bounded by the reply window plus your activity grace period, and the initial-activity check re-checks recently deferred pilots daily instead of only once on their exact Nth day. Pilots who previously escaped the initial check are grandfathered - there is no retroactive removal sweep.

  • Community Goal & Challenge outcome badges

    Badges can now be tied to community activity outcomes directly from the badge form. Two new rule blocks join the existing Event Participation rule:

    • Community – Completed / Won — on goals, awarded to every participant when the goal is achieved; on challenges, to every contributor on the winning team.

    • Community – Top 10% Contributors — awarded to the top 10% of contributors at activity end (on challenges, within the winning team), mirroring the activity-side tier badge exactly.

  • Both are evaluated when the activity's rewards are distributed, with helper text spelling out exactly who gets what. The same rule types are also available via the Operations API badge endpoints.

  • Badge selects on Community Goal & Challenge forms

    The Participation, Completion and Top 10% Contributors badge selects are now available directly on the Community Goal and Challenge create/edit forms in Orwell. Badges can be attached from whichever side suits your workflow — per-pilot de-duplication prevents double awards if both are set.

    Challenges now have a Winner Badge select, and the badge is awarded to every contributor on the winning team when rewards are distributed (provided the winning team reached its target). The field was previously settable via the Operations API but was never actually awarded.

  • Callsign generator validation everywhere

    Invalid callsign generator strings are now rejected at every intake point - the route importer, the Orwell route form, and airline-level route creation defaults - instead of being accepted and then failing at generation time. The generate-callsign button on the dispatch and booking pages now only appears when the route's generator is actually valid.

What's improved

  • One pilot ID, one pilot — enforced

    Concurrent registration approvals could race and hand two pilots the same pilot ID, or create duplicate pilots for the same user. Username allocation is now serialised per airline, approvals atomically claim the registration, and a database-level unique constraint on active pilot usernames backs it all up - with existing duplicates repaired as part of the rollout. Rejoining pilots can still reclaim their old number.

  • Orwell & Phoenix performance

    A round of query work across the platform: the Orwell pilot list statistics now use the airline index instead of scanning all PIREP analytics, the leaderboard year list is cached, the booking flight map no longer repeats expensive lookups, the shared cockpit pilot list no longer runs a query per friend, route maps no longer run a query per airway, and the rosters generator gained a dedicated index.

  • SimBrief saved airframes re-sync properly

    Saved airframes previously synced exactly once per user, ever - a stuck throttle meant a new airframe could take weeks to appear. Airframes now re-sync hourly, a failed fetch retries instead of locking, and opening the favourite-aircraft page in Phoenix triggers a sync. Relatedly, the airframe sync no longer rewrites every profile on every dispatch page load.

  • Dispatch survives broadcast outages

    SimBrief OFP notifications now broadcast via the queue, so a realtime-server outage no longer crashes dispatch or SimBrief imports. Broadcast connections now have proper timeouts so requests can't hang indefinitely.

  • More robust live flight tracking

    Flights now leave the live flight list as soon as their PIREP is filed, bulk updates to historical bookings (notably "Reset my account") can no longer resurrect years-old flights onto the live map, and position report cleanup is now atomic.

  • More resilient Discord notifications

    A single failed Discord send (rate limit, outage, timeout) previously disabled an airline's entire Discord integration until staff re-saved their settings, and the announcement was lost. Transient errors now simply retry on the next run, a deleted channel only clears that one channel setting, and only a deleted server (or kicked bot) disables the integration.

  • Operations API: removed pilots and past bookings now resolvable

    GET /pilots/{id} and GET /bookings/{id} now return removed pilots and completed/cancelled bookings instead of a 404 (matching what the list endpoints already showed), GET /registrations/{id} now genuinely resolves processed registrations for airline-restricted clients, and removed pilots can now be banned via POST /pilots/{id}/ban.

  • Operations API: stricter PIREP update validation

    PUT /pireps/{id}/times previously accepted empty or partial bodies and silently nulled any omitted time fields - a data-loss trap. All four time fields are now required, and missing fields return a 422. POST /pireps/{id}/select-landing likewise now rejects a missing touchdown_index.

What's fixed

Phoenix & dispatch

  • Pilots who switched Virtual Airline mid-dispatch could book another airline's route under the wrong airline, with the PIREP following the bad booking - the dispatch and booking pages now validate everything more robustly against the active Virtual Airline

  • Phoenix dashboard crashing for all viewers when a live flight referenced a deleted position report - the phase now shows "Unknown" instead

  • Saved SimBrief map type ("Advanced Route Map" or "No Map") silently falling back to the default on every new dispatch

  • The manual SimBrief link sending nonsense cargo and baggage weights - small cargo loads were inflated a thousandfold and passenger bag weight was dropped

  • Dispatch crashes for pilots whose browsers report legacy timezone names (e.g. Asia/Saigon), and from stale stacked Time Setter modals

  • Clicking the generate-callsign hint on the booking page throwing an error on routes with broken generator data

  • Attaching a SimBrief OFP via the Pilot API always being rejected with route_mismatch, even when the route matched

  • Fetching the flight profile of an in-progress PIREP via the Pilot API returning a 500

Orwell & staff tools

  • Event Participation badge rules pointed at a Community Goal or Challenge were never awarded - qualifying contributions now award them immediately, and a sweep at reward distribution catches badges created late

  • Tour, Roster and Curated Roster registrations made via the API never tracking progress - PIREPs now count, and unregistering cleans up in-progress logbooks consistently across web and API

  • Events created via the copy action (or weekly auto-replication) never being announced to Discord

  • Saving a Community Goal or Challenge failing with a 500 when an activity webhook was subscribed and event/focus airport webhooks that were silently never delivered now fire

  • The rank transfer message rendering raw Markdown to pilots - bold, lists and paragraphs now display properly (and the content is sanitised)

  • Aircraft photos disappearing from flight maps platform-wide after a photo-provider change

  • Orwell route form crashing on airports without ICAO codes and on non-Latin callsigns

  • Route import not clearing emptied SimBrief fields - an empty cell now clears the override instead of keeping the old value

  • 500 error when filtering the HQ statistics page

  • Duplicate pilot IDs from concurrent registration approvals (see "One pilot ID, one pilot" above)

Billing & OAuth

  • Billing webhook failing when an airline's owner staff record had been removed - receipts now fall back to a sensible address

  • OAuth authorisation showing a generic 500 when an integration sent a non-numeric client ID - it now shows a friendly invalid-client error

Operations API

  • 500 error when creating a callsign parameter, and create/update responses returning stale data

  • 500 error when approving a livery

  • 500 error when assigning containers or load factors to a route

  • 500 error fetching legacy PIREPs without a type - the type field is now nullable and its documented values corrected to what the API actually returns

  • 500 error on GET /statistics/general for clients of deleted airlines

vAMSYS v5.4.4

What's new

  • Bulk hide and unhide aircraft in Phoenix
    Select multiple aircraft in the Orwell aircraft list and hide or unhide them in Phoenix in one go - useful when part of your fleet moves in or out of maintenance. Updates run in the background, so even very large fleets are processed without timeouts.

  • More powerful route export filters
    Route and routing CSV exports can now exclude as well as include. The tag filter has three modes - routes with any selected tag, routes without any selected tag, or completely untagged routes. Route exports can also exclude by internal remarks and filter by visibility (all, visible only, or hidden only).

What's fixed

  • Saving a badge in Orwell admin caused a fatal error on every edit

  • Manual PIREP submission returned a 500 error when the airline's Discord review channel had been deleted - the PIREP was saved correctly, but the pilot saw an error; stale channels now clear themselves automatically

  • Rank, Badge, and Reward Settings forms crashed with a server error when saving very large points or bonus values — these fields now enforce sensible maximums

vAMSYS v5.4.3

What's new

  • APOC Network Support
    Full integration with the APOC (Apocalypse Flyleague) online network, joining VATSIM, IVAO, and POSCON. Pilots can link their APOC CID in social settings, and VA owners can use APOC in network restrictions, activity settings, scorer and OAuth scopes.

  • Activity Repeat-Until Date
    Recurring activities can now have an end date. Once the repeat-until date is reached, the activity stops replicating automatically — no more manually deleting future occurrences.

  • 2-1-3 Engine Start Sequence Scoring
    New scoring rule for 3-engine aircraft that awards correct centre-first engine start sequence (engine 2, then 1, then 3). Available as a selectable option in Orwell scoring group configuration.

What's improved

  • Activity Listing Filters
    Activity type tabs now filter to current activities by default. A new Personal Roster tab separates pilot-created roster items from VA-planned events, and the "All" tab has been renamed to "VA All" for clarity.

  • SimBrief Plan Format Priority
    Plan format selection now correctly follows the full override chain: Pilot preference, Aircraft, Fleet, then Airline default. Previously, aircraft and fleet-level overrides were skipped.

  • Account Deletion Messaging
    Replaced internal terminology with clear, user-friendly messaging when accounts are deleted — now explains what happened and provides links to VA and vAMSYS support.

  • Featurebase feedback widget replaced with the in-house vAMSYS Feedback system across the entire platform

What's fixed

  • Landing Distance Available calculation using full runway length instead of usable landing distance, overstating remaining runway on touchdown analysis

  • Runway profile graphic incorrectly inflating the rendered runway length by double-counting displaced thresholds

  • Destination map showing expired and future-dated routes that should not be available for booking

  • Booking page METAR display using wrong data field

  • Flight map failing when airport has no ICAO code

  • Network IDs not being transferred when merging duplicate user accounts

  • Dashboard booking and PIREP summary box items not aligning correctly

  • Marketing subscriber export including pilots with deleted user accounts

  • Activity restrictions not parsing network and landing rate settings correctly in the API

  • Recurring events re-sending Discord notifications on each replication

  • Activity sidebar allowing title without content and vice versa

  • Non-numeric PIREP filter values causing server errors instead of returning empty results

  • Webhook documentation Node.js example using re-encoded body for signature verification

vAMSYS v5.4.2

Internal refactoring, query improvements and other back-end work.

For latest substantive changes see vAMSYS 5.4.1 changelog

vAMSYS v5.4.1

What's new

  • Configurable Dashboard PIREP/Booking Boxes
    VA owners can now choose which data fields appear in PIREP and Booking summary boxes on the Phoenix dashboard. Pick from fields like flight time, landing rate, landing G, aircraft, fleet, network and more — all configurable from the Dashboard Builder in Orwell.

What's improved

  • Community Goal Percentile Accuracy
    Percentile calculation for community goals has been corrected - rank 1 now properly qualifies for the top 10% tier instead of being miscalculated. Tier thresholds have been unified across all community goal features for consistent results.

  • Selected Engine Taxi-In Scoring
    Multi-engine taxi-in scoring no longer falsely rejects valid procedures where the first selected engine shuts down slightly before on-blocks while the last engine shuts down at on-blocks.

  • Auth Page Security Hardening
    Airline login and registration pages have been hardened against crafted requests.

What's fixed

  • Personal rosters from Flight Generator appearing in Orwell's activities listing alongside VA-planned events

  • Flight booking filter options not refreshing after jumpseating to a new airport

  • Errors when viewing orphaned pilot accounts without linked users

  • SimBrief fuel configuration failing when airframe fuel options are incomplete

  • Curated roster sidebar entries appearing when no entries are visible to the pilot

  • Incorrect registration count shown on curated rosters listing page

  • Airport exporter load factor queries failing

  • Tour point updates failing when restrictions are not set

  • Stripe API failures causing crash instead of failing gracefully

  • Badge creation failing when bonus points percentage option is not set

  • Fixed gear aircraft (e.g. C208 Caravan) being auto-rejected for "gear up landing" when gear state cannot be determined

  • PIREP point values overflowing when extremely large values are saved

  • Scoring rules overview not sortable by group count column

  • Route tag suggestions query failing

  • Infinite recursion when loading activity completions

  • Mail preview failing when email content is missing

  • PIREP landing rate filter applying incorrectly

  • Operations API not returning accepted or rejected registrations when filtering by status

  • Touchdown data values not being cast to their correct types from the API

  • OAuth request logs failing when URL or user agent exceeds column length

  • OAuth authorization failing on non-numeric client IDs instead of returning a proper error

  • Deleted user accounts causing errors on registration lookups - now shows "Deleted User"

  • Socket-based page refresh failing when airline context is missing

vAMSYS v5.4.0

vAMSYS 5.4 is a major 5.0 release introducing the Pilot API, Pilot Passport, personal rosters, bonus points system changes, activity flight type exclusions, hot weather scoring exemptions, new autoreject rules, and significant performance improvements across the platform.

What's new

Some items are Launch Only

Some changelog items, even if configured in Beta environment, will not take effect until 5.4 is out to public release - 16th March at the earliest. For example:

  • Generated Roster Leg tracking
  • Staff Bonus Points
  • New Scorers/Autorejects
  • Activity requirement changes
    will work only when 5.4 launches

Pilot API

A brand-new OAuth PKCE API for third-party pilot-facing applications. Developers can build apps that authenticate pilots and access their data within the context of a specific Virtual Airline. The Pilot API offers over 40 endpoints across 10 granular scopes, covering:

  • Profile & Identity — pilot profile, rank, statistics, statistics breakdown, badges, holidays, preferences, location, and hub.

  • Bookings & Dispatch — list, create, and cancel bookings; generate dispatch URLs; link SimBrief OFPs.

  • PIREPs — browse flight history, view position reports and flight profiles, read and post comments.

  • Manual PIREP Claims — submit, view, and delete manual flight claims.

  • Activities & Rosters — register for activities, track progress, manage personal rosters.

  • Favourites & NOTAMs — toggle favourite aircraft and airports, browse and acknowledge NOTAMs.

Full OpenAPI documentation is auto-generated and available via the Scalar documentation viewer. OAuth clients are created and managed in Orwell.

Personal Rosters & My Rosters

Pilots can now save generated rosters from the Flight Generator as personal rosters. Personal rosters require a minimum of two legs and appear on the new My Rosters page alongside any registered curated rosters. Each roster includes progress tracking with real-time updates, dispatch integration for booking individual legs, and an interactive map showing the full route.

Registering for a curated roster now also adds it to My Rosters, giving pilots a single unified view of all their active rosters. Pilots can unregister from curated rosters directly from this page.

Bonus Points

Three new bonus scoring tiers can be applied to PIREPs, each configurable as fixed points or a percentage of the base PIREP score:

  • Staff Bonus — bonus points awarded on every PIREP filed by a staff member. Configured in PIREP & Reward Settings.

  • Badge Bonus — per-badge bonus points awarded on PIREPs when the pilot holds that badge. Configured on each badge individually.

  • Airport Manager Bonus — the existing Airport Manager bonus now supports percentage mode alongside fixed points.

All bonus types support custom display names.

Activity Flight Type Exclusions

Staff can now exclude specific flight types from pilot activity requirement checks. Excluded flight types do not count towards or against activity thresholds for both initial and ongoing requirements. Configure this in Orwell under Settings > Activity Requirements.

Hot Weather Flap Exemption

Parking flap scoring rules (Flaps Retracted Before Parking / Flaps Not Retracted Before Parking) now support a hot weather exemption. When the arrival airport temperature exceeds a threshold (determined from METAR data within 6 hours of arrival), an alternative flap range can be accepted. This prevents pilots from being penalised for leaving flaps extended in hot weather conditions. Configurable per scoring rule with minimum/maximum flap positions and optional bonus points.

Phoenix Dashboard Hide/Show Toggle

Each Phoenix Dashboard component now has a hidden toggle. Hidden components preserve all their configuration (size, position, settings) and can be quickly toggled back without re-entering settings. This makes it easy to seasonally enable or disable dashboard sections.

Flight Time on Activity Cards

Activity cards in Phoenix now display estimated flight time information. Tours and rosters show the total flight time, while airport-based events show a time range. This helps pilots gauge the time commitment before joining an activity.

Operations API Enhancements

  • OAuth Scopes — five granular scopes for Client Credentials tokens, allowing read-only tokens safe for public use. Fully backwards-compatible — existing tokens continue to work without changes.

  • See the separate Operations API changelog entry for full technical details including breaking changes.

Route Tag Review Autoreject

A new autoreject rule lets staff configure specific route tags (such as Exam or Checkflight) that automatically trigger PIREP rejection when a pilot flies a tagged route. Tags are configured per rule in the AutoReject Rules settings.

Engine Start Sequence Autoreject

Airlines can now automatically reject or flag PIREPs for review when engines are started in the wrong order. Configure the required start sequence (Engine 1–4) and set fleet-specific overrides for aircraft types that require different start orders. Uses the same violation detection as the existing Engine Start Sequence scoring rule. The required sequence is displayed to pilots on the Scores page.

Pilot Passport

A new section on pilot profiles that tracks every airport and country visited across your flights. See your exploration progress with country and airport completion percentages, per-country progress bars, and detailed airport visit histories including visit counts and first/last visit dates. Countries where all route network airports have been visited earn a gold star. Airports you have visited that are later removed from the route network are preserved as historical stamps — your visits are permanent.

What's improved

  • Curated Roster enhancements — curated rosters now support optional completion points (fixed or percentage), fleet-type-per-leg selection as an alternative to specifying individual aircraft, and points-as-percentage mode.

  • Roster name overrides — customise the "My Rosters" label, roster generator label, and roster type labels to match your Virtual Airline's terminology.

  • Orwell Profile link — staff can access Orwell pilot profiles directly from the Phoenix pilot profile page.

  • Dispatch information — callsign and flight number are now displayed in dispatch route information.

  • PIREP weight — all displayed flight counts throughout Phoenix now respect the pirep weight setting used during Transfer/Manual PIREP creation.

  • SimBrief OFP from booking detail — pilots can generate a SimBrief OFP directly from the booking detail page without returning to the dispatch screen.

  • Pilot search in Orwell — staff can now search for pilots by real name (in addition to username) across all pilot selection fields, including the Award Badge modal, Holiday management, Rank assignments, and Pilot Notes.

  • Dispatch Table columns — column visibility is now controlled entirely by the airline's dispatch box settings in Orwell. The pilot-facing column toggle has been removed for a cleaner, consistent experience.

What's fixed

  • Duplicate pilot accounts being created by repeated restore operations

  • ICAO/IATA airport lookup failing for lowercase input in route creation

  • Null flight distance on non-jumpseat routes — existing affected routes have been backfilled

  • Integer overflow when creating PIREPs through pilot invite with very large values

  • Leaderboard rank position mismatch in the My Position panel — deleted pilots and the system user are now excluded from ranking calculations

  • Route bulk actions could process an unlimited number of records — now capped at 500 and converted to batch SQL for reliability

  • Missing pirep_analytics_count column in Ranks pilot list

  • OpenAPI specification type mismatches causing documentation viewer errors

  • Hidden filter not working correctly in Fleet and Aircraft lists

  • API 500 errors caused by Spatie Data structure caching

  • Flight length arrival time calculation producing incorrect values

  • Various N+1 query issues: activity detail page reduced from 170+ to approximately 80 queries, with fixes also applied to the events listing and tour/roster tables

  • Hidden aircraft could be booked via pilot favourites, bypassing the visibility filter

  • Map sprite and glyph assets pointing to external URLs that intermittently failed — now self-hosted

  • Create Booking button becoming permanently disabled after form validation failure (e.g., passenger count exceeding maximum), requiring a page reload

  • Orwell edit pages crashing when a record was deleted while the page was open — users are now redirected to the listing page with a notification

  • Operations API scope enforcement not resolving wildcard tokens against the client's configured allowed scopes

  • Selected Engine Taxi In scorer falsely failing PIREPs when multiple engines were selected — the on-blocks timing check has been removed as it conflicted with multi-engine shutdown sequences

Performance

  • Column selection added to all Operations API index endpoint eager loads, reducing data transfer and query times

  • Covering partial index added for pilot listing by airline

  • Middleware audit: hot paths cached, dead code removed, OAuth logging made asynchronous

  • Three duplicate queries per page load eliminated from middleware and layout

vAMSYS v5.4.0-Operations API

This entry covers all changes to the Operations API shipping with vAMSYS 5.4. If you integrate with the Operations API, review the breaking changes section carefully and update your consumers. vAMSYS 5.4 Beta is not due to launch publicly till 16th March at the earliest.

Breaking changes

/routes pagination keys renamed

The GET /routes endpoint previously returned cursor pagination metadata using non-standard keys. These have been renamed to match all other cursor-paginated endpoints:

  • meta.next_page_url → meta.next_cursor_url

  • meta.prev_page_url → meta.prev_cursor_url

Consumers of GET /routes reading these keys must update to the new names. All other cursor-paginated endpoints already used the correct keys and are unaffected.

Viable upgrade path would be to update your various scripts to look for xxx_cursor_url and try to default to xxx_page_url if former is not available; This will make your scripts work with current 5.3 and will not error out when 5.4 goes out.

Action endpoints now wrap responses in data key

The following action endpoints previously returned fields at the root level of the JSON response. They now wrap all fields under a "data" key, consistent with every other endpoint in the API:

  • POST /registrations/{id}/approve and /reject

  • POST /transfers/{id}/approve and /reject

  • POST /ranks/reorder

  • POST /ranks/{id}/pilots/{pilot_id} (honorary rank)

  • POST and DELETE /hubs/{id}/pilots/{pilot_id}

Consumers reading response.message, response.email_sent, response.manual_pirep_queued, response.pilot_id, response.hub_id, or response.rank_id should update to read from response.data.* instead.

What's new

OAuth Scopes

Five opt-in OAuth scopes are now available for Client Credentials tokens. Existing tokens issued without scopes continue to work with full unrestricted access — no action required. New tokens that explicitly request scopes are restricted to matching endpoints only.

  • ops:read — all GET endpoints (fleet, routes, airports, pilots, PIREPs, bookings, statistics, activities, flight map).

  • ops:config:write — create, update, and delete fleet, aircraft, airports, hubs, ranks, badges, routes, parameters, containers, load factors, routings, alerts, and NOTAMs.

  • ops:flights:write — cancel bookings; manage PIREP comments, points, bonus points, need-reply flag, internal notes, times; select landings; manage pilot notes.

  • ops:moderation:write — PIREP accept, reject, and invalidate; pilot banning and deletion; registration and transfer approve/reject.

  • ops:activities:write — create, update, and delete events, tours, rosters, focus airports, community goals, community challenges, and activity registrations.

Scopes are configured per-client in the Orwell API settings panel. A token with only ops:read is safe to embed in client-side JavaScript for public displays. Tokens missing a required scope receive HTTP 403 with error "insufficient_scope".

New response fields

  • Booking responses — new user_route field containing the pilot's custom route string (or null).

Custom URI Schemes for OAuth

OAuth clients can now use custom URI schemes (e.g., myapp://callback) as redirect URIs, enabling native desktop and mobile applications to implement OAuth flows. Plain HTTP remains blocked; HTTPS and any custom scheme are accepted.

CuratedRoster enhancements

POST /rosters and PATCH /rosters/{id} now accept optional points configuration and fleet-level aircraft assignment per leg for CuratedRoster types:

  • Optional points — points, points_as_percentage, time_award_scale, restrictions.award_per_leg, and restrictions.activity_complete fields. Points default to 0 if omitted.

  • Fleet-per-leg — legs[].aircraft_type_id assigns a fleet type instead of a specific aircraft. For CuratedRoster legs, either aircraft_id or aircraft_type_id must be provided (previously aircraft_id was always required).

What's improved

  • All endpoints returning 422 Unprocessable Entity now document validation error responses in the OpenAPI specification.

  • Path parameters are documented with descriptions across all controllers.

  • Column selection added to all index endpoint eager loads, reducing query counts and response times.

What's fixed

  • GET /pireps/{id}/touchdowns returning 500 when the PIREP had no touchdown data.

  • PUT /badges/{id} returning 500 on every request due to an internal data class method error.

  • PATCH /parameters/{id} returning 500 when updating string or array fields.

  • GET /routes with fleet_id filter returning 500 due to an incorrect subquery reference.

  • PUT /ranks/{id} throwing a mass assignment error in certain update scenarios.

  • GET /ranks/{id}/pilots returning an error when pilots existed on the rank.

  • GET and PATCH /pilots/{id}/notes returning 500 due to a computed attribute eager-loading conflict.

  • Scope enforcement not resolving wildcard tokens against the client's configured allowed scopes — wildcard tokens are now properly resolved to the client's actual allowed scopes for per-endpoint enforcement.

  • OAuth Authorize page content being clipped when a client requests many scopes, making the Authorize button unreachable.

vAMSYS v5.3.38

What's improved

  • Automatic cleanup of orphaned transfer records
    Transfer records where the pilot has been deleted are now automatically cleaned up daily, preventing stale data accumulation.

What's fixed

  • Double-clicking the Create Booking button could create duplicate bookings

  • Live flight map ETA always showing as null

  • Community Goal tier calculation mismatch between displayed tier and actual reward tier

  • Reset Map button in Book Flight leaving the map in an unresponsive state

  • Freight and cargo amounts displaying incorrect values for imperial unit users in Community Goals

  • Transfer review page crashing when the transferring pilot has been deleted

  • Bulk PIREP reprocess attempting to process PIREPs without ACARS records

  • Community Goal and Challenge progress components failing to load rank informat

vAMSYS v5.3.37

What's fixed

  • Error when accessing activity logbook for newly registered pilots before their logbook record was created

  • SimBrief airframe sync showing duplicate success notifications when updating multiple airframes

  • Notification panel errors caused by corrupted session data

  • OAuth login failures when client ID was empty

  • Error when generating a new callsign from the booking sidebar

  • Pilot full name not displaying correctly in certain API and export contexts

  • URL validation errors when creating or updating records via API v3

vAMSYS v5.3.36

API Breaking Change

The flight-map endpoint (/api/v3/operations/flight-map) now excludes position reports by default for performance reasons. To include position history, add include_posreps=true to your request.

What's new

  • Preparation work put in place for Pegasus Addon API
    New API for Pegasus to identify addons via our backend API, instead of being hardcoded into Pegasus builds.

What's improved

  • API v3 Performance
    Pilots endpoint with statistics is now 10-25x faster. Flight map endpoint is 5-37x faster with position reports now optional for better performance.

  • Changelog entries now served from vamsys.co.uk and vamsys.io picks up new releases automatically

What's fixed

  • Route filtering on flight distance in Orwell causing invalid database queries

  • Badge selection allowing null badge submissions

  • Version service type error caused by stale cache entries

  • PIREP position reports not displaying on Orwell map

  • Several Dashboard boxes having some undefined widths, which are available for selection in Orwell

  • Aircraft icon URLs not using absolute origin and defaulting to basic icon on flight maps

vAMSYS v5.3.35
  • Added auto-switch airline when visiting airport/aircraft resources by a link (from say Pegasus) when said resource belongs to a different VA than the one you are currently logged into

  • Fix invalidated PIREPs not being aggregated in PIREP Analytics

  • Fixed undefined variable when deleting VA

  • Fixed Type Error in Position Reports API Endpoint

  • Add API v3 automated endpoint tests

vAMSYS v5.3.34
  • Fix Route Importer not recalculating flight length when imported value is empty

  • Fixed unhandled match case when dashboard component width is null

  • Fixed Community Goal rewards applying tier multipliers when tiers_enabled is false

vAMSYS v5.3.33
  • Remove API v2 URL endpoints, controllers and clases; Shut down protocol.vamsys.dev

  • Add API and webhook integration for upcoming Hangar v2

  • Fix PIREP reprocessing crash for older ACARS versions

  • Fix timestamp processing for older PIREPs where SimBrief used to send times in different format

  • Fix booking details validation when callsign editing is disabled

vAMSYS v5.3.32
  • Internal changes to logging in cloudflare worker processing position reports

  • Added Created/Updated date-time fields in Airport Export

  • Fixed Client Credentials grant not returning a token in Operations API documentation when redirect_url is included

  • Added honorary rank ID and whether honorary rank is preferred in Pilot API

  • Added multiple threshold support to Multiple Flights scorer

vAMSYS v5.3.31
  • Fixed Phoenix Flight List showing current time instead of Actual Departure time in certain scenarios

  • Added bidirectional route/aircraft filter in Roster/Curated Roster create/edit form in Orwell

  • Fixed Clock dropdown being invisible in Orwell in Safari

  • Added an option to hide aircraft from booking, lists and so on in Phoenix via toggle in Aircraft create/edit in Orwell

  • Added individual sortable start/end datetime columns in Orwell Routes table

  • Importers will now skip validation when it is asked to delete entries

vAMSYS v5.3.30
  • Fixed CommunityGoal flight time progress not updating when PIREPs filed

  • Improved Phoenix UI → PIREP View; Hid the link to Orwell Activity edit

  • Fixed live flight metrics not purging cache and not storing 0 values when there are no flight, making it seem there is always at least one live flight

  • Fixed some errors in Position Report API

  • Fixed undefined array key error in PIREP comment actions by hiding submit button for offsite appeals

vAMSYS v5.3.29

Refactored Phoenix PIREP view to modular panel architecture as used in Orwell

Other changes and fixes:

  • Fixed violation count PIREP evaluator for Community Goals/Challenges

  • Fixed some array to string conversions in Fleet API

  • Fixed orphaned transfers from pilots or users who no longer exist

  • Converted Next Departures from preset view to toggle button in Dispatch table

  • Fixed runway exit direction inversion in Runway Profile visualization

vAMSYS v5.3.28

Bugfix edition

  • Fix fuel used calculation to use takeoff fuel instead of ramp fuel in Orwell PIREP Review

  • Fix dashboard map bounds fitting for distant flights

  • Fix flight_time community goals to track seconds instead of floored hours

  • Fix for bonus point update in API

  • Fix community goals flight_time display to convert seconds to hours

  • Delay dispatch deletion by 5 minutes to prevent 404 errors

  • Filter out hidden routes on Event activity type pages

  • Fix Has Diversion flag for when diverting to departure airport

vAMSYS v5.3.27

Orwell → PIREP Review Rewrite

[Image: ]

Full overhaul of how Orwell PIREP Review page works and looks; We hope you will find it easier to read, information more clearly presented - and the actions you need to perform - conveniently located.

After a short initial test with VA Ownerss/Staff - similar layout and features will be rolled out to Phoenix PIREP View as well so Pilots can enjoy them too.

Other Fixes and Changes:

  • With local times enabled, Departure and Arrival times will sort according to local time, not UTC

  • Fixed an error when deleting an autoreject, which was already deleted

  • Improved Stabilized approach scorer event tracking to ignore events after landing

  • Fixed an error in Community Challenge team page when filtering by airports

  • Further attempts to fix point awarding API v3