@findhotel/sapi

中文文档
1.35.1发布于 2026/10/30ISCTypeScriptCommonJS零依赖近 30 天下载 3776

查找 Hotel 搜索 API

中文使用文档
文档目录42 节
  1. 国家防范机制
  2. GitHub 托肯语Name
  3. 新发行
  4. 开发处新发行
  5. 开始
  6. 原生反应
  7. 游戏场
  8. 使用量
  9. 搜索
  10. 买酒店的房间
  11. 去旅馆
  12. 去旅馆
  13. 买酒店
  14. 得到酒店报价
  15. 获得旅馆可用性(价目表)
  16. SAPI 客户端
  17. 支持的选项
  18. 可用的客户端回调
  19. 回应
  20. search() 方法
  21. 搜索参数
  22. 回电
  23. 启动时 ()
  24. 锁定接收 ()
  25. 在 Hotels 接收( )
  26. 输入( )
  27. 完成( )
  28. 回应
  29. 装入更多的结果 并装入更多的报价 酒店
  30. suggest() 方法
  31. 建议参数
  32. 回应
  33. freeTextSuggest() 方法
  34. 建议参数
  35. 回应
  36. rooms() 方法
  37. 房间参数
  38. 回应
  39. 投票时间长 rooms() 方法
  40. hotel() 方法
  41. 旅馆参数
  42. 回应

萨比SDK

SDK 为搜索提供高水平的TypeScript/JavaScript API 酒店 酒店的报价和房间.

目录

释放过程

SAP SDK没有连续的集成/交付. 合并 PR 进入主分支不会自动触发释放过程. 对于 释放 SAPI SDK 用途 船舶.js 工具。 它赋予了更多的控制过程。 船舶.js自动 在发布每版前创建 PR, 因此允许 :

  • 确认下一个版本正确 .
  • 确认哪些承诺将被释放,并与 同事们.
  • 编辑自动生成的更改日志, 以澄清( I) 可读性.

国家防范机制

释放前(beta)程序需要国家预防机制账户:

  • 转到 国家防范机制报名
  • 创建账户并请求 SAPI 允许您访问组织
  • 使用认证人/1 Password 激活您的两个因素认证

GitHub 托肯语Name

发布过程需要 GitHub 令牌 :

  • 转到 您的 GitHub 账户
  • 检查“ repo( 完全控制私人仓库) ”
  • 生成/复制符号
  • 在命令行中添加如下: GITHUB_TOKEN=xxx

新发行

要创建和部署 SAPI SDK 新版本, 请跟随下一个版本 步骤 :

  • 合并您的更改 。 一次发布会有多个变化
  • 检查最新版本 main 分支
  • 在根目录运行中 make release 命令 - 此 将启动释放进程
  • 审查和确认(或更改)新版本编号
  • 安装依赖关系和运行部署脚本后,将新建 将自动创建拉动请求
  • 审查/更新 CHANGELOG.md 在根目录中。 记下来 使用描述更改 保留更改日志 指导 原则,并将您的更改输入新建的版本 公关
  • 审查PR/任务SAPI工程师供批准
  • Squash and merge 公关。 这将启动自动 使用 GitHub 动作发布进程,并在一段时间后发布新进程 将发布到 NMP
  • 检查新版本是否已发布给国家预防机制

开发处新发行

有时 您可能想要在网站上测试您的更改, 例如本地或自定义/ 测试环境, 然后再将您的分支合并为主, 然后再制作一个新的 SAPI SDK 版本 。 为此,您可以创建并发布预释. 发行前向国家预防机制发布新版本,标签除外 latest (默认标记). 要发布预发本,请遵循下一步:

  • 从项目根部构建 SAPI SDK :

    make core-build
    
  • 创建新版本 npm version prepatch (preminor, premajor) --preid=beta (alpha, beta, etc...)数字 :

    npm version prepatch --preid=beta
    

    这会导致这样的事情 1.4.1-beta.0

    • 如果你已经发布了一个预发版,并且想要增加版本的预发部分,运行:

      npm version prerelease
      

      这会导致这样的事情 1.4.1-beta.1

  • 使用非标签发布更改 latest数字 :

    npm publish --tag=next
    

    在发布期间, 您会请求登录/ 输入您的 OTP( Two Factor Auth Code) , 您可以使用 Auth 程序访问 这里(中文(简体) )

  • 在新版本发布到 npm后, 将其安装到指定新版本的本地环境中 :

    npm install @findhotel/[email protected]
    

教学

开始

首先通过 无 软件包管理器 :

npm install @findhotel/sapi

然后,将 SAPI 导入到您的项目中 :

import sapi from "@findhotel/sapi";

创建 SAPI 客户端 :

const profileKey = "profile-key";

const sapiClient = await sapi(profileKey, {
  anonymousId: "fd9dbb5f-b337-4dd7-b640-1f177d1d3caa",
  language: "en",
  currency: "USD",
  userCountry: "US",
});

现在, SAPI 客户端已准备好用于您的应用程序 .

完整文档和辅助选项检查 客户端 api。 。 。 .

原生反应

使用 Sapi SDK 软件 uuid 用于生成随机字符串. uuid 使用全局 crypto 对象不是 可在本地环境中使用.

为了增加支持, crypto 应在 消费者方面。 我们建议安装 crypto.getRandomValues 不使用其他的多填充 crypto 方法。 。 。 有关多填充的更多信息 已找到 这里

游戏场

