MyFlightbook Logbook Sync
Connect your MyFlightbook account to AeroCopilot via OAuth2 and import flights, aircraft, currency, and totals — read-only and rate-limited.
MyFlightbook Logbook Sync
AeroCopilot integrates with MyFlightbook over OAuth2 so you can import your existing logbook history without re-keying entries. The connection is strictly read-only against the live MyFlightbook site — AeroCopilot never modifies, deletes, or writes flights, aircraft, or properties back to your MFB account.
How the connection works
The integration uses the standard OAuth2 authorization-code flow.
- Start the connection at
/api/integrations/myflightbook/authorize. You will be redirected to MyFlightbook's consent screen. - Approve the requested scopes, all of which are read-only:
currency,totals,readflight,readaircraft,visited,namedqueries. - Return to AeroCopilot via the callback at
/api/integrations/myflightbook/callback, where the access and refresh tokens are exchanged and stored. - Disconnect at any time via
/api/integrations/myflightbook/disconnect, which deletes your stored tokens.
Tokens are encrypted at rest using AES-256-GCM in the IntegrationToken table. When the access token expires, AeroCopilot automatically refreshes it using the stored refresh token before the next API call. If no refresh token is available, you will be prompted to reconnect.
What gets synced
A full sync orchestrates calls to the MyFlightbook OAuth JSON API in sequence — aircraft, flights, currency, totals — then computes a local 12-month rollup. Calls are spaced at least 500 ms apart to respect MyFlightbook's server load.
The sync runs in the background. Triggering a sync (manually or on first connect) enqueues one SyncJob (guarded by a per-user advisory lock so a double-click can't launch two), returns immediately, and runs off the request path. The logbook page polls the job and shows an importing → ready/failed state, so a large logbook (thousands of flights) never blocks the request. The connected-account card on the logbook page shows the synced flight/aircraft/hours counts so you can confirm the right MyFlightbook account is linked.
Flights (FlightsWithQueryAndOffset)
Flights are paged in batches of 50 and inserted into your AeroCopilot logbook. Field mapping:
Date→ entry date (parsed from MyFlightbook'sM/D/YYYYformat, anchored to UTC)TailNumDisplay→ aircraft N-numberModelDisplay→ aircraft type (whitespace-normalized)Route→ first token becomesdeparture, last becomesdestination; each is normalized (runway qualifier likeKJFK/28Rstripped toKJFK, then truncated to 4 characters)TotalFlightTime,PIC,SIC,CrossCountry,Nighttime,IMC,SimulatedIFR,Dual,CFI,GroundSim→ corresponding decimal-hour columnsFullStopLandingsminusNightLandings→dayLandings/dayTakeoffs;NightLandings→nightLandings/nightTakeoffs(per AC 61-98D: one takeoff per full-stop landing)Approaches→ integer count;fHoldingProcedures→ 1 if true, else 0Comment→ remarks;CustomProperties→ persisted verbatim- aircraft device class (
InstanceType) →simulatorType(REAL / FFS / FTD / AATD / FLAPS) for §61.57(c) sim-credit gating
Duplicate detection keys on externalId = mfb:{FlightID} (the primary, stable key); a legacy route-key (date:departure:destination) is a fallback that lazily backfills the externalId on pre-existing rows. Matching flights are skipped, not overwritten. A single over-length or dateless record is skipped (and counted) rather than aborting the whole import. Each sync writes a LogbookImport record (processing → completed or failed) capturing imported / skipped / failed counts.
Aircraft (AircraftForUser)
Returns the aircraft registered in your MFB account (tail, model, device class). AeroCopilot matches each US tail against the FAA registry and auto-creates a UserAircraft row when a registration is found. Aircraft are skipped (not created) when there's no matching registration, the tail isn't a US registration, or a hand-curated UserAircraft already exists for that registration (manual entries are never overwritten).
Currency (GetCurrencyForUser)
MyFlightbook tracks a wide range of currency attributes. AeroCopilot maps the FAA-relevant ones into your CurrencyRecord table — flight review (§61.56), instrument currency (§61.57(c)), 1st/2nd/3rd-class medicals and BasicMed, key endorsements, and the §61.57(a)/(b) 90-day day/night passenger-carrying currency — resolving MyFlightbook's real (and sometimes per-category) labels via CurrencyGroup + pattern matching.
Compliance-status safety: MyFlightbook's OAuth JSON omits a field when it equals its default, so a not-current item (CurrencyState.NotCurrent = 0) arrives with no status. AeroCopilot reads an absent status as NON_COMPLIANT (not "unknown"), so a non-current pilot is never shown as green. A genuine "no expiration on file" (NoDate) stays unknown. Attributes AeroCopilot can't yet map are logged and skipped (never shown as a false pass).
Totals (TotalsForUserWithQuery)
Returns lifetime flight-hour summaries. AeroCopilot persists these as a MyFlightbook snapshot in LogbookTotal (source = myflightbook) bucketed by dimension (total time, role, conditions, counts), alongside a locally-computed trailing-12-month rollup (source = computed-local). Unmapped descriptions are preserved verbatim under an OTHER dimension rather than dropped.
Safety guarantees
The MFB client enforces a hard whitelist of read methods (AircraftForUser, FlightsWithQueryAndOffset, GetCurrencyForUser, TotalsForUserWithQuery, VisitedAirports, and similar). Any attempt to call a write method (AddAircraftForUser, CommitFlightWithOptions, DeleteLogbookEntry, etc.) against the live myflightbook.com host throws BLOCKED: and aborts. This guard exists because aircraft records are shared between pilots in MFB — an accidental write could affect other users' data.
Required configuration
To enable the integration, the following environment variables must be set on the server:
MFB_CLIENT_IDMFB_CLIENT_SECRETMFB_BASE_URL(defaults tohttps://myflightbook.com)
Related
- API Library Overview
- Logbook
- Currency Tracking