seam-reservation-automations
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseSeam Reservation Automations
Seam 预订自动化
You are an expert Seam integration engineer. Write the integration code directly into the developer's existing codebase.
您是一位资深的Seam集成工程师。请直接将集成代码写入开发者的现有代码库中。
Approach
实施方案
- Move fast. Glob for key files (reservation/booking handlers, routes, models), read them, start writing code.
- Write code in existing files. Add Seam calls directly into existing service/handler functions. Don't create wrapper services.
- Minimize changes. Only touch files that need Seam calls + webhook route. Install SDK, add import, add calls.
- 快速推进:查找关键文件(预订/订单处理程序、路由、模型),读取文件内容后开始编写代码。
- 在现有文件中编写代码:直接在现有服务/处理函数中添加Seam调用。不要创建包装服务。
- 最小化改动:仅修改需要添加Seam调用的文件以及Webhook路由。安装SDK、添加导入语句、添加调用代码。
How Reservation Automations works
预订自动化的工作原理
The PMS pushes reservation data to Seam via . Seam automatically creates time-bound access codes on the unit's smart lock. When the reservation is cancelled, revokes the codes.
push_datadelete_dataThe PMS does NOT need to manage individual access codes, devices, or credentials.
PMS通过将预订数据推送给Seam。Seam会自动在对应单元的智能锁上创建限时访问码。当预订取消时,会撤销这些访问码。
push_datadelete_dataPMS无需管理单个访问码、设备或凭证。
1. Install SDK + initialize
1. 安装SDK并初始化
Do NOT pin to a specific version.
bash
npm install seam # Node.js
pip install seam # Python
bundle add seam # RubyCRITICAL for Next.js: at module scope BREAKS . Use a lazy getter:
new Seam()next buildtypescript
import { Seam } from "seam";
let _seam: Seam;
function getSeam() {
if (!_seam) _seam = new Seam({ apiKey: process.env.SEAM_API_KEY! });
return _seam;
}For Express / standard Node.js, module-scope is fine:
typescript
import { Seam } from "seam";
const seam = new Seam({ apiKey: process.env.SEAM_API_KEY });python
from seam import Seam
seam = Seam(api_key=os.environ["SEAM_API_KEY"])请勿固定到特定版本。
bash
npm install seam # Node.js
pip install seam # Python
bundle add seam # RubyNext.js 关键注意事项:在模块作用域使用会导致失败。请使用延迟获取器:
new Seam()next buildtypescript
import { Seam } from "seam";
let _seam: Seam;
function getSeam() {
if (!_seam) _seam = new Seam({ apiKey: process.env.SEAM_API_KEY! });
return _seam;
}对于Express/标准Node.js,模块作用域初始化是可行的:
typescript
import { Seam } from "seam";
const seam = new Seam({ apiKey: process.env.SEAM_API_KEY });python
from seam import Seam
seam = Seam(api_key=os.environ["SEAM_API_KEY"])2. Add push_data to reservation creation
2. 在预订创建时添加push_data调用
Add directly inside the create function — not in a helper:
typescript
await seam.customers.pushData({
customer_key: property.id, // Your property/PM ID — not a Seam ID
user_identities: [{
user_identity_key: `guest_${guest.id}`,
name: guest.name,
email_address: guest.email // Must be unique per guest
}],
reservations: [{
reservation_key: `res_${reservation.id}`,
user_identity_key: `guest_${guest.id}`,
starts_at: reservation.checkIn,
ends_at: reservation.checkOut,
space_keys: [unit.id] // Unit ID = space key
}]
});python
seam.customers.push_data(
customer_key=property.id,
user_identities=[{
"user_identity_key": f"guest_{guest.id}",
"name": guest.name,
"email_address": guest.email
}],
reservations=[{
"reservation_key": f"res_{reservation.id}",
"user_identity_key": f"guest_{guest.id}",
"starts_at": reservation.check_in,
"ends_at": reservation.check_out,
"space_keys": [unit.id]
}]
)直接在创建函数内部添加——不要使用辅助函数:
typescript
await seam.customers.pushData({
customer_key: property.id, // 您的物业/物业管理ID——不是Seam生成的ID
user_identities: [{
user_identity_key: `guest_${guest.id}`,
name: guest.name,
email_address: guest.email // 每个客人必须唯一
}],
reservations: [{
reservation_key: `res_${reservation.id}`,
user_identity_key: `guest_${guest.id}`,
starts_at: reservation.checkIn,
ends_at: reservation.checkOut,
space_keys: [unit.id] // 单元ID = space key
}]
});python
seam.customers.push_data(
customer_key=property.id,
user_identities=[{
"user_identity_key": f"guest_{guest.id}",
"name": guest.name,
"email_address": guest.email
}],
reservations=[{
"reservation_key": f"res_{reservation.id}",
"user_identity_key": f"guest_{guest.id}",
"starts_at": reservation.check_in,
"ends_at": reservation.check_out,
"space_keys": [unit.id]
}]
)Gotchas
注意事项
- — use an existing ID from your data model (property ID, PM ID). NOT a Seam-generated ID.
customer_key - — must match the space_key used when the space was created in Seam (typically the unit/room ID).
space_keys - — must be unique per guest. Duplicates cause silent failures (
email_addressbut no code created).ok: true - uses
delete_data(plural list), NOTcustomer_keys(singular). Different fromcustomer_key.push_data - Wrap all Seam calls in try/catch — Seam errors shouldn't break the reservation flow.
- ——使用您数据模型中的现有ID(物业ID、物业管理ID)。不要使用Seam生成的ID。
customer_key - ——必须与在Seam中创建空间时使用的space_key匹配(通常是单元/房间ID)。
space_keys - ——每个客人必须唯一。重复会导致静默失败(返回
email_address但不会创建访问码)。ok: true - 使用
delete_data(复数列表),而非customer_keys(单数)。这与customer_key不同。push_data - 将所有Seam调用包裹在try/catch块中——Seam的错误不应中断预订流程。
3. Add push_data to reservation updates
3. 在预订更新时添加push_data调用
Same call in the update handler with the same — Seam detects it's an update:
reservation_keytypescript
await seam.customers.pushData({
customer_key: property.id,
reservations: [{
reservation_key: `res_${reservation.id}`,
user_identity_key: `guest_${reservation.guestId}`,
starts_at: reservation.checkIn,
ends_at: reservation.checkOut,
space_keys: [reservation.unitId]
}]
});在更新处理程序中使用相同的调用和——Seam会识别出这是更新操作:
reservation_keytypescript
await seam.customers.pushData({
customer_key: property.id,
reservations: [{
reservation_key: `res_${reservation.id}`,
user_identity_key: `guest_${reservation.guestId}`,
starts_at: reservation.checkIn,
ends_at: reservation.checkOut,
space_keys: [reservation.unitId]
}]
});4. Add delete_data to cancellations
4. 在预订取消时添加delete_data调用
typescript
await seam.customers.deleteData({
customer_keys: [property.id],
reservation_keys: [`res_${reservation.id}`],
user_identity_keys: [`guest_${reservation.guestId}`]
});python
seam.customers.delete_data(
customer_keys=[property.id],
reservation_keys=[f"res_{reservation.id}"],
user_identity_keys=[f"guest_{reservation.guest_id}"]
)typescript
await seam.customers.deleteData({
customer_keys: [property.id],
reservation_keys: [`res_${reservation.id}`],
user_identity_keys: [`guest_${reservation.guestId}`]
});python
seam.customers.delete_data(
customer_keys=[property.id],
reservation_keys=[f"res_{reservation.id}"],
user_identity_keys=[f"guest_{reservation.guest_id}"]
)5. Add webhook endpoint
5. 添加Webhook端点
Find existing webhook handlers and add a Seam endpoint following the same pattern:
typescript
router.post("/seam", (req, res) => {
const { event_type, ...data } = req.body;
switch (event_type) {
case "access_code.set_on_device":
console.log("Access code set:", data.access_code_id);
break;
case "access_code.failed_to_set_on_device":
console.log("Access code failed:", data.access_code_id);
break;
case "device.disconnected":
console.log("Device disconnected:", data.device_id);
break;
}
res.json({ received: true });
});找到现有的Webhook处理程序,按照相同的模式添加Seam端点:
typescript
router.post("/seam", (req, res) => {
const { event_type, ...data } = req.body;
switch (event_type) {
case "access_code.set_on_device":
console.log("Access code set:", data.access_code_id);
break;
case "access_code.failed_to_set_on_device":
console.log("Access code failed:", data.access_code_id);
break;
case "device.disconnected":
console.log("Device disconnected:", data.device_id);
break;
}
res.json({ received: true });
});6. Make functions async
6. 将函数改为异步
Make service functions async and update callers to await them.
If something goes wrong, read . For production readiness, read .
references/troubleshooting.mdreferences/production-checklist.md将服务函数改为异步,并更新调用方以使用await等待结果。
如果出现问题,请阅读。如需确保生产环境就绪,请阅读。
references/troubleshooting.mdreferences/production-checklist.md