Playground 是一个本地环境,用于检查您的更改, 并测试执行是否正确, 您可以通过打开两个终端并运行这些命令来访问本地环境( http://localhost: 3: 00)

# watch your changes to core and create a new bundle
make core-dev
# runs the playground on http://localhost:3000
make playground-run

使用量

寻找酒店和酒店的报价:

const searchParameters = {
  placeId: "47319",
  checkIn: "2021-10-10",
  checkOut: "2021-10-11",
  rooms: "2",
};

const callbacks = {
  onStart: (response) => {
    log("Search started", response);
  },
  onAnchorReceived: (response) => {
    log("Anchor received", response);
  },
  onHotelsReceived: (response) => {
    log("Hotels received", response);
  },
  onOffersReceived: (response) => {
    log("Offers received", response);
  },
  onComplete: (response) => {
    log("Search completed", response);
  },
};

const search = await sapiClient.search(searchParameters, callbacks);

完整文档请检查 搜索方法 api。 。 。 .

买酒店的房间

获取房间数据和房间的报价:

const rooms = await sapiClient.rooms({
  hotelId: "47319",
  checkIn: "2021-10-10",
  checkOut: "2021-10-11",
  rooms: "2",
});

我们还介绍 roomsV2 即使古人堕落 rooms 方法

const rooms = await sapiClient.roomsV2({
  hotelId: "47319",
  checkIn: "2021-10-10",
  checkOut: "2021-10-11",
  rooms: "2",
});

完整文档请检查 房间方法 api。 。 。 .

去旅馆

把酒店的号码:

const hotel = await sapiClient.hotel("1196472");

完整文档请检查 旅馆方法 api。 。 。 .

去旅馆

给酒店打个电话:

const hotels = await sapiClient.hotels(["1714808", "1380416", "1710829"]);

完整文档请检查 旅馆方法 api。 。 。 .

买酒店

获得单家酒店的报价:

const parameters = {
  hotelId: "1196472",
};

const callbacks = {
  onStart: (response) => {
    log("Offers started", response);
  },
  onOffersReceived: (response) => {
    log("Offers received", response);
  },
  onComplete: (response) => {
    log("Offers completed", response);
  },
};

const offers = await sapiClient.offers(parameters, callbacks);

完整文档请检查 提供方法 api。 。 。 .

得到酒店报价

获得多个酒店的报价:

const parameters = {
  hotelIds: ["1196472", "1041597"],
};

const callbacks = {
  onStart: (response) => {
    log("Hotels offers started", response);
  },
  onOffersReceived: (response) => {
    log("Hotels offers received", response);
  },
  onComplete: (response) => {
    log("Hotels offers completed", response);
  },
};

const offers = await sapiClient.hotelsOffers(parameters, callbacks);

完整文档请检查 旅馆提供方法api。 。 。 .

获得旅馆可用性(价目表)

获得酒店服务:

const parameters = {
  hotelIds: ["1380416", "1359951"],
  startDate: "2023-08-05",
  endDate: "2023-08-12",
  nights: 2,
  rooms: "2",
};

const callbacks = {
  onStart: (response) => {
    log("Availability request started", response);
  },
  onAvailabilityReceived: (response) => {
    log("Availability received", response);
  },
  onComplete: (response) => {
    log("Availability completed", response);
  },
};

const response = await sapiClient.hotelAvailability(parameters, callbacks);

完整文档请检查 可用方法 api。 。 。 .

API 参考

SAPI 客户端

创建 SAPI 客户端 :

const profileKey = "profile-key";

const sapiClient = await sapi(profileKey, {
  anonymousId: "fd9dbb5f-b337-4dd7-b640-1f177d1d3caa",
  language: "en",
  currency: "USD",
  userCountry: "US",
  deviceType: "mobile",
  pageSize: 20,
  initWithAppConfig: {},
  callbacks: {
    onConfigReceived: (config) => {
      log("Config received", config);
    },
  },
  getTotalRate: (rate) => {
    let totalRate = rate.base;
    if (includeTaxes) totalRate += rate.taxes;
    if (includeHotelFees) totalRate += rate.hotelFees;

    return totalRate;
  },
  apiKey: "sk_test_123456789",
});

支持的选项

名称所需经费类型默认说明实例
anonymousId对string独特的ID识别用户2d360284-577b-4a53-8b91-68f72b9227fa
language没有stringen2-char 语言代码en
currency没有stringUSD3- Char 大写 ISO 货币代码USD
userCountry没有stringUS2-char 大写 ISO 国家代码US
deviceType对stringdesktop, (中文(简体) ), mobile, (中文(简体) ), tabletdesktop
pageSize没有number20显示的页面大小20
initWithAppConfig没有AppConfig外部应用程序配置以覆盖内部
variations没有Record<string, string>A/B测试变化{'pp000004-tags2': 'b', 'pp000004-tags3': '1'}
callbacks没有Record<string, fnc>客户调用
getTotalRate没有function税率共计,包括税费基于税务显示逻辑计算总显示率的函数 。 用于价格过滤和按价格功能排序.
apiKey没有string为 SAPI 后端验证请求的 API 密钥 。 每个客户端都有自己独特的密钥被存储在sapi-backend配置来识别请求源.sk_test_123456789
forcedRegion没有'eu' | 'us'SAPI部队通过发送 X-Sapi-Region 头曰.eu

可用的客户端回调

  1. 已接收( 配置) 上

    返回 sapiClient 使用的配置设置.

回应

{
  "exchangeRates": {
    "EUR": 0.982994
  },
  "lov": [
    {
      "id": 9,
      "categoryID": 19,
      "objectID": "Facility:9",
      "value": {
        "en": "Airport shuttle"
      }
    },
    {
      "categoryID": 2,
      "id": 7,
      "objectID": "Facility:7",
      "value": {
        "en": "Swimming pool"
      }
    }
  ]
}

search() 方法

搜索是一种方法 sapi 客户端 搜索旅馆和提供 提供 searchParameters数字 :

const search = await sapiClient.search(searchParameters, callbacks);

搜索参数

所有参数都是可选的.

名称类型说明实例
hotelIdstring旅馆 搜查旅馆1371626
placeIdstring地点 搜索地点47319
geolocation{lat: number, lon: number, precision: string}地理位置查询{lat: 36.114303, lon: -115.178312}
addressstring地址搜索字符串Nieuwe Looiersdwarsstraat 17,
boundingBox[p1Lat, p1Lng, p2Lat, p2Lng]topLeft 财务报告和审定财务报表 bottomRight 进行内部搜索的边框坐标[46.650828100116044, 7.123046875, 45.17210966999772, 1.009765625]
checkInstring检查日期( E)YYYY-MM-DD(中文(简体) )2021-10-10
checkOutstring检查日期( E)YYYY-MM-DD(中文(简体) )2021-10-11
roomsstring房间配置2
dayDistancenumber从现在到预期日期的全天检查(工作结合 nights 参数)15
nightsnumber停留夜数3
sortFieldstring按标准定义类型popularity, price
sortOrderstring定义排序顺序ascending, descending
filtersObject对象为 过滤器{starRatings: 5}
cugDealsstring[]获取要约的封闭用户组交易代码['signed_in', 'offline']
tierstring用户级别member
originIdstring提出请求的原产地识别符c3po6twr70
preferredRatenumber出价用户在 CA (meta) 平台看到196
labelstring传送到跟踪系统的不透明值gha-vr
userIdstring经认证的用户ID,例如用户的GoogleID. 由ACL使用 c34b0018-d434-4fad-8de6-9d8e8e18cb35
emailDomainstring认证用户的电子邮件域名, 由 ACL 使用@manatuscostarica.com
deviceIdstring设备ID,由ACL使用(iOS设备的以发光器或Android设备的GAID)
screenshotsnumber用户拍摄、网站检测、ACL使用的截图数量2
metadataRecord<string, string>将传送到搜索的其他元数据{esd: 'abcds', epv: 'qwert'}
offerSortstring如果存在,按价格分列的要约(见 解释(中文(简体) )
optimizeRoomsboolean若为 true 然后对非锚地酒店启用房间优化逻辑. 优化房间试图找到最佳的 可能的房间配置true
optimizeAnchorRoomsboolean若为 true 然后,房间优化逻辑被启用 对于锚酒店。 优化房间试图找到最佳的 可能的房间配置false
sbcstring拆分预订配置。如果存在,则查找分期预订报价sbc: '2~3'
skipOffersboolean跳过提供搜索, 只返回静态结果true
searchIdstring搜索会话的ID, 仅在重运行要跟踪的搜索会话时指定 true
useLiveOfferDataHSOboolean提示后端何时使用或不使用现场数据,用于精细的酒店分类true

拆分预订配置

分账配置的格式如下:

LOS1~LOS2

其中: LOS1 财务报告和审定财务报表 LOS2 是分别代表分期预订第一和第二部分停留时间的整数.

例如,如果我们有这些参数:

checkIn:'2023-08-10'

checkOut:'2023-08-15'

sbc:2~3

分会订会分会分会分会分会分会分会分会分会分会分会分会分会分会分会分会分会分会分会分会分会分会分会分会分会分会分会分会分会分会分会分会分会分会分会分会分会分会分会分会分会分会分会分会分会分会分会分会分会分会分会分会分会分会分会分会分会分会分会分会分会分会分会分会分会分会分会分会分会分会分会分会分会分会分会分会分会分会分会分会分会分会分会分会分会分会分会分会分会分会分会分会分会分会分会分会分会分会分会分会分会分会分会分会分会分会分会分会分会分会分会分会分会分会分会分会分会分会分会分会分会分会分会分会分会分会分. 因此,SAPI搜索两个停留:

拆分 1 : checkIn: '2023-08-10' checkOut: '2023-08-12'

拆分 2 : checkIn: '2023-08-12' checkOut: '2023-08-15'

过滤器

名称类型说明实例过滤范围
themeIdsnumber[]按主题 ID 过滤[1, 2, 3]旅馆
chainIdsnumber[]旅馆连锁身份证[4, 5]旅馆
facilitiesstring[]用于面部过滤的设施标识[299,7,6,21]旅馆
starRatingsnumber[]酒店的明星评分[3, 4]旅馆
propertyTypeIdnumber[]属性类型 ID[1, 0]旅馆
guestRatingnumber最低总嘉宾评级5旅馆
noHostelsboolean如果是真的, 宿舍将被排除在结果之外true旅馆
priceMinnumber每晚最低价格100旅馆/旅馆
priceMaxnumber每晚最高价格200旅馆/旅馆
hotelNamestring根据酒店名称过滤结果Hilton Amsterdam旅馆
freeCancellationboolean如果选中, 只有免费取消的报价才会被退回true提议
payLaterboolean如果属实,则只退还有报酬的报价true提议
mealIncludedboolean如果选中的话, 只有包含餐食选项的报价才会返回true提议
dealFreezeboolean如果是真的,只有可以被冻结的报价才会被退回true提议
exclusiveboolean如果是真的,只有Vio独有的报价才会退回true提议
amenitiesstring[]餐类["breakfast","allInclusive"]
isVrboolean如果是真的,那么只归还假期租金。 假的,就把假期租房过滤掉true旅馆
neighborhoodIdsstring[]根据酒店的邻居过滤结果["47689","45031"]旅馆
brandIdsstring[]根据酒店品牌过滤结果["12060","2137"]旅馆
设施

一些用于过滤的首选设施:

名称编号
free_wifi299 (中文(简体) )
swimming_pool第7条
restaurant页:1
parking6个
pet_friendly第8条
kitchen第50条
hot_tub页:1
spa第193条
air_conditioned21国
财产类型

用于过滤的一些属性类型 :

名称编号
hotel0 个
apartment第9条
hostel页:1
motel1个
机会

辅助设施:

名称说明
breakfast
lunch
dinner
halfBoard"快餐",或酒店明确使用"半板"一词
fullBoard"breakfast qq午餐qq晚餐",或酒店明确使用"全板"一词
allInclusive"所有饭吃喝喝" 或酒店明确使用"包罗万象"一词

回电

搜索方法接收回调对象作为第二个参数 :

const callbacks = {
  onStart: (response) => {
    log("Search started", response);
  },
  onAnchorReceived: (response) => {
    log("Anchor received", response);
  },
  onHotelsReceived: (response) => {
    log("Hotels received", response);
  },
  onOffersReceived: (response) => {
    log("Offers received", response);
  },
  onComplete: (response) => {
    log("Search completed", response);
  },
};

每个回调返回 SAPI 内部可用的完整搜索状态 死刑时间。 这意味着以后的每个回电 渐进添加新属性并返回更新状态。 数据在 状态可以在不同的召回之间重复.

  1. 启动时 ()

    每次新搜索开始时运行 .

    已生成回调 searchId 财务报告和审定财务报表 用于搜索的实际搜索参数,如日期, 如果引用者不提供这些语言的话.

    这种回调的另一个目的是,引用者可以跟踪 在搜索SPA中 旅馆。 。 。 .

  2. 锁定接收 ()

    当SAPI接收主播和(?)主播酒店(如果是酒店)时运行 搜索)
    返回关于锚的静态数据 response.anchor 和(?) 里面的旅馆 response.hotelEntities 对象( 在 宾馆搜查案).

  3. 在 Hotels 接收( )

    SAPI 收到静态搜索结果后运行
    返回内部旅馆的静态数据 response.hotelEntities 目标及适当时 酒店排序顺序 response.hotelIds 数组( 类型) 根据HSO.

  4. 输入( )

    当SAPI收到大量报价时运行
    返回旅馆的报价(答复不完整) response.hotelOfferEntities 对象及已更新 酒店排序顺序 response.hotelIds 数组( 类型) 根据健康标准并考虑到实际报价数据)
    答复的详细内容载于本文件附件 提供答复

  5. 完成( )

    当前搜索完成后运行, 所有要约都被检索
    返回完整的 SAPI 搜索响应 .
    答复的详细内容载于本文件附件 提供答复

