Loading...
Loading...
Integrate Seam's lower-level Access Codes API for direct, manual control over smart lock access codes. Create, update, and delete individual time-bound access codes on specific devices. Use this skill when someone manages their own credential lifecycle and just needs Seam for device communication, wants full control over individual access codes, or their use case doesn't fit the reservation model. Common use cases: coworking room booking, gym access, office visitor codes, custom access management. Works with August, Yale, Schlage, Kwikset, and other smart locks.
npx skill4agent add seamapi/seam-plugin seam-access-codesstarts_atends_ataccess_code_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_A1SEAM_DEVICE_ID_ROOM_101room.seamDeviceIdunit.deviceIdaccess_code_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 accessCode = await seam.accessCodes.create({
device_id: deviceId,
name: `${member.name} - ${room.name}`,
starts_at: booking.startTime,
ends_at: booking.endTime
});
booking.seamAccessCodeId = accessCode.access_code_id;
booking.accessCode = accessCode.code; // The actual PIN
} catch (err) {
console.error("Seam access code creation 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_code = seam.access_codes.create(
device_id=device_id,
name=f"{member.name} - {room.name}",
starts_at=booking.start_time,
ends_at=booking.end_time
)
booking.seam_access_code_id = access_code.access_code_id
booking.access_code = access_code.code
except Exception as e:
print(f"Seam access code failed: {e}")
# Consider: should this fail the booking? If access is required, raise.access_code_idnullundefineddevice_idcodenamedevice.properties.max_active_codes_supportedif (booking.seamAccessCodeId) {
await seam.accessCodes.update({
access_code_id: booking.seamAccessCodeId,
starts_at: booking.startTime,
ends_at: booking.endTime
});
}if booking.seam_access_code_id:
seam.access_codes.update(
access_code_id=booking.seam_access_code_id,
starts_at=booking.start_time,
ends_at=booking.end_time
)if (booking.seamAccessCodeId) {
await seam.accessCodes.delete({
access_code_id: booking.seamAccessCodeId
});
}if booking.seam_access_code_id:
seam.access_codes.delete(
access_code_id=booking.seam_access_code_id
)router.post("/seam", (req, res) => {
const { event_type, ...data } = req.body;
switch (event_type) {
case "access_code.set_on_device":
// Code is on the lock — safe to share with the user
console.log("Code set:", data.access_code_id);
break;
case "access_code.failed_to_set_on_device":
console.log("Code 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