Aircraft
Role names and
user_group_idvalues are listed in User groups.
Aircraft manager
Aircraft.ManagerIds names the aircraft's managers: the people responsible for that tail. An aircraft may name any number of them, including none, and they are peers — there is no primary manager and no ordering. The rule is per aircraft and independent of user_group_id — a Captain (180), a Pilot (190) or a Student Pilot (200) named on a tail gets the same authority over it as a Company Administrator, and none at all over any other aircraft.
Changed September 2026. This used to be a single
Aircraft.user_idcolumn. That field is gone from every aircraft payload; readAircraft.ManagerIds(ids) orManager(ids with names) instead, and never assume there is exactly one.
Two shared checks decide it (AircraftManagerPolicy server-side):
canEditAircraft
user_group_id in 1, 100, 105, 110, 150, 300, or any manager of the aircraft
aircraft/edit, aircraft/photo, aircraft/removePhoto, Mass & Balance aircraft profile
canManageAircraft
user_group_id in 1, 100, 105, 110, 300, or any manager of the aircraft
Maintenance Jobs create / edit / sign / duplicate / delete / link, Aircraft Reports MEL/CDL create, edit, extend and delete
A call aimed at an aircraft the caller neither manages nor covers by group answers 404, not 403 — the record is treated as not existing for that caller.
Two further endpoints follow the same rule:
GET /aircraft/my_aircraft.json— the aircraft this user manages. Clients use it to decide which per-aircraft actions to offer.GET /schedules/manager_index.json— a caller aboveuser_group_id170 (and not 300) is admitted only when they manage at least one aircraft, and the board returned holds only those aircraft.
Changing the manager list is staff-only: aircraft/edit silently drops the whole Manager key, plus Aircraft.company_id, Aircraft.active and Aircraft.deleted, from a request made by someone who is only there because they manage the tail. Otherwise a manager could drop the other managers of their own aeroplane, or add themselves to one they do not manage.
Reading and writing the list
Read (ids)
Aircraft.ManagerIds — e.g. ["17","204"]. Sent to user_group_id < 171 and to 300; omitted for everyone else.
Read (with names)
Manager — an array of { id, UserDetail: { name, surname } }.
Write
data[Manager][Manager][]=<user id>, repeated once per manager. Staff only.
Clear
post one empty value: data[Manager][Manager][]=. The aircraft then has no manager.
Leave unchanged
omit the Manager key entirely. A client that knows nothing about managers cannot wipe the list.
Posted ids are intersected with the active users of the caller's own company, so an id from another company or a deactivated account is dropped silently rather than rejecting the save. Deliberately not restricted by user_group_id: the person running a tail may be of any rank, including a third-party owner who does not fly for the school.
List Aircraft
GET /aircraft/index.json
Retrieve the fleet list. Pilots (user_group_id > 170 — Captain and below) see only active aircraft. Managers see all non-deleted aircraft.
Named Parameters
active
active:true
Filter by active status (true or false). Ignored for pilot-level users.
search
search:C172
Filter by registration or model name (partial match)
base_id
base_id:{uuid}
Filter aircraft assigned to a specific base
Response
Aircraft.hoursandAircraft.landingsare the running totals from the aircraft logbook (decimal hours string and integer count).Aircraft.log_referenceis a Unix timestamp of the last logbook entry.AircraftLogReference.total_time/landingsare the baseline reference values (oftennullor0.000when no reference has been set).Userisnullwhen no default pilot is assigned.
My Aircraft
GET /aircraft/my_aircraft.json
Retrieve the aircraft the authenticated user is a manager of, within the current company. Returns an empty list for a user who manages none. Retired (active: false) aircraft are included — a manager keeps access to a parked aeroplane's history — deleted ones are not.
Response
View Aircraft
GET /aircraft/view/{id}.json
Retrieve full details for a single aircraft, including maintenance, rates, logbook reference and the flight types the aircraft is attributed to (FlightType, an array of {id, name, color} — empty is the normal case and means the aircraft flies every unrestricted flight type; see Flight-type attributions).
Path Parameters
id
string
Aircraft ID
Response
Maintenance.next
Estimated next maintenance for this aircraft — the same object documented under Maintenance Jobs → Next maintenance forecast, minus the planned wrapper (booked work is already in Maintenance.scheduled).
An aircraft with no maintenance history at all answers with basis: "first_maintenance" — a nominal first check, not a tracked interval. null only when the aircraft cannot be resolved at all. Deployments that predate the forecast answer with a bare unix timestamp instead of the object; clients should accept both, and must treat the value as advisory — it never limits a booking or a flight.
Returned only on a club, premium or unlimited plan.
Expiration Date Fields
All *_exp fields use YYYY-MM-DD format. null means no expiration set.
airworthiness_exp
Airworthiness certificate expiration
insurance_exp
Insurance expiration
radio_exp
Radio station license expiration
weight_exp
Weight & balance check expiration
avionics_exp
Avionics check expiration
registration_exp
Aircraft registration expiration
Aircraft Logbook
GET /aircraft/logbook/{aircraftId}/limit:{limit}/page:{page}.json
Retrieve the aircraft technical logbook with pagination.
Path Parameters
aircraftId
string
Aircraft ID
limit
number
Records per page (default: 10)
page
number
Page number
Response
Export Logbook (XLS)
GET /aircraft/logbook/{aircraftId}/limit:10000/logbook.xls
Download the aircraft logbook as an Excel file. Token passed as query parameter: ?token=<token>
Fuel & Oil Consumptions
GET /aircraft/consumptions/{id}.json
Retrieve monthly average fuel and oil consumption rates. Defaults to last 12 months.
Path Parameters
id
string
Aircraft ID
Query Parameters
months
integer
Optional. Number of months to look back. Range: 1–120. Default: 12
Response
Fleet ADSB Positions
GET /aircraft/adsb.json
Retrieve real-time ADSB positions for all aircraft in the fleet with ADSB transponders configured.
Response
Aircraft ADSB History
GET /aircraft/adsb/{aircraftId}/{start}/{end}.json
Retrieve ADSB position history for a specific aircraft within a date range.
Path Parameters
aircraftId
string
Aircraft ID
start
string
Start date (YYYY-MM-DD)
end
string
End date (YYYY-MM-DD)
Manufacturers
GET /aircraft/manufacturers.json
List all aircraft manufacturers.
Models by Manufacturer
GET /aircraft/model/{manufacturerId}.json?q={search}
Search aircraft models by manufacturer.
Query Parameters
q
string
Search query for model name
Pilot Aircraft Prices
GET /manager/aircraft/pilot_prices/{pilotId}.json
POST /manager/aircraft/pilot_prices/{pilotId}.json
Custom hourly price a pilot is billed for each aircraft. When one exists it replaces the aircraft's default rate and any rate chosen on the flight when a flight is billed to that pilot. Restricted to user_group_id ≤ 130 (Financial Manager and above); any other caller gets 404. The pilot must belong to the caller's company and have billing enabled, otherwise 404.
Path Parameters
pilotId
string
Pilot user ID
GET response
history lists the latest 100 changes to this pilot's custom prices, newest first. old_price is null when a custom price was added and new_price is null when it was removed. changed_by is the manager's name, or null if the user no longer exists. created is a Unix timestamp. Changes made before October 2026 were not recorded, so the history starts empty.
POST request body
prices[{aircraftId}]
number | string
Yes
Custom hourly price for that aircraft. An empty string leaves the aircraft without custom price
The submitted list replaces all of the pilot's custom prices: aircraft not sent, or sent empty, lose their custom price. Each added, changed or removed price is recorded in the history with the caller as author; resubmitting identical values records nothing.
POST response
Create Aircraft
POST /aircraft/add.json
Add a new aircraft to the fleet. Admin access required.
Edit Aircraft
POST /aircraft/edit.json
Update aircraft details. Requires canEditAircraft: user_group_id in 1, 100, 105, 110, 150, 300, or being one of the aircraft's managers. A manager's request has the Manager key and Aircraft.company_id, Aircraft.active and Aircraft.deleted stripped before the save, so the manager list and those three columns can only be changed by staff.
Clocks
Two fields choose which clock drives a computation. Both accept the same vocabulary and are validated: an unknown value answers 400 with a field error under errors.Aircraft.<field> (it used to reach the database and fail with a 500).
btime
Block time (off-blocks → on-blocks)
ftime
Flight time (take-off → landing)
ttime
Tach: abs(tach_end − tach_start) from the readings entered on the flight
htime
Hobbs: abs(hobbs_end − hobbs_start) from the readings entered on the flight
Aircraft.maintenance
string
Clock that advances the airframe hours. htime treats the Hobbs end reading as the airframe's absolute value (see Maintenance Jobs).
Aircraft.billing_timer
string
Clock a flight is billed on when billing is enabled for the aircraft. For ttime and htime a flight missing either reading, or whose readings differ by more than 24 h, is not auto-billed. Only read when Aircraft.billing is 1.
ttime / htime need the matching Aircraft.tach / Aircraft.hobbs timer enabled, otherwise the flight form never collects the readings; the NEO client switches the Hobbs timer on for you when either clock is set to htime.
Flight-type attributions (optional)
The aircraft end of the fleet restriction that flight types own (see Flight Types → Aircraft restriction). The rows are the same rows; only the direction of editing differs, so an empty set is read the flight type's way:
none
The aircraft flies every flight type that itself names no aircraft. It is not grounded.
one or more
Those flight types are restricted to this aircraft (plus whatever other aircraft they name).
FlightType.FlightType[]
array
No
Flight type ids this aircraft is attributed to. When the key is present it replaces the whole set; an empty value detaches the aircraft from every flight type. When the key is absent, existing links are left untouched — so an older client posting an aircraft edit cannot wipe restrictions it knows nothing about.
Ids outside the authenticated company are dropped silently. Detaching the last aircraft from a flight type makes that flight type unrestricted again, which reopens it to the whole fleet — that is the empty-set rule, not a special case.
POST /aircraft/add.json does not accept these: it saves the Aircraft fields alone and would drop the links silently. Attribute the aircraft in a follow-up edit.
Example (form-encoded):
Detach from everything:
Upload Aircraft Photo
POST /aircraft/photo/{id}.json
Upload or replace the aircraft's photo. Requires being the aircraft's assigned manager, or an Admin / Operations Manager role.
Path Parameters
id
string
Aircraft ID
Request Body
Multipart form data, field logo: image file (JPG, PNG or GIF, max 8MB).
Response
Remove Aircraft Photo
POST /aircraft/removePhoto/{id}.json
Clear the aircraft's photo. Requires being the aircraft's assigned manager, or an Admin / Operations Manager role.
Path Parameters
id
string
Aircraft ID
Response
Delete Aircraft
GET /aircraft/delete/{id}.json
Remove an aircraft from the fleet. Admin access required.
Path Parameters
id
string
Aircraft ID
Last updated