回应

完整的 SAPI 搜索响应太大, 无法在页面上显示 因此有一个简化的例子:

{
  "anchor": {
    "_geoloc": {
      "lat": -6.28067,
      "lon": 39.53601,
      "precision": 5000,
      "radius": 20000
    },
    "objectID": "hotel:9660485",
    "objectType": "hotel",
    "pageSize": 25,
    "priceBucketWidth": 16,
    "navPath": ["3429", "300878", "235186"],
    "navPathInfo": {
      "adminDivision": {
        "id": "12598",
        "name": "Hokkaido Prefecture"
      },
      "city": {
        "id": "43727",
        "name": "Otaru"
      },
      "country": {
        "id": "125948",
        "name": "Japan"
      }
    },
    "hotelName": "Zanzibar White Sand Luxury Villas & Spa - Relais & Chateaux",
    "placeDisplayName": "Zanzibar"
  },
  "anchorType": "hotel",
  "anchorHotelId": "9660485",
  "facetFilters": {
    "brands": {
      "0": {
        "value": "Independent"
      },
      "11157": {
        "value": "NH Collection"
      },
      "12060": {
        "value": "Revenue Guru"
      }
    },
    "neighborhoods": {
      "253086": {
        "value": "Amsterdam City Centre"
      },
      "305373": {
        "value": "Amsterdam-West"
      },
      "305374": {
        "value": "Amsterdam-Zuid"
      }
    }
  },
  "hotelEntities": {
    "9660485": {
      "_geoloc": {
        "lat": -6.28067,
        "lon": 39.53601
      },
      "checkInTime": "14:00",
      "checkOutTime": "11:00",
      "country": "TZ",
      "facilities": [
        2, 5, 6, 7, 9, 11, 13, 20, 21, 22, 23, 28, 29, 31, 34, 35, 66, 84, 85,
        86, 98, 99, 100, 103, 104, 122, 127, 189, 191, 193, 195, 202, 222, 235,
        238, 243, 244, 253, 255, 266, 270, 292, 299
      ],
      "guestRating": {
        "cleanliness": 9.66,
        "dining": 9.42,
        "facilities": 9.9,
        "location": 9.8,
        "overall": 9.55,
        "rooms": 9.72
      },
      "guestType": {
        "business": 6,
        "couples": 235,
        "families": 110,
        "groups": 68,
        "solo": 13
      },
      "imageURIs": [
        "https://img.fih.io/image/raw/regular/provider_partition=eps/3xWl0k2P0Ofb7vxD4dr1NhFjOtdQaHXLe2p1tYLaOmw=.webp"
      ],
      "navPath": ["3429", "300878", "235186"],
      "navPathInfo": {
        "adminDivision": {
          "id": "12598",
          "name": "Hokkaido Prefecture"
        },
        "city": {
          "id": "43727",
          "name": "Otaru"
        },
        "country": {
          "id": "125948",
          "name": "Japan"
        }
      }
    }
  }
}

