---
title: "REST API"
description: "Package search, hotel content, destination codes and TripAdvisor, with the upstream keys kept server-side."
---

> Documentation Index
> Fetch the complete documentation index at: https://docs.easyjet-hackathon.uk/llms.txt
> Use this file to discover all available pages before exploring further.

# REST API

Five routes forward to the real APIs. The server injects the upstream credentials,
forwards the response untouched, and caches successful responses so 20 teams don't
exhaust the upstream rate limits.

| Route | Forwards to | Cached for |
|---|---|---|
| `/api/search/*` | metasearch `/search/*` | 5 minutes |
| `/api/hotel/<code>` | metasearch `/content/hotels/<code>` | 24 hours |
| `/api/tripadvisor/*` | TripAdvisor Partner API 2.0 | 1 hour |
| `/api/geography` | a local file, no upstream call | — |

Anything the upstream returns is passed straight through, error responses
included, so you can see what the real API said.

## Search for packages

```sh
curl -g -H "x-api-key: $KEY" \
  "$API/api/search/packages?departure=MAN&geography=ES,ESBA&startDate=2026-11-06&duration=7&room[0].adults=2&room[0].children=0&room[0].infants=0&take=10&page=1&isFlexible=false"
```

> **curl needs -g**
>
> `room[0].adults` contains square brackets, which curl treats as a glob pattern.
> Without `-g` the request is never sent. Browsers, `fetch` and Postman are fine.

| Parameter | Meaning |
|---|---|
| `departure` | Departure airport IATA code. Comma-separate for several: `LTN,LGW,STN` |
| `geography` | Destination code — see below |
| `startDate` | Departure date, `YYYY-MM-DD` |
| `duration` | Nights |
| `isFlexible` | `true` widens the search to three days either side |
| `room[N].adults` | Adults in room `N`, counting from 0. Same for `.children`, `.infants` |
| `take` | Results per page |
| `page` | Page number, from 1 |

The response has `status` (totals and price range), `offers` (the packages), and
`filters`.

There is also `/api/search/packages-meta`, which takes the same parameters and
returns just the aggregate view.

## Destination codes

Destinations use a hierarchical code, `<Country><Region><Resort>`, two letters per
level. Any depth works as a search term:

| Code | Means |
|---|---|
| `ES` | Spain |
| `ESBA` | Barcelona, Spain |
| `ESBABC` | a specific resort in Barcelona |

Fetch the full list, including which airports serve each destination:

```sh
curl -H "x-api-key: $KEY" $API/api/geography
```

Each entry has `code`, `name`, `type` (`Country`, `Region`, `Resort`,
`VirtualCountry`), `airportCodes`, and its `parents` and `children`.

> **The same data is queryable in GraphQL**
>
> This endpoint returns the raw nested tree, which suits building a cascading
> picker in one request. If you would rather filter or join it — every resort in
> Spain, which destinations `MAN` serves — use
> [`destinations`](/graphql-api#destinations) instead. Note the REST shape is
> nested and camelCase; the GraphQL one is flat and snake_case.

## Hotel content

```sh
curl -H "x-api-key: $KEY" $API/api/hotel/CYLN0072
```

Hotel codes here are the same codes as `bookings.hotel_code` in
[GraphQL](/graphql-api), so you can go from a booking straight to its hotel
description, images and facilities.

## TripAdvisor

Paths map onto the TripAdvisor Partner API 2.0 directly:

```sh
curl -H "x-api-key: $KEY" \
  "$API/api/tripadvisor/7392738"

curl -H "x-api-key: $KEY" \
  "$API/api/tripadvisor/7392738/reviews"
```

Available endpoints are `<id>`, `<id>/reviews` and `<id>/photos`, where `<id>`
is a TripAdvisor location id. There is no search endpoint — `location/{id}` already
returns the details, the recent reviews and the ratings breakdown in one
response, and its `partner_location_id` is the easyJet hotel code, so you can
join a TripAdvisor location straight back to `bookings.hotel_code`.

> **TripAdvisor has a daily budget**
>
> The account has a daily call limit shared by everyone. Responses are cached for an
> hour, so re-running the same query costs nothing — but a loop over thousands of
> hotels will spend the day's budget for the whole room. Cache results in your own
> app if you need to sweep a large list.

## Caching, and how to tell

Identical URLs are served from memory until the TTL expires. A cache hit is
typically 300 times faster than the upstream call, and the server logs which
happened:

```
upstream   200 /api/search/packages?departure=MAN...
cache hit  GET /api/search/packages?departure=MAN...
```

Failed upstream responses are never cached, so a transient upstream error won't
stick around. To force a fresh call, change any parameter, or restart the server.

Source: https://docs.easyjet-hackathon.uk/rest-api/index.mdx
