About letsfg
LetsFG is a flight and hotel search and booking skill for AI agents, with additional search for transfers and activities. It offers access through MCP, SDK, CLI, and API, and supports asynchronous bookings that can be checked for completion.
Key features
- 01Search flights across airlines and booking sites
- 02Search hotels, transfers, and activities
- 03Resolve city names and airport codes
- 04Book flights and hotels
- 05Poll booking status
Use cases
- 01Finding flights across multiple sellers
- 02Comparing bookable hotel offers
- 03Searching ground transfers or activities
- 04Tracking an in-progress travel booking
MCP support
LetsFG provides an MCP server at https://letsfg.co/mcp for compatible clients. It exposes travel search and booking capabilities, including flights, hotels, transfers, and activities.
Install
Copy the command and run it in a terminal.
npx skills add https:/ / github.com/ letsfg/ letsfg --skill letsfgAfter installing, type/letsfgin Claude Code to confirm it loaded.
Bundled files
References and scripts installed along with SKILL.md.
.dockerignore.mcp.json.gitignoreCODE_OF_CONDUCT.mdCLAUDE.mdBarWidget.qmlCONTRIBUTING.mdAGENTS.mdLICENSEDockerfile.pythonDockerfileREADME.mdSECURITY.mdOMARCHY-PLUGIN.mdModel.jsPanel.qmlcontext7.jsondocker-compose.yml.github/dependabot.yml.github/workflows/sdk-tests.ymltest.ymlplugin-scanner.ymlagent-skills-contribution/packages/skills-catalog/skills/(tooling)/letsfg/references/api-reference.mdmcp-setup.mdassets/OFL-Kalam.txtOFL.txtairports.jsonranking.jsname-fallbacks.jsonassets/icons/LICENSEDetails
From the project READMESKILL.md — LetsFG Capabilities
MPP: a card-free enrolment lane for agents holding a Tempo wallet is offered only when the
402fromPOST /api/agent-access/requestcarries anmppobject. 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.
⚠️ Agents: do not create a Developer API account
Do NOT call
/developers/api/v1/agents/registeror/developers/api/v1/agents/connect-payment, and do NOT runletsfg registerorletsfg 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/mcpand 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.
Machine-readable skill manifest for AI agents and documentation indexers.
Identity
- Name: LetsFG
- Type: API + SDK + MCP Server + CLI
- Purpose: Agent-native flight and hotel search and booking
- Compatible agents: OpenClaw, Perplexity Computer, Claude Desktop, Cursor, Windsurf, and any MCP-compatible client
- API Base URL:
https://letsfg.co/developers/api/v1 - MCP Endpoint:
https://letsfg.co/mcp(Streamable HTTP) - Packages: PyPI
letsfg· npmletsfg· npmletsfg-mcp - License: MIT
Access Modes
| Mode | Best for | Speed | Cost |
|---|---|---|---|
| MCP / SDK / CLI (PFS token) | Almost every agent. Search + booking | 8–10 s to first results | Free auth, free search, booking at the price on the offer |
Developer API (https://letsfg.co/developers) | Business / commercial / high-volume (hotels work on either credential) | 2–5 s (discover) · 8–10 s to first results (full search) | Look-to-book: 200 searches free after every booking, then $0.01. Booking via POST /flights/book, no booking fee, no transaction fee |
Skills
search_flights
Search every airline in the world AND the major booking sites (Google Flights, Skyscanner, Kiwi, Kayak, Momondo) in one call. Returns real-time prices plus per-flight reliability history.
- Cost: FREE (10 per 10 min, 30/hour, 100/day)
- Input: origin (IATA), destination (IATA), date_from, optional: date_to, return_from, return_to, adults, children, infants, cabin_class (M/W/C/F), max_stopovers, currency, sort, limit
- Output: List of flight offers with price, airlines, times, segments, conditions, passenger_ids
- Note: On PFS (Bearer token), call
book_flightdirectly — no unlock step — then pollget_flight_booking. The Developer API has no unlock step either: book withPOST /flights/bookand pollGET /flights/bookings/{id}. - Rate limit (PFS): 10 searches per 10 min, 30 per hour, 100 per day, per account (per card once one is added). Polling results never counts.
resolve_hotel_city
Resolve a place name to the supplier city id that hotel search needs.
- Cost: FREE (a card must still be on file)
- Endpoint:
POST /api/v1/hotels/destinations - Input: text (place name, e.g. "Warsaw")
- Output: Matches, best first. Use
Idas city_id andNameas city_name.
search_hotels
Search real, bookable hotel inventory.
- Cost: FREE. Searching needs no card; an account with no card on file gets a daily number of hotel searches. Booking needs a payment method on file and returns HTTP 402 without one.
- Auth: Either a Developer API key (
X-API-Key) or the PFS token from the connect flow. The same card authorises flights and hotels. - Endpoint:
POST /api/v1/hotels/search - Input: city_id, city_name, check_in, check_out, adults, children, child_ages, nationality, currency (USD by default), limit
- Output: hotels[] each with offers[] carrying
price(the all-in total the guest pays, incurrency),fx_rate,expected_cost,refundable,free_cancellation_until(refundable rates only),cancellation_policy,combination_id_v2andsession_id - Note: Every rate type is sold, refundable and non-refundable — show
refundableandfree_cancellation_untilbefore booking. Keep the chosen offer'ssession_idandcombination_id_v2; booking needs both.priceis what the guest pays. - Allowance: 1,000 hotel searches free after every hotel booking, then blocks of 1,000 for $5.00 from prepaid balance.
search_transfers
Search ground transfers — private cars, taxis, shared shuttles, airport express.
- Cost: FREE
- Input: origin, destination, date, passengers
- Output: Transfer options with prices and vehicle types
search_activities
Search activities — tours, tickets, day trips (limited supplier coverage).
- Cost: FREE
- Input: location, date_from, date_to
- Output: Activity options with prices, descriptions, availability
resolve_location
Resolve city names to IATA airport/city codes.
- Cost: FREE
- Input: query (city name, e.g. "London")
- Output: List of matching IATA codes (e.g. LON, LHR, LGW, STN, LTN, LCY)
unlock_flight_offer
RETIRED 2026-09-08 — the route answers 410 Gone.
- There is no unlock step on either lane. Booking holds the fare and captures only against a real PNR, which is what unlock existed to protect against. Call
/api/agent-book(PFS) orPOST /flights/book(Developer API) instead. - Endpoint:
POST /api/v1/bookings/unlock— answers410 Gone, and the SDKs'unlock()fails the same way.
book_flight
Book an offer.
- PFS (Bearer token):
POST /api/agent-book. No unlock step — search, then book directly. Works for every offer in the results, whichever seller it came from. Exactly what the website checkout does: the price shown is held on the connected card (not taken), a LetsFG booking agent buys the ticket from the seller, and the hold is captured only once a real airline PNR exists. If the booking fails the hold is released and nothing is charged.- Input:
search_id+offer_idexactly as search returned them (offers expire ~15 min),contact_email, and ONEpassengerper call: given_name, family_name, born_on, gender (m/f), nationality (ISO-2), phone_number + phone_country, address_line1, address_city, address_postal, address_country; passport_number/country/expiry optional. - Output (seconds):
{"state": "booking_in_progress", "booking_ref": "eyJ...", "held": {"amount": 93, "currency": "EUR", "card": "visa ending 5709"}, "charged": 0}. The booking itself takes 4–11 minutes — pollget_flight_booking. - Nothing charged on:
{"error": "missing_details", "missing_fields": [...]}(ask, call again),payment_method_requiredandpayment_declined(both carryadd_card_url: https://letsfg.co/connect). - Never call it twice for the same trip while one is in progress — that places a second hold.
- CLI:
letsfg book ws_off_xxx --search-id ws_xxx --passenger '{...}' --email [email protected] - Python:
bt.book(offer_id=..., passengers=[{...}], contact_email=..., search_id=...)
- Input:
- Developer API:
POST /api/v1/flights/book. The same flow with no unlock step: the fare is held on the connected Revolut method, a LetsFG booking agent buys the ticket, and the hold is captured only against a real airline PNR. No booking fee, no transaction fee.- Prerequisite: a Revolut method connected with
POST /api/v1/agents/connect-payment(nothing is charged to connect). - Input: search_id, offer_id, passengers (given_name, family_name, born_on, gender, email, phone_number, nationality, ...), contact_email, idempotency_key
- Output:
202withbooking_id,held,charged: 0andpoll_url. PollGET /api/v1/flights/bookings/{booking_id}untilterminal:completed(pnr,charged_amount) |failed(hold released, nothing charged) |needs_attention.
- Prerequisite: a Revolut method connected with
- CRITICAL (both paths): Use real passenger names (must match passport/ID) and real email (airline sends e-ticket there).
get_flight_booking
Where a booking started by book_flight has got to (PFS). POST /api/agent-book/status {"booking_ref": "eyJ..."}.
- Cost: FREE. Poll every 20–30 s.
- States:
booking_in_progress(the agent is at the seller's checkout — keep waiting) →completed(pnr,charged_amount,currency— booked) |failed(failure_reason; the hold was released, nothing charged) |needs_attention(a human at LetsFG is checking it — do NOT book again; the traveller will be emailed).updated_at_mssays when it last moved. - Only
completedwith a PNR means booked.
book_hotel
Start a hotel booking. Returns a job, NOT a booking.
- Cost: the offer's
price. It is held on the connected card (not taken), LetsFG books the room and pays the supplier, and the hold is captured only once the hotel confirms. A failed booking releases the hold. No reservation fee, no deposit, no pay link. - Endpoint:
POST /api/v1/hotels/book - Input: session_id (the chosen offer's), hotel_code, combination_id_v2, expected_price, expected_cost, currency, fx_rate, city_id, city_name, check_in, check_out, adults, guests[{title, first_name, last_name}], email, phone; optional phone_country_code, special_requests, idempotency_key
- Output: booking_job_id, booking_id, status "in_progress", the amount held, poll URL
- Asynchronous: a real booking takes minutes — the rate is re-blocked at the supplier, the room
committed and paid. Poll
get_hotel_bookinguntil status issucceeded,failedorattention. - CRITICAL: send
expected_price,expected_cost,currencyandfx_rateback exactly as the chosen offer returned them, or the booking is refused asprice_mismatch— a guest is never charged a price they did not agree to. There is noexpected_balance. - Local packages: hotel booking needs
letsfg-mcp2026.5.77+,letsfg2026.5.101+ (Python) orletsfg2026.5.74+ (npm). Earlier releases send the retiredexpected_balancecontract and every hotel booking they make is refused. The hosted MCP needs no update. - CRITICAL: never call this again while its job is running — poll the job. A retry with the same
idempotency_keyreturns the existing job instead of booking twice. - Note: guest names, phone and e-mail are checked before anything is held (
400 invalid_details). - CRITICAL:
guestsneeds a name for every person in the room, children included: adults first, then children inchild_agesorder. Fewer names than the searched party fails the booking before anything reaches the hotel, and the hold is released.
get_hotel_booking
Collect the result of a booking started with book_hotel.
- Cost: FREE
- Endpoint:
GET /api/v1/hotels/booking/{booking_job_id} - Output: status —
in_progress, thensucceeded(confirmation, total_price + currency = what the guest is charged, refundable, free_cancellation_until, terms with the full cancellation ladder) |failed(error; the hold was released, nothing charged) |attention(error; a person at LetsFG is confirming the outcome with the supplier, the hold is kept — do NOT book again) - Note: the guest is e-mailed however the booking ends.
cancel_hotel_booking
Release a hotel reservation.
- Cost: Free on a refundable rate before
free_cancellation_until— the charge is refunded in full. A cancellation the hotel would charge for (a non-refundable rate, or past that date) is refused with409; the hotel's own ladder is in the booking'sterms. - Endpoint:
POST /api/v1/hotels/cancel - Input: confirmation (only your own bookings)
- Output: confirmation, charge, refund
- Note: drives a browser at the supplier and takes over a minute. If it times out, do NOT assume it failed — re-check before retrying.
register
Register a new AI agent.
- Cost: FREE
- Input: agent_name, email
- Output: api_key (permanent credential)
connect_payment
Developer API only. POST /api/v1/agents/connect-payment returns a one-time connect_url; a
person opens it in a browser and saves a card or Revolut Pay. Agents on the PFS lane do not call
this — connecting at https://letsfg.co/connect needs no card, and the card is asked
for at their first booking.
- Cost: FREE — nothing is charged to connect
- Output:
connect_url(valid for one hour) - Note:
setup_payment(POST /agents/setup-payment) was retired with Stripe on 2026-09-08 and answers410 Gone.
get_agent_profile
Get current agent's profile, usage stats, and payment status.
- Cost: FREE
- Output: Agent details, search count, booking count, payment status
Authentication
PFS (recommended — almost every agent): a Bearer token from the connect flow. Connecting needs no card and nothing is charged. The card is asked for at the first booking, in a 0.00 Revolut setup at https://letsfg.co/connect (any card, or Revolut Pay / Google Pay; no Revolut account needed; card details never touch LetsFG). Search, flight booking and hotels all work with it.
Authorization: Bearer eyJ...
Get a token — the one way in:
- Add LetsFG as a remote MCP server:
https://letsfg.co/mcp. - Approve the connection. The OAuth consent step opens https://letsfg.co/connect: one tap, no card.
- Over the MCP the OAuth token is carried for you; over raw HTTP send it as
Authorization: Bearer <token>.
POST /api/agent-access/request answers 402 with these steps as JSON
(add_card_url, how). The Stripe enrolment lanes (setup_url, setup_intent,
card_token) were retired on 2026-09-02 and every token they issued was revoked
(401 TOKEN_REVOKED; /api/agent-access/verify answers 410 for a Stripe
credential) — reconnect at letsfg.co/connect. letsfg auth (npm or PyPI) now
drives that connect flow from the terminal and stores the token; the CLI and
SDKs otherwise read it from LETSFG_BEARER_TOKEN. One card = one account; quotas are per account, and per card once one is added. Full flow:
https://letsfg.co/for-agents.
Developer API (business / high-volume): every endpoint except register
requires an X-API-Key header.
X-API-Key: letsfg_...
Get your key by calling POST /api/v1/agents/register with agent_name and email. The key is permanent — save it once.
Then connect a payment method with POST /api/v1/agents/connect-payment and open the returned connect_url once (nothing is charged).
Complete Workflow
Flight Booking — PFS (3 API calls)
1. POST /api/search → Search flights (FREE), returns search_id; poll GET /api/results/{search_id}
2. POST /api/agent-book → Book directly — no unlock step. Holds the fare on the connected card, returns booking_ref in seconds
3. POST /api/agent-book/status → Poll every 20–30 s (4–11 min) → completed (PNR) | failed (hold released) | needs_attention
Flight Booking — Developer API (5 API calls)
1. POST /api/v1/agents/register → Get API key (once)
2. POST /api/v1/agents/connect-payment → Open the connect_url once to save a card (nothing charged)
3. POST /api/v1/flights/search → Search flights (look-to-book: 200 free after every booking)
4. POST /api/v1/flights/book → Hold the fare, dispatch the booking agent → booking_id (202)
5. GET /api/v1/flights/bookings/{id} → Poll until terminal → completed (PNR) | failed (hold released) | needs_attention
Hotel Booking (PFS Bearer token or Developer API key — the same card authorises both)
1. Card on file (to book; search needs none) → PFS: asked for at the first booking; Developer API: POST /api/v1/agents/connect-payment
2. POST /api/v1/hotels/destinations → Place name → city_id
3. POST /api/v1/hotels/search → Bookable rates (card required; 1,000 free after every hotel booking)
4. POST /api/v1/hotels/book → Holds the price; returns booking_job_id — NOT a booking
5. GET /api/v1/hotels/booking/{job_id} → Poll ~20s until succeeded / failed / attention
→ confirmation + total_price + currency
6. POST /api/v1/hotels/cancel → Optional; free on a refundable rate before free_cancellation_until
The full price is held on the card at step 4 and captured only once the hotel confirms; a failed booking releases the hold. There is no reservation fee, no deposit and no pay link. Never repeat step 4 while its job is running — poll it.
CLI Usage
pip install -U letsfg # 2026.5.101 or later books hotels
export LETSFG_BEARER_TOKEN=eyJ... # token from the connect flow (see Authentication)
# Search flights — prints search_id, needed for book
letsfg search LHR JFK 2026-04-15
letsfg search LON BCN 2026-04-01 --return 2026-04-08 --cabin C --sort price
letsfg search GDN BER 2026-05-10 --adults 2 --children 1
# Resolve locations
letsfg locations "New York"
# Book — price shown on the offer, no unlock step. Holds the fare on the connected
# card and prints a booking_ref; poll POST /api/agent-book/status every 20–30 s
letsfg book ws_off_xxx --search-id ws_xxx \
--passenger '{"given_name":"John","family_name":"Doe","born_on":"1990-01-15","gender":"m","nationality":"GB","phone_number":"+447123456789","phone_country":"GB","address_line1":"1 High St","address_city":"London","address_postal":"N1 9GU","address_country":"GB"}' \
--email [email protected]
# Machine-readable output
letsfg search GDN BER 2026-03-03 --json
Developer API instead? letsfg register + letsfg connect-payment once (open the link it
prints), then letsfg search ... --api-key letsfg_... and
letsfg book off_xxx --search-id <search_id> --api-key letsfg_... --passenger '{...}' --email ....
No unlock step.
Python SDK Usage
from letsfg import LetsFG
bt = LetsFG() # reads LETSFG_BEARER_TOKEN — the token from the connect flow
# Search
results = bt.search("LHR", "JFK", "2026-04-15")
for offer in results.offers:
print(f"{offer.price} {offer.currency} — {', '.join(offer.airlines)}")
# Book — price shown on the offer, no unlock step. Holds the fare on the
# connected card; a LetsFG agent buys the ticket; captured only on a real PNR.
result = bt.book(
offer_id=results.offers[0].id,
passengers=[{
"given_name": "John", "family_name": "Doe",
"born_on": "1990-01-15", "gender": "m", "nationality": "GB",
"phone_number": "+447123456789", "phone_country": "GB",
"address_line1": "1 High St", "address_city": "London",
"address_postal": "N1 9GU", "address_country": "GB",
}],
contact_email="[email protected]",
search_id=results.search_id,
)
if "missing_fields" in result:
print("Nothing charged — ask for:", result["missing_fields"])
else:
print("Started:", result["booking_ref"], result["held"])
# poll POST /api/agent-book/status {"booking_ref": ...} every 20–30 s
# until state is completed (pnr) | failed (hold released) | needs_attention
Developer API instead? LetsFG(api_key="letsfg_..."), then bt.book(offer_id, passengers, contact_email, search_id=..., idempotency_key=...) — no unlock step. It starts the booking; poll
it with bt.get_booking(booking_id), or call bt.book_and_wait(...) to block until it settles.
MCP Server Setup
Remote (Streamable HTTP) — the way in for agents:
{
"mcpServers": {
"letsfg": { "url": "https://letsfg.co/mcp" }
}
}
Claude Code: claude mcp add --transport http letsfg https://letsfg.co/mcp.
Claude: add it from Claude's official connector directory, https://claude.ai/directory/letsfg - no URL to paste (once added, it works in Claude Desktop and the Claude phone app too).
ChatGPT: at chatgpt.com in a browser (the ChatGPT phone app has no way to add one), Plugins > Add >
Add custom MCP server, that URL, authentication OAuth; once added it works in the phone app too. Windsurf uses
"serverUrl" instead of "url". The client runs OAuth; the consent step opens
https://letsfg.co/connect: one tap, no card. The token the client receives can
search at once, and the card is asked for at the first booking.
Developer API accounts can use the same URL with
"headers": {"X-API-Key": "letsfg_..."} instead of OAuth.
Local (stdio) — needs a token you already hold:
npm install -g letsfg-mcp@latest # 2026.5.77 or later books hotels
LETSFG_BEARER_TOKEN=eyJ... letsfg-mcp # token from the connect flow
The local server also accepts LETSFG_API_KEY instead, for the Developer API.
book_flight dispatches automatically based on which one is set. Its
authenticate tool returns the current connect instructions (add_card_url,
how); run letsfg auth to mint a token from the terminal.
MCP Tools
| Tool | Description | Cost |
|---|---|---|
search_flights | Search every airline in the world via server-side engine | FREE |
resolve_location | City name → IATA code | FREE |
book_flight | Start a booking. PFS: direct, no unlock step — holds the fare on the connected card, returns booking_ref. Developer API key: the same call, no unlock step | Price shown on the offer, no separate LetsFG fee (PFS) |
get_flight_booking | Poll a PFS booking every 20–30 s: booking_in_progress → completed (PNR) / failed (hold released) / needs_attention | FREE |
unlock_flight_offer | RETIRED 2026-09-08 — answers 410 Gone. Call book_flight directly | — |
connect_payment | [Developer API only] Mint a one-time link to connect a card to the paid account (nothing charged). PFS agents connect at letsfg.co/connect instead | FREE |
resolve_hotel_city | Place name → supplier city id for search_hotels | FREE |
search_hotels | Bookable hotel rates, refundable and non-refundable | FREE (1,000 per hotel booking) |
book_hotel | Start a hotel booking: the price is held, captured once the hotel confirms. Returns booking_job_id | The price on the offer |
get_hotel_booking | Poll until succeeded / failed / attention | FREE |
cancel_hotel_booking | Cancel a refundable booking before free_cancellation_until (98% refunded, 2% fee) | FREE |
get_agent_profile | View usage stats | FREE |
Search Flags Reference
| Flag | API Field | Values | Default |
|---|---|---|---|
--adults | adults | 1–9 | 1 |
--children | children | 0–9 | 0 |
--infants | infants | 0–9 | 0 |
--cabin | cabin_class | M (economy), W (premium), C (business), F (first) | (any) |
--return | return_from | YYYY-MM-DD | — |
--max-stops | max_stopovers | 0–4 | 2 |
--sort | sort | price, duration | price |
--limit | limit | 1–100 | 20 |
--currency | currency | EUR, USD, GBP, etc. | EUR |
Cabin Class Codes Explained
| Code | Class | Description | Typical Use Case |
|---|---|---|---|
M | Economy | Standard seating | Budget travel, most bookings |
W | Premium Economy | Extra legroom, priority boarding | Long-haul comfort without business price |
C | Business | Lie-flat on long-haul, lounge access | Corporate travel, 6+ hour flights |
F | First | Private suites, premium dining | Ultra-premium routes (limited airlines) |
--json | — | Output as JSON | — |
Error Handling
| Exception | HTTP Code | When |
|---|---|---|
AuthenticationError | 401 | Invalid or missing API key |
PaymentRequiredError | 402 | No payment method connected, or the search allowance is used up |
OfferExpiredError | 410 | Offer no longer available |
LetsFGError | 422 | Invalid request parameters |
LetsFGError | 429 | Too many requests (retry with backoff) |
LetsFGError | 502 | Upstream airline/hotel API error |
Authentication Failure Recovery
from letsfg import LetsFG
from letsfg.connectors.auth import BearerTokenError
try:
bt = LetsFG() # reads LETSFG_BEARER_TOKEN — the token from the connect flow
flights = bt.search("LHR", "JFK", "2026-04-15")
except BearerTokenError:
print("Token expired, revoked or missing — reconnect at https://letsfg.co/connect")
Developer API:
from letsfg import LetsFG, AuthenticationError
try:
bt = LetsFG(api_key="letsfg_...")
flights = bt.search("LHR", "JFK", "2026-04-15")
except AuthenticationError:
# API key invalid or expired — re-register, then connect a payment method on the new key
creds = LetsFG.register("my-agent", "[email protected]")
bt = LetsFG(api_key=creds["api_key"])
print("Open once to connect a card:", bt.connect_payment()["connect_url"]) # nothing is charged
Rate Limit and Timeout Handling
import time
from letsfg import LetsFG, LetsFGError
def search_with_retry(bt, origin, dest, date, max_retries=3):
for attempt in range(max_retries):
try:
return bt.search(origin, dest, date)
except LetsFGError as e:
if "429" in str(e) or "rate limit" in str(e).lower():
time.sleep(2 ** attempt) # exponential backoff
elif "timeout" in str(e).lower() or "504" in str(e):
time.sleep(1)
else:
raise
raise LetsFGError("Max retries exceeded")
Rate Limits
| Endpoint | Rate Limit | Typical Latency |
|---|---|---|
| Search flights | No hard limit (billing is the natural governor) | 2–5 s (discover) · 8–10 s to first results (full search) |
| Resolve location | 120 req/min | <1s |
| Book | 10 req/min | 3-10s |
| Search hotels | 30 req/min | 3-10s |
| Register | 5 req/min | <1s |
Pricing Summary
| Action | Cost |
|---|---|
| Search (flights, transfers, activities) | Free |
| Resolve locations | Free |
| Register agent | Free |
| Connect a payment method | Free — nothing is charged to connect |
| View profile | Free |
| Book flight (PFS, no unlock needed) | The price shown on the offer — held on the connected card, captured only on a real PNR; no separate LetsFG fee |
| Book flight (Developer API) | The price shown on the offer — held, captured only on a real PNR; no booking fee, no transaction fee |
| Hotel search | Free up to 1,000 searches after every hotel booking, then 1,000 for $5.00 |
| Hotel booking | The price shown on the offer — held on the connected card, captured only once the hotel confirms. No reservation fee |
| Hotel cancellation | 98% refunded on a refundable rate before free_cancellation_until (2% fee); otherwise refused |
Key Facts
- Every airline in the world via server-side engine
- Hotels via a wholesale hotel partner
- No cookie tracking — the same search returns the same prices
- Typically cheaper than booking through a single OTA, because it compares airlines and the major booking sites in one pass
- Real airline PNR codes and hotel confirmations
- E-tickets sent directly to passenger email
- Search is free (10 per 10 min, 30/hour, 100/day)
- PFS (Bearer token): book directly, no unlock step — the fare is held on the connected card, a LetsFG booking agent buys the ticket, captured only once a real PNR exists; failed booking = hold released, nothing charged
- Developer API:
POST /flights/book— the same hold-then-capture flow, then pollGET /flights/bookings/{id}. Search there is look-to-book (200 free after every booking) and there is no booking or transaction fee - API designed for machines, not browsers