导航PathInfo

此结构包含有关酒店位置的所有信息(从国家开始 - > 区域 - > 城市 - > 村庄)

  "navPathInfo": {
    "adminDivision": {
      "id": "12598",
      "name": "Hokkaido Prefecture"
    },
    "city": {
      "id": "43727",
      "name": "Otaru"
    },
    "country": {
      "id": "125948",
      "name": "Japan"
    }
  }

装入更多的结果 并装入更多的报价 酒店

搜索完成后:

const search = await sapiClient.search(searchParameters, callbacks);

它解决在 search 具有两种方法的对象:

  • search.loadMore() - SDK将返回给定搜索的下一组结果("next" page). 一样 调用 从原始搜索将使用.
  • search.loadOffers(hotelId, {filters, offersSort}) - 装载所提供的所有报价(最多23个) hotelId。也可以覆盖 提供范围过滤器 财务报告和审定财务报表 提议排序。 。 。 .

suggest() 方法

建议为给定查询提供自动建议

const suggestions = await sapiClient.suggest("London", 6);

建议参数

名称类型说明所需经费实例
querystring查询字符串对London
suggestsCountnumber理想建议数目(默认6)没有10

回应

const suggestions = await sapiClient.suggest("London", 2);
[
  {
    "highlightValue": "<em>London</em>",
    "objectID": "158584",
    "objectType": "place",
    "placeDisplayName": "United Kingdom",
    "placeTypeName": "city",
    "value": "London"
  },
  {
    "highlightValue": "<em>London</em> Heathrow Airport",
    "objectID": "167733",
    "objectType": "place",
    "placeDisplayName": "London, United Kingdom",
    "placeTypeName": "airport",
    "value": "London Heathrow Airport"
  }
]
const suggestions = await sapiClient.suggest("London hotel", 2);
[
  {
    "highlightValue": "Park Plaza Westminster Bridge <em>London</em>",
    "objectID": "1546646",
    "objectType": "hotel",
    "placeDisplayName": "London, United Kingdom",
    "placeTypeName": "property",
    "value": "Park Plaza Westminster Bridge London"
  },
  {
    "highlightValue": "Hampton by Hilton <em>London</em> Stansted Airport",
    "objectID": "3333916",
    "objectType": "hotel",
    "placeDisplayName": "United Kingdom",
    "placeTypeName": "property",
    "value": "Hampton by Hilton London Stansted Airport"
  }
]

