Skyscanner Flight API Integration: Developer Guide

Implement Skyscanner Flights Live Prices with x-api-key authentication, create/poll lifecycle, request-response models, itinerary/leg/segment mapping, agents, pricing options, rate limits and observability.

Editorial information
Changelog
  • 2026-09-26 — Provider companion standard applied; rate limits, refresh-price lifecycle, pagination and evidence boundaries clarified.
Related platform profiles
Advertisement

The core architecture decision in a Skyscanner flight integration is to model asynchronous search sessions + a canonical flight model + provider handoff, instead of exposing upstream JSON directly to the UI.

Skyscanner's current Flights Live Prices flow uses two endpoints:

text
POST /flights/live/search/create
        |
        v
initial / partial results
+ sessionToken
        |
        v
POST /flights/live/search/poll/{sessionToken}
        |
        v
progressively richer results
        |
        v
completed

This is not a classic one-request/one-response integration.

Provider companion snapshot

AreaStatus
AccessApproved Skyscanner partnership + API key
AuthServer-side x-api-key
Primary contractsFlights Live Prices create/poll, itinerary refresh, Autosuggest
Data directionClient/backend initiated create + poll
PaginationLive Prices is not a paginated collection; completeness progresses through session polling
PollingCore part of the contract after create
Public default rate limitsFlights Live Pricing Create: 100/sec and 100/min; Poll: 100/sec and 500/min. Partner agreements may differ
Reprice/refreshitineraryrefresh/create + itineraryrefresh/poll refresh selected-itinerary pricing
Booking ownershipDownstream airline/OTA after pricing-option/deeplink handoff
Evidence levelOfficial public docs reviewed; no claim of an authorized partner-account test
Code examplesIllustrative

Capability boundary

text
Place discovery       -> Flights Autosuggest
Initial live search   -> /flights/live/search/create
Search completion     -> /flights/live/search/poll/{sessionToken}
Selected price refresh-> /flights/live/itineraryrefresh/create
Refresh completion    -> /flights/live/itineraryrefresh/poll/{refreshSessionToken}
Booking handoff       -> pricing option / agent deep link

Search session, selected-itinerary refresh and downstream booking are different state machines.

Why pagination is N/A

Flights Live Prices is not a conventional page=2 collection. Result completeness evolves through create/poll on the same search session. Do not bolt on generic pagination; manage session progress and merge semantics instead.

Official rate-limit defaults

Skyscanner's current public Rate Limits page lists these standard Flights defaults:

APIPer secondPer minute
Flights Live Pricing — Create100100
Flights Live Pricing — Poll100500
Flights Indicative Prices100500

Skyscanner states that limits are API-key/partner specific and can be adjusted. Runtime 429 metrics and the active partner quota therefore remain the operational source of truth.

Price refresh / reprice lifecycle

Do not treat the first live-search pricing option as checkout truth. Skyscanner documents a selected-itinerary refresh flow:

text
search/create
   -> search/poll
   -> user selects itinerary
   -> itineraryrefresh/create
   -> itineraryrefresh/poll
   -> refreshed pricing options
   -> agent deeplink

If the refresh changes price, the UI should not keep the stale search price as confirmed state. A safer internal lifecycle is:

text
SEARCH_PRICE
REFRESHING
REFRESHED
PRICE_CHANGED
HANDOFF_READY

For platform responsibilities, commercial boundaries and operational decisions, see the Skyscanner profile. This guide covers implementation contracts and request/response handling.

1. Access and authentication

Access requires an approved Skyscanner partnership/API key.

Authentication:

http
x-api-key: <your-api-key>

Never expose the key in browser code or public repositories.

ts
interface SkyscannerCredentials {
  apiKeyRef: string;
}

Recommended boundary:

text
Browser
  -> Your backend
      -> Skyscanner API

2. Flights Live Prices create endpoint

http
POST https://partners.api.skyscanner.net/apiservices/v3/flights/live/search/create
Content-Type: application/json
x-api-key: <api-key>

Minimal request:

json
{
  "query": {
    "market": "UK",
    "locale": "en-GB",
    "currency": "GBP",
    "queryLegs": [
      {
        "originPlaceId": { "iata": "LHR" },
        "destinationPlaceId": { "iata": "SIN" },
        "date": { "year": 2026, "month": 10, "day": 12 }
      }
    ],
    "adults": 1,
    "cabinClass": "CABIN_CLASS_ECONOMY"
  }
}

Required request concepts include market, locale, currency, query legs and adults. Optional fields include children ages, carrier/agent inclusion or exclusion, sustainability data, nearby airports and baggage-related options when enabled.

3. Internal search request

Do not make provider enums your domain contract.

ts
interface FlightSearchRequest {
  market: string;
  locale: string;
  currency: string;

  legs: Array<{
    origin: { iata?: string; entityId?: string };
    destination: { iata?: string; entityId?: string };
    departureDate: string;
  }>;

  passengers: {
    adults: number;
    childAges: number[];
  };

  cabinClass:
    | "economy"
    | "premium_economy"
    | "business"
    | "first";
}
text
Internal request
   -> Skyscanner mapper
   -> create payload

