# Events

> The events Travel Orbit sends to Orbit Exchange when trips, departures, bookings and payments change, what each one carries, and how they are delivered. Travel Orbit doesn't send webhooks to your own systems.

Source: https://docs.bifrostorbit.com/travel/developers/webhooks-and-events/

When something changes in Travel Orbit, such as a trip being published or a payment going through, it records an event and sends it to Orbit Exchange, the hub that connects Orbit's products. Other satellites react to them there, and Orbit shows them under **Exchange**.

Travel Orbit doesn't send webhooks to your own website or systems. Events go to Orbit Exchange only, where Orbit's products use them: for example, a CMS Orbit website that shows your trips refreshes its pages when a trip, departure or booking changes (see [Show your trips on your website](https://docs.bifrostorbit.com/travel/everyone/cms-orbit/)). To keep your own website current, read the [booking API](https://docs.bifrostorbit.com/travel/developers/booking-api/) and cache its answers for a short time.

## The envelope

Every event has the same outer shape as events from CMS Orbit. Only `data` differs.

| Field | What it holds |
| --- | --- |
| `id` | A unique ID (UUID) for this event. Use it to spot duplicates. |
| `type` | The event name, such as `travel.booking.created`. |
| `version` | The version of this event's `data` shape. It only goes up for a change that could break a receiver. |
| `time` | When it happened, in UTC. |
| `source` | Always `travel`. |
| `sequence` | A number that goes up with each event from your organisation. |
| `tenant.organisationId` | Your organisation. The other `tenant` fields are `null`. |
| `subject.resourceType` | `trip`, `departure`, `booking` or `payment`. Failed automatic payments and refunds name the `booking`. |
| `subject.id` | The ID of what changed. |
| `actor.type` | `user` when someone on your team did it, `system` when a traveller or Travel Orbit did, such as a booking from the website or an automatic payment. |
| `actor.id` | The person's ID, or `null` for `system`. |
| `data` | The details below. |

## The events

| Event | When |
| --- | --- |
| `travel.trip.published` | A trip is published. |
| `travel.trip.unpublished` | A published trip is unpublished or archived. |
| `travel.trip.changed` | A published trip's details are saved. |
| `travel.departure.changed` | A departure is added, changed or deleted, or marked as guaranteed or not. |
| `travel.departure.full` | The last place on a departure is taken. |
| `travel.departure.reopened` | A full departure has places again, because places were added or a booking was cancelled. |
| `travel.booking.created` | A booking is made: held in checkout, sent as a request or booked by your team. |
| `travel.booking.changed` | A held booking is confirmed by its first payment, or your team confirms a request. |
| `travel.booking.cancelled` | A booking is cancelled. |
| `travel.payment.succeeded` | A payment goes through, by card or recorded by hand. |
| `travel.payment.failed` | An automatic payment from a saved card fails. A failed payment at checkout sends no event, as the traveller can try again. |
| `travel.payment.refunded` | A refund is made. |

### Trip events

`data` has `tripId`, `slug` and `name`, such as:

```json
{ "tripId": "6650f1c2a9e4b3d2c1f0e9b1", "slug": "lofoten-ridge-walk", "name": "Lofoten ridge walk" }
```

### Departure events

`data` has `tripId`, `departureId` and `startDate`, such as `"2027-05-17"`.

### Booking events

`data` has `bookingId`, `reference`, `tripId`, `departureId`, `status` (`held`, `requested`, `confirmed`, `cancelled` or `expired`), `travellers` (how many), `total` and `currency`:

```json
{
  "bookingId": "6650f1c2a9e4b3d2c1f0eb42",
  "reference": "NO-7KQ2MX",
  "tripId": "6650f1c2a9e4b3d2c1f0e9b1",
  "departureId": "6650f1c2a9e4b3d2c1f0ea07",
  "status": "confirmed",
  "travellers": 2,
  "total": 225250,
  "currency": "EUR"
}
```

Amounts are whole minor units: `225250` with `EUR` is €2,252.50.

### Payment events

`data` has `bookingId`, `reference`, `paymentId`, `amount`, `currency` and `method`: `stripe` for card and other Stripe payments, `cash`, `transfer`, `cheque` or `other` for payments recorded by hand, and `refund` for refunds. For a failed automatic payment, `paymentId` is the Stripe PaymentIntent ID, such as `pi_…`; for a refund, it is the booking's ID.

Events never carry travellers' names, emails or other personal details. Use the booking reference to look them up in Travel Orbit.

## Delivery

Events are sent at least once. Each one waits in Travel Orbit until Orbit Exchange accepts it. If Exchange can't be reached, Travel Orbit tries again after 2 minutes, then waits twice as long each time, up to 12 hours between tries, for 12 tries in all. After that the event is no longer sent. Because a try can succeed even when the answer is lost, the same event can arrive twice: use `id` to spot it.