freeTextSuggest() 方法

FreeTextSuggest 提供了基于 AI 特性的给定自由文本查询的建议

const result = await sapiClient.freeTextSuggest(
  "5 stars hotels in Amsterdam with pets allowed for tomorrow 2 nights",
);

建议参数

名称类型说明所需经费实例
querystring查询字符串对5 stars hotels in Amsterdam with pets allowed for tomorrow 2 nights

回应

const result = await sapiClient.freeTextSuggest(
  "5 stars hotels in Amsterdam with pets allowed for tomorrow 2 nights",
);
[
  {
    "filters": {
      "starRating": 5,
      "facilities": [
        {
          "id": 8,
          "value": "Pet Friendly"
        }
      ]
    },
    "checkIn": "2024-06-12",
    "checkOut": "2024-06-14",
    "highlightValue": "<em>Amsterdam</em>",
    "objectID": "47319",
    "objectType": "place",
    "placeDisplayName": "The Netherlands",
    "placeTypeName": "city",
    "value": "Amsterdam"
  },
  {
    "filters": {
      "starRating": 5,
      "facilities": [
        {
          "id": 8,
          "value": "Pet Friendly"
        }
      ]
    },
    "checkIn": "2024-06-12",
    "checkOut": "2024-06-14",
    "highlightValue": "InterContinental Amstel <em>Amsterdam</em>, an IHG Hotel",
    "objectID": "1363313",
    "objectType": "hotel",
    "placeDisplayName": "Weesperbuurt en Plantage, Amsterdam, The Netherlands",
    "placeTypeName": "property",
    "value": "InterContinental Amstel Amsterdam, an IHG Hotel"
  }
]

rooms() 方法

房间是一种方法 sapi 客户端 用于检索房间信息和 提供某一特定行程:

五一号

const rooms = await sapiClient.rooms({
  hotelId: "1714808",
  checkIn: "2021-10-10",
  checkOut: "2021-10-11",
  rooms: "2",
});

五. 2级

const rooms = await sapiClient.roomsV2({
  hotelId: "1714808",
  checkIn: "2021-10-10",
  checkOut: "2021-10-11",
  rooms: "2",
});

房间参数

名称类型说明所需经费实例
hotelIdstring旅馆 找回房间对1714808
checkInstring检查日期( E)YYYY-MM-DD(中文(简体) )对2021-10-10
checkOutstring检查日期( E)YYYY-MM-DD(中文(简体) )对2021-10-11
roomsstring房间配置对2
providerCodestring用于检索房间报价的供应商代码没有GAR
cugDealsstring要检索的 cug( 关闭用户组) 交易类型没有signed_in,offline
tierstring用户级别没有plus
clickedOfferIdstring提供用户点击 SRP 的 id没有oXstvXafDb2o
preHeatnumber启用预热模式没有1
labelstring传送到跟踪系统的不透明值没有gha-vr
userIdstring用户ID是一个认证的用户ID,例如用户的Google ID.没有7ea95191-b929-469d-8b02-0397dafd53a1
emailDomainstring如果有电子邮件,用户电子邮件域是作为值认证的用户.没有@findhotel.net
deviceIdstring设备 ID (iOS 设备的 FFV 或 Android 设备的 GAID )没有
searchIdstringSearchId 覆盖( SDK 如果未提供则生成一个新的覆盖)没有08230dfcc5f0fb95caaa82ce559ea60c4a975d6f
metadataRecord<string, string>需要传递给API的其他数据没有{vclid: '21d2d152-de19-4f39-b40a-d4bc3002c6e8'}
bundleIdstring套装 Id点击了SRP. 用于从缓存获取捆绑数据没有13b5d152-de19-4f39-b40a-d4bc3002c3u9
originIdstring提出请求的原产地识别符没有c3po6twr70

回应

V1 回应

