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 Basicbase64(hostapp_client_id:hostapp_secret_key), using the host-app credentials configured in the dashboard.
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: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 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.
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
Thepayload 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
200counts as a failure and is retried. Unsupported event types must also receive200.
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:
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
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 carriesorder.miniapp_order_id, which is the same id included in every lifecycle event for that order and should be stored with the payment.
{"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:
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.
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.