4. Handling the create response

The create call returns initial results and a sessionToken. Skyscanner documents the create response as a fast initial/incomplete subset used for time to first result.

Conceptual response:

json
{
  "sessionToken": "session-token",
  "status": "RESULT_STATUS_INCOMPLETE",
  "content": {
    "results": {
      "itineraries": {
        "itinerary-1": {
          "pricingOptions": []
        }
      }
    }
  }
}

A successful create call does not mean the search is complete.

ts
type SearchStatus =
  | "created"
  | "partial"
  | "polling"
  | "complete"
  | "failed"
  | "expired";

5. Poll endpoint

http
POST https://partners.api.skyscanner.net/apiservices/v3/flights/live/search/poll/{sessionToken}
x-api-key: <api-key>

Model session state explicitly:

ts
interface FlightSearchSession {
  id: string;
  provider: "skyscanner";
  providerSessionToken: string;
  requestHash: string;
  status: SearchStatus;
  createdAt: string;
  lastPolledAt?: string;
  completedAt?: string;
  pollCount: number;
}

6. Polling strategy

Avoid tight fixed polling loops.

Example:

text
poll 1 -> 300 ms
poll 2 -> 500 ms
poll 3 -> 800 ms
poll 4 -> 1200 ms
poll 5+ -> 1500-2000 ms

Stop on completion, client disconnect, max duration, unrecoverable errors or invalid sessions.

ts
interface PollPolicy {
  maxDurationMs: number;
  maxPollCount: number;
  initialDelayMs: number;
  maxDelayMs: number;
}

7. Progressive results

Render first useful results before the whole supplier fan-out matures.

ts
interface FlightSearchViewState {
  status: "searching" | "partial" | "complete" | "error";
  itineraries: FlightItinerary[];
  lastUpdatedAt: string;
}
text
create
  -> render first results
  -> poll
  -> merge/deduplicate
  -> rerank
  -> render
  -> poll
  -> complete

8. Canonical flight model

Keep itinerary, leg, segment, carrier, agent and pricing option separate.

text
Itinerary
  -> Leg
      -> Segment
          -> Carrier

Itinerary
  -> PricingOption
      -> Agent
      -> DeepLink
ts
interface FlightItinerary {
  id: string;
  legIds: string[];
  pricingOptions: FlightPricingOption[];
  score?: number;
}

interface FlightLeg {
  id: string;
  origin: string;
  destination: string;
  departure: string;
  arrival: string;
  durationMinutes: number;
  segmentIds: string[];
  stopCount: number;
}

interface FlightSegment {
  id: string;
  origin: string;
  destination: string;
  departure: string;
  arrival: string;
  marketingCarrierId?: string;
  operatingCarrierId?: string;
  flightNumber?: string;
}

9. Carrier and agent are different

Carriers market or operate flights. Agents sell/book itineraries.

ts
interface FlightAgent {
  id: string;
  name: string;
  type?: "airline" | "ota";
  rating?: number;
}

One itinerary may be sold by several agents with different prices, fees, baggage terms or deep links.

10. Pricing options

ts
interface FlightPricingOption {
  id: string;
  agentIds: string[];
  price: {
    amount: number;
    currency: string;
  };
  deepLink?: string;
  transferType?: string;
  farePolicy?: string;
}
text
itinerary != offer

11. Normalize response entities

text
Skyscanner JSON
    |
    v
Provider DTO
    |
    v
Entity dictionaries
    |
    +--> itineraries
    +--> legs
    +--> segments
    +--> carriers
    +--> agents
    |
    v
Canonical flight model

The frontend should consume your model, not Skyscanner DTOs.

12. Merge poll results

Do not blindly append every poll response.

ts
function mergeSearchResults(
  current: FlightSearchResult,
  incoming: FlightSearchResult
): FlightSearchResult {
  // upsert by provider-stable id
  // update pricing options
  // retain newest provider state
  return current;
}

13. Autosuggest

Use Skyscanner's Flights Autosuggest for place resolution rather than guessing IATA codes from free text.

http
POST https://partners.api.skyscanner.net/apiservices/v3/autosuggest/flights
json
{
  "query": {
    "market": "UK",
    "locale": "en-GB",
    "searchTerm": "London",
    "includedEntityTypes": [
      "PLACE_TYPE_CITY",
      "PLACE_TYPE_AIRPORT"
    ]
  },
  "limit": 10,
  "isDestination": false
}
ts
interface FlightPlace {
  id: string;
  entityId?: string;
  iata?: string;
  name: string;
  type: "airport" | "city" | "country";
}

14. Cache strategy

A live price cache key should include route, dates, passengers, cabin, market, locale and currency.

text
origin
+ destination
+ dates
+ adults
+ child ages
+ cabin
+ market
+ locale
+ currency

Use short-lived caching for duplicate suppression and burst control, not as permanent booking truth.

15. Indicative vs Live

text
Discovery
  -> indicative / aggregated data

Booking intent
  -> Flights Live Prices

Do not run a full live create/poll cycle for every flexible-date discovery cell.

16. Rate limits and 429

