-
Notifications
You must be signed in to change notification settings - Fork 22
1. Home
This project implements the MyFlightbook web server. This is where all the heavy lifting occurs - the database interaction, the business logic, account management, and the web service.
The Readme file (in the codebase) has instructions for how to set up an instance of the MyFlightbook server.
MyFlightbook offers a wide variety of web services, exposed by SOAP. (Yeah, remember my rule - no laughing). This is used primarily by the mobile apps; if you have a website and would like to integrate with MyFlightbook, I would strongly prefer that you use oAuth (described below).
Here’s the flow for using the SOAP web service:
- Your app needs an app token that identifies your app. Contact me for an app token.
- The app collects the user’s email/password and calls AuthTokenForUser, or collects their information and calls CreateUser. An authtoken is returned; keep this secure and safe. Ideally, you do NOT store the email/password
- You can then use the authtoken directly to make calls (described below).
Interacting with MyFlightbook via oAuth 2.0
MyFlightbook supports oAuth 2.0. If you have a website and wish to integrate with MyFlightbook, you can create your own credentials.
The flow for oAuth is described below when MyFlightbook is the oAuth server. You can see it in action (with MyFlightbook as the client) if you go to MyFlightbook's website and go to Profile->Preferences and authorize either a social network or cloud storage provider like Dropbox.
- When your app is set up with oAuth, it is given an app ID and an app secret.
- The user clicks on a link in your app to authorize the app to talk to MyFlightbook.
- The user is redirected – via web browser – to MyFlightbook; the URL includes both your app’s ID and a known redirect URL, as well as requested “scopes” (i.e., what permissions it wants, such as “View and update flights, View totals”, etc.)
- MyFlightbook validates that the app ID is known AND that the redirect URL is a known location (to prevent spoofing)
- MyFlightbook requires the user to sign in (or create an account), if they aren’t already, thus authenticating themselves.
- MyFlightbook presents a page to the user asking if it’s OK to grant your app the requested scopes.
- If the user says “yes”, then they are redirected back to the calling website, along with an authorization token in the URL. This token is what says “[Username] has given permission for [App name] to access [User]'s account on MyFlightbook”, but it doesn’t quite yet let you make those calls. After all, since it’s passed in the URL, it can be seen and thus isn't secret. This token has a time limit on it.
- The website now takes that authorization token and makes a server-to-server call to MyFlightbook, passing its App ID AND it’s App Secret AND the authorization token from step 7, along with the redirect_uri and grant_type=authorization_code. The App ID + secret prove to MyFlightbook that you really are the app you claim to be, and the authorization token proves that the user gave permission to your app. MyFlightbook then returns an actual access token, which can be used to make calls to the web service. This, obviously, needs to be safely and securely stored.
- The access token may be time limited (depends on the oAuth server), in which case steps 1-8 need to be periodically repeated. Alternatively, you can use the refreshtoken that is returned and repeat just step 8 to get a new access token. (When submitting a refresh token, you don't need to send the redirect_uri, and you set grant_type to "refresh_token" and pass the refresh token in the "refresh_token" parameter)
- You can now hit the functional endpoints on MyFlightbook, passing the access token from step 8. Some can be GET, most would need to be POST; you’d JSON-encode the relevant parameters and the results come back in JSON format.
###Making a Call Note that all calls MUST be over https. Calls using http will be rejected.
The URL for the actual calls is https://myflightbook.com/logbook/mvc/oAuth/OAuthResource/{methodname}?access_token={token}&..., where "methodname" is the method being called (below) and {token} is the URL-encoded access token returned in step 8 above. I currently also support "json=1" as an additional URL parameter if you want the results in JSON format; otherwise, you will get XML. If you request JSON and also provide a "callback=..." parameter with a non-empty name, then I will return JSONP. You can POST or GET, but due to URL length limitations, Posting is generally preferred.
A POST call is a bit more complicated. The key components are that you need to post a form using standard http forms, and you need to pass the access_token; the access token can be in the URL, or in an "Authorization Bearer=" header.
E.g., here is how you might do a query for totals of flights that contain the text "Angel Flight". Note that the flight query parameter ("fq") is passed containing a JSON-ified version of a flight query. In this example, the access token is passed in the url:
POST https://myflightbook.com/logbook/mvc/oAuth/OAuthResource/totals?access_token=...
...
Content-Type: multipart/form-data; boundary=---------------------------41184676334
-----------------------------41184676334
Content-Disposition: form-data; name="fq"
Content-Type: text/json
{GeneralText:"Angel Flight"}
-----------------------------41184676334--
Note: JSON results sometimes include more data than XML due to the way the Newtonsoft engine serializes objects. However, if the field is NOT present in the WSDL, then it is NOT supported and may disappear at any time.
There is a a web page on the site that goes through all of the above to verify the oAuth process and includes user interface to make many of the calls described below.
There is also a sample that demonstrates how you can use oAuth to integrate into Google Sheets.
You may also find this tutorial helpful.
The list of calls is described here, and the detailed description (WSDL, or "Web Service Description Language") of supported calls is here. Note: only the calls described below are supported; the remainder are deprecated and may disappear over time, or are used internally.
In particular, if you are using oAuth, do NOT call AuthTokenForUser, AuthTokenForUserNew, or RefreshAuthToken. These are reserved for use by the mobile apps, which do not use oAuth, and the authtokens from these calls are not interchangeable with oAuth tokens. If you cannot use oAuth, let me know and if appropriate we can grant access to these calls.
If you are using oAuth, these are accessed via GET or POST using JSON encoded values to send/receive data; if using SOAP, this is all XML. Also, if you are using oAuth, you can ignore the "szAuthToken" value in when calling the endpoint, since the oAuth token is passed as part of the HTTP post headers or as a parameter in the URL (as demonstrated above).
Also, if you are using oAuth, each call requires an oAuth "scope" to be granted in order to use it. The SOAP API does not use scopes; as a result, all calls are available via SOAP.
In the summary below, I denote each call by the common CRUD acronym role - Create, Read, Update, Delete.
| CRUD | Method | Scope | Description | Notes |
|---|---|---|---|---|
| C | AddAircraftForUser | addaircraft | Adds an aircraft to the user's account | You MUST pass in three parameters: (a) a tail number, (b) an instance ID (use 1 for a real aircraft), and (c) a model ID. The Model ID MUST come from the results of a "MakesAndModels" call. The response to this is a list of the user's aircraft (same as AircraftForUser). |
| R | AircraftForUser | readaircraft | Returns a list of the aircraft that the user has in their account | |
| R | MakesAndModels | readaircraft | returns a list of the models of aircraft in the system (necessary in order to create an aircraft) | |
| U | UpdateMaintenanceForAircraftWithFlagsAndNotes | addaircraft | Updates an aircraft (you can’t modify the aircraft per se from the app, you can only update maintenance, modify flags, or add/update notes.) | |
| D | DeleteAircraftForUser | addaircraft | removes an aircraft from the user’s account | Will fail if the aircraft is used in any flights |
So, for example, a common flow here would be to call AircraftForUser to get the user's current aircraft. This provides ID's that are valid to use when creating flights. If the user needs to add a new aircraft, you'd call MakesAndModels to get an up-to-date list of the models in the system and then call AddAircraftForUser to add it to their aircraft list.
| CRUD | Method | Scope | Description | Notes |
|---|---|---|---|---|
| C/U | CommitFlightWithOptions | addflight | Adds or updates a flight | The FlightID determines if it’s an add or update operation. FlightID < 0 = new. This also has a parameter "po" that contains PostingOptions, but PostingOptions is no longer used; you can pass an empty object for this (i.e., JSON "{}") Any properties being uploaded should specify the id of the flight and the id of the property type; see here for a list and description of available property types and into which field for a flight property you should store the value. Also note that the date of flight is a naked date (i.e., no time) and is in local time, but you may only have a date+time object; if so, specify the date-of-flight as if it were a UTC date; the time fields will be ignored. E.g., if the flight was at 8pm Pacific Time on April 3 2024 (=3am on the 4th UTC), you'd pass the date time as 2024-04-03T00:00:00Z |
| R | FlightsWithQueryAndOffset | readflight | Retrieves a specified number of flights, offset by a given offset. | E.g., “give me 30 flights starting at position 61”. This lets you do things like infinite scroll |
| R | FlightPathForFlight, FlightPathForFlightGPX | readflight | Returns the path of the flight (if present) | |
| R | PropertiesForFlight | readflight | Returns the additional flight properties associated with a flight | No longer necessary; FlightsWithQueryAndOffset now includes properties by default |
| R | AvailablePropertyTypesForUser | readflight | Returns the set of possible property types for this user | Result denotes which ones have been previously used by the user, and previous values for text values (e.g., student name) as well. |
| D | DeleteLogbookEntry | addflight | Deletes a flight | |
| D | DeletePropertiesForFlight | addflight | Removes one or more properties from a flight (without deleting the flight itself). | |
| C | CreatePendingFlight | addflight | Creates a flight, adding it to the pending flight list (as opposed to your regular logbook) | Returns a list of the remaining pending flights for the user |
| C/D | CommitPendingFlight | addflight | Commits a pending flight to the logbook, removing it from the list of pending flights | Returns a list of the remaining pending flights for the user |
| R | PendingFlightsForUser | readflight | Retrieves the pending flights for the user. | |
| U | UpdatePendingFlight | addflight | Updates a flight that is in the pending flight list, keying off of the "PendingID" | Returns a list of the remaining pending flights for the user |
| D | DeletePendingFlight | addflight | Deletes a pending flight from the pending flight list, keying off of the "PendingID" | Returns a list of the remaining pending flights for the user |
| CRUD | Method | Scope | Description | Notes |
|---|---|---|---|---|
| R | GetCurrencyForUser | currency | Returns the user’s currency |
| CRUD | Method | Scope | Description | Notes |
|---|---|---|---|---|
| R | TotalsForUserWithQuery | totals | Returns totals for the user. | You can pass a query indicating which flights to include. |
| CRUD | Method | Scope | Description | Notes |
|---|---|---|---|---|
| R | VisitedAirports | visited | Returns a list of airports that the user has recorded in their flights. |
Creating and reading images are not done through the web service.
To create an image, post the image to http://myflightbook.com/logbook/mvc/imageUploadFlightImage for flight images or to http://myflightbook.com/logbook/mvc/UploadAircraftImage for aircraft images. These are POSTs to the respective page and must be secure (https).
They must include the following form parameters:
- "txtAuthToken" - the authtoken (oAuth or webservice) authorizing the upload
- "txtComment" - the comment for the image (optional)
- "imgPicture" - the bytes of the image. MUST include the MIME content-type. This should match what a website would upload with an input tag
- "txtLat"/"txtLon" - the latitude/longitude (flights only, optional, using US formatting - e.g., decimal, period as decimal point, negative for west or south, positive for north or east))
- "idFlight" - the id of the flight (if a flight image); must be owned by the user authorized by the authtoken
- "id" (aircraft only) - if non-zero, then "txtAircraft" (described below) is the aircraftID of the aircraft for which the picture is intended; if zero, then "txtAircraft" is the tail number for the aircraft. When uploading a new aircraft, you will typically use the tail number, but when uploading for an existing aircraft, you will typically use the aircraft ID.
- "txtAircraft" (aircraft only) - either the numeric unique ID for the aircraft (if "id", above, is non-zero) OR the tail number of the aircraft for which the image is intended. The aircraft MUST be found in the user's aircraft list.
To read an image, simply get its URL reference as returned in the flight or aircraft object.
| CRUD | Method | Scope | Description | Notes |
|---|---|---|---|---|
| U | UpdateImageAnnotation | images | Updates the comment for an image. | |
| D | DeleteImage | images | Deletes an image for a flight or aircraft. |
| CRUD | Method | Scope | Description | Notes |
|---|---|---|---|---|
| C/U | AddNamedQueryForUser | namedqueries) | Adds or updates a query for the specified user with a given name. | Add/update is determined by the name for the query; if a named query with the same name already exists, it is updated |
| R | GetNamedQueriesForUser | namedqueries) | Retrieves the named queries for the specified user | |
| D | DeleteNamedQueryForUser | namedqueries | Deletes the named query for the specified users |
There are others, but they are either deprecated or used internally; DO NOT RELY ON THEM.
Below are descriptions for some key objects that get passed back and forth using the web service.
You may often find additional data present, which should be easy to reverse engineer, but you may want to double check with us using the Contact Us link to make sure that it will be supported into the future.
A flight has a set of core fields, described here, that are common across all flights. It also has a "CustomProperties" field which lists a set of additional attributes that can vary from flight to flight and from user to user.
The core fields:
- FlightID The unique identifier in the database for this flight. For new flights, this should be -1.
- Date The date (local) of the flight
- Route The route (departure, arrival, and any en-route airports or navaids) for the flight
- Comment Any remarks (comments) made by the pilot
- AircraftID Integer representing the unique identifier for this specific airframe
- TailNumDisplay A human-readable representation of the aircraft used for the flight. Read-only.
- ModelDisplay A human-readable representation of the model of aircraft used for the flight. Read-only.
- CatClassDisplay A human-readable representation of the category/class of the aircraft used for the flight. Read-only.
- Landings Total number of landings on the flight
- NightLandings Subset of landings that were full-stop night landings
- FullStopLandings Subset of landings that were full-stop landings (day)
- Approaches Number of approaches performed on the flight
- fHoldingProcedures Indicates that holding procedures were performed on the flight
- PrecisionApproaches/NonPrecissionApproaches DEPRECATED; DO NOT USE
- CrossCountry Cross-country time logged for the flight
- Nighttime Night flight time logged for the flight
- IMC Time spent in actual instrument conditions on the flight
- SimulatedIFR Time spent in simulated instrument conditions on the flight
- GroundSim Time spent in a training device/sim
- Dual Time spent receiving instruction
- CFI Time spent giving instruction
- SIC Second-in-command time recorded on the flight
- PIC Pilot-in-command time recorded on the flight
- TotalFlightTime The loggable duration of the flight
- fIsPublic True if the pilot has indicated that details of this flight can be shared with unauthenticated users
- FlightStart/FlightEnd The UTC date+time of the start/end of flight (i.e., first wheels-up to last wheels-down)
- EngineStart/EngineEnd The UTC date+time of engine start and engine stop
- HobbsStart/HobbsEnd The starting/ending hobbs values.
- FlightImages An array of MFBImageInfo image descriptors for the flight
- SendFlightLink A URL to send the flight to someone else for entry into their logbook
- SocialMediaLink A URL to share to a social-media website like Facebook or Twitter
- CFISignatureState None for no signature, Valid for a valid signature, Invalid for an invalid signature.
- CFISignatureDate/CFICertificate/CFIExpiration/CFIEmail/CFIName If the flight is signed, contains the date of the signature, the CFI's certificate, the CFI's certificate expiration, the CFI's email, and the CFI's name (respectively)
- HasDigitizedSignature If true, then the signature is a scribble. Can be viewed by going to myflightbook.com/logbook/public/ViewSig.aspx?id={id of flight}
- CustomProperties The set of properties for the flight. Each property is described by a flightproperty object (described below)
- PropID A unique ID for this property
- FlightID The ID for the flight to which this property is attached
- PropIDType The id of the property type ("CustomPropertytype", see below) for this property
- IntValue/BoolValue/DecValue/DateValue/TextValue Contains the value for the property. For which one to use, see the specific custompropertytype (below)
- PropTypeID Integer representing the unique id of the property.
- Title The display title for the property
- Type One of: cfpInteger, cfpDecimal, cfpBoolean, cfpDate, cfpDateTime, cfpString, or cfpCurrency, indicating that the value is an integer, a decimal, date, date + time, string, or currency (monetary value), respectively.
- SortKey The key for sorting. For example, "Block In" sorts before "Block Out", but you generally want Block Out to sort first because it's chronologically first
- IsFavorite If true, this property has been previously used in other flights by this user, so should be made more prominent
- FormatString When paired with a value from a flight property, indicates how it should be displayed. Put the value where this includes "{0}" field, if present
- Flags A set of bit flags for the property. Best to ignore, but a few bits are useful: 0x00200000 indicates that a decimal is not a time (e.g., "Oil Added" is always decimal, never hours:minutes, 0x02000000 indicates that autocomplete is inappropriate, and 0x04000000 indicates that the value should be all caps
- PreviousValues For text fields, contains a list of previously used values (useful for autocorrect)
A full list and details about custompropertytypes that are currently available can be found here
- TailNumber The aircraft's tail number (i.e., a human-readable identifier)
- AircraftID Integer representing the unique identifier for this specific airframe. While the user interacts with the tail number, all data interactions are based on the AircraftID
- ModelID Integer representing the unique identifier for the aircraft's model. When adding an aircraft to the user's account, this must be populated with the aircraft
- ModelDescription Read-only user-readable description of the aircraft's model. E.g., "C-172 F"
- ModelCommonName Read-only user-readable description of the model, including manufacturer. E.g., "Cessna Skywagon"
- HideFromSelection If true, indicates that this aircraft should generally be culled from view to reduce clutter.
- Version The version of the aircraft. Each edit increments the version.
- InstanceTypeID Indicates whether the aircraft is a real aircraft, uncertified sim (e.g., Microsoft Flight Simulator), FTD, Full Flight SIM (FFS), or ATD. These have the values 1, 2, 3, 4, and 5, respectively
- AircraftImages An array of MFBImageInfo image descriptors for the aircraft
- DefaultImage The value of the ThumbnailFile in the MFBImageInfo that is the preferred image for the aircraft, if any
- PublicNotes Public notes for the aircraft - visible to all pilots with that aircraft in their account
- PrivateNotes Private notes for the aircraft, visible only to this pilot.
- LastVOR, LastAltimeter, LastTransponder, LastELT, LastStatic, LastAnnual Dates representing the most recent of the named inspection.
- Last100, LastOilChange, LastNewEngine Decimal values representing a unitless (could be Hobbs or Tach or other measure) value for the most recent of 100 hour inspection, oil change, or new engine (respectively)
- WidthThumbnail The width for the image, if it's a thumbnail
- HeightThumbnail The height of the image, if it's a thumbnail
- ImageType Can be JPEG, PDF, S3PDF, or S3VideoMP4. A PDF file is a PDF file stored on the MyFlightbook server, an S3PDF is on Amazon S3, and a video file is always on S3
- Comment Any remark for the image
- URLThumbnail A relative URL for the thumbnail of the image. For a video, this is a still
- URLFullImage A relative URL for the full-sized image
- ThumbnailFile The (naked) filename of the file.
- ModelID The unique identifier for the model
- Description A human-readable description of the model (e.g., "Cessna (C-172 S "Skyhawk SP")")
- Attribute The name of the currency. E.g., "ASEL - Passengers"
- Status One of NotCurrent, GettingClose, OK, or NoDate. NotCurrent means this item is...not current. GettingClose and OK both indicate that the item is current, but GettingClose means that the date of expiration is...getting close. NoDate is for currencies where it is not possible to determine the status.
- Value The human-readable status of the currency. E.g., "Expired - 4/22/2017"
- Discrepancy A human-readable description of what needs to be done to regain currency, or other potential qualifying information
- Query The query, if any, that will find the flights that may have contributed to this currency
- AssociatedResourceID - do not use
- CurrencyGroup - Indicates the section of currency. This can grow over time, and is currently one of: FlightExperience for regulatory currencies that are based on the pilot's flying, FlightReview for flight reviews, Aircraft for things like maintenance, Deadline and AircraftDeadline for user-defined deadlines, CustomCurrency for user-defined currencies, Certificates for currencies related to certificates, and Medical for currencies related to medical expiration.
- Description The human-readable name for what is being totaled
- SubDescription Human-readable additional information. For example, with category/class totals, this shows the number of landings in that category/class
- Value - the value of the total
- NumericType One of: Integer, Decimal, Time, and Currency. All of these are, of course, numbers, but this helps with formatting. If the value is "2.0", then if it's Integer it should be displayed as "2", Decimal should be "2.0" (or "2.00" or "2,0", etc., as per the user's locale and preferences), Time should be either the same as decimal or else "2:00", and Currency would be displayed as "$2.00" (or otherwise as appropriate for the user's locale and preferences)
- Group, GroupName For grouped totals, this gives the name ("Group") and the human-readable name ("GroupName") of the group.
This may be the most complicated object to pass back and forth, but is a powerful way to express a query for a subset of flights
- DateRange Dates for matching flights. Can be one of AllTime, YTD, Tailing6Months, Trailing12Months, ThisMonth, PrevMonth, PrevYear, Trailing30, Trailing90, or Custom
- DateMin/DateMax For custom date ranges, specifies the start/end date of the query
- Distance Can be one of AllFlights, LocalOnly, NonLocalOnly. "Local" flights are ones where the route is either "ABC" or "ABC-ABC"
- CatClasses A set of category/class objects representing the category/classes for flights that are requested
- PropertyTypes A set of property types that matching flights must contain
- IsPublic Matches flights that have been publicly shared
- HasLandings Matches flights that have landings
- HasNightLandings Matches flights that have full-stop night landings
- HasFullStopLandings Matches flights that have full-stop day landings
- Hasapproaches Matches flights with instrument approaches
- HasHolds Matches flights where holding procedures were performed
- HasXC Matches flights where cross-country time was recorded
- HasIMC Matches flights where actual IMC time was recorded
- HasSimIMCTime Matches flights where simulated-IMC time was recorded
- HasGroundSim Matches flights where ground-simulator time was recorded
- HasAnyInstrument Matches flights where EITHER actual OR simulated IMC was recorded
- HasNight Matches flights where night flight was recorded
- HasDual Matches flights where dual instruction was received
- Has CFI Matches flights where dual instruction was given
- HasSIC/HasPIC Matches flights where Second-in-command (Pilot-in-command) time (respectively was recorded
- HasTotalTime Matches flights where total flight time was recorded
- IsSigned Matches flights that have been signed
- Generaltext Matches flights that contain specific text. See Tips for searching
- AircraftList Matches flights in the specified set of aircraft (see aircraft object)
- MakeList NOT SUPPORTED
- ModelName Specifies a text search for the model of aircraft used in a flight
- TypeNames Matches flights for which the aircraft models require one of the specified type ratings to fly
- IsComplex/HasFlaps/IsHighPerformance/IsConstantSpeedProp/Isretract/IsTechnicallyAdvanced/IsGlass/IsTailwheel/IsMultiEnginHeli/IsTurbine/IsMotorGlider matches flights in aircraft that are complex, have flaps, are high-performance, have a constant-speed propeller, are retractable gear, are technically advanced airplanes, are glass, are tailwheel, are multi-engine helicopters (respectively), are turbines or jets, or are a motorglider
- EngineType One of AllEngines, Piston, Jet, Turboprop, AnyTurbine, or Electric, indicating the type of engine for matching flights
- HasTelemetry Matches flights with telemetry attached
- HasImages Matches flights that contain telemetry
- AircraftInstanceTypes The types of aircraft (real aircraft, ATD, FTD, etc.) for matching flights
- QueryName (Named queries only) The name for this query
Here’s a simple JSON flight to post using CommitFlightWithOptions:
{
"User": "",
"AircraftID": xxxx,
"FullStopLandings": 2,
"Approaches": 2,
"Landings": 2,
"IMC": 1.00,
"PIC": 1.80,
"TotalFlightTime": 1.80,
"fHoldingProcedures": true,
"Route": "KSFO-EGLL",
"Comment": "New flight",
"Date": "2024-04-02T00:00:00",
"FlightID": -1
}
There are 3 critical fields above:
- User – leave this blank. This will be the internal database username for the authorized user; this gets assigned at the server based on your authtoken
- AircraftID - this is numeric and MUST be the AircraftID from one of the user’s aircraft, as retrieved from AircraftForUser
- FlightID – this is -1 for a new flight.
Post (must be HTTP Post) this with the JSON above in the “le” parameter using the CommitFlightWithOptions call. Note that you also want “json=1” either in the URL or as a parameter if you want JSON back; otherwise, you’ll get XML.
Here’s a slightly more complicated new flight where I’m adding a flight property for solo time:
{
"User": "",
"AircraftID": xxx,
"FullStopLandings": 2,
"Approaches": 2,
"Landings": 2,
"IMC": 1.00,
"PIC": 1.80,
"TotalFlightTime": 1.80,
"fHoldingProcedures": true,
"Route": "KSFO-EGLL",
"Comment": "New flight",
"Date": "2024-04-02T00:00:00",
"FlightID": -1,
"CustomProperties": [{
PropID": -1,
"FlightID": -1,
"PropTypeID": 77,
"DecValue": 1.80,
}
]
}
This is the same as above, but I’m specifying an array of CustomProperties (old naming, but still additional flight properties). Let me walk through the required fields for these:
- PropID – set this to -1 for a new property. This is the ID of the property in the database (properties are in their own table, separate from flights); it will be assigned by the database when it gets saved. Properties can be individually deleted using this ID.
- FlightID – this is the database ID of the flight to which the property is attached. Since the flight itself isn’t yet in the database, we keep this as -1 as well; when we update a flight with an existing property, this will be set and MUST be preserved.
- PropTypeID – this identifies what kind of property it is. 77 is “Solo Time”. You get this from a call to either AvailablePropertyTypesForUser or AvailablePropertyTypes.
- DecValue, TextValue, IntValue, DateValue, or BoolValue – depending on the datatype of property, this contains the value for the property. You only need to provide the relevant field value.
If I now retrieve that flight, here’s the flight I get back (JSON – you can also get XML):
{
"SendFlightLink": https://myflightbook.com/logbook/Member/LogbookNew.aspx?src=dhPfAq0jSyf6LUSuukzNku2vdZ3yVxpFV5QNDcdSNPU%3D,
"SocialMediaLink": https://myflightbook.com/logbook/mvc/pub/ViewFlight/22075026?v=2341,
"User": "xxxxx",
"AircraftID": #####,
"FullStopLandings": 2,
"Approaches": 2,
"Landings": 2,
"IMC": 1,
"PIC": 1.8,
"TotalFlightTime": 1.8,
"fHoldingProcedures": true,
"Route": "KSFO-EGLL",
"Comment": "New flight",
"Date": "2024-04-02T00:00:00",
"ErrorString": "",
"FlightID": 22075026,
"ModelDisplay": "TR182, Cessna Skylane Turbo RG",
"TailNumDisplay": "N12345",
"CatClassDisplay": "ASEL",
"CustomProperties": [
{
"PropID": 32699841,
"FlightID": 22075026,
"PropTypeID": 77,
"DecValue": 1.8,
"TextValue": ""
}
],
"FlightImages": [],
"Videos": []
}
A few things to note:
- The username has been filled in. This is internal; a valid oAuth token maps to the correct username.
- A flight ID has been assigned, and the solo time property now points to that flight ID.
- The property itself has been assigned an ID.
- Additional read-only fields like “SendFlightLink”, “SocialMediaLink”, and a few display fields are provided. If you include these when you update the flight, that’s fine – they will be ignored, or you can delete them (e.g., if you generate the JSON/XML yourself)
Updating an existing flight is essentially the same process as creating a new flight. You modify whatever fields you want and again call CommitFlightWithOptions. E.g., if I want to modify the 1.8 hours above to be 9.8 (more realistic for KSFO->EGLL), and if I want to add a “Passenger Names” property (PropTypeID=120), I can post this this (read-only fields removed just for clarity):
{
"User": "xxxx",
"AircraftID": #####,
"FullStopLandings": 2,
"Approaches": 2,
"Landings": 2,
"IMC": 1,
"PIC": 9.8,
"TotalFlightTime": 9.8,
"fHoldingProcedures": true,
"Route": "KSFO-EGLL",
"Comment": "New flight",
"Date": "2024-04-02T00:00:00",
"FlightID": 22075026,
"CustomProperties": [{
"PropID": 32699841,
"FlightID": 22075026,
"PropTypeID": 77,
"DecValue": 9.8,
}, {
"PropID": -1,
"FlightID": 22075026,
"PropTypeID": 120,
"TextValue": "Donald Duck"
}
]
}
And voila.
A few important things to note here:
- Notice that update and create are the same; the only difference is the flightID. -1 signifies a new flight, a positive integer corresponds to an existing flight. If that positive integer doesn’t correspond to a flight that you own (i.e., that your authtoken provides access to), you will get an error
- Updating a flight or its properties simply involves updating the existing values.
- Adding a new property to an existing flight is the same as adding a property to a new flight except that you want to set the flightID to point to the new flight. (If you forget and set it to -1, it looks like the code catches that and fixes it up for you)
- Deleting a property requires a call to the DeletePropertyForFlight call.
- Images are handled separately. You can only add/remove images from an EXISTING flight, so you save it first and, on success, you can then add images using the calls described here