{
  "anonymousId": "fd9dbb5f-b337-4dd7-b640-1f177d1d3caa",
  "hotelId": "1714808",
  "searchId": "08230dfcc5f0fb95caaa82ce559ea60c4a975d6f",
  "rooms": [
    {
      "amenities": ["Non-Smoking Facility"],
      "amenitiesList": [
        {
          "title": "Non-Smoking Facility",
          "id": "123",
          "categoryId": "room_features",
          "category": "Room Features"
        }
      ],
      "bedTypes": [],
      "bedrooms": [
        {
          "bedConfigurations": [
            {
              "cfgID": 1,
              "count": 1,
              "sleepCount": 2,
              "type": "Full Bed",
              "typeID": "full bed"
            }
          ]
        }
      ],
      "occupancy": {
        "maxAdults": 2,
        "maxChildren": 1,
        "maxOccupancy": 2,
        "requiresExtraBed": false
      },
      "description": "20 sqm room Continental breakfast included Free WiFi LCD TV Spacious work desk Choice of pillows Coffee and tea facilities Large walk-in power shower",
      "id": "K0LnAe-G9WI",
      "images": [{ "url": "http://images.getaroom-cdn.com/image/...." }],
      "masterId": "9643931",
      "name": "1 Double Standard",
      "offers": [
        {
          "availableRooms": 0,
          "canPayLater": false,
          "cancellationPenalties": [],
          "cug": ["signed_in"],
          "id": "o0KDe_mFPN4k",
          "links": [
            {
              "href": "https://secure.findhotel.net/checkout/?hotelID=1714808...",
              "method": "GET",
              "type": "checkout"
            }
          ],
          "prices": [
            {
              "chargeable": { "base": "1352.77", "taxes": "59.94" },
              "currencyCode": "EUR",
              "hotelFees": { "breakdown": [], "total": "0" },
              "type": "chargeable_currency"
            }
          ],
          "mealPlan": [
            {
              "meal": "breakfast",
              "rule": {
                "adults": 2,
                "kids": 1
              }
            }
          ],
          "providerCode": "GAR",
          "providerRateType": "public",
          "services": ["breakfast"]
        }
      ]
    }
  ]
}

V2 回应

