letsfg 2026.5.74 → 2026.5.75
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +10 -6
- package/dist/{chunk-GVKYPTY3.mjs → chunk-6IWYHW62.mjs} +13 -5
- package/dist/cli.js +13 -5
- package/dist/cli.mjs +1 -1
- package/dist/index.js +13 -5
- package/dist/index.mjs +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# LetsFG — Your AI agent just learned to book flights. (Node.js)
|
|
2
2
|
|
|
3
|
-
**Server-side search engine. Real prices. One function call.** Search
|
|
3
|
+
**Server-side search engine. Real prices. One function call.** Search every airline in the world and the major booking sites; the price shown is the total you pay. Zero dependencies. Built for AI agents.
|
|
4
4
|
|
|
5
5
|
[](https://github.com/LetsFG/LetsFG)
|
|
6
6
|
[](https://www.npmjs.com/package/letsfg)
|
|
@@ -54,7 +54,7 @@ const flights = await bt.search('GDN', 'BER', '2026-03-03');
|
|
|
54
54
|
const best = cheapestOffer(flights);
|
|
55
55
|
console.log(offerSummary(best));
|
|
56
56
|
|
|
57
|
-
// Book — no booking fee, no transaction fee
|
|
57
|
+
// Book — no booking fee, no transaction fee on top of the price you saw; no unlock step. Starts the booking:
|
|
58
58
|
// the fare is HELD on your card and a LetsFG agent buys the ticket (4-11 min).
|
|
59
59
|
const result = await bt.book(
|
|
60
60
|
best.id,
|
|
@@ -87,7 +87,7 @@ console.log(status); // { state: 'completed', pnr: 'ABC123', charged_amount: 93,
|
|
|
87
87
|
### How booking works
|
|
88
88
|
|
|
89
89
|
`bt.book()` posts to `POST /api/agent-book` and does exactly what the website
|
|
90
|
-
checkout does: the
|
|
90
|
+
checkout does: the price shown is **held** on the connected card
|
|
91
91
|
(not taken), a LetsFG booking agent buys the ticket from the seller, and the
|
|
92
92
|
hold is captured only once a real airline PNR exists. If the booking fails the
|
|
93
93
|
hold is released and nothing is charged. Every offer can be booked this way —
|
|
@@ -182,6 +182,12 @@ MIT
|
|
|
182
182
|
|
|
183
183
|
Your agent can book hotels as well as flights. Same card-backed token or API key, same connected payment method.
|
|
184
184
|
|
|
185
|
+
> **Update your SDK before booking hotels.** Hotel booking needs **letsfg 2026.5.101** or later (Python),
|
|
186
|
+
> **letsfg 2026.5.74** or later (JavaScript/TypeScript) or **letsfg-mcp 2026.5.77** or later. Earlier releases send
|
|
187
|
+
> the reservation-fee fields retired on 2026-09-11 (`expected_balance`, no `expected_cost`), and the API refuses
|
|
188
|
+
> every hotel booking they make. Update with `pip install -U letsfg`, `npm install letsfg@latest` or
|
|
189
|
+
> `npx -y letsfg-mcp@latest`. The hosted MCP at `https://letsfg.co/developers/api/mcp` needs no update.
|
|
190
|
+
|
|
185
191
|
```python
|
|
186
192
|
from letsfg import LetsFG
|
|
187
193
|
lfg = LetsFG()
|
|
@@ -232,9 +238,7 @@ released and nothing is charged.
|
|
|
232
238
|
There is **no reservation fee, no deposit and no pay link**, and the guest owes the hotel nothing
|
|
233
239
|
further. (Those belonged to the process retired on 2026-09-11.)
|
|
234
240
|
|
|
235
|
-
`price` is the
|
|
236
|
-
card issued in the EEA, or 8.3% for a card issued outside the EEA — the search response's
|
|
237
|
-
`markup_rate` says which. Nothing is added at booking. Prices are in the currency you search in:
|
|
241
|
+
`price` is what the guest pays. Nothing is added at booking. Prices are in the currency you search in:
|
|
238
242
|
USD unless you ask for another.
|
|
239
243
|
|
|
240
244
|
Cancelling a refundable rate before its `free_cancellation_until` costs nothing and refunds the
|
|
@@ -1618,15 +1618,23 @@ var LetsFG = class {
|
|
|
1618
1618
|
currency: options.currency ?? "EUR",
|
|
1619
1619
|
limit: options.limit ?? 50
|
|
1620
1620
|
};
|
|
1621
|
-
if (options.returnDate) body.return_date = options.returnDate;
|
|
1622
|
-
if (options.cabinClass) body.cabin_class = options.cabinClass;
|
|
1623
|
-
if (options.maxStopovers != null) body.max_stopovers = options.maxStopovers;
|
|
1624
|
-
if (options.sort) body.sort = options.sort;
|
|
1625
1621
|
if (options.departureTimeFrom) body.departure_time_from = options.departureTimeFrom;
|
|
1626
1622
|
if (options.departureTimeTo) body.departure_time_to = options.departureTimeTo;
|
|
1627
1623
|
if (this.usingPFS) {
|
|
1628
|
-
|
|
1624
|
+
if (options.returnDate) body.return_date = options.returnDate;
|
|
1625
|
+
if (options.cabinClass) body.cabin = options.cabinClass;
|
|
1626
|
+
if (options.maxStopovers != null) body.max_stops = options.maxStopovers;
|
|
1627
|
+
if (options.sort) body.sort_by = options.sort;
|
|
1628
|
+
const result = await this.searchPFS(body);
|
|
1629
|
+
if (options.limit != null && Array.isArray(result.offers)) {
|
|
1630
|
+
result.offers = result.offers.slice(0, Math.max(0, options.limit));
|
|
1631
|
+
}
|
|
1632
|
+
return result;
|
|
1629
1633
|
}
|
|
1634
|
+
if (options.returnDate) body.return_from = options.returnDate;
|
|
1635
|
+
if (options.cabinClass) body.cabin_class = options.cabinClass;
|
|
1636
|
+
if (options.maxStopovers != null) body.max_stopovers = options.maxStopovers;
|
|
1637
|
+
if (options.sort) body.sort = options.sort;
|
|
1630
1638
|
return this.post("/developers/api/v1/flights/search", body);
|
|
1631
1639
|
}
|
|
1632
1640
|
/** PFS path: POST /api/search -> poll /api/results/<id> */
|
package/dist/cli.js
CHANGED
|
@@ -374,15 +374,23 @@ var LetsFG = class {
|
|
|
374
374
|
currency: options.currency ?? "EUR",
|
|
375
375
|
limit: options.limit ?? 50
|
|
376
376
|
};
|
|
377
|
-
if (options.returnDate) body.return_date = options.returnDate;
|
|
378
|
-
if (options.cabinClass) body.cabin_class = options.cabinClass;
|
|
379
|
-
if (options.maxStopovers != null) body.max_stopovers = options.maxStopovers;
|
|
380
|
-
if (options.sort) body.sort = options.sort;
|
|
381
377
|
if (options.departureTimeFrom) body.departure_time_from = options.departureTimeFrom;
|
|
382
378
|
if (options.departureTimeTo) body.departure_time_to = options.departureTimeTo;
|
|
383
379
|
if (this.usingPFS) {
|
|
384
|
-
|
|
380
|
+
if (options.returnDate) body.return_date = options.returnDate;
|
|
381
|
+
if (options.cabinClass) body.cabin = options.cabinClass;
|
|
382
|
+
if (options.maxStopovers != null) body.max_stops = options.maxStopovers;
|
|
383
|
+
if (options.sort) body.sort_by = options.sort;
|
|
384
|
+
const result = await this.searchPFS(body);
|
|
385
|
+
if (options.limit != null && Array.isArray(result.offers)) {
|
|
386
|
+
result.offers = result.offers.slice(0, Math.max(0, options.limit));
|
|
387
|
+
}
|
|
388
|
+
return result;
|
|
385
389
|
}
|
|
390
|
+
if (options.returnDate) body.return_from = options.returnDate;
|
|
391
|
+
if (options.cabinClass) body.cabin_class = options.cabinClass;
|
|
392
|
+
if (options.maxStopovers != null) body.max_stopovers = options.maxStopovers;
|
|
393
|
+
if (options.sort) body.sort = options.sort;
|
|
386
394
|
return this.post("/developers/api/v1/flights/search", body);
|
|
387
395
|
}
|
|
388
396
|
/** PFS path: POST /api/search -> poll /api/results/<id> */
|
package/dist/cli.mjs
CHANGED
package/dist/index.js
CHANGED
|
@@ -1667,15 +1667,23 @@ var LetsFG = class {
|
|
|
1667
1667
|
currency: options.currency ?? "EUR",
|
|
1668
1668
|
limit: options.limit ?? 50
|
|
1669
1669
|
};
|
|
1670
|
-
if (options.returnDate) body.return_date = options.returnDate;
|
|
1671
|
-
if (options.cabinClass) body.cabin_class = options.cabinClass;
|
|
1672
|
-
if (options.maxStopovers != null) body.max_stopovers = options.maxStopovers;
|
|
1673
|
-
if (options.sort) body.sort = options.sort;
|
|
1674
1670
|
if (options.departureTimeFrom) body.departure_time_from = options.departureTimeFrom;
|
|
1675
1671
|
if (options.departureTimeTo) body.departure_time_to = options.departureTimeTo;
|
|
1676
1672
|
if (this.usingPFS) {
|
|
1677
|
-
|
|
1673
|
+
if (options.returnDate) body.return_date = options.returnDate;
|
|
1674
|
+
if (options.cabinClass) body.cabin = options.cabinClass;
|
|
1675
|
+
if (options.maxStopovers != null) body.max_stops = options.maxStopovers;
|
|
1676
|
+
if (options.sort) body.sort_by = options.sort;
|
|
1677
|
+
const result = await this.searchPFS(body);
|
|
1678
|
+
if (options.limit != null && Array.isArray(result.offers)) {
|
|
1679
|
+
result.offers = result.offers.slice(0, Math.max(0, options.limit));
|
|
1680
|
+
}
|
|
1681
|
+
return result;
|
|
1678
1682
|
}
|
|
1683
|
+
if (options.returnDate) body.return_from = options.returnDate;
|
|
1684
|
+
if (options.cabinClass) body.cabin_class = options.cabinClass;
|
|
1685
|
+
if (options.maxStopovers != null) body.max_stopovers = options.maxStopovers;
|
|
1686
|
+
if (options.sort) body.sort = options.sort;
|
|
1679
1687
|
return this.post("/developers/api/v1/flights/search", body);
|
|
1680
1688
|
}
|
|
1681
1689
|
/** PFS path: POST /api/search -> poll /api/results/<id> */
|
package/dist/index.mjs
CHANGED
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "letsfg",
|
|
3
|
-
"version": "2026.5.
|
|
4
|
-
"description": "Flights and hotels for AI agents. Server-side engine covers hundreds of airlines; hotels are real bookable inventory with
|
|
3
|
+
"version": "2026.5.75",
|
|
4
|
+
"description": "Flights and hotels for AI agents. Server-side engine covers hundreds of airlines; hotels are real bookable inventory with pay-later terms, and every rate says whether it is refundable. Includes open-source ranking engine.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
7
7
|
"types": "dist/index.d.ts",
|