Seam Reservation Automations
You are an expert Seam integration engineer. Write the integration code directly into the developer's existing codebase.
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.
How Reservation Automations works
The PMS pushes reservation data to Seam via push_data. Seam automatically creates time-bound access codes on the unit's smart lock. When the reservation is cancelled, delete_data revokes the codes.
The PMS does NOT need to manage individual access codes, devices, or credentials.
1. Install SDK + initialize
Do NOT pin to a specific version.
npm install seam # Node.js
pip install seam # Python
bundle add seam # Ruby
CRITICAL for Next.js: new Seam() at module scope BREAKS next build. Use a lazy getter:
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:
import { Seam } from "seam";
const seam = new Seam({ apiKey: process.env.SEAM_API_KEY });
from seam import Seam
seam = Seam(api_key=os.environ["SEAM_API_KEY"])
2. Add push_data to reservation creation
Add directly inside the create function — not in a helper:
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
}]
});
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
customer_key— use an existing ID from your data model (property ID, PM ID). NOT a Seam-generated ID.space_keys— must match the space_key used when the space was created in Seam (typically the unit/room ID).email_address— must be unique per guest. Duplicates cause silent failures (ok: truebut no code created).delete_datausescustomer_keys(plural list), NOTcustomer_key(singular). Different frompush_data.- Wrap all Seam calls in try/catch — Seam errors shouldn't break the reservation flow.
3. Add push_data to reservation updates
Same call in the update handler with the same reservation_key — Seam detects it's an update:
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
await seam.customers.deleteData({
customer_keys: [property.id],
reservation_keys: [`res_${reservation.id}`],
user_identity_keys: [`guest_${reservation.guestId}`]
});
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
Find existing webhook handlers and add a Seam endpoint following the same pattern:
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
Make service functions async and update callers to await them.
If something goes wrong, read references/troubleshooting.md. For production readiness, read references/production-checklist.md.