{
  "entities": [
    {
      "id": "b57ac4d3-72bf-4f0c-b82f-28e29543c06a",
      "entityType": "split_booking",
      "rooms": [
        {
          "id": "SHPLitp7oTk",
          "name": "Room",
          "raaName": "Room",
          "amenities": [],
          "amenitiesList": [],
          "images": [],
          "description": "",
          "smokingOptionsAvailable": false,
          "bedTypes": [],
          "area": {},
          "bedrooms": [
            {
              "bedConfigurations": [
                {
                  "cfgID": 1,
                  "count": 1,
                  "sleepCount": 2,
                  "type": "Full Bed",
                  "typeID": "full bed"
                }
              ]
            }
          ],
          "occupancy": {
            "maxAdults": 2,
            "maxChildren": 1,
            "maxOccupancy": 2,
            "requiresExtraBed": false
          }
        },
        {
          "id": "dn4Qijq4auI",
          "name": "cosy room(City view)",
          "raaName": "cosy room(City view)",
          "amenities": [],
          "amenitiesList": [],
          "images": [],
          "description": "",
          "smokingOptionsAvailable": false,
          "bedTypes": [],
          "area": {},
          "bedrooms": [
            {
              "bedConfigurations": [
                {
                  "cfgID": 1,
                  "count": 1,
                  "sleepCount": 2,
                  "type": "Full Bed",
                  "typeID": "full bed"
                }
              ]
            }
          ],
          "occupancy": {
            "maxAdults": 2,
            "maxChildren": 1,
            "maxOccupancy": 2,
            "requiresExtraBed": false
          }
        }
      ],
      "offers": [
        {
          "isClicked": true,
          "matchType": "by_price",
          "matchedOfferPriceDiff": 0,
          "id": "b57ac4d3-72bf-4f0c-b82f-28e29543c06a",
          "availableRooms": null,
          "canPayLater": false,
          "cancellationPenalties": [],
          "cug": null,
          "links": [
            {
              "href": "https://secure.findhotel.net/checkout/?bundleId=b57ac4d3-72bf-4f0c-b82f-28e29543c06a..",
              "method": "GET",
              "type": "checkout"
            }
          ],
          "prices": [
            {
              "chargeable": {
                "base": "570.7278477192",
                "taxes": "46.6959148134"
              },
              "currencyCode": "EUR",
              "hotelFees": {
                "breakdown": [],
                "total": "74.1946202035"
              },
              "rate": {
                "base": 570.7278477192,
                "taxes": 46.6959148134,
                "hotelFees": 74.1946202035
              },
              "type": "chargeable_currency"
            }
          ],
          "services": null,
          "providerCode": "",
          "tags": ["price_matched", "sb_single_flow"],
          "metadata": {
            "feedID": ""
          },
          "offerType": "split_booking",
          "itineraries": [
            {
              "checkIn": "2025-03-30",
              "checkOut": "2025-03-31",
              "roomID": "SHPLitp7oTk",
              "offer": {
                "id": "ojnRYasJ3-Ws",
                "availableRooms": null,
                "providerRateType": "public",
                "canPayLater": false,
                "cancellationPenalties": [],
                "cug": [],
                "links": [
                  {
                    "href": "https://secure.findhotel.net/checkout/?hotelId=1041597...",
                    "method": "GET",
                    "type": "checkout"
                  }
                ],
                "prices": [
                  {
                    "chargeable": {
                      "base": "119.8596330275",
                      "taxes": "9.8066972477"
                    },
                    "currencyCode": "EUR",
                    "hotelFees": {
                      "breakdown": [],
                      "total": "15.5817522936"
                    },
                    "rate": {
                      "base": 119.8596330275,
                      "taxes": 9.8066972477,
                      "hotelFees": 15.5817522936
                    },
                    "type": "chargeable_currency"
                  }
                ],
                "mealPlan": [
                  {
                    "meal": "breakfast"
                  }
                ],
                "services": [],
                "providerCode": "SMR",
                "tags": [
                  "preferred_rate",
                  "top_offer",
                  "exclusive_cheapest_offer"
                ],
                "metadata": {
                  "providerRateType": "public",
                  "feedID": ""
                },
                "offerType": "regular",
                "itineraries": null,
                "totalRate": {
                  "base": 0,
                  "taxes": 0,
                  "hotelFees": 0
                }
              }
            },
            {
              "checkIn": "2025-03-31",
              "checkOut": "2025-04-03",
              "roomID": "dn4Qijq4auI",
              "offer": {
                "id": "o33J8HXa4tJY",
                "availableRooms": 99,
                "providerRateType": "plus",
                "canPayLater": false,
                "cancellationPenalties": [],
                "cug": [],
                "links": [
                  {
                    "href": "https://secure.findhotel.net/checkout/?hotelId=1041597...",
                    "method": "GET",
                    "type": "checkout"
                  }
                ],
                "prices": [
                  {
                    "chargeable": {
                      "base": "450.8682146917",
                      "taxes": "36.8892175657"
                    },
                    "currencyCode": "EUR",
                    "hotelFees": {
                      "breakdown": [],
                      "total": "58.6128679099"
                    },
                    "rate": {
                      "base": 450.8682146917,
                      "taxes": 36.8892175657,
                      "hotelFees": 58.6128679099
                    },
                    "type": "chargeable_currency"
                  }
                ],
                "mealPlan": [
                  {
                    "meal": "breakfast",
                    "rule": {
                      "guests": 2
                    }
                  }
                ],
                "services": [],
                "providerCode": "DDT",
                "tags": [
                  "preferred_rate",
                  "top_offer",
                  "exclusive_cheapest_offer"
                ],
                "metadata": {
                  "providerRateType": "plus",
                  "feedID": ""
                },
                "offerType": "regular",
                "itineraries": null,
                "totalRate": {
                  "base": 0,
                  "taxes": 0,
                  "hotelFees": 0
                }
              }
            }
          ],
          "totalRate": {
            "base": 570.7278477192,
            "taxes": 46.6959148134,
            "hotelFees": 74.1946202035
          }
        }
      ],
      "hasClickedOffer": true
    },
    {
      "id": "dn4Qijq4auI",
      "entityType": "room",
      "rooms": [
        {
          "id": "dn4Qijq4auI",
          "name": "cosy room(City view)",
          "raaName": "cosy room(City view)",
          "amenities": [],
          "amenitiesList": [],
          "images": [],
          "description": "",
          "smokingOptionsAvailable": false,
          "bedTypes": [],
          "area": {}
        }
      ],
      "offers": [
        {
          "id": "o-9NZdSFm3Qc",
          "availableRooms": 99,
          "providerRateType": "plus",
          "canPayLater": false,
          "cancellationPenalties": [],
          "cug": [],
          "links": [
            {
              "href": "https://secure.findhotel.net/checkout/?hotelId=1041597...",
              "method": "GET",
              "type": "checkout"
            }
          ],
          "prices": [
            {
              "chargeable": {
                "base": "575.6297833706",
                "taxes": "47.0969822758"
              },
              "currencyCode": "EUR",
              "hotelFees": {
                "breakdown": [],
                "total": "74.8318718382"
              },
              "rate": {
                "base": 575.6297833706,
                "taxes": 47.0969822758,
                "hotelFees": 74.8318718382
              },
              "type": "chargeable_currency"
            }
          ],
          "mealPlan": [
            {
              "meal": "allInclusive"
            }
          ],
          "services": [],
          "providerCode": "DDT",
          "tags": ["top_offer", "exclusive_cheapest_offer"],
          "metadata": {
            "providerRateType": "plus",
            "feedID": ""
          },
          "offerType": "regular",
          "itineraries": null,
          "totalRate": {
            "base": 0,
            "taxes": 0,
            "hotelFees": 0
          }
        }
      ],
      "hasClickedOffer": false
    }
  ]
}

投票时间长 rooms() 方法

这个 rooms() 方法既支持同步请求,也支持长波. 为了实现长波波,仅提供回调作为第二个论据 rooms() 方法 :

const parameters = {
  hotelId: "1714808",
  checkIn: "2021-10-10",
  checkOut: "2021-10-11",
  rooms: "2",
};

const callbacks = {
  onStart(response) {
    log("Rooms Offers Poll Started", response);
  },
  onOffersReceived(response) {
    log("Rooms Offers Poll Received", response);
  },
  onComplete(response) {
    log("Rooms Offers Poll Completed", response);
  },
};

const rooms = await sapiClient.rooms(parameters, callbacks);

答复采用与标准室提供请求相同的结构,并增加了一个状态参数,表明长波的进度

{
  "anonymousId": "fd9dbb5f-b337-4dd7-b640-1f177d1d3caa",
  "hotelId": "1041597",
  "searchId": "9248cf1d-1fdd-4aa5-af6d-2ec6e6671009",
  "rooms": [...],
  "splitBooking": {...},
  "status": {
    "complete": true
  }
}

房间服务也可包括可选的 mealPlan 包含详细餐饮分类条目的阵列,而提供和酒店供应的回复则在下文披露同样细节 package.mealPlan。见 提供答复 合同细节.

hotel() 方法

旅馆是一种方法 sapi 客户端 由 id 取回一家旅馆

const hotel = await sapiClient.hotel("1196472");

旅馆参数

名称类型说明所需经费实例
hotelIdstring旅馆对1196472

回应

请求回复实例 hotelId 1196472 (英语) 还有"pt-BR" language

