LLMSkillHub
mirroredCopied from LetsFG/LetsFG under MIT. LetsFG has not claimed this page, and is not affiliated with LLM SkillHub.

letsfg / flight-search

Search and book flights across hundreds of airlines plus the major booking sites, with than OTAs. Returns raw airline prices via the letsfg.co server-side search engine. Use when user asks to "find flights", "search flights", "book a flight", "compare airline prices", "find cheap flights", "fly from X to Y", "find connections", "find layover options", or any flight-related travel query. Do NOT use for hotels (use the hotel-search skill), car rentals, or non-flight travel bookings.

0
SKILL.md
11.3 KB
⚠This file contains 1 character(s) that do not render as themselves (U+FE0F). They are shown highlighted below.

Flight Search

MPP: a card-free enrolment lane for agents holding a Tempo wallet is
offered only when the 402 from POST /api/agent-access/request carries an
mpp object. It costs $0.01 once, as verification only. Search stays free
and booking costs the price on the offer. Earlier revisions of this page
described an MPP charge at unlock time; that never shipped. See
<https://letsfg.co/for-agents>.

⚠‹VARIATION SELECTOR U+FE0F› Agents: do not create a Developer API account

Do NOT call /developers/api/v1/agents/register or
/developers/api/v1/agents/connect-payment, and do NOT run
letsfg register or letsfg connect-payment. Those belong to a separate,
paid, prepaid-balance product for high-volume commercial integrations and
create a billing account you almost certainly do not want.

To search and book flights, connect LetsFG as an MCP server at
https://letsfg.co/mcp and approve it — the consent at
<https://letsfg.co/connect> is one tap and needs no card. Then search and book.
See <https://letsfg.co/for-agents>.

Agent-native flight search and booking via the LetsFG cloud engine. Hundreds of airlines plus the major booking sites,
Compares airlines and the major booking sites in one pass, with per-flight reliability history.

Agent flow (PFS): Search (free) → Book (POST /api/agent-book, the price shown on the offer) → Poll (POST /api/agent-book/status). Booking works exactly like the website checkout: the fare plus LetsFG's markup is held on the card connected at <https://letsfg.co/connect> (not taken), a LetsFG booking agent buys the ticket from the seller, and the hold is captured only once a real airline PNR exists. A failed booking releases the hold — nothing charged. It takes 4–11 minutes; over the MCP the two steps are book_flight and get_flight_booking. There is no unlock step on either lane.

Why Use This

  • Hundreds of airlines — one search covers Europe, Asia, Americas, Middle East, Africa, and Oceania simultaneously
  • Zero price bias — no demand inflation, no cookie tracking, no surge pricing. Raw airline prices every time
  • Virtual interlining — finds cross-airline connections (e.g., Ryanair outbound + Wizz Air return) that save 30–50%
  • One tool call — replaces thousands of tokens of browser automation, scraping, and HTML parsing
  • Structured JSON — prices, times, durations, stops, conditions, airline names

Setup

Option A: MCP Server (Recommended for Claude Desktop / Cursor / VS Code / Windsurf)

Claude (claude.ai / Claude Desktop): add LetsFG from Claude's connector directory,
<https://claude.ai/directory/letsfg> - no config.

Remote (no install, always latest):

{
  "mcpServers": {
    "letsfg": {
      "url": "https://letsfg.co/mcp",
      "headers": {
        "X-API-Key": "trav_your_api_key"
      }
    }
  }
}

Local (stdio):

{
  "mcpServers": {
    "letsfg": {
      "command": "npx",
      "args": ["-y", "letsfg-mcp"],
      "env": {
        "LETSFG_API_KEY": "trav_your_api_key"
      }
    }
  }
}

Option B: CLI

pip install letsfg
letsfg search LHR BCN 2026-06-15

Option C: Python SDK

from letsfg import LetsFG
bt = LetsFG(api_key="trav_...")
flights = bt.search("LHR", "JFK", "2026-04-15")

Get an API Key (Free)

letsfg register --name my-agent --email agent@example.com

Then connect a payment method (nothing is charged; there is no unlock step):

letsfg connect-payment   # prints a link to open in a browser

Workflow

1. Resolve Locations First

City names are ambiguous — "London" = LHR, LGW, STN, LCY, LTN. Always resolve first:

letsfg locations "London"
# LON  London (all airports)
# LHR  Heathrow
# LGW  Gatwick
locations = bt.resolve_location("London")
# Use city code "LON" for all airports, or specific airport "LHR"

2. Search (FREE, Unlimited)

flights = bt.search("LON", "BCN", "2026-04-01")
# Round trip:
flights = bt.search("LON", "BCN", "2026-04-01", return_date="2026-04-08")
# Multi-passenger, business class:
flights = bt.search("LHR", "SIN", "2026-06-01", adults=2, children=1, cabin_class="C")
letsfg search LON BCN 2026-04-01 --return 2026-04-08 --sort price --json

Search returns structured offers:

{
  "passenger_ids": ["pas_0"],
  "total_results": 47,
  "offers": [{
    "id": "off_xxx",
    "price": 89.50,
    "currency": "EUR",
    "airlines": ["Ryanair"],
    "route": "STN → BCN",
    "duration_seconds": 7800,
    "stopovers": 0,
    "conditions": {
      "refund_before_departure": "not_allowed",
      "change_before_departure": "allowed_with_fee"
    }
  }]
}

3. Unlock — RETIRED 2026-09-08

