Skip to main content
For host app owners integrating the flights miniapp. This document defines every event sent by the flights miniapp to a host app, and every host-app request concerning a flight order. It covers payloads, triggers, authentication, retries, and integration flow. All instructions use the host-app perspective: endpoints exposed by the host app, Boxo Platform endpoints called by the host app, and the data exchanged through each.

How the integration fits together

The host app and flights miniapp do not call each other directly. The Boxo Platform mediates both directions. Consequently, all host-app inbound requests arrive from the Boxo Platform and use the host app’s credentials. All host-app outbound requests go to a Boxo Platform endpoint, which relays the request to the flights miniapp and returns its response.

Endpoints exposed by the host app

The host app must expose the following endpoints and register each URL in the Boxo Dashboard. The platform authenticates with Basic base64(hostapp_client_id:hostapp_secret_key), using the host-app credentials configured in the dashboard.
The Get order payment status endpoint is not optional in practice. Payment results do get lost in transit, and this is the only way an order stuck mid-payment ever resolves — otherwise a traveller can be charged and never ticketed.

Boxo Platform endpoints called by the host app

Dashboard settings to confirm

Boxo must enable Event Bridge for both the host app and the flights miniapp. Enabling only one side prevents event delivery.

Authentication

Calls received by the host app (event receiver, create order payment, get payment status) carry:
The host app must verify these credentials on every request. There is no signature over the body. Host-app endpoints should answer 200 in all cases, using a response field to report problems; a non-200 response is treated as a delivery failure and retried. Calls made by the host app to the Event Bridge API use the same Basic credentials. Payment platform endpoints such as complete-order are authorized by IP whitelisting or request signaturing configured in the dashboard.
IP whitelisting and request signaturing are also available for securing server-to-server calls. See Security measures.

What an event delivery looks like

Every flight order event arrives at the host app’s event receiver in the platform’s standard envelope:
Return HTTP 200. The response body is forwarded to the flights miniapp, but the flights event flow does not depend on its contents; {} is sufficient.
The receiver may also receive event types from other miniapps and the platform. Unsupported event types should be acknowledged with 200 and ignored.

The five event types

The event type identifies the outcome and can be used for routing without inspecting the payload. All five lifecycle events require a settled host-app payment. At the time an event is first emitted, payment_status is PAID. A pending, cancelled, or failed payment never produces a lifecycle event. Nothing is sent while an order is still moving — awaiting payment or mid-ticketing. Events communicate final outcomes rather than intermediate steps.

order.succeeded

Sent once the airline has issued the ticket. The host app should use this event to add or confirm the booking. booking_reference holds the PNR and booking contains the information required to render a booking card. Some airlines issue asynchronously, so this can arrive minutes after the payment settled. It fires when the ticket genuinely exists, not when it was requested.

order.failed

The trip was not delivered — typically the airline refused the booking, or the traveller paid for a change the airline then would not make.
Not sent when the host app declines the charge. A payment rejected by the host app is already known to it, and an unpaid order must not appear as a failed booking.
If money was taken and no ticket came back, order.refunded follows.

order.refunded

Sent when a refund obligation is opened, not when it later completes. The host app must return refund.amount in refund.currency against refund.source_order_payment_id, which is the order_payment_id originally issued by the host app. refund.amount is already net of any airline penalty. penalty_amount is informational and must not be subtracted again.

booking.changed

The trip moved. The payload carries the new flights. status is still BOOKED and miniapp_order_id is unchanged — this updates an existing booking, it is not a second ticket. Fires on a confirmed change and when the flights miniapp detects an airline-initiated itinerary retime.

booking.cancelled

The trip has ended. If a refund is due, a separate order.refunded follows.

Payload reference

The payload object of every order event. All keys are always present. Missing data is "" or null, never an omitted key. Amounts are decimal strings, never numbers.

Top level

booking

No airline is named at this level on purpose: one trip can be flown by several carriers. Airlines live on segments.

Place

Unknown place → all three "". Names are included so the host app does not require its own IATA lookup table. They use one stable catalogue language rather than the traveller’s locale; host apps may localize them independently.

Passenger

Journey

Display departing_at / arriving_at. Sort and compare on departs_at / arrives_at.

Segment

Carrier

All fields are "" when unknown. A logo is supplied when available, so a separate host-app airline image library is not required.

price

refund — on order.refunded only

Delivery, retries, and idempotency

  • Events are sent after the corresponding state change is committed, so delivered payloads describe committed state.
  • A failed delivery is retried periodically, up to 5 attempts in total. After that it is flagged for operational review and can be re-sent once the host-app endpoint is healthy.
  • Retried events are re-derived from current order state. If the order changes between attempts, the retry describes the current state rather than replaying stale data.
  • Delivery failures never affect the booking. An unavailable host-app endpoint cannot prevent ticket issuance.
  • Any response other than HTTP 200 counts as a failure and is retried. Unsupported event types must also receive 200.