{
  "objectID": "1196472",
  "guestRating": {
    "cleanliness": 8.82,
    "dining": 8.73,
    "facilities": 8.73,
    "location": 8.8,
    "overall": 8.54,
    "pricing": 4.49,
    "rooms": 8.82,
    "service": 8.67
  },
  "isDeleted": false,
  "starRating": 4,
  "_geoloc": {
    "lat": 52.377805,
    "lon": 4.914172
  },
  "feesOpt": "<p>Os seguintes depósitos e taxas são cobrados pelo hotel no momento do serviço prestado, durante o check-in ou check-out. </p> <ul> <li>Taxa para café da manhã em estilo buffet: EUR 25.00 por pessoa (aproximadamente)</li>  <li>Taxa para o acesso à internet com fio no quarto: EUR 15 por dia (as tarifas podem variar)</li> </ul> <p>A lista acima pode estar incompleta. As taxas e os depósitos podem não incluir impostos e estão sujeitos a mudanças. </p>",
  "checkInSpInst": "O funcionário da recepção receberá os hóspedes na chegada. Para mais informações, entre em contato com o estabelecimento usando os dados que estão na confirmação da reserva. Os hóspedes que forem usar o traslado da Estação Central de Amsterdã devem entrar em contato com o estabelecimento com antecedência. Devido à COVID-19, as opções de comida e bebida deste estabelecimento podem estar limitadas de acordo com os regulamentos locais.",
  "policies": "<ul>  <li>Este estabelecimento oferece transporte da estação de trem. Os hóspedes devem entrar em contato com o estabelecimento antes da viagem com os detalhes da chegada usando as informações para contato presentes na confirmação da reserva. </li> <li>É necessário reservar os seguintes serviços: serviços de massagem. As reservas podem ser feitas contatando este hotel antes da viagem usando as informações para contato fornecidas na confirmação da reserva. </li> <li>Somente hóspedes registrados podem ter acesso aos quartos. </li></ul>",
  "phone": "+31205191200",
  "imageURIs": [
    "https://i.travelapi.com/hotels/2000000/1460000/1452100/1452083/a39e2fc8_w.jpg",
    "https://i.travelapi.com/hotels/2000000/1460000/1452100/1452083/3892e861_w.jpg",
    "https://i.travelapi.com/hotels/2000000/1460000/1452100/1452083/aed25438_w.jpg"
  ],
  "checkInTime": "15:00",
  "checkInInst": "<ul>  <li>Pessoas extras podem incorrer em taxas adicionais que variam dependendo da política do estabelecimento</li><li>Documento de identificação oficial com foto e cartão de crédito, cartão de débito ou depósito em dinheiro podem ser exigidos no momento do check-in para despesas extras.</li></ul>",
  "reviewCount": 17538,
  "chainID": "2101",
  "checkInEnd": "01:00",
  "lastBooked": 1608030831,
  "checkOutTime": "12:00",
  "feesMnd": "<p>Você deverá pagar os seguintes encargos no estabelecimento:</p> <ul><li>Depósito: EUR 50 por noite</li><li>A cidade cobra um imposto de EUR 3.00 por pessoa, por noite até 21 noites. Esse imposto não se aplica a crianças de até 16 anos. </li><li>Será cobrado um imposto municipal/local de 6.422 %</li></ul> <p>Incluímos todas as cobranças que o estabelecimento nos forneceu. No entanto, as cobranças podem variar com base, por exemplo, na duração da estadia ou no tipo de quarto reservado. </p>",
  "deposit": {
    "value": {
      "currency": "USD",
      "amount": 300.0
    },
    "description": "Deposit: USD 300.00 per accommodation<br>Breakage deposit: USD 230.00"
  },
  "reviewCountBkt": 9,
  "hotelName": "Movenpick Hotel Amsterdam City Centre",
  "sentiments": [
    {
      "value": "Gostou do bar",
      "id": 46
    },
    {
      "value": "Processo rápido de check-in/check-out",
      "id": 180
    }
  ],
  "facilities": [
    {
      "categoryID": 4,
      "importance": 2,
      "value": "Centro de Negócios",
      "id": 1
    },
    {
      "categoryID": 17,
      "importance": 2,
      "value": "Serviço de quarto",
      "id": 2
    }
  ],
  "placeID": "311007",
  "guestType": {
    "business": 1333,
    "couples": 3125,
    "families":

版本与发布记录

@findhotel/sapi 共发布 296 个版本,首次发布于 2021/06/29;过去 12 个月发布了 39 个版本。

版本发布日期距今
1.35.1latest2026/10/3015 天前
1.35.02026/10/2817 天前
1.34.12026/10/2223 天前
1.34.02026/10/2124 天前
1.33.62026/10/011 个月前
1.33.52026/09/022 个月前

其他发布通道:rc → 0.26.0-rc.0,beta → 1.8.1-beta.1,next → 1.32.4-beta.0。

关于 @findhotel/sapi 的常见问题

@findhotel/sapi 是什么?

查找 Hotel 搜索 API

如何安装 @findhotel/sapi?

在项目目录运行 npm install @findhotel/sapi,或使用 pnpm add / yarn add / bun add。

@findhotel/sapi 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@findhotel/sapi 支持 ESM 还是 CommonJS?

以 CommonJS 形式发布,可以直接 require();在 ES Module 项目中也可以用 import 引入(Node.js 会把 module.exports 作为默认导出)。

@findhotel/sapi 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js >=20.10.0。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

@findhotel/sapi 可以商用吗?

@findhotel/sapi 使用 ISC 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@findhotel/sapi 的下载量有多少?

根据 npm 官方下载统计,@findhotel/sapi 在 2026/10/15 – 2026/11/13 这 30 天内被下载 3,776 次,日均约 126 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@findhotel/sapi 还在维护吗?

最新版本 1.35.1 发布于 2026/10/30(15 天前);至今共发布 296 个版本,其中过去 12 个月发布了 39 个;首次发布于 2021/06/29。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。