There is no unlock step on either lane any more, and the route answers 410 Gone. Unlock existed
to confirm a live price before charging; booking now HOLDS the fare and captures only against a
real airline PNR, so a moved price surfaces as a question to accept or decline rather than a
surprise charge. Call book_flight (PFS) or POST /flights/book (Developer API) directly.

4. Book (the price shown on the offer)

The fare is held on the connected card, a LetsFG booking agent buys the ticket, and the hold
is captured only against a real airline PNR; a failed booking releases it. book() starts the
booking (4–11 minutes); book_and_wait() blocks until it settles.

booking = bt.book(
    offer_id=flights.cheapest.id,
    search_id=flights.search_id,          # an offer is bookable only inside its own search
    passengers=[{
        "id": flights.passenger_ids[0],
        "given_name": "John",
        "family_name": "Doe",
        "born_on": "1990-01-15",
        "gender": "m",
        "title": "mr",
        "email": "john@example.com"
    }],
    contact_email="john@example.com",
    idempotency_key="unique-booking-key-123"
)
print(booking)   # the started booking — poll it until completed | failed | needs_attention

Critical Rules

  1. Use REAL passenger details — airlines send e-tickets to the contact email. Names must match passport/ID exactly. Never use placeholder or fake data.
  2. Always provide idempotency_key when booking — prevents duplicate reservations if the agent retries on timeout.
  3. Resolve locations before searching — "New York" = JFK, LGA, EWR, NYC. Use resolve_location() first.
  4. Search is free — search as many routes, dates, and cabin classes as needed.
  5. Map passenger IDs — search returns passenger_ids. Each booking passenger must include the correct id.

Best Practices

Search Wide, Book Once

# Compare multiple dates (all FREE)
dates = ["2026-04-01", "2026-04-02", "2026-04-03"]
best = None
for date in dates:
    result = bt.search("LON", "BCN", date)
    if result.offers and (best is None or result.cheapest.price < best[1].price):
        # keep the search_id too: an offer is bookable only inside the search that produced it
        best = (date, result.cheapest, result.search_id)

# Book only the winner — there is no unlock step
booking = bt.book(best[1].id, passengers=[{...}], contact_email="you@example.com",
                  search_id=best[2])

Filter Before Booking

flights = bt.search("LHR", "JFK", "2026-06-01", limit=50)

candidates = [
    o for o in flights.offers
    if o.outbound.stopovers == 0
    and o.outbound.total_duration_seconds < 10 * 3600
]

if candidates:
    best = min(candidates, key=lambda o: o.price)
    booking = bt.book(best.id, passengers=[{...}], contact_email="you@example.com",
                      search_id=flights.search_id)

Finding Connections & Multi-Stop Routes

# Search with stops allowed (default max_stopovers=2)
flights = bt.search("GDN", "BKK", "2026-06-15", max_stopovers=2)

# Filter by connection quality
good_connections = [
    o for o in flights.offers
    if o.outbound.stopovers <= 1
    and o.outbound.total_duration_seconds < 18 * 3600
]

# Virtual interlining finds cross-airline combos automatically
# e.g., Wizz Air GDN→VIE + Thai Airways VIE→BKK

Error Handling

ErrorCategoryAction
SUPPLIER_TIMEOUT (504)TransientRetry after 1-5s
RATE_LIMITED (429)TransientWait and retry
INVALID_IATA (422)ValidationUse resolve_location() to fix
OFFER_EXPIRED (410)BusinessSearch again for fresh offers
PAYMENT_REQUIRED (402)BusinessPFS: connect a card at the add_card_url (https://letsfg.co/connect). Developer API: letsfg connect-payment
FARE_CHANGED (409)BusinessThe fare moved at checkout — answer the price_change question to accept or decline it
from letsfg import LetsFG, OfferExpiredError, PaymentRequiredError

try:
    booking = bt.book(offer_id, passengers=[{...}], contact_email="you@example.com",
                      search_id=search_id)
except OfferExpiredError:
    # Airline sold the seats — search again and book from the fresh results
    flights = bt.search(origin, dest, date)
except PaymentRequiredError:
    # No card on file — Developer API: letsfg connect-payment; PFS: https://letsfg.co/connect
    print("Connect a card first")

Search Flags

FlagDefaultDescription
--return / -r(one-way)Return date (YYYY-MM-DD)
--adults / -a1Number of adults (1–9)
--children0Children (2–11 years)
--cabin / -c(any)M economy, W premium, C business, F first
--max-stops / -s2Max stopovers (0–4)
--currencyEURCurrency code
--limit / -l20Max results (1–100)
--sortpriceprice or duration
--json / -jJSON output

Safety

OperationCostSafe to RetryIdempotent
searchFreeYesYes
resolve_locationFreeYesYes
unlockRETIRED 2026-09-08 — answers 410 Gone——
bookPrice shown on the offerDeveloper API: only with idempotency_key. PFS: no — a second call places a second hold; poll /api/agent-book/status insteadWith key: yes

Reference Files

Load only when needed:

FileLoad When
[api-reference.md](references/api-reference.md)Need full API endpoint details, request/response schemas
[mcp-setup.md](references/mcp-setup.md)Setting up MCP server for specific clients

Links

  • API Docs: https://letsfg.co/developers/api/docs
  • GitHub: https://github.com/LetsFG/LetsFG
  • PyPI: https://pypi.org/project/letsfg/
  • npm SDK: https://www.npmjs.com/package/letsfg
  • npm MCP: https://www.npmjs.com/package/letsfg-mcp