Docs / Changelog
Changelog
A summary of every breaking and notable change.
v2026-08-28
- `cabinClass` on `POST /v1/search` no longer defaults to `economy`. Omitting it now means "no cabin stated" rather than "economy", which is what it always should have meant. Flight results are unaffected — the search still queries economy when you do not name a cabin — but scoring can now tell the difference.
- V19 (seat preference) scores the cabin you actually asked for. Its spec activates it only when a desired fare class was specified, which was impossible to honour while an omitted cabin arrived looking like a chosen economy. A search that states no cabin now drops V19 instead of scoring against an assumed one, and the category weight redistributes rather than counting a placeholder.
- V19 is scored per leg and averaged, per its spec formula, rather than reading a single option-level number. No provider writes a per-leg count yet, so this changes no score today — it means a future per-leg feed needs no formula change.
- Award options whose programme does not publish a remaining-seat count are no longer treated as sold out. Checked live: every award programme reports a real count except AAdvantage, which always reports zero — so a zero was costing every American Airlines award about seven points of TEO Score on every search, and hiding them from the results list entirely. Both are fixed: V19 now stands aside when no count is published, and results no longer drop a flight for want of one.
- Known limit, stated plainly: only award options carry per-cabin remaining-seat data today, so V19 drops on cash options. Because a dropped category redistributes its weight, that gives award options a small edge over otherwise identical cash ones until per-cabin availability reaches the cash path.
v2026-08-25
- Fixed: `GET /v1/flights/airports` returned `502 FETCH_UPSTREAM_ERROR` on every call. The endpoint validated the provider’s airport data against a schema that required `city_name`, `iata_city_code`, `iata_country_code`, `latitude`, `longitude`, `time_zone` and `city` — all of which come back as `null` for sparse airport records, which is most of the table. The error named the upstream, but the fault was ours. `/v1/flights/airlines` and `/v1/flights/aircraft` were never affected.
- Airport records now document what was always true: only `id` and `name` are guaranteed on an airport. Everything else may be `null`.
- Upstream 5xx errors now keep their specific error code and their real `retryable` value instead of being flattened into `FETCH_UPSTREAM_ERROR` with `retryable: true`. A deterministic failure no longer advertises itself as worth retrying. The free-text `message` is still masked.
- TypeScript SDK v0.4.0 corrects the `DuffelAirport` type to match — the seven fields above are now `?: T | null`. This is a compile-time break under `strictNullChecks` if you assigned any of them to a non-nullable target.
v2026-07-24
- Seat maps: `/v1/search` now attaches real seat availability (`details.seatMap` summary + `details.seatMapSegments`) for cash offers, shown as a “Seatmap” chip on results. Award/other providers have no seat map.
- V19 (seat preference) & V20 (contiguous seating) now compute on that real seat data — still weight-0 (display-only, doesn’t change ranking yet).
- V11 (Same-Day Recovery) simplified to `min(100, sameAirlineAlts×50 + otherAirlineAlts×20)`; in practice usually neutral 50 until recovery enumeration is wired.
- V8 renamed to “Layover Duration Efficiency”; layover MCT now uses a curated per-hub table (estimated, not official SSIM) with a 90/120-min default fallback.
- V5 (schedule fit) now weighted 0.50 within Schedule & Time when a preferred time is set. V16 (seat comfort) documented as defaulting to a per-cabin baseline when seat dimensions aren’t available.
- Docs: scoring-engine page adds a plain-English “is this real data?” view — for every variable, what it measures, what we do, how it’s implemented, its limitation, and whether the data is real vs estimated.
v2026-07-23
- TEOScore category labels aligned to the TEO21 spec — `categoryScores` is now keyed by the canonical names (e.g. `Economic Value` → `Financial Value & Loyalty`). Not a type change (still `Record<string, number>`), but the string values differ.
- New 8th category `Seating Logistics & Strategy` is now returned in the /v1/score/score response.
- TypeScript SDK v0.3.0 adds `TEO_SCORE_CATEGORY_LABELS` and `normalizeTeoScoreCategoryLabel()` for mapping legacy category labels onto the canonical set.
v2026-07-01
- Unified auth: one user identity works across consumer and partner surfaces.
- Cursor pagination is now mandatory for list endpoints larger than 100 items.
- New `booking.cancelled` webhook event.
v2026-05-15
- TEO21 V10 transfer protection tier added to the /v1/score/score response.
- Booking write support added for cash fares; previously only read was supported.
- IP allowlist now supports IPv6 CIDR.
v2026-04-01
- New TEO Score V2 (PMV) reference data tables.
- Per-application rate limits in addition to per-key.
- Webhook delivery signature is now HMAC-SHA256 instead of plain SHA-256.