The API reference documents 400, 401, 403, 404, 429, 500 and 503 response classes.

For 429:

text
backoff
+ jitter
+ quota metrics
+ duplicate suppression
+ short-lived cache

Potential retry candidates:

text
429
500
503
network timeout

Do not blindly retry 400/401/403.

17. Error taxonomy

text
SKYSCANNER_AUTH
SKYSCANNER_FORBIDDEN
SKYSCANNER_BAD_REQUEST
SKYSCANNER_RATE_LIMIT
SKYSCANNER_SESSION_INVALID
SKYSCANNER_TIMEOUT
SKYSCANNER_UPSTREAM
SKYSCANNER_PARSE
SKYSCANNER_EMPTY_RESULT
SKYSCANNER_DEEPLINK

Validate the itinerary, dates, passenger context, currency, final price and mobile redirect after click.

ts
interface FlightClickEvent {
  searchId: string;
  itineraryId: string;
  pricingOptionId: string;
  agentId: string;
  displayedPrice: number;
  currency: string;
  clickedAt: string;
}

19. Observability

Track search-session metrics:

text
search_created
time_to_first_result
time_to_complete
poll_count
itinerary_count
agent_count
api_429
api_5xx
empty_result
deeplink_click
deeplink_failure

Example context:

json
{
  "searchId": "srch_123",
  "provider": "skyscanner",
  "market": "UK",
  "currency": "GBP",
  "route": "LHR-SIN",
  "pollCount": 4,
  "providerStatus": "complete"
}

20. Example SLOs

Calibrate to your own traffic and partnership limits.

text
create success              >= 99%
time to first useful result <= product budget
poll completion             >= 98%
429 rate                    < quota threshold
deeplink success            >= 99%
search error rate           < 1%

21. Test matrix

TestExpected
one-wayone leg
returntwo legs
directzero stops
multi-segmentcorrect segment chain
multiple agentsone itinerary, multiple offers
child passengerage context preserved
business cabincorrect cabin
different currencycorrect currency
create partialpartial UI
repeated pollsno duplicate entities
completedpolling stops
429backoff
401no blind retry
503controlled retry
click handoffitinerary preserved

22. Go-live checklist

  • API key kept server-side
  • partnership access ready
  • create mapper tested
  • poll orchestration tested
  • session state persisted
  • cancellation/timeout policy defined
  • itinerary/leg/segment models separated
  • carrier/agent distinction correct
  • pricing options normalized
  • autosuggest mapping implemented
  • poll merge idempotent
  • 429/backoff implemented
  • observability dashboard available
  • deep-link tests complete
  • correlation IDs available
  • client disconnect stops polling

Summary

The correct integration boundary is:

text
Search Request
   -> Skyscanner Adapter
   -> create
   -> partial normalize
   -> poll
   -> merge
   -> canonical itinerary
   -> pricing options
   -> agent deep link
   -> post-click quality measurement

Developer success means managing the asynchronous lifecycle correctly, normalizing provider-specific entities, and preserving itinerary and price context through the provider handoff.

Idempotency and ordering

Correlate create, poll and itinerary-refresh events by provider session/token identity. Reprocessing the same poll response must not create duplicate itineraries or pricing options. Upsert incoming entities by provider-stable IDs and prevent older poll snapshots from overwriting newer refresh state.

text
same session + same entity revision -> idempotent upsert
older snapshot                       -> ignore
newer pricing state                  -> replace/update
Technical advisory

Planning a similar integration?

We can review requirements, feed/API design and the production approach with you.

Discuss your project →

Sources

Related content

flight-metasearch

Skyscanner: Flight Discovery, Live Prices and Booking Handoff

skyscanner.com

Choose Skyscanner live or indicative flight data, preserve itinerary and seller identity, and diagnose price, polling and booking-handoff failures.

skyscannerflightapi
Explore →
integration

Wego Affiliate API Integration: Developer Guide

developers.wego.com

Implement the Wego Affiliate API around OAuth client credentials, search creation, polling, offset merging, trip/fare/provider models, rate limits, handoff and commercial reconciliation.

wegoaffiliateapi
Explore →
comparison

Google Flights vs Skyscanner: Flight Metasearch Comparison

Compare Google Flights and Skyscanner across flight search, discovery, price tracking, API access and provider handoff.

google-flightsskyscannerflight
Explore →
car-rental-metasearch

Skyscanner Cars: Live Search, Discovery and Seller Handoff

skyscanner.com

Separate Skyscanner car-hire live, indicative and agent products; preserve rental context and diagnose session, price and handoff failures.

skyscannercar-rentalapi
Explore →
turkey-market

ENUYGUN vs Skyscanner in Turkey: Comparable Dimensions

Compare ENUYGUN and Skyscanner in Turkey only across comparable dimensions: discovery, transaction ownership, vertical coverage, handoff and developer model.

enuygunskyscannerturkey
Explore →
operations

Rate Limit & Quota Exhaustion Playbook

Manage supplier API rate limits and quota exhaustion with token budgets, backoff, queues, caching and traffic shaping.

apirate-limitquota
Explore →