Loading...
Loading...
Integrate Seam Access Grants for per-entrance, per-credential control over smart lock access. Create access grants specifying who gets access to which doors, when, and how (PIN code, mobile key, Instant Key). Use this skill when someone needs to control which access methods each guest or member gets, issue both PIN codes and mobile keys, manage access per-door (room + lobby + gym), or deliver Instant Key links. Works with August, Yale, Schlage, Kwikset, and other smart locks. Common use cases: hotel guest apps, gym/fitness access, office visitor management.
npx skill4agent add seamapi/seam-plugin seam-access-grantsaccess_grant_idnpm install seam # Node.js
pip install seam # Python
bundle add seam # Rubynew Seam()next buildimport { Seam } from "seam";
let _seam: Seam;
function getSeam() {
if (!_seam) _seam = new Seam({ apiKey: process.env.SEAM_API_KEY! });
return _seam;
}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"])device_idSEAM_DEVICE_ROOM_101SEAM_DEVICE_ID_ROOM_A1room.seamDeviceIdunit.deviceIdaccess_grant_id// Inside createBooking(), after saving the booking:
const deviceId = getDeviceIdForRoom(room); // Must resolve per-room
if (!deviceId) {
throw new Error(`No Seam device configured for room ${room.id}`);
}
try {
const accessGrant = await seam.accessGrants.create({
user_identity: {
full_name: guest.name,
email_address: guest.email
},
device_ids: [deviceId],
requested_access_methods: [
{ mode: "code" } // PIN code
// { mode: "mobile_key" } // Add for mobile key + Instant Key
],
starts_at: booking.checkIn,
ends_at: booking.checkOut
});
booking.seamAccessGrantId = accessGrant.access_grant_id;
} catch (err) {
console.error("Seam access grant failed:", err);
// Consider: should this fail the booking? If access is required, throw.
}# Inside create_booking(), after saving:
device_id = get_device_id_for_room(room) # Must resolve per-room
if not device_id:
raise ValueError(f"No Seam device configured for room {room.id}")
try:
access_grant = seam.access_grants.create(
user_identity={"full_name": guest.name, "email_address": guest.email},
device_ids=[device_id],
requested_access_methods=[{"mode": "code"}],
starts_at=booking.check_in,
ends_at=booking.check_out
)
booking.seam_access_grant_id = access_grant.access_grant_id
except Exception as e:
print(f"Seam access grant failed: {e}")
# Consider: should this fail the booking? If access is required, raise.access_grant_idnullundefineduser_identityfull_nameemail_addressnameemaildevice_idsrequested_access_methods"code""mobile_key"if (booking.seamAccessGrantId) {
await seam.accessGrants.update({
access_grant_id: booking.seamAccessGrantId,
starts_at: booking.checkIn,
ends_at: booking.checkOut
});
}if (booking.seamAccessGrantId) {
await seam.accessGrants.delete({
access_grant_id: booking.seamAccessGrantId
});
}if booking.seam_access_grant_id:
seam.access_grants.delete(
access_grant_id=booking.seam_access_grant_id
)router.post("/seam", (req, res) => {
const { event_type, ...data } = req.body;
switch (event_type) {
case "access_code.set_on_device":
console.log("PIN set on lock:", data.access_code_id);
break;
case "access_code.failed_to_set_on_device":
console.log("PIN failed:", data.access_code_id);
break;
case "device.disconnected":
console.log("Lock offline:", data.device_id);
break;
}
res.json({ received: true });
});references/troubleshooting.mdreferences/production-checklist.md