letsfg 2026.5.63 → 2026.5.65

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.
@@ -1637,10 +1637,36 @@ var LetsFG = class {
1637
1637
  return this.postWithAuth(path, { offer_id: offerId });
1638
1638
  }
1639
1639
  /**
1640
- * Book a flight via Developer API — charges ticket price via Stripe, creates real PNR.
1641
- * Always provide idempotencyKey to prevent double-bookings on retry.
1640
+ * Book a flight.
1641
+ *
1642
+ * PFS (Bearer token): POST /api/agent-book. Free — nothing charged beyond
1643
+ * the ticket price. Pass searchId (from search()'s result). Returns either
1644
+ * { ok, booked: true, order_id } or, when the booking genuinely could not
1645
+ * complete, { ok, booked: false, booking_url } — hand the link to the user,
1646
+ * nothing was charged.
1647
+ *
1648
+ * Developer API (X-API-Key): charges ticket price + service fee via Stripe,
1649
+ * creates a real PNR. Requires unlock() first. Always provide
1650
+ * idempotencyKey to prevent double-bookings on retry.
1642
1651
  */
1643
- async book(offerId, passengers, contactEmail, contactPhone = "", idempotencyKey = "") {
1652
+ async book(offerId, passengers, contactEmail, contactPhone = "", idempotencyKey = "", searchId = "") {
1653
+ this.requireAuth();
1654
+ if (this.usingPFS) {
1655
+ if (!searchId) {
1656
+ throw new LetsFGError(
1657
+ "searchId is required to book via PFS \u2014 pass the search_id from search()'s result.",
1658
+ 400
1659
+ );
1660
+ }
1661
+ const passenger = { ...passengers[0] };
1662
+ if (contactPhone && !passenger.phone_number) passenger.phone_number = contactPhone;
1663
+ return this.postWithBearer("/api/agent-book", {
1664
+ search_id: searchId,
1665
+ offer_id: offerId,
1666
+ passenger,
1667
+ contact_email: contactEmail
1668
+ });
1669
+ }
1644
1670
  this.requireApiKey();
1645
1671
  const body = {
1646
1672
  offer_id: offerId,
package/dist/cli.js CHANGED
@@ -392,10 +392,36 @@ var LetsFG = class {
392
392
  return this.postWithAuth(path, { offer_id: offerId });
393
393
  }
394
394
  /**
395
- * Book a flight via Developer API — charges ticket price via Stripe, creates real PNR.
396
- * Always provide idempotencyKey to prevent double-bookings on retry.
395
+ * Book a flight.
396
+ *
397
+ * PFS (Bearer token): POST /api/agent-book. Free — nothing charged beyond
398
+ * the ticket price. Pass searchId (from search()'s result). Returns either
399
+ * { ok, booked: true, order_id } or, when the booking genuinely could not
400
+ * complete, { ok, booked: false, booking_url } — hand the link to the user,
401
+ * nothing was charged.
402
+ *
403
+ * Developer API (X-API-Key): charges ticket price + service fee via Stripe,
404
+ * creates a real PNR. Requires unlock() first. Always provide
405
+ * idempotencyKey to prevent double-bookings on retry.
397
406
  */
398
- async book(offerId, passengers, contactEmail, contactPhone = "", idempotencyKey = "") {
407
+ async book(offerId, passengers, contactEmail, contactPhone = "", idempotencyKey = "", searchId = "") {
408
+ this.requireAuth();
409
+ if (this.usingPFS) {
410
+ if (!searchId) {
411
+ throw new LetsFGError(
412
+ "searchId is required to book via PFS \u2014 pass the search_id from search()'s result.",
413
+ 400
414
+ );
415
+ }
416
+ const passenger = { ...passengers[0] };
417
+ if (contactPhone && !passenger.phone_number) passenger.phone_number = contactPhone;
418
+ return this.postWithBearer("/api/agent-book", {
419
+ search_id: searchId,
420
+ offer_id: offerId,
421
+ passenger,
422
+ contact_email: contactEmail
423
+ });
424
+ }
399
425
  this.requireApiKey();
400
426
  const body = {
401
427
  offer_id: offerId,
package/dist/cli.mjs CHANGED
@@ -3,7 +3,7 @@ import {
3
3
  LetsFG,
4
4
  LetsFGError,
5
5
  offerSummary
6
- } from "./chunk-ZX2EIEN7.mjs";
6
+ } from "./chunk-DEFFV47W.mjs";
7
7
 
8
8
  // src/cli.ts
9
9
  function getFlag(args, flag, alias) {
package/dist/index.d.mts CHANGED
@@ -476,10 +476,19 @@ declare class LetsFG {
476
476
  */
477
477
  unlock(offerId: string): Promise<UnlockResult>;
478
478
  /**
479
- * Book a flight via Developer API — charges ticket price via Stripe, creates real PNR.
480
- * Always provide idempotencyKey to prevent double-bookings on retry.
479
+ * Book a flight.
480
+ *
481
+ * PFS (Bearer token): POST /api/agent-book. Free — nothing charged beyond
482
+ * the ticket price. Pass searchId (from search()'s result). Returns either
483
+ * { ok, booked: true, order_id } or, when the booking genuinely could not
484
+ * complete, { ok, booked: false, booking_url } — hand the link to the user,
485
+ * nothing was charged.
486
+ *
487
+ * Developer API (X-API-Key): charges ticket price + service fee via Stripe,
488
+ * creates a real PNR. Requires unlock() first. Always provide
489
+ * idempotencyKey to prevent double-bookings on retry.
481
490
  */
482
- book(offerId: string, passengers: Passenger[], contactEmail: string, contactPhone?: string, idempotencyKey?: string): Promise<BookingResult>;
491
+ book(offerId: string, passengers: Passenger[], contactEmail: string, contactPhone?: string, idempotencyKey?: string, searchId?: string): Promise<BookingResult | Record<string, unknown>>;
483
492
  /**
484
493
  * Resolve a place name to the city id that searchHotels() needs.
485
494
  *
package/dist/index.d.ts CHANGED
@@ -476,10 +476,19 @@ declare class LetsFG {
476
476
  */
477
477
  unlock(offerId: string): Promise<UnlockResult>;
478
478
  /**
479
- * Book a flight via Developer API — charges ticket price via Stripe, creates real PNR.
480
- * Always provide idempotencyKey to prevent double-bookings on retry.
479
+ * Book a flight.
480
+ *
481
+ * PFS (Bearer token): POST /api/agent-book. Free — nothing charged beyond
482
+ * the ticket price. Pass searchId (from search()'s result). Returns either
483
+ * { ok, booked: true, order_id } or, when the booking genuinely could not
484
+ * complete, { ok, booked: false, booking_url } — hand the link to the user,
485
+ * nothing was charged.
486
+ *
487
+ * Developer API (X-API-Key): charges ticket price + service fee via Stripe,
488
+ * creates a real PNR. Requires unlock() first. Always provide
489
+ * idempotencyKey to prevent double-bookings on retry.
481
490
  */
482
- book(offerId: string, passengers: Passenger[], contactEmail: string, contactPhone?: string, idempotencyKey?: string): Promise<BookingResult>;
491
+ book(offerId: string, passengers: Passenger[], contactEmail: string, contactPhone?: string, idempotencyKey?: string, searchId?: string): Promise<BookingResult | Record<string, unknown>>;
483
492
  /**
484
493
  * Resolve a place name to the city id that searchHotels() needs.
485
494
  *
package/dist/index.js CHANGED
@@ -1685,10 +1685,36 @@ var LetsFG = class {
1685
1685
  return this.postWithAuth(path, { offer_id: offerId });
1686
1686
  }
1687
1687
  /**
1688
- * Book a flight via Developer API — charges ticket price via Stripe, creates real PNR.
1689
- * Always provide idempotencyKey to prevent double-bookings on retry.
1688
+ * Book a flight.
1689
+ *
1690
+ * PFS (Bearer token): POST /api/agent-book. Free — nothing charged beyond
1691
+ * the ticket price. Pass searchId (from search()'s result). Returns either
1692
+ * { ok, booked: true, order_id } or, when the booking genuinely could not
1693
+ * complete, { ok, booked: false, booking_url } — hand the link to the user,
1694
+ * nothing was charged.
1695
+ *
1696
+ * Developer API (X-API-Key): charges ticket price + service fee via Stripe,
1697
+ * creates a real PNR. Requires unlock() first. Always provide
1698
+ * idempotencyKey to prevent double-bookings on retry.
1690
1699
  */
1691
- async book(offerId, passengers, contactEmail, contactPhone = "", idempotencyKey = "") {
1700
+ async book(offerId, passengers, contactEmail, contactPhone = "", idempotencyKey = "", searchId = "") {
1701
+ this.requireAuth();
1702
+ if (this.usingPFS) {
1703
+ if (!searchId) {
1704
+ throw new LetsFGError(
1705
+ "searchId is required to book via PFS \u2014 pass the search_id from search()'s result.",
1706
+ 400
1707
+ );
1708
+ }
1709
+ const passenger = { ...passengers[0] };
1710
+ if (contactPhone && !passenger.phone_number) passenger.phone_number = contactPhone;
1711
+ return this.postWithBearer("/api/agent-book", {
1712
+ search_id: searchId,
1713
+ offer_id: offerId,
1714
+ passenger,
1715
+ contact_email: contactEmail
1716
+ });
1717
+ }
1692
1718
  this.requireApiKey();
1693
1719
  const body = {
1694
1720
  offer_id: offerId,
package/dist/index.mjs CHANGED
@@ -22,7 +22,7 @@ import {
22
22
  offerSummary,
23
23
  rankOffers,
24
24
  selectDiverseTop
25
- } from "./chunk-ZX2EIEN7.mjs";
25
+ } from "./chunk-DEFFV47W.mjs";
26
26
  export {
27
27
  AuthenticationError,
28
28
  BoostedTravel,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "letsfg",
3
- "version": "2026.5.63",
4
- "description": "Flight search & booking for AI agents. Server-side engine covers hundreds of airlines. Free search via Bearer token or prepaid Developer API. Includes open-source ranking engine.",
3
+ "version": "2026.5.65",
4
+ "description": "Flights and hotels for AI agents. Server-side engine covers hundreds of airlines; hotels are real bookable inventory with free cancellation and pay-later terms. Includes open-source ranking engine.",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
7
7
  "types": "dist/index.d.ts",
@@ -31,7 +31,11 @@
31
31
  "airline",
32
32
  "ndc",
33
33
  "search",
34
- "ndc"
34
+ "ndc",
35
+ "hotels",
36
+ "hotel-booking",
37
+ "hotel-search",
38
+ "accommodation"
35
39
  ],
36
40
  "author": "LetsFG",
37
41
  "license": "MIT",