Back to changelog

vAMSYS 5.4.0-Operations API

Beta

These API changes are currently in beta. You can test against the beta environment at beta.vamsys.io. Additional changes may be added before the final release.

Beta Access:

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).

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.

Don't miss the next one

Subscribe and we'll email you when we ship.

Unsubscribe anytime.