# How the AirTrail Flight Import Integration Works in TREK: A Technical Deep Dive

> Explore the TREK AirTrail flight import integration. Learn how to connect AirTrail, import reservations, and synchronize data bidirectionally with Bearer API authentication.

- Repository: [Maurice/TREK](https://github.com/mauriceboe/TREK)
- Tags: deep-dive
- Published: 2026-07-09

---

**The TREK AirTrail flight import integration enables users to connect their AirTrail instance via Bearer API authentication, import flight reservations into trip plans, and optionally synchronize changes bidirectionally between the two systems.**

The AirTrail flight import integration in the TREK repository (`mauriceboe/TREK`) allows travelers to seamlessly pull flight data from a self-hosted AirTrail instance directly into their TREK trip planner. This integration supports secure API credential storage, flexible TLS configuration options, and background synchronization to keep reservation data consistent across both platforms.

## Configuring the AirTrail Connection

### User Settings and API Credentials

The integration setup begins in **Settings → Integrations**, where the **[`AirTrailConnectionSection.tsx`](https://github.com/mauriceboe/TREK/blob/main/AirTrailConnectionSection.tsx)** component renders a configuration form. This interface collects the AirTrail instance URL, a Bearer API key, and optional flags for `allowInsecureTls` and `writeEnabled` (write-back synchronization).

When the user clicks **Save**, the client invokes `airtrailApi.saveSettings()` to POST the configuration to the server. According to the schema definitions in **[`/shared/src/airtrail/airtrail.schema.ts`](https://github.com/mauriceboe/TREK/blob/main//shared/src/airtrail/airtrail.schema.ts)**, the server encrypts the API key before persistence and returns a masked placeholder (`••••••••`) to the client. This ensures the real secret never exposes itself to browser-based JavaScript, maintaining strict security hygiene.

### Testing the Connection

Before importing flights, users can validate their configuration using the **Test Connection** button. This triggers `airtrailApi.test({url, apiKey, allowInsecureTls})`, which POSTs to `/integrations/airtrail/test`. The server attempts a lightweight health check against the AirTrail API and returns a connection status object containing `{connected: true, flightCount: number}`. The UI surfaces this result as a toast notification, confirming connectivity and displaying the number of available flights before proceeding.

## Fetching and Importing Flights

### Retrieving Available Flights

Once connected, the import workflow displays a flight picker via **[`AirTrailImportModal.tsx`](https://github.com/mauriceboe/TREK/blob/main/AirTrailImportModal.tsx)**. The client calls `airtrailApi.flights()` to GET `/integrations/airtrail/flights`. The server proxies this request to the configured AirTrail instance and normalizes each flight into the **`AirtrailFlight`** schema.

This schema—defined in **[`/shared/src/airtrail/airtrail.schema.ts`](https://github.com/mauriceboe/TREK/blob/main//shared/src/airtrail/airtrail.schema.ts)**—standardizes fields including `id`, origin and destination airport codes, departure and arrival dates, airline details, and booking references. The normalized array renders in the modal, allowing users to preview their AirTrail inventory before selection.

### Importing Selected Flights into Trips

After the user selects specific flights, the client invokes `airtrailApi.import(tripId, flightIds)`, which POSTs to `/trips/:tripId/reservations/import/airtrail`. The server creates new reservation records with `external_source: 'airtrail'` and stores the original AirTrail flight identifier in the `external_id` field. This linkage preserves the relationship between TREK reservations and their source data.

The server returns an **`AirtrailImportResult`** object indicating how many flights were successfully imported and how many were skipped due to existing duplicates. The UI reports these counts to provide clear feedback on the import operation's scope.

## Synchronization and Write-Back Features

### Bidirectional Sync Support

Imported reservations can maintain live synchronization with AirTrail. Each reservation stores a **`sync_enabled`** flag, and the integration configuration tracks **`writeEnabled`** to determine if TREK should push local edits back to the AirTrail instance.

The `airtrailApi.sync()` method triggers a background job that re-fetches the user's AirTrail flight list, updates any changed reservation details in TREK, and flags removed flights as unsynchronized. Throughout the planner UI, reservation lists display AirTrail-specific labels and tooltips—such as "AirTrail – synced" or "AirTrail – not synced"—based on these flags. These status strings reside in the localization files under **`/shared/src/i18n/*/reservations.ts`**.

### Practical Implementation Examples

```typescript
// Configure the AirTrail connection
await airtrailApi.saveSettings({
  url: 'https://my-airtrail.example.com',
  apiKey: 'Bearer abc123',
  allowInsecureTls: false,
  writeEnabled: true,
});

// Verify connectivity before importing
const testResult = await airtrailApi.test({
  url: 'https://my-airtrail.example.com',
  apiKey: 'Bearer abc123',
});
if (testResult.connected) {
  console.log(`Connected – ${testResult.flightCount} flights available`);
}

// Retrieve available flights for the import picker
const flights = await airtrailApi.flights(); // Returns AirtrailFlight[]

// Import selected flights into a specific trip
await airtrailApi.import(tripId, ['flight-123', 'flight-456']);

// Trigger manual synchronization (optional)
const syncInfo = await airtrailApi.sync(); // Returns { changed: number }

```

All client-side API calls are thin wrappers around the core `apiClient` defined in **[`/client/src/api/client.ts`](https://github.com/mauriceboe/TREK/blob/main//client/src/api/client.ts)**, ensuring consistent error handling and authentication headers across the integration.

## Summary

- **Encrypted credential storage**: API keys are encrypted server-side and masked in the UI, with configuration handled by [`AirTrailConnectionSection.tsx`](https://github.com/mauriceboe/TREK/blob/main/AirTrailConnectionSection.tsx) and validated against [`airtrail.schema.ts`](https://github.com/mauriceboe/TREK/blob/main/airtrail.schema.ts).
- **Connection validation**: The `airtrailApi.test()` method verifies AirTrail connectivity via `/integrations/airtrail/test` before allowing imports.
- **Normalized data structure**: Flights are transformed into the `AirtrailFlight` schema during retrieval, ensuring consistent data handling regardless of AirTrail's internal format.
- **External source tracking**: Imported reservations carry `external_source: 'airtrail'` and `external_id` fields to maintain referential integrity with the source system.
- **Bidirectional synchronization**: Optional write-back support and background sync jobs keep TREK reservations aligned with AirTrail changes when `sync_enabled` and `writeEnabled` are active.

## Frequently Asked Questions

### What data format does TREK use when importing AirTrail flights?

TREK normalizes flight data into the **AirtrailFlight** schema defined in [`/shared/src/airtrail/airtrail.schema.ts`](https://github.com/mauriceboe/TREK/blob/main//shared/src/airtrail/airtrail.schema.ts). This Zod-defined structure includes mandatory fields for flight ID, origin and destination IATA codes, departure and arrival dates, airline information, and ancillary booking details.

### Is the AirTrail API key stored securely in TREK?

Yes. When `airtrailApi.saveSettings()` persists configuration, the server encrypts the API key before database storage. The client only receives a masked placeholder (`••••••••`) in subsequent responses, ensuring the actual Bearer token never exposes itself to browser-based JavaScript or network inspection.

### Can TREK sync flight changes back to AirTrail?

Yes, provided the user enabled **write-back** during initial configuration. When `writeEnabled` is true and a specific reservation has `sync_enabled` set, modifications made within TREK can propagate back to the AirTrail instance via the synchronization endpoints, maintaining data consistency across both platforms.

### How does TREK handle self-signed TLS certificates?

The integration supports an `allowInsecureTls` boolean flag in the connection settings. When enabled, TREK permits HTTPS connections to AirTrail instances using self-signed or otherwise untrusted TLS certificates. This flexibility supports local development environments and private network deployments without requiring public CA-signed certificates.