The receiver must be idempotent. The same event can arrive more than once, and events for one order can arrive out of order after an outage. Key records on miniapp_order_id and treat each payload as current order state rather than as a delta. Compare payment_status and fulfillment_status with stored values to discard stale repeats.

Reading status

status is a one-word summary of two independent facts: whether payment settled and whether a ticket exists. All lifecycle events are emitted only after payment_status=PAID; the three status fields still remain in the payload for explicit state tracking.
The critical combination is payment_status=PAID with fulfillment_status=FAILED: the traveller was charged but no ticket was issued. It produces order.failed, followed by order.refunded.

Full example — order.succeeded

As delivered to the host-app event receiver:
On order.refunded, payload.refund carries:

Request booking information — booking.info

The host app sends booking.info through the Boxo Event Bridge API. The platform relays the event to the flights miniapp and returns the flights miniapp response as the response body. This operation can backfill state after an outage or retrieve a booking list without storing every lifecycle event. POST /api/v1/events/hostapp/ on the Boxo Platform.

Response

Each entry is exactly the payload from Payload reference, so code that already handles order events handles this with no second parser. refund is null here. An unknown user_id returns an error rather than an empty list, preventing a mismatched reference from appearing to be a traveller with no trips.

Payments

Flight checkout uses the standard Boxo Payments flow with three host-app integration points.

Create order payment request

The Boxo Platform calls the host app’s create order payment endpoint. The body carries order.miniapp_order_id, which is the same id included in every lifecycle event for that order and should be stored with the payment.
Return {"order_payment_id": "..."} with HTTP 200. The traveller settles that payment through the SDK. If a refund is later required, the same id appears as refund.source_order_payment_id. Flight fares are quoted tax-inclusive: amount is the whole of what the traveller pays, subtotal_amount equals it, and the tax split is not broken out separately. Do not expect a subtotal below the total.

Report the payment result

After the traveller confirms, call the platform:
How each status affects the order: Booking starts after the payment result is acknowledged, not during the request. order.succeeded, rather than the payment-completion response, is the signal that a ticket exists. A failed notice for a payment already recorded as settled is ignored as an out-of-order redelivery.

Get order payment status

If a payment result is not delivered, the flights miniapp queries the Boxo Platform, which calls the host app’s get order payment status endpoint. The endpoint must return the current status (in_process, paid, cancelled, or failed). This endpoint is the recovery path for lost payment notifications. A missing or incorrect implementation can leave a charged traveller without a ticket or refund.

Payment custom attributes

order.custom_attributes carries only what the host needs to render the first charge: the fare’s expiry, the quoted trip as offer, and price. A booking does not exist yet — it is created after the host marks the payment paid, and arrives on order.succeeded as booking. offer uses the same itinerary keys as that later booking object (origin, destination, journeys, passengers, …) so the payment sheet and the booking card share a parser. It does not include reference: there is no PNR until the airline confirms. Lifecycle fields (miniapp_order_id, status, payment_status, fulfillment_status, booking_reference, refund, …) are omitted. When an order is also priced in the traveller’s own currency, the same object carries a local-pricing audit trail:
The charge amount is always order.amount, which is the rounded local total when local pricing applies. The additional pricing keys provide an audit trail after exchange rates change.

Traveller identity

Login uses Boxo Connect through either the OAuth or Direct flow. In both flows, reference in the supplied user data is the relevant identity field. reference becomes the traveller’s identity in the flights miniapp. It is sent as user_id in booking.info and echoed as hostapp_user_id in the create order payment request.
It must be stable for a user across sessions and devices. If it changes, that traveller’s booking history goes with it.
Supplying first_name, last_name, email, and phone allows checkout to prefill traveller details.

Integration checklist

1

Enable Event Bridge

Request that Boxo enable Event Bridge for the host app and flights miniapp, and register the host-app event receiver URL.
2

Register payment endpoints

Register the host-app create order payment and get order payment status URLs. Both are required for safe checkout.
3

Verify inbound credentials

Verify Basic hostapp_client_id:hostapp_secret_key on every inbound call.
4

Acknowledge every event

Return 200 from the event receiver for every event, including unsupported types.
5

Route on event_type

Route on event_type. Do not reduce the five types to one generic status update.
6

Key records on miniapp_order_id

Key records on payload.miniapp_order_id and make handlers idempotent.
7

Render booking cards from the payload

Render booking cards from payload.booking: names, logos, wall-clock times, terminals, seats, and PNR. No host-app lookup tables are required.
8

Treat booking.changed as an update

Treat booking.changed as an update to an existing booking, never as a new one.
9

Refund the net amount

On order.refunded, return refund.amount — already net — against refund.source_order_payment_id.
10

Read payment and fulfillment together

Read payment_status and fulfillment_status together, not just status.
11

Keep Connect reference stable

Keep reference stable per user at connect.

Quick reference

Platform reference: Boxo Event Bridge, Boxo Payments, Boxo Connect.