# Flight Status integration

<Aside type="caution" icon="setting" title="Developer assistance needed">
You'll need your development team to send the booking event with the right attributes and to build the Webhook step's request body. Share this guide with them.
</Aside>

The Flight Status integration connects Pushwoosh to [AeroDataBox](https://www.aerodatabox.com/), a flight-data provider, so a [customer journey](/product/customer-journey/pushwoosh-journey-overview/) can watch a specific passenger's flight and react the moment its status changes: a new gate, a delay, boarding, arrival, or a cancellation.

## Integration overview

### Integration type

**Source:** you subscribe a booking to its flight from inside a journey. Pushwoosh sends the status changes back as an event you use later in that same journey.

### Prerequisites

Before connecting Flight Status, make sure you have:

* An active Pushwoosh account with an application in Pushwoosh's NUE data center. Flight Status isn't available in other data centers yet.
* An AeroDataBox account and API key. The feed is billed on your own AeroDataBox account.
* A booking event that carries the flight's carrier, number, date, and departure airport (see [Build the flight status journey](#build-the-flight-status-journey)).
* A dedicated [API Access token](/developer/api-reference/api-access-token/) for the journey to authenticate with.

### How does the integration work?

You connect your AeroDataBox key once, in **Settings** → **3rd-party integrations**. From there, watching a flight happens per booking, inside a customer journey: a Webhook step calls Pushwoosh's own public API to subscribe that booking to its flight, and Pushwoosh posts a `PW_FlightStatusChanged` event back to the app every time something changes.

#### Data flow

Connecting the integration and watching one flight are two separate steps, done at different times:

1. Connect your AeroDataBox key in **Settings** → **3rd-party integrations**.
2. A booking event enters a passenger into your journey.
3. The journey's Webhook step subscribes that booking to its flight through Pushwoosh's public API.
4. Pushwoosh watches the flight with AeroDataBox and detects changes: gate, delay, boarding, arrival, cancellation, or a baggage belt assignment.
5. Each change is delivered to the app as a `PW_FlightStatusChanged` event, which the journey's [Wait for Trigger](/product/customer-journey/journey-elements/flow-controls/wait-for-trigger/) and [Condition split](/product/customer-journey/journey-elements/flow-controls/segment-split/) route to the right message.

### Use cases

Flight Status covers four kinds of updates, each usable on its own or combined in one journey:

#### Gate change alerts
Notify passengers the moment their departure gate changes.

#### Delay notifications
Alert passengers once a flight's delay passes a few minutes, so they can adjust their plans.

#### Boarding and arrival updates
Tell passengers when boarding opens or their flight lands.

#### Baggage claim
Send the baggage belt number as soon as it's assigned.

## Set up the integration

### Connect Flight Status to Pushwoosh

Connect your AeroDataBox key once per application:

1. Open your application and go to **Settings** → **3rd-party integrations**.
2. Under **Available services**, find the **Flight Status** card and click **Configure**.

![Flight Status card in the 3rd-party integrations list, showing its description and Configure button](/integrations-flight-status-integration-2.webp)

3. Paste your AeroDataBox key into **API key** and click **Connect**.

![Flight Status Configure dialog with Provider set to AeroDataBox and an empty API key field](/integrations-flight-status-integration-1.webp)

4. The card moves to **Connected services**. Reopen it from there any time to replace the key. The field only ever shows the last few characters of what's stored, and leaving it empty on save keeps the current key.

### If the key is rejected

Pushwoosh checks the key against AeroDataBox in the background and shows one of these messages on the card if something's wrong:

| Message | Cause |
|---|---|
| `provider rejected the API key` | The key is invalid or was revoked in AeroDataBox |
| `provider account is out of credits` | Your AeroDataBox plan has run out of credits |
| `provider rate limit reached` | AeroDataBox is throttling requests, and this clears on its own |
| `provider is unavailable` | AeroDataBox couldn't be reached, due to a network issue or an outage on either side |
| `provider refused the request` | AeroDataBox returned an error Pushwoosh doesn't otherwise recognize |

<Aside type="note">
Removing the key doesn't remove existing subscriptions. The active-subscriptions count on the card keeps including them until they end on their own or you delete them from the journey.
</Aside>

### Disconnect the integration

Open the **Flight Status** card from **Connected services** and remove the key. Journeys already watching a flight keep their subscriptions. Disconnecting only stops new ones from being created.

## Build the flight status journey

Prerequisites for the journey itself:

* A booking event carrying the flight's carrier, number, date (`YYYY-MM-DD`), and departure airport, plus one attribute holding the flight key in `<carrier><number>/<date>/<departure airport>` format, for example `LH400/2026-09-20/MUC`. This is what session matching uses throughout the journey.
* A dedicated [API Access token](/developer/api-reference/api-access-token/). The subscribe method accepts any token from your account, with no permissions to grant. Create one specifically for this journey so you can revoke it later without touching anything else.
* Your data center's public API host. For NUE accounts, that's `rpc-api.svc-nue.pushwoosh.com`.
* The journey's [Campaign entry limit](/product/customer-journey/journey-settings/#campaign-entry-limit), turned off. Campaign entry limit tracks entries per user only. It doesn't know about the session identifier you set up below, so it would block a passenger's second flight until the limit period passes.

### Start the journey from a booking event

1. Add a [Trigger-based entry](/product/customer-journey/journey-elements/entry-elements/trigger-based-entry/) and select your booking event, for example `flight_booked`.
2. Under **Control how many sessions a user can have at the same time**, choose **Multiple active sessions per user**.
3. Pick the flight-key attribute as the session identifier. This lets the same passenger track more than one flight at once, each in its own session.

### Subscribe the booking with a Webhook step

Add a [Webhook](/product/customer-journey/journey-elements/channels/webhook/) step directly after the entry. Its request body pulls the flight fields from the entry event, so the step needs to sit right after entry to use them.

1. Set **REQUEST TYPE** to `POST`.
2. Set **URL** to `https://rpc-api.svc-nue.pushwoosh.com/api/integrations/flight-status/subscriptions`.
3. In **HEADERS**, keep `Content-Type: application/json`.
4. Add a header `Authorization: Token <your API token>`. Pushwoosh masks this value after you save, because any header named `Authorization` is treated as a secret automatically. See [Mark a header value as secret](/product/customer-journey/journey-elements/channels/webhook/#mark-a-header-value-as-secret) for what that means for editing and version history.
5. In **DATA**, enter the request body below, typing your own application code directly:

```json
{
  "application": "<your application code>",
  "user_id": "{{device:user_id}}",
  "source": "journey",
  "flight": {
    "carrier": "",
    "flight_number": "",
    "flight_date": "",
    "departure_airport": ""
  }
}
```

6. For each of the four empty `flight` values, open **DATA BUILDER**.
7. Select category **Event**.
8. Pick the matching attribute from your booking event (carrier, flight number, flight date, departure airport).
9. Copy the macro Pushwoosh generates and paste it in as that field's value. Repeat for the remaining three values.

<Aside type="caution">
The response echoes back `flight_key`, which matches the attribute you already put on the booking event, so there's nothing to map from it. A failed subscribe call drops the passenger from the journey at this step instead, the same as any Webhook step: that passenger never gets watched, and won't receive any of the alerts further down the journey. See [What happens when a request fails](/product/customer-journey/journey-elements/channels/webhook/#what-happens-when-a-request-fails).
</Aside>

### Wait for a status update

Add a [Wait for Trigger](/product/customer-journey/journey-elements/flow-controls/wait-for-trigger/) step after the Webhook step.

1. Add one branch and set its event to `PW_FlightStatusChanged`.
2. Under multi-session attribute matching, select the same flight-key attribute you used on the entry. This makes sure a status update only wakes the passenger whose flight it's actually about.
3. Set the waiting period to comfortably cover the flight. 48 hours is enough for most itineraries.
4. Leave the **Not triggered** branch without a next step. A passenger whose flight produces no matching update before the wait expires isn't an error case, so ending here quietly is normal, though you can add a fallback message instead if you'd rather.

### Branch by event type

Add a [Condition split](/product/customer-journey/journey-elements/flow-controls/segment-split/) after the Wait for Trigger step.

1. Select **Event** as the condition type.
2. In **Event from Journey**, choose `PW_FlightStatusChanged`.
3. Under **Attribute**, select `event_type`.
4. Set the condition to **is**.
5. Add a branch with the value `gate_change`.
6. Click **Save**. This creates two branches: the one you named for a gate change, and **All other users** for every other event type.

Repeat this element, or add more branches to it, for the other `event_type` values you want to act on: `delay`, `boarding`, `departed`, `arrived`, `cancelled`, and `baggage_ready` all work the same way.

### Notify the passenger

Add a [Push](/product/customer-journey/journey-elements/channels/push/) element on the gate-change branch.

1. Select or create a push preset.
2. Set **Message type** to **Transactional message**, since a flight status alert is a service notification, not a promo. Frequency capping doesn't apply, and it still reaches passengers in a [control group](/product/audience-data-and-segmentation/control-groups/).
3. Enable [personalization with event attributes](/product/customer-journey/journey-elements/dynamic-content-and-liquid-templates-in-journeys/#dynamic-content-personalization).
4. Choose `PW_FlightStatusChanged` as the source event.
5. Fill your preset's placeholders from `flight_number` and `gate_new`.

## PW_FlightStatusChanged event reference

Every change the integration detects is delivered as one `PW_FlightStatusChanged` event, with all attributes always present: empty ones are sent as blank values, never left out.

| Attribute | Type | Description |
|---|---|---|
| `event_type` | String | What changed (see the values below) |
| `flight_key` | String | The same flight key you set on the booking event |
| `flight_number` | String | The flight number |
| `departure_airport` | String | Departure airport code |
| `arrival_airport` | String | Arrival airport code |
| `status` | String | Current flight status (see the values below) |
| `gate_old` / `gate_new` | String | Departure gate before and after the change |
| `terminal_old` / `terminal_new` | String | Departure terminal before and after the change |
| `baggage_claim` | String | Baggage belt number, once assigned |
| `provider` | String | The data provider that reported the change (`aerodatabox`) |
| `delay_minutes` | Integer | Minutes of delay, present once a flight is delayed by 5 minutes or more |
| `scheduled_at` / `estimated_at` / `actual_at` | String | Scheduled, currently estimated, and actual times, in the provider's own format |
| `flight_date` / `event_time` | Date | The flight's date, and when the change happened |

<Aside type="note">
`scheduled_at`, `estimated_at`, and `actual_at` are String attributes, not Date, because a flight without a revised time still has to keep the other two. A Date attribute is dropped from the event entirely when its value is empty. Use `flight_date` and `event_time` for anything you need to filter as a date.
</Aside>

**`event_type` values:** `gate_change`, `delay`, `boarding`, `departed`, `arrived`, `cancelled`, `baggage_ready`.

**`status` values:** `scheduled`, `check_in`, `boarding`, `departed`, `delayed`, `arrived`, `cancelled`, `diverted`, `unknown`. An AeroDataBox status Pushwoosh doesn't recognize is reported as `unknown` rather than guessed.